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 enum output_mode output_mode;
34 static void print_version (void);
35 static void usage (const char *progname);
36 static void do_rpcgen (const char *filename, const char *out);
37 static char *make_cpp_command (const char *filename);
40 main (int argc, char *argv[])
51 /* Note on command line arguments: We only support a small subset
52 * of command line arguments, because of the reduced functionality
53 * available in this version of rpcgen. However we accept the
54 * command line parameters from both GNU rpcgen and BSD rpcgen
55 * and print appropriate errors for any we don't understand.
57 while ((opt = getopt (argc, argv, "AD:IK:LMSTVchlmno:s:t")) != -1) {
60 /*-- Options supported by any rpcgen that we don't support. --*/
61 case 'D': case 'T': case 'K': case 'l': case 'm': case 't':
63 error ("option '%c' is not supported by this PortableXDR rpcgen.\nYou may need to use an alternative rpcgen program instead.", opt);
65 /*-- Options supported only by GNU rpcgen that we don't support. --*/
67 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);
69 /*-- Options supported only by BSD rpcgen that we don't support. --*/
70 case 'A': case 'M': case 'L': case 'S':
71 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);
73 /*-- Options that we do support. --*/
75 output_modes |= 1 << output_c;
79 output_modes |= 1 << output_h;
86 /* None of the other versions of rpcgen support a way to print
87 * the version number, which is extremely annoying because
88 * there are so many different variations of rpcgen around.
89 * So this option at least should be useful!
103 error ("expected name of input file after options");
105 while (optind < argc) {
106 filename = argv[optind++];
108 if (output_modes == 0) {
109 output_mode = output_h;
110 do_rpcgen (filename, out);
111 output_mode = output_c;
112 do_rpcgen (filename, out);
114 if ((output_modes & (1 << output_h)) != 0) {
115 output_mode = output_h;
116 do_rpcgen (filename, out);
118 if ((output_modes & (1 << output_c)) != 0) {
119 output_mode = output_c;
120 do_rpcgen (filename, out);
131 printf ("PortableXDR rpcgen %s\n", PACKAGE_VERSION);
135 usage (const char *progname)
139 ("Generate XDR bindings automatically.\n"
142 " portable-rpcgen infile.x\n"
143 " portable-rpcgen -c|-h [-o outfile] infile.x\n"
144 " portable-rpcgen -V\n"
147 " -c Generate C output file only.\n"
148 " -h Generate header output file only.\n"
149 " -o Name of output file (normally it is 'infile.[ch]').\n"
150 " -V Print the version and exit.\n"
152 "In the first form, without -c or -h, we generate both output files.\n"
154 "You can also list more than one input file on the command line, in\n"
155 "which case each input file is processed separately.\n"
161 /* This is a global so the error functions can delete the output file. */
162 const char *output_filename = NULL;
163 int unlink_output_filename;
165 /* Called for each input file. */
167 do_rpcgen (const char *filename, const char *out)
169 char *cmd, *t = NULL;
173 /* Open the output file. */
174 switch (output_mode) {
175 case output_c: ext = ".c"; break;
176 case output_h: ext = ".h"; break;
177 default: error ("internal error in do_rpcgen / output_mode");
180 if (out && strcmp (out, "-") == 0) {
181 output_filename = NULL;
182 unlink_output_filename = 0;
186 output_filename = out;
187 unlink_output_filename = 1;
188 yyout = fopen (output_filename, "w");
190 perrorf ("%s", output_filename);
193 len = strlen (filename);
194 t = malloc (len + 3);
197 strcpy (t, filename);
198 if (len >= 2 && strcmp (t + len - 2, ".x") == 0)
199 strcpy (t + len - 2, ext);
203 unlink_output_filename = 1;
204 yyout = fopen (output_filename, "w");
206 perrorf ("%s", output_filename);
209 free (input_filename);
210 input_filename = NULL;
212 /* Make the CPP command and open a pipe. */
213 cmd = make_cpp_command (filename);
215 yyin = popen (cmd, "r");
220 gen_prologue (filename);
222 /* Parse the input file, this also generates the output as a side-effect. */
227 error ("parsing failed, file is not a valid rpcgen input");
229 error ("parsing failed because we ran out of memory");
235 output_filename = NULL;
236 unlink_output_filename = 0;
238 free (input_filename);
239 input_filename = NULL;
244 /* Concatenate $EXTCPP and filename, and make sure the filename is
245 * quoted correctly. Tedious.
248 make_cpp_command (const char *filename)
250 static const char good[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.";
251 #define is_good(c) (strchr (good, (c)) != NULL)
254 /* We can use start_string etc. because this function is only used
255 * outside the scanner.
261 for (p = filename; *p; p++) {
262 if (is_good (*p)) add_char (*p);
269 return end_string ();
272 /* Some fairly random functions which are used by the scanner for
273 * constructing strings, reporting errors, etc.
276 /* The scanner sets this to the name of the input file (from cpp)
279 char *input_filename = NULL;
281 static char *str = NULL;
282 static int str_used, str_alloc;
288 error ("scanner called start_string without calling end_string");
292 str = malloc (str_alloc);
293 if (!str) perrorf ("malloc");
302 error ("scanner called end_string without calling start_string");
304 s = realloc (str, str_used+1);
305 if (!s) perrorf ("realloc");
316 while (str_used >= str_alloc) {
318 str = realloc (str, str_alloc);
319 if (!str) perrorf ("realloc");
325 add_string (const char *s)
328 int len = strlen (s);
331 while (str_used >= str_alloc) {
333 str = realloc (str, str_alloc);
334 if (!str) perrorf ("realloc");
336 memcpy (str+i, s, len);
340 error (const char *fs, ...)
344 if (output_filename && unlink_output_filename)
345 unlink (output_filename);
347 if (input_filename == NULL)
348 fputs (PACKAGE, stderr);
350 fprintf (stderr, "%s:%d", input_filename, yylineno);
351 fputs (": ", stderr);
354 vfprintf (stderr, fs, arg);
357 fputc ('\n', stderr);
363 perrorf (const char *fs, ...)
368 if (output_filename && unlink_output_filename)
369 unlink (output_filename);
371 if (input_filename == NULL)
372 fputs (PACKAGE, stderr);
374 fprintf (stderr, "%s:%d", input_filename, yylineno);
375 fputs (": ", stderr);
378 vfprintf (stderr, fs, arg);
381 fputs (": ", stderr);