2 * rpcgen - Generate XDR bindings automatically.
3 * Copyright (C) 2008 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include "rpcgen_int.h"
32 static void print_version (void);
33 static void usage (const char *progname);
34 static void do_rpcgen (const char *filename);
35 static char *make_cpp_command (const char *filename);
37 /* Symbols exported from the scanner. */
38 extern FILE *yyin, *yyout;
39 extern int yyparse (void);
44 main (int argc, char *argv[])
48 /* To enable debugging in the parser, you also need to compile
55 /* Note on command line arguments: We only support a small subset
56 * of command line arguments, because of the reduced functionality
57 * available in this version of rpcgen. However we accept the
58 * command line parameters from both GNU rpcgen and BSD rpcgen
59 * and print appropriate errors for any we don't understand.
61 while ((opt = getopt (argc, argv, "AD:IK:LMSTVchlmno:s:t")) != -1) {
64 /*-- Options supported by any rpcgen that we don't support. --*/
65 case 'D': case 'T': case 'K': case 'l': case 'm': case 't':
67 error ("option '%c' is not supported by this PortableXDR rpcgen.\nYou may need to use an alternative rpcgen program instead.", opt);
69 /*-- Options supported only by GNU rpcgen that we don't support. --*/
71 error ("option '%c' is not supported by this PortableXDR rpcgen.\nIf you were expecting to use GNU rpcgen, try /usr/bin/rpcgen on a GNU host.", opt);
73 /*-- Options supported only by BSD rpcgen that we don't support. --*/
74 case 'A': case 'M': case 'L': case 'S':
75 error ("option '%c' is not supported by this PortableXDR rpcgen.\nIf you were expecting to use BSD rpcgen, try /usr/bin/rpcgen on a BSD host.", opt);
77 /*-- Options that we do support. --*/
83 /* None of the other versions of rpcgen support a way to print
84 * the version number, which is extremely annoying because
85 * there are so many different variations of rpcgen around.
86 * So this option at least should be useful!
100 error ("expected name of input file after options");
102 while (optind < argc)
103 do_rpcgen (argv[optind++]);
111 printf ("PortableXDR rpcgen %s\n", PACKAGE_VERSION);
115 usage (const char *progname)
119 ("Generate XDR bindings automatically.\n"
122 " portable-rpcgen infile.x\n"
123 " portable-rpcgen -c|-h [-o outfile] infile.x\n"
124 " portable-rpcgen -V\n"
127 " -c Generate C output file only.\n"
128 " -h Generate header output file only.\n"
129 " -o Name of output file (normally it is 'infile.[ch]').\n"
130 " -V Print the version and exit.\n"
132 "In the first form, without -c or -h, we generate both output files.\n"
134 "You can also list more than one input file on the command line, in\n"
135 "which case each input file is processed separately.\n"
141 /* Called for each input file. */
143 do_rpcgen (const char *filename)
148 free (input_filename);
149 input_filename = NULL;
151 cmd = make_cpp_command (filename);
153 yyin = popen (cmd, "r");
160 /* Parse the input file. This either succeeds or exits with an error. */
165 error ("parsing failed, file is not a valid rpcgen input");
167 error ("parsing failed because we ran out of memory");
169 free (input_filename);
170 input_filename = NULL;
173 /* Concatenate $EXTCPP and filename, and make sure the filename is
174 * quoted correctly. Tedious.
177 make_cpp_command (const char *filename)
179 static const char good[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.";
180 #define is_good(c) (strchr (good, (c)) != NULL)
183 /* We can use start_string etc. because this function is only used
184 * outside the scanner.
190 for (p = filename; *p; p++) {
191 if (is_good (*p)) add_char (*p);
198 return end_string ();
201 /* Some fairly random functions which are used by the scanner for
202 * constructing strings, reporting errors, etc.
205 /* The scanner sets this to the name of the input file (from cpp)
208 char *input_filename = NULL;
210 static char *str = NULL;
211 static int str_used, str_alloc;
217 error ("scanner called start_string without calling end_string");
221 str = malloc (str_alloc);
222 if (!str) perrorf ("malloc");
231 error ("scanner called end_string without calling start_string");
233 s = realloc (str, str_used+1);
234 if (!s) perrorf ("realloc");
245 while (str_used >= str_alloc) {
247 str = realloc (str, str_alloc);
248 if (!str) perrorf ("realloc");
254 add_string (const char *s)
257 int len = strlen (s);
260 while (str_used >= str_alloc) {
262 str = realloc (str, str_alloc);
263 if (!str) perrorf ("realloc");
265 memcpy (str+i, s, len);
269 error (const char *fs, ...)
273 if (input_filename == NULL)
274 fputs (PACKAGE, stderr);
276 fprintf (stderr, "%s:%d", input_filename, yylineno);
277 fputs (": ", stderr);
280 vfprintf (stderr, fs, arg);
283 fputc ('\n', stderr);
289 perrorf (const char *fs, ...)
294 if (input_filename == NULL)
295 fputs (PACKAGE, stderr);
297 fprintf (stderr, "%s:%d", input_filename, yylineno);
298 fputs (": ", stderr);
301 vfprintf (stderr, fs, arg);
304 fputs (": ", stderr);