Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/msgcc/msgcpp.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2000-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* Glenn Fowler
23
* AT&T Research
24
*
25
* C message catalog preprocessor
26
*/
27
28
static const char usage[] =
29
"[-?\n@(#)$Id: msgcpp (AT&T Research) 2002-03-11 $\n]"
30
USAGE_LICENSE
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.]"
47
" }"
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"
54
" are enabled.]"
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"
58
" redefine a macro.]"
59
" [+(3)?Macro calls with an improper number of arguments are"
60
" silently ignored.]"
61
" [+(4)?\b#include\b on non-existent headers are silently"
62
" ignored.]"
63
" [+(5)?Invalid C source characters are silently ignored.]"
64
" }"
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.]"
76
77
"\n"
78
"\n[ input [ output ] ]\n"
79
"\n"
80
81
"[+SEE ALSO?\bcc\b(1), \bcpp\b(1), \bgencat\b(1), \bmsggen\b(1),"
82
" \bmsgcc\b(1), \bmsgcvt\b(1)]"
83
;
84
85
#include <ast.h>
86
#include <error.h>
87
88
#include "pp.h"
89
#include "ppkey.h"
90
91
#define T_STDERR (T_KEYWORD+1)
92
#define T_STDIO (T_KEYWORD+2)
93
#define T_TRANSLATE (T_KEYWORD+3)
94
95
#define OMIT "*@(\\[[-+]*\\?*\\]|\\@\\(#\\)|Copyright \\(c\\)|\\\\000|\\\\00[!0-9]|\\\\0[!0-9])*"
96
97
static struct ppkeyword keys[] =
98
{
99
"char", T_CHAR,
100
"int", T_INT,
101
"sfstderr", T_STDERR,
102
"stderr", T_STDERR,
103
"_STDIO_", T_STDIO,
104
"_TRANSLATE_", T_TRANSLATE,
105
0, 0
106
};
107
108
static int
109
msgppargs(char** argv, int last)
110
{
111
for (;;)
112
{
113
switch (optget(argv, usage))
114
{
115
case 0:
116
break;
117
case '?':
118
if (!last)
119
{
120
opt_info.again = 1;
121
return 1;
122
}
123
error(ERROR_USAGE|4, "%s", opt_info.arg);
124
break;
125
case ':':
126
if (!last)
127
{
128
opt_info.again = 1;
129
return 1;
130
}
131
error(2, "%s", opt_info.arg);
132
continue;
133
default:
134
if (!last)
135
{
136
opt_info.again = 1;
137
return 1;
138
}
139
continue;
140
}
141
break;
142
}
143
return argv[opt_info.index] != 0;
144
}
145
146
int
147
main(int argc, char** argv)
148
{
149
register char* s;
150
register int x;
151
register int c;
152
Sfio_t* tmp;
153
154
NoP(argc);
155
if (s = strrchr(*argv, '/'))
156
s++;
157
else
158
s = *argv;
159
error_info.id = s;
160
ppop(PP_DEFAULT, PPDEFAULT);
161
optjoin(argv, msgppargs, ppargs, NiL);
162
if (strlen(s) >= 5 && *(s + 3) != 'c')
163
{
164
ppop(PP_PLUSPLUS, 1);
165
ppop(PP_NOHASH, 1);
166
ppop(PP_PROBE, "CC");
167
}
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");
193
ppop(PP_INIT);
194
if (!(tmp = sfstropen()))
195
error(ERROR_SYSTEM|3, "out of space");
196
x = 0;
197
for (;;)
198
{
199
c = pplex();
200
again:
201
switch (c)
202
{
203
case 0:
204
break;
205
case T_TRANSLATE:
206
switch (c = pplex())
207
{
208
case '(':
209
x = 1;
210
break;
211
case ')':
212
if ((c = pplex()) != '(')
213
{
214
x = 0;
215
goto again;
216
}
217
x = 1;
218
break;
219
default:
220
x = 0;
221
goto again;
222
}
223
continue;
224
case '(':
225
if (x > 0)
226
x++;
227
continue;
228
case ')':
229
if (x > 0)
230
x--;
231
continue;
232
case T_STDIO:
233
if ((c = pplex()) != '(' || (c = pplex()) != T_STDERR || (c = pplex()) != ',')
234
{
235
x = 0;
236
goto again;
237
}
238
x = 1;
239
continue;
240
case T_STRING:
241
if (x > 0 && !strmatch(pp.token, OMIT))
242
sfprintf(sfstdout, "str \"%s\"\n", pp.token);
243
continue;
244
case T_ID:
245
s = pp.symbol->name;
246
if (x > 0)
247
{
248
if ((c = pplex()) == '+' && ppisinteger(c = pplex()))
249
sfprintf(sfstdout, "var %s %s\n", pp.token, s);
250
else
251
sfprintf(sfstdout, "var %s\n", s);
252
}
253
else if (s[0] == 'b' && s[1] == '_' && s[2])
254
{
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);
257
else
258
goto again;
259
}
260
else
261
{
262
if ((c = pplex()) == '[')
263
{
264
if (ppisinteger(c = pplex()))
265
c = pplex();
266
if (c != ']')
267
goto again;
268
c = pplex();
269
}
270
if (c == '=' && (c = pplex()) == T_STRING && !strmatch(pp.token, OMIT))
271
{
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);
277
}
278
else
279
goto again;
280
}
281
continue;
282
default:
283
continue;
284
}
285
break;
286
}
287
ppop(PP_DONE);
288
return error_info.errors != 0;
289
}
290
291