diff options
Diffstat (limited to 'usr/src/cmd/ast/msgcc/msgcpp.c')
-rw-r--r-- | usr/src/cmd/ast/msgcc/msgcpp.c | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/usr/src/cmd/ast/msgcc/msgcpp.c b/usr/src/cmd/ast/msgcc/msgcpp.c new file mode 100644 index 0000000000..677065f6cf --- /dev/null +++ b/usr/src/cmd/ast/msgcc/msgcpp.c @@ -0,0 +1,289 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 2000-2007 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@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * Glenn Fowler + * AT&T Research + * + * C message catalog preprocessor + */ + +static const char usage[] = +"[-?\n@(#)$Id: msgcpp (AT&T 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); + if (!(s = sfstruse(tmp))) + error(ERROR_SYSTEM|3, "out of space"); + ppinput(s, "string", 0); + } + else + goto again; + } + continue; + default: + continue; + } + break; + } + ppop(PP_DONE); + return error_info.errors != 0; +} |