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