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