xref: /csrg-svn/usr.bin/pascal/pmerge/pmerge.c (revision 47032)
122263Sdist /*
222263Sdist  * Copyright (c) 1980 Regents of the University of California.
322263Sdist  * All rights reserved.  The Berkeley software License Agreement
422263Sdist  * specifies the terms and conditions for redistribution.
522263Sdist  */
63570Smckusick 
722263Sdist #ifndef lint
822263Sdist char copyright[] =
922263Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1022263Sdist  All rights reserved.\n";
1122263Sdist #endif not lint
123570Smckusick 
1322263Sdist #ifndef lint
14*47032Sdonn static char sccsid[] = "@(#)pmerge.c	5.2 (Berkeley) 03/06/91";
1522263Sdist #endif not lint
1622263Sdist 
173570Smckusick #include <ctype.h>
183570Smckusick #include <stdio.h>
19*47032Sdonn #include <string.h>
20*47032Sdonn #include <stdlib.h>
21*47032Sdonn #include <unistd.h>
223570Smckusick #include <signal.h>
233570Smckusick 
243570Smckusick #define PRGFILE 0
253570Smckusick #define LABELFILE 1
263570Smckusick #define CONSTFILE 2
273570Smckusick #define TYPEFILE 3
283570Smckusick #define VARFILE 4
293570Smckusick #define RTNFILE 5
303570Smckusick #define BODYFILE 6
313570Smckusick #define NUMFILES 7
323570Smckusick 
333570Smckusick #define TRUE 1
343570Smckusick #define FALSE 0
353570Smckusick #define MAXINCL 9
363570Smckusick #define MAXNAM 75
373570Smckusick #define TMPNAME "/usr/tmp/MGXXXXXX"
383570Smckusick 
393570Smckusick FILE	*files[NUMFILES];
403570Smckusick char	*names[NUMFILES];
413570Smckusick FILE	*curfile;		/* current output file */
423570Smckusick char	labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE;
433570Smckusick 
443570Smckusick /*
453570Smckusick  * Remove temporary files if interrupted
463570Smckusick  */
47*47032Sdonn void
48*47032Sdonn onintr(unused)
493570Smckusick {
503570Smckusick 	int i;
513570Smckusick 
523570Smckusick 	for (i = 0; i < NUMFILES; i++)
533570Smckusick 		if (files[i] != NULL)
543570Smckusick 			unlink(names[i]);
553570Smckusick }
563570Smckusick 
573570Smckusick /*
583570Smckusick  * Program to merge separately compiled pascal modules into a
593570Smckusick  * single standard Pascal program.
603570Smckusick  */
613570Smckusick main(argc, argv)
623570Smckusick 	long argc;
633570Smckusick 	char **argv;
643570Smckusick {
653570Smckusick 	FILE	*incl[MAXINCL];	/* include stack */
663570Smckusick 	long	inclcnt = 0;	/* incl index */
673570Smckusick 	char	*name[MAXNAM];	/* include names seen so far */
683570Smckusick 	long	namcnt = 0;	/* next name ptr slot available */
699577Sgarrison 	char	*nambuf;	/* string table for names */
703570Smckusick 	char	line[BUFSIZ];	/* input line buffer */
719577Sgarrison 	char	*next;		/* next name space available */
723570Smckusick 	FILE	*input = stdin;	/* current input file */
733570Smckusick 	long	ac = 0;		/* argv index */
743570Smckusick 	char	**cpp, *cp, *fp;/* char ptrs */
753866Smckusic 	char	quote;		/* include quote character */
763570Smckusick 	int	i;		/* index var */
773570Smckusick 
789577Sgarrison 	for (i = 0; i < MAXNAM ; i++)
799577Sgarrison 		name[i] = 0;
809577Sgarrison 
813570Smckusick 	signal(SIGINT, onintr);
829577Sgarrison 
83*47032Sdonn 	curfile = files[PRGFILE] =
84*47032Sdonn 		fopen(names[PRGFILE] = mktemp(strdup(TMPNAME)), "w");
85*47032Sdonn 	files[LABELFILE] =
86*47032Sdonn 		fopen(names[LABELFILE] = mktemp(strdup(TMPNAME)), "w");
87*47032Sdonn 	files[CONSTFILE] =
88*47032Sdonn 		fopen(names[CONSTFILE] = mktemp(strdup(TMPNAME)), "w");
89*47032Sdonn 	files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(strdup(TMPNAME)), "w");
90*47032Sdonn 	files[VARFILE] = fopen(names[VARFILE] = mktemp(strdup(TMPNAME)), "w");
91*47032Sdonn 	files[RTNFILE] = fopen(names[RTNFILE] = mktemp(strdup(TMPNAME)), "w");
92*47032Sdonn 	files[BODYFILE] = fopen(names[BODYFILE] = mktemp(strdup(TMPNAME)), "w");
939577Sgarrison 
943570Smckusick 	for (i = 0; i < NUMFILES; i++)
953570Smckusick 		if (files[i] == NULL)
963570Smckusick 			quit(names[i]);
979577Sgarrison 	if ((nambuf = malloc(BUFSIZ)) == NULL) {
989577Sgarrison 		fputs("no space for string table\n", stderr);
999577Sgarrison 		quit(NULL);
1009577Sgarrison 	}
1019577Sgarrison 	next = nambuf;
1023570Smckusick 	name[namcnt] = next;
1033570Smckusick 	for(;;) {
1043570Smckusick 		if (inclcnt > 0) {
1053570Smckusick 			inclcnt--;
1063570Smckusick 			fclose(input);
1073570Smckusick 			input = incl[inclcnt];
1083570Smckusick 		} else if (++ac < argc) {
1093570Smckusick 			input = freopen(argv[ac], "r", input);
1103570Smckusick 			if (input == NULL)
1113570Smckusick 				quit(argv[ac]);
1123570Smckusick 		} else {
1133570Smckusick 			printout();
114*47032Sdonn 			onintr(0);
1153570Smckusick 			exit(0);
1163570Smckusick 		}
1173570Smckusick 		fgets(line, BUFSIZ, input);
1183570Smckusick 		while (!feof(input)) {
1193570Smckusick 			if (line[0] != '#') {
1203570Smckusick 				split(line);
1213570Smckusick 				fgets(line, BUFSIZ, input);
1223570Smckusick 				continue;
1233570Smckusick 			}
1243570Smckusick 			for (cp = &line[1]; isspace(*cp); cp++)
1253570Smckusick 				/* void */;
12615685Speter 			if (strncmp("include", cp, 7))
1273570Smckusick 				goto bad;
1283570Smckusick 			for (cp += 7; isspace(*cp); cp++)
1293570Smckusick 				/* void */;
1303570Smckusick 			if (*cp != '\'' && *cp != '"')
1313570Smckusick 				goto bad;
1329577Sgarrison 			if (&nambuf[BUFSIZ] < next + strlen(cp)) {
1339577Sgarrison 				if ((nambuf = malloc(BUFSIZ)) == NULL) {
1349577Sgarrison 					fputs("no space for string table\n",
1359577Sgarrison 						stderr);
1369577Sgarrison 					quit(NULL);
1379577Sgarrison 				}
1389577Sgarrison 				next = nambuf;
1399577Sgarrison 				name[namcnt] = next;
1409577Sgarrison 			}
1413866Smckusic 			for (fp = next, quote = *cp++;
1423866Smckusic 			     *cp != '\0' && *cp != quote; )
1433570Smckusick 				*fp++ = *cp++;
1443866Smckusic 			if (*cp != quote &&
1453570Smckusick 			    (fp[-1] != 'i' || fp[-1] != 'h') &&
1463570Smckusick 			    (fp[-2] != '.'))
1473570Smckusick 				goto bad;
1483570Smckusick 			*fp++ = '\0';
1493570Smckusick 			for (cpp = name; *cpp < next && strcmp(*cpp, next); )
1503570Smckusick 				cpp++;
1513570Smckusick 			if (*cpp == next) {
1523570Smckusick 				if (inclcnt == MAXINCL) {
1533570Smckusick 					fputs("include table overflow\n",
1543570Smckusick 						stderr);
1553570Smckusick 					quit(NULL);
1563570Smckusick 				}
1579577Sgarrison 				if (++namcnt == MAXNAM) {
1583570Smckusick 					fputs("include name table overflow\n",
1593570Smckusick 						stderr);
1603570Smckusick 					quit(NULL);
1613570Smckusick 				}
1623570Smckusick 				incl[inclcnt] = input;
1633570Smckusick 				inclcnt++;
1643570Smckusick 				input = fopen(next, "r");
1653570Smckusick 				if (input == NULL)
1663570Smckusick 					quit(next);
1673570Smckusick 				next = fp;
1683570Smckusick 				name[namcnt] = next;
1693570Smckusick 			}
1703570Smckusick 			fgets(line, BUFSIZ, input);
1713570Smckusick 		}
1723570Smckusick 	}
1733570Smckusick bad:
1743570Smckusick 	fputs("bad include format:", stderr);
1753570Smckusick 	fputs(line, stderr);
1763570Smckusick 	quit(NULL);
1773570Smckusick }
1783570Smckusick 
1793570Smckusick /*
1803570Smckusick  * Split up output into the approprite files
1813570Smckusick  */
1823570Smckusick char incom = FALSE;	/* TRUE => in comment */
1833570Smckusick char incur = FALSE;	/* TRUE => in (* *) style comment */
1843570Smckusick char inbrac = FALSE;	/* TRUE => in { } style comment */
1853570Smckusick char instr = FALSE;	/* TRUE => in quoted string */
1863570Smckusick char inprog = FALSE;	/* TRUE => program statement has been found */
1873570Smckusick int  beginnest = 0;	/* routine nesting level */
1883570Smckusick int  nest = 0;		/* begin block nesting level */
1899577Sgarrison int  paren_level = 0;	/* nesting level of parentheses */
1903570Smckusick 
1913570Smckusick split(line)
1923570Smckusick 	char *line;
1933570Smckusick {
1943570Smckusick 	char ch1, *cp;		/* input window */
1953570Smckusick 	char *word;		/* ptr to current word */
1963570Smckusick 	int len;		/* length of current word */
1973570Smckusick 	char prt = TRUE;	/* TRUE => print current word */
1983570Smckusick 
1993570Smckusick 	ch1 = ' ';
2003570Smckusick 	cp = line;
2013570Smckusick 	while (*cp) {
2023570Smckusick 		switch(*cp) {
2039577Sgarrison 		case '(':
2049577Sgarrison 			if (incom)
2059577Sgarrison 				break;
2069577Sgarrison 			if (*(cp+1) == '*') {
2079577Sgarrison 				fputc(*cp, curfile);
2089577Sgarrison 				cp++;
2093570Smckusick 				incom = TRUE;
2103570Smckusick 				incur = TRUE;
2119577Sgarrison 			} else {
2129577Sgarrison 				paren_level++;
2133570Smckusick 			}
2143570Smckusick 			break;
2153570Smckusick 		case ')':
2163570Smckusick 			if (incur && ch1 == '*') {
2173570Smckusick 				incom = FALSE;
2183570Smckusick 				incur = FALSE;
2199577Sgarrison 			} else if (!incom) {
2209577Sgarrison 				paren_level--;
2213570Smckusick 			}
2223570Smckusick 			break;
2233570Smckusick 		case '{':
2243570Smckusick 			if (!incom) {
2253570Smckusick 				inbrac = TRUE;
2263570Smckusick 				incom = TRUE;
2273570Smckusick 			}
2283570Smckusick 			break;
2293570Smckusick 		case '}':
2303570Smckusick 			if (inbrac) {
2313570Smckusick 				inbrac = FALSE;
2323570Smckusick 				incom = FALSE;
2333570Smckusick 			}
2343570Smckusick 			break;
2353570Smckusick 		case '\'':
2363570Smckusick 			if (!incom) {
2373570Smckusick 				incom = TRUE;
2383570Smckusick 				instr = TRUE;
2393570Smckusick 			} else if (instr) {
2403570Smckusick 				incom = FALSE;
2413570Smckusick 				instr = FALSE;
2423570Smckusick 			}
2433570Smckusick 			break;
2443570Smckusick 		}
2453570Smckusick 		if (incom || !isalpha(*cp)) {
2463570Smckusick 			fputc(*cp, curfile);
2473570Smckusick 			ch1 = *cp++;
2483570Smckusick 			continue;
2493570Smckusick 		}
2503570Smckusick 		word = cp;
2519577Sgarrison 		while (isalnum(*cp))
2523570Smckusick 			cp++;
2533570Smckusick 		len = cp - word;
2543570Smckusick 		switch (*word) {
2553570Smckusick 		case 'b':
25615685Speter 			if (len == 5 && !strncmp(word, "begin", 5)) {
2573570Smckusick 				if (nest == 0 && beginnest == 0) {
2583570Smckusick 					if (inprog != 1) {
2593570Smckusick 						fprintf(stderr,
2603570Smckusick 						    "improper program body");
2613570Smckusick 						quit(NULL);
2623570Smckusick 					}
2633570Smckusick 					curfile = files[BODYFILE];
2643570Smckusick 				} else {
2653570Smckusick 					beginnest++;
2663570Smckusick 				}
2673570Smckusick 			}
2683570Smckusick 			break;
2693570Smckusick 		case 'c':
27015685Speter 			if (len == 4 && !strncmp(word, "case", 4)) {
2713570Smckusick 				if (beginnest > 0) {
2723570Smckusick 					beginnest++;
2733570Smckusick 				}
2743570Smckusick 				break;
2753570Smckusick 			}
27615685Speter 			if (len == 5 && !strncmp(word, "const", 5)) {
2773570Smckusick 				if (nest == 0) {
2783570Smckusick 					prt = FALSE;
2793570Smckusick 					if (!constopen) {
2803570Smckusick 						constopen = TRUE;
2813570Smckusick 						prt = TRUE;
2823570Smckusick 					}
2833570Smckusick 					curfile = files[CONSTFILE];
2843570Smckusick 				}
2853570Smckusick 			}
2863570Smckusick 			break;
2873570Smckusick 		case 'e':
28815685Speter 			if (len == 3 && !strncmp(word, "end", 3)) {
2893570Smckusick 				if (beginnest == 1) {
2903570Smckusick 					nest--;
2913570Smckusick 				}
2923570Smckusick 				if (beginnest > 0) {
2933570Smckusick 					beginnest--;
2943570Smckusick 				}
2953570Smckusick 				if (nest < 0) {
2963570Smckusick 					if (inprog == 1) {
2973570Smckusick 						inprog = 0;
2983570Smckusick 						nest = 0;
2993570Smckusick 					} else {
3003570Smckusick 						fprintf(stderr, "too many end statements");
3013570Smckusick 						quit(NULL);
3023570Smckusick 					}
3033570Smckusick 				}
3043570Smckusick 				break;
3053570Smckusick 			}
30615685Speter 			if (len == 8 && !strncmp(word, "external", 8)) {
3073570Smckusick 				fputs("forward", curfile);
3083570Smckusick 				prt = FALSE;
3099577Sgarrison 				if (paren_level == 0) {
3109577Sgarrison 					nest--;
3119577Sgarrison 				}
3123570Smckusick 			}
3133570Smckusick 			break;
3143570Smckusick 		case 'f':
31515685Speter 			if (len == 8 && !strncmp(word, "function", 8)) {
3163570Smckusick 				if (nest == 0) {
3173570Smckusick 					curfile = files[RTNFILE];
3183570Smckusick 				}
3199577Sgarrison 				if (paren_level == 0) {
3209577Sgarrison 					nest++;
3219577Sgarrison 				}
3223570Smckusick 				break;
3233570Smckusick 			}
32415685Speter 			if (len == 7 && !strncmp(word, "forward", 7)) {
3259577Sgarrison 				if (paren_level == 0) {
3269577Sgarrison 					nest--;
3279577Sgarrison 				}
3283570Smckusick 			}
3293570Smckusick 			break;
3303570Smckusick 		case 'l':
33115685Speter 			if (len == 5 && !strncmp(word, "label", 5)) {
3323570Smckusick 				if (nest == 0) {
3333570Smckusick 					prt = FALSE;
3343570Smckusick 					if (!labelopen) {
3353570Smckusick 						labelopen = TRUE;
3363570Smckusick 						prt = TRUE;
3373570Smckusick 					}
3383570Smckusick 					curfile = files[LABELFILE];
3393570Smckusick 				}
3403570Smckusick 			}
3413570Smckusick 			break;
3423570Smckusick 		case 'p':
34315685Speter 			if (len == 9 && !strncmp(word, "procedure", 9)) {
3443570Smckusick 				if (nest == 0) {
3453570Smckusick 					curfile = files[RTNFILE];
3463570Smckusick 				}
3479577Sgarrison 				if (paren_level == 0) {
3489577Sgarrison 					nest++;
3499577Sgarrison 				}
3503570Smckusick 				break;
3513570Smckusick 			}
35215685Speter 			if (len == 7 && !strncmp(word, "program", 7)) {
3533570Smckusick 				if (nest != 0) {
3543570Smckusick 					fprintf(stderr, "improper program nesting");
3553570Smckusick 					quit(NULL);
3563570Smckusick 				}
3573570Smckusick 				inprog = 1;
3583570Smckusick 				curfile = files[PRGFILE];
3593570Smckusick 			}
3603570Smckusick 			break;
3613570Smckusick 		case 't':
36215685Speter 			if (len == 4 && !strncmp(word, "type", 4)) {
3633570Smckusick 				if (nest == 0) {
3643570Smckusick 					prt = FALSE;
3653570Smckusick 					if (!typeopen) {
3663570Smckusick 						typeopen = TRUE;
3673570Smckusick 						prt = TRUE;
3683570Smckusick 					}
3693570Smckusick 					curfile = files[TYPEFILE];
3703570Smckusick 				}
3713570Smckusick 			}
3723570Smckusick 			break;
3733570Smckusick 		case 'v':
37415685Speter 			if (len == 3 && !strncmp(word, "var", 3)) {
3753570Smckusick 				if (nest == 0) {
3763570Smckusick 					prt = FALSE;
3773570Smckusick 					if (!varopen) {
3783570Smckusick 						varopen = TRUE;
3793570Smckusick 						prt = TRUE;
3803570Smckusick 					}
3813570Smckusick 					curfile = files[VARFILE];
3823570Smckusick 				}
3833570Smckusick 			}
3843570Smckusick 			break;
3853570Smckusick 		}
3863570Smckusick 		if (prt)
3873570Smckusick 			fprintf(curfile, "%.*s", len, word);
3883570Smckusick 		prt = TRUE;
3893570Smckusick 		ch1 = ' ';
3903570Smckusick 	}
3913570Smckusick }
3923570Smckusick 
3933570Smckusick /*
3943570Smckusick  * Print out the merged result
3953570Smckusick  */
3963570Smckusick printout()
3973570Smckusick {
3983570Smckusick 	FILE *fp;
3993570Smckusick 	int i;
4003570Smckusick 	char ch;
4013570Smckusick 
4023570Smckusick 	for(i = 0; i < NUMFILES; i++) {
4033570Smckusick 		fp = freopen(names[i], "r", files[i]);
4043570Smckusick 		if (fp == NULL)
4053570Smckusick 			quit(names[i]);
4063570Smckusick 		ch = getc(fp);
4073570Smckusick 		while (!feof(fp)) {
4083570Smckusick 			putc(ch,stdout);
4093570Smckusick 			ch = getc(fp);
4103570Smckusick 		}
4113570Smckusick 	}
4123570Smckusick }
4133570Smckusick 
4143570Smckusick /*
4153570Smckusick  * Die gracefully
4163570Smckusick  */
4173570Smckusick quit(fp)
4183570Smckusick 	char *fp;
4193570Smckusick {
4203570Smckusick 	if (fp != NULL)
4213570Smckusick 		perror(fp);
422*47032Sdonn 	onintr(0);
4233570Smckusick 	exit(1);
4243570Smckusick }
425