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.\n"
64 "You may need to use an alternative rpcgen program instead.",
67 /*-- Options supported only by GNU rpcgen that we don't support. --*/
69 error ("option '%c' is not supported by this PortableXDR rpcgen.\n"
70 "If you were expecting to use GNU rpcgen, try /usr/bin/rpcgen on a GNU host.",
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.\n"
76 "If you were expecting to use BSD rpcgen, try /usr/bin/rpcgen on a BSD host.",
79 /*-- Options that we do support. --*/
81 output_modes |= 1 << output_c;
85 output_modes |= 1 << output_h;
92 /* None of the other versions of rpcgen support a way to print
93 * the version number, which is extremely annoying because
94 * there are so many different variations of rpcgen around.
95 * So this option at least should be useful!
101 /*-- Usage case. --*/
109 error ("expected name of input file after options");
111 while (optind < argc) {
112 filename = argv[optind++];
114 if (output_modes == 0) {
115 output_mode = output_h;
116 do_rpcgen (filename, out);
117 output_mode = output_c;
118 do_rpcgen (filename, out);
120 if ((output_modes & (1 << output_h)) != 0) {
121 output_mode = output_h;
122 do_rpcgen (filename, out);
124 if ((output_modes & (1 << output_c)) != 0) {
125 output_mode = output_c;
126 do_rpcgen (filename, out);
137 printf ("PortableXDR rpcgen %s\n", PACKAGE_VERSION);
141 usage (const char *progname)
145 ("Generate XDR bindings automatically.\n"
148 " portable-rpcgen infile.x\n"
149 " portable-rpcgen -c|-h [-o outfile] infile.x\n"
150 " portable-rpcgen -V\n"
153 " -c Generate C output file only.\n"
154 " -h Generate header output file only.\n"
155 " -o Name of output file (normally it is 'infile.[ch]').\n"
156 " -V Print the version and exit.\n"
158 "In the first form, without -c or -h, we generate both output files.\n"
160 "You can also list more than one input file on the command line, in\n"
161 "which case each input file is processed separately.\n"
167 /* This is a global so the error functions can delete the output file. */
168 const char *output_filename = NULL;
169 int unlink_output_filename;
171 /* Called for each input file. */
173 do_rpcgen (const char *filename, const char *out)
175 char *cmd, *t = NULL;
179 /* Open the output file. */
180 switch (output_mode) {
181 case output_c: ext = ".c"; break;
182 case output_h: ext = ".h"; break;
183 default: error ("internal error in do_rpcgen / output_mode");
186 if (out && strcmp (out, "-") == 0) {
187 output_filename = NULL;
188 unlink_output_filename = 0;
192 output_filename = out;
193 unlink_output_filename = 1;
194 yyout = fopen (output_filename, "w");
196 perrorf ("%s", output_filename);
199 len = strlen (filename);
200 t = malloc (len + 3);
203 strcpy (t, filename);
204 if (len >= 2 && strcmp (t + len - 2, ".x") == 0)
205 strcpy (t + len - 2, ext);
209 unlink_output_filename = 1;
210 yyout = fopen (output_filename, "w");
212 perrorf ("%s", output_filename);
215 free (input_filename);
216 input_filename = NULL;
218 /* Make the CPP command and open a pipe. */
219 cmd = make_cpp_command (filename);
221 yyin = popen (cmd, "r");
226 gen_prologue (filename);
228 /* Parse the input file, this also generates the output as a side-effect. */
233 error ("parsing failed, file is not a valid rpcgen input");
235 error ("parsing failed because we ran out of memory");
241 output_filename = NULL;
242 unlink_output_filename = 0;
244 free (input_filename);
245 input_filename = NULL;
250 /* Concatenate $EXTCPP and filename, and make sure the filename is
251 * quoted correctly. Tedious.
254 make_cpp_command (const char *filename)
256 static const char good[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.";
257 #define is_good(c) (strchr (good, (c)) != NULL)
260 /* We can use start_string etc. because this function is only used
261 * outside the scanner.
267 for (p = filename; *p; p++) {
268 if (is_good (*p)) add_char (*p);
275 return end_string ();
278 /* Some fairly random functions which are used by the scanner for
279 * constructing strings, reporting errors, etc.
282 /* The scanner sets this to the name of the input file (from cpp)
285 char *input_filename = NULL;
287 static char *str = NULL;
288 static int str_used, str_alloc;
294 error ("scanner called start_string without calling end_string");
298 str = malloc (str_alloc);
299 if (!str) perrorf ("malloc");
308 error ("scanner called end_string without calling start_string");
310 s = realloc (str, str_used+1);
311 if (!s) perrorf ("realloc");
322 while (str_used >= str_alloc) {
324 str = realloc (str, str_alloc);
325 if (!str) perrorf ("realloc");
331 add_string (const char *s)
334 int len = strlen (s);
337 while (str_used >= str_alloc) {
339 str = realloc (str, str_alloc);
340 if (!str) perrorf ("realloc");
342 memcpy (str+i, s, len);
346 error (const char *fs, ...)
350 if (output_filename && unlink_output_filename)
351 unlink (output_filename);
353 if (input_filename == NULL)
354 fputs (PACKAGE, stderr);
356 fprintf (stderr, "%s:%d", input_filename, yylineno);
357 fputs (": ", stderr);
360 vfprintf (stderr, fs, arg);
363 fputc ('\n', stderr);
369 perrorf (const char *fs, ...)
374 if (output_filename && unlink_output_filename)
375 unlink (output_filename);
377 if (input_filename == NULL)
378 fputs (PACKAGE, stderr);
380 fprintf (stderr, "%s:%d", input_filename, yylineno);
381 fputs (": ", stderr);
384 vfprintf (stderr, fs, arg);
387 fputs (": ", stderr);