1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 2000-2009 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
19 ***********************************************************************/
25 * C message catalog preprocessor
28 static const char usage
[] =
29 "[-?\n@(#)$Id: msgcpp (AT&T Research) 2002-03-11 $\n]"
31 "[+NAME?msgcpp - C language message catalog preprocessor]"
32 "[+DESCRIPTION?\bmsgcpp\b is a C language message catalog preprocessor."
33 " It accepts \bcpp\b(1) style options and arguments. \bmsgcpp\b"
34 " preprocesses an input C source file and emits keyed lines to the"
35 " output, usually for further processing by \bmsgcc\b(1). \bmsgcc\b"
36 " output is in the \bgencat\b(1) syntax. Candidate message text is"
37 " determined by arguments to the \bast\b \b<error.h>\b and"
38 " \b<option.h>\b functions. The \bmsgcpp\b keyed output lines are:]{"
39 " [+cmd \acommand\a?\acommand\a is a candidate for \b--??keys\b"
40 " option string generation. Triggered by"
41 " \bb_\b\acommand\a\b(int argc,\b in the input.]"
42 " [+def \aname\a \astring\a?\aname\a is a candidate variable with"
43 " string value \astring\a.]"
44 " [+str \astring\a?\astring\a should be entered into the catalog.]"
45 " [+var \aname\a?If \bdef\b \aname\a occurs then its \astring\a value"
46 " should be entered into the catalog.]"
48 "[+?The input source file is preprocessed with the \bpp:allpossible\b"
49 " option on. This enables non-C semantics; all source should first"
50 " be compiled error-free with a real compiler before running \bmsgcpp\b."
51 " The following changes are enabled for the top level files (i.e.,"
52 " included file behavior is not affected):]{"
53 " [+(1)?All \b#if\b, \b#ifdef\b and \b#ifndef\b branches"
55 " [+(2)?The first definition for a macro is retained, even when"
56 " subsequent \b#define\b statements would normally"
57 " redefine the macro. \b#undef\b must be used to"
59 " [+(3)?Macro calls with an improper number of arguments are"
61 " [+(4)?\b#include\b on non-existent headers are silently"
63 " [+(5)?Invalid C source characters are silently ignored.]"
65 "[+?\b\"msgcat.h\"\b is included if it exists. This file may contain macro"
66 " definitions for functions that translate string arguments. If \afoo\a"
67 " is a function that translates its string arguments then include the"
68 " line \b#define \b\afoo\a\b _TRANSLATE_\b in \bmsgcat.h\b or specify"
69 " the option \b-D\b\afoo\a\b=_TRANSLATE_\b. If \abar\a is a function"
70 " that translates string arguments if the first argument is \bstderr\b"
71 " then use either \b#define \b\abar\a\b _STDIO_\b or"
72 " \b-D\b\abar\a\b=_STDIO_\b.]"
73 "[+?The macro \b_BLD_msgcat\b is defined to be \b1\b. As an alternative to"
74 " \bmsgcat.h\b, \b_TRANSLATE_\b definitions could be placed inside"
75 " \b#ifdef _BLD_msgcat\b ... \b#endif\b.]"
78 "\n[ input [ output ] ]\n"
81 "[+SEE ALSO?\bcc\b(1), \bcpp\b(1), \bgencat\b(1), \bmsggen\b(1),"
82 " \bmsgcc\b(1), \bmsgcvt\b(1)]"
91 #define T_STDERR (T_KEYWORD+1)
92 #define T_STDIO (T_KEYWORD+2)
93 #define T_TRANSLATE (T_KEYWORD+3)
95 #define OMIT "*@(\\[[-+]*\\?*\\]|\\@\\(#\\)|Copyright \\(c\\)|\\\\000|\\\\00[!0-9]|\\\\0[!0-9])*"
97 static struct ppkeyword keys
[] =
101 "sfstderr", T_STDERR
,
104 "_TRANSLATE_", T_TRANSLATE
,
109 msgppargs(char** argv
, int last
)
113 switch (optget(argv
, usage
))
123 error(ERROR_USAGE
|4, "%s", opt_info
.arg
);
131 error(2, "%s", opt_info
.arg
);
143 return argv
[opt_info
.index
] != 0;
147 main(int argc
, char** argv
)
155 if (s
= strrchr(*argv
, '/'))
160 ppop(PP_DEFAULT
, PPDEFAULT
);
161 optjoin(argv
, msgppargs
, ppargs
, NiL
);
162 if (strlen(s
) >= 5 && *(s
+ 3) != 'c')
164 ppop(PP_PLUSPLUS
, 1);
166 ppop(PP_PROBE
, "CC");
168 ppop(PP_SPACEOUT
, 0);
169 ppop(PP_COMPILE
, keys
);
170 ppop(PP_OPTION
, "allpossible");
171 ppop(PP_OPTION
, "catliteral");
172 ppop(PP_OPTION
, "modern");
173 ppop(PP_OPTION
, "readonly");
174 ppop(PP_DEFINE
, "_BLD_msgcat=1");
175 ppop(PP_DEFINE
, "const=");
176 ppop(PP_DEFINE
, "errorf=_TRANSLATE_");
177 ppop(PP_DEFINE
, "register=");
178 ppop(PP_DEFINE
, "sfstderr=sfstderr");
179 ppop(PP_DEFINE
, "stderr=stderr");
180 ppop(PP_DEFINE
, "_(m)=_TRANSLATE_(m)");
181 ppop(PP_DEFINE
, "__(m)=_TRANSLATE_(m)");
182 ppop(PP_DEFINE
, "gettxt(i,m)=_TRANSLATE_(m)");
183 ppop(PP_DEFINE
, "gettext(m)=_TRANSLATE_(m)");
184 ppop(PP_DEFINE
, "dgettext(d,m)=_TRANSLATE_(m)");
185 ppop(PP_DEFINE
, "dcgettext(d,m,c)=_TRANSLATE_(m)");
186 ppop(PP_DEFINE
, "ERROR_catalog(m)=_TRANSLATE_(m)");
187 ppop(PP_DEFINE
, "ERROR_dictionary(m)=_TRANSLATE_(m)");
188 ppop(PP_DEFINE
, "ERROR_translate(l,i,c,m)=_TRANSLATE_(m)");
189 ppop(PP_DEFINE
, "error(l,f,...)=_TRANSLATE_(f)");
190 ppop(PP_DEFINE
, "errormsg(t,l,f,...)=_TRANSLATE_(f)");
191 ppop(PP_DIRECTIVE
, "include \"msgcat.h\"");
192 ppop(PP_OPTION
, "noreadonly");
194 if (!(tmp
= sfstropen()))
195 error(ERROR_SYSTEM
|3, "out of space");
212 if ((c
= pplex()) != '(')
233 if ((c
= pplex()) != '(' || (c
= pplex()) != T_STDERR
|| (c
= pplex()) != ',')
241 if (x
> 0 && !strmatch(pp
.token
, OMIT
))
242 sfprintf(sfstdout
, "str \"%s\"\n", pp
.token
);
248 if ((c
= pplex()) == '+' && ppisinteger(c
= pplex()))
249 sfprintf(sfstdout
, "var %s %s\n", pp
.token
, s
);
251 sfprintf(sfstdout
, "var %s\n", s
);
253 else if (s
[0] == 'b' && s
[1] == '_' && s
[2])
255 if ((c
= pplex()) == '(' && (c
= pplex()) == T_INT
&& (c
= pplex()) == T_ID
&& (c
= pplex()) == ',' && (c
= pplex()) == T_CHAR
&& (c
= pplex()) == '*')
256 sfprintf(sfstdout
, "cmd %s\n", s
+ 2);
262 if ((c
= pplex()) == '[')
264 if (ppisinteger(c
= pplex()))
270 if (c
== '=' && (c
= pplex()) == T_STRING
&& !strmatch(pp
.token
, OMIT
))
272 sfprintf(sfstdout
, "def %s \"%s\"\n", s
, pp
.token
);
273 sfprintf(tmp
, "#define %s \"%s\"\n", s
, pp
.token
);
274 if (!(s
= sfstruse(tmp
)))
275 error(ERROR_SYSTEM
|3, "out of space");
276 ppinput(s
, "string", 0);
288 return error_info
.errors
!= 0;