1*da2e3ebdSchin /*********************************************************************** 2*da2e3ebdSchin * * 3*da2e3ebdSchin * This software is part of the ast package * 4*da2e3ebdSchin * Copyright (c) 2000-2007 AT&T Knowledge Ventures * 5*da2e3ebdSchin * and is licensed under the * 6*da2e3ebdSchin * Common Public License, Version 1.0 * 7*da2e3ebdSchin * by AT&T Knowledge Ventures * 8*da2e3ebdSchin * * 9*da2e3ebdSchin * A copy of the License is available at * 10*da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt * 11*da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*da2e3ebdSchin * * 13*da2e3ebdSchin * Information and Software Systems Research * 14*da2e3ebdSchin * AT&T Research * 15*da2e3ebdSchin * Florham Park NJ * 16*da2e3ebdSchin * * 17*da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> * 18*da2e3ebdSchin * * 19*da2e3ebdSchin ***********************************************************************/ 20*da2e3ebdSchin #pragma prototyped 21*da2e3ebdSchin /* 22*da2e3ebdSchin * Glenn Fowler 23*da2e3ebdSchin * AT&T Research 24*da2e3ebdSchin * 25*da2e3ebdSchin * C message catalog preprocessor 26*da2e3ebdSchin */ 27*da2e3ebdSchin 28*da2e3ebdSchin static const char usage[] = 29*da2e3ebdSchin "[-?\n@(#)$Id: msgcpp (AT&T Research) 2002-03-11 $\n]" 30*da2e3ebdSchin USAGE_LICENSE 31*da2e3ebdSchin "[+NAME?msgcpp - C language message catalog preprocessor]" 32*da2e3ebdSchin "[+DESCRIPTION?\bmsgcpp\b is a C language message catalog preprocessor." 33*da2e3ebdSchin " It accepts \bcpp\b(1) style options and arguments. \bmsgcpp\b" 34*da2e3ebdSchin " preprocesses an input C source file and emits keyed lines to the" 35*da2e3ebdSchin " output, usually for further processing by \bmsgcc\b(1). \bmsgcc\b" 36*da2e3ebdSchin " output is in the \bgencat\b(1) syntax. Candidate message text is" 37*da2e3ebdSchin " determined by arguments to the \bast\b \b<error.h>\b and" 38*da2e3ebdSchin " \b<option.h>\b functions. The \bmsgcpp\b keyed output lines are:]{" 39*da2e3ebdSchin " [+cmd \acommand\a?\acommand\a is a candidate for \b--??keys\b" 40*da2e3ebdSchin " option string generation. Triggered by" 41*da2e3ebdSchin " \bb_\b\acommand\a\b(int argc,\b in the input.]" 42*da2e3ebdSchin " [+def \aname\a \astring\a?\aname\a is a candidate variable with" 43*da2e3ebdSchin " string value \astring\a.]" 44*da2e3ebdSchin " [+str \astring\a?\astring\a should be entered into the catalog.]" 45*da2e3ebdSchin " [+var \aname\a?If \bdef\b \aname\a occurs then its \astring\a value" 46*da2e3ebdSchin " should be entered into the catalog.]" 47*da2e3ebdSchin " }" 48*da2e3ebdSchin "[+?The input source file is preprocessed with the \bpp:allpossible\b" 49*da2e3ebdSchin " option on. This enables non-C semantics; all source should first" 50*da2e3ebdSchin " be compiled error-free with a real compiler before running \bmsgcpp\b." 51*da2e3ebdSchin " The following changes are enabled for the top level files (i.e.," 52*da2e3ebdSchin " included file behavior is not affected):]{" 53*da2e3ebdSchin " [+(1)?All \b#if\b, \b#ifdef\b and \b#ifndef\b branches" 54*da2e3ebdSchin " are enabled.]" 55*da2e3ebdSchin " [+(2)?The first definition for a macro is retained, even when" 56*da2e3ebdSchin " subsequent \b#define\b statements would normally" 57*da2e3ebdSchin " redefine the macro. \b#undef\b must be used to" 58*da2e3ebdSchin " redefine a macro.]" 59*da2e3ebdSchin " [+(3)?Macro calls with an improper number of arguments are" 60*da2e3ebdSchin " silently ignored.]" 61*da2e3ebdSchin " [+(4)?\b#include\b on non-existent headers are silently" 62*da2e3ebdSchin " ignored.]" 63*da2e3ebdSchin " [+(5)?Invalid C source characters are silently ignored.]" 64*da2e3ebdSchin " }" 65*da2e3ebdSchin "[+?\b\"msgcat.h\"\b is included if it exists. This file may contain macro" 66*da2e3ebdSchin " definitions for functions that translate string arguments. If \afoo\a" 67*da2e3ebdSchin " is a function that translates its string arguments then include the" 68*da2e3ebdSchin " line \b#define \b\afoo\a\b _TRANSLATE_\b in \bmsgcat.h\b or specify" 69*da2e3ebdSchin " the option \b-D\b\afoo\a\b=_TRANSLATE_\b. If \abar\a is a function" 70*da2e3ebdSchin " that translates string arguments if the first argument is \bstderr\b" 71*da2e3ebdSchin " then use either \b#define \b\abar\a\b _STDIO_\b or" 72*da2e3ebdSchin " \b-D\b\abar\a\b=_STDIO_\b.]" 73*da2e3ebdSchin "[+?The macro \b_BLD_msgcat\b is defined to be \b1\b. As an alternative to" 74*da2e3ebdSchin " \bmsgcat.h\b, \b_TRANSLATE_\b definitions could be placed inside" 75*da2e3ebdSchin " \b#ifdef _BLD_msgcat\b ... \b#endif\b.]" 76*da2e3ebdSchin 77*da2e3ebdSchin "\n" 78*da2e3ebdSchin "\n[ input [ output ] ]\n" 79*da2e3ebdSchin "\n" 80*da2e3ebdSchin 81*da2e3ebdSchin "[+SEE ALSO?\bcc\b(1), \bcpp\b(1), \bgencat\b(1), \bmsggen\b(1)," 82*da2e3ebdSchin " \bmsgcc\b(1), \bmsgcvt\b(1)]" 83*da2e3ebdSchin ; 84*da2e3ebdSchin 85*da2e3ebdSchin #include <ast.h> 86*da2e3ebdSchin #include <error.h> 87*da2e3ebdSchin 88*da2e3ebdSchin #include "pp.h" 89*da2e3ebdSchin #include "ppkey.h" 90*da2e3ebdSchin 91*da2e3ebdSchin #define T_STDERR (T_KEYWORD+1) 92*da2e3ebdSchin #define T_STDIO (T_KEYWORD+2) 93*da2e3ebdSchin #define T_TRANSLATE (T_KEYWORD+3) 94*da2e3ebdSchin 95*da2e3ebdSchin #define OMIT "*@(\\[[-+]*\\?*\\]|\\@\\(#\\)|Copyright \\(c\\)|\\\\000|\\\\00[!0-9]|\\\\0[!0-9])*" 96*da2e3ebdSchin 97*da2e3ebdSchin static struct ppkeyword keys[] = 98*da2e3ebdSchin { 99*da2e3ebdSchin "char", T_CHAR, 100*da2e3ebdSchin "int", T_INT, 101*da2e3ebdSchin "sfstderr", T_STDERR, 102*da2e3ebdSchin "stderr", T_STDERR, 103*da2e3ebdSchin "_STDIO_", T_STDIO, 104*da2e3ebdSchin "_TRANSLATE_", T_TRANSLATE, 105*da2e3ebdSchin 0, 0 106*da2e3ebdSchin }; 107*da2e3ebdSchin 108*da2e3ebdSchin static int 109*da2e3ebdSchin msgppargs(char** argv, int last) 110*da2e3ebdSchin { 111*da2e3ebdSchin for (;;) 112*da2e3ebdSchin { 113*da2e3ebdSchin switch (optget(argv, usage)) 114*da2e3ebdSchin { 115*da2e3ebdSchin case 0: 116*da2e3ebdSchin break; 117*da2e3ebdSchin case '?': 118*da2e3ebdSchin if (!last) 119*da2e3ebdSchin { 120*da2e3ebdSchin opt_info.again = 1; 121*da2e3ebdSchin return 1; 122*da2e3ebdSchin } 123*da2e3ebdSchin error(ERROR_USAGE|4, "%s", opt_info.arg); 124*da2e3ebdSchin break; 125*da2e3ebdSchin case ':': 126*da2e3ebdSchin if (!last) 127*da2e3ebdSchin { 128*da2e3ebdSchin opt_info.again = 1; 129*da2e3ebdSchin return 1; 130*da2e3ebdSchin } 131*da2e3ebdSchin error(2, "%s", opt_info.arg); 132*da2e3ebdSchin continue; 133*da2e3ebdSchin default: 134*da2e3ebdSchin if (!last) 135*da2e3ebdSchin { 136*da2e3ebdSchin opt_info.again = 1; 137*da2e3ebdSchin return 1; 138*da2e3ebdSchin } 139*da2e3ebdSchin continue; 140*da2e3ebdSchin } 141*da2e3ebdSchin break; 142*da2e3ebdSchin } 143*da2e3ebdSchin return argv[opt_info.index] != 0; 144*da2e3ebdSchin } 145*da2e3ebdSchin 146*da2e3ebdSchin int 147*da2e3ebdSchin main(int argc, char** argv) 148*da2e3ebdSchin { 149*da2e3ebdSchin register char* s; 150*da2e3ebdSchin register int x; 151*da2e3ebdSchin register int c; 152*da2e3ebdSchin Sfio_t* tmp; 153*da2e3ebdSchin 154*da2e3ebdSchin NoP(argc); 155*da2e3ebdSchin if (s = strrchr(*argv, '/')) 156*da2e3ebdSchin s++; 157*da2e3ebdSchin else 158*da2e3ebdSchin s = *argv; 159*da2e3ebdSchin error_info.id = s; 160*da2e3ebdSchin ppop(PP_DEFAULT, PPDEFAULT); 161*da2e3ebdSchin optjoin(argv, msgppargs, ppargs, NiL); 162*da2e3ebdSchin if (strlen(s) >= 5 && *(s + 3) != 'c') 163*da2e3ebdSchin { 164*da2e3ebdSchin ppop(PP_PLUSPLUS, 1); 165*da2e3ebdSchin ppop(PP_NOHASH, 1); 166*da2e3ebdSchin ppop(PP_PROBE, "CC"); 167*da2e3ebdSchin } 168*da2e3ebdSchin ppop(PP_SPACEOUT, 0); 169*da2e3ebdSchin ppop(PP_COMPILE, keys); 170*da2e3ebdSchin ppop(PP_OPTION, "allpossible"); 171*da2e3ebdSchin ppop(PP_OPTION, "catliteral"); 172*da2e3ebdSchin ppop(PP_OPTION, "modern"); 173*da2e3ebdSchin ppop(PP_OPTION, "readonly"); 174*da2e3ebdSchin ppop(PP_DEFINE, "_BLD_msgcat=1"); 175*da2e3ebdSchin ppop(PP_DEFINE, "const="); 176*da2e3ebdSchin ppop(PP_DEFINE, "errorf=_TRANSLATE_"); 177*da2e3ebdSchin ppop(PP_DEFINE, "register="); 178*da2e3ebdSchin ppop(PP_DEFINE, "sfstderr=sfstderr"); 179*da2e3ebdSchin ppop(PP_DEFINE, "stderr=stderr"); 180*da2e3ebdSchin ppop(PP_DEFINE, "_(m)=_TRANSLATE_(m)"); 181*da2e3ebdSchin ppop(PP_DEFINE, "__(m)=_TRANSLATE_(m)"); 182*da2e3ebdSchin ppop(PP_DEFINE, "gettxt(i,m)=_TRANSLATE_(m)"); 183*da2e3ebdSchin ppop(PP_DEFINE, "gettext(m)=_TRANSLATE_(m)"); 184*da2e3ebdSchin ppop(PP_DEFINE, "dgettext(d,m)=_TRANSLATE_(m)"); 185*da2e3ebdSchin ppop(PP_DEFINE, "dcgettext(d,m,c)=_TRANSLATE_(m)"); 186*da2e3ebdSchin ppop(PP_DEFINE, "ERROR_catalog(m)=_TRANSLATE_(m)"); 187*da2e3ebdSchin ppop(PP_DEFINE, "ERROR_dictionary(m)=_TRANSLATE_(m)"); 188*da2e3ebdSchin ppop(PP_DEFINE, "ERROR_translate(l,i,c,m)=_TRANSLATE_(m)"); 189*da2e3ebdSchin ppop(PP_DEFINE, "error(l,f,...)=_TRANSLATE_(f)"); 190*da2e3ebdSchin ppop(PP_DEFINE, "errormsg(t,l,f,...)=_TRANSLATE_(f)"); 191*da2e3ebdSchin ppop(PP_DIRECTIVE, "include \"msgcat.h\""); 192*da2e3ebdSchin ppop(PP_OPTION, "noreadonly"); 193*da2e3ebdSchin ppop(PP_INIT); 194*da2e3ebdSchin if (!(tmp = sfstropen())) 195*da2e3ebdSchin error(ERROR_SYSTEM|3, "out of space"); 196*da2e3ebdSchin x = 0; 197*da2e3ebdSchin for (;;) 198*da2e3ebdSchin { 199*da2e3ebdSchin c = pplex(); 200*da2e3ebdSchin again: 201*da2e3ebdSchin switch (c) 202*da2e3ebdSchin { 203*da2e3ebdSchin case 0: 204*da2e3ebdSchin break; 205*da2e3ebdSchin case T_TRANSLATE: 206*da2e3ebdSchin switch (c = pplex()) 207*da2e3ebdSchin { 208*da2e3ebdSchin case '(': 209*da2e3ebdSchin x = 1; 210*da2e3ebdSchin break; 211*da2e3ebdSchin case ')': 212*da2e3ebdSchin if ((c = pplex()) != '(') 213*da2e3ebdSchin { 214*da2e3ebdSchin x = 0; 215*da2e3ebdSchin goto again; 216*da2e3ebdSchin } 217*da2e3ebdSchin x = 1; 218*da2e3ebdSchin break; 219*da2e3ebdSchin default: 220*da2e3ebdSchin x = 0; 221*da2e3ebdSchin goto again; 222*da2e3ebdSchin } 223*da2e3ebdSchin continue; 224*da2e3ebdSchin case '(': 225*da2e3ebdSchin if (x > 0) 226*da2e3ebdSchin x++; 227*da2e3ebdSchin continue; 228*da2e3ebdSchin case ')': 229*da2e3ebdSchin if (x > 0) 230*da2e3ebdSchin x--; 231*da2e3ebdSchin continue; 232*da2e3ebdSchin case T_STDIO: 233*da2e3ebdSchin if ((c = pplex()) != '(' || (c = pplex()) != T_STDERR || (c = pplex()) != ',') 234*da2e3ebdSchin { 235*da2e3ebdSchin x = 0; 236*da2e3ebdSchin goto again; 237*da2e3ebdSchin } 238*da2e3ebdSchin x = 1; 239*da2e3ebdSchin continue; 240*da2e3ebdSchin case T_STRING: 241*da2e3ebdSchin if (x > 0 && !strmatch(pp.token, OMIT)) 242*da2e3ebdSchin sfprintf(sfstdout, "str \"%s\"\n", pp.token); 243*da2e3ebdSchin continue; 244*da2e3ebdSchin case T_ID: 245*da2e3ebdSchin s = pp.symbol->name; 246*da2e3ebdSchin if (x > 0) 247*da2e3ebdSchin { 248*da2e3ebdSchin if ((c = pplex()) == '+' && ppisinteger(c = pplex())) 249*da2e3ebdSchin sfprintf(sfstdout, "var %s %s\n", pp.token, s); 250*da2e3ebdSchin else 251*da2e3ebdSchin sfprintf(sfstdout, "var %s\n", s); 252*da2e3ebdSchin } 253*da2e3ebdSchin else if (s[0] == 'b' && s[1] == '_' && s[2]) 254*da2e3ebdSchin { 255*da2e3ebdSchin if ((c = pplex()) == '(' && (c = pplex()) == T_INT && (c = pplex()) == T_ID && (c = pplex()) == ',' && (c = pplex()) == T_CHAR && (c = pplex()) == '*') 256*da2e3ebdSchin sfprintf(sfstdout, "cmd %s\n", s + 2); 257*da2e3ebdSchin else 258*da2e3ebdSchin goto again; 259*da2e3ebdSchin } 260*da2e3ebdSchin else 261*da2e3ebdSchin { 262*da2e3ebdSchin if ((c = pplex()) == '[') 263*da2e3ebdSchin { 264*da2e3ebdSchin if (ppisinteger(c = pplex())) 265*da2e3ebdSchin c = pplex(); 266*da2e3ebdSchin if (c != ']') 267*da2e3ebdSchin goto again; 268*da2e3ebdSchin c = pplex(); 269*da2e3ebdSchin } 270*da2e3ebdSchin if (c == '=' && (c = pplex()) == T_STRING && !strmatch(pp.token, OMIT)) 271*da2e3ebdSchin { 272*da2e3ebdSchin sfprintf(sfstdout, "def %s \"%s\"\n", s, pp.token); 273*da2e3ebdSchin sfprintf(tmp, "#define %s \"%s\"\n", s, pp.token); 274*da2e3ebdSchin if (!(s = sfstruse(tmp))) 275*da2e3ebdSchin error(ERROR_SYSTEM|3, "out of space"); 276*da2e3ebdSchin ppinput(s, "string", 0); 277*da2e3ebdSchin } 278*da2e3ebdSchin else 279*da2e3ebdSchin goto again; 280*da2e3ebdSchin } 281*da2e3ebdSchin continue; 282*da2e3ebdSchin default: 283*da2e3ebdSchin continue; 284*da2e3ebdSchin } 285*da2e3ebdSchin break; 286*da2e3ebdSchin } 287*da2e3ebdSchin ppop(PP_DONE); 288*da2e3ebdSchin return error_info.errors != 0; 289*da2e3ebdSchin } 290