xref: /onnv-gate/usr/src/cmd/ast/msgcc/msgcpp.c (revision 10898:1883b621b3ea)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*10898Sroland.mainz@nrubsig.org *          Copyright (c) 2000-2009 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                                                                      *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin  * Glenn Fowler
234887Schin  * AT&T Research
244887Schin  *
254887Schin  * C message catalog preprocessor
264887Schin  */
274887Schin 
284887Schin static const char usage[] =
294887Schin "[-?\n@(#)$Id: msgcpp (AT&T Research) 2002-03-11 $\n]"
304887Schin USAGE_LICENSE
314887Schin "[+NAME?msgcpp - C language message catalog preprocessor]"
324887Schin "[+DESCRIPTION?\bmsgcpp\b is a C language message catalog preprocessor."
334887Schin "	It accepts \bcpp\b(1) style options and arguments. \bmsgcpp\b"
344887Schin "	preprocesses an input C source file and emits keyed lines to the"
354887Schin "	output, usually for further processing by \bmsgcc\b(1). \bmsgcc\b"
364887Schin "	output is in the \bgencat\b(1) syntax. Candidate message text is"
374887Schin "	determined by arguments to the \bast\b \b<error.h>\b and"
384887Schin "	\b<option.h>\b functions. The \bmsgcpp\b keyed output lines are:]{"
394887Schin "	[+cmd \acommand\a?\acommand\a is a candidate for \b--??keys\b"
404887Schin "		option string generation. Triggered by"
414887Schin "		\bb_\b\acommand\a\b(int argc,\b in the input.]"
424887Schin "	[+def \aname\a \astring\a?\aname\a is a candidate variable with"
434887Schin "		string value \astring\a.]"
444887Schin "	[+str \astring\a?\astring\a should be entered into the catalog.]"
454887Schin "	[+var \aname\a?If \bdef\b \aname\a occurs then its \astring\a value"
464887Schin "		should be entered into the catalog.]"
474887Schin "	}"
484887Schin "[+?The input source file is preprocessed with the \bpp:allpossible\b"
494887Schin "	option on. This enables non-C semantics; all source should first"
504887Schin "	be compiled error-free with a real compiler before running \bmsgcpp\b."
514887Schin "	The following changes are enabled for the top level files (i.e.,"
524887Schin "	included file behavior is not affected):]{"
534887Schin "		[+(1)?All \b#if\b, \b#ifdef\b and \b#ifndef\b branches"
544887Schin "			are enabled.]"
554887Schin "		[+(2)?The first definition for a macro is retained, even when"
564887Schin "			subsequent \b#define\b statements would normally"
574887Schin "			redefine the macro. \b#undef\b must be used to"
584887Schin "			redefine a macro.]"
594887Schin "		[+(3)?Macro calls with an improper number of arguments are"
604887Schin "			silently ignored.]"
614887Schin "		[+(4)?\b#include\b on non-existent headers are silently"
624887Schin "			ignored.]"
634887Schin "		[+(5)?Invalid C source characters are silently ignored.]"
644887Schin "	}"
654887Schin "[+?\b\"msgcat.h\"\b is included if it exists. This file may contain macro"
664887Schin "	definitions for functions that translate string arguments. If \afoo\a"
674887Schin "	is a function that translates its string arguments then include the"
684887Schin "	line \b#define \b\afoo\a\b _TRANSLATE_\b in \bmsgcat.h\b or specify"
694887Schin "	the option \b-D\b\afoo\a\b=_TRANSLATE_\b. If \abar\a is a function"
704887Schin "	that translates string arguments if the first argument is \bstderr\b"
714887Schin "	then use either \b#define \b\abar\a\b _STDIO_\b or"
724887Schin "	\b-D\b\abar\a\b=_STDIO_\b.]"
734887Schin "[+?The macro \b_BLD_msgcat\b is defined to be \b1\b. As an alternative to"
744887Schin "	\bmsgcat.h\b, \b_TRANSLATE_\b definitions could be placed inside"
754887Schin "	\b#ifdef _BLD_msgcat\b ... \b#endif\b.]"
764887Schin 
774887Schin "\n"
784887Schin "\n[ input [ output ] ]\n"
794887Schin "\n"
804887Schin 
814887Schin "[+SEE ALSO?\bcc\b(1), \bcpp\b(1), \bgencat\b(1), \bmsggen\b(1),"
824887Schin "	\bmsgcc\b(1), \bmsgcvt\b(1)]"
834887Schin ;
844887Schin 
854887Schin #include <ast.h>
864887Schin #include <error.h>
874887Schin 
884887Schin #include "pp.h"
894887Schin #include "ppkey.h"
904887Schin 
914887Schin #define T_STDERR	(T_KEYWORD+1)
924887Schin #define T_STDIO		(T_KEYWORD+2)
934887Schin #define T_TRANSLATE	(T_KEYWORD+3)
944887Schin 
954887Schin #define OMIT		"*@(\\[[-+]*\\?*\\]|\\@\\(#\\)|Copyright \\(c\\)|\\\\000|\\\\00[!0-9]|\\\\0[!0-9])*"
964887Schin 
974887Schin static struct ppkeyword	keys[] =
984887Schin {
994887Schin 	"char",		T_CHAR,
1004887Schin 	"int",		T_INT,
1014887Schin 	"sfstderr",	T_STDERR,
1024887Schin 	"stderr",	T_STDERR,
1034887Schin 	"_STDIO_",	T_STDIO,
1044887Schin 	"_TRANSLATE_",	T_TRANSLATE,
1054887Schin 	0,		0
1064887Schin };
1074887Schin 
1084887Schin static int
msgppargs(char ** argv,int last)1094887Schin msgppargs(char** argv, int last)
1104887Schin {
1114887Schin 	for (;;)
1124887Schin 	{
1134887Schin 		switch (optget(argv, usage))
1144887Schin 		{
1154887Schin 		case 0:
1164887Schin 			break;
1174887Schin 		case '?':
1184887Schin 			if (!last)
1194887Schin 			{
1204887Schin 				opt_info.again = 1;
1214887Schin 				return 1;
1224887Schin 			}
1234887Schin 			error(ERROR_USAGE|4, "%s", opt_info.arg);
1244887Schin 			break;
1254887Schin 		case ':':
1264887Schin 			if (!last)
1274887Schin 			{
1284887Schin 				opt_info.again = 1;
1294887Schin 				return 1;
1304887Schin 			}
1314887Schin 			error(2, "%s", opt_info.arg);
1324887Schin 			continue;
1334887Schin 		default:
1344887Schin 			if (!last)
1354887Schin 			{
1364887Schin 				opt_info.again = 1;
1374887Schin 				return 1;
1384887Schin 			}
1394887Schin 			continue;
1404887Schin 		}
1414887Schin 		break;
1424887Schin 	}
1434887Schin 	return argv[opt_info.index] != 0;
1444887Schin }
1454887Schin 
1464887Schin int
main(int argc,char ** argv)1474887Schin main(int argc, char** argv)
1484887Schin {
1494887Schin 	register char*	s;
1504887Schin 	register int	x;
1514887Schin 	register int	c;
1524887Schin 	Sfio_t*		tmp;
1534887Schin 
1544887Schin 	NoP(argc);
1554887Schin 	if (s = strrchr(*argv, '/'))
1564887Schin 		s++;
1574887Schin 	else
1584887Schin 		s = *argv;
1594887Schin 	error_info.id = s;
1604887Schin 	ppop(PP_DEFAULT, PPDEFAULT);
1614887Schin 	optjoin(argv, msgppargs, ppargs, NiL);
1624887Schin 	if (strlen(s) >= 5 && *(s + 3) != 'c')
1634887Schin 	{
1644887Schin 		ppop(PP_PLUSPLUS, 1);
1654887Schin 		ppop(PP_NOHASH, 1);
1664887Schin 		ppop(PP_PROBE, "CC");
1674887Schin 	}
1684887Schin 	ppop(PP_SPACEOUT, 0);
1694887Schin 	ppop(PP_COMPILE, keys);
1704887Schin 	ppop(PP_OPTION, "allpossible");
1714887Schin 	ppop(PP_OPTION, "catliteral");
1724887Schin 	ppop(PP_OPTION, "modern");
1734887Schin 	ppop(PP_OPTION, "readonly");
1744887Schin 	ppop(PP_DEFINE, "_BLD_msgcat=1");
1754887Schin 	ppop(PP_DEFINE, "const=");
1764887Schin 	ppop(PP_DEFINE, "errorf=_TRANSLATE_");
1774887Schin 	ppop(PP_DEFINE, "register=");
1784887Schin 	ppop(PP_DEFINE, "sfstderr=sfstderr");
1794887Schin 	ppop(PP_DEFINE, "stderr=stderr");
1804887Schin 	ppop(PP_DEFINE, "_(m)=_TRANSLATE_(m)");
1814887Schin 	ppop(PP_DEFINE, "__(m)=_TRANSLATE_(m)");
1824887Schin 	ppop(PP_DEFINE, "gettxt(i,m)=_TRANSLATE_(m)");
1834887Schin 	ppop(PP_DEFINE, "gettext(m)=_TRANSLATE_(m)");
1844887Schin 	ppop(PP_DEFINE, "dgettext(d,m)=_TRANSLATE_(m)");
1854887Schin 	ppop(PP_DEFINE, "dcgettext(d,m,c)=_TRANSLATE_(m)");
1864887Schin 	ppop(PP_DEFINE, "ERROR_catalog(m)=_TRANSLATE_(m)");
1874887Schin 	ppop(PP_DEFINE, "ERROR_dictionary(m)=_TRANSLATE_(m)");
1884887Schin 	ppop(PP_DEFINE, "ERROR_translate(l,i,c,m)=_TRANSLATE_(m)");
1894887Schin 	ppop(PP_DEFINE, "error(l,f,...)=_TRANSLATE_(f)");
1904887Schin 	ppop(PP_DEFINE, "errormsg(t,l,f,...)=_TRANSLATE_(f)");
1914887Schin 	ppop(PP_DIRECTIVE, "include \"msgcat.h\"");
1924887Schin 	ppop(PP_OPTION, "noreadonly");
1934887Schin 	ppop(PP_INIT);
1944887Schin 	if (!(tmp = sfstropen()))
1954887Schin 		error(ERROR_SYSTEM|3, "out of space");
1964887Schin 	x = 0;
1974887Schin 	for (;;)
1984887Schin 	{
1994887Schin 		c = pplex();
2004887Schin 	again:
2014887Schin 		switch (c)
2024887Schin 		{
2034887Schin 		case 0:
2044887Schin 			break;
2054887Schin 		case T_TRANSLATE:
2064887Schin 			switch (c = pplex())
2074887Schin 			{
2084887Schin 			case '(':
2094887Schin 				x = 1;
2104887Schin 				break;
2114887Schin 			case ')':
2124887Schin 				if ((c = pplex()) != '(')
2134887Schin 				{
2144887Schin 					x = 0;
2154887Schin 					goto again;
2164887Schin 				}
2174887Schin 				x = 1;
2184887Schin 				break;
2194887Schin 			default:
2204887Schin 				x = 0;
2214887Schin 				goto again;
2224887Schin 			}
2234887Schin 			continue;
2244887Schin 		case '(':
2254887Schin 			if (x > 0)
2264887Schin 				x++;
2274887Schin 			continue;
2284887Schin 		case ')':
2294887Schin 			if (x > 0)
2304887Schin 				x--;
2314887Schin 			continue;
2324887Schin 		case T_STDIO:
2334887Schin 			if ((c = pplex()) != '(' || (c = pplex()) != T_STDERR || (c = pplex()) != ',')
2344887Schin 			{
2354887Schin 				x = 0;
2364887Schin 				goto again;
2374887Schin 			}
2384887Schin 			x = 1;
2394887Schin 			continue;
2404887Schin 		case T_STRING:
2414887Schin 			if (x > 0 && !strmatch(pp.token, OMIT))
2424887Schin 				sfprintf(sfstdout, "str \"%s\"\n", pp.token);
2434887Schin 			continue;
2444887Schin 		case T_ID:
2454887Schin 			s = pp.symbol->name;
2464887Schin 			if (x > 0)
2474887Schin 			{
2484887Schin 				if ((c = pplex()) == '+' && ppisinteger(c = pplex()))
2494887Schin 					sfprintf(sfstdout, "var %s %s\n", pp.token, s);
2504887Schin 				else
2514887Schin 					sfprintf(sfstdout, "var %s\n", s);
2524887Schin 			}
2534887Schin 			else if (s[0] == 'b' && s[1] == '_' && s[2])
2544887Schin 			{
2554887Schin 				if ((c = pplex()) == '(' && (c = pplex()) == T_INT && (c = pplex()) == T_ID && (c = pplex()) == ',' && (c = pplex()) == T_CHAR && (c = pplex()) == '*')
2564887Schin 					sfprintf(sfstdout, "cmd %s\n", s + 2);
2574887Schin 				else
2584887Schin 					goto again;
2594887Schin 			}
2604887Schin 			else
2614887Schin 			{
2624887Schin 				if ((c = pplex()) == '[')
2634887Schin 				{
2644887Schin 					if (ppisinteger(c = pplex()))
2654887Schin 						c = pplex();
2664887Schin 					if (c != ']')
2674887Schin 						goto again;
2684887Schin 					c = pplex();
2694887Schin 				}
2704887Schin 				if (c == '=' && (c = pplex()) == T_STRING && !strmatch(pp.token, OMIT))
2714887Schin 				{
2724887Schin 					sfprintf(sfstdout, "def %s \"%s\"\n", s, pp.token);
2734887Schin 					sfprintf(tmp, "#define %s \"%s\"\n", s, pp.token);
2744887Schin 					if (!(s = sfstruse(tmp)))
2754887Schin 						error(ERROR_SYSTEM|3, "out of space");
2764887Schin 					ppinput(s, "string", 0);
2774887Schin 				}
2784887Schin 				else
2794887Schin 					goto again;
2804887Schin 			}
2814887Schin 			continue;
2824887Schin 		default:
2834887Schin 			continue;
2844887Schin 		}
2854887Schin 		break;
2864887Schin 	}
2874887Schin 	ppop(PP_DONE);
2884887Schin 	return error_info.errors != 0;
2894887Schin }
290