xref: /original-bsd/usr.bin/pascal/pmerge/pmerge.c (revision 957a0273)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)pmerge.c 1.2 06/09/81";
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 
24 FILE	*files[NUMFILES];
25 char	*names[NUMFILES];
26 FILE	*curfile;		/* current output file */
27 FILE	*fopen();
28 char	labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE;
29 char	*mktemp();
30 
31 /*
32  * Remove temporary files if interrupted
33  */
34 onintr()
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  */
47 main(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 */
61 	char	quote;		/* include quote character */
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;
105 			for (fp = next, quote = *cp++;
106 			     *cp != '\0' && *cp != quote; )
107 				*fp++ = *cp++;
108 			if (*cp != quote &&
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 	}
137 bad:
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  */
146 char incom = FALSE;	/* TRUE => in comment */
147 char incur = FALSE;	/* TRUE => in (* *) style comment */
148 char inbrac = FALSE;	/* TRUE => in { } style comment */
149 char instr = FALSE;	/* TRUE => in quoted string */
150 char inprog = FALSE;	/* TRUE => program statement has been found */
151 int  beginnest = 0;	/* routine nesting level */
152 int  nest = 0;		/* begin block nesting level */
153 
154 split(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  */
343 printout()
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  */
364 quit(fp)
365 	char *fp;
366 {
367 	if (fp != NULL)
368 		perror(fp);
369 	onintr();
370 	exit(1);
371 }
372