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