beta-0.89.2
[luatex.git] / source / texk / web2c / web2c / fixwrites.c
blob2c1f33608c8001dacf89bafbdb2aa10f643f45fd
1 /* fixwrites -- convert Pascal write/writeln's into fprintf's or putc's.
2 Originally by Tim Morgan, October 10, 1987. */
4 #include <w2c/config.h>
5 #include <kpathsea/c-pathmx.h>
7 char buf[BUFSIZ], filename[PATH_MAX], args[100];
8 char *file, *argp, *as, *cmd;
10 int tex = false;
12 /* Replace the last (should be only) newline in S with a null. */
14 static void
15 remove_newline (string s)
17 char *temp = strrchr (s, '\n');
18 if (temp == NULL)
20 fprintf (stderr, "Lost newline somehow.\n");
21 /* This is so the convert script can delete the output file on error. */
22 puts ("@error@");
23 exit (1);
26 *temp = 0;
30 static char *
31 insert_long (string cp)
33 char tbuf[BUFSIZ];
34 register int i;
36 for (i = 0; &buf[i] < cp; ++i)
37 tbuf[i] = buf[i];
38 strcpy (&tbuf[i], "(long)");
39 strcpy (&tbuf[i + 6], cp);
40 strcpy (buf, tbuf);
41 return cp + 6;
45 static void
46 join (string cp)
48 char temp[BUFSIZ], *tp;
50 if (!fgets (temp, BUFSIZ, stdin))
51 return;
52 remove_newline (temp);
54 *cp++ = ' ';
55 for (tp = temp; *tp == ' '; ++tp)
58 strcpy (cp, tp);
62 static void
63 do_blanks (int indent)
65 register int i;
67 for (i = 0; i < indent / 8; i++)
68 putchar ('\t');
69 indent %= 8;
70 for (i = 0; i < indent; i++)
71 putchar (' ');
75 /* Return true if we have a whole write/writeln statement. We determine
76 this by matching parens, ignoring those within strings. */
77 static int
78 whole (string cp)
80 register int depth = 0;
82 while (cp && *cp)
84 switch (*cp)
86 case '(':
87 ++depth;
88 break;
89 case ')':
90 --depth;
91 break;
92 case '"':
93 for (++cp; cp && *cp && *cp != '"'; ++cp)
94 if (*cp == '\\')
95 ++cp;
96 break;
97 case '\'':
98 ++cp;
99 if (*cp == '\\') ++cp;
100 ++cp;
101 break;
103 ++cp;
105 return depth <= 0;
109 /* Skips to the next , or ), skipping over balanced paren pairs. */
111 static char *
112 skip_balanced (string cp)
114 register int depth = 0;
116 while (depth > 0 || (*cp != ',' && *cp != ')'))
118 switch (*cp)
120 case '(':
121 ++depth;
122 break;
123 case ')':
124 --depth;
125 break;
127 ++cp;
129 return cp;
133 /* Return true if c appears, except inside a quoted string */
135 static int
136 bare (string cp, char c)
138 for (; *cp && *cp != c; ++cp)
140 if (*cp == '"')
142 ++cp; /* skip over initial quotation mark */
143 while (*cp && *cp != '"')
144 { /* skip to closing double quote */
145 if (*cp == '\\')
146 ++cp;
147 ++cp;
150 else if (*cp == '\'')
152 ++cp; /* skip to contained char */
153 if (*cp == '\'')
154 ++cp; /* if backslashed, it's double */
155 ++cp; /* skip to closing single-quote mark */
158 return *cp;
162 /* xchr[...] is supposed to be replaced by Xchr(...) when characters
163 take more than a single octet each, as is the case in Aleph. Now
164 there are several occurrences of xchr[...[...]...], which are
165 translated into Xchr(...[...)...], and the compiler dies on syntax
166 errors. Ensures that it is the matching bracket that is replaced,
167 not the first one. */
169 static char *
170 advance_cp (char *cp, int lefts)
172 char *cp1;
173 char *cp2;
175 cp1 = strchr (cp + 1, ']');
176 cp2 = strchr (cp + 1, '[');
177 if (cp2 && cp2 < cp1)
178 return advance_cp (cp2, lefts + 1);
179 if (lefts == 1)
180 return cp1;
181 return advance_cp (cp1, lefts - 1);
184 #ifdef WIN32
185 #include <io.h>
186 #include <fcntl.h>
187 #endif
190 main (int argc, string *argv)
192 register char *cp;
193 int blanks_done, indent, i;
194 const char *program_name = "";
196 #ifdef WIN32
197 setmode(fileno(stdout), _O_BINARY);
198 #endif
199 for (i = 1; i < argc; i++)
201 if (STREQ(argv[i],"-t"))
202 tex = true;
203 else
204 program_name = argv[i];
207 while (fgets (buf, BUFSIZ, stdin))
209 remove_newline (buf);
210 blanks_done = false;
212 for (cp = buf; *cp; ++cp) ;
214 while (cp != buf && *--cp == ' ') ;
216 while (*cp == '.')
218 join (cp + 1);
219 while (*cp)
220 ++cp;
221 while (*--cp == ' ') ;
224 for (cp = buf, indent = 0; *cp == ' ' || *cp == '\t'; ++cp)
226 if (*cp == ' ')
227 indent++;
228 else
229 indent += 8;
232 if (!*cp)
233 { /* All blanks, possibly with "{" */
234 puts (buf);
235 continue;
237 if (*cp == '{')
240 do_blanks (indent);
241 putchar ('{');
242 ++cp;
243 while (*cp == ' ' || *cp == '\t')
244 ++cp;
245 blanks_done = true;
246 if (!*cp)
248 putchar ('\n');
249 continue;
253 if (!blanks_done)
254 do_blanks (indent);
256 if (strncmp (cp, "read ( input", 12) == 0)
258 char variable_name[20];
259 if (sscanf (cp, "read ( input , %s )", variable_name) != 1)
261 fprintf (stderr, "sscanf failed\n");
262 exit (1);
264 printf ("%s = getint();\n", variable_name);
265 continue;
268 if (strncmp (cp, "lab", 3) == 0 && strchr (cp, ':'))
272 putchar (*cp);
274 while (*cp++ != ':');
276 while (*cp == ' ')
277 ++cp;
278 putchar (' ');
281 if (strncmp (cp, "else write", 10) == 0)
283 puts ("else");
284 do_blanks (indent);
285 cp += 5;
286 while (*cp == ' ')
287 ++cp;
290 if (bare (cp, '{'))
292 while (*cp != '{')
294 putchar (*cp);
295 ++cp;
297 ++cp;
298 puts ("{");
299 indent += 4;
300 do_blanks (indent);
301 while (*cp == ' ')
302 ++cp;
305 if (strncmp (cp, "write (", 7) && strncmp (cp, "writeln (", 9))
307 /* if not a write/writeln, just copy it to stdout and continue */
308 puts (cp);
309 continue;
311 cmd = cp;
312 while (!whole (buf)) /* make sure we have whole stmt */
314 fgets (&buf[strlen (buf)], BUFSIZ - strlen (buf), stdin);
315 remove_newline (buf);
318 while (*cp != '(')
319 ++cp;
320 ++cp;
321 while (*(cp + 1) == ' ')
322 ++cp;
324 /* Some writes start with a variable, instead of a file. */
325 if (*(cp + 1) == '"' || *(cp + 1) == '\''
326 || strncmp (cp + 1, "buffer", 6) == 0
327 || strncmp (cp + 1, "xchr", 4) == 0
328 || strncmp (cp + 1, "k ,", 3) == 0
329 || strncmp (cp + 1, "s ,", 3) == 0
330 || strncmp (cp + 1, "dig", 3) == 0
331 || strncmp (cp + 1, "HEX", 3) == 0
332 || strncmp (cp + 1, "versionstring", 13) == 0
333 || strncmp (cp + 1, "kpathseaversionstring", 21) == 0
335 strcpy (filename, "stdout");
336 else
338 file = filename;
339 while (*cp != ',' && *cp != ')')
340 *file++ = *cp++;
341 *file = '\0';
343 if (*cp == ')')
345 printf ("putc ('\\n', %s);\n", filename);
346 continue;
348 argp = ++cp;
349 as = args;
350 while (*cp == ' ')
351 ++cp;
352 while (*cp != ')')
354 if (*cp == '\'' || strncmp (cp, "xchr", 4) == 0
355 || (strncmp (cp ,"HEX", 3) == 0
356 && (STREQ (program_name, "ofm2opl")
357 || STREQ (program_name, "opl2ofm")
358 || STREQ (program_name, "ovp2ovf")
359 || STREQ (program_name, "ovf2ovp")))
360 || strncmp (cp, "ASCII04", 7) == 0
361 || strncmp (cp, "ASCII1", 6) == 0
362 || strncmp (cp, "ASCIIall", 8) == 0
363 || strncmp (cp, "months", 6) == 0
364 || strncmp (cp, "nameoffile", 10) == 0
365 || (strncmp (cp, "buffer", 6) == 0
366 && (STREQ (program_name, "vptovf")
367 || STREQ (program_name, "pltotf")
368 || STREQ (program_name, "ppltotf")
369 || STREQ (program_name, "uppltotf")
370 || STREQ (program_name, "ovp2ovf")
371 || STREQ (program_name, "opl2ofm")))
372 || (((strncmp (cp, "buf", 3) == 0
373 || strncmp (cp, "xdig", 4) == 0
374 || strncmp (cp, "xext", 4) == 0
375 || strncmp (cp, "xhyf", 4) == 0)
376 && STREQ (program_name, "patgen")))
379 *as++ = '%';
380 *as++ = 'c';
381 if (tex && strncmp (cp, "xchr", 4) == 0)
383 *cp = 'X';
384 cp = strchr (cp, '[');
385 *cp = '(';
386 cp = advance_cp(cp,1);
387 *cp++ = ')';
389 else if (*cp == '\'')
390 cp += 2;
393 else if (*cp == '"')
395 *as++ = '%';
396 *as++ = 's';
397 while (*++cp != '"') /* skip to end of string */
398 if (*cp == '\\')
399 ++cp; /* allow \" in string */
402 /* More kludges -- recognize some things as strings and use %s:
403 - versionstring
404 - poolname
405 - formatengine
406 - dumpname */
407 else if (strncmp (cp, "versionstring", 13) == 0
408 || strncmp (cp, "poolname", 8) == 0
409 || strncmp (cp, "formatengine", 12) == 0
410 || strncmp (cp, "dumpname", 8) == 0)
412 *as++ = '%';
413 *as++ = 's';
416 /* And yet another kludge, to handle stringcast (<whatever>) */
417 else if (strncmp (cp, "stringcast", 10) == 0
418 || strncmp (cp, "conststringcast", 15) == 0)
420 *as++ = '%';
421 *as++ = 's';
422 cp = skip_balanced (cp); /* Skip cast expression */
425 else
427 *as++ = '%';
428 *as++ = 'l';
429 *as++ = 'd';
430 cp = insert_long (cp);
431 cp = skip_balanced (cp); /* It's a numeric expression */
433 while (*cp != ',' && *cp != ')')
434 ++cp;
435 while (*cp == ',' || *cp == ' ')
436 ++cp;
439 if (strncmp (cmd, "writeln", 7) == 0)
441 *as++ = '\\';
442 *as++ = 'n';
445 *as = '\0';
446 if (strcmp (args, "%c") == 0)
448 for (as = argp; *as; ++as) ;
449 while (*--as != ')') ;
450 *as = '\0';
451 printf ("putc (%s, %s);\n", argp, filename);
453 else if (strcmp (args, "%c\\n") == 0)
455 for (as = argp; *as; ++as) ;
456 while (*--as != ')') ;
457 *as = '\0';
458 printf ("{ putc (%s, %s); ", argp, filename);
459 printf ("putc ( '\\n', %s); }\n", filename);
461 else if (strcmp (args, "%s") == 0)
462 printf ("Fputs (%s, %s\n", filename, argp);
463 else
464 printf ("fprintf (%s, \"%s\", %s\n", filename, args, argp);
467 return EXIT_SUCCESS;