Hi!

----

Attached is a first prototype patch
("ksh93_l10n_support_prototype01.diff.txt") of l10n (=localisation)
support for the ksh93-integration prototype. The patch is completely
untested for now but I'd like to get some feedback on the
implementation.

The missing parts are that AST "libpp" (needed by AST's "msgcpp" tool)
isn't integrated yet, instead I am using a prebuild libpp.a archive
which lives outside the tree.

Mike: I'd like to put libpp into usr/src/lib/libpp/ - but how should we
handle the library when we do not ship it ? Should we build it simply as
static library (how can I do that ?) or build it as dynamic version but
add libpp.so&co. to the exception list in the package database (what was
the exact file name again ?) ?

----

Bye,
Roland

-- 
  __ .  . __
 (o.\ \/ /.o) roland.mainz at nrubsig.org
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 7950090
 (;O/ \/ \O;)
-------------- next part --------------
Index: src/pkgdefs/SUNW0on/prototype_com
===================================================================
--- src/pkgdefs/SUNW0on/prototype_com   (revision 387)
+++ src/pkgdefs/SUNW0on/prototype_com   (working copy)
@@ -68,6 +68,10 @@
 f none usr/lib/locale/C/LC_MESSAGES/mailx.help           644 root sys
 f none usr/lib/locale/C/LC_MESSAGES/more.help            644 root sys
 f none usr/lib/locale/C/LC_MESSAGES/uxlibc.src           644 root sys
+f none usr/lib/locale/C/LC_MESSAGES/libshell             644 root sys
+f none usr/lib/locale/C/LC_MESSAGES/libdll               644 root sys
+f none usr/lib/locale/C/LC_MESSAGES/libcmd               644 root sys
+f none usr/lib/locale/C/LC_MESSAGES/libast               644 root sys
 f none usr/lib/locale/C/LC_TIME/SUNW_OST_OSCMD.po        644 root sys
 f none usr/lib/locale/C/LC_TIME/SUNW_OST_OSLIB.po        644 root sys
 #
Index: src/cmd/Makefile
===================================================================
--- src/cmd/Makefile    (revision 387)
+++ src/cmd/Makefile    (working copy)
@@ -63,6 +63,7 @@
        acctadm         \
        arch            \
        asa             \
+       ast             \
        audio           \
        auths           \
        autopush        \
Index: src/cmd/ast/msgcc/msggen.c
===================================================================
--- src/cmd/ast/msgcc/msggen.c  (revision 0)
+++ src/cmd/ast/msgcc/msggen.c  (revision 0)
@@ -0,0 +1,520 @@
+/***********************************************************************
+*                                                                      *
+*               This software is part of the ast package               *
+*           Copyright (c) 2000-2006 AT&T Knowledge Ventures            *
+*                      and is licensed under the                       *
+*                  Common Public License, Version 1.0                  *
+*                      by AT&T Knowledge Ventures                      *
+*                                                                      *
+*                A copy of the License is available at                 *
+*            http://www.opensource.org/licenses/cpl1.0.txt             *
+*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
+*                                                                      *
+*              Information and Software Systems Research               *
+*                            AT&T Research                             *
+*                           Florham Park NJ                            *
+*                                                                      *
+*                 Glenn Fowler <gsf at research.att.com>                  *
+*                                                                      *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Labs Research
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: msggen (AT&T Labs Research) 2002-03-11 $\n]"
+USAGE_LICENSE
+"[+NAME?msggen - generate a machine independent formatted message catalog]"
+"[+DESCRIPTION?\bmsggen\b merges the message text source files \amsgfile\a"
+"      into a machine independent formatted message catalog \acatfile\a."
+"      The file \acatfile\a will be created if it does not already exist."
+"      If \acatfile\a does exist, its messages will be included in the new"
+"      \acatfile\a. If set and message numbers collide, the new message"
+"      text defined in \amsgfile\a will replace the old message text"
+"      currently contained in \acatfile\a. Non-ASCII characters must be"
+"      UTF-8 encoded. \biconv\b(1) can be used to convert to/from UTF-8.]"
+"[f:format?List the \bprintf\b(3) format signature for each message in"
+"      \acatfile\a. A format signature is one line containing one character"
+"      per format specification:]{"
+"              [c?char]"
+"              [d?double]"
+"              [D?long double]"
+"              [f?float]"
+"              [h?short]"
+"              [i?int]"
+"              [j?long long]"
+"              [l?long]"
+"              [p?void*]"
+"              [s?string]"
+"              [t?ptrdiff_t]"
+"              [z?size_t]"
+"              [???unknown]"
+"}"
+"[l:list?List \acatfile\a in UTF-8 \amsgfile\a form.]"
+"[s:set?Convert the \acatfile\a operand to a message set number and"
+"      print the number on the standard output.]"
+"[+EXTENDED DESCRIPTION?Message text source files are in \bgencat\b(1)"
+"      format, defined as follows. Note that the fields of a message text"
+"      source line are separated by a single blank character. Any other"
+"      blank characters are considered as being part of the subsequent"
+"      field. The \bNL_*\b constants are defined in one or both of"
+"      \b<limits.h>\b and \b<nl_types.h>\b.]{"
+"              [+$ \acomment\a?A line beginning with \b$\b followed by a"
+"                      blank character is treated as a comment.]"
+"              [+$delset \an\a \acomment\a?This line deletes message set"
+"                      \an\a from an existing message catalog. \an\a"
+"                      denotes the set number [1, \bNL_SETMAX\b]]. Any"
+"                      text following the set number is treated as a"
+"                      comment.]"
+"              [+$quote \ac\a?This line specifies an optional quote"
+"                      character \ac\a, which can be used to surround"
+"                      \amessage-text\a so that trailing spaces or"
+"                      empty messages are visible in a message source"
+"                      line. By default, or if an empty \b$quote\b"
+"                      directive is supplied, no quoting of \amessage-text\a"
+"                      will be recognized.]"
+"              [+$set \an\a \acomment\a?This line specifies the set"
+"                      identifier of the following messages until the next"
+"                      \b$set\b or end-of-file appears. \an\a denotes the set"
+"                      identifier, which is defined as a number in the range"
+"                      [1, \bNL_SETMAX\b]]. Set numbers need not be"
+"                      contiguous. Any text following the set identifier is"
+"                      treated as a comment. If no \b$set\b directive is"
+"                      specified in a  message text source file, all messages"
+"                      will be located in message set \b1\b.]"
+"              [+$translation \aidentification\a \aYYYY-MM-DD\a[,...]]?Append"
+"                      translation info to the message catalog header. Only"
+"                      the newest date for a given \aidentification\a"
+"                      is retained in the catalog. Multiple translation lines"
+"                      are combined into a single \b,\b separated list.]"
+"              [+\am\a \amessage-text\a?\am\a denotes the message identifier,"
+"                      which is defined as a number in the range"
+"                      [1, \bNL_MSGMAX\b]]. The message-text is stored in the"
+"                      message catalogue with the set identifier specified by"
+"                      the last \b$set\b directive, and with message"
+"                      identifier \am\a. If the \amessage-text\a is empty,"
+"                      and a blank character field separator is present, an"
+"                      empty string is stored in the message catalogue. If a"
+"                      message source line has a message number, but neither"
+"                      a field separator nor \amessage-text\a, the existing"
+"                      message with that number (if any) is deleted from the"
+"                      catalogue. Message identifiers need not be contiguous."
+"                      There are no \amessage-text\a length restrictions.]"
+"}"
+
+"\n"
+"\ncatfile [ msgfile ]\n"
+"\n"
+
+"[+SEE ALSO?\bgencat\b(1), \biconv\b(1), \bmsgcc\b(1), \btranslate\b(1),"
+"      \bfmtfmt\b(3)]"
+;
+
+#include <ast.h>
+#include <ctype.h>
+#include <ccode.h>
+#include <error.h>
+#include <mc.h>
+
+typedef struct Xl_s
+{
+       struct Xl_s*    next;
+       char*           date;
+       char            name[1];
+} Xl_t;
+
+/*
+ * append s to the translation list
+ */
+
+static Xl_t*
+translation(Xl_t* xp, register char* s)
+{
+       register Xl_t*  px;
+       register char*  t;
+       char*           d;
+       char*           e;
+
+       do
+       {
+               for (; isspace(*s); s++);
+               for (d = e = 0, t = s; *t; t++)
+                       if (*t == ',')
+                       {
+                               e = t;
+                               *e++ = 0;
+                               break;
+                       }
+                       else if (isspace(*t))
+                               d = t;
+               if (d)
+               {
+                       *d++ = 0;
+                       for (px = xp; px; px = px->next)
+                               if (streq(px->name, s))
+                               {
+                                       if (strcoll(px->date, d) < 0)
+                                       {
+                                               free(px->date);
+                                               if (!(px->date = strdup(d)))
+                                                       error(ERROR_SYSTEM|3, 
"out of space [translation]");
+                                       }
+                                       break;
+                               }
+                       if (!px)
+                       {
+                               if (!(px = newof(0, Xl_t, 1, strlen(s))) || 
!(px->date = strdup(d)))
+                                       error(ERROR_SYSTEM|3, "out of space 
[translation]");
+                               strcpy(px->name, s);
+                               px->next = xp;
+                               xp = px;
+                       }
+               }
+       } while (s = e);
+       return xp;
+}
+
+/*
+ * sfprintf() with ccmaps(from,to)
+ */
+
+static int
+ccsfprintf(int from, int to, Sfio_t* sp, const char* format, ...)
+{
+       va_list         ap;
+       Sfio_t*         tp;
+       char*           s;
+       int             n;
+
+       va_start(ap, format);
+       if (from == to)
+               n = sfvprintf(sp, format, ap);
+       else if (tp = sfstropen())
+       {
+               n = sfvprintf(tp, format, ap);
+               s = sfstrbase(tp);
+               ccmaps(s, n, from, to);
+               n = sfwrite(sp, s, n);
+               sfstrclose(tp);
+       }
+       else
+               n = -1;
+       return n;
+}
+
+int
+main(int argc, char** argv)
+{
+       register Mc_t*  mc;
+       register char*  s;
+       register char*  t;
+       register int    c;
+       register int    q;
+       register int    i;
+       int             num;
+       char*           b;
+       char*           e;
+       char*           catfile;
+       char*           msgfile;
+       Sfio_t*         sp;
+       Sfio_t*         mp;
+       Sfio_t*         tp;
+       Xl_t*           px;
+       Xl_t*           bp;
+
+       Xl_t*           xp = 0;
+       int             format = 0;
+       int             list = 0;
+       int             set = 0;
+
+       NoP(argc);
+       error_info.id = "msggen";
+       for (;;)
+       {
+               switch (optget(argv, usage))
+               {
+               case 'f':
+                       format = list = 1;
+                       continue;
+               case 'l':
+                       list = 1;
+                       continue;
+               case 's':
+                       set = 1;
+                       continue;
+               case '?':
+                       error(ERROR_USAGE|4, "%s", opt_info.arg);
+                       continue;
+               case ':':
+                       error(2, "%s", opt_info.arg);
+                       continue;
+               }
+               break;
+       }
+       argv += opt_info.index;
+       if (error_info.errors || !(catfile = *argv++))
+               error(ERROR_USAGE|4, "%s", optusage(NiL));
+
+       /*
+        * set and list only need catfile
+        */
+
+       if (set)
+       {
+               sfprintf(sfstdout, "%d\n", mcindex(catfile, NiL, NiL, NiL));
+               return error_info.errors != 0;
+       }
+       else if (list)
+       {
+               if (!(sp = sfopen(NiL, catfile, "r")))
+                       error(ERROR_SYSTEM|3, "%s: cannot read catalog", 
catfile);
+               if (!(mc = mcopen(sp)))
+                       error(ERROR_SYSTEM|3, "%s: catalog content error", 
catfile);
+               sfclose(sp);
+               if (format)
+               {
+                       for (set = 1; set <= mc->num; set++)
+                               if (mc->set[set].num)
+                               {
+                                       sfprintf(sfstdout, "$set %d\n", set);
+                                       for (num = 1; num <= mc->set[set].num; 
num++)
+                                               if (s = mc->set[set].msg[num])
+                                                       sfprintf(sfstdout, "%d 
\"%s\"\n", num, fmtfmt(s));
+                               }
+               }
+               else
+               {
+                       if (*mc->translation)
+                       {
+                               ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, 
"$translation ");
+                               sfprintf(sfstdout, "%s", mc->translation);
+                               ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\n");
+                       }
+                       ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$quote 
\"\n");
+                       for (set = 1; set <= mc->num; set++)
+                               if (mc->set[set].num)
+                               {
+                                       ccsfprintf(CC_NATIVE, CC_ASCII, 
sfstdout, "$set %d\n", set);
+                                       for (num = 1; num <= mc->set[set].num; 
num++)
+                                               if (s = mc->set[set].msg[num])
+                                               {
+                                                       ccsfprintf(CC_NATIVE, 
CC_ASCII, sfstdout, "%d \"", num);
+                                                       while (c = *s++)
+                                                       {
+                                                               /*INDENT...*/
+
+                       switch (c)
+                       {
+                       case 0x22: /* " */
+                       case 0x5C: /* \ */
+                               sfputc(sfstdout, 0x5C);
+                               break;
+                       case 0x07: /* \a */
+                               c = 0x61;
+                               sfputc(sfstdout, 0x5C);
+                               break;
+                       case 0x08: /* \b */
+                               c = 0x62;
+                               sfputc(sfstdout, 0x5C);
+                               break;
+                       case 0x0A: /* \n */
+                               c = 0x6E;
+                               sfputc(sfstdout, 0x5C);
+                               break;
+                       case 0x0B: /* \v */
+                               c = 0x76;
+                               sfputc(sfstdout, 0x5C);
+                               break;
+                       case 0x0C: /* \f */
+                               c = 0x66;
+                               sfputc(sfstdout, 0x5C);
+                               break;
+                       case 0x0D: /* \r */
+                               c = 0x72;
+                               sfputc(sfstdout, 0x5C);
+                               break;
+                       }
+
+                                                               /*...UNDENT*/
+                                                               
sfputc(sfstdout, c);
+                                                       }
+                                                       ccsfprintf(CC_NATIVE, 
CC_ASCII, sfstdout, "\"\n");
+                                               }
+                               }
+               }
+               mcclose(mc);
+               return error_info.errors != 0;
+       }
+       else if (!(msgfile = *argv++) || *argv)
+               error(3, "exactly one message file must be specified");
+
+       /*
+        * open the files and handles
+        */
+
+       if (!(tp = sfstropen()))
+               error(ERROR_SYSTEM|3, "out of space [string stream]");
+       if (!(mp = sfopen(NiL, msgfile, "r")))
+               error(ERROR_SYSTEM|3, "%s: cannot read message file", msgfile);
+       sp = sfopen(NiL, catfile, "r");
+       if (!(mc = mcopen(sp)))
+               error(ERROR_SYSTEM|3, "%s: catalog content error", catfile);
+       if (sp)
+               sfclose(sp);
+       xp = translation(xp, mc->translation);
+
+       /*
+        * read the message file
+        */
+
+       q = 0;
+       set = 1;
+       error_info.file = msgfile;
+       while (s = sfgetr(mp, '\n', 1))
+       {
+               error_info.line++;
+               if (!*s)
+                       continue;
+               if (*s == '$')
+               {
+                       if (!*++s || isspace(*s))
+                               continue;
+                       for (t = s; *s && !isspace(*s); s++);
+                       if (*s)
+                               *s++ = 0;
+                       if (streq(t, "delset"))
+                       {
+                               while (isspace(*s))
+                                       s++;
+                               num = (int)strtol(s, NiL, 0);
+                               if (num < mc->num && mc->set[num].num)
+                                       for (i = 1; i <= mc->set[num].num; i++)
+                                               mcput(mc, num, i, NiL);
+                       }
+                       else if (streq(t, "quote"))
+                               q = *s ? *s : 0;
+                       else if (streq(t, "set"))
+                       {
+                               while (isspace(*s))
+                                       s++;
+                               num = (int)strtol(s, &e, 0);
+                               if (e != s)
+                                       set = num;
+                               else
+                                       error(2, "set number expected");
+                       }
+                       else if (streq(t, "translation"))
+                               xp = translation(xp, s);
+               }
+               else
+               {
+                       t = s + sfvalue(mp);
+                       num = (int)strtol(s, &e, 0);
+                       if (e != s)
+                       {
+                               s = e;
+                               if (!*s)
+                               {
+                                       if (mcput(mc, set, num, NiL))
+                                               error(2, "(%d,%d): cannot 
delete message", set, num);
+                               }
+                               else if (isspace(*s++))
+                               {
+                                       if (t > (s + 1) && *(t -= 2) == '\\')
+                                       {
+                                               sfwrite(tp, s, t - s);
+                                               while (s = sfgetr(mp, '\n', 0))
+                                               {
+                                                       error_info.line++;
+                                                       t = s + sfvalue(mp);
+                                                       if (t <= (s + 1) || *(t 
-= 2) != '\\')
+                                                               break;
+                                                       sfwrite(tp, s, t - s);
+                                               }
+                                               s = sfstruse(tp);
+                                       }
+                                       if (q)
+                                       {
+                                               if (*s++ != q)
+                                               {
+                                                       error(2, "(%d,%d): %c 
quote expected", set, num, q);
+                                                       continue;
+                                               }
+                                               b = t = s;
+                                               while (c = *s++)
+                                               {
+                                                       if (c == '\\')
+                                                       {
+                                                               c = chresc(s - 
1, &e);
+                                                               s = e;
+                                                               if (c)
+                                                                       *t++ = 
c;
+                                                               else
+                                                                       
error(1, "nul character ignored");
+                                                       }
+                                                       else if (c == q)
+                                                               break;
+                                                       else
+                                                               *t++ = c;
+                                               }
+                                               if (*s)
+                                               {
+                                                       error(2, "(%d,%d): 
characters after quote not expected", set, num);
+                                                       continue;
+                                               }
+                                               *t = 0;
+                                               s = b;
+                                       }
+                                       if (mcput(mc, set, num, s))
+                                               error(2, "(%d,%d): cannot add 
message", set, num);
+                               }
+                               else
+                                       error(2, "message text expected");
+                       }
+                       else
+                               error(2, "message number expected");
+               }
+       }
+       error_info.file = 0;
+       error_info.line = 0;
+
+       /*
+        * fix up the translation record
+        */
+
+       if (xp)
+       {
+               t = "";
+               for (;;)
+               {
+                       for (bp = 0, px = xp; px; px = px->next)
+                               if (px->date && (!bp || strcoll(bp->date, 
px->date) < 0))
+                                       bp = px;
+                       if (!bp)
+                               break;
+                       sfprintf(tp, "%s%s %s", t, bp->name, bp->date);
+                       t = ", ";
+                       bp->date = 0;
+               }
+               mc->translation = sfstruse(tp);
+       }
+
+       /*
+        * dump the catalog to a local temporary
+        * rename if no errors
+        */
+
+       if (!(s = pathtemp(NiL, 0, "", error_info.id, NiL)) || !(sp = 
sfopen(NiL, s, "w")))
+               error(ERROR_SYSTEM|3, "%s: cannot write catalog file", catfile);
+       if (mcdump(mc, sp) || mcclose(mc) || sfclose(sp))
+       {
+               remove(s);
+               error(ERROR_SYSTEM|3, "%s: temporary catalog file write error", 
s);
+       }
+       remove(catfile);
+       if (rename(s, catfile))
+               error(ERROR_SYSTEM|3, "%s: cannot rename from temporary catalog 
file %s", catfile, s);
+       return error_info.errors != 0;
+}
Index: src/cmd/ast/msgcc/PROMO.mm
===================================================================
--- src/cmd/ast/msgcc/PROMO.mm  (revision 0)
+++ src/cmd/ast/msgcc/PROMO.mm  (revision 0)
@@ -0,0 +1,22 @@
+.H 1 msgcc
+.B msgcc
+and
+.B msgcpp
+extract message text from C source for
+.BR gencat (1)
+message catalogs.
+.BR msggen (1)
+is a
+.BR gencat (1)
+replacement that generates machine independent binary message
+catalogs that are compatible with the
+.B ast
+.BR catgets (3)
+implementation.
+.B catgets
+also supports native message catalogs where available.
+.BR msgcvt (1)
+and
+.BR msgadmin (1)
+are administrative commands that support machine translation
+of C locale message catalogs.
Index: src/cmd/ast/msgcc/msgcvt.c
===================================================================
--- src/cmd/ast/msgcc/msgcvt.c  (revision 0)
+++ src/cmd/ast/msgcc/msgcvt.c  (revision 0)
@@ -0,0 +1,691 @@
+/***********************************************************************
+*                                                                      *
+*               This software is part of the ast package               *
+*           Copyright (c) 2000-2006 AT&T Knowledge Ventures            *
+*                      and is licensed under the                       *
+*                  Common Public License, Version 1.0                  *
+*                      by AT&T Knowledge Ventures                      *
+*                                                                      *
+*                A copy of the License is available at                 *
+*            http://www.opensource.org/licenses/cpl1.0.txt             *
+*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
+*                                                                      *
+*              Information and Software Systems Research               *
+*                            AT&T Research                             *
+*                           Florham Park NJ                            *
+*                                                                      *
+*                 Glenn Fowler <gsf at research.att.com>                  *
+*                                                                      *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Labs Research
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: msgcvt (AT&T Labs Research) 2000-05-01 $\n]"
+USAGE_LICENSE
+"[+NAME?msgcvt - convert message file to/from html]"
+"[+DESCRIPTION?\bmsgcvt\b reads a \bgencat\b(1) format file on the standard"
+"      input and converts it to \bhtml\b on the standard output. The input"
+"      file must contain the control statement \b$quote \"\b and use the \""
+"      character to quote message text. The output is in a form suitable for"
+"      automatic translation by web sites like"
+"      \bhttp://babelfish.altavista.com/\b or filters like"
+"      \btranslate\b(1).]"
+"[h:html?Generate \bhtml\b from \bgencat\b(1) input. This is the default.]"
+"[m:msg?Generate a \bgencat\b(1) message file from (presumably translated)"
+"      \bhtml\b. Wide characters are UTF-8 encoded.]"
+"[r:raw?The message file is raw message text, one message per line, with no"
+"      quoting or line numbering.]"
+"[+SEE ALSO?\bgencat\b(1), \bmsgcc\b(1), \bmsggen\b(1), \btranslate\b(1)]"
+;
+
+#include <ast.h>
+#include <ctype.h>
+#include <error.h>
+
+#define MSG_RAW                (1<<0)
+#define MSG_SPLICE     (1<<1)
+
+#define SPACE(s)       
(isspace(*s)&&(s+=1)||*s=='\\'&&(*(s+1)=='n'||*(s+1)=='t')&&(s+=2))
+
+typedef void (*Convert_f)(Sfio_t*, Sfio_t*, int);
+
+typedef struct
+{
+       const char*     name;
+       int             code;
+} Code_t;
+
+static const Code_t    codes[] =
+{
+       "aacute",       225,
+       "Aacute",       193,
+       "acirc",        226,
+       "Acirc",        194,
+       "aelig",        230,
+       "AElig",        198,
+       "agrave",       224,
+       "Agrave",       192,
+       "amp",          '&',
+       "aring",        229,
+       "Aring",        197,
+       "atilde",       227,
+       "Atilde",       195,
+       "auml",         228,
+       "Auml",         196,
+       "ccedil",       231,
+       "Ccedil",       199,
+       "copy",         169,
+       "eacute",       233,
+       "Eacute",       201,
+       "ecirc",        234,
+       "Ecirc",        202,
+       "egrave",       232,
+       "Egrave",       200,
+       "euml",         235,
+       "Euml",         203,
+       "gt",           '>',
+       "iacute",       237,
+       "Iacute",       205,
+       "icirc",        238,
+       "Icirc",        206,
+       "igrave",       236,
+       "Igrave",       204,
+       "iuml",         239,
+       "Iuml",         207,
+       "lt",           '<',
+       "nbsp",         ' ',
+       "ntilde",       241,
+       "Ntilde",       209,
+       "oacute",       243,
+       "Oacute",       211,
+       "ocirc",        244,
+       "Ocirc",        212,
+       "ograve",       242,
+       "Ograve",       210,
+       "oslash",       248,
+       "Oslash",       216,
+       "otilde",       245,
+       "Otilde",       213,
+       "ouml",         246,
+       "Ouml",         214,
+       "quot",         '"',
+       "reg",          174,
+       "szlig",        223,
+       "uacute",       250,
+       "Uacute",       218,
+       "ucirc",        251,
+       "Ucirc",        219,
+       "ugrave",       249,
+       "Ugrave",       217,
+       "uuml",         252,
+       "Uuml",         220,
+       "yuml",         255,
+};
+
+static int
+decode(Sfio_t* ip)
+{
+       register int    c;
+       register int    i;
+       char            name[32];
+
+       if ((c = sfgetc(ip)) == EOF)
+               return '&';
+       name[0] = c;
+       i = 1;
+       if (c != '#' && !isalpha(c))
+               goto bad;
+       while ((c = sfgetc(ip)) != EOF && c != ';')
+       {
+               if (c == '&')
+                       i = 0;
+               else
+               {
+                       name[i++] = c;
+                       if (!isalnum(c) && (i > 1 || c != '#') || i >= 
(elementsof(name) - 1))
+                               goto bad;
+               }
+       }
+       name[i] = 0;
+       if (name[0] == '#')
+       {
+               switch (c = strtol(name + 1, NiL, 10))
+               {
+               case 91:
+                       c = '[';
+                       break;
+               case 93:
+                       c = ']';
+                       break;
+               }
+       }
+       else
+       {
+               for (i = 0; i < elementsof(codes); i++)
+                       if (streq(codes[i].name, name))
+                       {
+                               c = codes[i].code;
+                               break;
+                       }
+               if (i >= elementsof(codes))
+                       goto bad;
+       }
+       return c;
+ bad:
+       name[i] = 0;
+       if (c == ';')
+               error(1, "&%s: unknown HTML special character -- & assumed", 
name);
+       else
+               error(1, "&%s: invalid HTML special character -- & assumed", 
name);
+       while (i--)
+               sfungetc(ip, name[i]);
+       return '&';
+}
+
+static int
+sfpututf(Sfio_t* op, register int w)
+{
+       if (!(w & ~0x7F))
+               return sfputc(op, w);
+       else if (!(w & ~0x7FF))
+               sfputc(op, 0xC0 + (w >> 6));
+       else if (!(w & ~0xFFFF))
+       {
+               sfputc(op, 0xE0 + (w >> 12));
+               sfputc(op, 0x80 + (w >> 6 ) & 0x3F);
+       }
+       else
+               return sfputc(op, '?');
+       return sfputc(op, 0x80 + (w & 0x3F));
+}
+
+static int
+sfnext(Sfio_t* ip)
+{
+       register int    c;
+
+       while (isspace(c = sfgetc(ip)));
+       return c;
+}
+
+static void
+html2msg(register Sfio_t* ip, register Sfio_t* op, int flags)
+{
+       register int    c;
+       register int    q;
+
+ again:
+       while ((c = sfgetc(ip)) != EOF)
+               if (c == '<')
+               {
+                       if ((c = sfnext(ip)) == 'O' &&
+                           (c = sfnext(ip)) == 'L' &&
+                           isspace(c = sfgetc(ip)) &&
+                           (c = sfnext(ip)) == 'S' &&
+                           (c = sfnext(ip)) == 'T' &&
+                           (c = sfnext(ip)) == 'A' &&
+                           (c = sfnext(ip)) == 'R' &&
+                           (c = sfnext(ip)) == 'T' &&
+                           (c = sfnext(ip)) == '=' &&
+                           (c = sfnext(ip)) == '"' &&
+                           (c = sfnext(ip)) == '5' &&
+                           (c = sfnext(ip)) == '5' &&
+                           (c = sfnext(ip)) == '0' &&
+                           (c = sfnext(ip)) == '7' &&
+                           (c = sfnext(ip)) == '1' &&
+                           (c = sfnext(ip)) == '7' &&
+                           (c = sfnext(ip)) == '"' &&
+                           (c = sfnext(ip)) == '>')
+                               break;
+                       while (c != EOF && c != '>')
+                               c = sfgetc(ip);
+               }
+       if ((c = sfnext(ip)) != EOF)
+               sfungetc(ip, c);
+       q = 0;
+       for (;;)
+       {
+               switch (c = sfgetc(ip))
+               {
+               case EOF:
+                       break;
+               case '&':
+                       c = decode(ip);
+                       sfpututf(op, c);
+                       if (isspace(c))
+                       {
+                               while (isspace(c = sfgetc(ip)));
+                               if (c == EOF)
+                                       break;
+                               sfungetc(ip, c);
+                       }
+                       continue;
+               case '<':
+                       switch (c = sfnext(ip))
+                       {
+                       case '/':
+                               if ((c = sfnext(ip)) == 'O' &&
+                                   (c = sfgetc(ip)) == 'L' &&
+                                   (c = sfnext(ip)) == '>')
+                               {
+                                       if (q)
+                                       {
+                                               sfputc(op, q);
+                                               q = '"';
+                                       }
+                                       goto again;
+                               }
+                               break;
+                       case 'B':
+                               if ((c = sfgetc(ip)) == 'R' &&
+                                   (c = sfnext(ip)) == '>')
+                                       sfputc(op, ' ');
+                               break;
+                       case 'L':
+                               if ((c = sfgetc(ip)) == 'I' &&
+                                   (c = sfnext(ip)) == '>' &&
+                                    isdigit(c = sfnext(ip)))
+                               {
+                                       if (q)
+                                               sfputc(op, q);
+                                       else
+                                               q = '"';
+                                       sfputc(op, '\n');
+                                       do
+                                       {
+                                               sfputc(op, c);
+                                       } while (isdigit(c = sfgetc(ip)));
+                                       if (c == EOF)
+                                               break;
+                                       sfputc(op, ' ');
+                                       sfputc(op, '"');
+                                       if (isspace(c))
+                                               c = sfnext(ip);
+                                       if (c == '<' &&
+                                           (c = sfnext(ip)) == 'L' &&
+                                           (c = sfgetc(ip)) == 'I' &&
+                                           (c = sfnext(ip)) == '>')
+                                               /* great */;
+                                       continue;
+                               }
+                               break;
+                       case 'P':
+                               if ((c = sfnext(ip)) == '>')
+                                       sfputc(op, '\n');
+                               else if (c == 'C' &&
+                                        (c = sfgetc(ip)) == 'L' &&
+                                        (c = sfgetc(ip)) == 'A' &&
+                                        (c = sfgetc(ip)) == 'S' &&
+                                        (c = sfgetc(ip)) == 'S' &&
+                                        (c = sfnext(ip)) == '=' &&
+                                        (c = sfnext(ip)) == '"')
+                                       for (;;)
+                                       {
+                                               switch (c = sfgetc(ip))
+                                               {
+                                               case EOF:
+                                               case '"':
+                                                       break;
+                                               case '&':
+                                                       c = decode(ip);
+                                                       sfpututf(op, c);
+                                                       continue;
+                                               default:
+                                                       sfpututf(op, c);
+                                                       continue;
+                                               }
+                                               break;
+                                       }
+                               break;
+                       }
+                       while (c != EOF && c != '>')
+                               c = sfgetc(ip);
+                       if (c == EOF || (c = sfgetc(ip)) == EOF)
+                               break;
+                       sfungetc(ip, c);
+                       continue;
+               case '"':
+                       if (!flags)
+                               sfputc(op, '\\');
+                       sfputc(op, c);
+                       continue;
+               case '\n':
+                       if (flags)
+                       {
+                               sfputc(op, c);
+                               continue;
+                       }
+                       /*FALLTHROUGH*/
+               case ' ':
+               case '\t':
+                       while ((c = sfgetc(ip)) != EOF)
+                               if (c == '&')
+                               {
+                                       c = decode(ip);
+                                       if (!isspace(c))
+                                               sfputc(op, ' ');
+                                       sfpututf(op, c);
+                                       break;
+                               }
+                               else if (!isspace(c))
+                               {
+                                       if (c == '<')
+                                       {
+                                               c = sfgetc(ip);
+                                               if (c == EOF)
+                                                       break;
+                                               sfungetc(ip, c);
+                                               sfungetc(ip, '<');
+                                               if (c != 'L' && c != '/')
+                                                       sfputc(op, ' ');
+                                       }
+                                       else
+                                       {
+                                               if (c != EOF)
+                                                       sfungetc(ip, c);
+                                               sfputc(op, ' ');
+                                       }
+                                       break;
+                               }
+                       continue;
+               case '\r':
+               case '[':
+               case ']':
+                       continue;
+               default:
+                       sfpututf(op, c);
+                       continue;
+               }
+               break;
+       }
+       if (q)
+               sfputc(op, q);
+       sfputc(op, '\n');
+}
+
+static void
+encode(Sfio_t* op, register int c)
+{
+       if (c == '<')
+               sfprintf(op, "&lt;");
+       else if (c == '>')
+               sfprintf(op, "&gt;");
+       else if (c == '"')
+               sfprintf(op, "&quot;");
+       else if (c == '&')
+               sfprintf(op, "&amp;");
+       else if (c == '[')
+               sfprintf(op, "&#091;");
+       else if (c == ']')
+               sfprintf(op, "&#093;");
+       else
+               sfputc(op, c);
+}
+
+static void
+msg2html(register Sfio_t* ip, register Sfio_t* op, register int flags)
+{
+       register char*  s;
+       register int    c;
+       register int    q;
+       register int    p;
+
+       sfprintf(op, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 
4.0//EN\"><HTML><HEAD><!-- text massaged for external translation 
--></HEAD><BODY>\n");
+       sfprintf(op, "<OL START=\"550717\">\n");
+       p = q = 0;
+       while (s = sfgetr(ip, '\n', 1))
+       {
+               error_info.line++;
+               if (flags)
+                       sfprintf(op, "<P>");
+               else
+               {
+                       if (*s == '$')
+                       {
+                               if (p)
+                                       sfprintf(op, "<P>");
+                               else
+                                       p = 1;
+                               sfprintf(op, "<P CLASS=\"", s);
+                               while (c = *s++)
+                                       encode(op, c);
+                               sfprintf(op, "\">\n");
+                               continue;
+                       }
+                       p = 0;
+                       if (!isdigit(*s))
+                               continue;
+                       sfprintf(op, "<LI>");
+                       while (isdigit(c = *s++))
+                               sfputc(op, c);
+                       sfprintf(op, "<LI>");
+                       while (c && c != '"')
+                               c = *s++;
+                       if (!c)
+                               s--;
+                       else if (isspace(*s))
+                       {
+                               s++;
+                               sfprintf(op, "<BR>");
+                       }
+               }
+               for (;;)
+               {
+                       switch (c = *s++)
+                       {
+                       case 0:
+                               flags &= ~MSG_SPLICE;
+                               if (q)
+                               {
+                                       q = 0;
+                                       sfprintf(op, "\">");
+                               }
+                               sfputc(op, '\n');
+                               break;
+                       case '<':
+                               sfprintf(op, "&lt;");
+                               continue;
+                       case '>':
+                               sfprintf(op, "&gt;");
+                               continue;
+                       case '&':
+                               sfprintf(op, "&amp;");
+                               continue;
+                       case '[':
+                               sfprintf(op, "&#091;");
+                               continue;
+                       case ']':
+                               sfprintf(op, "&#093;");
+                               continue;
+                       case '$':
+                               if (!q)
+                               {
+                                       q = 1;
+                                       sfprintf(op, "<P CLASS=\"");
+                               }
+                               sfputc(op, c);
+                               while (isalnum(c = *s++))
+                                       sfputc(op, c);
+                               s--;
+                               continue;
+                       case '%':
+                               if (!q)
+                               {
+                                       q = 1;
+                                       sfprintf(op, "<P CLASS=\"");
+                               }
+                               sfputc(op, c);
+                               if (*s == '%')
+                                       sfputc(op, *s++);
+                               else
+                                       do
+                                       {
+                                               if (!(c = *s++) || c == '"')
+                                               {
+                                                       s--;
+                                                       break;
+                                               }
+                                               encode(op, c);
+                                       } while (!isalpha(c) || (!islower(c) || 
c == 'h' || c == 'l') && isalpha(*s));
+                               if (SPACE(s))
+                                       sfprintf(op, "&nbsp;");
+                               continue;
+                       case '"':
+                               if (!(flags & MSG_RAW))
+                               {
+                                       s = "";
+                                       continue;
+                               }
+                               /*FALLTHROUGH*/
+                       case '\'':
+                       case ':':
+                       case '/':
+                       case '+':
+                       case '@':
+                               if (!q)
+                               {
+                                       q = 1;
+                                       sfprintf(op, "<P CLASS=\"");
+                               }
+                               /*FALLTHROUGH*/
+                       case '.':
+                       case ',':
+                               sfputc(op, c);
+                               if (SPACE(s))
+                                       sfprintf(op, "&nbsp;");
+                               continue;
+                       case '\\':
+                               if (!(c = *s++))
+                               {
+                                       flags |= MSG_SPLICE;
+                                       break;
+                               }
+                               if (c != 'n' && c != 't')
+                               {
+                                       if (!q)
+                                       {
+                                               q = 1;
+                                               sfprintf(op, "<P CLASS=\"");
+                                       }
+                                       sfputc(op, '\\');
+                                       encode(op, c);
+                                       if (c == 'b')
+                                       {
+                                               for (;;)
+                                               {
+                                                       if (!(c = *s++) || c == 
'"')
+                                                       {
+                                                               s--;
+                                                               break;
+                                                       }
+                                                       if (c == '?')
+                                                       {
+                                                               if (*s != '?')
+                                                               {
+                                                                       s--;
+                                                                       break;
+                                                               }
+                                                               sfputc(op, c);
+                                                               sfputc(op, 
*s++);
+                                                               continue;
+                                                       }
+                                                       if (c == '\\')
+                                                       {
+                                                               if (!*s)
+                                                                       break;
+                                                               sfputc(op, c);
+                                                               if (*s == 'a' 
|| *s == 'b' || *s == '0')
+                                                               {
+                                                                       
sfputc(op, *s++);
+                                                                       break;
+                                                               }
+                                                               c = *s++;
+                                                       }
+                                                       encode(op, c);
+                                               }
+                                       }
+                                       else if (isdigit(c) && isdigit(*s))
+                                       {
+                                               sfputc(op, *s++);
+                                               if (isdigit(*s))
+                                                       sfputc(op, *s++);
+                                       }
+                                       if (SPACE(s))
+                                               sfprintf(op, "&nbsp;");
+                                       continue;
+                               }
+                               /*FALLTHROUGH*/
+                       case ' ':
+                       case '\t':
+                               while (isspace(*s) || *s == '\\' && (*(s + 1) 
== 'n' || *(s + 1) == 't') && s++)
+                                       s++;
+                               if (*s == '"')
+                               {
+                                       if (q)
+                                       {
+                                               q = 0;
+                                               sfprintf(op, " \">");
+                                       }
+                                       else
+                                               sfprintf(op, "<BR>");
+                                       continue;
+                               }
+                               c = ' ';
+                               /*FALLTHROUGH*/
+                       default:
+                               if (q)
+                               {
+                                       q = 0;
+                                       sfprintf(op, "\">");
+                               }
+                               sfputc(op, c);
+                               continue;
+                       }
+                       break;
+               }
+       }
+       sfprintf(op, "</OL>\n");
+       sfprintf(op, "</BODY></HTML>\n");
+       error_info.line = 0;
+}
+
+int
+main(int argc, char** argv)
+{
+       int             flags = 0;
+       Convert_f       convert = msg2html;
+
+       NoP(argc);
+       error_info.id = "msgcvt";
+       for (;;)
+       {
+               switch (optget(argv, usage))
+               {
+               case 'h':
+                       convert = msg2html;
+                       continue;
+               case 'm':
+                       convert = html2msg;
+                       continue;
+               case 'r':
+                       flags |= MSG_RAW;
+                       continue;
+               case '?':
+                       error(ERROR_USAGE|4, "%s", opt_info.arg);
+                       continue;
+               case ':':
+                       error(2, "%s", opt_info.arg);
+                       continue;
+               }
+               break;
+       }
+       argv += opt_info.index;
+       if (error_info.errors)
+               error(ERROR_USAGE|4, "%s", optusage(NiL));
+       (*convert)(sfstdin, sfstdout, flags);
+       return error_info.errors != 0;
+}
Index: src/cmd/ast/msgcc/msgcc.sh
===================================================================
--- src/cmd/ast/msgcc/msgcc.sh  (revision 0)
+++ src/cmd/ast/msgcc/msgcc.sh  (revision 0)
@@ -0,0 +1,405 @@
+########################################################################
+#                                                                      #
+#               This software is part of the ast package               #
+#           Copyright (c) 2000-2006 AT&T Knowledge Ventures            #
+#                      and is licensed under the                       #
+#                  Common Public License, Version 1.0                  #
+#                      by AT&T Knowledge Ventures                      #
+#                                                                      #
+#                A copy of the License is available at                 #
+#            http://www.opensource.org/licenses/cpl1.0.txt             #
+#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
+#                                                                      #
+#              Information and Software Systems Research               #
+#                            AT&T Research                             #
+#                           Florham Park NJ                            #
+#                                                                      #
+#                 Glenn Fowler <gsf at research.att.com>                  #
+#                                                                      #
+########################################################################
+: C language message catalog compiler
+
+# NOTE: all variable names match __*__ to avoid clash with msgcpp def vars
+
+__command__=msgcc
+integer __similar__=30
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123)  ARGV0="-a $__command__"
+       USAGE=$'
+[-?
+@(#)$Id: msgcc (AT&T Labs Research) 2002-09-15 $
+]
+'$USAGE_LICENSE$'
+[+NAME?msgcc - C language message catalog compiler]
+[+DESCRIPTION?\bmsgcc\b is a C language message catalog compiler. It accepts
+       \bcc\b(1) style options and arguments. A \bmsgcpp\b(1) \b.mso\b file
+       is generated for each input \b.c\b file. If the \b-c\b option is not
+       specified then a \bgencat\b(1) format \b.msg\b file is generated from
+       the input \b.mso\b and \b.msg\b files. If \b-c\b is not specified then
+       a \b.msg\b suffix is appended to the \b-o\b \afile\a if it doesn\'t
+       already have a suffix. The default output is \ba.out.msg\b if \b-c\b
+       and \b-o\b are not specified.]
+[+?If \b-M-new\b is not specified then messages are merged with those in the
+       pre-existing \b-o\b file.]
+[M?Set a \bmsgcc\b specific \aoption\a. \aoption\a may be:]:[-option]{
+       [+mkmsgs?The \b-o\b file is assumed to be in \bmkmsgs\b(1) format.]
+       [+new?Create a new \b-o\b file.]
+       [+preserve?Messages in the \b-o\b file that are not in new
+               \b.msg\b file arguments are preserved. The default is to
+               either reuse the message numbers with new message text that
+               is similar to the old or to delete the message text, leaving
+               an unused message number.]
+       [+set=\anumber\a?Set the message set number to \anumber\a. The default
+               is \b1\b.]
+       [+similar=\anumber\a?The message text similarity measure thresshold.
+               The similarity measure between \aold\a and \anew\a message
+               text is 
100*(2*gzip(\aold\a+\anew\a)/(gzip(\aold\a)+gzip(\anew\a))-1),
+               where gzip(\ax\a) is the size of text \ax\a when compressed by
+               \bgzip\b(1). The default threshhold is '$__similar__$'. A
+               threshhold of \b0\b turns off message replacement, but unused
+               old messages are still deleted. Use \b-M-preserve\b to preserve
+               all old messages.]
+       [+verbose?Trace similar message replacements on the standard error.]
+}
+
+file ...
+
+[+SEE ALSO?\bcc\b(1), \bcpp\b(1), \bgencat\b(1), \bmsggen\b(1),
+       \bmsgcpp\b(1), \bmsgcvt\b(1)]
+'
+       ;;
+*)     ARGV0=""
+       USAGE="M:[-option] [ cc-options ] file ..."
+       ;;
+esac
+
+usage()
+{
+       OPTIND=0
+       getopts $ARGV0 "$USAGE" OPT '-?'
+       exit 2
+}
+
+keys()
+{
+       $1 --??keys -- 2>&1 | grep '^".*"$'
+}
+
+typeset -A __index__
+typeset __keep__ __text__ __drop__ __oz__ __nz__ __z__ __hit__ __hit_i__
+typeset __compile__ __debug__ __mkmsgs__ __preprocess__
+typeset __merge__=1 __preserve__ __verbose__
+integer __i__=0 __args__=0 __code__=0 __files__=0 __max__=0 __num__=0 
__skip__=0
+integer __set__=1 __sources__=0 __cmds__=0 __ndrop__=0 __new__=0 __old__=0
+__out__=a.out.msg
+__OUT__=
+
+case " $* " in
+*" --"*|*" -?"*)
+       while   getopts $ARGV0 "$USAGE" OPT
+       do      case $OPT in
+               *)      break ;;
+               esac
+       done
+       ;;
+esac
+while  :
+do     case $# in
+       0)      break ;;
+       esac
+       __arg__=$1
+       case $__arg__ in
+       -c)     __compile__=1
+               ;;
+       -[DIU]*)__argv__[__args__]=$__arg__
+               (( __args__++ ))
+               ;;
+       -E)     __preprocess__=1
+               ;;
+       -M-debug)
+               __debug__=1
+               ;;
+       -M-mkmsgs)
+               __mkmsgs__=1
+               ;;
+       -M-new) __merge__=
+               ;;
+       -M-perserve)
+               __preserve__=1
+               ;;
+       -M-set=*)
+               __set__=$(msggen -s ${__arg__#*=}.1)
+               ;;
+       -M-similar=*)
+               __similar__=${__arg__#*=}
+               ;;
+       -M-verbose)
+               __verbose__=1
+               ;;
+       -o)     case $# in
+               1)      print -u2 $"$__command__: output argument expected"
+                       exit 1
+                       ;;
+               esac
+               shift
+               __out__=${1%.*}.msg
+               __OUT__=$1
+               ;;
+       [-+]*|*.[aAlLsS]*)
+               ;;
+       *.[cCiI]*|*.[oO]*)
+               case $__arg__ in
+               *.[oO]*);;
+               *)      __srcv__[__files__]=$__arg__
+                       (( __sources__++ ))
+                       ;;
+               esac
+               __arg__=${__arg__##*/}
+               __arg__=${__arg__%.*}.mso
+               __objv__[__files__]=$__arg__
+               (( __files__++ ))
+               ;;
+       *.ms[go])
+               __objv__[__files__]=$__arg__
+               (( __files__++ ))
+               ;;
+       *)      __cmdv__[__cmds__]=$__arg__
+               (( __cmds__++ ))
+               ;;
+       esac
+       shift
+done
+__cmdv__[__cmds__]=${__out__%.msg}
+(( __cmds__++ ))
+
+# generate the .mso files
+
+if     [[ $__OUT__ && $__compile__ ]]
+then   __objv__[0]=$__OUT__
+fi
+
+if     (( __sources__ ))
+then   for (( __i__=0; __i__<=__files__; __i__++ ))
+       do      if      [[ ${__srcv__[__i__]} ]]
+               then    if      (( __sources__ > 1 ))
+                       then    print "${__srcv__[__i__]}:"
+                       fi
+                       if      [[ $__preprocess__ ]]
+                       then    msgcpp "${__argv...@]}" "${__srcv__[__i__]}"
+                       else    msgcpp "${__argv...@]}" "${__srcv__[__i__]}" > 
"${__objv__[__i__]}"
+                       fi
+               fi
+       done
+fi
+
+# combine the .mso and .msg files
+
+if     [[ ! $__compile__ && ! $__preprocess__ ]]
+then   if      [[ $__merge__ && -r $__out__ ]]
+       then    __tmp__=$__out__.tmp
+               trap '__code__=$?; rm -f ${__tmp__}*; exit $__code__' 0 1 2
+               while   read -r __line__
+               do      if      (( $__skip__ ))
+                       then    if      [[ $__line__ == '%}'* ]]
+                               then    __skip__=0
+                               fi
+                               continue
+                       fi
+                       if      [[ $__mkmsgs__ && $__line__ == '%{'* ]]
+                       then    __skip__=1
+                               continue
+                       fi
+                       if      [[ $__mkmsgs__ ]]
+                       then    if      [[ $__line__ == '%#'*';;'* ]]
+                               then    __line__=${__line__#'%#'}
+                                       __num__=${__line__%';;'*}
+                                       read -r __line__
+                               elif    [[ $__line__ == %* ]]
+                               then    continue
+                               else    print -u2 $"$__command__: unrecognized 
line=$__line__"
+                                       __code__=1
+                               fi
+                       else    case $__line__ in
+                               +([0-9])' '*)
+                                       __num__=${__line__%%' '*}
+                                       __line__=${__line__#*'"'}
+                                       __line__=${__line__%'"'}
+                                       ;;
+                               *)      continue
+                                       ;;
+                               esac
+                       fi
+                       __index__["$__line__"]=$__num__
+                       __text__[$__num__]=$__line__
+                       if      (( __max__ < __num__ ))
+                       then    (( __max__=__num__ ))
+                       fi
+               done < $__out__
+               (( __new__=__max__+1 ))
+       else    __tmp__=$__out__
+               (( __new__=1 ))
+       fi
+       if      (( __code__ ))
+       then    exit $__code__
+       fi
+       exec 1>$__tmp__ 9>&1
+       print -r -- '$'" ${__out__%.msg} message catalog"
+       print -r -- '$translation'" $__command__ $(date -f %Y-%m-%d)"
+       print -r -- '$set'" $__set__"
+       print -r -- '$quote "'
+       sort -u "${__objv...@]}" | {
+               while   read -r __line__
+               do      __op__=${__line__%% *}
+                       __line__=${__line__#* }
+                       case $__op__ in
+                       cmd)    __a1__=${__line__%% *}
+                               case $__a1__ in
+                               dot_cmd)        __a1__=. ;;
+                               esac
+                               keys $__a1__
+                               ;;
+                       def)    __a1__=${__line__%% *}
+                               __a2__=${__line__#* }
+                               eval $__a1__='$'__a2__
+                               ;;
+                       str)    print -r -- "$__line__"
+                               ;;
+                       var)    __a1__=${__line__%% *}
+                               __a2__=${__line__#* }
+                               case $__a1__ in
+                               [[:digit:]]*)
+                                       eval __v__='$'$__a2__
+                                       __v__='"'${__v__:__a1__+1}
+                                       ;;
+                               *)      eval __v__='$'$__a1__
+                                       ;;
+                               esac
+                               if      [[ $__v__ == '"'*'"' ]]
+                               then    print -r -- "$__v__"
+                               fi
+                               ;;
+                       [[:digit:]]*)
+                               [[ $__preserve__ ]] && print -r -- "$__line__"
+                               ;;
+                       '$')    print -r -u9 $__op__ include $__line__
+                               ;;
+                       esac
+               done
+               for (( __i__=0; __i__ < __cmds__; __i__++ ))
+               do      keys ${__cmdv__[__i__]}
+               done
+       } | {
+               __num__=1
+               while   read -r __line__
+               do      case $__line__ in
+                       '$'[\ \ ]*)
+                               print -r -- "$__line__"
+                               continue
+                               ;;
+                       '$'*|*"@(#)"*|*"<"*([[:word:] .-])"@"*([[:word:] 
.-])">"*([     ])'"'|"http://"*)
+                               continue
+                               ;;
+                       *[[:alpha:]][[:alpha:]]*)
+                               __line__=${__line__#*'"'}
+                               __line__=${__line__%'"'}
+                               if      [[ $__line__ ]]
+                               then    if      [[ ${__index__["$__line__"]} ]]
+                                       then    if [[ ! $__preserve__ ]]
+                                               then    
__num__=${__index__["$__line__"]}
+                                                       __keep__[$__num__]=1
+                                               fi
+                                       else    while    [[ 
${__text__[$__num__]} ]]
+                                               do      (( __num__++ ))
+                                               done
+                                               if      (( __max__ < __num__ ))
+                                               then    (( __max__=__num__ ))
+                                               fi
+                                               if      [[ ! $__preserve__ ]]
+                                               then     __keep__[$__num__]=1
+                                               fi
+                                               __text__[$__num__]=$__line__
+                                               __index__["$__line__"]=$__num__
+                                               (( __num__++ ))
+                                       fi
+                               fi
+                               ;;
+                       esac
+               done
+               if      (( __max__ < __num__ ))
+               then    (( __max__=__num__ ))
+               fi
+               if [[ $__debug__ ]]
+               then    for (( __num__=1; __num__<=__max__; __num__++ ))
+                       do      if      [[ ${__text__[$__num__]} ]]
+                               then    if      (( __num__ > __new__ ))
+                                       then    if      [[ ! 
${__keep__[$__num__]} ]]
+                                               then    print -r -u2 -- 
$__num__ HUH '"'"${__text__[$__num__]}"'"'
+                                               else    print -r -u2 -- 
$__num__ NEW '"'"${__text__[$__num__]}"'"'
+                                               fi
+                                       elif    [[ ${__keep__[$__num__]} ]]
+                                       then    print -r -u2 -- $__num__ OLD 
'"'"${__text__[$__num__]}"'"'
+                                       else    print -r -u2 -- $__num__ XXX 
'"'"${__text__[$__num__]}"'"'
+                                       fi
+                               fi
+                       done
+                       exit 0
+               fi
+               # check for replacements
+               if      [[ ! $__preserve__ ]]
+               then    for (( __num__=1; __num__<__new__; __num__++ ))
+                       do      if      [[ ${__text__[$__num__]} && ! 
${__keep__[$__num__]} ]]
+                               then    (( __ndrop__++ ))
+                                       __drop__[__ndrop__]=$__num__
+                               fi
+                       done
+                       [[ $__verbose__ ]] && print -u2 $__command__: 
old:1-$((__new__-1)) new:$__new__-$__max__ drop $__ndrop__ add 
$((__max__-__new__+1))
+                       if      (( __ndrop__ ))
+                       then    for (( __i__=1; __i__<=__ndrop__; __i__++ ))
+                               do      (( __old__=${__drop__[$__i__]} ))
+                                       __oz__[__i__]=$(print -r -- 
"\"${__text__[$__old__]}\"" | gzip | wc -c)
+                               done
+                               for (( __num__=__new__; __num__<=__max__; 
__num__++ ))
+                               do      [[ ${__text__[$__num__]} ]] || continue
+                                       __nz__=$(print -r -- 
"\"${__text__[$__num__]}\"" | gzip | wc -c)
+                                       __hit__=0
+                                       (( __bz__=__similar__ ))
+                                       for (( __i__=1; __i__<=__ndrop__; 
__i__++ ))
+                                       do      if      (( 
__old__=${__drop__[$__i__]} ))
+                                               then    __z__=$(print -r -- 
"\"${__text__[$__old__]}\"""\"${__text__[$__num__]}\"" | gzip | wc -c)
+                                                       (( __z__ = (__z__ * 200 
/ (${__oz__[__i__]} + $__nz__)) - 100 ))
+                                                       if      (( __z__ < 
__bz__ ))
+                                                       then    (( __bz__=__z__ 
))
+                                                               (( 
__hit__=__old__ ))
+                                                               (( 
__hit_i__=__i__ ))
+                                                       fi
+                                               fi
+                                       done
+                                       if      (( __hit__ ))
+                                       then    [[ $__verbose__ ]] && print -u2 
$__command__: $__hit__ $__num__ $__bz__
+                                               
__text__[$__hit__]=${__text__[$__num__]}
+                                               __keep__[$__hit__]=1
+                                               __drop__[$__hit_i__]=0
+                                               __text__[$__num__]=
+                                               __keep__[$__num__]=
+                                       fi
+                               done
+                       fi
+               fi
+               # final output
+               for (( __num__=1; __num__<=__max__; __num__++ ))
+               do      if      [[ ${__text__[$__num__]} && ( $__preserve__ || 
${__keep__[$__num__]} ) ]]
+                       then    print -r -- $__num__ "\"${__text__[$__num__]}\""
+                       fi
+               done
+       }
+       if [[ $__tmp__ != $__out__ ]]
+       then    grep -v '^\$' $__tmp__ > ${__tmp__}n
+               [[ -f $__out__ ]] && grep -v '^\$' $__out__ > ${__tmp__}o
+               cmp -s ${__tmp__}n ${__tmp__}o || {
+                       [[ -f $__out__ ]] && mv $__out__ $__out__.old
+                       mv $__tmp__ $__out__
+               }
+       fi
+fi
+exit $__code__
Index: src/cmd/ast/msgcc/msgcc.tst
===================================================================
--- src/cmd/ast/msgcc/msgcc.tst (revision 0)
+++ src/cmd/ast/msgcc/msgcc.tst (revision 0)
@@ -0,0 +1,28 @@
+# regression tests for the msgcc utility
+
+TEST 01 'basics'
+       EXEC -c t.c
+               NOTE 'pp:allpossible'
+               INPUT t.c $'
+                       #include <foo-bar.h>
+                       void f(void)
+                       {
+                       #if 0
+                               error(1, "foo bar");
+                       #else
+                               errormsg(locale, 2, "%s: bar foo");
+                       #endif
+                       }
+               '
+               OUTPUT t.mso $'str "foo bar"\nstr "%s: bar foo"'
+               OUTPUT -
+       EXEC -Dfprintf=_STDIO_ -c t.c
+               NOTE 'ignore readonly redefinitions'
+               INPUT t.c $'
+                       #define stderr foo
+                       void f(void)
+                       {
+                               fprintf(stderr, "foo bar");
+                       }
+               '
+               OUTPUT t.mso $'str "foo bar"'
Index: src/cmd/ast/msgcc/msgget.c
===================================================================
--- src/cmd/ast/msgcc/msgget.c  (revision 0)
+++ src/cmd/ast/msgcc/msgget.c  (revision 0)
@@ -0,0 +1,109 @@
+/***********************************************************************
+*                                                                      *
+*               This software is part of the ast package               *
+*           Copyright (c) 2000-2006 AT&T Knowledge Ventures            *
+*                      and is licensed under the                       *
+*                  Common Public License, Version 1.0                  *
+*                      by AT&T Knowledge Ventures                      *
+*                                                                      *
+*                A copy of the License is available at                 *
+*            http://www.opensource.org/licenses/cpl1.0.txt             *
+*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
+*                                                                      *
+*              Information and Software Systems Research               *
+*                            AT&T Research                             *
+*                           Florham Park NJ                            *
+*                                                                      *
+*                 Glenn Fowler <gsf at research.att.com>                  *
+*                                                                      *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Labs Research
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: msgget (AT&T Labs Research) 2001-04-21 $\n]"
+USAGE_LICENSE
+"[+NAME?msgget - get a message from a message catalog]"
+"[+DESCRIPTION?\bmsgget\b gets the message corresponding to the parameters."
+"      If \alocale\a is \b-\b then the current locale is used. \acommand\a"
+"      may be specified for command specific messages. \acatalog\a specifies"
+"      the message catalog name. [\aset\a.]]\anumber\a identifies the message"
+"      by message \anumber\a and an optional message \aset\a; if specified as"
+"      \b-\b then the message set and number are determined by looking up"
+"      \atext\a in the corresponding \bC\b locale message catalog.]"
+
+"\n"
+"\nlocale [command:]catalog [set.]number [ text ]\n"
+"\n"
+
+"[+SEE ALSO?\biconv\b(1), \bmsgcc\b(1), \bmsggen\b(1)]"
+;
+
+#include <ast.h>
+#include <error.h>
+#include <mc.h>
+
+int
+main(int argc, char** argv)
+{
+       register Mc_t*  mc;
+       register char*  s;
+       char*           loc;
+       char*           cmd;
+       char*           cat;
+       char*           msg;
+       int             set;
+       int             num;
+       Sfio_t*         sp;
+       char            path[PATH_MAX];
+
+       NoP(argc);
+       error_info.id = "msgget";
+       for (;;)
+       {
+               switch (optget(argv, usage))
+               {
+               case '?':
+                       error(ERROR_USAGE|4, "%s", opt_info.arg);
+                       continue;
+               case ':':
+                       error(2, "%s", opt_info.arg);
+                       continue;
+               }
+               break;
+       }
+       argv += opt_info.index;
+       if (error_info.errors || !(loc = *argv++) || !(cmd = *argv++) || !(s = 
*argv++))
+               error(ERROR_USAGE|4, "%s", optusage(NiL));
+       if (streq(s, "-"))
+               set = num = 0;
+       else
+               mcindex(s, NiL, &set, &num);
+       if (!(msg = *argv++))
+               msg = "";
+       else if (*argv)
+               error(ERROR_USAGE|4, "%s", optusage(NiL));
+       if (streq(loc, "-"))
+               loc = 0;
+       if (cat = strchr(cmd, ':'))
+               *cat++ = 0;
+       if (!mcfind(path, loc, cmd, LC_MESSAGES, 0) && (!cat || !mcfind(path, 
loc, cat, LC_MESSAGES, 0)))
+       {
+               if (cat)
+                       *--cat = ':';
+               error(3, "%s: cannot locate message catalog", cmd);
+       }
+       if (!(sp = sfopen(NiL, path, "r")))
+               error(ERROR_SYSTEM|3, "%s: cannot read message catalog", path);
+       if (!(mc = mcopen(sp)))
+               error(3, "%s: invalid message catalog", path);
+       if (set)
+               s = mcget(mc, set, num, msg);
+       else
+               s = errorx(loc, cmd, cat, msg);
+       sfputr(sfstdout, s, '\n');
+       return error_info.errors != 0;
+}
Index: src/cmd/ast/msgcc/NOTES
===================================================================
--- src/cmd/ast/msgcc/NOTES     (revision 0)
+++ src/cmd/ast/msgcc/NOTES     (revision 0)
@@ -0,0 +1,65 @@
+2000-04-01 ast message catalog plan
+
+(1) error_info.dictionary should be error_info.catalog
+    to match xopen and the internal naming in our implementation
+    and also to more closely match the webster definition
+    (catalog == enumerated list)
+
+    DONE
+
+(2) nmake by default will
+       CATALOG = 
$(ID:N=+([A-Za-z0-9_]):?$(PWD:N=*/lib/*:Y,lib,,)$(ID)?$(PWD:B)?)
+       ERROR_CATALOG == "$(CATALOG)"
+    e.g., commands in src/cmd/std will use the "std" catalog; all of the
+    commands in src/lib/libcmd will use the "libcmd" catalog
+
+    nmake will add "[--catalog?$(CATALOG)]" to USAGE_LICENSE
+    optget() will set error_info.catalog if not defined on the first call
+    commands that don't emit messages before optget() need not change
+    otherwise the command should
+
+       error_info.id = "foo";
+       error_info.catalog = ERROR_CATALOG;
+
+    undefined references to { USAGE_LICENSE ERROR_CATALOG } are hard
+    compile time errors
+
+    DONE
+
+(3) add catalog argument to libcmd <cmd.h> cmdinit(argv, context, catalog)
+
+    DONE
+
+(4) msgcat global target build msgs/*.mso and $(CATALOG).msg
+    each Makefile will generate one catalog $(CATALOG).msg where
+
+    the *.msg files are weird -- we need to build them viewed over an
+    architecture specific tree, even though they will be eventually used
+    as architecture independent source
+
+    $(CATALOG).msg will be the "C" locale
+
+    debug will be a debugging locale that will translate each message to
+       (CATALOG-NAME:MESSAGE-INDEX)\n
+    this will make it easy to locate text that escaped translation (in what
+    should be translated output); it will also be a way for us to do
+    regression tests in the face of typo fixes -- presumably typos can be
+    fixed without changing the message index
+
+    see msgadmin(1)
+
+    DONE
+
+(5) once all this is working I'll do catopen(3) and msggen(1)
+
+    DONE
+
+(6) the makerules "all" action will
+       catgen $(CATALOG).cat
+       catgen $(CATALOG)-*.cat
+    and the makerules "install" action will copy the catgen output to
+       $(LOCALEDIR)/$(LOCALE)/LC_MESSAGES/$(CATALOG)*
+    where
+       LOCALEDIR = $(INSTALLROOT)/lib/locale
+
+    NOTE: still under consideration
Index: src/cmd/ast/msgcc/msgadmin.sh
===================================================================
--- src/cmd/ast/msgcc/msgadmin.sh       (revision 0)
+++ src/cmd/ast/msgcc/msgadmin.sh       (revision 0)
@@ -0,0 +1,180 @@
+########################################################################
+#                                                                      #
+#               This software is part of the ast package               #
+#           Copyright (c) 2000-2006 AT&T Knowledge Ventures            #
+#                      and is licensed under the                       #
+#                  Common Public License, Version 1.0                  #
+#                      by AT&T Knowledge Ventures                      #
+#                                                                      #
+#                A copy of the License is available at                 #
+#            http://www.opensource.org/licenses/cpl1.0.txt             #
+#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
+#                                                                      #
+#              Information and Software Systems Research               #
+#                            AT&T Research                             #
+#                           Florham Park NJ                            #
+#                                                                      #
+#                 Glenn Fowler <gsf at research.att.com>                  #
+#                                                                      #
+########################################################################
+: message catalog administration
+
+command=msgadmin
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123)  ARGV0="-a $command"
+       USAGE=$'
+[-?
+@(#)$Id: msgadmin (AT&T Labs Research) 2001-06-08 $
+]
+'$USAGE_LICENSE$'
+[+NAME?'$command$' - message catalog file administration]
+[+DESCRIPTION?\b'$command$'\b administers message catalog files. If no \afile\a
+       operands are specified then all message files in the local
+       \b$INSTALLROOT\b source tree are operated on. Exaclty one of
+       \b--generate\b, \b--remove\b, \b--translate\b, or \b--verify\b
+       must be specified.]
+[D:debug?Passed to \btranslate\b(1).]
+[a:all?Passed to \btranslate\b(1).]
+[c:cache?Passed to \btranslate\b(1).]
+[d:dialect?Operate on the dialects in the \b,\b separated \adialect\a list.
+       \b-\b means all dialects supported by \btranslate\b(1).]:[dialect:=-]
+[f:force?Force binary catalog generation even when the current binary is newer
+       than the source.]
+[g:generate?Generate and install \bgencat\b(1) binary message catalogs.]
+[l:list?List each installed message catalog name paired with its input source.]
+[n:show?Show commands but do not execute.]
+[o:omit?Omit \btranslate\b(1) methods matching the \bksh\b(1)
+       \apattern\a.]:[pattern]
+[r:remove?Remove all translated message files and work directories.]
+[s:share?Generate and install \bmsggen\b(1) machine independent binary
+       message catalogs.]
+[t:translate?Translate using \btranslate\b(1).]
+[v:verify?Verify that translated message files satisfy \bgencat\b(1) syntax.]
+
+[ file ... ]
+
+[+SEE ALSO?\bgencat\b(1), \bksh\b(1), \bmsggen\b(1), \btranslate\b(1)]
+'
+       ;;
+*)     ARGV0=""
+       USAGE="Dcd:gno:rstv [ file ... ]"
+       ;;
+esac
+
+usage()
+{
+       OPTIND=0
+       getopts $ARGV0 "$USAGE" OPT '-?'
+       exit 2
+}
+
+messages()
+{
+       if      [[ $PACKAGEROOT && -d $PACKAGEROOT ]]
+       then    MSGROOT=$PACKAGEROOT
+       else    MSGROOT=$HOME
+       fi
+       set -- $MSGROOT/arch/*/src/cmd/INIT/INIT.msg
+       [[ -f $1 ]] || { print -u2 $"$command: INIT.msg: not found"; exit 1; }
+       MSGROOT=${1%/src/cmd/INIT/INIT.msg}
+       grep -l '^1' $MSGROOT/src/@(cmd|lib)/*/*.msg
+}
+
+integer n
+typeset all cache dialect=- exec force omit op show verbose
+typeset dir=$INSTALLROOT gen=gencat
+
+while  getopts $ARGV0 "$USAGE" OPT
+do     case $OPT in
+       D)      debug=-D ;;
+       a)      all=-a ;;
+       c)      cache=-c ;;
+       d)      dialect=$OPTARG ;;
+       f)      force=1 ;;
+       g)      op=generate ;;
+       l)      op=list ;;
+       n)      exec=print show=-n ;;
+       o)      omit="-o $OPTARG" ;;
+       r)      op=remove ;;
+       s)      gen=msggen dir=$dir/share ;;
+       t)      op=translate ;;
+       v)      op=verify ;;
+       *)      usage ;;
+       esac
+done
+shift $OPTIND-1
+
+[[ $INSTALLROOT ]] || { print -u2 $"$command: INSTALLROOT not defined"; exit 
1; }
+
+case $op in
+
+generate)
+       dir=$dir/lib/locale
+       [[ -d $dir ]] || { print -u2 $"$command: $dir: not found"; exit 1; }
+       (( ! $# )) && set -- C $(ls *-*.msg 2>/dev/null | sed 
's,.*-\(.*\)\.msg,\1,' | sort -u)
+       owd=$PWD
+       for locale
+       do      case $locale in
+               C)      set -- $(messages) ;;
+               *)      set -- *-$locale.msg ;;
+               esac
+               if      [[ ! -f $1 ]]
+               then    print -u2 "$command: $locale: no message files"
+               else    nwd=$dir/$locale/LC_MESSAGES
+                       [[ -d $nwd ]] || $exec mkdir -p $nwd || exit
+                       [[ -d $nwd ]] && { cd $nwd || exit; }
+                       for file
+                       do      case $file in
+                               /*)     name=${file##*/}
+                                       name=${name%*.msg}
+                                       ;;
+                               *)      name=${file%-$locale.msg}
+                                       file=$owd/$file
+                                       ;;
+                               esac
+                               if      [[ $force || ! $name -nt $file ]]
+                               then    print -u2 $locale $name:
+                                       $exec rm -f $name $name.*
+                                       $exec $gen $name $file
+                               fi
+                       done
+                       cd $owd
+               fi
+       done
+       ;;
+
+list)  messages | sed 's,^.*/\(.*\)\.msg$,\1 &,'
+       ;;
+
+remove)        (( !$# )) && set -- *.msg translate.tmp
+       $exec rm -rf "$@"
+       ;;
+
+translate)
+       (( !$# )) && set -- $(messages)
+       translate -lmv $all $cache $debug $omit $show $dialect "$@"
+       ;;
+
+verify)        (( ! $# )) && set -- *.msg
+       for file
+       do      n=0
+               while   read -r num txt
+               do      if      [[ $num == +([0-9]) ]]
+                       then    ((n++))
+                               if      [[ $n != $num ]]
+                               then    if      (( n == $num-1 ))
+                                       then    print -u2 "$file: [$n] missing"
+                                       else    print -u2 "$file: 
[$n-$(($num-1))] missing"
+                                       fi
+                                       n=$num
+                               fi
+                       fi
+               done < $file
+       done
+       ;;
+
+*)     usage
+       ;;
+
+esac
Index: src/cmd/ast/msgcc/msgcpp.c
===================================================================
--- src/cmd/ast/msgcc/msgcpp.c  (revision 0)
+++ src/cmd/ast/msgcc/msgcpp.c  (revision 0)
@@ -0,0 +1,287 @@
+/***********************************************************************
+*                                                                      *
+*               This software is part of the ast package               *
+*           Copyright (c) 2000-2006 AT&T Knowledge Ventures            *
+*                      and is licensed under the                       *
+*                  Common Public License, Version 1.0                  *
+*                      by AT&T Knowledge Ventures                      *
+*                                                                      *
+*                A copy of the License is available at                 *
+*            http://www.opensource.org/licenses/cpl1.0.txt             *
+*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
+*                                                                      *
+*              Information and Software Systems Research               *
+*                            AT&T Research                             *
+*                           Florham Park NJ                            *
+*                                                                      *
+*                 Glenn Fowler <gsf at research.att.com>                  *
+*                                                                      *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * C message catalog preprocessor
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: msgcpp (AT&T Labs Research) 2002-03-11 $\n]"
+USAGE_LICENSE
+"[+NAME?msgcpp - C language message catalog preprocessor]"
+"[+DESCRIPTION?\bmsgcpp\b is a C language message catalog preprocessor."
+"      It accepts \bcpp\b(1) style options and arguments. \bmsgcpp\b"
+"      preprocesses an input C source file and emits keyed lines to the"
+"      output, usually for further processing by \bmsgcc\b(1). \bmsgcc\b"
+"      output is in the \bgencat\b(1) syntax. Candidate message text is"
+"      determined by arguments to the \bast\b \b<error.h>\b and"
+"      \b<option.h>\b functions. The \bmsgcpp\b keyed output lines are:]{"
+"      [+cmd \acommand\a?\acommand\a is a candidate for \b--??keys\b"
+"              option string generation. Triggered by"
+"              \bb_\b\acommand\a\b(int argc,\b in the input.]"
+"      [+def \aname\a \astring\a?\aname\a is a candidate variable with"
+"              string value \astring\a.]"
+"      [+str \astring\a?\astring\a should be entered into the catalog.]"
+"      [+var \aname\a?If \bdef\b \aname\a occurs then its \astring\a value"
+"              should be entered into the catalog.]"
+"      }"
+"[+?The input source file is preprocessed with the \bpp:allpossible\b"
+"      option on. This enables non-C semantics; all source should first"
+"      be compiled error-free with a real compiler before running \bmsgcpp\b."
+"      The following changes are enabled for the top level files (i.e.,"
+"      included file behavior is not affected):]{"
+"              [+(1)?All \b#if\b, \b#ifdef\b and \b#ifndef\b branches"
+"                      are enabled.]"
+"              [+(2)?The first definition for a macro is retained, even when"
+"                      subsequent \b#define\b statements would normally"
+"                      redefine the macro. \b#undef\b must be used to"
+"                      redefine a macro.]"
+"              [+(3)?Macro calls with an improper number of arguments are"
+"                      silently ignored.]"
+"              [+(4)?\b#include\b on non-existent headers are silently"
+"                      ignored.]"
+"              [+(5)?Invalid C source characters are silently ignored.]"
+"      }"
+"[+?\b\"msgcat.h\"\b is included if it exists. This file may contain macro"
+"      definitions for functions that translate string arguments. If \afoo\a"
+"      is a function that translates its string arguments then include the"
+"      line \b#define \b\afoo\a\b _TRANSLATE_\b in \bmsgcat.h\b or specify"
+"      the option \b-D\b\afoo\a\b=_TRANSLATE_\b. If \abar\a is a function"
+"      that translates string arguments if the first argument is \bstderr\b"
+"      then use either \b#define \b\abar\a\b _STDIO_\b or"
+"      \b-D\b\abar\a\b=_STDIO_\b.]"
+"[+?The macro \b_BLD_msgcat\b is defined to be \b1\b. As an alternative to"
+"      \bmsgcat.h\b, \b_TRANSLATE_\b definitions could be placed inside"
+"      \b#ifdef _BLD_msgcat\b ... \b#endif\b.]"
+
+"\n"
+"\n[ input [ output ] ]\n"
+"\n"
+
+"[+SEE ALSO?\bcc\b(1), \bcpp\b(1), \bgencat\b(1), \bmsggen\b(1),"
+"      \bmsgcc\b(1), \bmsgcvt\b(1)]"
+;
+
+#include <ast.h>
+#include <error.h>
+
+#include "pp.h"
+#include "ppkey.h"
+
+#define T_STDERR       (T_KEYWORD+1)
+#define T_STDIO                (T_KEYWORD+2)
+#define T_TRANSLATE    (T_KEYWORD+3)
+
+#define OMIT           "*@(\\[[-+]*\\?*\\]|\...@\\(#\\)|Copyright 
\\(c\\)|\\\\000|\\\\00[!0-9]|\\\\0[!0-9])*"
+
+static struct ppkeyword        keys[] =
+{
+       "char",         T_CHAR,
+       "int",          T_INT,
+       "sfstderr",     T_STDERR,
+       "stderr",       T_STDERR,
+       "_STDIO_",      T_STDIO,
+       "_TRANSLATE_",  T_TRANSLATE,
+       0,              0
+};
+
+static int
+msgppargs(char** argv, int last)
+{
+       for (;;)
+       {
+               switch (optget(argv, usage))
+               {
+               case 0:
+                       break;
+               case '?':
+                       if (!last)
+                       {
+                               opt_info.again = 1;
+                               return 1;
+                       }
+                       error(ERROR_USAGE|4, "%s", opt_info.arg);
+                       break;
+               case ':':
+                       if (!last)
+                       {
+                               opt_info.again = 1;
+                               return 1;
+                       }
+                       error(2, "%s", opt_info.arg);
+                       continue;
+               default:
+                       if (!last)
+                       {
+                               opt_info.again = 1;
+                               return 1;
+                       }
+                       continue;
+               }
+               break;
+       }
+       return argv[opt_info.index] != 0;
+}
+
+int
+main(int argc, char** argv)
+{
+       register char*  s;
+       register int    x;
+       register int    c;
+       Sfio_t*         tmp;
+
+       NoP(argc);
+       if (s = strrchr(*argv, '/'))
+               s++;
+       else
+               s = *argv;
+       error_info.id = s;
+       ppop(PP_DEFAULT, PPDEFAULT);
+       optjoin(argv, msgppargs, ppargs, NiL);
+       if (strlen(s) >= 5 && *(s + 3) != 'c')
+       {
+               ppop(PP_PLUSPLUS, 1);
+               ppop(PP_NOHASH, 1);
+               ppop(PP_PROBE, "CC");
+       }
+       ppop(PP_SPACEOUT, 0);
+       ppop(PP_COMPILE, keys);
+       ppop(PP_OPTION, "allpossible");
+       ppop(PP_OPTION, "catliteral");
+       ppop(PP_OPTION, "modern");
+       ppop(PP_OPTION, "readonly");
+       ppop(PP_DEFINE, "_BLD_msgcat=1");
+       ppop(PP_DEFINE, "const=");
+       ppop(PP_DEFINE, "errorf=_TRANSLATE_");
+       ppop(PP_DEFINE, "register=");
+       ppop(PP_DEFINE, "sfstderr=sfstderr");
+       ppop(PP_DEFINE, "stderr=stderr");
+       ppop(PP_DEFINE, "_(m)=_TRANSLATE_(m)");
+       ppop(PP_DEFINE, "__(m)=_TRANSLATE_(m)");
+       ppop(PP_DEFINE, "gettxt(i,m)=_TRANSLATE_(m)");
+       ppop(PP_DEFINE, "gettext(m)=_TRANSLATE_(m)");
+       ppop(PP_DEFINE, "dgettext(d,m)=_TRANSLATE_(m)");
+       ppop(PP_DEFINE, "dcgettext(d,m,c)=_TRANSLATE_(m)");
+       ppop(PP_DEFINE, "ERROR_catalog(m)=_TRANSLATE_(m)");
+       ppop(PP_DEFINE, "ERROR_dictionary(m)=_TRANSLATE_(m)");
+       ppop(PP_DEFINE, "ERROR_translate(l,i,c,m)=_TRANSLATE_(m)");
+       ppop(PP_DEFINE, "error(l,f,...)=_TRANSLATE_(f)");
+       ppop(PP_DEFINE, "errormsg(t,l,f,...)=_TRANSLATE_(f)");
+       ppop(PP_DIRECTIVE, "include \"msgcat.h\"");
+       ppop(PP_OPTION, "noreadonly");
+       ppop(PP_INIT);
+       if (!(tmp = sfstropen()))
+               error(ERROR_SYSTEM|3, "out of space");
+       x = 0;
+       for (;;)
+       {
+               c = pplex();
+       again:
+               switch (c)
+               {
+               case 0:
+                       break;
+               case T_TRANSLATE:
+                       switch (c = pplex())
+                       {
+                       case '(':
+                               x = 1;
+                               break;
+                       case ')':
+                               if ((c = pplex()) != '(')
+                               {
+                                       x = 0;
+                                       goto again;
+                               }
+                               x = 1;
+                               break;
+                       default:
+                               x = 0;
+                               goto again;
+                       }
+                       continue;
+               case '(':
+                       if (x > 0)
+                               x++;
+                       continue;
+               case ')':
+                       if (x > 0)
+                               x--;
+                       continue;
+               case T_STDIO:
+                       if ((c = pplex()) != '(' || (c = pplex()) != T_STDERR 
|| (c = pplex()) != ',')
+                       {
+                               x = 0;
+                               goto again;
+                       }
+                       x = 1;
+                       continue;
+               case T_STRING:
+                       if (x > 0 && !strmatch(pp.token, OMIT))
+                               sfprintf(sfstdout, "str \"%s\"\n", pp.token);
+                       continue;
+               case T_ID:
+                       s = pp.symbol->name;
+                       if (x > 0)
+                       {
+                               if ((c = pplex()) == '+' && ppisinteger(c = 
pplex()))
+                                       sfprintf(sfstdout, "var %s %s\n", 
pp.token, s);
+                               else
+                                       sfprintf(sfstdout, "var %s\n", s);
+                       }
+                       else if (s[0] == 'b' && s[1] == '_' && s[2])
+                       {
+                               if ((c = pplex()) == '(' && (c = pplex()) == 
T_INT && (c = pplex()) == T_ID && (c = pplex()) == ',' && (c = pplex()) == 
T_CHAR && (c = pplex()) == '*')
+                                       sfprintf(sfstdout, "cmd %s\n", s + 2);
+                               else
+                                       goto again;
+                       }
+                       else
+                       {
+                               if ((c = pplex()) == '[')
+                               {
+                                       if (ppisinteger(c = pplex()))
+                                               c = pplex();
+                                       if (c != ']')
+                                               goto again;
+                                       c = pplex();
+                               }
+                               if (c == '=' && (c = pplex()) == T_STRING && 
!strmatch(pp.token, OMIT))
+                               {
+                                       sfprintf(sfstdout, "def %s \"%s\"\n", 
s, pp.token);
+                                       sfprintf(tmp, "#define %s \"%s\"\n", s, 
pp.token);
+                                       ppinput(sfstruse(tmp), "string", 0);
+                               }
+                               else
+                                       goto again;
+                       }
+                       continue;
+               default:
+                       continue;
+               }
+               break;
+       }
+       ppop(PP_DONE);
+       return error_info.errors != 0;
+}
Index: src/cmd/ast/msgcc/Makefile
===================================================================
--- src/cmd/ast/msgcc/Makefile  (revision 0)
+++ src/cmd/ast/msgcc/Makefile  (revision 0)
@@ -0,0 +1,88 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident        "@(#)Makefile   1.1     2006/04/25 SMI"
+#
+# cmd/ast/msgcc/Makefile
+#
+
+PROG= msgcc
+
+include ../../Makefile.cmd
+
+CPPFLAGS = \
+       -I/home/test001/ksh93/localetest/build/arch/sol11.i386/include/ast \
+       -D_PACKAGE_ast \
+       '-DUSAGE_LICENSE="[-author?Glenn Fowler <gsf at 
research.att.com>][-copyright?Copyright (c) 2000-2006 AT&T Knowledge 
Ventures][-license?http://www.opensource.org/licenses/cpl1.0.txt][--catalog?msgcc]";'
+
+
+msgcvt.o: msgcvt.c
+msgcvt: msgcvt.o
+       $(LINK.c) $(CPPFLAGS) -o $@ $(@).o 
-L/home/test001/ksh93/localetest/build/arch/sol11.i386/lib -Bstatic -lpp -last 
-Bdynamic -lm
+       $(POST_PROCESS)
+       
+msggen.o: msggen.c
+msggen: msggen.o
+       $(LINK.c) $(CPPFLAGS) -o $@ $(@).o 
-L/home/test001/ksh93/localetest/build/arch/sol11.i386/lib -Bstatic -lpp -last 
-Bdynamic -lm
+       $(POST_PROCESS)
+       
+msgget.o: msgget.c
+msgget: msgget.o
+       $(LINK.c) $(CPPFLAGS) -o $@ $(@).o 
-L/home/test001/ksh93/localetest/build/arch/sol11.i386/lib -Bstatic -lpp -last 
-Bdynamic -lm
+       $(POST_PROCESS)
+
+msgcpp.o: msgcpp.c
+msgcpp: msgcpp.o
+       $(LINK.c) $(CPPFLAGS) -o $@ $(@).o 
-L/home/test001/ksh93/localetest/build/arch/sol11.i386/lib -Bstatic -lpp -last 
-Bdynamic -lm
+       $(POST_PROCESS)
+
+msgcc: msgcc.sh
+       $(RM) msgcc
+       ( \
+               printf "builtin date\n" ; \
+               cat msgcc.sh ; \
+       ) >msgcc
+       chmod a+rx msgcc
+
+msgadmin: msgadmin.sh
+       $(RM) msgadmin
+       cat msgadmin.sh >msgadmin
+       chmod a+rx msgadmin
+       
+.KEEP_STATE:
+
+all: msgcvt msggen msgget msgcpp msgcc msgadmin
+
+install: all
+
+clean:
+
+lint:
+
+
+
+include ../../Makefile.targ
+
+# EOF.
Index: src/cmd/ast/Makefile
===================================================================
--- src/cmd/ast/Makefile        (revision 0)
+++ src/cmd/ast/Makefile        (revision 0)
@@ -0,0 +1,56 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident        "@(#)Makefile   1.1     2006/04/25 SMI"
+#
+# cmd/ast/Makefile
+#
+
+include ../Makefile.cmd
+
+SUBDIRS= \
+       msgcc
+
+all     :=      TARGET = all
+install :=      TARGET = install
+clean   :=      TARGET = clean
+clobber :=      TARGET = clobber
+lint    :=      TARGET = lint
+
+.KEEP_STATE:
+
+all clean clobber lint: $(SUBDIRS)
+
+install:        $(SUBDIRS)
+
+$(SUBDIRS):     FRC
+       @cd $@; pwd; $(MAKE) $(TARGET)
+
+
+FRC:
+
+include ../Makefile.targ
+
+# EOF.
Index: src/lib/libshell/Makefile.com
===================================================================
--- src/lib/libshell/Makefile.com       (revision 387)
+++ src/lib/libshell/Makefile.com       (working copy)
@@ -108,6 +108,8 @@
        $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
        $(POST_PROCESS_O)
 
+include ../../libast/Makefile.libastl10n
+
 include ../../Makefile.lib
 include ../../Makefile.rootfs
 
Index: src/lib/libshell/Makefile
===================================================================
--- src/lib/libshell/Makefile   (revision 387)
+++ src/lib/libshell/Makefile   (working copy)
@@ -48,9 +48,6 @@
 lint: $(SUBDIRS)
 
 LIBRARY=       libshell.a
-XGETFLAGS=     -a
-POFILE=                $(LIBRARY:.a=.po)
-POFILES=       generic.po
 
 # definitions for install_h target
 HDRS= \
@@ -68,20 +65,9 @@
 spec $(SUBDIRS):       FRC
        @cd $@; pwd; $(MAKE) $(TARGET)
 
-_msg:  $(MSGDOMAIN) $(POFILE)
-       $(RM) $(MSGDOMAIN)/$(POFILE)
-       $(CP) $(POFILE) $(MSGDOMAIN)
+_msg: $(MACH)
+       @cd $(MACH); pwd; $(MAKE) _msg
 
-$(POFILE):     $(POFILES)
-       $(RM) $@
-       $(CAT) $(POFILES) > $@
-
-$(POFILES):
-       $(RM) messages.po
-       $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]*
-       $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
-       $(RM) messages.po
-
 FRC:
 
 # rules to install demo files in $(ROOT)/usr/demo/ksh/
Index: src/lib/libcmd/Makefile.com
===================================================================
--- src/lib/libcmd/Makefile.com (revision 387)
+++ src/lib/libcmd/Makefile.com (working copy)
@@ -71,6 +71,7 @@
        wc.o \
        wclib.o
 
+include ../../libast/Makefile.libastl10n
 
 include ../../Makefile.lib
 include ../../Makefile.rootfs
Index: src/lib/libcmd/Makefile
===================================================================
--- src/lib/libcmd/Makefile     (revision 387)
+++ src/lib/libcmd/Makefile     (working copy)
@@ -63,6 +63,9 @@
 $(SUBDIRS) spec: FRC
        @cd $@; pwd; $(MAKE) $(TARGET)
 
+_msg: $(MACH)
+       @cd $(MACH); pwd; $(MAKE) _msg
+
 FRC:
 
 include ../Makefile.targ
Index: src/lib/Makefile
===================================================================
--- src/lib/Makefile    (revision 387)
+++ src/lib/Makefile    (working copy)
@@ -252,11 +252,14 @@
        gss_mechs/mech_dh       \
        gss_mechs/mech_krb5     \
        krb5            \
+       libast          \
        libbsm          \
        libc            \
        libcfgadm       \
+       libcmd          \
        libcontract     \
        libcurses       \
+       libdll          \
        libdhcpsvc      \
        libdhcputil     \
        libgss          \
@@ -268,6 +271,7 @@
        libpool         \
        libscf          \
        libsasl         \
+       libshell        \
        libldap5        \
        libsecdb        \
        libsldap        \
Index: src/lib/libdll/Makefile.com
===================================================================
--- src/lib/libdll/Makefile.com (revision 387)
+++ src/lib/libdll/Makefile.com (working copy)
@@ -42,6 +42,8 @@
 
 OBJECTS= $(COBJS)
 
+include ../../libast/Makefile.libastl10n
+
 include ../../Makefile.lib
 include ../../Makefile.rootfs
 
Index: src/lib/libdll/Makefile
===================================================================
--- src/lib/libdll/Makefile     (revision 387)
+++ src/lib/libdll/Makefile     (working copy)
@@ -48,9 +48,6 @@
 lint: $(SUBDIRS)
 
 LIBRARY=       libdll.a
-XGETFLAGS=     -a
-POFILE=                $(LIBRARY:.a=.po)
-POFILES=       generic.po
 
 # definitions for install_h target
 HDRS= \
@@ -67,20 +64,9 @@
 spec $(SUBDIRS):       FRC
        @cd $@; pwd; $(MAKE) $(TARGET)
 
-_msg:  $(MSGDOMAIN) $(POFILE)
-       $(RM) $(MSGDOMAIN)/$(POFILE)
-       $(CP) $(POFILE) $(MSGDOMAIN)
+_msg: $(MACH)
+       @cd $(MACH); pwd; $(MAKE) _msg
 
-$(POFILE):     $(POFILES)
-       $(RM) $@
-       $(CAT) $(POFILES) > $@
-
-$(POFILES):
-       $(RM) messages.po
-       $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]*
-       $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
-       $(RM) messages.po
-
 FRC:
 
 include ../Makefile.targ
Index: src/lib/libast/Makefile.libastl10n
===================================================================
--- src/lib/libast/Makefile.libastl10n  (revision 0)
+++ src/lib/libast/Makefile.libastl10n  (revision 0)
@@ -0,0 +1,56 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident        "@(#)Makefile.com       1.1     2006/04/25 SMI"
+#
+# lib/libast/Makefile.astl10n
+#
+
+#
+# l10n mesage catalog generation for AST libraries
+#
+
+# l10n mesage catalog generation
+MSGLIBNAME= $(LIBRARY:.a=)
+ASTMSGCATALOG= $(ROOT)/usr/lib/locale/C/LC_MESSAGES/$(MSGLIBNAME)
+ASTMSGCC= PATH="$(SRC)/cmd/ast/msgcc/:/bin:/usr/bin" 
LD_LIBRARY_PATH=$(ROOTFS_LIBDIR) "$(ROOT)/bin/ksh93" 
"$(SRC)/cmd/ast/msgcc/msgcc"
+ASTMSGS=  $(OBJECTS:%.o=msgs/%.mso)
+ASTMSGCCFLAGS=-D_STDC_C99 -D__STDC__ -D__BUILTIN_VA_ARG_INCR -D__i386
+
+msgs/%.mso: ../common/%.c
+       mkdir -p "$$(dirname "$@")"
+       $(ASTMSGCC) -M-set=ast $(ASTMSGCCFLAGS) $(CFLAGS) $(CPPFLAGS) -c $< -o 
$@
+msgs/%.mso: ../%.c
+       mkdir -p "$$(dirname "$@")"
+       $(ASTMSGCC) -M-set=ast $(ASTMSGCCFLAGS) $(CFLAGS) $(CPPFLAGS) -c $< -o 
$@
+
+$(MSGLIBNAME).msg: $(ASTMSGS)
+       $(ASTMSGCC) -M-set=ast $(ASTMSGCCFLAGS) $(CFLAGS) $(CPPFLAGS) -o $@ 
$(ASTMSGS)
+$(ASTMSGCATALOG): $(MSGLIBNAME).msg
+       $(RM) $(ASTMSGCATALOG)
+       cat "$(MSGLIBNAME).msg" | sed 's/^$$translation msgcc .*//' | gencat 
"$(ASTMSGCATALOG)" -
+
+_msg:  $(ASTMSGCATALOG)
+
Index: src/lib/libast/spec/ast.spec
===================================================================
--- src/lib/libast/spec/ast.spec        (revision 387)
+++ src/lib/libast/spec/ast.spec        (working copy)
@@ -3300,6 +3300,8 @@
 data            Vmregion 
 version         SUNWprivate_1.1
 end
+data            _ccmap 
+version         SUNWprivate_1.1
+end
 
-
 # EOF.
Index: src/lib/libast/Makefile.com
===================================================================
--- src/lib/libast/Makefile.com (revision 387)
+++ src/lib/libast/Makefile.com (working copy)
@@ -617,6 +617,8 @@
        $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
        $(POST_PROCESS_O)
 
+include ../Makefile.libastl10n
+
 include ../../Makefile.lib
 include ../../Makefile.rootfs
 
Index: src/lib/libast/Makefile
===================================================================
--- src/lib/libast/Makefile     (revision 387)
+++ src/lib/libast/Makefile     (working copy)
@@ -35,10 +35,6 @@
 SUBDIRS =      $(MACH)
 $(BUILD64)SUBDIRS += $(MACH64)
 
-# 64bit disabled for now until AST upstream fixed the differences between
-# 32bit and 64bit generated includes
-#$(BUILD64)SUBDIRS += $(MACH64)
-
 all :=         TARGET= all
 clean :=       TARGET= clean
 clobber :=     TARGET= clobber
@@ -52,9 +48,6 @@
 lint: $(SUBDIRS)
 
 LIBRARY=       libast.a
-XGETFLAGS=     -a
-POFILE=                $(LIBRARY:.a=.po)
-POFILES=       generic.po
 
 # definitions for install_h target
 HDRS=          \
@@ -166,20 +159,9 @@
 spec $(SUBDIRS):       FRC
        @cd $@; pwd; $(MAKE) $(TARGET)
 
-_msg:  $(MSGDOMAIN) $(POFILE)
-       $(RM) $(MSGDOMAIN)/$(POFILE)
-       $(CP) $(POFILE) $(MSGDOMAIN)
+_msg: $(MACH)
+       @cd $(MACH); pwd; $(MAKE) _msg
 
-$(POFILE):     $(POFILES)
-       $(RM) $@
-       $(CAT) $(POFILES) > $@
-
-$(POFILES):
-       $(RM) messages.po
-       $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]*
-       $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
-       $(RM) messages.po
-
 FRC:
 
 include ../Makefile.targ

Reply via email to