xref: /csrg-svn/usr.bin/pascal/pxp/main.c (revision 15991)
1 static	char *sccsid = "@(#)main.c	2.1 (Berkeley) 02/08/84";
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 #			ifdef RMOTHERS
136 			case 'O':
137 				rmothers++;
138 				continue;
139 #			endif RMOTHERS
140 			default:
141 				if (c >= '2' && c <= '9') {
142 					unit = c - '0';
143 					continue;
144 				}
145 usage:
146 				Perror("Usage", usagestr);
147 				exit(1);
148 		}
149 		argc--, argv++;
150 	}
151 	if (core && !profile && !table)
152 		profile++;
153 	if (argc == 0 || argc > 2)
154 		goto usage;
155 	if (profile || table) {
156 		noinclude = 0;
157 		if (argc == 2) {
158 			argc--;
159 			getit(argv[1]);
160 		} else
161 			getit(core ? "core" : "pmon.out");
162 	} else
163 		noinclude++;
164 	if (argc != 1)
165 		goto usage;
166 	firstname = filename = argv[0];
167 	if (dotted(filename, 'i')) {
168 		if (profile || table)
169 			goto usage;
170 		noinclude = 1;
171 		bracket++;
172 	} else if (!dotted(filename, 'p')) {
173 		Perror(filename, "Name must end in '.p'");
174 		exit(1);
175 	}
176 	if ((ibuf = fopen(filename, "r")) == NULL)
177 		perror(filename), pexit(NOSTART);
178 	ibp = ibuf;
179 	if (onefile) {
180 		int onintr();
181 
182 		cp = (stdoutn = "/tmp/pxp00000") + 13;
183 		signal(2, onintr);
184 		for (c = getpid(); c; c =/ 10)
185 			*--cp =| (c % 10);
186 		if (freopen(stdoutn, "w", stdout) == NULL)
187 bad:
188 			perror(stdoutn), exit(1);
189 	} else {
190 		extern char _sobuf[BUFSIZ];
191 		setbuf(stdout, _sobuf);
192 	}
193 	if (profile || opt('l')) {
194 		opt('n')++;
195 		yysetfile(filename);
196 		opt('n')--;
197 	} else
198 		lastname = filename;
199 	errout = 2;
200 	yymain();
201 	/* No return */
202 }
203 
204 /*
205  * Put a header on a top of a page
206  */
207 header()
208 {
209 	extern char version[];
210 	static char reenter;
211 	extern int outcol;
212 
213 	gettime();
214 	if (reenter) {
215 		if (outcol)
216 			putchar('\n');
217 		putchar('\f');
218 	}
219 	reenter++;
220 	if (profile || table) {
221 		printf("Berkeley Pascal PXP -- Version %s\n\n%s  %s\n\n",
222 			version, myctime(&tvec), filename);
223 		printf("Profiled %s\n\n", myctime(&ptvec));
224 	}
225 }
226 
227 char	ugh[] =	"Fatal error in pxp\n";
228 /*
229  * Exit from the Pascal system.
230  * We throw in an ungraceful termination
231  * message if c > 1 indicating a severe
232  * error such as running out of memory
233  * or an internal inconsistency.
234  */
235 pexit(c)
236 	int c;
237 {
238 	register char *cp;
239 	extern int outcol;
240 
241 	if (stdoutn[0] == '/')
242 		unlink(stdoutn);
243 	if (outcol)
244 		putchar('\n');
245 	flush();
246 	if (c == DIED)
247 		write(2, ugh, sizeof ugh);
248 	exit(c);
249 }
250 
251 onintr()
252 {
253 
254 	pexit(DIED);
255 }
256 
257 puthedr()
258 {
259 
260 	yysetfile(filename);
261 }
262