xref: /csrg-svn/usr.bin/pascal/pmerge/pmerge.c (revision 62176)
148107Sbostic /*-
2*62176Sbostic  * Copyright (c) 1980, 1993
3*62176Sbostic  *	The Regents of the University of California.  All rights reserved.
448107Sbostic  *
548107Sbostic  * %sccs.include.redist.c%
622263Sdist  */
73570Smckusick 
822263Sdist #ifndef lint
9*62176Sbostic static char copyright[] =
10*62176Sbostic "@(#) Copyright (c) 1980, 1993\n\
11*62176Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1248107Sbostic #endif /* not lint */
133570Smckusick 
1422263Sdist #ifndef lint
15*62176Sbostic static char sccsid[] = "@(#)pmerge.c	8.1 (Berkeley) 06/06/93";
1648107Sbostic #endif /* not lint */
1722263Sdist 
183570Smckusick #include <ctype.h>
193570Smckusick #include <stdio.h>
2047032Sdonn #include <string.h>
2147032Sdonn #include <stdlib.h>
2247032Sdonn #include <unistd.h>
233570Smckusick #include <signal.h>
243570Smckusick 
253570Smckusick #define PRGFILE 0
263570Smckusick #define LABELFILE 1
273570Smckusick #define CONSTFILE 2
283570Smckusick #define TYPEFILE 3
293570Smckusick #define VARFILE 4
303570Smckusick #define RTNFILE 5
313570Smckusick #define BODYFILE 6
323570Smckusick #define NUMFILES 7
333570Smckusick 
343570Smckusick #define TRUE 1
353570Smckusick #define FALSE 0
363570Smckusick #define MAXINCL 9
373570Smckusick #define MAXNAM 75
383570Smckusick #define TMPNAME "/usr/tmp/MGXXXXXX"
393570Smckusick 
403570Smckusick FILE	*files[NUMFILES];
413570Smckusick char	*names[NUMFILES];
423570Smckusick FILE	*curfile;		/* current output file */
433570Smckusick char	labelopen = FALSE, constopen = FALSE, typeopen = FALSE, varopen = FALSE;
443570Smckusick 
453570Smckusick /*
463570Smckusick  * Remove temporary files if interrupted
473570Smckusick  */
4847032Sdonn void
onintr(unused)4947032Sdonn onintr(unused)
503570Smckusick {
513570Smckusick 	int i;
523570Smckusick 
533570Smckusick 	for (i = 0; i < NUMFILES; i++)
543570Smckusick 		if (files[i] != NULL)
553570Smckusick 			unlink(names[i]);
563570Smckusick }
573570Smckusick 
583570Smckusick /*
593570Smckusick  * Program to merge separately compiled pascal modules into a
603570Smckusick  * single standard Pascal program.
613570Smckusick  */
main(argc,argv)623570Smckusick main(argc, argv)
633570Smckusick 	long argc;
643570Smckusick 	char **argv;
653570Smckusick {
663570Smckusick 	FILE	*incl[MAXINCL];	/* include stack */
673570Smckusick 	long	inclcnt = 0;	/* incl index */
683570Smckusick 	char	*name[MAXNAM];	/* include names seen so far */
693570Smckusick 	long	namcnt = 0;	/* next name ptr slot available */
709577Sgarrison 	char	*nambuf;	/* string table for names */
713570Smckusick 	char	line[BUFSIZ];	/* input line buffer */
729577Sgarrison 	char	*next;		/* next name space available */
733570Smckusick 	FILE	*input = stdin;	/* current input file */
743570Smckusick 	long	ac = 0;		/* argv index */
753570Smckusick 	char	**cpp, *cp, *fp;/* char ptrs */
763866Smckusic 	char	quote;		/* include quote character */
773570Smckusick 	int	i;		/* index var */
783570Smckusick 
799577Sgarrison 	for (i = 0; i < MAXNAM ; i++)
809577Sgarrison 		name[i] = 0;
819577Sgarrison 
823570Smckusick 	signal(SIGINT, onintr);
839577Sgarrison 
8447032Sdonn 	curfile = files[PRGFILE] =
8547032Sdonn 		fopen(names[PRGFILE] = mktemp(strdup(TMPNAME)), "w");
8647032Sdonn 	files[LABELFILE] =
8747032Sdonn 		fopen(names[LABELFILE] = mktemp(strdup(TMPNAME)), "w");
8847032Sdonn 	files[CONSTFILE] =
8947032Sdonn 		fopen(names[CONSTFILE] = mktemp(strdup(TMPNAME)), "w");
9047032Sdonn 	files[TYPEFILE] = fopen(names[TYPEFILE] = mktemp(strdup(TMPNAME)), "w");
9147032Sdonn 	files[VARFILE] = fopen(names[VARFILE] = mktemp(strdup(TMPNAME)), "w");
9247032Sdonn 	files[RTNFILE] = fopen(names[RTNFILE] = mktemp(strdup(TMPNAME)), "w");
9347032Sdonn 	files[BODYFILE] = fopen(names[BODYFILE] = mktemp(strdup(TMPNAME)), "w");
949577Sgarrison 
953570Smckusick 	for (i = 0; i < NUMFILES; i++)
963570Smckusick 		if (files[i] == NULL)
973570Smckusick 			quit(names[i]);
989577Sgarrison 	if ((nambuf = malloc(BUFSIZ)) == NULL) {
999577Sgarrison 		fputs("no space for string table\n", stderr);
1009577Sgarrison 		quit(NULL);
1019577Sgarrison 	}
1029577Sgarrison 	next = nambuf;
1033570Smckusick 	name[namcnt] = next;
1043570Smckusick 	for(;;) {
1053570Smckusick 		if (inclcnt > 0) {
1063570Smckusick 			inclcnt--;
1073570Smckusick 			fclose(input);
1083570Smckusick 			input = incl[inclcnt];
1093570Smckusick 		} else if (++ac < argc) {
1103570Smckusick 			input = freopen(argv[ac], "r", input);
1113570Smckusick 			if (input == NULL)
1123570Smckusick 				quit(argv[ac]);
1133570Smckusick 		} else {
1143570Smckusick 			printout();
11547032Sdonn 			onintr(0);
1163570Smckusick 			exit(0);
1173570Smckusick 		}
1183570Smckusick 		fgets(line, BUFSIZ, input);
1193570Smckusick 		while (!feof(input)) {
1203570Smckusick 			if (line[0] != '#') {
1213570Smckusick 				split(line);
1223570Smckusick 				fgets(line, BUFSIZ, input);
1233570Smckusick 				continue;
1243570Smckusick 			}
1253570Smckusick 			for (cp = &line[1]; isspace(*cp); cp++)
1263570Smckusick 				/* void */;
12715685Speter 			if (strncmp("include", cp, 7))
1283570Smckusick 				goto bad;
1293570Smckusick 			for (cp += 7; isspace(*cp); cp++)
1303570Smckusick 				/* void */;
1313570Smckusick 			if (*cp != '\'' && *cp != '"')
1323570Smckusick 				goto bad;
1339577Sgarrison 			if (&nambuf[BUFSIZ] < next + strlen(cp)) {
1349577Sgarrison 				if ((nambuf = malloc(BUFSIZ)) == NULL) {
1359577Sgarrison 					fputs("no space for string table\n",
1369577Sgarrison 						stderr);
1379577Sgarrison 					quit(NULL);
1389577Sgarrison 				}
1399577Sgarrison 				next = nambuf;
1409577Sgarrison 				name[namcnt] = next;
1419577Sgarrison 			}
1423866Smckusic 			for (fp = next, quote = *cp++;
1433866Smckusic 			     *cp != '\0' && *cp != quote; )
1443570Smckusick 				*fp++ = *cp++;
1453866Smckusic 			if (*cp != quote &&
1463570Smckusick 			    (fp[-1] != 'i' || fp[-1] != 'h') &&
1473570Smckusick 			    (fp[-2] != '.'))
1483570Smckusick 				goto bad;
1493570Smckusick 			*fp++ = '\0';
1503570Smckusick 			for (cpp = name; *cpp < next && strcmp(*cpp, next); )
1513570Smckusick 				cpp++;
1523570Smckusick 			if (*cpp == next) {
1533570Smckusick 				if (inclcnt == MAXINCL) {
1543570Smckusick 					fputs("include table overflow\n",
1553570Smckusick 						stderr);
1563570Smckusick 					quit(NULL);
1573570Smckusick 				}
1589577Sgarrison 				if (++namcnt == MAXNAM) {
1593570Smckusick 					fputs("include name table overflow\n",
1603570Smckusick 						stderr);
1613570Smckusick 					quit(NULL);
1623570Smckusick 				}
1633570Smckusick 				incl[inclcnt] = input;
1643570Smckusick 				inclcnt++;
1653570Smckusick 				input = fopen(next, "r");
1663570Smckusick 				if (input == NULL)
1673570Smckusick 					quit(next);
1683570Smckusick 				next = fp;
1693570Smckusick 				name[namcnt] = next;
1703570Smckusick 			}
1713570Smckusick 			fgets(line, BUFSIZ, input);
1723570Smckusick 		}
1733570Smckusick 	}
1743570Smckusick bad:
1753570Smckusick 	fputs("bad include format:", stderr);
1763570Smckusick 	fputs(line, stderr);
1773570Smckusick 	quit(NULL);
1783570Smckusick }
1793570Smckusick 
1803570Smckusick /*
1813570Smckusick  * Split up output into the approprite files
1823570Smckusick  */
1833570Smckusick char incom = FALSE;	/* TRUE => in comment */
1843570Smckusick char incur = FALSE;	/* TRUE => in (* *) style comment */
1853570Smckusick char inbrac = FALSE;	/* TRUE => in { } style comment */
1863570Smckusick char instr = FALSE;	/* TRUE => in quoted string */
1873570Smckusick char inprog = FALSE;	/* TRUE => program statement has been found */
1883570Smckusick int  beginnest = 0;	/* routine nesting level */
1893570Smckusick int  nest = 0;		/* begin block nesting level */
1909577Sgarrison int  paren_level = 0;	/* nesting level of parentheses */
1913570Smckusick 
split(line)1923570Smckusick split(line)
1933570Smckusick 	char *line;
1943570Smckusick {
1953570Smckusick 	char ch1, *cp;		/* input window */
1963570Smckusick 	char *word;		/* ptr to current word */
1973570Smckusick 	int len;		/* length of current word */
1983570Smckusick 	char prt = TRUE;	/* TRUE => print current word */
1993570Smckusick 
2003570Smckusick 	ch1 = ' ';
2013570Smckusick 	cp = line;
2023570Smckusick 	while (*cp) {
2033570Smckusick 		switch(*cp) {
2049577Sgarrison 		case '(':
2059577Sgarrison 			if (incom)
2069577Sgarrison 				break;
2079577Sgarrison 			if (*(cp+1) == '*') {
2089577Sgarrison 				fputc(*cp, curfile);
2099577Sgarrison 				cp++;
2103570Smckusick 				incom = TRUE;
2113570Smckusick 				incur = TRUE;
2129577Sgarrison 			} else {
2139577Sgarrison 				paren_level++;
2143570Smckusick 			}
2153570Smckusick 			break;
2163570Smckusick 		case ')':
2173570Smckusick 			if (incur && ch1 == '*') {
2183570Smckusick 				incom = FALSE;
2193570Smckusick 				incur = FALSE;
2209577Sgarrison 			} else if (!incom) {
2219577Sgarrison 				paren_level--;
2223570Smckusick 			}
2233570Smckusick 			break;
2243570Smckusick 		case '{':
2253570Smckusick 			if (!incom) {
2263570Smckusick 				inbrac = TRUE;
2273570Smckusick 				incom = TRUE;
2283570Smckusick 			}
2293570Smckusick 			break;
2303570Smckusick 		case '}':
2313570Smckusick 			if (inbrac) {
2323570Smckusick 				inbrac = FALSE;
2333570Smckusick 				incom = FALSE;
2343570Smckusick 			}
2353570Smckusick 			break;
2363570Smckusick 		case '\'':
2373570Smckusick 			if (!incom) {
2383570Smckusick 				incom = TRUE;
2393570Smckusick 				instr = TRUE;
2403570Smckusick 			} else if (instr) {
2413570Smckusick 				incom = FALSE;
2423570Smckusick 				instr = FALSE;
2433570Smckusick 			}
2443570Smckusick 			break;
2453570Smckusick 		}
2463570Smckusick 		if (incom || !isalpha(*cp)) {
2473570Smckusick 			fputc(*cp, curfile);
2483570Smckusick 			ch1 = *cp++;
2493570Smckusick 			continue;
2503570Smckusick 		}
2513570Smckusick 		word = cp;
2529577Sgarrison 		while (isalnum(*cp))
2533570Smckusick 			cp++;
2543570Smckusick 		len = cp - word;
2553570Smckusick 		switch (*word) {
2563570Smckusick 		case 'b':
25715685Speter 			if (len == 5 && !strncmp(word, "begin", 5)) {
2583570Smckusick 				if (nest == 0 && beginnest == 0) {
2593570Smckusick 					if (inprog != 1) {
2603570Smckusick 						fprintf(stderr,
2613570Smckusick 						    "improper program body");
2623570Smckusick 						quit(NULL);
2633570Smckusick 					}
2643570Smckusick 					curfile = files[BODYFILE];
2653570Smckusick 				} else {
2663570Smckusick 					beginnest++;
2673570Smckusick 				}
2683570Smckusick 			}
2693570Smckusick 			break;
2703570Smckusick 		case 'c':
27115685Speter 			if (len == 4 && !strncmp(word, "case", 4)) {
2723570Smckusick 				if (beginnest > 0) {
2733570Smckusick 					beginnest++;
2743570Smckusick 				}
2753570Smckusick 				break;
2763570Smckusick 			}
27715685Speter 			if (len == 5 && !strncmp(word, "const", 5)) {
2783570Smckusick 				if (nest == 0) {
2793570Smckusick 					prt = FALSE;
2803570Smckusick 					if (!constopen) {
2813570Smckusick 						constopen = TRUE;
2823570Smckusick 						prt = TRUE;
2833570Smckusick 					}
2843570Smckusick 					curfile = files[CONSTFILE];
2853570Smckusick 				}
2863570Smckusick 			}
2873570Smckusick 			break;
2883570Smckusick 		case 'e':
28915685Speter 			if (len == 3 && !strncmp(word, "end", 3)) {
2903570Smckusick 				if (beginnest == 1) {
2913570Smckusick 					nest--;
2923570Smckusick 				}
2933570Smckusick 				if (beginnest > 0) {
2943570Smckusick 					beginnest--;
2953570Smckusick 				}
2963570Smckusick 				if (nest < 0) {
2973570Smckusick 					if (inprog == 1) {
2983570Smckusick 						inprog = 0;
2993570Smckusick 						nest = 0;
3003570Smckusick 					} else {
3013570Smckusick 						fprintf(stderr, "too many end statements");
3023570Smckusick 						quit(NULL);
3033570Smckusick 					}
3043570Smckusick 				}
3053570Smckusick 				break;
3063570Smckusick 			}
30715685Speter 			if (len == 8 && !strncmp(word, "external", 8)) {
3083570Smckusick 				fputs("forward", curfile);
3093570Smckusick 				prt = FALSE;
3109577Sgarrison 				if (paren_level == 0) {
3119577Sgarrison 					nest--;
3129577Sgarrison 				}
3133570Smckusick 			}
3143570Smckusick 			break;
3153570Smckusick 		case 'f':
31615685Speter 			if (len == 8 && !strncmp(word, "function", 8)) {
3173570Smckusick 				if (nest == 0) {
3183570Smckusick 					curfile = files[RTNFILE];
3193570Smckusick 				}
3209577Sgarrison 				if (paren_level == 0) {
3219577Sgarrison 					nest++;
3229577Sgarrison 				}
3233570Smckusick 				break;
3243570Smckusick 			}
32515685Speter 			if (len == 7 && !strncmp(word, "forward", 7)) {
3269577Sgarrison 				if (paren_level == 0) {
3279577Sgarrison 					nest--;
3289577Sgarrison 				}
3293570Smckusick 			}
3303570Smckusick 			break;
3313570Smckusick 		case 'l':
33215685Speter 			if (len == 5 && !strncmp(word, "label", 5)) {
3333570Smckusick 				if (nest == 0) {
3343570Smckusick 					prt = FALSE;
3353570Smckusick 					if (!labelopen) {
3363570Smckusick 						labelopen = TRUE;
3373570Smckusick 						prt = TRUE;
3383570Smckusick 					}
3393570Smckusick 					curfile = files[LABELFILE];
3403570Smckusick 				}
3413570Smckusick 			}
3423570Smckusick 			break;
3433570Smckusick 		case 'p':
34415685Speter 			if (len == 9 && !strncmp(word, "procedure", 9)) {
3453570Smckusick 				if (nest == 0) {
3463570Smckusick 					curfile = files[RTNFILE];
3473570Smckusick 				}
3489577Sgarrison 				if (paren_level == 0) {
3499577Sgarrison 					nest++;
3509577Sgarrison 				}
3513570Smckusick 				break;
3523570Smckusick 			}
35315685Speter 			if (len == 7 && !strncmp(word, "program", 7)) {
3543570Smckusick 				if (nest != 0) {
3553570Smckusick 					fprintf(stderr, "improper program nesting");
3563570Smckusick 					quit(NULL);
3573570Smckusick 				}
3583570Smckusick 				inprog = 1;
3593570Smckusick 				curfile = files[PRGFILE];
3603570Smckusick 			}
3613570Smckusick 			break;
3623570Smckusick 		case 't':
36315685Speter 			if (len == 4 && !strncmp(word, "type", 4)) {
3643570Smckusick 				if (nest == 0) {
3653570Smckusick 					prt = FALSE;
3663570Smckusick 					if (!typeopen) {
3673570Smckusick 						typeopen = TRUE;
3683570Smckusick 						prt = TRUE;
3693570Smckusick 					}
3703570Smckusick 					curfile = files[TYPEFILE];
3713570Smckusick 				}
3723570Smckusick 			}
3733570Smckusick 			break;
3743570Smckusick 		case 'v':
37515685Speter 			if (len == 3 && !strncmp(word, "var", 3)) {
3763570Smckusick 				if (nest == 0) {
3773570Smckusick 					prt = FALSE;
3783570Smckusick 					if (!varopen) {
3793570Smckusick 						varopen = TRUE;
3803570Smckusick 						prt = TRUE;
3813570Smckusick 					}
3823570Smckusick 					curfile = files[VARFILE];
3833570Smckusick 				}
3843570Smckusick 			}
3853570Smckusick 			break;
3863570Smckusick 		}
3873570Smckusick 		if (prt)
3883570Smckusick 			fprintf(curfile, "%.*s", len, word);
3893570Smckusick 		prt = TRUE;
3903570Smckusick 		ch1 = ' ';
3913570Smckusick 	}
3923570Smckusick }
3933570Smckusick 
3943570Smckusick /*
3953570Smckusick  * Print out the merged result
3963570Smckusick  */
printout()3973570Smckusick printout()
3983570Smckusick {
3993570Smckusick 	FILE *fp;
4003570Smckusick 	int i;
4013570Smckusick 	char ch;
4023570Smckusick 
4033570Smckusick 	for(i = 0; i < NUMFILES; i++) {
4043570Smckusick 		fp = freopen(names[i], "r", files[i]);
4053570Smckusick 		if (fp == NULL)
4063570Smckusick 			quit(names[i]);
4073570Smckusick 		ch = getc(fp);
4083570Smckusick 		while (!feof(fp)) {
4093570Smckusick 			putc(ch,stdout);
4103570Smckusick 			ch = getc(fp);
4113570Smckusick 		}
4123570Smckusick 	}
4133570Smckusick }
4143570Smckusick 
4153570Smckusick /*
4163570Smckusick  * Die gracefully
4173570Smckusick  */
quit(fp)4183570Smckusick quit(fp)
4193570Smckusick 	char *fp;
4203570Smckusick {
4213570Smckusick 	if (fp != NULL)
4223570Smckusick 		perror(fp);
42347032Sdonn 	onintr(0);
4243570Smckusick 	exit(1);
4253570Smckusick }
426