check for empty others clause.
[unix-history] / usr / src / usr.bin / pascal / pxp / yycomm.c
CommitLineData
5bbe9cdb 1static char *sccsid = "@(#)yycomm.c 1.2 (Berkeley) %G%";
16f88651
PK
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
5bbe9cdb 11#include "whoami.h"
16f88651
PK
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 */
39line2of(l)
40 int l;
41{
42
43 return (lineNof(l, 2));
44}
45
46lineof(l)
47 int l;
48{
49
50 return (lineNof(l, 1));
51}
52
53lineNof(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 */
68int 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 */
88setline(ip)
89 int *ip;
90{
91
92 line = ip[0];
93 return(setinfo(ip));
94}
95
96setinfo(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
111char 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 */
118getcm(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 */
160newcomm(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
174int nilcml[3];
175
176quickcomm(t)
177 int t;
178{
179
180 if (incomm)
181 return;
182 newcomm(tree5(nilcml, NIL, NIL, t, yyseqid));
183}
184
185commincl(cp, ch)
186 char *cp, ch;
187{
188
189 newcomm(tree5(nilcml, savestr(cp), ch, CINCLUD, yyseqid));
190}
191
192getcmline(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 }
226endcm:
227 cmeof++;
228done:
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 */
238putcml()
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 */
256putcmp()
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 */
270putcm()
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 */
298putone(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 */
339align(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 */
380oneline(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 }
401out:
402 ppid(tp);
403}
404
405/*
406 * Flush all comments
407 */
408flushcm()
409{
410
411 Seqid = 32767;
412 return(putcm());
413}
414
415#define BLANKS ((1 << CNL) | (1 << CNLBL) | (1 << CFORM))
416noblank(i)
417 int i;
418{
419
420 return ((i & BLANKS) == 0);
421}
422
423int needform, neednlbl, neednl, needseqid;
424
425needtree()
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++;
443seq:
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
456packtree()
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}