diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
commit | 3950ffe2a485479f6561c27364d3d7df5a21d124 (patch) | |
tree | 468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/port | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/port')
-rw-r--r-- | src/lib/libast/port/astconf.c | 1718 | ||||
-rw-r--r-- | src/lib/libast/port/astcopy.c | 90 | ||||
-rw-r--r-- | src/lib/libast/port/astdynamic.c | 132 | ||||
-rw-r--r-- | src/lib/libast/port/astlicense.c | 1292 | ||||
-rw-r--r-- | src/lib/libast/port/astmath.c | 72 | ||||
-rw-r--r-- | src/lib/libast/port/astquery.c | 114 | ||||
-rw-r--r-- | src/lib/libast/port/aststatic.c | 44 | ||||
-rw-r--r-- | src/lib/libast/port/astwinsize.c | 143 | ||||
-rw-r--r-- | src/lib/libast/port/atmain.C | 37 | ||||
-rw-r--r-- | src/lib/libast/port/iblocks.c | 95 | ||||
-rw-r--r-- | src/lib/libast/port/lc.c | 883 | ||||
-rw-r--r-- | src/lib/libast/port/lc.tab | 275 | ||||
-rw-r--r-- | src/lib/libast/port/lcgen.c | 791 | ||||
-rw-r--r-- | src/lib/libast/port/lclang.h | 120 | ||||
-rw-r--r-- | src/lib/libast/port/lclib.h | 71 | ||||
-rw-r--r-- | src/lib/libast/port/mc.c | 675 | ||||
-rw-r--r-- | src/lib/libast/port/mnt.c | 816 | ||||
-rw-r--r-- | src/lib/libast/port/touch.c | 74 |
18 files changed, 7442 insertions, 0 deletions
diff --git a/src/lib/libast/port/astconf.c b/src/lib/libast/port/astconf.c new file mode 100644 index 0000000..ee199fa --- /dev/null +++ b/src/lib/libast/port/astconf.c @@ -0,0 +1,1718 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped + +/* + * string interface to confstr(),pathconf(),sysconf(),sysinfo() + * extended to allow some features to be set per-process + */ + +static const char id[] = "\n@(#)$Id: getconf (AT&T Research) 2011-05-18 $\0\n"; + +#include "univlib.h" + +#include <ast.h> +#include <error.h> +#include <fs3d.h> +#include <ctype.h> +#include <regex.h> +#include <proc.h> +#include <ls.h> +#include <sys/utsname.h> + +#include "conftab.h" +#include "FEATURE/libpath" + +#ifndef DEBUG_astconf +#define DEBUG_astconf 0 +#endif + +#ifndef _pth_getconf +#undef ASTCONF_system +#define ASTCONF_system 0 +#endif + +#if _sys_systeminfo +# if !_lib_sysinfo +# if _lib_systeminfo +# define _lib_sysinfo 1 +# define sysinfo(a,b,c) systeminfo(a,b,c) +# else +# if _lib_syscall && _sys_syscall +# include <sys/syscall.h> +# if defined(SYS_systeminfo) +# define _lib_sysinfo 1 +# define sysinfo(a,b,c) syscall(SYS_systeminfo,a,b,c) +# endif +# endif +# endif +# endif +#else +# undef _lib_sysinfo +#endif + +#define CONF_ERROR (CONF_USER<<0) +#define CONF_READONLY (CONF_USER<<1) +#define CONF_ALLOC (CONF_USER<<2) +#define CONF_GLOBAL (CONF_USER<<3) + +#define DEFAULT(o) ((state.std||!dynamic[o].ast)?dynamic[o].std:dynamic[o].ast) +#define INITIALIZE() do{if(!state.data)synthesize(NiL,NiL,NiL);}while(0) +#define STANDARD(v) (streq(v,"standard")||streq(v,"strict")||streq(v,"posix")||streq(v,"xopen")) + +#define MAXVAL 256 + +#if MAXVAL <= UNIV_SIZE +#undef MAXVAL +#define MAXVAL (UNIV_SIZE+1) +#endif + +#ifndef _UNIV_DEFAULT +#define _UNIV_DEFAULT "att" +#endif + +static char null[1]; +static char root[2] = "/"; + +typedef struct Feature_s +{ + struct Feature_s*next; + const char* name; + char* value; + char* std; + char* ast; + short length; + short standard; + unsigned int flags; + short op; +} Feature_t; + +typedef struct Lookup_s +{ + Conf_t* conf; + const char* name; + unsigned int flags; + short call; + short standard; + short section; +} Lookup_t; + +static Feature_t dynamic[] = +{ +#define OP_architecture 0 + { + &dynamic[OP_architecture+1], + "ARCHITECTURE", + &null[0], + 0, + 0, + 12, + CONF_AST, + 0, + OP_architecture + }, +#define OP_conformance 1 + { + &dynamic[OP_conformance+1], + "CONFORMANCE", + "ast", + "standard", + "ast", + 11, + CONF_AST, + 0, + OP_conformance + }, +#define OP_fs_3d 2 + { + &dynamic[OP_fs_3d+1], + "FS_3D", + &null[0], + "0", + 0, + 5, + CONF_AST, + 0, + OP_fs_3d + }, +#define OP_getconf 3 + { + &dynamic[OP_getconf+1], + "GETCONF", +#ifdef _pth_getconf + _pth_getconf, +#else + &null[0], +#endif + 0, + 0, + 7, + CONF_AST, + CONF_READONLY, + OP_getconf + }, +#define OP_hosttype 4 + { + &dynamic[OP_hosttype+1], + "HOSTTYPE", + HOSTTYPE, + 0, + 0, + 8, + CONF_AST, + CONF_READONLY, + OP_hosttype + }, +#define OP_libpath 5 + { + &dynamic[OP_libpath+1], + "LIBPATH", +#ifdef CONF_LIBPATH + CONF_LIBPATH, +#else + &null[0], +#endif + 0, + 0, + 7, + CONF_AST, + 0, + OP_libpath + }, +#define OP_libprefix 6 + { + &dynamic[OP_libprefix+1], + "LIBPREFIX", +#ifdef CONF_LIBPREFIX + CONF_LIBPREFIX, +#else + "lib", +#endif + 0, + 0, + 9, + CONF_AST, + 0, + OP_libprefix + }, +#define OP_libsuffix 7 + { + &dynamic[OP_libsuffix+1], + "LIBSUFFIX", +#ifdef CONF_LIBSUFFIX + CONF_LIBSUFFIX, +#else + ".so", +#endif + 0, + 0, + 9, + CONF_AST, + 0, + OP_libsuffix + }, +#define OP_path_attributes 8 + { + &dynamic[OP_path_attributes+1], + "PATH_ATTRIBUTES", +#if _WINIX + "c", +#else + &null[0], +#endif + &null[0], + 0, + 15, + CONF_AST, + CONF_READONLY, + OP_path_attributes + }, +#define OP_path_resolve 9 + { + &dynamic[OP_path_resolve+1], + "PATH_RESOLVE", + &null[0], + "physical", + "metaphysical", + 12, + CONF_AST, + 0, + OP_path_resolve + }, +#define OP_universe 10 + { + 0, + "UNIVERSE", + &null[0], + "att", + 0, + 8, + CONF_AST, + 0, + OP_universe + }, + { + 0 + } +}; + +typedef struct State_s +{ + + const char* id; + const char* name; + const char* standard; + const char* strict; + Feature_t* features; + + int std; + + /* default initialization from here down */ + + int prefix; + int synthesizing; + + char* data; + char* last; + + Feature_t* recent; + + Ast_confdisc_f notify; + +} State_t; + +static State_t state = { "getconf", "_AST_FEATURES", "CONFORMANCE = standard", "POSIXLY_CORRECT", dynamic, -1 }; + +static char* feature(Feature_t*, const char*, const char*, const char*, unsigned int, Error_f); + +/* + * return fmtbuf() copy of s + */ + +static char* +buffer(char* s) +{ + return strcpy(fmtbuf(strlen(s) + 1), s); +} + +/* + * synthesize state for fp + * fp==0 initializes from getenv(state.name) + * value==0 just does lookup + * otherwise state is set to value + */ + +static char* +synthesize(register Feature_t* fp, const char* path, const char* value) +{ + register char* s; + register char* d; + register char* v; + register char* p; + register int n; + +#if DEBUG_astconf + if (fp) + error(-2, "astconf synthesize name=%s path=%s value=%s fp=%p%s", fp->name, path, value, fp, state.synthesizing ? " SYNTHESIZING" : ""); +#endif + if (state.synthesizing) + return null; + if (!state.data) + { + char* se; + char* de; + char* ve; + + state.prefix = strlen(state.name) + 1; + n = state.prefix + 3 * MAXVAL; + if ((s = getenv(state.name)) || getenv(state.strict) && (s = (char*)state.standard)) + n += strlen(s) + 1; + n = roundof(n, 32); + if (!(state.data = newof(0, char, n, 0))) + return 0; + state.last = state.data + n - 1; + strcpy(state.data, state.name); + state.data += state.prefix - 1; + *state.data++ = '='; + if (s) + strcpy(state.data, s); + ve = state.data; + state.synthesizing = 1; + for (;;) + { + for (s = ve; isspace(*s); s++); + for (d = s; *d && !isspace(*d); d++); + for (se = d; isspace(*d); d++); + for (v = d; *v && !isspace(*v); v++); + for (de = v; isspace(*v); v++); + if (!*v) + break; + for (ve = v; *ve && !isspace(*ve); ve++); + if (*ve) + *ve = 0; + else + ve = 0; + *de = 0; + *se = 0; + feature(0, s, d, v, 0, 0); + *se = ' '; + *de = ' '; + if (!ve) + break; + *ve++ = ' '; + } + state.synthesizing = 0; + } + if (!fp) + return state.data; + if (!state.last) + { + if (!value) + return 0; + n = strlen(value); + goto ok; + } + s = (char*)fp->name; + n = fp->length; + d = state.data; + for (;;) + { + while (isspace(*d)) + d++; + if (!*d) + break; + if (strneq(d, s, n) && isspace(d[n])) + { + if (!value) + { + for (d += n + 1; *d && !isspace(*d); d++); + for (; isspace(*d); d++); + for (s = d; *s && !isspace(*s); s++); + n = s - d; + value = (const char*)d; + goto ok; + } + for (s = p = d + n + 1; *s && !isspace(*s); s++); + for (; isspace(*s); s++); + for (v = s; *s && !isspace(*s); s++); + n = s - v; + if ((!path || *path == *p && strlen(path) == (v - p - 1) && !memcmp(path, p, v - p - 1)) && strneq(v, value, n)) + goto ok; + for (; isspace(*s); s++); + if (*s) + for (; *d = *s++; d++); + else if (d != state.data) + d--; + break; + } + for (; *d && !isspace(*d); d++); + for (; isspace(*d); d++); + for (; *d && !isspace(*d); d++); + for (; isspace(*d); d++); + for (; *d && !isspace(*d); d++); + } + if (!value) + { + if (!fp->op) + { + if (fp->flags & CONF_ALLOC) + fp->value[0] = 0; + else + fp->value = null; + } + return 0; + } + if (!value[0]) + value = "0"; + if (!path || !path[0] || path[0] == '/' && !path[1]) + path = "-"; + n += strlen(path) + strlen(value) + 3; + if (d + n >= state.last) + { + int c; + int i; + + i = d - state.data; + state.data -= state.prefix; + c = n + state.last - state.data + 3 * MAXVAL; + c = roundof(c, 32); + if (!(state.data = newof(state.data, char, c, 0))) + return 0; + state.last = state.data + c - 1; + state.data += state.prefix; + d = state.data + i; + } + if (d != state.data) + *d++ = ' '; + for (s = (char*)fp->name; *d = *s++; d++); + *d++ = ' '; + for (s = (char*)path; *d = *s++; d++); + *d++ = ' '; + for (s = (char*)value; *d = *s++; d++); +#if DEBUG_astconf + error(-3, "astconf synthesize %s", state.data - state.prefix); +#endif + setenviron(state.data - state.prefix); + if (state.notify) + (*state.notify)(NiL, NiL, state.data - state.prefix); + n = s - (char*)value - 1; + ok: + if (!(fp->flags & CONF_ALLOC)) + fp->value = 0; + if (n == 1 && (*value == '0' || *value == '-')) + n = 0; + if (!(fp->value = newof(fp->value, char, n, 1))) + fp->value = null; + else + { + fp->flags |= CONF_ALLOC; + memcpy(fp->value, value, n); + fp->value[n] = 0; + } + return fp->value; +} + +/* + * initialize the value for fp + * if command!=0 then it is checked for on $PATH + * synthesize(fp,path,succeed) called on success + * otherwise synthesize(fp,path,fail) called + */ + +static void +initialize(register Feature_t* fp, const char* path, const char* command, const char* succeed, const char* fail) +{ + register char* p; + register int ok = 1; + +#if DEBUG_astconf + error(-2, "astconf initialize name=%s path=%s command=%s succeed=%s fail=%s fp=%p%s", fp->name, path, command, succeed, fail, fp, state.synthesizing ? " SYNTHESIZING" : ""); +#endif + switch (fp->op) + { + case OP_architecture: + ok = 1; + break; + case OP_conformance: + ok = getenv(state.strict) != 0; + break; + case OP_hosttype: + ok = 1; + break; + case OP_path_attributes: + ok = 1; + break; + case OP_path_resolve: + ok = fs3d(FS3D_TEST); + break; + case OP_universe: + ok = streq(_UNIV_DEFAULT, DEFAULT(OP_universe)); + /*FALLTHROUGH...*/ + default: + if (p = getenv("PATH")) + { + register int r = 1; + register char* d = p; + Sfio_t* tmp; + +#if DEBUG_astconf + error(-2, "astconf initialize name=%s ok=%d PATH=%s", fp->name, ok, p); +#endif + if (tmp = sfstropen()) + { + for (;;) + { + switch (*p++) + { + case 0: + break; + case ':': + if (command && fp->op != OP_universe) + { + if (r = p - d - 1) + { + sfwrite(tmp, d, r); + sfputc(tmp, '/'); + sfputr(tmp, command, 0); + if ((d = sfstruse(tmp)) && !eaccess(d, X_OK)) + { + ok = 1; + if (fp->op != OP_universe) + break; + } + } + d = p; + } + r = 1; + continue; + case '/': + if (r) + { + r = 0; + if (fp->op == OP_universe) + { + if (p[0] == 'u' && p[1] == 's' && p[2] == 'r' && p[3] == '/') + for (p += 4; *p == '/'; p++); + if (p[0] == 'b' && p[1] == 'i' && p[2] == 'n') + { + for (p += 3; *p == '/'; p++); + if (!*p || *p == ':') + break; + } + } + } + if (fp->op == OP_universe) + { + if (strneq(p, "xpg", 3) || strneq(p, "5bin", 4)) + { + ok = 1; + break; + } + if (strneq(p, "bsd", 3) || strneq(p, "ucb", 3)) + { + ok = 0; + break; + } + } + continue; + default: + r = 0; + continue; + } + break; + } + sfclose(tmp); + } + else + ok = 1; + } + break; + } +#if DEBUG_astconf + error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s ok=%d", __LINE__, state.std, fp->name, ok ? succeed : fail, fp->std, fp->ast, fp->value, ok); +#endif + synthesize(fp, path, ok ? succeed : fail); +} + +/* + * format synthesized value + */ + +static char* +format(register Feature_t* fp, const char* path, const char* value, unsigned int flags, Error_f conferror) +{ + register Feature_t* sp; + register int n; +#if _UWIN && ( _X86_ || _X64_ ) + struct stat st; +#else + static struct utsname uts; +#endif + +#if DEBUG_astconf + error(-2, "astconf format name=%s path=%s value=%s flags=%04x fp=%p%s", fp->name, path, value, flags, fp, state.synthesizing ? " SYNTHESIZING" : ""); +#endif + if (value) + fp->flags &= ~CONF_GLOBAL; + else if (fp->flags & CONF_GLOBAL) + return fp->value; + switch (fp->op) + { + + case OP_architecture: +#if _UWIN && ( _X86_ || _X64_ ) + if (!stat("/", &st)) + { + if (st.st_ino == 64) + { + fp->value = "x64"; + break; + } + if (st.st_ino == 32) + { + fp->value = "x86"; + break; + } + } +#if _X64_ + fp->value = "x64"; +#else + fp->value = "x86"; +#endif +#else + if (!uname(&uts)) + return fp->value = uts.machine; + if (!(fp->value = getenv("HOSTNAME"))) + fp->value = "unknown"; +#endif + break; + + case OP_conformance: + if (value && STANDARD(value)) + value = fp->std; + state.std = streq(fp->value, fp->std); +#if DEBUG_astconf + error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s", __LINE__, state.std, fp->name, value, fp->std, fp->ast, fp->value); +#endif + if (state.synthesizing && value == (char*)fp->std) + fp->value = (char*)value; + else if (!synthesize(fp, path, value)) + initialize(fp, path, NiL, fp->std, fp->value); +#if DEBUG_astconf + error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s", __LINE__, state.std, fp->name, value, fp->std, fp->ast, fp->value); +#endif + if (!state.std && value == fp->std) + { + state.std = 1; + for (sp = state.features; sp; sp = sp->next) + if (sp->std && sp->op && sp->op != OP_conformance) + feature(sp, 0, path, sp->std, 0, 0); + } +#if DEBUG_astconf + error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s", __LINE__, state.std, fp->name, value, fp->std, fp->ast, fp->value); +#endif + break; + + case OP_fs_3d: + fp->value = fs3d(value ? value[0] ? FS3D_ON : FS3D_OFF : FS3D_TEST) ? "1" : null; + break; + + case OP_hosttype: + break; + + case OP_path_attributes: +#ifdef _PC_PATH_ATTRIBUTES + { + register char* s; + register char* e; + intmax_t v; + + /* + * _PC_PATH_ATTRIBUTES is a bitmap for 'a' to 'z' + */ + + if ((v = pathconf(path, _PC_PATH_ATTRIBUTES)) == -1L) + return 0; + s = fp->value; + e = s + sizeof(fp->value) - 1; + for (n = 'a'; n <= 'z'; n++) + if (v & (1 << (n - 'a'))) + { + *s++ = n; + if (s >= e) + break; + } + *s = 0; + } +#endif + break; + + case OP_path_resolve: + if (state.synthesizing && value == (char*)fp->std) + fp->value = (char*)value; + else if (!synthesize(fp, path, value)) + initialize(fp, path, NiL, "logical", DEFAULT(OP_path_resolve)); + break; + + case OP_universe: +#if _lib_universe + if (getuniverse(fp->value) < 0) + strcpy(fp->value, DEFAULT(OP_universe)); + if (value) + setuniverse(value); +#else +#ifdef UNIV_MAX + n = 0; + if (value) + { + while (n < univ_max && !streq(value, univ_name[n])) + n++; + if (n >= univ_max) + { + if (conferror) + (*conferror)(&state, &state, 2, "%s: %s: universe value too large", fp->name, value); + return 0; + } + } +#ifdef ATT_UNIV + n = setuniverse(n + 1); + if (!value && n > 0) + setuniverse(n); +#else + n = universe(value ? n + 1 : U_GET); +#endif + if (n <= 0 || n >= univ_max) + n = 1; + strcpy(fp->value, univ_name[n - 1]); +#else + if (value && streq(path, "=")) + { + if (state.synthesizing) + { + if (!(fp->flags & CONF_ALLOC)) + fp->value = 0; + n = strlen(value); + if (!(fp->value = newof(fp->value, char, n, 1))) + fp->value = null; + else + { + fp->flags |= CONF_ALLOC; + memcpy(fp->value, value, n); + fp->value[n] = 0; + } + } + else + synthesize(fp, path, value); + } + else + initialize(fp, path, "echo", DEFAULT(OP_universe), "ucb"); +#endif +#endif + break; + + default: + if (state.synthesizing && value == (char*)fp->std) + fp->value = (char*)value; + else + synthesize(fp, path, value); + break; + + } + if (streq(path, "=")) + fp->flags |= CONF_GLOBAL; + return fp->value; +} + +/* + * value==0 get feature name + * value!=0 set feature name + * 0 returned if error or not defined; otherwise previous value + */ + +static char* +feature(register Feature_t* fp, const char* name, const char* path, const char* value, unsigned int flags, Error_f conferror) +{ + register int n; + + if (value && (streq(value, "-") || streq(value, "0"))) + value = null; + if (!fp) + for (fp = state.features; fp && !streq(fp->name, name); fp = fp->next); +#if DEBUG_astconf + error(-2, "astconf feature name=%s path=%s value=%s flags=%04x fp=%p%s", name, path, value, flags, fp, state.synthesizing ? " SYNTHESIZING" : ""); +#endif + if (!fp) + { + if (!value) + return 0; + if (state.notify && !(*state.notify)(name, path, value)) + return 0; + n = strlen(name); + if (!(fp = newof(0, Feature_t, 1, n + 1))) + { + if (conferror) + (*conferror)(&state, &state, 2, "%s: out of space", name); + return 0; + } + fp->op = -1; + fp->name = (const char*)fp + sizeof(Feature_t); + strcpy((char*)fp->name, name); + fp->length = n; + fp->std = &null[0]; + fp->next = state.features; + state.features = fp; + } + else if (value) + { + if (fp->flags & CONF_READONLY) + { + if (conferror) + (*conferror)(&state, &state, 2, "%s: cannot set readonly symbol", fp->name); + return 0; + } + if (state.notify && !streq(fp->value, value) && !(*state.notify)(name, path, value)) + return 0; + } + else + state.recent = fp; + return format(fp, path, value, flags, conferror); +} + +/* + * binary search for name in conf[] + */ + +static int +lookup(register Lookup_t* look, const char* name, unsigned int flags) +{ + register Conf_t* mid = (Conf_t*)conf; + register Conf_t* lo = mid; + register Conf_t* hi = mid + conf_elements; + register int v; + register int c; + char* e; + const Prefix_t* p; + + static Conf_t num; + + look->flags = 0; + look->call = -1; + look->standard = (flags & ASTCONF_AST) ? CONF_AST : -1; + look->section = -1; + while (*name == '_') + name++; + again: + for (p = prefix; p < &prefix[prefix_elements]; p++) + if (strneq(name, p->name, p->length) && ((c = name[p->length] == '_' || name[p->length] == '(' || name[p->length] == '#') || (v = isdigit(name[p->length]) && name[p->length + 1] == '_'))) + { + if (p->call < 0) + { + if (look->standard >= 0) + break; + look->standard = p->standard; + } + else + { + if (look->call >= 0) + break; + look->call = p->call; + } + if (name[p->length] == '(' || name[p->length] == '#') + { + look->conf = # + strlcpy((char*)num.name, name, sizeof(num.name)); + num.call = p->call; + num.flags = *name == 'C' ? CONF_STRING : 0; + num.op = (short)strtol(name + p->length + 1, &e, 10); + if (name[p->length] == '(' && *e == ')') + e++; + if (*e) + break; + return 1; + } + name += p->length + c; + if (look->section < 0 && !c && v) + { + look->section = name[0] - '0'; + name += 2; + } + goto again; + } +#if HUH_2006_02_10 + if (look->section < 0) + look->section = 1; +#endif + look->name = name; +#if DEBUG_astconf + error(-2, "astconf normal name=%s standard=%d section=%d call=%d flags=%04x elements=%d", look->name, look->standard, look->section, look->call, flags, conf_elements); +#endif + c = *((unsigned char*)name); + while (lo <= hi) + { + mid = lo + (hi - lo) / 2; +#if DEBUG_astconf + error(-3, "astconf lookup name=%s mid=%s", name, mid->name); +#endif + if (!(v = c - *((unsigned char*)mid->name)) && !(v = strcmp(name, mid->name))) + { + hi = mid; + lo = (Conf_t*)conf; + do + { + if ((look->standard < 0 || look->standard == mid->standard) && + (look->section < 0 || look->section == mid->section) && + (look->call < 0 || look->call == mid->call)) + goto found; + } while (mid-- > lo && streq(mid->name, look->name)); + mid = hi; + hi = lo + conf_elements - 1; + while (++mid < hi && streq(mid->name, look->name)) + { + if ((look->standard < 0 || look->standard == mid->standard) && + (look->section < 0 || look->section == mid->section) && + (look->call < 0 || look->call == mid->call)) + goto found; + } + break; + } + else if (v > 0) + lo = mid + 1; + else + hi = mid - 1; + } + return 0; + found: + if (look->call < 0 && look->standard >= 0 && (look->section <= 1 || (mid->flags & CONF_MINMAX))) + look->flags |= CONF_MINMAX; + look->conf = mid; +#if DEBUG_astconf + error(-2, "astconf lookup name=%s standard=%d:%d section=%d:%d call=%d:%d", look->name, look->standard, mid->standard, look->section, mid->section, look->call, mid->call); +#endif + return 1; +} + +/* + * return a tolower'd copy of s + */ + +static char* +fmtlower(register const char* s) +{ + register int c; + register char* t; + char* b; + + b = t = fmtbuf(strlen(s) + 1); + while (c = *s++) + { + if (isupper(c)) + c = tolower(c); + *t++ = c; + } + *t = 0; + return b; +} + +/* + * print value line for p + * if !name then value prefixed by "p->name=" + * if (flags & CONF_MINMAX) then default minmax value used + */ + +static char* +print(Sfio_t* sp, register Lookup_t* look, const char* name, const char* path, int listflags, Error_f conferror) +{ + register Conf_t* p = look->conf; + register unsigned int flags = look->flags; + Feature_t* fp; + char* call; + char* f; + const char* s; + int i; + int n; + int olderrno; + int drop; + int defined; + intmax_t v; + char buf[PATH_MAX]; + char flg[16]; + + if (!name && !(p->flags & CONF_STRING) && (p->flags & (CONF_FEATURE|CONF_LIMIT|CONF_MINMAX)) && (p->flags & (CONF_LIMIT|CONF_PREFIXED)) != CONF_LIMIT) + flags |= CONF_PREFIXED; + olderrno = errno; + errno = 0; +#if DEBUG_astconf + error(-1, "astconf name=%s:%s:%s standard=%d section=%d call=%s op=%d flags=|%s%s%s%s%s:|%s%s%s%s%s%s%s%s%s%s" + , name, look->name, p->name, p->standard, p->section, prefix[p->call + CONF_call].name, p->op + , (flags & CONF_FEATURE) ? "FEATURE|" : "" + , (flags & CONF_LIMIT) ? "LIMIT|" : "" + , (flags & CONF_MINMAX) ? "MINMAX|" : "" + , (flags & CONF_PREFIXED) ? "PREFIXED|" : "" + , (flags & CONF_STRING) ? "STRING|" : "" + , (p->flags & CONF_DEFER_CALL) ? "DEFER_CALL|" : "" + , (p->flags & CONF_DEFER_MM) ? "DEFER_MM|" : "" + , (p->flags & CONF_FEATURE) ? "FEATURE|" : "" + , (p->flags & CONF_LIMIT_DEF) ? "LIMIT_DEF|" : (p->flags & CONF_LIMIT) ? "LIMIT|" : "" + , (p->flags & CONF_MINMAX_DEF) ? "MINMAX_DEF|" : (p->flags & CONF_MINMAX) ? "MINMAX|" : "" + , (p->flags & CONF_NOUNDERSCORE) ? "NOUNDERSCORE|" : "" + , (p->flags & CONF_PREFIXED) ? "PREFIXED|" : "" + , (p->flags & CONF_PREFIX_ONLY) ? "PREFIX_ONLY|" : "" + , (p->flags & CONF_STANDARD) ? "STANDARD|" : "" + , (p->flags & CONF_STRING) ? "STRING|" : "" + , (p->flags & CONF_UNDERSCORE) ? "UNDERSCORE|" : "" + ); +#endif + flags |= CONF_LIMIT_DEF|CONF_MINMAX_DEF; + if (conferror && name) + { + if ((p->flags & CONF_PREFIX_ONLY) && look->standard < 0) + goto bad; + if (!(flags & CONF_MINMAX) || !(p->flags & CONF_MINMAX)) + { + switch (p->call) + { + case CONF_pathconf: + if (path == root) + { + (*conferror)(&state, &state, 2, "%s: path expected", name); + goto bad; + } + break; + default: + if (path != root) + { + (*conferror)(&state, &state, 2, "%s: path not expected", name); + goto bad; + } + break; + } +#ifdef _pth_getconf + if (p->flags & CONF_DEFER_CALL) + goto bad; +#endif + } + else + { + if (path != root) + { + (*conferror)(&state, &state, 2, "%s: path not expected", name); + goto bad; + } +#ifdef _pth_getconf + if ((p->flags & CONF_DEFER_MM) || !(p->flags & CONF_MINMAX_DEF)) + goto bad; +#endif + } + if (look->standard >= 0 && (name[0] != '_' && ((p->flags & CONF_UNDERSCORE) || look->section <= 1) || name[0] == '_' && (p->flags & CONF_NOUNDERSCORE)) || look->standard < 0 && name[0] == '_') + goto bad; + } + s = 0; + defined = 1; + switch (i = (p->op < 0 || (flags & CONF_MINMAX) && (p->flags & CONF_MINMAX_DEF)) ? 0 : p->call) + { + case CONF_confstr: + call = "confstr"; +#if _lib_confstr + if (!(v = confstr(p->op, buf, sizeof(buf)))) + { + defined = 0; + v = -1; + errno = EINVAL; + } + else if (v > 0) + { + buf[sizeof(buf) - 1] = 0; + s = (const char*)buf; + } + else + defined = 0; + break; +#else + goto predef; +#endif + case CONF_pathconf: + call = "pathconf"; +#if _lib_pathconf + if ((v = pathconf(path, p->op)) < 0) + defined = 0; + break; +#else + goto predef; +#endif + case CONF_sysconf: + call = "sysconf"; +#if _lib_sysconf + if ((v = sysconf(p->op)) < 0) + defined = 0; + break; +#else + goto predef; +#endif + case CONF_sysinfo: + call = "sysinfo"; +#if _lib_sysinfo + if ((v = sysinfo(p->op, buf, sizeof(buf))) >= 0) + { + buf[sizeof(buf) - 1] = 0; + s = (const char*)buf; + } + else + defined = 0; + break; +#else + goto predef; +#endif + default: + call = "synthesis"; + errno = EINVAL; + v = -1; + defined = 0; + break; + case 0: + call = 0; + if (p->standard == CONF_AST) + { + if (streq(p->name, "RELEASE") && (i = open("/proc/version", O_RDONLY)) >= 0) + { + n = read(i, buf, sizeof(buf) - 1); + close(i); + if (n > 0 && buf[n - 1] == '\n') + n--; + if (n > 0 && buf[n - 1] == '\r') + n--; + buf[n] = 0; + if (buf[0]) + { + v = 0; + s = buf; + break; + } + } + } + if (p->flags & CONF_MINMAX_DEF) + { + if (!((p->flags & CONF_LIMIT_DEF))) + flags |= CONF_MINMAX; + listflags &= ~ASTCONF_system; + } + predef: + if (look->standard == CONF_AST) + { + if (streq(p->name, "VERSION")) + { + v = ast.version; + break; + } + } + if (flags & CONF_MINMAX) + { + if ((p->flags & CONF_MINMAX_DEF) && (!(listflags & ASTCONF_system) || !(p->flags & CONF_DEFER_MM))) + { + v = p->minmax.number; + s = p->minmax.string; + break; + } + } + else if ((p->flags & CONF_LIMIT_DEF) && (!(listflags & ASTCONF_system) || !(p->flags & CONF_DEFER_CALL))) + { + v = p->limit.number; + s = p->limit.string; + break; + } + flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF); + v = -1; + errno = EINVAL; + defined = 0; + break; + } + if (!defined) + { + if (!errno) + { + if ((p->flags & CONF_FEATURE) || !(p->flags & (CONF_LIMIT|CONF_MINMAX))) + flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF); + } + else if (flags & CONF_PREFIXED) + flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF); + else if (errno != EINVAL || !i) + { + if (!sp) + { + if (conferror) + { + if (call) + (*conferror)(&state, &state, ERROR_SYSTEM|2, "%s: %s error", p->name, call); + else if (!(listflags & ASTCONF_system)) + (*conferror)(&state, &state, 2, "%s: unknown name", p->name); + } + goto bad; + } + else + { + flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF); + flags |= CONF_ERROR; + } + } + } + errno = olderrno; + if ((listflags & ASTCONF_defined) && !(flags & (CONF_LIMIT_DEF|CONF_MINMAX_DEF))) + goto bad; + if ((drop = !sp) && !(sp = sfstropen())) + goto bad; + if (listflags & ASTCONF_table) + { + f = flg; + if (p->flags & CONF_DEFER_CALL) + *f++ = 'C'; + if (p->flags & CONF_DEFER_MM) + *f++ = 'D'; + if (p->flags & CONF_FEATURE) + *f++ = 'F'; + if (p->flags & CONF_LIMIT) + *f++ = 'L'; + if (p->flags & CONF_MINMAX) + *f++ = 'M'; + if (p->flags & CONF_NOSECTION) + *f++ = 'N'; + if (p->flags & CONF_PREFIXED) + *f++ = 'P'; + if (p->flags & CONF_STANDARD) + *f++ = 'S'; + if (p->flags & CONF_UNDERSCORE) + *f++ = 'U'; + if (p->flags & CONF_NOUNDERSCORE) + *f++ = 'V'; + if (p->flags & CONF_PREFIX_ONLY) + *f++ = 'W'; + if (f == flg) + *f++ = 'X'; + *f = 0; + sfprintf(sp, "%*s %*s %d %2s %4d %6s ", sizeof(p->name), p->name, sizeof(prefix[p->standard].name), prefix[p->standard].name, p->section, prefix[p->call + CONF_call].name, p->op, flg); + if (p->flags & CONF_LIMIT_DEF) + { + if (p->limit.string) + sfprintf(sp, "L[%s] ", (listflags & ASTCONF_quote) ? fmtquote(p->limit.string, "\"", "\"", strlen(p->limit.string), FMT_SHELL) : p->limit.string); + else + sfprintf(sp, "L[%I*d] ", sizeof(p->limit.number), p->limit.number); + } + if (p->flags & CONF_MINMAX_DEF) + { + if (p->minmax.string) + sfprintf(sp, "M[%s] ", (listflags & ASTCONF_quote) ? fmtquote(p->minmax.string, "\"", "\"", strlen(p->minmax.string), FMT_SHELL) : p->minmax.string); + else + sfprintf(sp, "M[%I*d] ", sizeof(p->minmax.number), p->minmax.number); + } + if (flags & CONF_ERROR) + sfprintf(sp, "error"); + else if (defined) + { + if (s) + sfprintf(sp, "%s", (listflags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s); + else if (v != -1) + sfprintf(sp, "%I*d", sizeof(v), v); + else + sfprintf(sp, "%I*u", sizeof(v), v); + } + sfprintf(sp, "\n"); + } + else + { + if (!(flags & CONF_PREFIXED) || (listflags & ASTCONF_base)) + { + if (!name) + { + if ((p->flags & (CONF_PREFIXED|CONF_STRING)) == (CONF_PREFIXED|CONF_STRING) && (!(listflags & ASTCONF_base) || p->standard != CONF_POSIX)) + { + if ((p->flags & CONF_UNDERSCORE) && !(listflags & ASTCONF_base)) + sfprintf(sp, "_"); + sfprintf(sp, "%s", (listflags & ASTCONF_lower) ? fmtlower(prefix[p->standard].name) : prefix[p->standard].name); + if (p->section > 1) + sfprintf(sp, "%d", p->section); + sfprintf(sp, "_"); + } + sfprintf(sp, "%s=", (listflags & ASTCONF_lower) ? fmtlower(p->name) : p->name); + } + if (flags & CONF_ERROR) + sfprintf(sp, "error"); + else if (defined) + { + if (s) + sfprintf(sp, "%s", (listflags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s); + else if (v != -1) + sfprintf(sp, "%I*d", sizeof(v), v); + else + sfprintf(sp, "%I*u", sizeof(v), v); + } + else + sfprintf(sp, "undefined"); + if (!name) + sfprintf(sp, "\n"); + } + if (!name && !(listflags & ASTCONF_base) && !(p->flags & CONF_STRING) && (p->flags & (CONF_FEATURE|CONF_MINMAX))) + { + if (p->flags & CONF_UNDERSCORE) + sfprintf(sp, "_"); + sfprintf(sp, "%s", (listflags & ASTCONF_lower) ? fmtlower(prefix[p->standard].name) : prefix[p->standard].name); + if (p->section > 1) + sfprintf(sp, "%d", p->section); + sfprintf(sp, "_%s=", (listflags & ASTCONF_lower) ? fmtlower(p->name) : p->name); + if (v != -1) + sfprintf(sp, "%I*d", sizeof(v), v); + else if (defined) + sfprintf(sp, "%I*u", sizeof(v), v); + else + sfprintf(sp, "undefined"); + sfprintf(sp, "\n"); + } + } + if (drop) + { + if (call = sfstruse(sp)) + call = buffer(call); + else + call = "[ out of space ]"; + sfclose(sp); + return call; + } + bad: + if (!(listflags & ~(ASTCONF_error|ASTCONF_system))) + for (fp = state.features; fp; fp = fp->next) + if (streq(name, fp->name)) + return format(fp, path, 0, listflags, conferror); + return (listflags & ASTCONF_error) ? (char*)0 : null; +} + +/* + * return read stream to native getconf utility + */ + +static Sfio_t* +nativeconf(Proc_t** pp, const char* operand) +{ +#ifdef _pth_getconf + Sfio_t* sp; + char* cmd[3]; + long ops[2]; + +#if DEBUG_astconf + error(-2, "astconf defer %s %s", _pth_getconf, operand); +#endif + cmd[0] = (char*)state.id; + cmd[1] = (char*)operand; + cmd[2] = 0; + ops[0] = PROC_FD_DUP(open("/dev/null",O_WRONLY,0), 2, PROC_FD_CHILD); + ops[1] = 0; + if (*pp = procopen(_pth_getconf, cmd, environ, ops, PROC_READ)) + { + if (sp = sfnew(NiL, NiL, SF_UNBOUND, (*pp)->rfd, SF_READ)) + { + sfdisc(sp, SF_POPDISC); + return sp; + } + procclose(*pp); + } +#endif + return 0; +} + +/* + * value==0 gets value for name + * value!=0 sets value for name and returns previous value + * path==0 implies path=="/" + * + * settable return values are in permanent store + * non-settable return values copied to a tmp fmtbuf() buffer + * + * if (streq(astgetconf("PATH_RESOLVE", NiL, NiL, 0, 0), "logical")) + * our_way(); + * + * universe = astgetconf("UNIVERSE", NiL, "att", 0, 0); + * astgetconf("UNIVERSE", NiL, universe, 0, 0); + * + * if (flags&ASTCONF_error)!=0 then error return value is 0 + * otherwise 0 not returned + */ + +#define ALT 16 + +char* +astgetconf(const char* name, const char* path, const char* value, int flags, Error_f conferror) +{ + register char* s; + int n; + Lookup_t look; + Sfio_t* tmp; + +#if __OBSOLETE__ < 20080101 + if (pointerof(flags) == (void*)errorf) + { + conferror = errorf; + flags = ASTCONF_error; + } + else if (conferror && conferror != errorf) + conferror = 0; +#endif + if (!name) + { + if (path) + return null; + if (!(name = value)) + { + if (state.data) + { + Ast_confdisc_f notify; + +#if _HUH20000515 /* doesn't work for shell builtins */ + free(state.data - state.prefix); +#endif + state.data = 0; + notify = state.notify; + state.notify = 0; + INITIALIZE(); + state.notify = notify; + } + return null; + } + value = 0; + } + INITIALIZE(); + if (!path) + path = root; + if (state.recent && streq(name, state.recent->name) && (s = format(state.recent, path, value, flags, conferror))) + return s; + if (lookup(&look, name, flags)) + { + if (value) + { + ro: + errno = EINVAL; + if (conferror) + (*conferror)(&state, &state, 2, "%s: cannot set value", name); + return (flags & ASTCONF_error) ? (char*)0 : null; + } + return print(NiL, &look, name, path, flags, conferror); + } + if ((n = strlen(name)) > 3 && n < (ALT + 3)) + { + if (streq(name + n - 3, "DEV")) + { + if (tmp = sfstropen()) + { + sfprintf(tmp, "/dev/"); + for (s = (char*)name; s < (char*)name + n - 3; s++) + sfputc(tmp, isupper(*s) ? tolower(*s) : *s); + if ((s = sfstruse(tmp)) && !access(s, F_OK)) + { + if (value) + goto ro; + s = buffer(s); + sfclose(tmp); + return s; + } + sfclose(tmp); + } + } + else if (streq(name + n - 3, "DIR")) + { + Lookup_t altlook; + char altname[ALT]; + + static const char* dirs[] = { "/usr/lib", "/usr", null }; + + strcpy(altname, name); + altname[n - 3] = 0; + if (lookup(&altlook, altname, flags)) + { + if (value) + { + errno = EINVAL; + if (conferror) + (*conferror)(&state, &state, 2, "%s: cannot set value", altname); + return (flags & ASTCONF_error) ? (char*)0 : null; + } + return print(NiL, &altlook, altname, path, flags, conferror); + } + for (s = altname; *s; s++) + if (isupper(*s)) + *s = tolower(*s); + if (tmp = sfstropen()) + { + for (n = 0; n < elementsof(dirs); n++) + { + sfprintf(tmp, "%s/%s/.", dirs[n], altname); + if ((s = sfstruse(tmp)) && !access(s, F_OK)) + { + if (value) + goto ro; + s = buffer(s); + sfclose(tmp); + return s; + } + } + sfclose(tmp); + } + } + } + if ((look.standard < 0 || look.standard == CONF_AST) && look.call <= 0 && look.section <= 1 && (s = feature(0, look.name, path, value, flags, conferror))) + return s; + errno = EINVAL; + if (conferror && !(flags & ASTCONF_system)) + (*conferror)(&state, &state, 2, "%s: unknown name", name); + return (flags & ASTCONF_error) ? (char*)0 : null; +} + +/* + * astconf() never returns 0 + */ + +char* +astconf(const char* name, const char* path, const char* value) +{ + return astgetconf(name, path, value, 0, 0); +} + +/* + * set discipline function to be called when features change + * old discipline function returned + */ + +Ast_confdisc_f +astconfdisc(Ast_confdisc_f new_notify) +{ + Ast_confdisc_f old_notify; + + INITIALIZE(); + old_notify = state.notify; + state.notify = new_notify; + return old_notify; +} + +/* + * list all name=value entries on sp + * path==0 implies path=="/" + */ + +void +astconflist(Sfio_t* sp, const char* path, int flags, const char* pattern) +{ + char* s; + char* f; + char* call; + Feature_t* fp; + Lookup_t look; + regex_t re; + regdisc_t redisc; + int olderrno; + char flg[8]; +#ifdef _pth_getconf_a + Proc_t* proc; + Sfio_t* pp; +#endif + + INITIALIZE(); + if (!path) + path = root; + else if (access(path, F_OK)) + { + errorf(&state, &state, 2, "%s: not found", path); + return; + } + olderrno = errno; + look.flags = 0; + if (!(flags & (ASTCONF_read|ASTCONF_write|ASTCONF_parse))) + flags |= ASTCONF_read|ASTCONF_write; + else if (flags & ASTCONF_parse) + flags |= ASTCONF_write; + if (!(flags & (ASTCONF_matchcall|ASTCONF_matchname|ASTCONF_matchstandard))) + pattern = 0; + if (pattern) + { + memset(&redisc, 0, sizeof(redisc)); + redisc.re_version = REG_VERSION; + redisc.re_errorf = (regerror_t)errorf; + re.re_disc = &redisc; + if (regcomp(&re, pattern, REG_DISCIPLINE|REG_EXTENDED|REG_LENIENT|REG_NULL)) + return; + } + if (flags & ASTCONF_read) + { + for (look.conf = (Conf_t*)conf; look.conf < (Conf_t*)&conf[conf_elements]; look.conf++) + { + if (pattern) + { + if (flags & ASTCONF_matchcall) + { + if (regexec(&re, prefix[look.conf->call + CONF_call].name, 0, NiL, 0)) + continue; + } + else if (flags & ASTCONF_matchname) + { + if (regexec(&re, look.conf->name, 0, NiL, 0)) + continue; + } + else if (flags & ASTCONF_matchstandard) + { + if (regexec(&re, prefix[look.conf->standard].name, 0, NiL, 0)) + continue; + } + } + look.standard = look.conf->standard; + look.section = look.conf->section; + print(sp, &look, NiL, path, flags, errorf); + } +#ifdef _pth_getconf_a + if (pp = nativeconf(&proc, _pth_getconf_a)) + { + call = "GC"; + while (f = sfgetr(pp, '\n', 1)) + { + for (s = f; *s && *s != '=' && *s != ':' && !isspace(*s); s++); + if (*s) + for (*s++ = 0; isspace(*s); s++); + if (!lookup(&look, f, flags)) + { + if (flags & ASTCONF_table) + { + if (look.standard < 0) + look.standard = 0; + if (look.section < 1) + look.section = 1; + sfprintf(sp, "%*s %*s %d %2s %4d %5s %s\n", sizeof(conf[0].name), f, sizeof(prefix[look.standard].name), prefix[look.standard].name, look.section, call, 0, "N", s); + } + else if (flags & ASTCONF_parse) + sfprintf(sp, "%s %s - %s\n", state.id, f, s); + else + sfprintf(sp, "%s=%s\n", f, (flags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s); + } + } + sfclose(pp); + procclose(proc); + } +#endif + } + if (flags & ASTCONF_write) + { + call = "AC"; + for (fp = state.features; fp; fp = fp->next) + { + if (pattern) + { + if (flags & ASTCONF_matchcall) + { + if (regexec(&re, call, 0, NiL, 0)) + continue; + } + else if (flags & ASTCONF_matchname) + { + if (regexec(&re, fp->name, 0, NiL, 0)) + continue; + } + else if (flags & ASTCONF_matchstandard) + { + if (regexec(&re, prefix[fp->standard].name, 0, NiL, 0)) + continue; + } + } + if (!(s = feature(fp, 0, path, NiL, 0, 0)) || !*s) + s = "0"; + if (flags & ASTCONF_table) + { + f = flg; + if (fp->flags & CONF_ALLOC) + *f++ = 'A'; + if (fp->flags & CONF_READONLY) + *f++ = 'R'; + if (f == flg) + *f++ = 'X'; + *f = 0; + sfprintf(sp, "%*s %*s %d %2s %4d %5s %s\n", sizeof(conf[0].name), fp->name, sizeof(prefix[fp->standard].name), prefix[fp->standard].name, 1, call, 0, flg, s); + } + else if (flags & ASTCONF_parse) + sfprintf(sp, "%s %s - %s\n", state.id, (flags & ASTCONF_lower) ? fmtlower(fp->name) : fp->name, fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL)); + else + sfprintf(sp, "%s=%s\n", (flags & ASTCONF_lower) ? fmtlower(fp->name) : fp->name, (flags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s); + } + } + if (pattern) + regfree(&re); + errno = olderrno; +} diff --git a/src/lib/libast/port/astcopy.c b/src/lib/libast/port/astcopy.c new file mode 100644 index 0000000..853eb9a --- /dev/null +++ b/src/lib/libast/port/astcopy.c @@ -0,0 +1,90 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * Glenn Fowler + * AT&T Bell Laboratories + * + * copy from rfd to wfd (with conditional mmap hacks) + */ + +#include <ast.h> +#include <ast_mmap.h> + +#if _mmap_worthy > 1 + +#include <ls.h> + +#define MAPSIZE (1024*256) + +#endif + +#undef BUFSIZ +#define BUFSIZ 4096 + +/* + * copy n bytes from rfd to wfd + * actual byte count returned + * if n<=0 then ``good'' size is used + */ + +off_t +astcopy(int rfd, int wfd, off_t n) +{ + register off_t c; +#ifdef MAPSIZE + off_t pos; + off_t mapsize; + char* mapbuf; + struct stat st; +#endif + + static int bufsiz; + static char* buf; + + if (n <= 0 || n >= BUFSIZ * 2) + { +#if MAPSIZE + if (!fstat(rfd, &st) && S_ISREG(st.st_mode) && (pos = lseek(rfd, (off_t)0, 1)) != ((off_t)-1)) + { + if (pos >= st.st_size) return(0); + mapsize = st.st_size - pos; + if (mapsize > MAPSIZE) mapsize = (mapsize > n && n > 0) ? n : MAPSIZE; + if (mapsize >= BUFSIZ * 2 && (mapbuf = (char*)mmap(NiL, mapsize, PROT_READ, MAP_SHARED, rfd, pos)) != ((caddr_t)-1)) + { + if (write(wfd, mapbuf, mapsize) != mapsize || lseek(rfd, mapsize, 1) == ((off_t)-1)) return(-1); + munmap((caddr_t)mapbuf, mapsize); + return(mapsize); + } + } +#endif + if (n <= 0) n = BUFSIZ; + } + if (n > bufsiz) + { + if (buf) free(buf); + bufsiz = roundof(n, BUFSIZ); + if (!(buf = newof(0, char, bufsiz, 0))) return(-1); + } + if ((c = read(rfd, buf, (size_t)n)) > 0 && write(wfd, buf, (size_t)c) != c) c = -1; + return(c); +} diff --git a/src/lib/libast/port/astdynamic.c b/src/lib/libast/port/astdynamic.c new file mode 100644 index 0000000..c3035a8 --- /dev/null +++ b/src/lib/libast/port/astdynamic.c @@ -0,0 +1,132 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped + +/* + * ast dynamic data initialization + */ + +#ifdef _UWIN + +#define _std_def_cfree 1 + +#include <sfio_t.h> +#include <ast.h> + +#undef strcoll + +#include <ast_windows.h> + +extern Sfio_t _Sfstdin; +extern Sfio_t _Sfstdout; +extern Sfio_t _Sfstderr; + +#include "sfhdr.h" + +#undef sfstdin +#undef sfstdout +#undef sfstderr + +#if defined(__EXPORT__) +#define extern __EXPORT__ +#endif + +/* + * for backward compatibility with early UNIX + */ + +extern void +cfree(void* addr) +{ + free(addr); +} + +extern void +_ast_libinit(void* in, void* out, void* err) +{ + Sfio_t* sp; + + sp = (Sfio_t*)in; + *sp = _Sfstdin; + sfstdin = sp; + sp = (Sfio_t*)out; + *sp = _Sfstdout; + sfstdout = sp; + sp = (Sfio_t*)err; + *sp = _Sfstderr; + sfstderr = sp; +} + +extern void +_ast_init(void) +{ + struct _astdll* ap = _ast_getdll(); + + _ast_libinit(ap->_ast_stdin,ap->_ast_stdout,ap->_ast_stderr); +} + +extern void +_ast_exit(void) +{ + if (_Sfcleanup) + (*_Sfcleanup)(); +} + +BOOL WINAPI +DllMain(HINSTANCE hinst, DWORD reason, VOID* reserved) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + break; + case DLL_PROCESS_DETACH: + _ast_exit(); + break; + } + return 1; +} + +#else + +#include <ast.h> + +#if _dll_data_intercept && ( _DLL_BLD || _BLD_DLL ) + +#undef environ + +extern char** environ; + +struct _astdll _ast_dll = { &environ }; + +struct _astdll* +_ast_getdll(void) +{ + return &_ast_dll; +} + +#else + +NoN(astdynamic) + +#endif + +#endif diff --git a/src/lib/libast/port/astlicense.c b/src/lib/libast/port/astlicense.c new file mode 100644 index 0000000..913e9ca --- /dev/null +++ b/src/lib/libast/port/astlicense.c @@ -0,0 +1,1292 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2012 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped + +/* + * Glenn Fowler + * AT&T Research + * + * generate a license comment -- see proto(1) + * + * NOTE: coded for minimal library dependence + * not so for the legal department + */ + +#ifndef _PPLIB_H +#include <ast.h> +#include <time.h> +#endif + +#undef copy +#undef BSD /* guess who defines this */ +#undef END +#undef INLINE +#undef TEST +#undef VERBOSE + +#define NONE 0 +#define INLINE 1 +#define TEST 2 +#define VERBOSE 3 +#define USAGE 4 +#define OPEN 5 +#define CPL 6 +#define EPL 7 +#define BSD 8 +#define ZLIB 9 +#define MIT 10 +#define GPL 11 +#define SPECIAL 12 +#define NONEXCLUSIVE 13 +#define NONCOMMERCIAL 14 +#define PROPRIETARY 15 + +#define AUTHOR 0 +#define CLASS 1 +#define COMPANY 2 +#define COMPONENT 3 +#define CONTRIBUTOR 4 +#define CORPORATION 5 +#define DOMAIN 6 +#define ID 7 +#define INCORPORATION 8 +#define LICENSE 9 +#define LOCATION 10 +#define NAME 11 +#define NOTICE 12 +#define ORGANIZATION 13 +#define PACKAGE 14 +#define PARENT 15 +#define QUERY 16 +#define SINCE 17 +#define SOURCE 18 +#define START 19 +#define STYLE 20 +#define URL 21 +#define URLMD5 22 +#define VERSION 23 + +#define IDS 64 + +#define COMDATA 70 +#define COMLINE (COMDATA+4) +#define COMLONG (COMDATA-32) +#define COMMENT(x,b,s,u) comment(x,b,s,sizeof(s)-1,u) + +#define PUT(b,c) (((b)->nxt<(b)->end)?(*(b)->nxt++=(c)):((c),(-1))) +#define BUF(b) ((b)->buf) +#define USE(b) ((b)->siz=(b)->nxt-(b)->buf,(b)->nxt=(b)->buf,(b)->siz) +#define SIZ(b) ((b)->nxt-(b)->buf) +#define END(b) (*((b)->nxt>=(b)->end?((b)->nxt=(b)->end-1):(b)->nxt)=0,(b)->nxt-(b)->buf) + +#ifndef NiL +#define NiL ((char*)0) +#endif + +typedef struct Buffer_s +{ + char* buf; + char* nxt; + char* end; + int siz; +} Buffer_t; + +typedef struct Item_s +{ + char* data; + int size; + int quote; +} Item_t; + +typedef struct Id_s +{ + Item_t name; + Item_t value; +} Id_t; + +/* + * NOTE: key[] element order must match the corresponding macro + */ + +#define KEY(s) {s,sizeof(s)-1,0} + +static const Item_t key[] = +{ + KEY("author"), + KEY("class"), + KEY("company"), + KEY("component"), + KEY("contributor"), + KEY("corporation"), + KEY("domain"), + KEY("id"), + KEY("incorporation"), + KEY("license"), + KEY("location"), + KEY("name"), + KEY("notice"), + KEY("organization"), + KEY("package"), + KEY("parent"), + KEY("query"), + KEY("since"), + KEY("source"), + KEY("start"), + KEY("type"), + KEY("url"), + KEY("urlmd5"), + KEY("version"), + {0} +}; + +#define ITEMS (sizeof(key)/sizeof(key[0])-1) + +#define LIC(s,c) {s,sizeof(s)-1,c} + +static const Item_t lic[] = +{ + LIC("none", NONE), + LIC("inline", SPECIAL), + LIC("test", TEST), + LIC("verbose", VERBOSE), + LIC("usage", USAGE), + LIC("open", OPEN), + LIC("cpl", OPEN), + LIC("epl", OPEN), + LIC("bsd", OPEN), + LIC("zlib", OPEN), + LIC("mit", OPEN), + LIC("gpl", GPL), + LIC("special", SPECIAL), + LIC("nonexclusive", SPECIAL), + LIC("noncommercial", SPECIAL), + LIC("proprietary", PROPRIETARY), + {0} +}; + +typedef struct Notice_s +{ + int test; + int type; + int verbose; + int ids; + Item_t item[ITEMS]; + Id_t id[IDS]; + char cc[3]; +} Notice_t; + +/* + * return index given <name,size> + */ + +static int +lookup(register const Item_t* item, const char* name, int size) +{ + register int c; + register int i; + + c = name[0]; + for (i = 0; item[i].data; i++) + if (c == item[i].data[0] && size == item[i].size && !strncmp(name, item[i].data, size)) + return i; + return -1; +} + +/* + * copy s of size n to b + * n<0 means 0 terminated string + */ + +static void +copy(register Buffer_t* b, register char* s, int n) +{ + if (n < 0) + n = strlen(s); + while (n--) + PUT(b, *s++); +} + +/* + * center and copy comment line s to p + * if s==0 then + * n>0 first frame line + * n=0 blank line + * n<0 last frame line + * if u>0 then s converted to upper case + * if u<0 then s is left justified + */ + +static void +comment(Notice_t* notice, register Buffer_t* b, register char* s, register int n, int u) +{ + register int i; + register int m; + register int x; + int cc; + + cc = notice->cc[1]; + if (!s) + { + if (n) + { + PUT(b, notice->cc[n > 0 ? 0 : 1]); + for (i = 0; i < COMDATA; i++) + PUT(b, cc); + PUT(b, notice->cc[n > 0 ? 1 : 2]); + } + else + s = ""; + } + if (s) + { + if (n > COMDATA) + n = COMDATA; + PUT(b, cc); + m = (u < 0) ? 1 : (COMDATA - n) / 2; + if ((x = COMDATA - m - n) < 0) + n--; + while (m-- > 0) + PUT(b, ' '); + while (n-- > 0) + { + i = *s++; + if (u > 0 && i >= 'a' && i <= 'z') + i = i - 'a' + 'A'; + PUT(b, i); + } + while (x-- > 0) + PUT(b, ' '); + PUT(b, cc); + } + PUT(b, '\n'); +} + +/* + * expand simple ${...} + */ + +static void +expand(Notice_t* notice, register Buffer_t* b, const Item_t* item) +{ + register char* t; + register char* e; + register int q; + register char* x; + register char* z; + register int c; + int m; + int i; + int k; + + if (t = item->data) + { + q = item->quote; + e = t + item->size; + i = 0; + while (t < e) + { + if (*t == '$' && t < (e + 2) && *(t + 1) == '{') + { + k = m = 0; + x = t += 2; + while (t < e && (c = *t++) != '}') + if (c == '.') + x = t; + else if (c == '-') + { + k = 1; + break; + } + else if (c == '/') + { + m = 1; + break; + } + if ((c = lookup(key, x, t - x - 1)) >= 0 && (x = notice->item[c].data)) + { + z = x + notice->item[c].size; + while (x < z) + { + c = *x++; + if (!m || c >= '0' && c <= '9') + PUT(b, c); + } + } + else if (k) + { + k = 0; + i++; + } + if (k || m) + { + k = 1; + while (t < e) + if ((c = *t++) == '{') + k++; + else if (c == '}' && !--k) + break; + } + } + else if (q > 0 && *t == '\\' && (*(t + 1) == q || *(t + 1) == '\\')) + t++; + else if (*t == '}' && i) + { + t++; + i--; + } + else + PUT(b, *t++); + } + } +} + +/* + * generate a copright notice + */ + +static void +copyright(Notice_t* notice, register Buffer_t* b) +{ + register char* x; + register char* t; + time_t clock; + + copy(b, "Copyright (c) ", -1); + if (notice->test) + clock = (time_t)1000212300; + else if (!(t = notice->item[SOURCE].data)) + { + time(&clock); + t = ctime(&clock) + 20; + } + if ((x = notice->item[START].data) && strncmp(t, x, 4) < 0) + t = x; + if ((x = notice->item[SINCE].data) && strncmp(x, t, 4) < 0) + { + expand(notice, b, ¬ice->item[SINCE]); + PUT(b, '-'); + } + copy(b, t, 4); + if (notice->item[PARENT].data) + { + PUT(b, ' '); + expand(notice, b, ¬ice->item[PARENT]); + } + if (notice->item[CORPORATION].data) + { + PUT(b, ' '); + expand(notice, b, ¬ice->item[CORPORATION]); + if (notice->item[INCORPORATION].data) + { + PUT(b, ' '); + expand(notice, b, ¬ice->item[INCORPORATION]); + } + } + else if (notice->item[COMPANY].data) + { + PUT(b, ' '); + expand(notice, b, ¬ice->item[COMPANY]); + } +} + +typedef struct Stack_s +{ + char* info; + char* file; + int line; + int size; +} Stack_t; + +static int +push(Stack_t* sp, char* file, char* parent, char* info, int size, Buffer_t* buf) +{ + char* s; + char* t; + int i; + int n; + char path[1024]; + + if (size <= 8) + { + copy(buf, file, -1); + copy(buf, ": no space", -1); + PUT(buf, 0); + return -1; + } + if (*file != '/' && parent && (s = strrchr(parent, '/'))) + { + n = s - parent + 1; + if ((strlen(file) + n + 1) <= sizeof(path)) + { + memcpy(path, parent, n); + strcpy(path + n, file); + file = path; + } + } + if ((i = open(file, O_RDONLY)) < 0) + { + /* this hack viewpath lookup works for default package setups */ + if (file == path) + for (s = path; *s; s++) + if (s[0] == '/' && s[1] == 'a' && s[2] == 'r' && s[3] == 'c' && s[4] == 'h' && s[5] == '/') + { + t = s; + for (s += 6; *s && *s != '/'; s++); + while (*t++ = *s++); + i = open(file, O_RDONLY); + } + if (i < 0) + { + copy(buf, file, -1); + copy(buf, ": cannot open", -1); + PUT(buf, 0); + return -1; + } + } + n = read(i, info, size - 1); + close(i); + if (n < 0) + { + copy(buf, file, -1); + copy(buf, ": cannot read", -1); + PUT(buf, 0); + return -1; + } + info[n++] = 0; + sp->file = file; + sp->info = info; + sp->line = 0; + sp->size = n; + return 0; +} + +/* + * read the license file and generate a comment in p, length size + * license length in p returned, -1 on error + * -1 return places 0 terminated error string in p + */ + +int +astlicense(char* p, int size, char* file, char* options, int cc1, int cc2, int cc3) +{ + register char* s; + register char* v; + register char* x; + register int c; + int i; + int h; + int k; + int n; + int q; + int contributor; + int first; + int level; + int quote; + char* data; + char tmpbuf[COMLINE]; + char info[8 * 1024]; + Stack_t input[4]; + Notice_t notice; + Item_t item; + Buffer_t buf; + Buffer_t tmp; + + buf.end = (buf.buf = buf.nxt = p) + size; + tmp.end = (tmp.buf = tmp.nxt = tmpbuf) + sizeof(tmpbuf); + level = 0; + data = info; + level = -1; + if (options) + { + level++; + input[level].file = "<options>"; + input[level].info = options; + input[level].line = 0; + } + if (file && *file) + { + if (push(&input[++level], file, 0, data, &info[sizeof(info)] - data, &buf)) + return -1; + data += input[level].size; + } + if (level < 0) + return 0; + s = input[level].info; + notice.test = 0; + notice.type = NONE; + notice.verbose = 0; + notice.ids = 0; + notice.cc[0] = cc1; + notice.cc[1] = cc2; + notice.cc[2] = cc3; + for (i = 0; i < ITEMS; i++) + notice.item[i].data = 0; + notice.item[STYLE] = notice.item[CLASS] = lic[notice.type]; + notice.item[STYLE].quote = notice.item[CLASS].quote = 0; + contributor = i = k = 0; + for (;;) + { + first = 1; + while (c = *s) + { + while (c == ' ' || c == '\t' || c == '\n' && ++input[level].line || c == '\r' || c == ',' || c == ';' || c == ')') + c = *++s; + if (!c) + break; + if (c == '#') + { + while (*++s && *s != '\n'); + if (*s) + s++; + input[level].line++; + continue; + } + if (c == '.') + { + while ((c = *++s) && (c == ' ' || c == '\t')); + file = s; + while (c && c != ' ' && c != '\t' && c != '\r' && c != '\n') + c = *++s; + *s = 0; + while (c && c != '\n') + c = *++s; + if (*file) + { + input[level].info = s + (c != 0); + if (++level >= (sizeof(input) / sizeof(input[0])) || push(&input[level], file, input[level-1].file, data, &info[sizeof(info)] - data, &buf)) + return -1; + data += input[level].size; + s = input[level].info; + } + continue; + } + if (c == '\n') + { + s++; + input[level].line++; + continue; + } + if (c == '[') + c = *++s; + x = s; + n = 0; + while (c && c != '+' && c != '=' && c != ']' && c != ')' && c != ',' && c != ' ' && c != '\t' && c != '\n' && c != '\r') + c = *++s; + n = s - x; + h = lookup(key, x, n); + if (c == '+' || c == ']') + c = *++s; + quote = 0; + if (c == '=' || first) + { + if (c == '=') + { + q = ((c = *++s) == '"' || c == '\'') ? *s++ : 0; + if (c == '(') + { + s++; + if (h == LICENSE) + contributor = 0; + else if (h == CONTRIBUTOR) + contributor = 1; + else + { + q = 1; + i = 0; + for (;;) + { + switch (*s++) + { + case 0: + s--; + break; + case '(': + if (!i) + q++; + continue; + case ')': + if (!i && !--q) + break; + continue; + case '"': + case '\'': + if (!i) + i = *(s - 1); + else if (i == *(s - 1)) + i = 0; + continue; + case '\\': + if (*s == i && i == '"') + i++; + continue; + case '\n': + input[level].line++; + continue; + default: + continue; + } + break; + } + } + continue; + } + v = s; + while ((c = *s) && (q == '"' && (c == '\\' && (*(s + 1) == '"' || *(s + 1) == '\\') && s++ && (quote = q)) || q && c != q || !q && c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != ',' && c != ';')) + { + if (c == '\n') + input[level].line++; + s++; + } + } + else + { + h = STYLE; + v = x; + } + if (c == '\n') + input[level].line++; + if (contributor) + { + for (i = 0; i < notice.ids; i++) + if (n == notice.id[i].name.size && !strncmp(x, notice.id[i].name.data, n)) + break; + if (i < IDS) + { + notice.id[i].name.data = x; + notice.id[i].name.size = n; + notice.id[i].name.quote = 0; + notice.id[i].value.data = v; + notice.id[i].value.size = s - v; + notice.id[i].value.quote = quote; + if (notice.ids <= i) + notice.ids = i + 1; + } + } + else if (h == QUERY) + { + if ((s - v) == 3 && v[0] == 'a' && v[1] == 'l' && v[2] == 'l') + { + for (i = 0; i < ITEMS; i++) + if (notice.item[i].size) + { + expand(¬ice, &buf, &key[i]); + PUT(&buf, '='); + for (h = 0;; h++) + if (h >= notice.item[i].size) + { + h = 0; + break; + } + else if (notice.item[i].data[h] == ' ' || notice.item[i].data[h] == '\t') + break; + if (h) + PUT(&buf, '\''); + expand(¬ice, &buf, ¬ice.item[i]); + if (h) + PUT(&buf, '\''); + PUT(&buf, '\n'); + } + } + else + { + if ((h = lookup(key, v, s - v)) < 0) + { + item.data = v; + item.size = s - v; + item.quote = 0; + expand(¬ice, &buf, &item); + } + else + expand(¬ice, &buf, ¬ice.item[h]); + PUT(&buf, '\n'); + } + return END(&buf); + } + else + { + if (h == STYLE) + switch (c = lookup(lic, v, s - v)) + { + case NONE: + return 0; + case TEST: + notice.test = 1; + h = -1; + break; + case VERBOSE: + notice.verbose = 1; + h = -1; + break; + case USAGE: + notice.type = c; + h = -1; + break; + case -1: + c = SPECIAL; + /*FALLTHROUGH*/ + default: + notice.type = c; + notice.item[CLASS].data = lic[lic[c].quote].data; + notice.item[CLASS].size = lic[lic[c].quote].size; + if (notice.item[STYLE].data != lic[NONE].data) + h = -1; + break; + } + if (h >= 0) + { + notice.item[h].data = (notice.item[h].size = s - v) ? v : (char*)0; + notice.item[h].quote = quote; + k = 1; + } + } + } + else + { + if (input[level].file) + { + copy(&buf, "\"", -1); + copy(&buf, input[level].file, -1); + copy(&buf, "\", line ", -1); + x = &tmpbuf[sizeof(tmpbuf)]; + *--x = 0; + n = ++input[level].line; + do *--x = ("0123456789")[n % 10]; while (n /= 10); + copy(&buf, x, -1); + copy(&buf, ": ", -1); + } + copy(&buf, "option error: assignment expected", -1); + PUT(&buf, 0); + return -1; + } + if (*s) + s++; + first = 0; + } + if (!level--) + break; + s = input[level].info; + } + if (!k) + return 0; + if (notice.type == INLINE && (!notice.verbose || !notice.item[NOTICE].data)) + return 0; + if (notice.type != USAGE) + { + if (!notice.type) + notice.type = SPECIAL; + comment(¬ice, &buf, NiL, 1, 0); + comment(¬ice, &buf, NiL, 0, 0); + if (notice.item[PACKAGE].data) + { + copy(&tmp, "This software is part of the ", -1); + expand(¬ice, &tmp, ¬ice.item[PACKAGE]); + copy(&tmp, " package", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + if (notice.type >= OPEN) + { + copyright(¬ice, &tmp); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.type >= SPECIAL) + COMMENT(¬ice, &buf, "All Rights Reserved", 0); + } + if (notice.type == CPL || notice.type == EPL) + { + copy(&tmp, notice.item[PACKAGE].data ? "and" : "This software", -1); + copy(&tmp, " is licensed under the", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.type == EPL) + copy(&tmp, "Eclipse Public License", -1); + else + copy(&tmp, "Common Public License", -1); + if (notice.item[VERSION].data) + { + copy(&tmp, ", Version ", -1); + expand(¬ice, &tmp, ¬ice.item[VERSION]); + } + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[CORPORATION].data || notice.item[COMPANY].data) + { + copy(&tmp, "by ", -1); + if (notice.item[PARENT].data) + { + expand(¬ice, &tmp, ¬ice.item[PARENT]); + copy(&tmp, " ", -1); + } + if (notice.item[CORPORATION].data) + { + expand(¬ice, &tmp, ¬ice.item[CORPORATION]); + if (notice.item[INCORPORATION].data) + { + copy(&tmp, " ", -1); + expand(¬ice, &tmp, ¬ice.item[INCORPORATION]); + } + } + else if (notice.item[COMPANY].data) + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "A copy of the License is available at", 0); + if (notice.item[URL].data) + { + expand(¬ice, &tmp, ¬ice.item[URL]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[URLMD5].data) + { + copy(&tmp, "(with md5 checksum ", -1); + expand(¬ice, &tmp, ¬ice.item[URLMD5]); + copy(&tmp, ")", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + } + else if (notice.type == EPL) + COMMENT(¬ice, &buf, "http://www.eclipse.org/org/documents/epl-v10.html", 0); + else + COMMENT(¬ice, &buf, "http://www.opensource.org/licenses/cpl", 0); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == OPEN) + { + copy(&tmp, notice.item[PACKAGE].data ? "and it" : "This software", -1); + copy(&tmp, " may only be used by you under license from", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[i = CORPORATION].data) + { + if (notice.item[PARENT].data) + { + expand(¬ice, &tmp, ¬ice.item[i = PARENT]); + copy(&tmp, " ", -1); + } + expand(¬ice, &tmp, ¬ice.item[CORPORATION]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + else if (notice.item[i = COMPANY].data) + { + if (notice.item[PARENT].data) + { + expand(¬ice, &tmp, ¬ice.item[i = PARENT]); + copy(&tmp, " ", -1); + } + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + else + i = -1; + if (notice.item[URL].data) + { + COMMENT(¬ice, &buf, "A copy of the Source Code Agreement is available", 0); + copy(&tmp, "at the ", -1); + if (i >= 0) + expand(¬ice, &tmp, ¬ice.item[i]); + copy(&tmp, " Internet web site URL", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + comment(¬ice, &buf, NiL, 0, 0); + expand(¬ice, &tmp, ¬ice.item[URL]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[URLMD5].data) + { + copy(&tmp, "(with an md5 checksum of ", -1); + expand(¬ice, &tmp, ¬ice.item[URLMD5]); + copy(&tmp, ")", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + comment(¬ice, &buf, NiL, 0, 0); + } + COMMENT(¬ice, &buf, "If you have copied or used this software without agreeing", 0); + COMMENT(¬ice, &buf, "to the terms of the license you are infringing on", 0); + COMMENT(¬ice, &buf, "the license and copyright and are violating", 0); + if (i >= 0) + expand(¬ice, &tmp, ¬ice.item[i]); + copy(&tmp, "'s", -1); + if (n >= COMLONG) + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + else + PUT(&tmp, ' '); + copy(&tmp, "intellectual property rights.", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == GPL) + { + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "This is free software; you can redistribute it and/or", 0); + COMMENT(¬ice, &buf, "modify it under the terms of the GNU General Public License", 0); + COMMENT(¬ice, &buf, "as published by the Free Software Foundation;", 0); + COMMENT(¬ice, &buf, "either version 2, or (at your option) any later version.", 0); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "This software is distributed in the hope that it", 0); + COMMENT(¬ice, &buf, "will be useful, but WITHOUT ANY WARRANTY;", 0); + COMMENT(¬ice, &buf, "without even the implied warranty of MERCHANTABILITY", 0); + COMMENT(¬ice, &buf, "or FITNESS FOR A PARTICULAR PURPOSE.", 0); + COMMENT(¬ice, &buf, "See the GNU General Public License for more details.", 0); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "You should have received a copy of the", 0); + COMMENT(¬ice, &buf, "GNU General Public License", 0); + COMMENT(¬ice, &buf, "along with this software (see the file COPYING.)", 0); + COMMENT(¬ice, &buf, "If not, a copy is available at", 0); + COMMENT(¬ice, &buf, "http://www.gnu.org/copyleft/gpl.html", 0); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == BSD) + { + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "Redistribution and use in source and binary forms, with or", -1); + COMMENT(¬ice, &buf, "without modification, are permitted provided that the following", -1); + COMMENT(¬ice, &buf, "conditions are met:", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, " 1. Redistributions of source code must retain the above", -1); + COMMENT(¬ice, &buf, " copyright notice, this list of conditions and the", -1); + COMMENT(¬ice, &buf, " following disclaimer.", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, " 2. Redistributions in binary form must reproduce the above", -1); + COMMENT(¬ice, &buf, " copyright notice, this list of conditions and the", -1); + COMMENT(¬ice, &buf, " following disclaimer in the documentation and/or other", -1); + COMMENT(¬ice, &buf, " materials provided with the distribution.", -1); + comment(¬ice, &buf, NiL, 0, 0); + copy(&tmp, " 3. Neither the name of ", -1); + if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data || notice.item[i = COMPANY].data) + expand(¬ice, &tmp, ¬ice.item[i]); + else + copy(&tmp, "the copyright holder", -1); + copy(&tmp, " nor the", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), -1); + COMMENT(¬ice, &buf, " names of its contributors may be used to endorse or", -1); + COMMENT(¬ice, &buf, " promote products derived from this software without", -1); + COMMENT(¬ice, &buf, " specific prior written permission.", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND", -1); + COMMENT(¬ice, &buf, "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,", -1); + COMMENT(¬ice, &buf, "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF", -1); + COMMENT(¬ice, &buf, "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE", -1); + COMMENT(¬ice, &buf, "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS", -1); + COMMENT(¬ice, &buf, "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,", -1); + COMMENT(¬ice, &buf, "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED", -1); + COMMENT(¬ice, &buf, "TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,", -1); + COMMENT(¬ice, &buf, "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON", -1); + COMMENT(¬ice, &buf, "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,", -1); + COMMENT(¬ice, &buf, "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY", -1); + COMMENT(¬ice, &buf, "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE", -1); + COMMENT(¬ice, &buf, "POSSIBILITY OF SUCH DAMAGE.", -1); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == ZLIB) + { + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "This software is provided 'as-is', without any express or implied", -1); + COMMENT(¬ice, &buf, "warranty. In no event will the authors be held liable for any", -1); + COMMENT(¬ice, &buf, "damages arising from the use of this software.", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "Permission is granted to anyone to use this software for any", -1); + COMMENT(¬ice, &buf, "purpose, including commercial applications, and to alter it and", -1); + COMMENT(¬ice, &buf, "redistribute it freely, subject to the following restrictions:", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, " 1. The origin of this software must not be misrepresented;", -1); + COMMENT(¬ice, &buf, " you must not claim that you wrote the original software. If", -1); + COMMENT(¬ice, &buf, " you use this software in a product, an acknowledgment in the", -1); + COMMENT(¬ice, &buf, " product documentation would be appreciated but is not", -1); + COMMENT(¬ice, &buf, " required.", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, " 2. Altered source versions must be plainly marked as such,", -1); + COMMENT(¬ice, &buf, " and must not be misrepresented as being the original", -1); + COMMENT(¬ice, &buf, " software.", -1); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, " 3. This notice may not be removed or altered from any source", -1); + COMMENT(¬ice, &buf, " distribution.", -1); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == MIT) + { + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "Permission is hereby granted, free of charge, to any person", 0); + COMMENT(¬ice, &buf, "obtaining a copy of this software and associated", 0); + COMMENT(¬ice, &buf, "documentation files (the \"Software\"), to deal in the", 0); + COMMENT(¬ice, &buf, "Software without restriction, including without limitation", 0); + COMMENT(¬ice, &buf, "the rights to use, copy, modify, merge, publish, distribute,", 0); + COMMENT(¬ice, &buf, "sublicense, and/or sell copies of the Software, and to", 0); + COMMENT(¬ice, &buf, "permit persons to whom the Software is furnished to do so,", 0); + COMMENT(¬ice, &buf, "subject to the following conditions:", 0); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "The above copyright notice and this permission notice shall", 0); + COMMENT(¬ice, &buf, "be included in all copies or substantial portions of the", 0); + COMMENT(¬ice, &buf, "Software.", 0); + comment(¬ice, &buf, NiL, 0, 0); + COMMENT(¬ice, &buf, "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY", 0); + COMMENT(¬ice, &buf, "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE", 0); + COMMENT(¬ice, &buf, "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR", 0); + COMMENT(¬ice, &buf, "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS", 0); + COMMENT(¬ice, &buf, "OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR", 0); + COMMENT(¬ice, &buf, "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR", 0); + COMMENT(¬ice, &buf, "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE", 0); + COMMENT(¬ice, &buf, "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", 0); + comment(¬ice, &buf, NiL, 0, 0); + } + else + { + if (notice.type == PROPRIETARY) + { + if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data || notice.item[i = COMPANY].data) + { + expand(¬ice, &tmp, ¬ice.item[i]); + copy(&tmp, " - ", -1); + } + else + i = -1; + copy(&tmp, "Proprietary", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + comment(¬ice, &buf, NiL, 0, 0); + if (notice.item[URL].data) + { + copy(&tmp, "This is proprietary source code", -1); + if (i >= 0) + copy(&tmp, " licensed by", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + if (notice.item[PARENT].data) + { + expand(¬ice, &tmp, ¬ice.item[PARENT]); + copy(&tmp, " ", -1); + } + if (notice.item[CORPORATION].data) + { + expand(¬ice, &tmp, ¬ice.item[CORPORATION]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + } + else if (notice.item[COMPANY].data) + { + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + } + } + else + { + copy(&tmp, "This is unpublished proprietary source code", -1); + if (i >= 0) + copy(&tmp, " of", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data) + expand(¬ice, &tmp, ¬ice.item[i]); + if (notice.item[COMPANY].data) + { + if (SIZ(&tmp)) + PUT(&tmp, ' '); + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + } + if (SIZ(&tmp)) + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1); + COMMENT(¬ice, &buf, "and is not to be disclosed or used except in", 1); + COMMENT(¬ice, &buf, "accordance with applicable agreements", 1); + } + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == NONEXCLUSIVE) + { + COMMENT(¬ice, &buf, "For nonexclusive individual use", 1); + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == NONCOMMERCIAL) + { + COMMENT(¬ice, &buf, "For noncommercial use", 1); + comment(¬ice, &buf, NiL, 0, 0); + } + if (notice.type >= PROPRIETARY && !notice.item[URL].data) + { + COMMENT(¬ice, &buf, "Unpublished & Not for Publication", 0); + comment(¬ice, &buf, NiL, 0, 0); + } + if (notice.item[URL].data) + { + copy(&tmp, "This software is licensed", -1); + if (notice.item[CORPORATION].data || notice.item[COMPANY].data) + { + copy(&tmp, " by", -1); + if ((notice.item[PARENT].size + (notice.item[CORPORATION].data ? (notice.item[CORPORATION].size + notice.item[INCORPORATION].size) : notice.item[COMPANY].size)) >= (COMLONG - 6)) + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + else + PUT(&tmp, ' '); + if (notice.item[PARENT].data) + { + expand(¬ice, &tmp, ¬ice.item[PARENT]); + copy(&tmp, " ", -1); + } + if (notice.item[CORPORATION].data) + { + expand(¬ice, &tmp, ¬ice.item[CORPORATION]); + if (notice.item[INCORPORATION].data) + { + copy(&tmp, " ", -1); + expand(¬ice, &tmp, ¬ice.item[INCORPORATION]); + } + } + else if (notice.item[COMPANY].data) + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + } + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + COMMENT(¬ice, &buf, "under the terms and conditions of the license in", 0); + expand(¬ice, &tmp, ¬ice.item[URL]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[URLMD5].data) + { + copy(&tmp, "(with an md5 checksum of ", -1); + expand(¬ice, &tmp, ¬ice.item[URLMD5]); + copy(&tmp, ")", -1); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + comment(¬ice, &buf, NiL, 0, 0); + } + else if (notice.type == PROPRIETARY) + { + COMMENT(¬ice, &buf, "The copyright notice above does not evidence any", 0); + COMMENT(¬ice, &buf, "actual or intended publication of such source code", 0); + comment(¬ice, &buf, NiL, 0, 0); + } + } + if (v = notice.item[NOTICE].data) + { + x = v + notice.item[NOTICE].size; + if (*v == '\n') + v++; + item.quote = notice.item[NOTICE].quote; + do + { + for (item.data = v; v < x && *v != '\n'; v++); + if ((item.size = v - item.data) && *item.data == '\t') + { + item.data++; + item.size--; + h = 0; + } + else + h = -1; + expand(¬ice, &tmp, &item); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), h); + } while (v++ < x); + if (item.size) + comment(¬ice, &buf, NiL, 0, 0); + } + if (notice.item[ORGANIZATION].data) + { + expand(¬ice, &tmp, ¬ice.item[ORGANIZATION]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data) + expand(¬ice, &tmp, ¬ice.item[i]); + if (notice.item[COMPANY].data) + { + if (SIZ(&tmp)) + PUT(&tmp, ' '); + expand(¬ice, &tmp, ¬ice.item[COMPANY]); + } + if (SIZ(&tmp)) + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + if (notice.item[LOCATION].data) + { + expand(¬ice, &tmp, ¬ice.item[LOCATION]); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + comment(¬ice, &buf, NiL, 0, 0); + } + } + if (v = notice.item[AUTHOR].data) + { + x = v + notice.item[AUTHOR].size; + q = (x - v) == 1 && (*v == '*' || *v == '-'); + k = q && notice.type != USAGE ? -1 : 0; + for (;;) + { + if (!q) + { + while (v < x && (*v == ' ' || *v == '\t' || *v == '\r' || *v == '\n' || *v == ',' || *v == '+')) + v++; + if (v >= x) + break; + item.data = v; + while (v < x && *v != ',' && *v != '+' && *v++ != '>'); + item.size = v - item.data; + item.quote = notice.item[AUTHOR].quote; + } + h = 0; + for (i = 0; i < notice.ids; i++) + if (q || item.size == notice.id[i].name.size && !strncmp(item.data, notice.id[i].name.data, item.size)) + { + h = 1; + if (notice.type == USAGE) + { + copy(&buf, "[-author?", -1); + expand(¬ice, &buf, ¬ice.id[i].value); + PUT(&buf, ']'); + } + else + { + if (k < 0) + { + COMMENT(¬ice, &buf, "CONTRIBUTORS", 0); + comment(¬ice, &buf, NiL, 0, 0); + } + k = 1; + expand(¬ice, &tmp, ¬ice.id[i].value); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + if (!q) + break; + } + if (q) + break; + if (!h) + { + if (notice.type == USAGE) + { + copy(&buf, "[-author?", -1); + expand(¬ice, &buf, &item); + PUT(&buf, ']'); + } + else + { + if (k < 0) + { + COMMENT(¬ice, &buf, "CONTRIBUTORS", 0); + comment(¬ice, &buf, NiL, 0, 0); + } + k = 1; + expand(¬ice, &tmp, &item); + comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0); + } + } + } + if (k > 0) + comment(¬ice, &buf, NiL, 0, 0); + } + if (notice.type == USAGE) + { + copy(&buf, "[-copyright?", -1); + copyright(¬ice, &buf); + PUT(&buf, ']'); + if (notice.item[URL].data) + { + copy(&buf, "[-license?", -1); + expand(¬ice, &buf, ¬ice.item[URL]); + PUT(&buf, ']'); + } + PUT(&buf, '\n'); + } + else + comment(¬ice, &buf, NiL, -1, 0); + return END(&buf); +} diff --git a/src/lib/libast/port/astmath.c b/src/lib/libast/port/astmath.c new file mode 100644 index 0000000..395312e --- /dev/null +++ b/src/lib/libast/port/astmath.c @@ -0,0 +1,72 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +/* + * used to test if -last requires -lm + * + * arch -last -lm + * ---- ----- --- + * linux.sparc sfdlen,sfputd frexp,ldexp + */ + +#if N >= 8 +#define _ISOC99_SOURCE 1 +#endif + +#include <math.h> + +int +main() +{ +#if N & 1 + long double value = 0; +#else + double value = 0; +#endif +#if N < 5 + int exp = 0; +#endif + +#if N == 1 + return ldexpl(value, exp) != 0; +#endif +#if N == 2 + return ldexp(value, exp) != 0; +#endif +#if N == 3 + return frexpl(value, &exp) != 0; +#endif +#if N == 4 + return frexp(value, &exp) != 0; +#endif +#if N == 5 + return isnan(value); +#endif +#if N == 6 + return isnan(value); +#endif +#if N == 7 + return copysign(1.0, value) < 0; +#endif +#if N == 8 + return signbit(value); +#endif +} diff --git a/src/lib/libast/port/astquery.c b/src/lib/libast/port/astquery.c new file mode 100644 index 0000000..d0d87db --- /dev/null +++ b/src/lib/libast/port/astquery.c @@ -0,0 +1,114 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * AT&T Research + * + * output printf prompt and read response + * if format==0 then verify that interaction is possible + * + * return: + * + * 0 [1yY+] + * -1 [qQ] or EOF + * 1 otherwise + * + * if (quit&ERROR_PROMPT) then tty forced for IO + * if quit>=0 then [qQ] or EOF calls exit(quit) + */ + +#include <ast.h> +#include <error.h> + +int +astquery(int quit, const char* format, ...) +{ + va_list ap; + register int n; + register int c; + int r; + Sfio_t* ip; + Sfio_t* op; + + static Sfio_t* rfp; + static Sfio_t* wfp; + + r = 0; + va_start(ap, format); + if (!format) + goto done; + r = -1; + if (!rfp) + { + c = errno; + if (isatty(sffileno(sfstdin))) + rfp = sfstdin; + else if (!(rfp = sfopen(NiL, "/dev/tty", "r"))) + goto done; + if (isatty(sffileno(sfstderr))) + wfp = sfstderr; + else if (!(wfp = sfopen(NiL, "/dev/tty", "w"))) + goto done; + errno = c; + } + if (quit & ERROR_PROMPT) + { + quit &= ~ERROR_PROMPT; + ip = rfp; + op = wfp; + } + else + { + ip = sfstdin; + op = sfstderr; + } + sfsync(sfstdout); + sfvprintf(op, format, ap); + sfsync(op); + for (n = c = sfgetc(ip);; c = sfgetc(ip)) + switch (c) + { + case EOF: + n = c; + /*FALLTHROUGH*/ + case '\n': + switch (n) + { + case EOF: + case 'q': + case 'Q': + if (quit >= 0) + exit(quit); + goto done; + case '1': + case 'y': + case 'Y': + case '+': + r = 0; + goto done; + } + return 1; + } + done: + va_end(ap); + return r; +} diff --git a/src/lib/libast/port/aststatic.c b/src/lib/libast/port/aststatic.c new file mode 100644 index 0000000..7517572 --- /dev/null +++ b/src/lib/libast/port/aststatic.c @@ -0,0 +1,44 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped + +/* + * ast static data initialization + */ + +#include <ast.h> + +#if _dll_data_intercept && ( _DLL_BLD || _BLD_DLL ) + +void +_ast_init(void) +{ + struct _astdll* ap = _ast_getdll(); + + ap->_dll_environ = &environ; +} + +#else + +NoN(aststatic) + +#endif diff --git a/src/lib/libast/port/astwinsize.c b/src/lib/libast/port/astwinsize.c new file mode 100644 index 0000000..66f4e09 --- /dev/null +++ b/src/lib/libast/port/astwinsize.c @@ -0,0 +1,143 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped + +/* + * AT&T Research + * return terminal rows and cols + */ + +#include <ast.h> +#include <ast_tty.h> + +#if defined(__STDPP__directive) && defined(__STDPP__hide) +__STDPP__directive pragma pp:hide ioctl sleep +#else +#define ioctl ______ioctl +#define sleep ______sleep +#endif + +#if _sys_ioctl +#include <sys/ioctl.h> +#endif + +#if defined(TIOCGWINSZ) +#if _sys_stream && _sys_ptem +#include <sys/stream.h> +#include <sys/ptem.h> +#endif +#else +#if !defined(TIOCGSIZE) && !defined(TIOCGWINSZ) +#if _hdr_jioctl +#define jwinsize winsize +#include <jioctl.h> +#else +#if _sys_jioctl +#define jwinsize winsize +#include <sys/jioctl.h> +#endif +#endif +#endif +#endif + +#if defined(__STDPP__directive) && defined(__STDPP__hide) +__STDPP__directive pragma pp:nohide ioctl sleep +#else +#undef ioctl +#undef sleep +#endif + +static int ttctl(int, int, void*); + +void +astwinsize(int fd, register int* rows, register int* cols) +{ +#ifdef TIOCGWINSZ +#define NEED_ttctl + struct winsize ws; + + if (!ttctl(fd, TIOCGWINSZ, &ws) && ws.ws_col > 0 && ws.ws_row > 0) + { + if (rows) *rows = ws.ws_row; + if (cols) *cols = ws.ws_col; + } + else +#else +#ifdef TIOCGSIZE +#define NEED_ttctl + struct ttysize ts; + + if (!ttctl(fd, TIOCGSIZE, &ts) && ts.ts_lines > 0 && ts.ts_cols > 0) + { + if (rows) *rows = ts.ts_lines; + if (cols) *cols = ts.ts_cols; + } + else +#else +#ifdef JWINSIZE +#define NEED_ttctl + struct winsize ws; + + if (!ttctl(fd, JWINSIZE, &ws) && ws.bytesx > 0 && ws.bytesy > 0) + { + if (rows) *rows = ws.bytesy; + if (cols) *cols = ws.bytesx; + } + else +#endif +#endif +#endif + { + char* s; + + if (rows) *rows = (s = getenv("LINES")) ? strtol(s, NiL, 0) : 0; + if (cols) *cols = (s = getenv("COLUMNS")) ? strtol(s, NiL, 0) : 0; + } +} + +#ifdef NEED_ttctl + +/* + * tty ioctl() -- no cache + */ + +static int +ttctl(register int fd, int op, void* tt) +{ + register int v; + + if (fd < 0) + { + for (fd = 0; fd <= 2; fd++) + if (!ioctl(fd, op, tt)) return(0); + if ((fd = open("/dev/tty", O_RDONLY)) >= 0) + { + v = ioctl(fd, op, tt); + close(fd); + return(v); + } + } + else if (!ioctl(fd, op, tt)) return(0); + return(-1); +} + +#endif diff --git a/src/lib/libast/port/atmain.C b/src/lib/libast/port/atmain.C new file mode 100644 index 0000000..b6d7560 --- /dev/null +++ b/src/lib/libast/port/atmain.C @@ -0,0 +1,37 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#if ! __MVS__ + +void _STUB_atmain(){} + +#else + +extern "C" void _ast_init(); + +class Atmain_t +{ +public: Atmain_t() { _ast_init(); } +}; + +static Atmain_t atmain(); + +#endif diff --git a/src/lib/libast/port/iblocks.c b/src/lib/libast/port/iblocks.c new file mode 100644 index 0000000..a768b84 --- /dev/null +++ b/src/lib/libast/port/iblocks.c @@ -0,0 +1,95 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * aux function for <ls.h> iblocks() macro + * + * return number of blocks, including indirect block count + * given stat info + * + * mail gsf@research.att.com when you figure out the stat.st_blocks units + * until then we assume LS_BLOCKSIZE (512) + */ + +#include <ast.h> +#if _AIX /* XXX */ +#undef major +#undef minor +#undef makedev +#endif +#include <ast_param.h> +#include <ls.h> + +#if !_mem_st_blocks_stat + +#ifndef B_DIRECT +#define B_DIRECT 10 +#endif + +#ifdef BITFS + +#define B_SIZE BSIZE(st->st_dev) +#define B_INDIRECT NINDIR(st->st_dev) + +#else + +#ifdef BSIZE +#define B_SIZE BSIZE +#else +#define B_SIZE 1024 +#endif + +#ifdef NINDIR +#define B_INDIRECT NINDIR +#else +#define B_INDIRECT 128 +#endif + +#endif + +#endif + +off_t +_iblocks(register struct stat* st) +{ +#if _mem_st_blocks_stat + + return (st->st_blocks <= 0 || st->st_size <= 0) ? 0 : st->st_blocks; + +#else + unsigned long b; + unsigned long t; + + t = b = (st->st_size + B_SIZE - 1) / B_SIZE; + if ((b -= B_DIRECT) > 0) + { + t += (b - 1) / B_INDIRECT + 1; + if ((b -= B_INDIRECT) > 0) + { + t += (b - 1) / (B_INDIRECT * B_INDIRECT) + 1; + if (b > B_INDIRECT * B_INDIRECT) + t++; + } + } + return t * B_SIZE / LS_BLOCKSIZE; +#endif +} diff --git a/src/lib/libast/port/lc.c b/src/lib/libast/port/lc.c new file mode 100644 index 0000000..488dd8d --- /dev/null +++ b/src/lib/libast/port/lc.c @@ -0,0 +1,883 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped + +/* + * locale state implementation + */ + +#include "lclib.h" +#include "lclang.h" +#include "FEATURE/locale" + +#include <ctype.h> + +typedef struct Local_s +{ + const char* name; + int size; +} Local_t; + +#undef setlocale /* this file deals with the system locale */ + +static Lc_numeric_t default_numeric = { '.', -1 }; + +static Lc_t default_lc = +{ + "C", + "POSIX", + &lc_languages[0], + &lc_territories[0], + &lc_charsets[0], + 0, + LC_default|LC_checked|LC_local, + 0, + { + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 }, + { &default_lc, 0, (void*)&default_numeric }, + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 }, + { &default_lc, 0, 0 } + } +}; + +static Lc_numeric_t debug_numeric = { ',', '.' }; + +static Lc_t debug_lc = +{ + "debug", + "debug", + &lc_languages[1], + &lc_territories[1], + &lc_charsets[0], + 0, + LC_debug|LC_checked|LC_local, + 0, + { + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, (void*)&debug_numeric }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 }, + { &debug_lc, 0, 0 } + }, + &default_lc +}; + +static Lc_t* lcs = &debug_lc; + +Lc_t* locales[] = +{ + &default_lc, + &default_lc, + &default_lc, + &default_lc, + &default_lc, + &default_lc, + &default_lc, + &default_lc, + &default_lc, + &default_lc, + &default_lc, + &default_lc, + &default_lc, + &default_lc +}; + +/* + * return the internal category index for category + */ + +int +lcindex(int category, int min) +{ + switch (category) + { + case LC_ALL: return min ? -1 : AST_LC_ALL; + case LC_ADDRESS: return AST_LC_ADDRESS; + case LC_COLLATE: return AST_LC_COLLATE; + case LC_CTYPE: return AST_LC_CTYPE; + case LC_IDENTIFICATION: return AST_LC_IDENTIFICATION; + case LC_LANG: return AST_LC_LANG; + case LC_MEASUREMENT: return AST_LC_MEASUREMENT; + case LC_MESSAGES: return AST_LC_MESSAGES; + case LC_MONETARY: return AST_LC_MONETARY; + case LC_NAME: return AST_LC_NAME; + case LC_NUMERIC: return AST_LC_NUMERIC; + case LC_PAPER: return AST_LC_PAPER; + case LC_TELEPHONE: return AST_LC_TELEPHONE; + case LC_TIME: return AST_LC_TIME; + case LC_XLITERATE: return AST_LC_XLITERATE; + } + return -1; +} + +/* + * return the first category table entry + */ + +Lc_category_t* +lccategories(void) +{ + return (Lc_category_t*)&lc_categories[0]; +} + +/* + * return the current info for category + */ + +Lc_info_t* +lcinfo(register int category) +{ + if ((category = lcindex(category, 0)) < 0) + return 0; + return LCINFO(category); +} + +/* + * return 1 if s matches the alternation pattern p + * if minimum!=0 then at least that many chars must match + * if standard!=0 and s[0] is a digit leading non-digits are ignored in p + */ + +static int +match(const char* s, register const char* p, int minimum, int standard) +{ + register const char* t; + const char* x; + int w; + int z; + + z = 0; + do + { + t = s; + if (standard) + { + if (isdigit(*t)) + while (*p && !isdigit(*p)) + p++; + else if (isdigit(*p)) + while (*t && !isdigit(*t)) + t++; + } + if (*p) + { + w = 0; + x = p; + while (*p && *p != '|') + { + if (!*t || *t == ',') + break; + else if (*t == *p) + /*ok*/; + else if (*t == '-') + { + if (standard && isdigit(*p)) + { + t++; + continue; + } + while (*p && *p != '-') + p++; + if (!*p) + break; + } + else if (*p == '-') + { + if (standard && isdigit(*t)) + { + p++; + continue; + } + w = 1; + while (*t && *t != '-') + t++; + if (!*t) + break; + } + else + break; + t++; + p++; + } + if ((!*t || *t == ',') && (!*p || *p == '|' || w)) + return p - x; + if (minimum && z < (p - x) && (p - x) >= minimum) + z = p - x; + } + while (*p && *p != '|') + p++; + } while (*p++); + return z; +} + +/* + * return 1 if s matches the charset names in cp + */ + +static int +match_charset(register const char* s, register const Lc_charset_t* cp) +{ + return match(s, cp->code, 0, 1) || match(s, cp->alternates, 3, 1) || cp->ms && match(s, cp->ms, 0, 1); +} + +/* + * low level for lccanon + */ + +static size_t +canonical(const Lc_language_t* lp, const Lc_territory_t* tp, const Lc_charset_t* cp, const Lc_attribute_list_t* ap, unsigned long flags, char* buf, size_t siz) +{ + register int c; + register int u; + register char* s; + register char* e; + register const char* t; + char* p; + char* r; + + if (!(flags & (LC_abbreviated|LC_default|LC_local|LC_qualified|LC_verbose))) + flags |= LC_abbreviated; + s = buf; + e = &buf[siz - 3]; + if (lp) + { + if (lp->flags & (LC_debug|LC_default)) + { + for (t = lp->code; s < e && (*s = *t++); s++); + *s++ = 0; + return s - buf; + } + if (flags & LC_verbose) + { + u = 1; + t = lp->name; + while (s < e && (c = *t++)) + { + if (u) + { + u = 0; + c = toupper(c); + } + else if (!isalnum(c)) + u = 1; + *s++ = c; + } + } + else + for (t = lp->code; s < e && (*s = *t++); s++); + } + if (s < e) + { + if (tp && tp != &lc_territories[0]) + { + r = 0; + if (lp) + { + if ((flags & (LC_abbreviated|LC_default)) && streq(lp->code, tp->code)) + r = s; + *s++ = '_'; + } + if (flags & LC_verbose) + { + u = 1; + t = tp->name; + while (s < e && (c = *t++) && c != '|') + { + if (u) + { + u = 0; + c = toupper(c); + } + else if (!isalnum(c)) + u = 1; + *s++ = c; + } + } + else + for (t = tp->code; s < e && (*s = toupper(*t++)); s++); + if (r) + { + *s = 0; + if ((p = setlocale(LC_MESSAGES, 0)) && (p = strdup(p))) + { + if (!setlocale(LC_MESSAGES, buf)) + { + *r = 0; + if (!setlocale(LC_MESSAGES, buf)) + *r = '_'; + } + setlocale(LC_MESSAGES, p); + free(p); + } + } + } + if (lp && (!(flags & (LC_abbreviated|LC_default)) || cp != lp->charset) && s < e) + { + *s++ = '.'; + t = cp->code; + if (streq(cp->code, "utf8") && (t = _locale_utf8_str)) + for (; s < e && (c = *t++); s++) + *s = c; + else + for (t = cp->code; s < e && (c = *t++); s++) + { + if (islower(c)) + c = toupper(c); + *s = c; + } + } + for (c = '@'; ap && s < e; ap = ap->next) + if (!(flags & (LC_abbreviated|LC_default|LC_verbose)) || !(ap->attribute->flags & LC_default)) + { + *s++ = c; + c = ','; + for (t = ap->attribute->name; s < e && (*s = *t++); s++); + } + } + *s++ = 0; + return s - buf; +} + +/* + * generate a canonical locale name in buf + */ + +size_t +lccanon(Lc_t* lc, unsigned long flags, char* buf, size_t siz) +{ + if ((flags & LC_local) && (!lc->language || !(lc->language->flags & (LC_debug|LC_default)))) + { +#if _WINIX + char lang[64]; + char code[64]; + char ctry[64]; + + if (lc->index && + GetLocaleInfo(lc->index, LOCALE_SENGLANGUAGE, lang, sizeof(lang)) && + GetLocaleInfo(lc->index, LOCALE_SENGCOUNTRY, ctry, sizeof(ctry))) + { + if (!GetLocaleInfo(lc->index, LOCALE_IDEFAULTANSICODEPAGE, code, sizeof(code))) + code[0] = 0; + if (!lc->charset || !lc->charset->ms) + return sfsprintf(buf, siz, "%s_%s", lang, ctry); + else if (streq(lc->charset->ms, code)) + return sfsprintf(buf, siz, "%s_%s.%s", lang, ctry, code); + else + return sfsprintf(buf, siz, "%s_%s.%s,%s", lang, ctry, code, lc->charset->ms); + } +#endif + buf[0] = '-'; + buf[1] = 0; + return 0; + } + return canonical(lc->language, lc->territory, lc->charset, lc->attributes, flags, buf, siz); +} + +/* + * make an Lc_t from a locale name + */ + +Lc_t* +lcmake(const char* name) +{ + register int c; + register char* s; + register char* e; + register const char* t; + const char* a; + char* w; + char* language_name; + char* territory_name; + char* charset_name; + char* attributes_name; + Lc_t* lc; + const Lc_map_t* mp; + const Lc_language_t* lp; + const Lc_territory_t* tp; + const Lc_territory_t* tpb; + const Lc_territory_t* primary; + const Lc_charset_t* cp; + const Lc_charset_t* ppa; + const Lc_attribute_t* ap; + Lc_attribute_list_t* ai; + Lc_attribute_list_t* al; + int i; + int n; + int z; + char buf[PATH_MAX / 2]; + char tmp[PATH_MAX / 2]; + Local_t local[2]; + + if (!(t = name) || !*t) + return &default_lc; + for (lc = lcs; lc; lc = lc->next) + if (!strcasecmp(t, lc->code) || !strcasecmp(t, lc->name)) + return lc; + for (mp = lc_maps; mp->code; mp++) + if (streq(t, mp->code)) + { + lp = mp->language; + tp = mp->territory; + cp = mp->charset; + if (!mp->attribute) + al = 0; + else if (al = newof(0, Lc_attribute_list_t, 1, 0)) + al->attribute = mp->attribute; + goto mapped; + } + language_name = buf; + territory_name = charset_name = attributes_name = 0; + s = buf; + e = &buf[sizeof(buf)-2]; + a = 0; + n = 0; + while (s < e && (c = *t++)) + { + if (isspace(c) || (c == '(' || c == '-' && *t == '-') && ++n) + { + while ((c = *t++) && (isspace(c) || (c == '-' || c == '(' || c == ')') && ++n)) + if (!c) + break; + if (isalnum(c) && !n) + *s++ = '-'; + else + { + n = 0; + if (!a) + { + a = t - 1; + while (c && c != '_' && c != '.' && c != '@') + c = *t++; + if (!c) + break; + } + } + } + if (c == '_' && !territory_name) + { + *s++ = 0; + territory_name = s; + } + else if (c == '.' && !charset_name) + { + *s++ = 0; + charset_name = s; + } + else if (c == '@' && !attributes_name) + { + *s++ = 0; + attributes_name = s; + } + else + { + if (isupper(c)) + c = tolower(c); + *s++ = c; + } + } + if ((t = a) && s < e) + { + if (attributes_name) + *s++ = ','; + else + { + *s++ = 0; + attributes_name = s; + } + while (s < e && (c = *t++)) + { + if (isspace(c) || (c == '(' || c == ')' || c == '-' && *t == '-') && ++n) + { + while ((c = *t++) && (isspace(c) || (c == '-' || c == '(' || c == ')') && ++n)) + if (!c) + break; + if (isalnum(c) && !n) + *s++ = '-'; + else + n = 0; + } + if (c == '_' || c == '.' || c == '@') + break; + if (isupper(c)) + c = tolower(c); + *s++ = c; + } + } + *s = 0; +#if AHA + if ((ast.locale.set & AST_LC_debug) && !(ast.locale.set & AST_LC_internal)) + sfprintf(sfstderr, "locale make %s language=%s territory=%s charset=%s attributes=%s\n", name, language_name, territory_name, charset_name, attributes_name); +#endif + tp = 0; + cp = ppa = 0; + al = 0; + + /* + * language + */ + + n = strlen(s = language_name); + if (n == 2) + for (lp = lc_languages; lp->code && !streq(s, lp->code); lp++); + else if (n == 3) + { + for (lp = lc_languages; lp->code && (!lp->alternates || !match(s, lp->alternates, n, 0)); lp++); + if (!lp->code) + { + c = s[2]; + s[2] = 0; + for (lp = lc_languages; lp->code && !streq(s, lp->code); lp++); + s[2] = c; + if (lp->code) + n = 1; + } + } + else if (streq(s, "c") || streq(s, "posix")) + lp = &lc_languages[0]; + else + lp = 0; + if (!lp || !lp->code) + { + for (lp = lc_languages; lp->code && !match(s, lp->name, 0, 0); lp++); + if (!lp || !lp->code) + { + if (!territory_name) + { + if (n == 2) + for (tp = lc_territories; tp->code && !streq(s, tp->code); tp++); + else + { + z = 0; + tpb = 0; + for (tp = lc_territories; tp->name; tp++) + if ((i = match(s, tp->name, 3, 0)) > z) + { + tpb = tp; + if ((z = i) == n) + break; + } + if (tpb) + tp = tpb; + } + if (tp->code) + lp = tp->languages[0]; + } + if (!lp || !lp->code) + { + /* + * name not in the tables so let + * _ast_setlocale() and/or setlocale() + * handle the validity checks + */ + + s = (char*)name; + z = strlen(s) + 1; + if (!(lp = newof(0, Lc_language_t, 1, z))) + return 0; + name = ((Lc_language_t*)lp)->code = ((Lc_language_t*)lp)->name = (const char*)(lp + 1); + memcpy((char*)lp->code, s, z - 1); + tp = &lc_territories[0]; + cp = &lc_charsets[0]; + if (charset_name) + for (ppa = lc_charsets; ppa->code; ppa++) + if (match_charset(charset_name, ppa)) + { + cp = ppa; + break; + } + ((Lc_language_t*)lp)->charset = cp; + al = 0; + goto override; + } + } + } + + /* + * territory + */ + + if (!tp || !tp->code) + { + if (!(s = territory_name)) + { + n = 0; + primary = 0; + for (tp = lc_territories; tp->code; tp++) + if (tp->languages[0] == lp) + { + if (tp->flags & LC_primary) + { + n = 1; + primary = tp; + break; + } + n++; + primary = tp; + } + if (n == 1) + tp = primary; + s = (char*)lp->code; + } + if (!tp || !tp->code) + { + n = strlen(s); + if (n == 2) + { + for (tp = lc_territories; tp->code; tp++) + if (streq(s, tp->code)) + { + if (lp != &lc_languages[0]) + { + for (i = 0; i < elementsof(tp->languages) && lp != tp->languages[i]; i++); + if (i >= elementsof(tp->languages)) + tp = 0; + } + break; + } + } + else + { + for (tp = lc_territories; tp->code; tp++) + if (match(s, tp->name, 3, 0)) + { + for (i = 0; i < elementsof(tp->languages) && lp != tp->languages[i]; i++); + if (i < elementsof(tp->languages)) + break; + } + } + if (tp && !tp->code) + tp = 0; + } + } + + /* + * attributes -- done here to catch misplaced charset references + */ + + if (s = attributes_name) + { + do + { + for (w = s; *s && *s != ','; s++); + c = *s; + *s = 0; + if (!(cp = lp->charset) || !match_charset(w, cp)) + for (cp = lc_charsets; cp->code; cp++) + if (match_charset(w, cp)) + { + ppa = cp; + break; + } + if (!cp->code) + { + for (i = 0; i < elementsof(lp->attributes) && (ap = lp->attributes[i]); i++) + if (match(w, ap->name, 5, 0)) + { + if (ai = newof(0, Lc_attribute_list_t, 1, 0)) + { + ai->attribute = ap; + ai->next = al; + al = ai; + } + break; + } + if (i >= elementsof(lp->attributes) && (ap = newof(0, Lc_attribute_t, 1, sizeof(Lc_attribute_list_t) + s - w + 1))) + { + ai = (Lc_attribute_list_t*)(ap + 1); + strcpy((char*)(((Lc_attribute_t*)ap)->name = (const char*)(ai + 1)), w); + ai->attribute = ap; + ai->next = al; + al = ai; + } + } + *s = c; + } while (*s++); + } + + /* + * charset + */ + + if (s = charset_name) + for (cp = lc_charsets; cp->code; cp++) + if (match_charset(s, cp)) + break; +#if AHA + if ((ast.locale.set & AST_LC_debug) && !(ast.locale.set & AST_LC_internal)) + sfprintf(sfstderr, "locale make %s charset_name=%s cp=%s ppa=%s lp=%s\n", name, charset_name, cp ? cp->code : 0, ppa, lp->charset); +#endif + if (!cp || !cp->code) + cp = ppa ? ppa : lp->charset; + mapped: + z = canonical(lp, tp, cp, al, 0, s = tmp, sizeof(tmp)); + + /* + * add to the list of possibly active locales + */ + + override: + n = strlen(name) + 1; + local[0].name = default_lc.name; + local[0].size = strlen(local[0].name); + local[1].name = default_lc.code; + local[1].size = strlen(local[1].name); + i = -1; + for (c = 0; c < elementsof(local); ++c) + if (strneq(name, local[c].name, local[c].size)) + { + switch (name[local[c].size]) + { + case '.': + case '_': + case 0: + i = c; + z += local[!i].size + n; + break; + } + break; + } + if (!(lc = newof(0, Lc_t, 1, n + z))) + return 0; + strcpy((char*)(lc->name = (const char*)(lc + 1)), name); + lc->code = lc->name + n; + if (i >= 0) + { + lc->flags |= LC_local; + strcpy((char*)lc->code, local[!i].name); + strcpy((char*)lc->code + local[!i].size, name + local[i].size); + } + else + strcpy((char*)lc->code, s); + lc->language = lp ? lp : &lc_languages[0]; + lc->territory = tp ? tp : &lc_territories[0]; + lc->charset = cp ? cp : &lc_charsets[0]; + if (streq(lc->charset->code, "utf8")) + lc->flags |= LC_utf8; + lc->attributes = al; + for (i = 0; i < elementsof(lc->info); i++) + lc->info[i].lc = lc; +#if _WINIX + n = SUBLANG_DEFAULT; + if (tp) + for (i = 0; i < elementsof(tp->languages); i++) + if (lp == tp->languages[i]) + { + n = tp->indices[i]; + break; + } + lc->index = MAKELCID(MAKELANGID(lp->index, n), SORT_DEFAULT); +#endif + lc->next = lcs; + lcs = lc; + if ((ast.locale.set & AST_LC_debug) && !(ast.locale.set & AST_LC_internal)) + sfprintf(sfstderr, "locale make %17s %16s %16s %16s language=%s territory=%s charset=%s%s\n", "", lc->name, lc->code, "", lc->language->name, lc->territory->name, lc->charset->code, (lc->flags & LC_local) ? " local" : ""); + return lc; +} + +/* + * return an Lc_t* for each locale in the tables + * one Lc_t is allocated on the first call with lc==0 + * this is freed when 0 returned + * the return value is not part of the lcmake() cache + */ + +typedef struct Lc_scan_s +{ + Lc_t lc; + Lc_attribute_list_t list; + int territory; + int language; + int attribute; + char buf[256]; +} Lc_scan_t; + +Lc_t* +lcscan(Lc_t* lc) +{ + register Lc_scan_t* ls; + + if (!(ls = (Lc_scan_t*)lc)) + { + if (!(ls = newof(0, Lc_scan_t, 1, 0))) + return 0; + ls->lc.code = ls->lc.name = ls->buf; + ls->territory = -1; + ls->language = elementsof(ls->lc.territory->languages); + ls->attribute = elementsof(ls->lc.language->attributes); + } + if (++ls->attribute >= elementsof(ls->lc.language->attributes) || !(ls->list.attribute = ls->lc.language->attributes[ls->attribute])) + { + if (++ls->language >= elementsof(ls->lc.territory->languages) || !(ls->lc.language = ls->lc.territory->languages[ls->language])) + { + if (!lc_territories[++ls->territory].code) + { + free(ls); + return 0; + } + ls->lc.territory = &lc_territories[ls->territory]; + ls->lc.language = ls->lc.territory->languages[ls->language = 0]; + } + if (ls->lc.language) + { + ls->lc.charset = ls->lc.language->charset ? ls->lc.language->charset : &lc_charsets[0]; + ls->list.attribute = ls->lc.language->attributes[ls->attribute = 0]; + } + else + { + ls->lc.charset = &lc_charsets[0]; + ls->list.attribute = 0; + } + } + ls->lc.attributes = ls->list.attribute ? &ls->list : (Lc_attribute_list_t*)0; +#if _WINIX + if (!ls->lc.language || !ls->lc.language->index) + ls->lc.index = 0; + else + { + if ((!ls->list.attribute || !(ls->lc.index = ls->list.attribute->index)) && + (!ls->lc.territory || !(ls->lc.index = ls->lc.territory->indices[ls->language]))) + ls->lc.index = SUBLANG_DEFAULT; + ls->lc.index = MAKELCID(MAKELANGID(ls->lc.language->index, ls->lc.index), SORT_DEFAULT); + } +#endif + canonical(ls->lc.language, ls->lc.territory, ls->lc.charset, ls->lc.attributes, 0, ls->buf, sizeof(ls->buf)); + return (Lc_t*)ls; +} diff --git a/src/lib/libast/port/lc.tab b/src/lib/libast/port/lc.tab new file mode 100644 index 0000000..87905a1 --- /dev/null +++ b/src/lib/libast/port/lc.tab @@ -0,0 +1,275 @@ +# +# language_territory.charset@attribute tables +# + +:charset: + + iso8859-1 latin1|west-europe 1252 + iso8859-2 latin2|east-europe 1250 + iso8859-3 latin3|south-europe 1257 + iso8859-4 latin4|north-europe + iso8859-5 cyrillic 1251 + iso8859-6 arabic 1256 + iso8859-7 greek 1253 + iso8859-8 hebrew 1255 + iso8859-9 latin5|turkish 1254 + iso8859-10 latin6|nordic + iso8859-13 latin7 + iso8859-14 latin8|celtic + iso8859-15 latin0 + iso2022 japanese|korean + iso4873 japanese-ascii|korean-ascii + koi8-r russian + utf8 plan9 + +:language: + + aa afar + ab abkhazian + af afrikaans afr + am amharic + ar arabic ara iso8859-6 + as assamese + ay aymara + az azerbaijani + ba bashkir + be belarusian bel + bg bulgarian bul iso8859-5 + bh bihari + bi bislama + bn bengali-bangla + bo tibetan + br breton + ca catalan cat + co corsican + cs czech ces|cze iso8859-2 + cy welsh + da danish dan + de german deu|ger + dz bhutani + el greek ell|gre iso8859-7 + en english eng + eo esperanto + es spanish spa - traditional:default|modern + et estonian est iso8859-3 + eu basque eus|baq + fa persian + fi finnish fin + fj fiji + fo faeroese + fr french fra|fre + fy frisian + ga irish - iso8859-14 + gd scots-gaelic - iso8859-14 + gl galician + gn guarani + gu gujarati + ha hausa + he hebrew heb iso8859-8 + hi hindi + hr croatian hrv|scr iso8859-2 + hu hungarian hun iso8859-2 + hy armenian + ia interlingua + id indonesian ind + ie interlingue + ik inupiak + in indonesian + is icelandic isl|ice + it italian ita + iw hebrew + ja japanese jpn + ji yiddish + jw javanese + ka georgian + kk kazakh kaz + kl greenlandic + km cambodian + kn kannada + ko korean kor + ks kashmiri + ku kurdish + ky kirghiz + la latin + ln lingala + lo laothian + lt lithuanian lit iso8859-13 + lv latvian lav iso8859-13 + mg malagasy + mi maori + mk macedonian mkd|mac + ml malayalam mal + mn mongolian + mo moldavian + mr marathi + ms malay msa|may + mt maltese + my burmese + na nauru + nb norwegian-bokmal nob + ne nepali + nl dutch nld|dut + nn norwegian-nynorsk nno|non + no norwegian nor + oc occitan + om oromo + or oriya + pa punjabi + pl polish pol iso8859-2 + ps pushto + pt portuguese por + qu quechua + rm rhaeto-romance + rn kirundi + ro romanian ron|rum iso8859-2 + ru russian rus iso8859-5 + rw kinyarwanda + sa sanskrit + sd sindhi + sg sangro + sh serbo-croatian + si singhalese + sk slovak slk|slo iso8859-2 + sl slovenian slv iso8859-2 + sm samoan + sn shona + so somali + sq albanian sqi|alb + sr serbian srp iso8859-2 + ss siswati + st sesotho + su sudanese + sv swedish swe + sw swahili swa + ta tamil + te telugu + tg tajik + th thai tha + ti tigrinya + tk turkmen + tl tagalog + tn setswana + to tonga + tr turkish tur iso8859-9 + ts tsonga + tt tatar tat + tw chinese-traditional cht + uk ukrainian ukr iso8859-5 + ur urdu + uz uzbek uzb + vi vietnamese + vo volapuk + wo wolof + xh xhosa + yo yoruba + zh chinese-simplified zho|chi|chs + zu zulu + +:territory: + + al albania + an netherlands-antilles nl + ar argentina es + at austria de + au australia en + az azerbaijan + be belgium nl|fr|de + bg bulgaria bg + bn brunei-darussalam ar + bo bolivia es + br brazil pt + bw botswana en + by belarus ru + bz belize en + ca canada en|fr + ch switzerland fr|de|it + cl chile es + cn china zh:primary + co colombia es + cr costa-rica es + cz czech-republic cs + de germany de + dk denmark da|en + do dominican-republic es + dz algeria + ec ecuador es + ee estonia et + eg egypt ar + es spain es|ca|eu|gl + fi finland sv + fo faroe-islands fo + fr france fr + gb united-kingdom|great-britain|england en:primary + gl greenland kl + gr greece el + gt guatemala es + hk hong-kong zh + hn honduras es + hr croatia hr + hu hungary hu + id indonesia id + ie ireland en|ga + il israel he + iq iraq ar + is iceland is + it italy it + jm jamaica en + jo jordan ar + jp japan ja + ke kenya + kr south-korea ko + kw kuwait ar + lb lebanon ar + li liechtenstein de|fr + lt lithuania lt + lu luxembourg de|fr + lv latvia lv + ly libya ar + ma morocco ar + mk macedonia mk + mo macau zh + mx mexico es + my malaysia + ni nicaragua es + nl netherlands nl + no norway nb|no|nn + nz new-zealand en + om oman ar + pa panama es + pe peru es + pl poland pl + pr puerto-rico es + pt portugal pt + py paraguay es + ro romania ro + ru russia ru + sa saudi-arabia ar + se sweden sv:primary + sg singapore zh + si slovenia sl + sk slovakia sk + sp serbia sr + sv el-salvador es + sy syria ar + th thailand th + tn tunisia ar + tr turkey tr + tt trinidad&tobago en + tw taiwan tw + ua ukraine uk|ru + uk united-kingdom en:primary + us united-states|usa en + uy uruguay es + ve venezuela es + yu yugoslavia sr + za south-africa af + zw zimbabwe en + +:map: + + enu en us + enz en nz + esm es mx + esn es es - modern + esp es es - traditional + usa en us diff --git a/src/lib/libast/port/lcgen.c b/src/lib/libast/port/lcgen.c new file mode 100644 index 0000000..82eb88d --- /dev/null +++ b/src/lib/libast/port/lcgen.c @@ -0,0 +1,791 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +/* + * generate <lc.h> implementation tables from lc.tab + * this must make it through vanilla cc with no -last + * + * # comment + * :charset: + * code name ms-codepage + * :language: + * code name alt1|alt2... charset|... attr1|attr2|... + * ... + * :territory: + * code name lang1|lang2... + * :abbreviation: + */ + +#include <stdio.h> +#include <ctype.h> +#ifdef __STDC__ +#include <stdlib.h> +#include <string.h> +#endif + +typedef struct Link_s +{ + struct Link_s* next; + char* code; + int index; +} Link_t; + +typedef struct Table_s +{ + Link_t* root; + int count; +} Table_t; + +typedef struct Abbreviation_s +{ + Link_t link; + char* value; +} Abbreviation_t; + +typedef struct Attribute_s +{ + Link_t link; +} Attribute_t; + +typedef struct Attribute_list_s +{ + struct Attribute_list_s*next; + Attribute_t* attribute; +} Attribute_list_t; + +typedef struct Charset_s +{ + Link_t link; + char* alternates; + char* ms; +} Charset_t; + +typedef struct Language_s +{ + Link_t link; + char* name; + char* alternates; + Charset_t* charset; + Attribute_list_t* attributes; +} Language_t; + +typedef struct Language_list_s +{ + struct Language_list_s* next; + Language_t* language; +} Language_list_t; + +typedef struct Territory_s +{ + Link_t link; + char* name; + Language_list_t* languages; + int primary; + int index; +} Territory_t; + +typedef struct Map_s +{ + Link_t link; + Language_t* language; + Territory_t* territory; + Charset_t* charset; + Attribute_t* attribute; +} Map_t; + +static struct State_s +{ + Table_t attribute; + Table_t charset; + Table_t language; + Table_t territory; + Table_t map; +} state; + +#define INIT 0 +#define CHARSET 1 +#define LANGUAGE 2 +#define TERRITORY 3 +#define MAP 4 + +#define elementsof(x) (sizeof(x)/sizeof(x[0])) +#define newof(p,t,n,x) ((t*)malloc(sizeof(t)*(n)+(x))) + +static Link_t* +#if defined(__STDC__) || defined(__cplusplus) +enter(register Table_t* tab, register Link_t* v) +#else +enter(tab, v) +register Table_t* tab; +register Link_t* v; +#endif +{ + register Link_t* x; + register Link_t* p; + + for (p = 0, x = tab->root; x; p = x, x = x->next) + if (!strcmp(x->code, v->code)) + return x; + if (p) + p->next = v; + else + tab->root = v; + v->next = 0; + v->index = tab->count++; + return v; +} + +static Link_t* +#if defined(__STDC__) || defined(__cplusplus) +lookup(register Table_t* tab, register char* s) +#else +lookup(tab, s) +register Table_t* tab; +register char* s; +#endif +{ + register Link_t* x; + + for (x = tab->root; x; x = x->next) + if (!strcmp(x->code, s)) + return x; + return 0; +} + +static char* +#if defined(__STDC__) || defined(__cplusplus) +copy(char** p, register char* f) +#else +copy(p, f) +char** p; +register char* f; +#endif +{ + register char* t; + char* b; + + if (!f) + return 0; + b = t = *p; + while (*t++ = *f++); + *p = t; + return b; +} + +static void +#if defined(__STDC__) || defined(__cplusplus) +macro(FILE* f, char* p1, char* p2, char* p3) +#else +macro(f, p1, p2, p3) +FILE* f; +char* p1; +char* p2; +char* p3; +#endif +{ + register int c; + register char* s; + register char* b; + register char* e; + int i; + int m; + int n; + char* part[4]; + char buf[128]; + + part[0] = p1; + part[1] = p2; + part[2] = p3; + part[3] = 0; + n = 0; + fprintf(f, "\n"); + do + { + i = m = 0; + b = buf; + e = &buf[sizeof(buf)-1]; + while (b < e) + { + if (!(s = part[i++])) + break; + if (i > 1) + *b++ = '_'; + while ((c = *s++) && b < e) + { + if (c == '|') + { + part[i-1] = s; + m = 1; + break; + } + else if (islower(c)) + c = toupper(c); + else if (!isalnum(c)) + c = '_'; + *b++ = c; + } + } + *b = 0; + fprintf(f, "#ifdef %s\n%s,\n#else\n", buf, buf); + n++; + } while (m); + fprintf(f, "0,\n"); + while (n-- > 0) + fprintf(f, "#endif\n"); +} + +#if defined(__STDC__) || defined(__cplusplus) +int +main(int argc, char** argv) +#else +int +main(argc, argv) +int argc; +char** argv; +#endif +{ + register char* s; + register char** vp; + register char** ve; + Attribute_t* ap; + Attribute_list_t* al; + Attribute_list_t* az; + Charset_t* cp; + Territory_t* tp; + Language_t* lp; + Language_list_t* ll; + Language_list_t* lz; + Map_t* mp; + char* b; + char* f; + char* command; + char* hdr; + char* lib; + FILE* hf; + FILE* lf; + int c; + int i; + int line; + int type; + int language_attribute_max; + int territory_language_max; + char* arg[5]; + char buf[1024]; + + command = *argv++; + line = 0; + if (!(hdr = *argv++) || !(lib = *argv++) || *argv) + { + fprintf(stderr, "%s: { hdr lib tab } arguments expected\n", command); + return 1; + } + if (!(hf = fopen(hdr, "w"))) + { + fprintf(stderr, "%s: %s: cannot write\n", command, hdr); + return 1; + } + if (!(lf = fopen(lib, "w"))) + { + fprintf(stderr, "%s: %s: cannot write\n", command, lib); + return 1; + } + type = 0; + language_attribute_max = 0; + territory_language_max = 0; + state.language.count = 2; + state.territory.count = 3; + ve = &arg[elementsof(arg)]; + fprintf(hf, "/* : : generated by %s : : */\n", command); + fprintf(hf, "#pragma prototyped\n"); + fprintf(hf, "\n"); + fprintf(hf, "#ifndef _LC_H\n"); + fprintf(hf, "#define _LC_H\t\t\t1\n"); + fprintf(hf, "\n"); + fprintf(hf, "#include <ast.h>\n"); + fprintf(hf, "\n"); + fprintf(hf, "#define LC_abbreviated\t\t0x00001\n"); + fprintf(hf, "#define LC_checked\t\t0x00002\n"); + fprintf(hf, "#define LC_debug\t\t0x00004\n"); + fprintf(hf, "#define LC_default\t\t0x00008\n"); + fprintf(hf, "#define LC_defined\t\t0x00010\n"); + fprintf(hf, "#define LC_local\t\t0x00020\n"); + fprintf(hf, "#define LC_primary\t\t0x00040\n"); + fprintf(hf, "#define LC_qualified\t\t0x00080\n"); + fprintf(hf, "#define LC_undefined\t\t0x00100\n"); + fprintf(hf, "#define LC_utf8\t\t\t0x00200\n"); + fprintf(hf, "#define LC_verbose\t\t0x00400\n"); + fprintf(hf, "#define LC_setlocale\t\t0x10000\n"); + fprintf(hf, "#define LC_setenv\t\t0x20000\n"); + fprintf(hf, "#define LC_user\t\t\t0x40000\n"); + fprintf(lf, "/* : : generated by %s : : */\n", command); + fprintf(lf, "\n"); + fprintf(lf, "#include \"lclib.h\"\n"); + fprintf(lf, "#include \"lclang.h\"\n"); + fprintf(lf, "\n"); + while (s = fgets(buf, sizeof(buf), stdin)) + { + line++; + while (isspace(*s)) + s++; + if (!*s || *s == '#') + continue; + b = s; + vp = arg; + for (;;) + { + for (*vp++ = s; *s && !isspace(*s); s++); + if (!*s) + break; + for (*s++ = 0; isspace(*s); s++); + if (!strcmp(*(vp - 1), "-")) + *(vp - 1) = 0; + if (!*s || vp >= ve) + break; + } + while (vp < ve) + *vp++ = 0; + if (*arg[0] == ':') + { + if (!strcmp(arg[0], ":map:")) + { + if (type != TERRITORY) + { + fprintf(stderr, "%s: %d: %s: must be specified after :territory:\n", command, line, arg[0]); + return 1; + } + type = MAP; + continue; + } + else if (!strcmp(arg[0], ":charset:")) + { + if (type != INIT) + { + fprintf(stderr, "%s: %d: %s must be specified first\n", command, line, arg[0]); + return 1; + } + type = CHARSET; + continue; + } + else if (!strcmp(arg[0], ":territory:")) + { + if (type != LANGUAGE) + { + fprintf(stderr, "%s: %d: %s: must be specified after :language:\n", command, line, arg[0]); + return 1; + } + type = TERRITORY; + continue; + } + else if (!strcmp(arg[0], ":language:")) + { + if (type != CHARSET) + { + fprintf(stderr, "%s: %d: %s must be specified after :charset:\n", command, line, arg[0]); + return 1; + } + type = LANGUAGE; + continue; + } + else + { + fprintf(stderr, "%s: %d: %s invalid\n", command, line, arg[0]); + return 1; + } + } + if (!arg[1]) + { + fprintf(stderr, "%s: %d: at least two arguments expected\n", command, line); + return 1; + } + switch (type) + { + case CHARSET: + if (!(cp = newof(0, Charset_t, 1, s - b + 1))) + { + fprintf(stderr, "%s: %d: out of space\n", command, line); + return 1; + } + b = (char*)(cp + 1); + cp->link.code = copy(&b, arg[0]); + cp->alternates = copy(&b, arg[1]); + cp->ms = copy(&b, arg[2]); + if (cp != (Charset_t*)enter(&state.charset, (Link_t*)cp)) + { + fprintf(stderr, "%s: %d: %s: duplicate charset\n", command, line, cp->link.code); + return 1; + } + break; + case TERRITORY: + if (!(tp = newof(0, Territory_t, 1, s - b + 1))) + { + fprintf(stderr, "%s: %d: out of space\n", command, line); + return 1; + } + b = (char*)(tp + 1); + tp->link.code = copy(&b, arg[0]); + tp->name = copy(&b, arg[1]); + tp->languages = 0; + if (s = copy(&b, arg[2])) + { + i = 0; + while (*(b = s)) + { + for (; *s && *s != ':' && *s != '|'; s++); + if (c = *s) + *s++ = 0; + if (!(lp = (Language_t*)lookup(&state.language, b))) + { + fprintf(stderr, "%s: %d: %s: unknown language\n", command, line, b); + return 1; + } + if (!(ll = newof(0, Language_list_t, 1, 0))) + { + fprintf(stderr, "%s: %d: out of space\n", command, line); + return 1; + } + if (!tp->languages) + tp->languages = ll; + else + lz->next = ll; + lz = ll; + ll->language = lp; + ll->next = 0; + i++; + if (c == ':') + { + for (b = s; *s && *s != '|'; s++); + if (*s) + *s++ = 0; + if (!strcmp(b, "primary")) + tp->primary = 1; + } + } + if (territory_language_max < i) + territory_language_max = i; + } + if (tp != (Territory_t*)enter(&state.territory, (Link_t*)tp)) + { + fprintf(stderr, "%s: %d: %s: duplicate territory\n", command, line, tp->link.code); + return 1; + } + break; + case LANGUAGE: + if (!(lp = newof(0, Language_t, 1, s - b + 1))) + { + fprintf(stderr, "%s: %d: out of space\n", command, line); + return 1; + } + b = (char*)(lp + 1); + lp->link.code = copy(&b, arg[0]); + lp->name = copy(&b, arg[1]); + lp->alternates = copy(&b, arg[2]); + if (!arg[3]) + lp->charset = 0; + else if (!(lp->charset = (Charset_t*)lookup(&state.charset, arg[3]))) + { + fprintf(stderr, "%s: %d: %s: unknown charset\n", command, line, arg[3]); + return 1; + } + lp->attributes = 0; + if (s = copy(&b, arg[4])) + { + i = 0; + fprintf(lf, "\nconst Lc_attribute_t attribute_%s[] =\n{\n", lp->link.code); + while (*(b = s)) + { + for (f = 0; *s && *s != '|'; s++) + if (*s == ':') + { + *s++ = 0; + f = s; + } + if (*s) + *s++ = 0; + fprintf(lf, "{\"%s\",", b); + if (f) + fprintf(lf, "LC_%s,", f); + else + fprintf(lf, "0,"); + if (!(ap = newof(0, Attribute_t, 1, 0))) + { + fprintf(stderr, "%s: %d: out of space\n", command, line); + return 1; + } + ap->link.code = b; + ap->link.index = i++; + if (!(al = newof(0, Attribute_list_t, 1, 0))) + { + fprintf(stderr, "%s: %d: out of space\n", command, line); + return 1; + } + if (!lp->attributes) + lp->attributes = al; + else + az->next = al; + az = al; + al->attribute = ap; + al->next = 0; + macro(lf, "SUBLANG", lp->name, b); + fprintf(lf, "\n},\n"); + } + if (language_attribute_max < i) + language_attribute_max = i; + fprintf(lf, "};\n"); + } + if (lp != (Language_t*)enter(&state.language, (Link_t*)lp)) + { + fprintf(stderr, "%s: %d: %s: duplicate language\n", command, line, lp->link.code); + return 1; + } + break; + case MAP: + if (!(mp = newof(0, Map_t, 1, s - b + 1))) + { + fprintf(stderr, "%s: %d: out of space\n", command, line); + return 1; + } + b = (char*)(mp + 1); + mp->link.code = copy(&b, arg[0]); + if (!arg[2]) + { + fprintf(stderr, "%s: %d: territory code expected\n", command, line); + return 1; + } + if (!(mp->language = (Language_t*)lookup(&state.language, arg[1]))) + { + fprintf(stderr, "%s: %d: %s: unknown language\n", command, line, arg[1]); + return 1; + } + if (!(mp->territory = (Territory_t*)lookup(&state.territory, arg[2]))) + { + fprintf(stderr, "%s: %d: %s: unknown territory\n", command, line, arg[2]); + return 1; + } + if (!arg[3]) + mp->charset = 0; + else if (!(mp->charset = (Charset_t*)lookup(&state.charset, arg[3]))) + { + fprintf(stderr, "%s: %d: %s: unknown charset\n", command, line, arg[3]); + return 1; + } + mp->attribute = 0; + if (arg[4]) + { + for (al = mp->language->attributes; al; al = al->next) + if (!strcmp(al->attribute->link.code, arg[4])) + { + mp->attribute = al->attribute; + break; + } + if (!mp->attribute) + { + fprintf(stderr, "%s: %d: %s: unknown attribute\n", command, line, arg[4]); + return 1; + } + } + if (mp != (Map_t*)enter(&state.map, (Link_t*)mp)) + { + fprintf(stderr, "%s: %d: %s: duplicate map\n", command, line, mp->link.code); + return 1; + } + break; + } + } + if (!language_attribute_max) + language_attribute_max = 1; + if (!territory_language_max) + territory_language_max = 1; + fprintf(hf, "\n#define LC_language_attribute_max\t%d\n", language_attribute_max); + fprintf(hf, "#define LC_territory_language_max\t%d\n", territory_language_max); + fprintf(hf, "\nstruct Lc_s;\n"); + fprintf(hf, "\ntypedef struct Lc_info_s\n{\n"); + fprintf(hf, "\tconst struct Lc_s*\tlc;\n"); + fprintf(hf, "\tunsigned long\t\tnumber;\n"); + fprintf(hf, "\tvoid*\t\t\tdata;\n"); + fprintf(hf, "} Lc_info_t;\n"); + fprintf(hf, "\ntypedef struct Lc_attribute_s\n{\n"); + fprintf(hf, "\tconst char*\t\tname;\n"); + fprintf(hf, "\tunsigned long\t\tflags;\n"); + fprintf(hf, "\tunsigned long\t\tindex;\n"); + fprintf(hf, "} Lc_attribute_t;\n"); + fprintf(hf, "\ntypedef struct Lc_charset_s\n{\n"); + fprintf(hf, "\tconst char*\t\tcode;\n"); + fprintf(hf, "\tconst char*\t\talternates;\n"); + fprintf(hf, "\tconst char*\t\tms;\n"); + fprintf(hf, "\tunsigned long\t\tindex;\n"); + fprintf(hf, "} Lc_charset_t;\n"); + fprintf(hf, "\ntypedef struct Lc_language_s\n{\n"); + fprintf(hf, "\tconst char*\t\tcode;\n"); + fprintf(hf, "\tconst char*\t\tname;\n"); + fprintf(hf, "\tconst char*\t\talternates;\n"); + fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n"); + fprintf(hf, "\tunsigned long\t\tflags;\n"); + fprintf(hf, "\tunsigned long\t\tindex;\n"); + fprintf(hf, "\tconst Lc_attribute_t*\tattributes[LC_language_attribute_max];\n"); + fprintf(hf, "} Lc_language_t;\n"); + fprintf(hf, "\ntypedef struct Lc_territory_s\n{\n"); + fprintf(hf, "\tconst char*\t\tcode;\n"); + fprintf(hf, "\tconst char*\t\tname;\n"); + fprintf(hf, "\tunsigned long\t\tflags;\n"); + fprintf(hf, "\tunsigned long\t\tindex;\n"); + fprintf(hf, "\tconst Lc_language_t*\tlanguages[LC_territory_language_max];\n"); + fprintf(hf, "#ifdef _LC_TERRITORY_PRIVATE_\n"); + fprintf(hf, "\t_LC_TERRITORY_PRIVATE_\n"); + fprintf(hf, "#endif\n"); + fprintf(hf, "} Lc_territory_t;\n"); + fprintf(hf, "\ntypedef struct Lc_map_s\n{\n"); + fprintf(hf, "\tconst char*\t\tcode;\n"); + fprintf(hf, "\tconst Lc_language_t*\tlanguage;\n"); + fprintf(hf, "\tconst Lc_territory_t*\tterritory;\n"); + fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n"); + fprintf(hf, "\tconst Lc_attribute_t*\tattribute;\n"); + fprintf(hf, "} Lc_map_t;\n"); + fprintf(hf, "\ntypedef struct Lc_attribute_list_s\n{\n"); + fprintf(hf, "\tstruct Lc_attribute_list_s*\tnext;\n"); + fprintf(hf, "\tconst Lc_attribute_t*\t\tattribute;\n"); + fprintf(hf, "} Lc_attribute_list_t;\n"); + fprintf(hf, "\ntypedef struct Lc_s\n{\n"); + fprintf(hf, "\tconst char*\t\tname;\n"); + fprintf(hf, "\tconst char*\t\tcode;\n"); + fprintf(hf, "\tconst Lc_language_t*\tlanguage;\n"); + fprintf(hf, "\tconst Lc_territory_t*\tterritory;\n"); + fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n"); + fprintf(hf, "\tconst Lc_attribute_list_t*\tattributes;\n"); + fprintf(hf, "\tunsigned long\t\tflags;\n"); + fprintf(hf, "\tunsigned long\t\tindex;\n"); + fprintf(hf, "#ifdef _LC_PRIVATE_\n"); + fprintf(hf, "\t_LC_PRIVATE_\n"); + fprintf(hf, "#endif\n"); + fprintf(hf, "} Lc_t;\n"); + fprintf(hf, "\nstruct Lc_category_s;\n"); + fprintf(hf, "\ntypedef int (*Lc_category_set_f)(struct Lc_category_s*);\n"); + fprintf(hf, "\ntypedef struct Lc_category_s\n{\n"); + fprintf(hf, "\tconst char*\t\tname;\n"); + fprintf(hf, "\tint\t\t\texternal;\n"); + fprintf(hf, "\tint\t\t\tinternal;\n"); + fprintf(hf, "\tLc_category_set_f\tsetf;\n"); + fprintf(hf, "\tLc_t*\t\t\tprev;\n"); + fprintf(hf, "\tunsigned int\t\tflags;\n"); + fprintf(hf, "} Lc_category_t;\n"); + fprintf(hf, "\n"); + fprintf(hf, "#if _BLD_ast && defined(__EXPORT__)\n"); + fprintf(hf, "#define extern\t\t__EXPORT__\n"); + fprintf(hf, "#endif\n"); + fprintf(hf, "\n"); + fprintf(hf, "extern size_t\t\tlccanon(Lc_t*, unsigned long flags, char*, size_t);\n"); + fprintf(hf, "extern Lc_category_t*\tlccategories(void);\n"); + fprintf(hf, "extern int\t\tlcindex(int, int);\n"); + fprintf(hf, "extern Lc_info_t*\tlcinfo(int);\n"); + fprintf(hf, "extern Lc_t*\t\tlcmake(const char*);\n"); + fprintf(hf, "extern Lc_t*\t\tlcscan(Lc_t*);\n"); + fprintf(hf, "\n"); + fprintf(hf, "#undef\textern\n"); + fprintf(lf, "\nconst Lc_charset_t lc_charsets[] =\n{\n"); + for (cp = (Charset_t*)state.charset.root; cp; cp = (Charset_t*)cp->link.next) + { + fprintf(lf, "{\"%s\",", cp->link.code); + if (cp->alternates) + fprintf(lf, "\"%s\",", cp->alternates); + else + fprintf(lf, "0,"); + if (cp->ms) + fprintf(lf, "\"%s\",", cp->ms); + else + fprintf(lf, "0"); + fprintf(lf, "},\n"); + } + fprintf(lf, "\t0\n};\n"); + fprintf(lf, "\nconst Lc_language_t lc_languages[] =\n{\n"); + fprintf(lf, "{\"C\",\"C\",\"POSIX\",&lc_charsets[0],LC_default,0,"); + for (i = 0; i < language_attribute_max; i++) + fprintf(lf, "0,"); + fprintf(lf, "},\n"); + fprintf(lf, "{\"debug\",\"debug\",0,&lc_charsets[0],LC_debug,0,"); + for (i = 0; i < language_attribute_max; i++) + fprintf(lf, "0,"); + fprintf(lf, "},\n"); + for (lp = (Language_t*)state.language.root; lp; lp = (Language_t*)lp->link.next) + { + fprintf(lf, "{\"%s\",\"%s\",", lp->link.code, lp->name); + if (lp->alternates) + fprintf(lf, "\"%s\",", lp->alternates); + else + fprintf(lf, "0,"); + fprintf(lf, "&lc_charsets[%d],0,", lp->charset ? lp->charset->link.index : 0); + macro(lf, "LANG", lp->name, (char*)0); + for (i = 0, al = lp->attributes; al; al = al->next, i++) + fprintf(lf, "&attribute_%s[%d],", lp->link.code, al->attribute->link.index); + for (; i < language_attribute_max; i++) + fprintf(lf, "0,"); + fprintf(lf, "\n},\n"); + } + fprintf(lf, "\t0\n};\n"); + fprintf(lf, "\nconst Lc_territory_t lc_territories[] =\n{\n"); + fprintf(lf, "{\"C\",\"C\",LC_default,0,&lc_languages[0],"); + for (i = 1; i < 2 * territory_language_max; i++) + fprintf(lf, "0,"); + fprintf(lf, "},\n"); + fprintf(lf, "{\"debug\",\"debug\",LC_debug,0,&lc_languages[1],"); + for (i = 1; i < 2 * territory_language_max; i++) + fprintf(lf, "0,"); + fprintf(lf, "},\n"); + fprintf(lf, "{\"eu\",\"euro\",0,0,&lc_languages[0],"); + for (i = 1; i < 2 * territory_language_max; i++) + fprintf(lf, "0,"); + fprintf(lf, "},\n"); + for (tp = (Territory_t*)state.territory.root; tp; tp = (Territory_t*)tp->link.next) + { + fprintf(lf, "{\"%s\",\"%s\",", tp->link.code, tp->name); + if (tp->primary) + fprintf(lf, "LC_primary,"); + else + fprintf(lf, "0,"); + macro(lf, "CTRY", tp->name, (char*)0); + for (i = 0, ll = tp->languages; ll; ll = ll->next, i++) + fprintf(lf, "&lc_languages[%d],", ll->language->link.index); + for (; i < territory_language_max; i++) + fprintf(lf, "0,"); + for (i = 0, ll = tp->languages; ll; ll = ll->next, i++) + macro(lf, "SUBLANG", ll->language->name, tp->name); + for (; i < territory_language_max; i++) + fprintf(lf, "0,"); + fprintf(lf, "\n},\n"); + } + fprintf(lf, "\t0\n};\n"); + fprintf(lf, "\nconst Lc_map_t lc_maps[] =\n{\n"); + for (mp = (Map_t*)state.map.root; mp; mp = (Map_t*)mp->link.next) + { + fprintf(lf, "{\"%s\",", mp->link.code); + fprintf(lf, "&lc_languages[%d],", mp->language->link.index); + fprintf(lf, "&lc_territories[%d],", mp->territory->link.index); + fprintf(lf, "&lc_charsets[%d],", mp->charset ? mp->charset->link.index : 0); + if (mp->attribute) + fprintf(lf, "&attribute_%s[%d]", mp->language->link.code, mp->attribute->link.index); + else + fprintf(lf, "0"); + fprintf(lf, "},\n"); + } + fprintf(lf, "\t0\n};\n"); + fclose(lf); + fprintf(hf, "\n#endif\n"); + fclose(hf); + return 0; +} diff --git a/src/lib/libast/port/lclang.h b/src/lib/libast/port/lclang.h new file mode 100644 index 0000000..356f2b0 --- /dev/null +++ b/src/lib/libast/port/lclang.h @@ -0,0 +1,120 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +/* + * lc (sub)lang definitions -- very windowsish + */ + +#if _WINIX + +#include <ast_windows.h> + +#ifndef LANG_CHINESE_SIMPLIFIED +#define LANG_CHINESE_SIMPLIFIED LANG_CHINESE +#endif +#ifndef LANG_CHINESE_TRADITIONAL +#define LANG_CHINESE_TRADITIONAL LANG_CHINESE +#endif +#ifndef LANG_NORWEGIAN_BOKMAL +#define LANG_NORWEGIAN_BOKMAL LANG_NORWEGIAN +#endif +#ifndef LANG_NORWEGIAN_NYNORSK +#define LANG_NORWEGIAN_NYNORSK LANG_NORWEGIAN +#endif +#ifndef LANG_SERBO_CROATIAN +#define LANG_SERBO_CROATIAN LANG_CROATIAN +#endif + +#ifndef CTRY_CZECH_REPUBLIC +#define CTRY_CZECH_REPUBLIC CTRY_CZECH +#endif + +#ifndef SUBLANG_CHINESE_SIMPLIFIED_CHINA +#define SUBLANG_CHINESE_SIMPLIFIED_CHINA SUBLANG_CHINESE_SIMPLIFIED +#endif +#ifndef SUBLANG_CHINESE_SIMPLIFIED_HONG_KONG +#define SUBLANG_CHINESE_SIMPLIFIED_HONG_KONG SUBLANG_CHINESE_HONGKONG +#endif +#ifndef SUBLANG_CHINESE_SIMPLIFIED_SINGAPORE +#define SUBLANG_CHINESE_SIMPLIFIED_SINGAPORE SUBLANG_CHINESE_SINGAPORE +#endif +#ifndef SUBLANG_CHINESE_TRADITIONAL_TAIWAN +#define SUBLANG_CHINESE_TRADITIONAL_TAIWAN SUBLANG_CHINESE_TRADITIONAL +#endif +#ifndef SUBLANG_DUTCH_NETHERLANDS_ANTILLES +#define SUBLANG_DUTCH_NETHERLANDS_ANTILLES SUBLANG_DUTCH +#endif +#ifndef SUBLANG_DUTCH_BELGIUM +#define SUBLANG_DUTCH_BELGIUM SUBLANG_DUTCH_BELGIAN +#endif +#ifndef SUBLANG_ENGLISH_AUSTRALIA +#define SUBLANG_ENGLISH_AUSTRALIA SUBLANG_ENGLISH_AUS +#endif +#ifndef SUBLANG_ENGLISH_CANADA +#define SUBLANG_ENGLISH_CANADA SUBLANG_ENGLISH_CAN +#endif +#ifndef SUBLANG_ENGLISH_IRELAND +#define SUBLANG_ENGLISH_IRELAND SUBLANG_ENGLISH_EIRE +#endif +#ifndef SUBLANG_ENGLISH_NEW_ZEALAND +#define SUBLANG_ENGLISH_NEW_ZEALAND SUBLANG_ENGLISH_NZ +#endif +#ifndef SUBLANG_ENGLISH_TRINIDAD_TOBAGO +#define SUBLANG_ENGLISH_TRINIDAD_TOBAGO SUBLANG_ENGLISH_CARIBBEAN +#endif +#ifndef SUBLANG_ENGLISH_UNITED_KINGDOM +#define SUBLANG_ENGLISH_UNITED_KINGDOM SUBLANG_ENGLISH_UK +#endif +#ifndef SUBLANG_ENGLISH_UNITED_STATES +#define SUBLANG_ENGLISH_UNITED_STATES SUBLANG_ENGLISH_US +#endif +#ifndef SUBLANG_FRENCH_BELGIUM +#define SUBLANG_FRENCH_BELGIUM SUBLANG_FRENCH_BELGIAN +#endif +#ifndef SUBLANG_FRENCH_CANADA +#define SUBLANG_FRENCH_CANADA SUBLANG_FRENCH_CANADIAN +#endif +#ifndef SUBLANG_FRENCH_SWITZERLAND +#define SUBLANG_FRENCH_SWITZERLAND SUBLANG_FRENCH_SWISS +#endif +#ifndef SUBLANG_GERMAN_AUSTRIA +#define SUBLANG_GERMAN_AUSTRIA SUBLANG_GERMAN_AUSTRIAN +#endif +#ifndef SUBLANG_GERMAN_SWITZERLAND +#define SUBLANG_GERMAN_SWITZERLAND SUBLANG_GERMAN_SWISS +#endif +#ifndef SUBLANG_ITALIAN_SWITZERLAND +#define SUBLANG_ITALIAN_SWITZERLAND SUBLANG_ITALIAN_SWISS +#endif +#ifndef SUBLANG_NORWEGIAN_BOKMAL_NORWAY +#define SUBLANG_NORWEGIAN_BOKMAL_NORWAY SUBLANG_NORWEGIAN_BOKMAL +#endif +#ifndef SUBLANG_NORWEGIAN_NORWAY +#define SUBLANG_NORWEGIAN_NORWAY SUBLANG_NORWEGIAN_BOKMAL +#endif +#ifndef SUBLANG_NORWEGIAN_NYNORSK_NORWAY +#define SUBLANG_NORWEGIAN_NYNORSK_NORWAY SUBLANG_NORWEGIAN_NYNORSK +#endif +#ifndef SUBLANG_PORTUGUESE_BRAZIL +#define SUBLANG_PORTUGUESE_BRAZIL SUBLANG_PORTUGUESE_BRAZILIAN +#endif + +#endif diff --git a/src/lib/libast/port/lclib.h b/src/lib/libast/port/lclib.h new file mode 100644 index 0000000..5daeb8a --- /dev/null +++ b/src/lib/libast/port/lclib.h @@ -0,0 +1,71 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped + +/* + * locale state private definitions + */ + +#ifndef _LCLIB_H +#define _LCLIB_H 1 + +#define locales _ast_locales +#define translate _ast_translate + +#define lc_categories _ast_lc_categories +#define lc_charsets _ast_lc_charsets +#define lc_languages _ast_lc_languages +#define lc_maps _ast_lc_maps +#define lc_territories _ast_lc_territories + +struct Lc_info_s; + +#define _LC_PRIVATE_ \ + struct Lc_info_s info[AST_LC_COUNT]; \ + struct Lc_s* next; + +#define _LC_TERRITORY_PRIVATE_ \ + unsigned char indices[LC_territory_language_max]; + +#include <ast.h> +#include <error.h> +#include <lc.h> + +typedef struct Lc_numeric_s +{ + int decimal; + int thousand; +} Lc_numeric_t; + +#define LCINFO(c) (&locales[c]->info[c]) + +extern const Lc_charset_t lc_charsets[]; +extern const Lc_language_t lc_languages[]; +extern const Lc_map_t lc_maps[]; +extern const Lc_territory_t lc_territories[]; + +extern Lc_category_t lc_categories[]; +extern Lc_t* locales[]; + +extern char* translate(const char*, const char*, const char*, const char*); + +#endif diff --git a/src/lib/libast/port/mc.c b/src/lib/libast/port/mc.c new file mode 100644 index 0000000..f2ee65c --- /dev/null +++ b/src/lib/libast/port/mc.c @@ -0,0 +1,675 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped + +/* + * Glenn Fowler + * AT&T Research + * + * machine independent binary message catalog implementation + */ + +#include "sfhdr.h" +#include "lclib.h" + +#include <iconv.h> + +#define _MC_PRIVATE_ \ + size_t nstrs; \ + size_t nmsgs; \ + iconv_t cvt; \ + Sfio_t* tmp; \ + Vmalloc_t* vm; + +#include <vmalloc.h> +#include <error.h> +#include <mc.h> +#include <nl_types.h> + +/* + * find the binary message catalog path for <locale,catalog> + * result placed in path of size PATH_MAX + * pointer to path returned + * catalog==0 tests for category directory or file + * nls!=0 enables NLSPATH+LANG hack (not implemented yet) + */ + +char* +mcfind(const char* locale, const char* catalog, int category, int nls, char* path, size_t size) +{ + register int c; + register char* s; + register char* e; + register char* p; + register const char* v; + int i; + int first; + int next; + int last; + int oerrno; + Lc_t* lc; + char file[PATH_MAX]; + char* paths[5]; + + static char lc_messages[] = "LC_MESSAGES"; + + if ((category = lcindex(category, 1)) < 0) + return 0; + if (!(lc = locale ? lcmake(locale) : locales[category])) + return 0; + oerrno = errno; + if (catalog && *catalog == '/') + { + i = eaccess(catalog, R_OK); + errno = oerrno; + if (i) + return 0; + strlcpy(path, catalog, size); + return path; + } + i = 0; + if ((p = getenv("NLSPATH")) && *p) + paths[i++] = p; + paths[i++] = "share/lib/locale/%l/%C/%N"; + paths[i++] = "share/locale/%l/%C/%N"; + paths[i++] = "lib/locale/%l/%C/%N"; + paths[i] = 0; + next = 1; + for (i = 0; p = paths[i]; i += next) + { + first = 1; + last = 0; + e = &file[elementsof(file) - 1]; + while (*p) + { + s = file; + for (;;) + { + switch (c = *p++) + { + case 0: + p--; + break; + case ':': + break; + case '%': + if (s < e) + { + switch (c = *p++) + { + case 0: + p--; + continue; + case 'N': + v = catalog; + break; + case 'L': + if (first) + { + first = 0; + if (next) + { + v = lc->code; + if (lc->code != lc->language->code) + next = 0; + } + else + { + next = 1; + v = lc->language->code; + } + } + break; + case 'l': + v = lc->language->code; + break; + case 't': + v = lc->territory->code; + break; + case 'c': + v = lc->charset->code; + break; + case 'C': + case_C: + if (!catalog) + last = 1; + v = lc_categories[category].name; + break; + default: + *s++ = c; + continue; + } + if (v) + while (*v && s < e) + *s++ = *v++; + } + continue; + case '/': + if (last) + break; + if (category != AST_LC_MESSAGES && strneq(p, lc_messages, sizeof(lc_messages) - 1) && p[sizeof(lc_messages)-1] == '/') + { + p += sizeof(lc_messages) - 1; + goto case_C; + } + /*FALLTHROUGH*/ + default: + if (s < e) + *s++ = c; + continue; + } + break; + } + if (s > file) + *s = 0; + else if (!catalog) + continue; + else + strlcpy(file, catalog, elementsof(file)); + if (ast.locale.set & AST_LC_find) + sfprintf(sfstderr, "locale find %s\n", file); + if (s = pathpath(file, "", (!catalog && category == AST_LC_MESSAGES) ? PATH_READ : (PATH_REGULAR|PATH_READ|PATH_ABSOLUTE), path, size)) + { + if (ast.locale.set & (AST_LC_find|AST_LC_setlocale)) + sfprintf(sfstderr, "locale path %s\n", s); + errno = oerrno; + return s; + } + } + } + errno = oerrno; + return 0; +} + +/* + * allocate and read the binary message catalog ip + * if ip==0 then space is allocated for mcput() + * 0 returned on any error + */ + +Mc_t* +mcopen(register Sfio_t* ip) +{ + register Mc_t* mc; + register char** mp; + register char* sp; + Vmalloc_t* vm; + char* rp; + int i; + int j; + int oerrno; + size_t n; + char buf[MC_MAGIC_SIZE]; + + oerrno = errno; + if (ip) + { + /* + * check the magic + */ + + if (sfread(ip, buf, MC_MAGIC_SIZE) != MC_MAGIC_SIZE) + { + errno = oerrno; + return 0; + } + if (memcmp(buf, MC_MAGIC, MC_MAGIC_SIZE)) + return 0; + } + + /* + * allocate the region + */ + + if (!(vm = vmopen(Vmdcheap, Vmbest, 0)) || !(mc = vmnewof(vm, 0, Mc_t, 1, 0))) + { + errno = oerrno; + return 0; + } + mc->vm = vm; + mc->cvt = (iconv_t)(-1); + if (ip) + { + /* + * read the translation record + */ + + if (!(sp = sfgetr(ip, 0, 0)) || !(mc->translation = vmstrdup(vm, sp))) + goto bad; + + /* + * read the optional header records + */ + + do + { + if (!(sp = sfgetr(ip, 0, 0))) + goto bad; + } while (*sp); + + /* + * get the component dimensions + */ + + mc->nstrs = sfgetu(ip); + mc->nmsgs = sfgetu(ip); + mc->num = sfgetu(ip); + if (sfeof(ip)) + goto bad; + } + else if (!(mc->translation = vmnewof(vm, 0, char, 1, 0))) + goto bad; + + /* + * allocate the remaining space + */ + + if (!(mc->set = vmnewof(vm, 0, Mcset_t, mc->num + 1, 0))) + goto bad; + if (!ip) + return mc; + if (!(mp = vmnewof(vm, 0, char*, mc->nmsgs + mc->num + 1, 0))) + goto bad; + if (!(rp = sp = vmalloc(vm, mc->nstrs + 1))) + goto bad; + + /* + * get the set dimensions and initialize the msg pointers + */ + + while (i = sfgetu(ip)) + { + if (i > mc->num) + goto bad; + n = sfgetu(ip); + mc->set[i].num = n; + mc->set[i].msg = mp; + mp += n + 1; + } + + /* + * read the msg sizes and set up the msg pointers + */ + + for (i = 1; i <= mc->num; i++) + for (j = 1; j <= mc->set[i].num; j++) + if (n = sfgetu(ip)) + { + mc->set[i].msg[j] = sp; + sp += n; + } + + /* + * read the string table + */ + + if (sfread(ip, rp, mc->nstrs) != mc->nstrs || sfgetc(ip) != EOF) + goto bad; + if (!(mc->tmp = sfstropen())) + goto bad; + mc->cvt = iconv_open("", "utf"); + errno = oerrno; + return mc; + bad: + vmclose(vm); + errno = oerrno; + return 0; +} + +/* + * return the <set,num> message in mc + * msg returned on error + * utf message text converted to ucs + */ + +char* +mcget(register Mc_t* mc, int set, int num, const char* msg) +{ + char* s; + size_t n; + int p; + + if (!mc || set < 0 || set > mc->num || num < 1 || num > mc->set[set].num || !(s = mc->set[set].msg[num])) + return (char*)msg; + if (mc->cvt == (iconv_t)(-1)) + return s; + if ((p = sfstrtell(mc->tmp)) > sfstrsize(mc->tmp) / 2) + { + p = 0; + sfstrseek(mc->tmp, p, SEEK_SET); + } + n = strlen(s) + 1; + iconv_write(mc->cvt, mc->tmp, &s, &n, NiL); + return sfstrbase(mc->tmp) + p; +} + +/* + * set message <set,num> to msg + * msg==0 deletes the message + * the message and set counts are adjusted + * 0 returned on success, -1 otherwise + */ + +int +mcput(register Mc_t* mc, int set, int num, const char* msg) +{ + register int i; + register char* s; + register Mcset_t* sp; + register char** mp; + + /* + * validate the arguments + */ + + if (!mc || set > MC_SET_MAX || num > MC_NUM_MAX) + return -1; + + /* + * deletions don't kick in allocations (duh) + */ + + if (!msg) + { + if (set <= mc->num && num <= mc->set[set].num && (s = mc->set[set].msg[num])) + { + /* + * decrease the string table size + */ + + mc->set[set].msg[num] = 0; + mc->nstrs -= strlen(s) + 1; + if (mc->set[set].num == num) + { + /* + * decrease the max msg num + */ + + mp = mc->set[set].msg + num; + while (num && !mp[--num]); + mc->nmsgs -= mc->set[set].num - num; + if (!(mc->set[set].num = num) && mc->num == set) + { + /* + * decrease the max set num + */ + + while (num && !mc->set[--num].num); + mc->num = num; + } + } + } + return 0; + } + + /* + * keep track of the highest set and allocate if necessary + */ + + if (set > mc->num) + { + if (set > mc->gen) + { + i = MC_SET_MAX; + if (!(sp = vmnewof(mc->vm, 0, Mcset_t, i + 1, 0))) + return -1; + mc->gen = i; + for (i = 1; i <= mc->num; i++) + sp[i] = mc->set[i]; + mc->set = sp; + } + mc->num = set; + } + sp = mc->set + set; + + /* + * keep track of the highest msg and allocate if necessary + */ + + if (num > sp->num) + { + if (num > sp->gen) + { + if (!mc->gen) + { + i = (MC_NUM_MAX + 1) / 32; + if (i <= num) + i = 2 * num; + if (i > MC_NUM_MAX) + i = MC_NUM_MAX; + if (!(mp = vmnewof(mc->vm, 0, char*, i + 1, 0))) + return -1; + mc->gen = i; + sp->msg = mp; + for (i = 1; i <= sp->num; i++) + mp[i] = sp->msg[i]; + } + else + { + i = 2 * mc->gen; + if (i > MC_NUM_MAX) + i = MC_NUM_MAX; + if (!(mp = vmnewof(mc->vm, sp->msg, char*, i + 1, 0))) + return -1; + sp->gen = i; + sp->msg = mp; + } + } + mc->nmsgs += num - sp->num; + sp->num = num; + } + + /* + * decrease the string table size + */ + + if (s = sp->msg[num]) + { + /* + * no-op if no change + */ + + if (streq(s, msg)) + return 0; + mc->nstrs -= strlen(s) + 1; + } + + /* + * allocate, add and adjust the string table size + */ + + if (!(s = vmstrdup(mc->vm, msg))) + return -1; + sp->msg[num] = s; + mc->nstrs += strlen(s) + 1; + return 0; +} + +/* + * dump message catalog mc to op + * 0 returned on success, -1 otherwise + */ + +int +mcdump(register Mc_t* mc, register Sfio_t* op) +{ + register int i; + register int j; + register int n; + register char* s; + register Mcset_t* sp; + + /* + * write the magic + */ + + if (sfwrite(op, MC_MAGIC, MC_MAGIC_SIZE) != MC_MAGIC_SIZE) + return -1; + + /* + * write the translation record + */ + + sfputr(op, mc->translation, 0); + + /* optional header records here */ + + /* + * end of optional header records + */ + + sfputu(op, 0); + + /* + * write the global dimensions + */ + + sfputu(op, mc->nstrs); + sfputu(op, mc->nmsgs); + sfputu(op, mc->num); + + /* + * write the set dimensions + */ + + for (i = 1; i <= mc->num; i++) + if (mc->set[i].num) + { + sfputu(op, i); + sfputu(op, mc->set[i].num); + } + sfputu(op, 0); + + /* + * write the message sizes + */ + + for (i = 1; i <= mc->num; i++) + if (mc->set[i].num) + { + sp = mc->set + i; + for (j = 1; j <= sp->num; j++) + { + n = (s = sp->msg[j]) ? (strlen(s) + 1) : 0; + sfputu(op, n); + } + } + + /* + * write the string table + */ + + for (i = 1; i <= mc->num; i++) + if (mc->set[i].num) + { + sp = mc->set + i; + for (j = 1; j <= sp->num; j++) + if (s = sp->msg[j]) + sfputr(op, s, 0); + } + + /* + * sync and return + */ + + return sfsync(op); +} + +/* + * parse <set,msg> number from s + * e!=0 is set to the next char after the parse + * set!=0 is set to message set number + * msg!=0 is set to message number + * the message set number is returned + * + * the base 36 hash gives reasonable values for these: + * + * "ast" : ((((36#a^36#s^36#t)-9)&63)+1) = 3 + * "gnu" : ((((36#g^36#n^36#u)-9)&63)+1) = 17 + * "sgi" : ((((36#s^36#g^36#i)-9)&63)+1) = 22 + * "sun" : ((((36#s^36#u^36#n)-9)&63)+1) = 13 + */ + +int +mcindex(register const char* s, char** e, int* set, int* msg) +{ + register int c; + register int m; + register int n; + register int r; + register unsigned char* cv; + char* t; + + m = 0; + n = strtol(s, &t, 0); + if (t == (char*)s) + { + SFCVINIT(); + cv = _Sfcv36; + for (n = m = 0; (c = cv[*s]) < 36; s++) + { + m++; + n ^= c; + } + m = (m <= 3) ? 63 : ((1 << (m + 3)) - 1); + n = ((n - 9) & m) + 1; + } + else + s = (const char*)t; + r = n; + if (*s) + m = strtol(s + 1, e, 0); + else + { + if (e) + *e = (char*)s; + if (m) + m = 0; + else + { + m = n; + n = 1; + } + } + if (set) + *set = n; + if (msg) + *msg = m; + return r; +} + +/* + * close the message catalog mc + */ + +int +mcclose(register Mc_t* mc) +{ + if (!mc) + return -1; + if (mc->tmp) + sfclose(mc->tmp); + if (mc->cvt != (iconv_t)(-1)) + iconv_close(mc->cvt); + vmclose(mc->vm); + return 0; +} diff --git a/src/lib/libast/port/mnt.c b/src/lib/libast/port/mnt.c new file mode 100644 index 0000000..f773ae8 --- /dev/null +++ b/src/lib/libast/port/mnt.c @@ -0,0 +1,816 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * Glenn Fowler + * AT&T Research + * + * mounted filesystem scan support + * where are the standards when you really need them + */ + +#include <ast.h> +#include <mnt.h> +#include <ls.h> + +#if _lib_mntopen && _lib_mntread && _lib_mntclose + +NoN(mnt) + +#else + +/* + * the original interface just had mode + */ + +#define FIXARGS(p,m,s) do { \ + if ((p)&&*(p)!='/') { \ + mode = p; \ + path = 0; \ + } \ + if (!path) \ + path = s; \ + } while (0) +typedef struct +{ + Mnt_t mnt; + char buf[128]; +#if __CYGWIN__ + char typ[128]; + char opt[128]; +#endif +} Header_t; + +#if __CYGWIN__ +#include <ast_windows.h> +#endif + +static void +set(register Header_t* hp, const char* fs, const char* dir, const char* type, const char* options) +{ + const char* x; + + hp->mnt.flags = 0; + if (x = (const char*)strchr(fs, ':')) + { + if (*++x && *x != '\\') + { + hp->mnt.flags |= MNT_REMOTE; + if (*x == '(') + { + fs = x; + type = "auto"; + } + } + } + else if (x = (const char*)strchr(fs, '@')) + { + hp->mnt.flags |= MNT_REMOTE; + sfsprintf(hp->buf, sizeof(hp->buf) - 1, "%s:%*.*s", x + 1, x - fs, x - fs, fs); + fs = (const char*)hp->buf; + } + else if (strmatch(type, "[aAnN][fF][sS]*")) + hp->mnt.flags |= MNT_REMOTE; + if (streq(fs, "none")) + fs = dir; + hp->mnt.fs = (char*)fs; + hp->mnt.dir = (char*)dir; + hp->mnt.type = (char*)type; + hp->mnt.options = (char*)options; +#if __CYGWIN__ + if (streq(type, "system") || streq(type, "user")) + { + char* s; + int mode; + DWORD vser; + DWORD flags; + DWORD len; + char drive[4]; + + mode = SetErrorMode(SEM_FAILCRITICALERRORS); + drive[0] = fs[0]; + drive[1] = ':'; + drive[2] = '\\'; + drive[3] = 0; + if (GetVolumeInformation(drive, 0, 0, &vser, &len, &flags, hp->typ, sizeof(hp->typ) - 1)) + hp->mnt.type = hp->typ; + else + flags = 0; + SetErrorMode(mode); + s = strcopy(hp->mnt.options = hp->opt, type); + s = strcopy(s, ",ignorecase"); + if (options) + { + *s++ = ','; + strcpy(s, options); + } + } +#endif +} + +#undef MNT_REMOTE + +#if _sys_mount && ( _lib_getfsstat || _lib_getmntinfo ) + +/* + * 4.4 bsd getmntinfo + * + * what a crappy interface + * data returned in static buffer -- ok + * big chunk of allocated memory that cannot be freed -- come on + * *and* netbsd changed the interface somewhere along the line + * private interface? my bad -- public interface? par for the bsd course + * + * we assume getfsstat may suffer the same statfs/statvfs confusion + */ + +#include <sys/param.h> /* expect some macro redefinitions here */ +#include <sys/mount.h> + +#if _lib_getfsstat +#if _lib_getfsstat_statvfs +#define statfs statvfs +#define f_flags f_flag +#endif +#else +#if _lib_getmntinfo_statvfs +#define statfs statvfs +#define f_flags f_flag +#endif +#endif + +typedef struct +{ + Header_t hdr; + struct statfs* next; + struct statfs* last; + char opt[256]; +#if _lib_getfsstat + struct statfs buf[1]; +#endif +} Handle_t; + +#ifdef MFSNAMELEN +#define TYPE(f) ((f)->f_fstypename) +#else +#ifdef INITMOUNTNAMES +#define TYPE(f) ((char*)type[(f)->f_type]) +static const char* type[] = INITMOUNTNAMES; +#else +#if _sys_fs_types +#define TYPE(f) ((char*)mnt_names[(f)->f_type]) +#include <sys/fs_types.h> +#else +#define TYPE(f) (strchr((f)->f_mntfromname,':')?"nfs":"ufs") +#endif +#endif +#endif + +static struct Mnt_options_t +{ + unsigned long flag; + const char* name; +} +options[] = +{ +#ifdef MNT_RDONLY + MNT_RDONLY, "rdonly", +#endif +#ifdef MNT_SYNCHRONOUS + MNT_SYNCHRONOUS,"synchronous", +#endif +#ifdef MNT_NOEXEC + MNT_NOEXEC, "noexec", +#endif +#ifdef MNT_NOSUID + MNT_NOSUID, "nosuid", +#endif +#ifdef MNT_NODEV + MNT_NODEV, "nodev", +#endif +#ifdef MNT_UNION + MNT_UNION, "union", +#endif +#ifdef MNT_ASYNC + MNT_ASYNC, "async", +#endif +#ifdef MNT_NOCOREDUMP + MNT_NOCOREDUMP, "nocoredump", +#endif +#ifdef MNT_NOATIME + MNT_NOATIME, "noatime", +#endif +#ifdef MNT_SYMPERM + MNT_SYMPERM, "symperm", +#endif +#ifdef MNT_NODEVMTIME + MNT_NODEVMTIME, "nodevmtime", +#endif +#ifdef MNT_SOFTDEP + MNT_SOFTDEP, "softdep", +#endif +#ifdef MNT_EXRDONLY + MNT_EXRDONLY, "exrdonly", +#endif +#ifdef MNT_EXPORTED + MNT_EXPORTED, "exported", +#endif +#ifdef MNT_DEFEXPORTED + MNT_DEFEXPORTED,"defexported", +#endif +#ifdef MNT_EXPORTANON + MNT_EXPORTANON, "exportanon", +#endif +#ifdef MNT_EXKERB + MNT_EXKERB, "exkerb", +#endif +#ifdef MNT_EXNORESPORT + MNT_EXNORESPORT,"exnoresport", +#endif +#ifdef MNT_EXPUBLIC + MNT_EXPUBLIC, "expublic", +#endif +#ifdef MNT_LOCAL + MNT_LOCAL, "local", +#endif +#ifdef MNT_QUOTA + MNT_QUOTA, "quota", +#endif +#ifdef MNT_ROOTFS + MNT_ROOTFS, "rootfs", +#endif + 0, "unknown", +}; + +void* +mntopen(const char* path, const char* mode) +{ + register Handle_t* mp; + register int n; + + FIXARGS(path, mode, 0); +#if _lib_getfsstat + if ((n = getfsstat(NiL, 0, MNT_WAIT)) <= 0) + return 0; + n = (n - 1) * sizeof(struct statfs); +#else + n = 0; +#endif + if (!(mp = newof(0, Handle_t, 1, n))) + return 0; +#if _lib_getfsstat + n = getfsstat(mp->next = mp->buf, n + sizeof(struct statfs), MNT_WAIT); +#else + n = getmntinfo(&mp->next, 0); +#endif + if (n <= 0) + { + free(mp); + return 0; + } + mp->last = mp->next + n; + return (void*)mp; +} + +Mnt_t* +mntread(void* handle) +{ + register Handle_t* mp = (Handle_t*)handle; + register int i; + register int n; + register unsigned long flags; + + if (mp->next < mp->last) + { + flags = mp->next->f_flags; + n = 0; + for (i = 0; i < elementsof(options); i++) + if (flags & options[i].flag) + n += sfsprintf(mp->opt + n, sizeof(mp->opt) - n - 1, ",%s", options[i].name); + set(&mp->hdr, mp->next->f_mntfromname, mp->next->f_mntonname, TYPE(mp->next), n ? (mp->opt + 1) : (char*)0); + mp->next++; + return &mp->hdr.mnt; + } + return 0; +} + +int +mntclose(void* handle) +{ + register Handle_t* mp = (Handle_t*)handle; + + if (!mp) + return -1; + free(mp); + return 0; +} + +#else + +#if _lib_mntctl && _sys_vmount + +/* + * aix + */ + +#include <sys/vmount.h> + +#define SIZE (16 * 1024) + +static const char* type[] = +{ + "aix", "aix#1", "nfs", "jfs", "aix#4", "cdrom" +}; + +typedef struct +{ + Header_t hdr; + long count; + struct vmount* next; + char remote[128]; + char type[16]; + struct vmount info[1]; +} Handle_t; + +void* +mntopen(const char* path, const char* mode) +{ + register Handle_t* mp; + + FIXARGS(path, mode, 0); + if (!(mp = newof(0, Handle_t, 1, SIZE))) + return 0; + if ((mp->count = mntctl(MCTL_QUERY, sizeof(Handle_t) + SIZE, &mp->info)) <= 0) + { + free(mp); + return 0; + } + mp->next = mp->info; + return (void*)mp; +} + +Mnt_t* +mntread(void* handle) +{ + register Handle_t* mp = (Handle_t*)handle; + register char* s; + register char* t; + register char* o; + + if (mp->count > 0) + { + if (vmt2datasize(mp->next, VMT_HOST) && (s = vmt2dataptr(mp->next, VMT_HOST)) && !streq(s, "-")) + { + sfsprintf(mp->remote, sizeof(mp->remote) - 1, "%s:%s", s, vmt2dataptr(mp->next, VMT_OBJECT)); + s = mp->remote; + } + else + s = vmt2dataptr(mp->next, VMT_OBJECT); + if (vmt2datasize(mp->next, VMT_ARGS)) + o = vmt2dataptr(mp->next, VMT_ARGS); + else + o = NiL; + switch (mp->next->vmt_gfstype) + { +#ifdef MNT_AIX + case MNT_AIX: + t = "aix"; + break; +#endif +#ifdef MNT_NFS + case MNT_NFS: + t = "nfs"; + break; +#endif +#ifdef MNT_JFS + case MNT_JFS: + t = "jfs"; + break; +#endif +#ifdef MNT_CDROM + case MNT_CDROM: + t = "cdrom"; + break; +#endif +#ifdef MNT_SFS + case MNT_SFS: + t = "sfs"; + break; +#endif +#ifdef MNT_CACHEFS + case MNT_CACHEFS: + t = "cachefs"; + break; +#endif +#ifdef MNT_NFS3 + case MNT_NFS3: + t = "nfs3"; + break; +#endif +#ifdef MNT_AUTOFS + case MNT_AUTOFS: + t = "autofs"; + break; +#endif + default: + sfsprintf(t = mp->type, sizeof(mp->type), "aix%+d", mp->next->vmt_gfstype); + break; + } + set(&mp->hdr, s, vmt2dataptr(mp->next, VMT_STUB), t, o); + if (--mp->count > 0) + mp->next = (struct vmount*)((char*)mp->next + mp->next->vmt_length); + return &mp->hdr.mnt; + } + return 0; +} + +int +mntclose(void* handle) +{ + register Handle_t* mp = (Handle_t*)handle; + + if (!mp) + return -1; + free(mp); + return 0; +} + +#else + +#if !_lib_setmntent +#undef _lib_getmntent +#if !_SCO_COFF && !_SCO_ELF && !_UTS +#undef _hdr_mnttab +#endif +#endif + +#if _lib_getmntent && ( _hdr_mntent || _sys_mntent && !_sys_mnttab ) + +#if defined(__STDPP__directive) && defined(__STDPP__hide) +__STDPP__directive pragma pp:hide endmntent getmntent +#else +#define endmntent ______endmntent +#define getmntent ______getmntent +#endif + +#include <stdio.h> +#if _hdr_mntent +#include <mntent.h> +#else +#include <sys/mntent.h> +#endif + +#if defined(__STDPP__directive) && defined(__STDPP__hide) +__STDPP__directive pragma pp:nohide endmntent getmntent +#else +#undef endmntent +#undef getmntent +#endif + +extern int endmntent(FILE*); +extern struct mntent* getmntent(FILE*); + +#else + +#undef _lib_getmntent + +#if _hdr_mnttab +#include <mnttab.h> +#else +#if _sys_mnttab +#include <sys/mnttab.h> +#endif +#endif + +#endif + +#ifndef MOUNTED +#ifdef MNT_MNTTAB +#define MOUNTED MNT_MNTTAB +#else +#if _hdr_mnttab || _sys_mnttab +#define MOUNTED "/etc/mnttab" +#else +#define MOUNTED "/etc/mtab" +#endif +#endif +#endif + +#ifdef __Lynx__ +#undef MOUNTED +#define MOUNTED "/etc/fstab" +#define SEP ':' +#endif + +#if _lib_getmntent + +typedef struct +#if _mem_mnt_opts_mntent +#define OPTIONS(p) ((p)->mnt_opts) +#else +#define OPTIONS(p) NiL +#endif + +{ + Header_t hdr; + FILE* fp; +} Handle_t; + +void* +mntopen(const char* path, const char* mode) +{ + register Handle_t* mp; + + FIXARGS(path, mode, MOUNTED); + if (!(mp = newof(0, Handle_t, 1, 0))) + return 0; + if (!(mp->fp = setmntent(path, mode))) + { + free(mp); + return 0; + } + return (void*)mp; +} + +Mnt_t* +mntread(void* handle) +{ + register Handle_t* mp = (Handle_t*)handle; + register struct mntent* mnt; + + if (mnt = getmntent(mp->fp)) + { + set(&mp->hdr, mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, OPTIONS(mnt)); + return &mp->hdr.mnt; + } + return 0; +} + +int +mntclose(void* handle) +{ + register Handle_t* mp = (Handle_t*)handle; + + if (!mp) + return -1; + endmntent(mp->fp); + free(mp); + return 0; +} + +#else + +#if _sys_mntent && _lib_w_getmntent + +#include <sys/mntent.h> + +#define mntent w_mntent + +#define mnt_dir mnt_mountpoint +#define mnt_type mnt_fstname + +#define MNTBUFSIZE (sizeof(struct w_mnth)+16*sizeof(struct w_mntent)) + +#if _mem_mnt_opts_w_mntent +#define OPTIONS(p) ((p)->mnt_opts) +#else +#define OPTIONS(p) NiL +#endif + +#else + +#undef _lib_w_getmntent + +#define MNTBUFSIZE sizeof(struct mntent) + +#if !_mem_mt_dev_mnttab || !_mem_mt_filsys_mnttab +#undef _hdr_mnttab +#endif + +#if _hdr_mnttab + +#define mntent mnttab + +#define mnt_fsname mt_dev +#define mnt_dir mt_filsys +#if _mem_mt_fstyp_mnttab +#define mnt_type mt_fstyp +#endif + +#if _mem_mnt_opts_mnttab +#define OPTIONS(p) ((p)->mnt_opts) +#else +#define OPTIONS(p) NiL +#endif + +#else + +struct mntent +{ + char mnt_fsname[256]; + char mnt_dir[256]; + char mnt_type[32]; + char mnt_opts[64]; +}; + +#define OPTIONS(p) ((p)->mnt_opts) + +#endif + +#endif + +typedef struct +{ + Header_t hdr; + Sfio_t* fp; + struct mntent* mnt; +#if _lib_w_getmntent + int count; +#endif + char buf[MNTBUFSIZE]; +} Handle_t; + +void* +mntopen(const char* path, const char* mode) +{ + register Handle_t* mp; + + FIXARGS(path, mode, MOUNTED); + if (!(mp = newof(0, Handle_t, 1, 0))) + return 0; +#if _lib_w_getmntent + if ((mp->count = w_getmntent(mp->buf, sizeof(mp->buf))) > 0) + mp->mnt = (struct mntent*)(((struct w_mnth*)mp->buf) + 1); + else +#else + mp->mnt = (struct mntent*)mp->buf; + if (!(mp->fp = sfopen(NiL, path, mode))) +#endif + { + free(mp); + return 0; + } + return (void*)mp; +} + +Mnt_t* +mntread(void* handle) +{ + register Handle_t* mp = (Handle_t*)handle; + +#if _lib_w_getmntent + + if (mp->count-- <= 0) + { + if ((mp->count = w_getmntent(mp->buf, sizeof(mp->buf))) <= 0) + return 0; + mp->count--; + mp->mnt = (struct mntent*)(((struct w_mnth*)mp->buf) + 1); + } + set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt)); + mp->mnt++; + return &mp->hdr.mnt; + +#else + +#if _hdr_mnttab + + while (sfread(mp->fp, &mp->buf, sizeof(mp->buf)) == sizeof(mp->buf)) + if (*mp->mnt->mnt_fsname && *mp->mnt->mnt_dir) + { +#ifndef mnt_type + struct stat st; + + static char typ[32]; + + set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, stat(mp->mnt->mnt_dir, &st) ? FS_default : strlcpy(typ, fmtfs(&st), sizeof(typ)), OPTIONS(mp->mnt)); +#else + set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt)); +#endif + return &mp->hdr.mnt; + } + return 0; + +#else + + register int c; + register char* s; + register char* m; + register char* b; + register int q; + register int x; + + again: + q = 0; + x = 0; + b = s = mp->mnt->mnt_fsname; + m = s + sizeof(mp->mnt->mnt_fsname) - 1; + for (;;) switch (c = sfgetc(mp->fp)) + { + case EOF: + return 0; + case '"': + case '\'': + if (q == c) + q = 0; + else if (!q) + q = c; + break; +#ifdef SEP + case SEP: +#else + case ' ': + case '\t': +#endif + if (s != b && !q) switch (++x) + { + case 1: + *s = 0; + b = s = mp->mnt->mnt_dir; + m = s + sizeof(mp->mnt->mnt_dir) - 1; + break; + case 2: + *s = 0; + b = s = mp->mnt->mnt_type; + m = s + sizeof(mp->mnt->mnt_type) - 1; + break; + case 3: + *s = 0; + b = s = mp->mnt->mnt_opts; + m = s + sizeof(mp->mnt->mnt_opts) - 1; + break; + case 4: + *s = 0; + b = s = m = 0; + break; + } + break; + case '\n': + if (x >= 3) + { + set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt)); + return &mp->hdr.mnt; + } + goto again; + default: + if (s < m) + *s++ = c; + break; + } + +#endif + +#endif + +} + +int +mntclose(void* handle) +{ + register Handle_t* mp = (Handle_t*)handle; + + if (!mp) + return -1; + sfclose(mp->fp); + free(mp); + return 0; +} + +#endif + +#endif + +#endif + +/* + * currently no write + */ + +int +mntwrite(void* handle, const Mnt_t* mnt) +{ + NoP(handle); + NoP(mnt); + return -1; +} + +#endif diff --git a/src/lib/libast/port/touch.c b/src/lib/libast/port/touch.c new file mode 100644 index 0000000..c921181 --- /dev/null +++ b/src/lib/libast/port/touch.c @@ -0,0 +1,74 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * Glenn Fowler + * AT&T Research + * + * touch file access and modify times of file + * if flags&PATH_TOUCH_CREATE then file will be created if it doesn't exist + * if flags&PATH_TOUCH_VERBATIM then times are taken verbatim + * times have one second granularity + * + * (time_t)(-1) retain old time + * 0 use current time + * + * the old interface flag values were: + * 1 PATH_TOUCH_CREATE + * -1 PATH_TOUCH_CREATE|PATH_TOUCH_VERBATIM + * PATH_TOUCH_VERBATIM -- not supported + */ + +#include <ast.h> +#include <times.h> +#include <tv.h> + +int +touch(const char* path, time_t at, time_t mt, int flags) +{ + Tv_t av; + Tv_t mv; + Tv_t* ap; + Tv_t* mp; + + if (at == (time_t)(-1) && !(flags & PATH_TOUCH_VERBATIM)) + ap = TV_TOUCH_RETAIN; + else if (!at && !(flags & PATH_TOUCH_VERBATIM)) + ap = 0; + else + { + av.tv_sec = at; + av.tv_nsec = 0; + ap = &av; + } + if (mt == (time_t)(-1) && !(flags & PATH_TOUCH_VERBATIM)) + mp = TV_TOUCH_RETAIN; + else if (!mt && !(flags & PATH_TOUCH_VERBATIM)) + mp = 0; + else + { + mv.tv_sec = mt; + mv.tv_nsec = 0; + mp = &mv; + } + return tvtouch(path, ap, mp, NiL, flags & 1); +} |