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;
main(argc,argv)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 */
header()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 */
pexit(c)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
onintr()262 onintr()
263 {
264
265 pexit(DIED);
266 }
267
puthedr()268 puthedr()
269 {
270
271 yysetfile(filename);
272 }
273