xref: /csrg-svn/usr.bin/pascal/pmerge/pmerge.c (revision 22263)
1*22263Sdist /*
2*22263Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22263Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22263Sdist  * specifies the terms and conditions for redistribution.
5*22263Sdist  */
63570Smckusick 
7*22263Sdist #ifndef lint
8*22263Sdist char copyright[] =
9*22263Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10*22263Sdist  All rights reserved.\n";
11*22263Sdist #endif not lint
123570Smckusick 
13*22263Sdist #ifndef lint
14*22263Sdist static char sccsid[] = "@(#)pmerge.c	5.1 (Berkeley) 06/05/85";
15*22263Sdist #endif not lint
16*22263Sdist 
173570Smckusick #include <ctype.h>
183570Smckusick #include <stdio.h>
193570Smckusick #include <signal.h>
203570Smckusick 
213570Smckusick #define PRGFILE 0
223570Smckusick #define LABELFILE 1
233570Smckusick #define CONSTFILE 2
243570Smckusick #define TYPEFILE 3
253570Smckusick #define VARFILE 4
263570Smckusick #define RTNFILE 5
273570Smckusick #define BODYFILE 6
283570Smckusick #define NUMFILES 7
293570Smckusick 
303570Smckusick #define TRUE 1
313570Smckusick #define FALSE 0
323570Smckusick #define MAXINCL 9
333570Smckusick #define MAXNAM 75
343570Smckusick #define TMPNAME "/usr/tmp/MGXXXXXX"
353570Smckusick 
363570Smckusick FILE	*files[NUMFILES];
373570Smckusick char	*names[NUMFILES];
383570Smckusick FILE	*curfile;		/* current output file */
393570Smckusick FILE	*fopen();
403570Smckusick char	labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE;
413570Smckusick char	*mktemp();
429577Sgarrison char	*malloc();
433570Smckusick 
443570Smckusick /*
453570Smckusick  * Remove temporary files if interrupted
463570Smckusick  */
473570Smckusick onintr()
483570Smckusick {
493570Smckusick 	int i;
503570Smckusick 
513570Smckusick 	for (i = 0; i < NUMFILES; i++)
523570Smckusick 		if (files[i] != NULL)
533570Smckusick 			unlink(names[i]);
543570Smckusick }
553570Smckusick 
563570Smckusick /*
573570Smckusick  * Program to merge separately compiled pascal modules into a
583570Smckusick  * single standard Pascal program.
593570Smckusick  */
603570Smckusick main(argc, argv)
613570Smckusick 	long argc;
623570Smckusick 	char **argv;
633570Smckusick {
643570Smckusick 	FILE	*incl[MAXINCL];	/* include stack */
653570Smckusick 	long	inclcnt = 0;	/* incl index */
663570Smckusick 	char	*name[MAXNAM];	/* include names seen so far */
673570Smckusick 	long	namcnt = 0;	/* next name ptr slot available */
689577Sgarrison 	char	*nambuf;	/* string table for names */
693570Smckusick 	char	line[BUFSIZ];	/* input line buffer */
709577Sgarrison 	char	*next;		/* next name space available */
713570Smckusick 	FILE	*input = stdin;	/* current input file */
723570Smckusick 	long	ac = 0;		/* argv index */
733570Smckusick 	char	**cpp, *cp, *fp;/* char ptrs */
743866Smckusic 	char	quote;		/* include quote character */
753570Smckusick 	int	i;		/* index var */
763570Smckusick 
779577Sgarrison 	for (i = 0; i < MAXNAM ; i++)
789577Sgarrison 		name[i] = 0;
799577Sgarrison 
803570Smckusick 	signal(SIGINT, onintr);
819577Sgarrison 
823570Smckusick 	curfile = files[PRGFILE] = fopen(names[PRGFILE] = mktemp(TMPNAME), "w");
833570Smckusick 	files[LABELFILE] = fopen(names[LABELFILE] = mktemp(TMPNAME), "w");
843570Smckusick 	files[CONSTFILE] = fopen(names[CONSTFILE] = mktemp(TMPNAME), "w");
853570Smckusick 	files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(TMPNAME), "w");
863570Smckusick 	files[VARFILE] = fopen(names[VARFILE] = mktemp(TMPNAME), "w");
873570Smckusick 	files[RTNFILE] = fopen(names[RTNFILE] = mktemp(TMPNAME), "w");
883570Smckusick 	files[BODYFILE] = fopen(names[BODYFILE] = mktemp(TMPNAME), "w");
899577Sgarrison 
903570Smckusick 	for (i = 0; i < NUMFILES; i++)
913570Smckusick 		if (files[i] == NULL)
923570Smckusick 			quit(names[i]);
939577Sgarrison 	if ((nambuf = malloc(BUFSIZ)) == NULL) {
949577Sgarrison 		fputs("no space for string table\n", stderr);
959577Sgarrison 		quit(NULL);
969577Sgarrison 	}
979577Sgarrison 	next = nambuf;
983570Smckusick 	name[namcnt] = next;
993570Smckusick 	for(;;) {
1003570Smckusick 		if (inclcnt > 0) {
1013570Smckusick 			inclcnt--;
1023570Smckusick 			fclose(input);
1033570Smckusick 			input = incl[inclcnt];
1043570Smckusick 		} else if (++ac < argc) {
1053570Smckusick 			input = freopen(argv[ac], "r", input);
1063570Smckusick 			if (input == NULL)
1073570Smckusick 				quit(argv[ac]);
1083570Smckusick 		} else {
1093570Smckusick 			printout();
1103570Smckusick 			onintr();
1113570Smckusick 			exit(0);
1123570Smckusick 		}
1133570Smckusick 		fgets(line, BUFSIZ, input);
1143570Smckusick 		while (!feof(input)) {
1153570Smckusick 			if (line[0] != '#') {
1163570Smckusick 				split(line);
1173570Smckusick 				fgets(line, BUFSIZ, input);
1183570Smckusick 				continue;
1193570Smckusick 			}
1203570Smckusick 			for (cp = &line[1]; isspace(*cp); cp++)
1213570Smckusick 				/* void */;
12215685Speter 			if (strncmp("include", cp, 7))
1233570Smckusick 				goto bad;
1243570Smckusick 			for (cp += 7; isspace(*cp); cp++)
1253570Smckusick 				/* void */;
1263570Smckusick 			if (*cp != '\'' && *cp != '"')
1273570Smckusick 				goto bad;
1289577Sgarrison 			if (&nambuf[BUFSIZ] < next + strlen(cp)) {
1299577Sgarrison 				if ((nambuf = malloc(BUFSIZ)) == NULL) {
1309577Sgarrison 					fputs("no space for string table\n",
1319577Sgarrison 						stderr);
1329577Sgarrison 					quit(NULL);
1339577Sgarrison 				}
1349577Sgarrison 				next = nambuf;
1359577Sgarrison 				name[namcnt] = next;
1369577Sgarrison 			}
1373866Smckusic 			for (fp = next, quote = *cp++;
1383866Smckusic 			     *cp != '\0' && *cp != quote; )
1393570Smckusick 				*fp++ = *cp++;
1403866Smckusic 			if (*cp != quote &&
1413570Smckusick 			    (fp[-1] != 'i' || fp[-1] != 'h') &&
1423570Smckusick 			    (fp[-2] != '.'))
1433570Smckusick 				goto bad;
1443570Smckusick 			*fp++ = '\0';
1453570Smckusick 			for (cpp = name; *cpp < next && strcmp(*cpp, next); )
1463570Smckusick 				cpp++;
1473570Smckusick 			if (*cpp == next) {
1483570Smckusick 				if (inclcnt == MAXINCL) {
1493570Smckusick 					fputs("include table overflow\n",
1503570Smckusick 						stderr);
1513570Smckusick 					quit(NULL);
1523570Smckusick 				}
1539577Sgarrison 				if (++namcnt == MAXNAM) {
1543570Smckusick 					fputs("include name table overflow\n",
1553570Smckusick 						stderr);
1563570Smckusick 					quit(NULL);
1573570Smckusick 				}
1583570Smckusick 				incl[inclcnt] = input;
1593570Smckusick 				inclcnt++;
1603570Smckusick 				input = fopen(next, "r");
1613570Smckusick 				if (input == NULL)
1623570Smckusick 					quit(next);
1633570Smckusick 				next = fp;
1643570Smckusick 				name[namcnt] = next;
1653570Smckusick 			}
1663570Smckusick 			fgets(line, BUFSIZ, input);
1673570Smckusick 		}
1683570Smckusick 	}
1693570Smckusick bad:
1703570Smckusick 	fputs("bad include format:", stderr);
1713570Smckusick 	fputs(line, stderr);
1723570Smckusick 	quit(NULL);
1733570Smckusick }
1743570Smckusick 
1753570Smckusick /*
1763570Smckusick  * Split up output into the approprite files
1773570Smckusick  */
1783570Smckusick char incom = FALSE;	/* TRUE => in comment */
1793570Smckusick char incur = FALSE;	/* TRUE => in (* *) style comment */
1803570Smckusick char inbrac = FALSE;	/* TRUE => in { } style comment */
1813570Smckusick char instr = FALSE;	/* TRUE => in quoted string */
1823570Smckusick char inprog = FALSE;	/* TRUE => program statement has been found */
1833570Smckusick int  beginnest = 0;	/* routine nesting level */
1843570Smckusick int  nest = 0;		/* begin block nesting level */
1859577Sgarrison int  paren_level = 0;	/* nesting level of parentheses */
1863570Smckusick 
1873570Smckusick split(line)
1883570Smckusick 	char *line;
1893570Smckusick {
1903570Smckusick 	char ch1, *cp;		/* input window */
1913570Smckusick 	char *word;		/* ptr to current word */
1923570Smckusick 	int len;		/* length of current word */
1933570Smckusick 	char prt = TRUE;	/* TRUE => print current word */
1943570Smckusick 
1953570Smckusick 	ch1 = ' ';
1963570Smckusick 	cp = line;
1973570Smckusick 	while (*cp) {
1983570Smckusick 		switch(*cp) {
1999577Sgarrison 		case '(':
2009577Sgarrison 			if (incom)
2019577Sgarrison 				break;
2029577Sgarrison 			if (*(cp+1) == '*') {
2039577Sgarrison 				fputc(*cp, curfile);
2049577Sgarrison 				cp++;
2053570Smckusick 				incom = TRUE;
2063570Smckusick 				incur = TRUE;
2079577Sgarrison 			} else {
2089577Sgarrison 				paren_level++;
2093570Smckusick 			}
2103570Smckusick 			break;
2113570Smckusick 		case ')':
2123570Smckusick 			if (incur && ch1 == '*') {
2133570Smckusick 				incom = FALSE;
2143570Smckusick 				incur = FALSE;
2159577Sgarrison 			} else if (!incom) {
2169577Sgarrison 				paren_level--;
2173570Smckusick 			}
2183570Smckusick 			break;
2193570Smckusick 		case '{':
2203570Smckusick 			if (!incom) {
2213570Smckusick 				inbrac = TRUE;
2223570Smckusick 				incom = TRUE;
2233570Smckusick 			}
2243570Smckusick 			break;
2253570Smckusick 		case '}':
2263570Smckusick 			if (inbrac) {
2273570Smckusick 				inbrac = FALSE;
2283570Smckusick 				incom = FALSE;
2293570Smckusick 			}
2303570Smckusick 			break;
2313570Smckusick 		case '\'':
2323570Smckusick 			if (!incom) {
2333570Smckusick 				incom = TRUE;
2343570Smckusick 				instr = TRUE;
2353570Smckusick 			} else if (instr) {
2363570Smckusick 				incom = FALSE;
2373570Smckusick 				instr = FALSE;
2383570Smckusick 			}
2393570Smckusick 			break;
2403570Smckusick 		}
2413570Smckusick 		if (incom || !isalpha(*cp)) {
2423570Smckusick 			fputc(*cp, curfile);
2433570Smckusick 			ch1 = *cp++;
2443570Smckusick 			continue;
2453570Smckusick 		}
2463570Smckusick 		word = cp;
2479577Sgarrison 		while (isalnum(*cp))
2483570Smckusick 			cp++;
2493570Smckusick 		len = cp - word;
2503570Smckusick 		switch (*word) {
2513570Smckusick 		case 'b':
25215685Speter 			if (len == 5 && !strncmp(word, "begin", 5)) {
2533570Smckusick 				if (nest == 0 && beginnest == 0) {
2543570Smckusick 					if (inprog != 1) {
2553570Smckusick 						fprintf(stderr,
2563570Smckusick 						    "improper program body");
2573570Smckusick 						quit(NULL);
2583570Smckusick 					}
2593570Smckusick 					curfile = files[BODYFILE];
2603570Smckusick 				} else {
2613570Smckusick 					beginnest++;
2623570Smckusick 				}
2633570Smckusick 			}
2643570Smckusick 			break;
2653570Smckusick 		case 'c':
26615685Speter 			if (len == 4 && !strncmp(word, "case", 4)) {
2673570Smckusick 				if (beginnest > 0) {
2683570Smckusick 					beginnest++;
2693570Smckusick 				}
2703570Smckusick 				break;
2713570Smckusick 			}
27215685Speter 			if (len == 5 && !strncmp(word, "const", 5)) {
2733570Smckusick 				if (nest == 0) {
2743570Smckusick 					prt = FALSE;
2753570Smckusick 					if (!constopen) {
2763570Smckusick 						constopen = TRUE;
2773570Smckusick 						prt = TRUE;
2783570Smckusick 					}
2793570Smckusick 					curfile = files[CONSTFILE];
2803570Smckusick 				}
2813570Smckusick 			}
2823570Smckusick 			break;
2833570Smckusick 		case 'e':
28415685Speter 			if (len == 3 && !strncmp(word, "end", 3)) {
2853570Smckusick 				if (beginnest == 1) {
2863570Smckusick 					nest--;
2873570Smckusick 				}
2883570Smckusick 				if (beginnest > 0) {
2893570Smckusick 					beginnest--;
2903570Smckusick 				}
2913570Smckusick 				if (nest < 0) {
2923570Smckusick 					if (inprog == 1) {
2933570Smckusick 						inprog = 0;
2943570Smckusick 						nest = 0;
2953570Smckusick 					} else {
2963570Smckusick 						fprintf(stderr, "too many end statements");
2973570Smckusick 						quit(NULL);
2983570Smckusick 					}
2993570Smckusick 				}
3003570Smckusick 				break;
3013570Smckusick 			}
30215685Speter 			if (len == 8 && !strncmp(word, "external", 8)) {
3033570Smckusick 				fputs("forward", curfile);
3043570Smckusick 				prt = FALSE;
3059577Sgarrison 				if (paren_level == 0) {
3069577Sgarrison 					nest--;
3079577Sgarrison 				}
3083570Smckusick 			}
3093570Smckusick 			break;
3103570Smckusick 		case 'f':
31115685Speter 			if (len == 8 && !strncmp(word, "function", 8)) {
3123570Smckusick 				if (nest == 0) {
3133570Smckusick 					curfile = files[RTNFILE];
3143570Smckusick 				}
3159577Sgarrison 				if (paren_level == 0) {
3169577Sgarrison 					nest++;
3179577Sgarrison 				}
3183570Smckusick 				break;
3193570Smckusick 			}
32015685Speter 			if (len == 7 && !strncmp(word, "forward", 7)) {
3219577Sgarrison 				if (paren_level == 0) {
3229577Sgarrison 					nest--;
3239577Sgarrison 				}
3243570Smckusick 			}
3253570Smckusick 			break;
3263570Smckusick 		case 'l':
32715685Speter 			if (len == 5 && !strncmp(word, "label", 5)) {
3283570Smckusick 				if (nest == 0) {
3293570Smckusick 					prt = FALSE;
3303570Smckusick 					if (!labelopen) {
3313570Smckusick 						labelopen = TRUE;
3323570Smckusick 						prt = TRUE;
3333570Smckusick 					}
3343570Smckusick 					curfile = files[LABELFILE];
3353570Smckusick 				}
3363570Smckusick 			}
3373570Smckusick 			break;
3383570Smckusick 		case 'p':
33915685Speter 			if (len == 9 && !strncmp(word, "procedure", 9)) {
3403570Smckusick 				if (nest == 0) {
3413570Smckusick 					curfile = files[RTNFILE];
3423570Smckusick 				}
3439577Sgarrison 				if (paren_level == 0) {
3449577Sgarrison 					nest++;
3459577Sgarrison 				}
3463570Smckusick 				break;
3473570Smckusick 			}
34815685Speter 			if (len == 7 && !strncmp(word, "program", 7)) {
3493570Smckusick 				if (nest != 0) {
3503570Smckusick 					fprintf(stderr, "improper program nesting");
3513570Smckusick 					quit(NULL);
3523570Smckusick 				}
3533570Smckusick 				inprog = 1;
3543570Smckusick 				curfile = files[PRGFILE];
3553570Smckusick 			}
3563570Smckusick 			break;
3573570Smckusick 		case 't':
35815685Speter 			if (len == 4 && !strncmp(word, "type", 4)) {
3593570Smckusick 				if (nest == 0) {
3603570Smckusick 					prt = FALSE;
3613570Smckusick 					if (!typeopen) {
3623570Smckusick 						typeopen = TRUE;
3633570Smckusick 						prt = TRUE;
3643570Smckusick 					}
3653570Smckusick 					curfile = files[TYPEFILE];
3663570Smckusick 				}
3673570Smckusick 			}
3683570Smckusick 			break;
3693570Smckusick 		case 'v':
37015685Speter 			if (len == 3 && !strncmp(word, "var", 3)) {
3713570Smckusick 				if (nest == 0) {
3723570Smckusick 					prt = FALSE;
3733570Smckusick 					if (!varopen) {
3743570Smckusick 						varopen = TRUE;
3753570Smckusick 						prt = TRUE;
3763570Smckusick 					}
3773570Smckusick 					curfile = files[VARFILE];
3783570Smckusick 				}
3793570Smckusick 			}
3803570Smckusick 			break;
3813570Smckusick 		}
3823570Smckusick 		if (prt)
3833570Smckusick 			fprintf(curfile, "%.*s", len, word);
3843570Smckusick 		prt = TRUE;
3853570Smckusick 		ch1 = ' ';
3863570Smckusick 	}
3873570Smckusick }
3883570Smckusick 
3893570Smckusick /*
3903570Smckusick  * Print out the merged result
3913570Smckusick  */
3923570Smckusick printout()
3933570Smckusick {
3943570Smckusick 	FILE *fp;
3953570Smckusick 	int i;
3963570Smckusick 	char ch;
3973570Smckusick 
3983570Smckusick 	for(i = 0; i < NUMFILES; i++) {
3993570Smckusick 		fp = freopen(names[i], "r", files[i]);
4003570Smckusick 		if (fp == NULL)
4013570Smckusick 			quit(names[i]);
4023570Smckusick 		ch = getc(fp);
4033570Smckusick 		while (!feof(fp)) {
4043570Smckusick 			putc(ch,stdout);
4053570Smckusick 			ch = getc(fp);
4063570Smckusick 		}
4073570Smckusick 	}
4083570Smckusick }
4093570Smckusick 
4103570Smckusick /*
4113570Smckusick  * Die gracefully
4123570Smckusick  */
4133570Smckusick quit(fp)
4143570Smckusick 	char *fp;
4153570Smckusick {
4163570Smckusick 	if (fp != NULL)
4173570Smckusick 		perror(fp);
4183570Smckusick 	onintr();
4193570Smckusick 	exit(1);
4203570Smckusick }
421