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