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