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