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