/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 2000-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* 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]"
"[+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"
{
"char", T_CHAR,
"int", T_INT,
"sfstderr", T_STDERR,
"stderr", T_STDERR,
"_STDIO_", T_STDIO,
"_TRANSLATE_", T_TRANSLATE,
0, 0
};
static int
{
for (;;)
{
{
case 0:
break;
case '?':
if (!last)
{
return 1;
}
break;
case ':':
if (!last)
{
return 1;
}
continue;
default:
if (!last)
{
return 1;
}
continue;
}
break;
}
}
int
{
register char* s;
register int x;
register int c;
s++;
else
s = *argv;
error_info.id = s;
{
}
ppop(PP_SPACEOUT, 0);
x = 0;
for (;;)
{
c = pplex();
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:
{
x = 0;
goto again;
}
x = 1;
continue;
case T_STRING:
continue;
case T_ID:
if (x > 0)
{
else
}
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()) == '*')
else
goto again;
}
else
{
if ((c = pplex()) == '[')
{
if (ppisinteger(c = pplex()))
c = pplex();
if (c != ']')
goto again;
c = pplex();
}
{
ppinput(s, "string", 0);
}
else
goto again;
}
continue;
default:
continue;
}
break;
}
return error_info.errors != 0;
}