Back to index

tetex-bin  3.0
splitup.c
Go to the documentation of this file.
00001 /* splitup -- take TeX or MF in C as a single stream on stdin,
00002    and it produces several .c and .h files in the current directory
00003    as its output.
00004 
00005    Tim Morgan  September 19, 1987.  */
00006 
00007 #include "config.h"
00008 #include <kpathsea/getopt.h>
00009 
00010 #ifdef VMS
00011 #define unlink delete
00012 #endif
00013 
00014 char *program_invocation_name;
00015 int filenumber = 0, ifdef_nesting = 0, lines_in_file = 0;
00016 char *output_name = NULL;
00017 boolean has_ini;
00018 
00019 /* This used to be a fixed 2000, but since bibtex.c is almost 10000 lines
00020    (200+K), we may as well decrease the number of split files we create.
00021    Probably faster for the compiler, definitely faster for the linker,
00022    simpler for the Makefiles, and generally better.  Now we specify this
00023    in 'convert'. */
00024 long int max_lines;
00025 
00026 /* Do we split out a separate *ini.c file? */
00027 boolean do_ini;
00028 
00029 /* Don't need long filenames, since we generate them all.  */
00030 char buffer[1024], tempfile[100], filename[100], ini_name[100];
00031 
00032 FILE *out, *ini, *temp;
00033 
00034 /*
00035  * Read a line of input into the buffer, returning `false' on EOF.
00036  * If the line is of the form "#ifdef INI...", we set "has_ini"
00037  * `true' else `false'.  We also keep up with the #ifdef/#endif nesting
00038  * so we know when it's safe to finish writing the current file.
00039  */
00040 int
00041 read_line P1H(void)
00042 {
00043   if (fgets (buffer, sizeof (buffer), stdin) == NULL)
00044     return false;
00045   if (strncmp (buffer, "#ifdef", 6) == 0
00046       || strncmp (buffer, "#ifndef", 7) == 0)
00047     {
00048       ++ifdef_nesting;
00049       if (strncmp (&buffer[7], "INI", 3) == 0)
00050        has_ini = true;
00051     }
00052   else if (strncmp (buffer, "#endif", 6) == 0)
00053     --ifdef_nesting;
00054   return true;
00055 }
00056 
00057 int
00058 main P2C(int, argc, string *, argv)
00059 {
00060   string coerce;
00061   unsigned coerce_len;
00062   int option;
00063 
00064   program_invocation_name = argv[0];
00065   
00066   while ((option = getopt(argc, argv, "il:")) != -1) {
00067     switch (option) {
00068     case 'i':
00069       do_ini = true;
00070       break;
00071     case 'l':
00072       max_lines = atoi(optarg);
00073       if (max_lines <= 0)
00074         FATAL("[-i] [-l lines] name");
00075       break;
00076     default:
00077       FATAL("[-i] [-l lines] name");
00078       break;
00079     }
00080   }
00081   if (optind + 1 != argc)
00082     FATAL("[-i] [-l lines] name");
00083   output_name = argv[optind];
00084 
00085   sprintf (filename, "%sd.h", output_name);
00086   sprintf (tempfile, "%s.tmp", output_name);
00087   out = xfopen (filename, FOPEN_W_MODE);
00088   fputs ("#undef TRIP\n#undef TRAP\n", out);
00089   /* We have only one binary that can do both ini stuff and vir stuff.  */
00090   fputs ("#define STAT\n#define INI\n", out);
00091   
00092   if (STREQ (output_name, "mf")) {
00093     fputs ("#define INIMF\n#define MF\n", out);
00094     coerce = "mfcoerce.h";
00095   } else if (STREQ (output_name, "tex")) {
00096     fputs ("#define INITEX\n#define TeX\n", out);
00097     coerce = "texcoerce.h";
00098   } else if (STREQ (output_name, "aleph")) {
00099     fputs ("#define INITEX\n#define TeX\n#define Aleph\n", out);
00100     coerce = "alephcoerce.h";
00101   } else if (STREQ (output_name, "eomega")) {
00102     fputs ("#define INITEX\n#define TeX\n#define eOmega\n", out);
00103     coerce = "eomegacoerce.h";
00104   } else if (STREQ (output_name, "etex")) {
00105     fputs ("#define INITEX\n#define TeX\n#define eTeX\n", out);
00106     coerce = "etexcoerce.h";
00107   } else if (STREQ (output_name, "omega")) {
00108     fputs ("#define INITEX\n#define TeX\n#define Omega\n", out);
00109     coerce = "omegacoerce.h";
00110   } else if (STREQ (output_name, "pdftex")) {
00111     fputs ("#define INITEX\n#define TeX\n#define pdfTeX\n", out);
00112     coerce = "pdftexcoerce.h";
00113   } else if (STREQ (output_name, "pdfetex")) {
00114     fputs ("#define INITEX\n#define TeX\n#define pdfeTeX\n", out);
00115     coerce = "pdfetexcoerce.h";
00116   } else if (STREQ (output_name, "pdfxtex")) {
00117     fputs ("#define INITEX\n#define TeX\n#define pdfxTeX\n", out);
00118     coerce = "pdfxtexcoerce.h";
00119   } else if (STREQ (output_name, "mp")) {
00120     fputs ("#define INIMP\n#define MP\n", out);
00121     coerce = "mpcoerce.h";
00122   } else
00123     FATAL1 ("Can only split mf, mp, tex, etex, omega, eomega, aleph, or pdf[ex]tex,\n not %s", output_name);
00124   
00125   coerce_len = strlen (coerce);
00126   
00127   /* Read everything up to coerce.h.  */
00128   while (fgets (buffer, sizeof (buffer), stdin))
00129     {
00130       if (strncmp (&buffer[10], coerce, coerce_len) == 0)
00131        break;
00132 
00133       if (buffer[0] == '#' || buffer[0] == '\n' || buffer[0] == '}'
00134          || buffer[0] == '/' || buffer[0] == ' '
00135          || strncmp (buffer, "typedef", 7) == 0)
00136        /*nothing */ ;
00137       else
00138        fputs ("EXTERN ", out);
00139 
00140       fputs (buffer, out);
00141     }
00142 
00143   if (strncmp (&buffer[10], coerce, coerce_len) != 0)
00144     FATAL1 ("No #include %s line", coerce);
00145 
00146   fputs (buffer, out);
00147   xfclose (out, filename);
00148 
00149   if (do_ini) {
00150     sprintf (ini_name, "%sini.c", output_name);
00151     ini = xfopen (ini_name, FOPEN_W_MODE);
00152     fputs ("#define EXTERN extern\n", ini);
00153     fprintf (ini, "#include \"%sd.h\"\n\n", output_name);
00154   }
00155 
00156   sprintf (filename, "%s0.c", output_name);
00157   out = xfopen (filename, FOPEN_W_MODE);
00158   fputs ("#define EXTERN extern\n", out);
00159   fprintf (out, "#include \"%sd.h\"\n\n", output_name);
00160 
00161   do
00162     {
00163       /* Read one routine into a temp file */
00164       has_ini = false;
00165       temp = xfopen (tempfile, "w+");
00166 
00167       while (read_line ())
00168        {
00169          fputs (buffer, temp);
00170          if (buffer[0] == '}')
00171            break;           /* End of procedure */
00172        }
00173       while (ifdef_nesting > 0 && read_line ())
00174        fputs (buffer, temp);
00175       rewind (temp);
00176 
00177       if (do_ini && has_ini)
00178        {                    /* Contained "#ifdef INI..." */
00179          while (fgets (buffer, sizeof (buffer), temp))
00180            fputs (buffer, ini);
00181        }
00182       else
00183        {                    /* Doesn't contain "#ifdef INI..." */
00184          while (fgets (buffer, sizeof (buffer), temp))
00185            {
00186              fputs (buffer, out);
00187              lines_in_file++;
00188            }
00189        }
00190       xfclose (temp, tempfile);
00191 
00192       /* Switch to new output file.  */
00193       if (max_lines && lines_in_file > max_lines)
00194        {
00195          xfclose (out, filename);
00196          sprintf (filename, "%s%d.c", output_name, ++filenumber);
00197          out = xfopen (filename, FOPEN_W_MODE);
00198          fputs ("#define EXTERN extern\n", out);
00199          fprintf (out, "#include \"%sd.h\"\n\n", output_name);
00200          lines_in_file = 0;
00201        }
00202     }
00203   while (!feof (stdin));
00204 
00205   xfclose (out, filename);
00206   if (lines_in_file == 0)
00207     unlink (filename);
00208 
00209   if (do_ini)
00210     xfclose (ini, ini_name);
00211 
00212   if (unlink (tempfile)) {
00213       perror (tempfile);
00214       exit (EXIT_FAILURE);
00215   }
00216 
00217   return EXIT_SUCCESS;
00218 }