1 /* splitup -- take TeX or MF in C as a single stream on stdin,
2 and it produces several .c and .h files in the current directory
3 as its output.
4
5 $Id: splitup.c 27708 2012-09-18 17:43:20Z peter $
6
7 Tim Morgan September 19, 1987. */
8
9 #include <w2c/config.h>
10 #include <kpathsea/getopt.h>
11
12 #if defined (FATAL)
13 #undef FATAL
14 #endif
15
16 #define FATAL(str) do { \
17 fprintf (stderr, "%s: fatal: ", argv[0]); \
18 fputs (str, stderr); \
19 fputs (".\n", stderr); exit (1); } while (0)
20
21
22 #if defined (FATAL1)
23 #undef FATAL1
24 #endif
25
26 #define FATAL1(str, e1) do { \
27 fprintf (stderr, "%s: fatal: ", argv[0]); \
28 fprintf (stderr, str, e1); \
29 fputs (".\n", stderr); exit (1); } while (0)
30
31
32 #ifdef VMS
33 #define unlink delete
34 #endif
35
36 int filenumber = 0, ifdef_nesting = 0, lines_in_file = 0;
37 char *output_name = NULL;
38 boolean has_ini;
39
40 /* This used to be a fixed 2000, but since bibtex.c is almost 10000 lines
41 (200+K), we may as well decrease the number of split files we create.
42 Probably faster for the compiler, definitely faster for the linker,
43 simpler for the Makefiles, and generally better. Now we specify this
44 in 'convert'. */
45 long int max_lines;
46
47 /* Do we split out a separate *ini.c file? */
48 boolean do_ini;
49
50 /* Don't need long filenames, since we generate them all. */
51 char buffer[1024], tempfile[100], filename[100], ini_name[100];
52
53 FILE *out, *ini, *temp;
54
55 /*
56 * Read a line of input into the buffer, returning `false' on EOF.
57 * If the line is of the form "#ifdef INI...", we set "has_ini"
58 * `true' else `false'. We also keep up with the #ifdef/#endif nesting
59 * so we know when it's safe to finish writing the current file.
60 */
61 static int
read_line(void)62 read_line (void)
63 {
64 if (fgets (buffer, sizeof (buffer), stdin) == NULL)
65 return false;
66 if (strncmp (buffer, "#ifdef", 6) == 0
67 || strncmp (buffer, "#ifndef", 7) == 0)
68 {
69 ++ifdef_nesting;
70 if (strncmp (&buffer[7], "INI", 3) == 0)
71 has_ini = true;
72 }
73 else if (strncmp (buffer, "#endif", 6) == 0)
74 --ifdef_nesting;
75 return true;
76 }
77
78 #ifdef WIN32
79 #include <io.h>
80 #include <fcntl.h>
81 #endif
82
83 int
main(int argc,string * argv)84 main (int argc, string *argv)
85 {
86 const_string coerce;
87 unsigned coerce_len;
88 int option;
89
90 #ifdef WIN32
91 setmode(fileno(stdout), _O_BINARY);
92 #endif
93
94 while ((option = getopt(argc, argv, "il:")) != -1) {
95 switch (option) {
96 case 'i':
97 do_ini = true;
98 break;
99 case 'l':
100 max_lines = atoi(optarg);
101 if (max_lines <= 0)
102 FATAL("[-i] [-l lines] name");
103 break;
104 default:
105 FATAL("[-i] [-l lines] name");
106 break;
107 }
108 }
109 if (optind + 1 != argc)
110 FATAL("[-i] [-l lines] name");
111 output_name = argv[optind];
112
113 sprintf (filename, "%sd.h", output_name);
114 sprintf (tempfile, "%s.tmp", output_name);
115 out = xfopen (filename, FOPEN_W_MODE);
116 fputs ("#undef TRIP\n#undef TRAP\n", out);
117 /* We have only one binary that can do both ini stuff and vir stuff. */
118 fputs ("#define STAT\n#define INI\n", out);
119
120 if (STREQ (output_name, "mf")) {
121 fputs ("#define INIMF\n#define MF\n", out);
122 coerce = "mfcoerce.h";
123 } else if (STREQ (output_name, "tex")) {
124 fputs ("#define INITEX\n#define TeX\n#define onlyTeX\n", out);
125 coerce = "texcoerce.h";
126 } else if (STREQ (output_name, "aleph")) {
127 fputs ("#define INITEX\n#define TeX\n#define Aleph\n", out);
128 coerce = "alephcoerce.h";
129 } else if (STREQ (output_name, "etex")) {
130 fputs ("#define INITEX\n#define TeX\n#define eTeX\n", out);
131 coerce = "etexcoerce.h";
132 } else if (STREQ (output_name, "pdftex")) {
133 fputs ("#define INITEX\n#define TeX\n#define pdfTeX\n", out);
134 coerce = "pdftexcoerce.h";
135 } else if (STREQ (output_name, "ptex")) {
136 fputs ("#define INITEX\n#define TeX\n#define pTeX\n", out);
137 coerce = "ptexcoerce.h";
138 } else if (STREQ (output_name, "eptex")) {
139 fputs ("#define INITEX\n#define TeX\n#define epTeX\n", out);
140 coerce = "eptexcoerce.h";
141 } else if (STREQ (output_name, "euptex")) {
142 fputs ("#define INITEX\n#define TeX\n#define eupTeX\n", out);
143 coerce = "euptexcoerce.h";
144 } else if (STREQ (output_name, "uptex")) {
145 fputs ("#define INITEX\n#define TeX\n#define upTeX\n", out);
146 coerce = "uptexcoerce.h";
147 } else if (STREQ (output_name, "xetex")) {
148 fputs ("#define INITEX\n#define TeX\n#define XeTeX\n", out);
149 coerce = "xetexcoerce.h";
150 } else
151 FATAL1 ("Can only split mf, tex, aleph, eptex, euptex, etex, pdftex, ptex, uptex, or xetex,\n not %s", output_name);
152
153 coerce_len = strlen (coerce);
154
155 /* Read everything up to coerce.h. */
156 while (fgets (buffer, sizeof (buffer), stdin))
157 {
158 if (strncmp (&buffer[10], coerce, coerce_len) == 0)
159 break;
160
161 if (buffer[0] == '#' || buffer[0] == '\n' || buffer[0] == '}'
162 || buffer[0] == '/' || buffer[0] == ' '
163 || strncmp (buffer, "typedef", 7) == 0)
164 /*nothing */ ;
165 else
166 fputs ("EXTERN ", out);
167
168 fputs (buffer, out);
169 }
170
171 if (strncmp (&buffer[10], coerce, coerce_len) != 0)
172 FATAL1 ("No #include %s line", coerce);
173
174 fputs (buffer, out);
175 xfclose (out, filename);
176
177 if (do_ini) {
178 sprintf (ini_name, "%sini.c", output_name);
179 ini = xfopen (ini_name, FOPEN_W_MODE);
180 fputs ("#define EXTERN extern\n", ini);
181 fprintf (ini, "#include \"%sd.h\"\n\n", output_name);
182 }
183
184 sprintf (filename, "%s0.c", output_name);
185 out = xfopen (filename, FOPEN_W_MODE);
186 fputs ("#define EXTERN extern\n", out);
187 fprintf (out, "#include \"%sd.h\"\n\n", output_name);
188
189 do
190 {
191 /* Read one routine into a temp file */
192 has_ini = false;
193 temp = xfopen (tempfile, "wb+");
194
195 while (read_line ())
196 {
197 fputs (buffer, temp);
198 if (buffer[0] == '}')
199 break; /* End of procedure */
200 }
201 while (ifdef_nesting > 0 && read_line ())
202 fputs (buffer, temp);
203 rewind (temp);
204
205 if (do_ini && has_ini)
206 { /* Contained "#ifdef INI..." */
207 while (fgets (buffer, sizeof (buffer), temp))
208 fputs (buffer, ini);
209 }
210 else
211 { /* Doesn't contain "#ifdef INI..." */
212 while (fgets (buffer, sizeof (buffer), temp))
213 {
214 fputs (buffer, out);
215 lines_in_file++;
216 }
217 }
218 xfclose (temp, tempfile);
219
220 /* Switch to new output file. */
221 if (max_lines && lines_in_file > max_lines)
222 {
223 xfclose (out, filename);
224 sprintf (filename, "%s%d.c", output_name, ++filenumber);
225 out = xfopen (filename, FOPEN_W_MODE);
226 fputs ("#define EXTERN extern\n", out);
227 fprintf (out, "#include \"%sd.h\"\n\n", output_name);
228 lines_in_file = 0;
229 }
230 }
231 while (!feof (stdin));
232
233 xfclose (out, filename);
234 if (lines_in_file == 0)
235 unlink (filename);
236
237 if (do_ini)
238 xfclose (ini, ini_name);
239
240 if (unlink (tempfile)) {
241 perror (tempfile);
242 exit (EXIT_FAILURE);
243 }
244
245 return EXIT_SUCCESS;
246 }
247