Commit | Line | Data |
---|---|---|
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 |
9 | char 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 |
15 | static 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 | ||
40 | FILE *files[NUMFILES]; | |
41 | char *names[NUMFILES]; | |
42 | FILE *curfile; /* current output file */ | |
1d0a5d33 | 43 | char labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE; |
1d0a5d33 KM |
44 | |
45 | /* | |
46 | * Remove temporary files if interrupted | |
47 | */ | |
c35e0be0 DS |
48 | void |
49 | onintr(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 | */ | |
62 | main(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 | } | |
174 | bad: | |
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 | */ | |
183 | char incom = FALSE; /* TRUE => in comment */ | |
184 | char incur = FALSE; /* TRUE => in (* *) style comment */ | |
185 | char inbrac = FALSE; /* TRUE => in { } style comment */ | |
186 | char instr = FALSE; /* TRUE => in quoted string */ | |
187 | char inprog = FALSE; /* TRUE => program statement has been found */ | |
188 | int beginnest = 0; /* routine nesting level */ | |
189 | int nest = 0; /* begin block nesting level */ | |
df82ec71 | 190 | int paren_level = 0; /* nesting level of parentheses */ |
1d0a5d33 KM |
191 | |
192 | split(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 | */ | |
397 | printout() | |
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 | */ | |
418 | quit(fp) | |
419 | char *fp; | |
420 | { | |
421 | if (fp != NULL) | |
422 | perror(fp); | |
c35e0be0 | 423 | onintr(0); |
1d0a5d33 KM |
424 | exit(1); |
425 | } |