1 static char *sccsid = "@(#)yycomm.c 1.2 (Berkeley) 02/05/83"; 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 "whoami.h" 12 #include "0.h" 13 #include "yy.h" 14 15 /* 16 * COMMENT PROCESSING CLUSTER 17 * 18 * The global organization of this cluster is as follows. 19 * While parsing the program information is saved in the tree which 20 * tells the source text coordinates (sequence numbers and columns) 21 * bounding each production. The comments from the source program 22 * are also saved, with information about their source text position 23 * and a classification as to their kind. 24 * 25 * When printing the reformatted program we flush out the comments 26 * at various points using the information in the comments and the parse 27 * tree to "resynchronize". A number of special cases are recognized to 28 * deal with the vagarities of producing a true "fixed point" so that 29 * a prettyprinted program will re-prettyprint to itself. 30 */ 31 32 /* 33 * Save sequence id's and column markers bounding a production 34 * for later use in placing comments. We save the sequence id 35 * and column of the leftmost token and the following token, and 36 * the sequence id of the last token in this reduction. 37 * See putcm, putcml, and putcmp below for motivation. 38 */ 39 line2of(l) 40 int l; 41 { 42 43 return (lineNof(l, 2)); 44 } 45 46 lineof(l) 47 int l; 48 { 49 50 return (lineNof(l, 1)); 51 } 52 53 lineNof(l, i) 54 int l, i; 55 { 56 57 return(tree(6, l, yypw[i].Wseqid, yypw[i].Wcol, yyseqid, yycol, yypw[N].Wseqid)); 58 } 59 60 /* 61 * After a call to setline, Seqid is set to the sequence id 62 * of the symbol which followed the reduction in which the 63 * lineof call was embedded, Col to the associated column, 64 * and LSeqid to the sequence id of the last symbol in the reduction 65 * (Note that this is exact only if the last symbol was a terminal 66 * this is always true when it matters.) 67 */ 68 int Seqid, Col, LSeqid; 69 70 /* 71 * Retrieve the information from a call to lineof before beginning the 72 * output of a tree from a reduction. First flush to the left margin 73 * of the production, and then set so that later calls to putcm, putcml 74 * and putcmp will deal with the right margin of this comment. 75 * 76 * The routine setinfo is called when the lineof has no embedded line 77 * number to avoid trashing the current "line". 78 * 79 * The routine setinfo is often called after completing the output of 80 * the text of a tree to restore Seqid, Col, and LSeqid which may have 81 * been destroyed by the nested processing calls to setline. 82 * In this case the only effect of the call to setinfo is to 83 * modify the above three variables as a side effect. 84 * 85 * We return a word giving information about the comments which were 86 * actually put out. See putcm for details. 87 */ 88 setline(ip) 89 int *ip; 90 { 91 92 line = ip[0]; 93 return(setinfo(ip)); 94 } 95 96 setinfo(ip) 97 register int *ip; 98 { 99 register int i; 100 101 ip++; 102 Seqid = *ip++; 103 Col = *ip++; 104 i = putcm(); 105 Seqid = *ip++; 106 Col = *ip++; 107 LSeqid = *ip++; 108 return (i); 109 } 110 111 char cmeof, incomm; 112 113 /* 114 * Get the text of a comment from the input stream, 115 * recording its type and linking it into the linked 116 * list of comments headed by cmhp. 117 */ 118 getcm(cmdelim) 119 char cmdelim; 120 { 121 int cmjust, col; 122 register struct comment *cp; 123 register struct commline *kp; 124 125 incomm = 1; 126 if (cmdelim == '*' && yycol == 10 || cmdelim == '{' && yycol == 9) 127 cmjust = CLMARG; 128 else if (yytokcnt <= 1) 129 cmjust = CALIGN; 130 else if (yywhcnt < 2) 131 cmjust = CTRAIL; 132 else 133 cmjust = CRMARG; 134 col = yycol - (cmdelim == '{' ? 1 : 2); 135 cp = tree5(NIL, cmdelim, NIL, cmjust, yyseqid); 136 cmeof = 0; 137 do { 138 kp = getcmline(cmdelim); 139 if (cp->cml == NIL) { 140 kp->cml = kp; 141 kp->cmcol = col; 142 } else { 143 kp->cml = cp->cml->cml; 144 cp->cml->cml = kp; 145 switch (cp->cmjust) { 146 case CTRAIL: 147 case CRMARG: 148 cp->cmjust = CALIGN; 149 } 150 } 151 cp->cml = kp; 152 } while (!cmeof); 153 newcomm(cp); 154 incomm = 0; 155 } 156 157 /* 158 * Chain the new comment at "cp" onto the linked list of comments. 159 */ 160 newcomm(cp) 161 register struct comment *cp; 162 { 163 164 if (cmhp == NIL) 165 cp->cmnext = cp; 166 else { 167 cp->cmnext = cmhp->cmnext; 168 cmhp->cmnext = cp; 169 } 170 cmhp = cp; 171 } 172 173 174 int nilcml[3]; 175 176 quickcomm(t) 177 int t; 178 { 179 180 if (incomm) 181 return; 182 newcomm(tree5(nilcml, NIL, NIL, t, yyseqid)); 183 } 184 185 commincl(cp, ch) 186 char *cp, ch; 187 { 188 189 newcomm(tree5(nilcml, savestr(cp), ch, CINCLUD, yyseqid)); 190 } 191 192 getcmline(cmdelim) 193 char cmdelim; 194 { 195 char lastc; 196 register char *tp; 197 register CHAR c; 198 register struct commline *kp; 199 200 c = readch(); 201 kp = tree3(NIL, yycol, NIL); 202 tp = token; 203 lastc = 0; 204 for (;;) { 205 switch (c) { 206 case '}': 207 if (cmdelim == '{') 208 goto endcm; 209 break; 210 case ')': 211 if (cmdelim == '*' && lastc == '*') { 212 --tp; 213 goto endcm; 214 } 215 break; 216 case '\n': 217 goto done; 218 case -1: 219 yerror("Comment does not terminate - QUIT"); 220 pexit(ERRS); 221 } 222 lastc = c; 223 *tp++ = c; 224 c = readch(); 225 } 226 endcm: 227 cmeof++; 228 done: 229 *tp = 0; 230 kp->cmtext = copystr(token); 231 return (kp); 232 } 233 234 /* 235 * Flush through the line this token is on. 236 * Ignore if next token on same line as this one. 237 */ 238 putcml() 239 { 240 register int i, SSeqid, SCol; 241 242 if (Seqid == LSeqid) 243 return (1); 244 SSeqid = Seqid, SCol = Col; 245 Seqid = LSeqid, Col = 32767; 246 i = putcm(); 247 Seqid = SSeqid, Col = SCol; 248 return (i); 249 } 250 251 /* 252 * Flush to the beginning of the line this token is on. 253 * Ignore if this token is on the same line as the previous one 254 * (effectively since all such already then flushed.) 255 */ 256 putcmp() 257 { 258 register int i, SSeqid, SCol; 259 260 SSeqid = Seqid, SCol = Col; 261 Seqid = LSeqid, Col = 0; 262 i = putcm(); 263 Seqid = SSeqid, Col = SCol; 264 return (i); 265 } 266 267 /* 268 * Put out the comments to the border indicated by Seqid and Col 269 */ 270 putcm() 271 { 272 register struct comment *cp; 273 register int i; 274 275 cp = cmhp; 276 if (cp == NIL) 277 return (0); 278 i = 0; 279 cp = cp->cmnext; 280 while (cp->cmseqid < Seqid || cp->cmseqid == Seqid && cp->cml->cmcol < Col) { 281 putone(cp); 282 i =| 1 << cp->cmjust; 283 if (cp->cmnext == cp) { 284 cmhp = NIL; 285 break; 286 } 287 cp = cp->cmnext; 288 cmhp->cmnext = cp; 289 } 290 return (i); 291 } 292 293 /* 294 * Put out one comment. 295 * Note that empty lines, form feeds and #include statements 296 * are treated as comments are regurgitated here. 297 */ 298 putone(cp) 299 register struct comment *cp; 300 { 301 register struct commline *cml, *cmf; 302 303 align(cp); 304 switch (cp->cmjust) { 305 case CINCLUD: 306 /* ppflush() */ 307 if (noinclude == 0) { 308 putchar('\f'); 309 return; 310 } 311 printf("#include %c%s%c", cp->cml, cp->cmdelim, cp->cml); 312 return; 313 } 314 if (stripcomm) 315 return; 316 switch (cp->cmjust) { 317 case CFORM: 318 ppop("\f"); 319 ppnl(); 320 case CNL: 321 case CNLBL: 322 return; 323 } 324 ppbra(cp->cmdelim == '{' ? "{" : "(*"); 325 cmf = cp->cml->cml; 326 ppid(cmf->cmtext); 327 for (cml = cmf->cml; cml != cmf; cml = cml->cml) { 328 align(cp); 329 oneline(cmf->cmcol, cml); 330 } 331 ppket(cp->cmdelim == '{' ? "}" : "*)"); 332 } 333 334 /* 335 * Do the preliminary horizontal and vertical 336 * motions necessary before beginning a comment, 337 * or between lines of a mult-line comment. 338 */ 339 align(cp) 340 register struct comment *cp; 341 { 342 343 switch (cp->cmjust) { 344 case CNL: 345 ppsnl(); 346 break; 347 case CNLBL: 348 ppsnlb(); 349 break; 350 case CFORM: 351 case CINCLUD: 352 ppnl(); 353 break; 354 case CLMARG: 355 ppnl(); 356 if (profile) 357 ppid("\t"); 358 break; 359 case CALIGN: 360 ppnl(); 361 indent(); 362 break; 363 case CTRAIL: 364 ppspac(); 365 break; 366 case CRMARG: 367 case CSRMARG: 368 pptab(); 369 break; 370 } 371 } 372 373 /* 374 * One line of a multi-line comment 375 * Deal with alignment and initial white space trimming. 376 * The "margin" indicates where the first line of the 377 * comment began... don't print stuff in this comment 378 * which came before this. 379 */ 380 oneline(margin, cml) 381 int margin; 382 struct commline *cml; 383 { 384 register char *tp; 385 register int i; 386 387 for (i = 8, tp = cml->cmtext; i < margin && *tp; tp++) 388 switch (*tp) { 389 case ' ': 390 i++; 391 continue; 392 case '\t': 393 i =+ 8; 394 i =& ~7; 395 if (i < margin) 396 continue; 397 ppop("\t"); 398 default: 399 goto out; 400 } 401 out: 402 ppid(tp); 403 } 404 405 /* 406 * Flush all comments 407 */ 408 flushcm() 409 { 410 411 Seqid = 32767; 412 return(putcm()); 413 } 414 415 #define BLANKS ((1 << CNL) | (1 << CNLBL) | (1 << CFORM)) 416 noblank(i) 417 int i; 418 { 419 420 return ((i & BLANKS) == 0); 421 } 422 423 int needform, neednlbl, neednl, needseqid; 424 425 needtree() 426 { 427 register struct comment *cp; 428 429 needform = neednlbl = neednl = 0; 430 cp = cmhp; 431 if (cp == NIL) 432 return (0); 433 do { 434 switch (cp->cmjust) { 435 case CNL: 436 neednl++; 437 goto seq; 438 case CNLBL: 439 neednlbl++; 440 goto seq; 441 case CFORM: 442 needform++; 443 seq: 444 needseqid = cp->cmseqid; 445 break; 446 default: 447 neednl = neednlbl = needform = 0; 448 return (1); 449 } 450 cp = cp->cmnext; 451 } while (cp != cmhp); 452 cmhp = NIL; 453 return (0); 454 } 455 456 packtree() 457 { 458 int save; 459 460 save = yyseqid; 461 yyseqid = needseqid; 462 for (; needform > 0; needform--) 463 commform(); 464 for (; neednl > 0; neednl--) 465 commnl(); 466 for (; neednlbl > 0; neednlbl--) 467 commnlbl(); 468 yyseqid = save; 469 } 470