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