#include "rpcgen_int.h"
+enum output_mode output_mode;
+
static void print_version (void);
static void usage (const char *progname);
-static void do_rpcgen (const char *filename);
+static void do_rpcgen (const char *filename, const char *out);
static char *make_cpp_command (const char *filename);
-/* Symbols exported from the scanner. */
-extern FILE *yyin, *yyout;
-extern int yyparse (void);
-extern int yylineno;
-extern int yydebug;
-
int
main (int argc, char *argv[])
{
int opt;
+ char *filename;
+ int output_modes = 0;
+ char *out = NULL;
- /* To enable debugging in the parser, you also need to compile
- * with -DYYDEBUG
- */
-#if 0
+#if YYDEBUG
yydebug = 1;
#endif
/*-- Options that we do support. --*/
case 'c':
+ output_modes |= 1 << output_c;
+ break;
+
case 'h':
+ output_modes |= 1 << output_h;
+ break;
+
case 'o':
- ;
+ out = optarg;
+ break;
/* None of the other versions of rpcgen support a way to print
* the version number, which is extremely annoying because
if (optind >= argc)
error ("expected name of input file after options");
- while (optind < argc)
- do_rpcgen (argv[optind++]);
+ while (optind < argc) {
+ filename = argv[optind++];
+
+ if (output_modes == 0) {
+ output_mode = output_h;
+ do_rpcgen (filename, out);
+ output_mode = output_c;
+ do_rpcgen (filename, out);
+ } else {
+ if ((output_modes & (1 << output_h)) != 0) {
+ output_mode = output_h;
+ do_rpcgen (filename, out);
+ }
+ if ((output_modes & (1 << output_c)) != 0) {
+ output_mode = output_c;
+ do_rpcgen (filename, out);
+ }
+ }
+ }
exit (0);
}
exit (0);
}
+/* This is a global so the error functions can delete the output file. */
+const char *output_filename = NULL;
+int unlink_output_filename;
+
/* Called for each input file. */
static void
-do_rpcgen (const char *filename)
+do_rpcgen (const char *filename, const char *out)
{
- char *cmd;
- int r;
+ char *cmd, *t = NULL;
+ int r, len;
+ const char *ext;
+
+ /* Open the output file. */
+ switch (output_mode) {
+ case output_c: ext = ".c"; break;
+ case output_h: ext = ".h"; break;
+ default: error ("internal error in do_rpcgen / output_mode");
+ }
+
+ if (out && strcmp (out, "-") == 0) {
+ output_filename = NULL;
+ unlink_output_filename = 0;
+ yyout = stdout;
+ }
+ else if (out) {
+ output_filename = out;
+ unlink_output_filename = 1;
+ yyout = fopen (output_filename, "w");
+ if (yyout == NULL)
+ perrorf ("%s", output_filename);
+ }
+ else {
+ len = strlen (filename);
+ t = malloc (len + 3);
+ if (t == NULL)
+ perrorf ("malloc");
+ strcpy (t, filename);
+ if (len >= 2 && strcmp (t + len - 2, ".x") == 0)
+ strcpy (t + len - 2, ext);
+ else
+ strcat (t, ext);
+ output_filename = t;
+ unlink_output_filename = 1;
+ yyout = fopen (output_filename, "w");
+ if (yyout == NULL)
+ perrorf ("%s", output_filename);
+ }
free (input_filename);
input_filename = NULL;
+ /* Make the CPP command and open a pipe. */
cmd = make_cpp_command (filename);
yyin = popen (cmd, "r");
perrorf ("%s", cmd);
free (cmd);
- yyout = stdout;
+ gen_prologue (filename);
- /* Parse the input file. This either succeeds or exits with an error. */
+ /* Parse the input file, this also generates the output as a side-effect. */
r = yyparse ();
pclose (yyin);
else if (r == 2)
error ("parsing failed because we ran out of memory");
+ gen_epilogue ();
+
+ if (yyout != stdout)
+ fclose (yyout);
+ output_filename = NULL;
+ unlink_output_filename = 0;
+
free (input_filename);
input_filename = NULL;
+
+ free (t);
}
/* Concatenate $EXTCPP and filename, and make sure the filename is
{
va_list arg;
+ if (output_filename && unlink_output_filename)
+ unlink (output_filename);
+
if (input_filename == NULL)
fputs (PACKAGE, stderr);
else
va_list arg;
int e = errno;
+ if (output_filename && unlink_output_filename)
+ unlink (output_filename);
+
if (input_filename == NULL)
fputs (PACKAGE, stderr);
else