4e4f8897934cdab1657e8cc9272afe52892501ce
[unix-history] / usr / src / usr.bin / pascal / pxp / yycomm.c
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#ifndef lint
static char sccsid[] = "@(#)yycomm.c 5.2 (Berkeley) %G%";
#endif not lint
/*
* pxp - Pascal execution profiler
*
* Bill Joy UCB
* Version 1.2 January 1979
*/
#include "whoami.h"
#include "0.h"
#include "yy.h"
/*
* COMMENT PROCESSING CLUSTER
*
* The global organization of this cluster is as follows.
* While parsing the program information is saved in the tree which
* tells the source text coordinates (sequence numbers and columns)
* bounding each production. The comments from the source program
* are also saved, with information about their source text position
* and a classification as to their kind.
*
* When printing the reformatted program we flush out the comments
* at various points using the information in the comments and the parse
* tree to "resynchronize". A number of special cases are recognized to
* deal with the vagarities of producing a true "fixed point" so that
* a prettyprinted program will re-prettyprint to itself.
*/
/*
* Save sequence id's and column markers bounding a production
* for later use in placing comments. We save the sequence id
* and column of the leftmost token and the following token, and
* the sequence id of the last token in this reduction.
* See putcm, putcml, and putcmp below for motivation.
*/
line2of(l)
int l;
{
return (lineNof(l, 2));
}
lineof(l)
int l;
{
return (lineNof(l, 1));
}
lineNof(l, i)
int l, i;
{
return(tree(6, l, yypw[i].Wseqid, yypw[i].Wcol, yyseqid, yycol, yypw[N].Wseqid));
}
/*
* After a call to setline, Seqid is set to the sequence id
* of the symbol which followed the reduction in which the
* lineof call was embedded, Col to the associated column,
* and LSeqid to the sequence id of the last symbol in the reduction
* (Note that this is exact only if the last symbol was a terminal
* this is always true when it matters.)
*/
int Seqid, Col, LSeqid;
/*
* Retrieve the information from a call to lineof before beginning the
* output of a tree from a reduction. First flush to the left margin
* of the production, and then set so that later calls to putcm, putcml
* and putcmp will deal with the right margin of this comment.
*
* The routine setinfo is called when the lineof has no embedded line
* number to avoid trashing the current "line".
*
* The routine setinfo is often called after completing the output of
* the text of a tree to restore Seqid, Col, and LSeqid which may have
* been destroyed by the nested processing calls to setline.
* In this case the only effect of the call to setinfo is to
* modify the above three variables as a side effect.
*
* We return a word giving information about the comments which were
* actually put out. See putcm for details.
*/
setline(ip)
int *ip;
{
line = ip[0];
return(setinfo(ip));
}
setinfo(ip)
register int *ip;
{
register int i;
ip++;
Seqid = *ip++;
Col = *ip++;
i = putcm();
Seqid = *ip++;
Col = *ip++;
LSeqid = *ip++;
return (i);
}
char cmeof, incomm;
/*
* Get the text of a comment from the input stream,
* recording its type and linking it into the linked
* list of comments headed by cmhp.
*/
getcm(cmdelim)
char cmdelim;
{
int cmjust, col;
register struct comment *cp;
register struct commline *kp;
incomm = 1;
if (cmdelim == '*' && yycol == 10 || cmdelim == '{' && yycol == 9)
cmjust = CLMARG;
else if (yytokcnt <= 1)
cmjust = CALIGN;
else if (yywhcnt < 2)
cmjust = CTRAIL;
else
cmjust = CRMARG;
col = yycol - (cmdelim == '{' ? 1 : 2);
cp = tree5(NIL, cmdelim, NIL, cmjust, yyseqid);
cmeof = 0;
do {
kp = getcmline(cmdelim);
if (cp->cml == NIL) {
kp->cml = kp;
kp->cmcol = col;
} else {
kp->cml = cp->cml->cml;
cp->cml->cml = kp;
switch (cp->cmjust) {
case CTRAIL:
case CRMARG:
cp->cmjust = CALIGN;
}
}
cp->cml = kp;
} while (!cmeof);
newcomm(cp);
incomm = 0;
}
/*
* Chain the new comment at "cp" onto the linked list of comments.
*/
newcomm(cp)
register struct comment *cp;
{
if (cmhp == NIL)
cp->cmnext = cp;
else {
cp->cmnext = cmhp->cmnext;
cmhp->cmnext = cp;
}
cmhp = cp;
}
int nilcml[3];
quickcomm(t)
int t;
{
if (incomm)
return;
newcomm(tree5(nilcml, NIL, NIL, t, yyseqid));
}
commincl(cp, ch)
char *cp, ch;
{
newcomm(tree5(nilcml, savestr(cp), ch, CINCLUD, yyseqid));
}
getcmline(cmdelim)
char cmdelim;
{
char lastc;
register char *tp;
register CHAR c;
register struct commline *kp;
c = readch();
kp = tree3(NIL, yycol, NIL);
tp = token;
lastc = 0;
for (;;) {
switch (c) {
case '}':
if (cmdelim == '{')
goto endcm;
break;
case ')':
if (cmdelim == '*' && lastc == '*') {
--tp;
goto endcm;
}
break;
case '\n':
goto done;
case -1:
yerror("Comment does not terminate - QUIT");
pexit(ERRS);
}
lastc = c;
*tp++ = c;
c = readch();
}
endcm:
cmeof++;
done:
*tp = 0;
kp->cmtext = copystr(token);
return (kp);
}
/*
* Flush through the line this token is on.
* Ignore if next token on same line as this one.
*/
putcml()
{
register int i, SSeqid, SCol;
if (Seqid == LSeqid)
return (1);
SSeqid = Seqid, SCol = Col;
Seqid = LSeqid, Col = 32767;
i = putcm();
Seqid = SSeqid, Col = SCol;
return (i);
}
/*
* Flush to the beginning of the line this token is on.
* Ignore if this token is on the same line as the previous one
* (effectively since all such already then flushed.)
*/
putcmp()
{
register int i, SSeqid, SCol;
SSeqid = Seqid, SCol = Col;
Seqid = LSeqid, Col = 0;
i = putcm();
Seqid = SSeqid, Col = SCol;
return (i);
}
/*
* Put out the comments to the border indicated by Seqid and Col
*/
putcm()
{
register struct comment *cp;
register int i;
cp = cmhp;
if (cp == NIL)
return (0);
i = 0;
cp = cp->cmnext;
while (cp->cmseqid < Seqid || cp->cmseqid == Seqid && cp->cml->cmcol < Col) {
putone(cp);
i |= 1 << cp->cmjust;
if (cp->cmnext == cp) {
cmhp = NIL;
break;
}
cp = cp->cmnext;
cmhp->cmnext = cp;
}
return (i);
}
/*
* Put out one comment.
* Note that empty lines, form feeds and #include statements
* are treated as comments are regurgitated here.
*/
putone(cp)
register struct comment *cp;
{
register struct commline *cml, *cmf;
align(cp);
switch (cp->cmjust) {
case CINCLUD:
/* ppflush() */
if (noinclude == 0) {
putchar('\f');
return;
}
printf("#include %c%s%c", cp->cml, cp->cmdelim, cp->cml);
return;
}
if (stripcomm)
return;
switch (cp->cmjust) {
case CFORM:
ppop("\f");
ppnl();
case CNL:
case CNLBL:
return;
}
ppbra(cp->cmdelim == '{' ? "{" : "(*");
cmf = cp->cml->cml;
ppid(cmf->cmtext);
for (cml = cmf->cml; cml != cmf; cml = cml->cml) {
align(cp);
oneline(cmf->cmcol, cml);
}
ppket(cp->cmdelim == '{' ? "}" : "*)");
}
/*
* Do the preliminary horizontal and vertical
* motions necessary before beginning a comment,
* or between lines of a mult-line comment.
*/
align(cp)
register struct comment *cp;
{
switch (cp->cmjust) {
case CNL:
ppsnl();
break;
case CNLBL:
ppsnlb();
break;
case CFORM:
case CINCLUD:
ppnl();
break;
case CLMARG:
ppnl();
if (profile)
ppid("\t");
break;
case CALIGN:
ppnl();
indent();
break;
case CTRAIL:
ppspac();
break;
case CRMARG:
case CSRMARG:
pptab();
break;
}
}
/*
* One line of a multi-line comment
* Deal with alignment and initial white space trimming.
* The "margin" indicates where the first line of the
* comment began... don't print stuff in this comment
* which came before this.
*/
oneline(margin, cml)
int margin;
struct commline *cml;
{
register char *tp;
register int i;
for (i = 8, tp = cml->cmtext; i < margin && *tp; tp++)
switch (*tp) {
case ' ':
i++;
continue;
case '\t':
i += 8;
i &= ~7;
if (i < margin)
continue;
ppop("\t");
default:
goto out;
}
out:
ppid(tp);
}
/*
* Flush all comments
*/
flushcm()
{
Seqid = 32767;
return(putcm());
}
#define BLANKS ((1 << CNL) | (1 << CNLBL) | (1 << CFORM))
noblank(i)
int i;
{
return ((i & BLANKS) == 0);
}
int needform, neednlbl, neednl, needseqid;
needtree()
{
register struct comment *cp;
needform = neednlbl = neednl = 0;
cp = cmhp;
if (cp == NIL)
return (0);
do {
switch (cp->cmjust) {
case CNL:
neednl++;
goto seq;
case CNLBL:
neednlbl++;
goto seq;
case CFORM:
needform++;
seq:
needseqid = cp->cmseqid;
break;
default:
neednl = neednlbl = needform = 0;
return (1);
}
cp = cp->cmnext;
} while (cp != cmhp);
cmhp = NIL;
return (0);
}
packtree()
{
int save;
save = yyseqid;
yyseqid = needseqid;
for (; needform > 0; needform--)
commform();
for (; neednl > 0; neednl--)
commnl();
for (; neednlbl > 0; neednlbl--)
commnlbl();
yyseqid = save;
}