xref: /original-bsd/usr.bin/pascal/pxp/main.c (revision c0e889e7)
1 static	char *sccsid = "@(#)main.c	1.2 (Berkeley) 08/13/82";
2 /* Copyright (c) 1979 Regents of the University of California */
3 #
4 /*
5  * pxp - Pascal execution profiler
6  *
7  * Bill Joy UCB
8  * Version 1.2 January 1979
9  */
10 
11 #include "0.h"
12 
13 /*
14  * This program is described in detail in the "PXP 1.0 Implementation Notes"
15  *
16  * The structure of pxp is very similar to that of the translator pi.
17  * The major new pieces here are a set of profile data maintenance
18  * routines in the file pmon.c and a set of pretty printing utility
19  * routines in the file pp.c.
20  * The semantic routines of pi have been rewritten to do a simple
21  * reformatting tree walk, the parsing and scanning remains
22  * the same.
23  *
24  * This version does not place more than one statement per line and
25  * is not very intelligent about folding long lines, with only
26  * an ad hoc way of folding case label list and enumerated type
27  * declarations being implemented.
28  */
29 
30 char	usagestr[] =
31 	"pxp [ -acdefjntuw_ ] [ -23456789 ] [ -z [ name ... ] ] name.p";
32 char	*howfile =	"/usr/lib/how_pxp";
33 char	*stdoutn =	"Standard output";
34 
35 int	unit =	4;
36 
37 FILE	*ibuf;
38 extern	char errout;
39 
40 /*
41  * Main program for pxp.
42  * Process options, then call yymain
43  * to do all the real work.
44  */
45 FILE *ibp;
46 main(argc, argv)
47 	int argc;
48 	char *argv[];
49 {
50 	register char *cp;
51 	register c;
52 
53 	if (argv[0][0] == 'a')
54 		howfile =+ 9;
55 	argc--, argv++;
56 	if (argc == 0) {
57 		execl("/bin/cat", "cat", howfile, 0);
58 		goto usage;
59 	}
60 	while (argc > 0) {
61 		cp = argv[0];
62 		if (*cp++ != '-')
63 			break;
64 		while (c = *cp++) switch (c) {
65 #ifdef DEBUG
66 			case 'T':
67 				typetest++;
68 				continue;
69 			case 'A':
70 				testtrace++;
71 			case 'F':
72 				fulltrace++;
73 			case 'E':
74 				errtrace++;
75 				continue;
76 			case 'C':
77 				yycosts();
78 				pexit(NOSTART);
79 			case 'U':
80 				yyunique++;
81 				continue;
82 #endif
83 			case 'a':
84 				all++;
85 				continue;
86 			case 'c':
87 				core++;
88 				continue;
89 			case 'd':
90 				nodecl++;
91 				continue;
92 			case 'e':
93 				noinclude = -1;
94 				continue;
95 			case 'f':
96 				full++;
97 				continue;
98 			case 'j':
99 				justify++;
100 				continue;
101 			case 'l':
102 			case 'n':
103 				togopt(c);
104 				continue;
105 			case 'o':
106 				onefile++;
107 				continue;
108 			case 's':
109 				stripcomm++;
110 				continue;
111 			case 't':
112 				table++;
113 				continue;
114 			case 'u':
115 			case 'w':
116 				togopt(c);
117 				continue;
118 			case 'z':
119 				profile++;
120 				pflist = argv + 1;
121 				pflstc = 0;
122 				while (argc > 1) {
123 					if (dotted(argv[1], 'p'))
124 						break;
125 					pflstc++, argc--, argv++;
126 				}
127 				if (pflstc == 0)
128 					togopt(c);
129 				else
130 					nojunk++;
131 				continue;
132 			case '_':
133 				underline++;
134 				continue;
135 			default:
136 				if (c >= '2' && c <= '9') {
137 					unit = c - '0';
138 					continue;
139 				}
140 usage:
141 				Perror("Usage", usagestr);
142 				exit(1);
143 		}
144 		argc--, argv++;
145 	}
146 	if (core && !profile && !table)
147 		profile++;
148 	if (argc == 0 || argc > 2)
149 		goto usage;
150 	if (profile || table) {
151 		noinclude = 0;
152 		if (argc == 2) {
153 			argc--;
154 			getit(argv[1]);
155 		} else
156 			getit(core ? "core" : "pmon.out");
157 	} else
158 		noinclude++;
159 	if (argc != 1)
160 		goto usage;
161 	firstname = filename = argv[0];
162 	if (dotted(filename, 'i')) {
163 		if (profile || table)
164 			goto usage;
165 		noinclude = 1;
166 		bracket++;
167 	} else if (!dotted(filename, 'p')) {
168 		Perror(filename, "Name must end in '.p'");
169 		exit(1);
170 	}
171 	if ((ibuf = fopen(filename, "r")) == NULL)
172 		perror(filename), pexit(NOSTART);
173 	ibp = ibuf;
174 	if (onefile) {
175 		int onintr();
176 
177 		cp = (stdoutn = "/tmp/pxp00000") + 13;
178 		signal(2, onintr);
179 		for (c = getpid(); c; c =/ 10)
180 			*--cp =| (c % 10);
181 		if (freopen(stdoutn, "w", stdout) == NULL)
182 bad:
183 			perror(stdoutn), exit(1);
184 	} else {
185 		extern char _sobuf[BUFSIZ];
186 		setbuf(stdout, _sobuf);
187 	}
188 	if (profile || opt('l')) {
189 		opt('n')++;
190 		yysetfile(filename);
191 		opt('n')--;
192 	} else
193 		lastname = filename;
194 	errout = 2;
195 	yymain();
196 	/* No return */
197 }
198 
199 /*
200  * Put a header on a top of a page
201  */
202 header()
203 {
204 	extern char version[];
205 	static char reenter;
206 	extern int outcol;
207 
208 	gettime();
209 	if (reenter) {
210 		if (outcol)
211 			putchar('\n');
212 		putchar('\f');
213 	}
214 	reenter++;
215 	if (profile || table) {
216 		printf("Berkeley Pascal PXP -- Version %s\n\n%s  %s\n\n",
217 			version, myctime(&tvec), filename);
218 		printf("Profiled %s\n\n", myctime(&ptvec));
219 	}
220 }
221 
222 char	ugh[] =	"Fatal error in pxp\n";
223 /*
224  * Exit from the Pascal system.
225  * We throw in an ungraceful termination
226  * message if c > 1 indicating a severe
227  * error such as running out of memory
228  * or an internal inconsistency.
229  */
230 pexit(c)
231 	int c;
232 {
233 	register char *cp;
234 	extern int outcol;
235 
236 	if (stdoutn[0] == '/')
237 		unlink(stdoutn);
238 	if (outcol)
239 		putchar('\n');
240 	flush();
241 	if (c == DIED)
242 		write(2, ugh, sizeof ugh);
243 	exit(c);
244 }
245 
246 onintr()
247 {
248 
249 	pexit(DIED);
250 }
251 
252 puthedr()
253 {
254 
255 	yysetfile(filename);
256 }
257