new copyright; att/bsd/shared
[unix-history] / usr / src / usr.bin / pascal / pmerge / pmerge.c
CommitLineData
505bf312
KB
1/*-
2 * Copyright (c) 1980 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
252367af 6 */
1d0a5d33 7
252367af
DF
8#ifndef lint
9char copyright[] =
505bf312 10"@(#) Copyright (c) 1980 The Regents of the University of California.\n\
252367af 11 All rights reserved.\n";
505bf312 12#endif /* not lint */
252367af
DF
13
14#ifndef lint
505bf312
KB
15static char sccsid[] = "@(#)pmerge.c 5.3 (Berkeley) %G%";
16#endif /* not lint */
1d0a5d33
KM
17
18#include <ctype.h>
19#include <stdio.h>
c35e0be0
DS
20#include <string.h>
21#include <stdlib.h>
22#include <unistd.h>
1d0a5d33
KM
23#include <signal.h>
24
25#define PRGFILE 0
26#define LABELFILE 1
27#define CONSTFILE 2
28#define TYPEFILE 3
29#define VARFILE 4
30#define RTNFILE 5
31#define BODYFILE 6
32#define NUMFILES 7
33
34#define TRUE 1
35#define FALSE 0
36#define MAXINCL 9
37#define MAXNAM 75
38#define TMPNAME "/usr/tmp/MGXXXXXX"
39
40FILE *files[NUMFILES];
41char *names[NUMFILES];
42FILE *curfile; /* current output file */
1d0a5d33 43char labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE;
1d0a5d33
KM
44
45/*
46 * Remove temporary files if interrupted
47 */
c35e0be0
DS
48void
49onintr(unused)
1d0a5d33
KM
50{
51 int i;
52
53 for (i = 0; i < NUMFILES; i++)
54 if (files[i] != NULL)
55 unlink(names[i]);
56}
57
58/*
59 * Program to merge separately compiled pascal modules into a
60 * single standard Pascal program.
61 */
62main(argc, argv)
63 long argc;
64 char **argv;
65{
66 FILE *incl[MAXINCL]; /* include stack */
67 long inclcnt = 0; /* incl index */
68 char *name[MAXNAM]; /* include names seen so far */
69 long namcnt = 0; /* next name ptr slot available */
df82ec71 70 char *nambuf; /* string table for names */
1d0a5d33 71 char line[BUFSIZ]; /* input line buffer */
df82ec71 72 char *next; /* next name space available */
1d0a5d33
KM
73 FILE *input = stdin; /* current input file */
74 long ac = 0; /* argv index */
75 char **cpp, *cp, *fp;/* char ptrs */
02ce5298 76 char quote; /* include quote character */
1d0a5d33
KM
77 int i; /* index var */
78
df82ec71
GL
79 for (i = 0; i < MAXNAM ; i++)
80 name[i] = 0;
81
1d0a5d33 82 signal(SIGINT, onintr);
df82ec71 83
c35e0be0
DS
84 curfile = files[PRGFILE] =
85 fopen(names[PRGFILE] = mktemp(strdup(TMPNAME)), "w");
86 files[LABELFILE] =
87 fopen(names[LABELFILE] = mktemp(strdup(TMPNAME)), "w");
88 files[CONSTFILE] =
89 fopen(names[CONSTFILE] = mktemp(strdup(TMPNAME)), "w");
90 files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(strdup(TMPNAME)), "w");
91 files[VARFILE] = fopen(names[VARFILE] = mktemp(strdup(TMPNAME)), "w");
92 files[RTNFILE] = fopen(names[RTNFILE] = mktemp(strdup(TMPNAME)), "w");
93 files[BODYFILE] = fopen(names[BODYFILE] = mktemp(strdup(TMPNAME)), "w");
df82ec71 94
1d0a5d33
KM
95 for (i = 0; i < NUMFILES; i++)
96 if (files[i] == NULL)
97 quit(names[i]);
df82ec71
GL
98 if ((nambuf = malloc(BUFSIZ)) == NULL) {
99 fputs("no space for string table\n", stderr);
100 quit(NULL);
101 }
102 next = nambuf;
1d0a5d33
KM
103 name[namcnt] = next;
104 for(;;) {
105 if (inclcnt > 0) {
106 inclcnt--;
107 fclose(input);
108 input = incl[inclcnt];
109 } else if (++ac < argc) {
110 input = freopen(argv[ac], "r", input);
111 if (input == NULL)
112 quit(argv[ac]);
113 } else {
114 printout();
c35e0be0 115 onintr(0);
1d0a5d33
KM
116 exit(0);
117 }
118 fgets(line, BUFSIZ, input);
119 while (!feof(input)) {
120 if (line[0] != '#') {
121 split(line);
122 fgets(line, BUFSIZ, input);
123 continue;
124 }
125 for (cp = &line[1]; isspace(*cp); cp++)
126 /* void */;
b14de798 127 if (strncmp("include", cp, 7))
1d0a5d33
KM
128 goto bad;
129 for (cp += 7; isspace(*cp); cp++)
130 /* void */;
131 if (*cp != '\'' && *cp != '"')
132 goto bad;
df82ec71
GL
133 if (&nambuf[BUFSIZ] < next + strlen(cp)) {
134 if ((nambuf = malloc(BUFSIZ)) == NULL) {
135 fputs("no space for string table\n",
136 stderr);
137 quit(NULL);
138 }
139 next = nambuf;
140 name[namcnt] = next;
141 }
02ce5298
KM
142 for (fp = next, quote = *cp++;
143 *cp != '\0' && *cp != quote; )
1d0a5d33 144 *fp++ = *cp++;
02ce5298 145 if (*cp != quote &&
1d0a5d33
KM
146 (fp[-1] != 'i' || fp[-1] != 'h') &&
147 (fp[-2] != '.'))
148 goto bad;
149 *fp++ = '\0';
150 for (cpp = name; *cpp < next && strcmp(*cpp, next); )
151 cpp++;
152 if (*cpp == next) {
153 if (inclcnt == MAXINCL) {
154 fputs("include table overflow\n",
155 stderr);
156 quit(NULL);
157 }
df82ec71 158 if (++namcnt == MAXNAM) {
1d0a5d33
KM
159 fputs("include name table overflow\n",
160 stderr);
161 quit(NULL);
162 }
163 incl[inclcnt] = input;
164 inclcnt++;
165 input = fopen(next, "r");
166 if (input == NULL)
167 quit(next);
168 next = fp;
169 name[namcnt] = next;
170 }
171 fgets(line, BUFSIZ, input);
172 }
173 }
174bad:
175 fputs("bad include format:", stderr);
176 fputs(line, stderr);
177 quit(NULL);
178}
179
180/*
181 * Split up output into the approprite files
182 */
183char incom = FALSE; /* TRUE => in comment */
184char incur = FALSE; /* TRUE => in (* *) style comment */
185char inbrac = FALSE; /* TRUE => in { } style comment */
186char instr = FALSE; /* TRUE => in quoted string */
187char inprog = FALSE; /* TRUE => program statement has been found */
188int beginnest = 0; /* routine nesting level */
189int nest = 0; /* begin block nesting level */
df82ec71 190int paren_level = 0; /* nesting level of parentheses */
1d0a5d33
KM
191
192split(line)
193 char *line;
194{
195 char ch1, *cp; /* input window */
196 char *word; /* ptr to current word */
197 int len; /* length of current word */
198 char prt = TRUE; /* TRUE => print current word */
199
200 ch1 = ' ';
201 cp = line;
202 while (*cp) {
203 switch(*cp) {
df82ec71
GL
204 case '(':
205 if (incom)
206 break;
207 if (*(cp+1) == '*') {
208 fputc(*cp, curfile);
209 cp++;
1d0a5d33
KM
210 incom = TRUE;
211 incur = TRUE;
df82ec71
GL
212 } else {
213 paren_level++;
1d0a5d33
KM
214 }
215 break;
216 case ')':
217 if (incur && ch1 == '*') {
218 incom = FALSE;
219 incur = FALSE;
df82ec71
GL
220 } else if (!incom) {
221 paren_level--;
1d0a5d33
KM
222 }
223 break;
224 case '{':
225 if (!incom) {
226 inbrac = TRUE;
227 incom = TRUE;
228 }
229 break;
230 case '}':
231 if (inbrac) {
232 inbrac = FALSE;
233 incom = FALSE;
234 }
235 break;
236 case '\'':
237 if (!incom) {
238 incom = TRUE;
239 instr = TRUE;
240 } else if (instr) {
241 incom = FALSE;
242 instr = FALSE;
243 }
244 break;
245 }
246 if (incom || !isalpha(*cp)) {
247 fputc(*cp, curfile);
248 ch1 = *cp++;
249 continue;
250 }
251 word = cp;
df82ec71 252 while (isalnum(*cp))
1d0a5d33
KM
253 cp++;
254 len = cp - word;
255 switch (*word) {
256 case 'b':
b14de798 257 if (len == 5 && !strncmp(word, "begin", 5)) {
1d0a5d33
KM
258 if (nest == 0 && beginnest == 0) {
259 if (inprog != 1) {
260 fprintf(stderr,
261 "improper program body");
262 quit(NULL);
263 }
264 curfile = files[BODYFILE];
265 } else {
266 beginnest++;
267 }
268 }
269 break;
270 case 'c':
b14de798 271 if (len == 4 && !strncmp(word, "case", 4)) {
1d0a5d33
KM
272 if (beginnest > 0) {
273 beginnest++;
274 }
275 break;
276 }
b14de798 277 if (len == 5 && !strncmp(word, "const", 5)) {
1d0a5d33
KM
278 if (nest == 0) {
279 prt = FALSE;
280 if (!constopen) {
281 constopen = TRUE;
282 prt = TRUE;
283 }
284 curfile = files[CONSTFILE];
285 }
286 }
287 break;
288 case 'e':
b14de798 289 if (len == 3 && !strncmp(word, "end", 3)) {
1d0a5d33
KM
290 if (beginnest == 1) {
291 nest--;
292 }
293 if (beginnest > 0) {
294 beginnest--;
295 }
296 if (nest < 0) {
297 if (inprog == 1) {
298 inprog = 0;
299 nest = 0;
300 } else {
301 fprintf(stderr, "too many end statements");
302 quit(NULL);
303 }
304 }
305 break;
306 }
b14de798 307 if (len == 8 && !strncmp(word, "external", 8)) {
1d0a5d33
KM
308 fputs("forward", curfile);
309 prt = FALSE;
df82ec71
GL
310 if (paren_level == 0) {
311 nest--;
312 }
1d0a5d33
KM
313 }
314 break;
315 case 'f':
b14de798 316 if (len == 8 && !strncmp(word, "function", 8)) {
1d0a5d33
KM
317 if (nest == 0) {
318 curfile = files[RTNFILE];
319 }
df82ec71
GL
320 if (paren_level == 0) {
321 nest++;
322 }
1d0a5d33
KM
323 break;
324 }
b14de798 325 if (len == 7 && !strncmp(word, "forward", 7)) {
df82ec71
GL
326 if (paren_level == 0) {
327 nest--;
328 }
1d0a5d33
KM
329 }
330 break;
331 case 'l':
b14de798 332 if (len == 5 && !strncmp(word, "label", 5)) {
1d0a5d33
KM
333 if (nest == 0) {
334 prt = FALSE;
335 if (!labelopen) {
336 labelopen = TRUE;
337 prt = TRUE;
338 }
339 curfile = files[LABELFILE];
340 }
341 }
342 break;
343 case 'p':
b14de798 344 if (len == 9 && !strncmp(word, "procedure", 9)) {
1d0a5d33
KM
345 if (nest == 0) {
346 curfile = files[RTNFILE];
347 }
df82ec71
GL
348 if (paren_level == 0) {
349 nest++;
350 }
1d0a5d33
KM
351 break;
352 }
b14de798 353 if (len == 7 && !strncmp(word, "program", 7)) {
1d0a5d33
KM
354 if (nest != 0) {
355 fprintf(stderr, "improper program nesting");
356 quit(NULL);
357 }
358 inprog = 1;
359 curfile = files[PRGFILE];
360 }
361 break;
362 case 't':
b14de798 363 if (len == 4 && !strncmp(word, "type", 4)) {
1d0a5d33
KM
364 if (nest == 0) {
365 prt = FALSE;
366 if (!typeopen) {
367 typeopen = TRUE;
368 prt = TRUE;
369 }
370 curfile = files[TYPEFILE];
371 }
372 }
373 break;
374 case 'v':
b14de798 375 if (len == 3 && !strncmp(word, "var", 3)) {
1d0a5d33
KM
376 if (nest == 0) {
377 prt = FALSE;
378 if (!varopen) {
379 varopen = TRUE;
380 prt = TRUE;
381 }
382 curfile = files[VARFILE];
383 }
384 }
385 break;
386 }
387 if (prt)
388 fprintf(curfile, "%.*s", len, word);
389 prt = TRUE;
390 ch1 = ' ';
391 }
392}
393
394/*
395 * Print out the merged result
396 */
397printout()
398{
399 FILE *fp;
400 int i;
401 char ch;
402
403 for(i = 0; i < NUMFILES; i++) {
404 fp = freopen(names[i], "r", files[i]);
405 if (fp == NULL)
406 quit(names[i]);
407 ch = getc(fp);
408 while (!feof(fp)) {
409 putc(ch,stdout);
410 ch = getc(fp);
411 }
412 }
413}
414
415/*
416 * Die gracefully
417 */
418quit(fp)
419 char *fp;
420{
421 if (fp != NULL)
422 perror(fp);
c35e0be0 423 onintr(0);
1d0a5d33
KM
424 exit(1);
425}