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