summaryrefslogtreecommitdiff
path: root/src/lib/libast/port
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
commit3950ffe2a485479f6561c27364d3d7df5a21d124 (patch)
tree468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/port
downloadksh-upstream.tar.gz
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/port')
-rw-r--r--src/lib/libast/port/astconf.c1718
-rw-r--r--src/lib/libast/port/astcopy.c90
-rw-r--r--src/lib/libast/port/astdynamic.c132
-rw-r--r--src/lib/libast/port/astlicense.c1292
-rw-r--r--src/lib/libast/port/astmath.c72
-rw-r--r--src/lib/libast/port/astquery.c114
-rw-r--r--src/lib/libast/port/aststatic.c44
-rw-r--r--src/lib/libast/port/astwinsize.c143
-rw-r--r--src/lib/libast/port/atmain.C37
-rw-r--r--src/lib/libast/port/iblocks.c95
-rw-r--r--src/lib/libast/port/lc.c883
-rw-r--r--src/lib/libast/port/lc.tab275
-rw-r--r--src/lib/libast/port/lcgen.c791
-rw-r--r--src/lib/libast/port/lclang.h120
-rw-r--r--src/lib/libast/port/lclib.h71
-rw-r--r--src/lib/libast/port/mc.c675
-rw-r--r--src/lib/libast/port/mnt.c816
-rw-r--r--src/lib/libast/port/touch.c74
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 = &num;
+ 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, &notice->item[SINCE]);
+ PUT(b, '-');
+ }
+ copy(b, t, 4);
+ if (notice->item[PARENT].data)
+ {
+ PUT(b, ' ');
+ expand(notice, b, &notice->item[PARENT]);
+ }
+ if (notice->item[CORPORATION].data)
+ {
+ PUT(b, ' ');
+ expand(notice, b, &notice->item[CORPORATION]);
+ if (notice->item[INCORPORATION].data)
+ {
+ PUT(b, ' ');
+ expand(notice, b, &notice->item[INCORPORATION]);
+ }
+ }
+ else if (notice->item[COMPANY].data)
+ {
+ PUT(b, ' ');
+ expand(notice, b, &notice->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(&notice, &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(&notice, &buf, &notice.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(&notice, &buf, &item);
+ }
+ else
+ expand(&notice, &buf, &notice.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(&notice, &buf, NiL, 1, 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ if (notice.item[PACKAGE].data)
+ {
+ copy(&tmp, "This software is part of the ", -1);
+ expand(&notice, &tmp, &notice.item[PACKAGE]);
+ copy(&tmp, " package", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ if (notice.type >= OPEN)
+ {
+ copyright(&notice, &tmp);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.type >= SPECIAL)
+ COMMENT(&notice, &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(&notice, &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(&notice, &tmp, &notice.item[VERSION]);
+ }
+ comment(&notice, &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(&notice, &tmp, &notice.item[PARENT]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[CORPORATION].data)
+ {
+ expand(&notice, &tmp, &notice.item[CORPORATION]);
+ if (notice.item[INCORPORATION].data)
+ {
+ copy(&tmp, " ", -1);
+ expand(&notice, &tmp, &notice.item[INCORPORATION]);
+ }
+ }
+ else if (notice.item[COMPANY].data)
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "A copy of the License is available at", 0);
+ if (notice.item[URL].data)
+ {
+ expand(&notice, &tmp, &notice.item[URL]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[URLMD5].data)
+ {
+ copy(&tmp, "(with md5 checksum ", -1);
+ expand(&notice, &tmp, &notice.item[URLMD5]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ }
+ else if (notice.type == EPL)
+ COMMENT(&notice, &buf, "http://www.eclipse.org/org/documents/epl-v10.html", 0);
+ else
+ COMMENT(&notice, &buf, "http://www.opensource.org/licenses/cpl", 0);
+ comment(&notice, &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(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[i = CORPORATION].data)
+ {
+ if (notice.item[PARENT].data)
+ {
+ expand(&notice, &tmp, &notice.item[i = PARENT]);
+ copy(&tmp, " ", -1);
+ }
+ expand(&notice, &tmp, &notice.item[CORPORATION]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ else if (notice.item[i = COMPANY].data)
+ {
+ if (notice.item[PARENT].data)
+ {
+ expand(&notice, &tmp, &notice.item[i = PARENT]);
+ copy(&tmp, " ", -1);
+ }
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ else
+ i = -1;
+ if (notice.item[URL].data)
+ {
+ COMMENT(&notice, &buf, "A copy of the Source Code Agreement is available", 0);
+ copy(&tmp, "at the ", -1);
+ if (i >= 0)
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, " Internet web site URL", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ expand(&notice, &tmp, &notice.item[URL]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[URLMD5].data)
+ {
+ copy(&tmp, "(with an md5 checksum of ", -1);
+ expand(&notice, &tmp, &notice.item[URLMD5]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ COMMENT(&notice, &buf, "If you have copied or used this software without agreeing", 0);
+ COMMENT(&notice, &buf, "to the terms of the license you are infringing on", 0);
+ COMMENT(&notice, &buf, "the license and copyright and are violating", 0);
+ if (i >= 0)
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, "'s", -1);
+ if (n >= COMLONG)
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ else
+ PUT(&tmp, ' ');
+ copy(&tmp, "intellectual property rights.", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == GPL)
+ {
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "This is free software; you can redistribute it and/or", 0);
+ COMMENT(&notice, &buf, "modify it under the terms of the GNU General Public License", 0);
+ COMMENT(&notice, &buf, "as published by the Free Software Foundation;", 0);
+ COMMENT(&notice, &buf, "either version 2, or (at your option) any later version.", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "This software is distributed in the hope that it", 0);
+ COMMENT(&notice, &buf, "will be useful, but WITHOUT ANY WARRANTY;", 0);
+ COMMENT(&notice, &buf, "without even the implied warranty of MERCHANTABILITY", 0);
+ COMMENT(&notice, &buf, "or FITNESS FOR A PARTICULAR PURPOSE.", 0);
+ COMMENT(&notice, &buf, "See the GNU General Public License for more details.", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "You should have received a copy of the", 0);
+ COMMENT(&notice, &buf, "GNU General Public License", 0);
+ COMMENT(&notice, &buf, "along with this software (see the file COPYING.)", 0);
+ COMMENT(&notice, &buf, "If not, a copy is available at", 0);
+ COMMENT(&notice, &buf, "http://www.gnu.org/copyleft/gpl.html", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == BSD)
+ {
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "Redistribution and use in source and binary forms, with or", -1);
+ COMMENT(&notice, &buf, "without modification, are permitted provided that the following", -1);
+ COMMENT(&notice, &buf, "conditions are met:", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, " 1. Redistributions of source code must retain the above", -1);
+ COMMENT(&notice, &buf, " copyright notice, this list of conditions and the", -1);
+ COMMENT(&notice, &buf, " following disclaimer.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, " 2. Redistributions in binary form must reproduce the above", -1);
+ COMMENT(&notice, &buf, " copyright notice, this list of conditions and the", -1);
+ COMMENT(&notice, &buf, " following disclaimer in the documentation and/or other", -1);
+ COMMENT(&notice, &buf, " materials provided with the distribution.", -1);
+ comment(&notice, &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(&notice, &tmp, &notice.item[i]);
+ else
+ copy(&tmp, "the copyright holder", -1);
+ copy(&tmp, " nor the", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), -1);
+ COMMENT(&notice, &buf, " names of its contributors may be used to endorse or", -1);
+ COMMENT(&notice, &buf, " promote products derived from this software without", -1);
+ COMMENT(&notice, &buf, " specific prior written permission.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND", -1);
+ COMMENT(&notice, &buf, "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,", -1);
+ COMMENT(&notice, &buf, "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF", -1);
+ COMMENT(&notice, &buf, "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE", -1);
+ COMMENT(&notice, &buf, "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS", -1);
+ COMMENT(&notice, &buf, "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,", -1);
+ COMMENT(&notice, &buf, "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED", -1);
+ COMMENT(&notice, &buf, "TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,", -1);
+ COMMENT(&notice, &buf, "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON", -1);
+ COMMENT(&notice, &buf, "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,", -1);
+ COMMENT(&notice, &buf, "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY", -1);
+ COMMENT(&notice, &buf, "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE", -1);
+ COMMENT(&notice, &buf, "POSSIBILITY OF SUCH DAMAGE.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == ZLIB)
+ {
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "This software is provided 'as-is', without any express or implied", -1);
+ COMMENT(&notice, &buf, "warranty. In no event will the authors be held liable for any", -1);
+ COMMENT(&notice, &buf, "damages arising from the use of this software.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "Permission is granted to anyone to use this software for any", -1);
+ COMMENT(&notice, &buf, "purpose, including commercial applications, and to alter it and", -1);
+ COMMENT(&notice, &buf, "redistribute it freely, subject to the following restrictions:", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, " 1. The origin of this software must not be misrepresented;", -1);
+ COMMENT(&notice, &buf, " you must not claim that you wrote the original software. If", -1);
+ COMMENT(&notice, &buf, " you use this software in a product, an acknowledgment in the", -1);
+ COMMENT(&notice, &buf, " product documentation would be appreciated but is not", -1);
+ COMMENT(&notice, &buf, " required.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, " 2. Altered source versions must be plainly marked as such,", -1);
+ COMMENT(&notice, &buf, " and must not be misrepresented as being the original", -1);
+ COMMENT(&notice, &buf, " software.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, " 3. This notice may not be removed or altered from any source", -1);
+ COMMENT(&notice, &buf, " distribution.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == MIT)
+ {
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "Permission is hereby granted, free of charge, to any person", 0);
+ COMMENT(&notice, &buf, "obtaining a copy of this software and associated", 0);
+ COMMENT(&notice, &buf, "documentation files (the \"Software\"), to deal in the", 0);
+ COMMENT(&notice, &buf, "Software without restriction, including without limitation", 0);
+ COMMENT(&notice, &buf, "the rights to use, copy, modify, merge, publish, distribute,", 0);
+ COMMENT(&notice, &buf, "sublicense, and/or sell copies of the Software, and to", 0);
+ COMMENT(&notice, &buf, "permit persons to whom the Software is furnished to do so,", 0);
+ COMMENT(&notice, &buf, "subject to the following conditions:", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "The above copyright notice and this permission notice shall", 0);
+ COMMENT(&notice, &buf, "be included in all copies or substantial portions of the", 0);
+ COMMENT(&notice, &buf, "Software.", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY", 0);
+ COMMENT(&notice, &buf, "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE", 0);
+ COMMENT(&notice, &buf, "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR", 0);
+ COMMENT(&notice, &buf, "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS", 0);
+ COMMENT(&notice, &buf, "OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR", 0);
+ COMMENT(&notice, &buf, "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR", 0);
+ COMMENT(&notice, &buf, "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE", 0);
+ COMMENT(&notice, &buf, "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", 0);
+ comment(&notice, &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(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, " - ", -1);
+ }
+ else
+ i = -1;
+ copy(&tmp, "Proprietary", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ comment(&notice, &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(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ if (notice.item[PARENT].data)
+ {
+ expand(&notice, &tmp, &notice.item[PARENT]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[CORPORATION].data)
+ {
+ expand(&notice, &tmp, &notice.item[CORPORATION]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ }
+ else if (notice.item[COMPANY].data)
+ {
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ }
+ }
+ else
+ {
+ copy(&tmp, "This is unpublished proprietary source code", -1);
+ if (i >= 0)
+ copy(&tmp, " of", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ if (notice.item[COMPANY].data)
+ {
+ if (SIZ(&tmp))
+ PUT(&tmp, ' ');
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ }
+ if (SIZ(&tmp))
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ COMMENT(&notice, &buf, "and is not to be disclosed or used except in", 1);
+ COMMENT(&notice, &buf, "accordance with applicable agreements", 1);
+ }
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == NONEXCLUSIVE)
+ {
+ COMMENT(&notice, &buf, "For nonexclusive individual use", 1);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == NONCOMMERCIAL)
+ {
+ COMMENT(&notice, &buf, "For noncommercial use", 1);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ if (notice.type >= PROPRIETARY && !notice.item[URL].data)
+ {
+ COMMENT(&notice, &buf, "Unpublished & Not for Publication", 0);
+ comment(&notice, &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(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ else
+ PUT(&tmp, ' ');
+ if (notice.item[PARENT].data)
+ {
+ expand(&notice, &tmp, &notice.item[PARENT]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[CORPORATION].data)
+ {
+ expand(&notice, &tmp, &notice.item[CORPORATION]);
+ if (notice.item[INCORPORATION].data)
+ {
+ copy(&tmp, " ", -1);
+ expand(&notice, &tmp, &notice.item[INCORPORATION]);
+ }
+ }
+ else if (notice.item[COMPANY].data)
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ }
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ COMMENT(&notice, &buf, "under the terms and conditions of the license in", 0);
+ expand(&notice, &tmp, &notice.item[URL]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[URLMD5].data)
+ {
+ copy(&tmp, "(with an md5 checksum of ", -1);
+ expand(&notice, &tmp, &notice.item[URLMD5]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == PROPRIETARY)
+ {
+ COMMENT(&notice, &buf, "The copyright notice above does not evidence any", 0);
+ COMMENT(&notice, &buf, "actual or intended publication of such source code", 0);
+ comment(&notice, &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(&notice, &tmp, &item);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), h);
+ } while (v++ < x);
+ if (item.size)
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ if (notice.item[ORGANIZATION].data)
+ {
+ expand(&notice, &tmp, &notice.item[ORGANIZATION]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ if (notice.item[COMPANY].data)
+ {
+ if (SIZ(&tmp))
+ PUT(&tmp, ' ');
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ }
+ if (SIZ(&tmp))
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[LOCATION].data)
+ {
+ expand(&notice, &tmp, &notice.item[LOCATION]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ comment(&notice, &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(&notice, &buf, &notice.id[i].value);
+ PUT(&buf, ']');
+ }
+ else
+ {
+ if (k < 0)
+ {
+ COMMENT(&notice, &buf, "CONTRIBUTORS", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ k = 1;
+ expand(&notice, &tmp, &notice.id[i].value);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ if (!q)
+ break;
+ }
+ if (q)
+ break;
+ if (!h)
+ {
+ if (notice.type == USAGE)
+ {
+ copy(&buf, "[-author?", -1);
+ expand(&notice, &buf, &item);
+ PUT(&buf, ']');
+ }
+ else
+ {
+ if (k < 0)
+ {
+ COMMENT(&notice, &buf, "CONTRIBUTORS", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ k = 1;
+ expand(&notice, &tmp, &item);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ }
+ }
+ if (k > 0)
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ if (notice.type == USAGE)
+ {
+ copy(&buf, "[-copyright?", -1);
+ copyright(&notice, &buf);
+ PUT(&buf, ']');
+ if (notice.item[URL].data)
+ {
+ copy(&buf, "[-license?", -1);
+ expand(&notice, &buf, &notice.item[URL]);
+ PUT(&buf, ']');
+ }
+ PUT(&buf, '\n');
+ }
+ else
+ comment(&notice, &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);
+}