Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <bio.h>
#include "cb.h"
#include "cbtype.h"

static void
usage(void)
{
        fprint(2, "usage: cb [-sj] [-l width]\n");
        exits("usage");
}

void
main(int argc, char *argv[])
{
        Biobuf stdin, stdout;

        ARGBEGIN{
        case 'j':
                join = 1;
                break;
        case 'l':
                maxleng = atoi(EARGF(usage()));
                maxtabs = maxleng/TABLENG - 2;
                maxleng -= (maxleng + 5)/10;
                break;
        case 's':
                strict = 1;
                break;
        default:
                usage();
        }ARGEND

        Binit(&stdout, 1, OWRITE);
        output = &stdout;
        if (argc <= 0){
                Binit(&stdin, 0, OREAD);
                input = &stdin;
                work();
                Bterm(input);
        } else {
                while (argc-- > 0){
                        if ((input = Bopen(*argv, OREAD)) == 0)
                                sysfatal("can't open input file %s: %r", *argv);
                        work();
                        Bterm(input);
                        argv++;
                }
        }
        exits(0);
}
void
work(void)
{
        int c, cc;
        struct keyw *lptr;
        char *pt;
        int ct;

        while ((c = getch()) != Beof){
                switch (c){
                case '{':
                        if ((lptr = lookup(lastlook,p)) != 0){
                                if (lptr->type == ELSE)gotelse();
                                else if(lptr->type == DO)gotdo();
                                else if(lptr->type == STRUCT)structlev++;
                        }
                        if(++clev >= &ind[CLEVEL-1]){
                                fprint(2,"too many levels of curly brackets\n");
                                clev = &ind[CLEVEL-1];
                        }
                        clev->pdepth = 0;
                        clev->tabs = (clev-1)->tabs;
                        clearif(clev);
                        if(strict && clev->tabs > 0)
                                putspace(' ',NO);
                        putch(c,NO);
                        getnl();
                        if(keyflag == DATADEF){
                                OUT;
                        }
                        else {
                                OUTK;
                        }
                        clev->tabs++;
                        pt = getnext(0);                /* to handle initialized structures */
                        if(*pt == '{'){         /* hide one level of {} */
                                while((c=getch()) != '{')
                                        if(c == Beof)error("{");
                                putch(c,NO);
                                if(strict){
                                        putch(' ',NO);
                                        eatspace();
                                }
                                keyflag = SINIT;
                        }
                        continue;
                case '}':
                        pt = getnext(0);                /* to handle initialized structures */
                        if(*pt == ','){
                                if(strict){
                                        putspace(' ',NO);
                                        eatspace();
                                }
                                putch(c,NO);
                                putch(*pt,NO);
                                *pt = '\0';
                                ct = getnl();
                                pt = getnext(0);
                                if(*pt == '{'){
                                        OUT;
                                        while((cc = getch()) != '{')
                                                if(cc == Beof)error("}");
                                        putch(cc,NO);
                                        if(strict){
                                                putch(' ',NO);
                                                eatspace();
                                        }
                                        getnext(0);
                                        continue;
                                }
                                else if(strict || ct){
                                        OUT;
                                }
                                continue;
                        }
                        else if(keyflag == SINIT && *pt == '}'){
                                if(strict)
                                        putspace(' ',NO);
                                putch(c,NO);
                                getnl();
                                OUT;
                                keyflag = DATADEF;
                                *pt = '\0';
                                pt = getnext(0);
                        }
                        outs(clev->tabs);
                        if(--clev < ind)clev = ind;
                        ptabs(clev->tabs);
                        putch(c,NO);
                        lbegin = 0;
                        lptr=lookup(pt,lastplace+1);
                        c = *pt;
                        if(*pt == ';' || *pt == ','){
                                putch(*pt,NO);
                                *pt = '\0';
                                lastplace=pt;
                        }
                        ct = getnl();
                        if((dolevel && clev->tabs <= dotabs[dolevel]) || (structlev )
                            || (lptr != 0 &&lptr->type == ELSE&& clev->pdepth == 0)){
                                if(c == ';'){
                                        OUTK;
                                }
                                else if(strict || (lptr != 0 && lptr->type == ELSE && ct == 0)){
                                        putspace(' ',NO);
                                        eatspace();
                                }
                                else if(lptr != 0 && lptr->type == ELSE){
                                        OUTK;
                                }
                                if(structlev){
                                        structlev--;
                                        keyflag = DATADEF;
                                }
                        }
                        else {
                                OUTK;
                                if(strict && clev->tabs == 0){
                                        if((c=getch()) != '\n'){
                                                Bputc(output, '\n');
                                                Bputc(output, '\n');
                                                unget(c);
                                        }
                                        else {
                                                lineno++;
                                                Bputc(output, '\n');
                                                if((c=getch()) != '\n')unget(c);
                                                else lineno++;
                                                Bputc(output, '\n');
                                        }
                                }
                        }
                        if(lptr != 0 && lptr->type == ELSE && clev->pdepth != 0){
                                UNBUMP;
                        }
                        if(lptr == 0 || lptr->type != ELSE){
                                clev->iflev = 0;
                                if(dolevel && docurly[dolevel] == NO && clev->tabs == dotabs[dolevel]+1)
                                        clev->tabs--;
                                else if(clev->pdepth != 0){
                                        UNBUMP;
                                }
                        }
                        continue;
                case '(':
                        paren++;
                        if ((lptr = lookup(lastlook,p)) != 0){
                                if(!(lptr->type == TYPE || lptr->type == STRUCT))keyflag=KEYWORD;
                                if (strict){
                                        putspace(lptr->punc,NO);
                                        opflag = 1;
                                }
                                putch(c,NO);
                                if (lptr->type == IF)gotif();
                        }
                        else {
                                putch(c,NO);
                                lastlook = p;
                                opflag = 1;
                        }
                        continue;
                case ')':
                        if(--paren < 0)paren = 0;
                        putch(c,NO);
                        if((lptr = lookup(lastlook,p)) != 0){
                                if(lptr->type == TYPE || lptr->type == STRUCT)
                                        opflag = 1;
                        }
                        else if(keyflag == DATADEF)opflag = 1;
                        else opflag = 0;
                        outs(clev->tabs);
                        pt = getnext(1);
                        if ((ct = getnl()) == 1 && !strict){
                                if(dolevel && clev->tabs <= dotabs[dolevel])
                                        resetdo();
                                if(clev->tabs > 0 && (paren != 0 || keyflag == 0)){
                                        if(join){
                                                eatspace();
                                                putch(' ',YES);
                                                continue;
                                        } else {
                                                OUT;
                                                split = 1;
                                                continue;
                                        }
                                }
                                else if(clev->tabs > 0 && *pt != '{'){
                                        BUMP;
                                }
                                OUTK;
                        }
                        else if(strict){
                                if(clev->tabs == 0){
                                        if(*pt != ';' && *pt != ',' && *pt != '(' && *pt != '['){
                                                OUTK;
                                        }
                                }
                                else {
                                        if(keyflag == KEYWORD && paren == 0){
                                                if(dolevel && clev->tabs <= dotabs[dolevel]){
                                                        resetdo();
                                                        eatspace();
                                                        continue;
                                                }
                                                if(*pt != '{'){
                                                        BUMP;
                                                        OUTK;
                                                }
                                                else {
                                                        *pt='\0';
                                                        eatspace();
                                                        unget('{');
                                                }
                                        }
                                        else if(ct){
                                                if(paren){
                                                        if(join){
                                                                eatspace();
                                                        } else {
                                                                split = 1;
                                                                OUT;
                                                        }
                                                }
                                                else {
                                                        OUTK;
                                                }
                                        }
                                }
                        }
                        else if(dolevel && clev->tabs <= dotabs[dolevel])
                                resetdo();
                        continue;
                case ' ':
                case '\t':
                        if ((lptr = lookup(lastlook,p)) != 0){
                                if(!(lptr->type==TYPE||lptr->type==STRUCT))
                                        keyflag = KEYWORD;
                                else if(paren == 0)keyflag = DATADEF;
                                if(strict){
                                        if(lptr->type != ELSE){
                                                if(lptr->type == TYPE){
                                                        if(paren != 0)putch(' ',YES);
                                                }
                                                else
                                                        putch(lptr->punc,NO);
                                                eatspace();
                                        }
                                }
                                else putch(c,YES);
                                switch(lptr->type){
                                case CASE:
                                        outs(clev->tabs-1);
                                        continue;
                                case ELSE:
                                        pt = getnext(1);
                                        eatspace();
                                        if((cc = getch()) == '\n' && !strict){
                                                unget(cc);
                                        }
                                        else {
                                                unget(cc);
                                                if(checkif(pt))continue;
                                        }
                                        gotelse();
                                        if(strict) unget(c);
                                        if(getnl() == 1 && !strict){
                                                OUTK;
                                                if(*pt != '{'){
                                                        BUMP;
                                                }
                                        }
                                        else if(strict){
                                                if(*pt != '{'){
                                                        OUTK;
                                                        BUMP;
                                                }
                                        }
                                        continue;
                                case IF:
                                        gotif();
                                        continue;
                                case DO:
                                        gotdo();
                                        pt = getnext(1);
                                        if(*pt != '{'){
                                                eatallsp();
                                                OUTK;
                                                docurly[dolevel] = NO;
                                                dopdepth[dolevel] = clev->pdepth;
                                                clev->pdepth = 0;
                                                clev->tabs++;
                                        }
                                        continue;
                                case TYPE:
                                        if(paren)continue;
                                        if(!strict)continue;
                                        gottype(lptr);
                                        continue;
                                case STRUCT:
                                        gotstruct();
                                        continue;
                                }
                        }
                        else if (lbegin == 0 || p > string) 
                                if(strict)
                                        putch(c,NO);
                                else putch(c,YES);
                        continue;
                case ';':
                        putch(c,NO);
                        if(paren != 0){
                                if(strict){
                                        putch(' ',YES);
                                        eatspace();
                                }
                                opflag = 1;
                                continue;
                        }
                        outs(clev->tabs);
                        pt = getnext(0);
                        lptr=lookup(pt,lastplace+1);
                        if(lptr == 0 || lptr->type != ELSE){
                                clev->iflev = 0;
                                if(clev->pdepth != 0){
                                        UNBUMP;
                                }
                                if(dolevel && docurly[dolevel] == NO && clev->tabs <= dotabs[dolevel]+1)
                                        clev->tabs--;
/*
                                else if(clev->pdepth != 0){
                                        UNBUMP;
                                }
*/
                        }
                        getnl();
                        OUTK;
                        continue;
                case '\n':
                        if ((lptr = lookup(lastlook,p)) != 0){
                                pt = getnext(1);
                                if (lptr->type == ELSE){
                                        if(strict)
                                                if(checkif(pt))continue;
                                        gotelse();
                                        OUTK;
                                        if(*pt != '{'){
                                                BUMP;
                                        }
                                }
                                else if(lptr->type == DO){
                                        OUTK;
                                        gotdo();
                                        if(*pt != '{'){
                                                docurly[dolevel] = NO;
                                                dopdepth[dolevel] = clev->pdepth;
                                                clev->pdepth = 0;
                                                clev->tabs++;
                                        }
                                }
                                else {
                                        OUTK;
                                        if(lptr->type == STRUCT)gotstruct();
                                }
                        }
                        else if(p == string)Bputc(output, '\n');
                        else {
                                if(clev->tabs > 0 &&(paren != 0 || keyflag == 0)){
                                        if(join){
                                                putch(' ',YES);
                                                eatspace();
                                                continue;
                                        } else {
                                                OUT;
                                                split = 1;
                                                continue;
                                        }
                                }
                                else if(keyflag == KEYWORD){
                                        OUTK;
                                        continue;
                                }
                                OUT;
                        }
                        continue;
                case '"':
                case '\'':
                        putch(c,NO);
                        while ((cc = getch()) != c){
                                if(cc == Beof)
                                        error("\" or '");
                                putch(cc,NO);
                                if (cc == '\\'){
                                        putch(getch(),NO);
                                }
                                if (cc == '\n'){
                                        outs(clev->tabs);
                                        lbegin = 1;
                                        count = 0;
                                }
                        }
                        putch(cc,NO);
                        opflag=0;
                        if (getnl() == 1){
                                unget('\n');
                        }
                        continue;
                case '\\':
                        putch(c,NO);
                        putch(getch(),NO);
                        continue;
                case '?':
                        question = 1;
                        gotop(c);
                        continue;
                case ':':
                        if ((cc = getch()) == ':') {
                                putch(c,NO);
                                putch(cc,NO);
                                continue;
                        }
                        unget(cc);
                        if (question == 1){
                                question = 0;
                                gotop(c);
                                continue;
                        }
                        putch(c,NO);
                        if(structlev)continue;
                        if ((lptr = lookup(lastlook,p)) != 0){
                                if (lptr->type == CASE)outs(clev->tabs - 1);
                        }
                        else {
                                lbegin = 0;
                                outs(clev->tabs);
                        }
                        getnl();
                        OUTK;
                        continue;
                case '/':
                        if ((cc = getch()) == '/') {
                                putch(c,NO);
                                putch(cc,NO);
                                cpp_comment(YES);
                                OUT;
                                lastlook = 0;
                                continue;
                        }
                        else if (cc != '*') {
                                unget(cc);
                                gotop(c);
                                continue;
                        }
                        putch(c,NO);
                        putch(cc,NO);
                        cc = comment(YES);
                        if(getnl() == 1){
                                if(cc == 0){
                                        OUT;
                                }
                                else {
                                        outs(0);
                                        Bputc(output, '\n');
                                        lbegin = 1;
                                        count = 0;
                                }
                                lastlook = 0;
                        }
                        continue;
                case '[':
                        putch(c,NO);
                        ct = 0;
                        while((c = getch()) != ']' || ct > 0){
                                if(c == Beof)error("]");
                                putch(c,NO);
                                if(c == '[')ct++;
                                if(c == ']')ct--;
                        }
                        putch(c,NO);
                        continue;
                case '#':
                        putch(c,NO);
                        while ((cc = getch()) != '\n'){
                                if(cc == Beof)error("newline");
                                if (cc == '\\'){
                                        putch(cc,NO);
                                        cc = getch();
                                }
                                putch(cc,NO);
                        }
                        putch(cc,NO);
                        lbegin = 0;
                        outs(clev->tabs);
                        lbegin = 1;
                        count = 0;
                        continue;
                default:
                        if (c == ','){
                                opflag = 1;
                                putch(c,YES);
                                if (strict){
                                        if ((cc = getch()) != ' ')unget(cc);
                                        if(cc != '\n')putch(' ',YES);
                                }
                        }
                        else if(isop(c))gotop(c);
                        else {
                                if(isalnum(c) && lastlook == 0)lastlook = p;
                                if(isdigit(c)){
                                        putch(c,NO);
                                        while(isdigit(c=Bgetc(input))||c == '.')putch(c,NO);
                                        if(c == 'e'){
                                                putch(c,NO);
                                                c = Bgetc(input);
                                                putch(c, NO);
                                                while(isdigit(c=Bgetc(input)))putch(c,NO);
                                        }
                                        Bungetc(input);
                                }
                                else putch(c,NO);
                                if(keyflag != DATADEF)opflag = 0;
                        }
                }
        }
}
void
gotif(void){
        outs(clev->tabs);
        if(++clev->iflev >= IFLEVEL-1){
                fprint(2,"too many levels of if %d\n",clev->iflev );
                clev->iflev = IFLEVEL-1;
        }
        clev->ifc[clev->iflev] = clev->tabs;
        clev->spdepth[clev->iflev] = clev->pdepth;
}
void
gotelse(void){
        clev->tabs = clev->ifc[clev->iflev];
        clev->pdepth = clev->spdepth[clev->iflev];
        if(--(clev->iflev) < 0)clev->iflev = 0;
}
int
checkif(char *pt)
{
        struct keyw *lptr;
        int cc;
        if((lptr=lookup(pt,lastplace+1))!= 0){
                if(lptr->type == IF){
                        if(strict)putch(' ',YES);
                        copy(lptr->name);
                        *pt='\0';
                        lastplace = pt;
                        if(strict){
                                putch(lptr->punc,NO);
                                eatallsp();
                        }
                        clev->tabs = clev->ifc[clev->iflev];
                        clev->pdepth = clev->spdepth[clev->iflev];
                        keyflag = KEYWORD;
                        return(1);
                }
        }
        return(0);
}
void
gotdo(void){
        if(++dolevel >= DOLEVEL-1){
                fprint(2,"too many levels of do %d\n",dolevel);
                dolevel = DOLEVEL-1;
        }
        dotabs[dolevel] = clev->tabs;
        docurly[dolevel] = YES;
}
void
resetdo(void){
        if(docurly[dolevel] == NO)
                clev->pdepth = dopdepth[dolevel];
        if(--dolevel < 0)dolevel = 0;
}
void
gottype(struct keyw *lptr)
{
        char *pt;
        struct keyw *tlptr;
        int c;
        while(1){
                pt = getnext(1);
                if((tlptr=lookup(pt,lastplace+1))!=0){
                        putch(' ',YES);
                        copy(tlptr->name);
                        *pt='\0';
                        lastplace = pt;
                        if(tlptr->type == STRUCT){
                                putch(tlptr->punc,YES);
                                gotstruct();
                                break;
                        }
                        lptr=tlptr;
                        continue;
                }
                else{
                        putch(lptr->punc,NO);
                        while((c=getch())== ' ' || c == '\t');
                        unget(c);
                        break;
                }
        }
}
void
gotstruct(void){
        int c;
        int cc;
        char *pt;
        while((c=getch()) == ' ' || c == '\t')
                if(!strict)putch(c,NO);
        if(c == '{'){
                structlev++;
                unget(c);
                return;
        }
        if(isalpha(c)){
                putch(c,NO);
                while(isalnum(c=getch()))putch(c,NO);
        }
        unget(c);
        pt = getnext(1);
        if(*pt == '{')structlev++;
        if(strict){
                eatallsp();
                putch(' ',NO);
        }
}
void
gotop(int c)
{
        char optmp[OPLENGTH];
        char *op_ptr;
        struct op *s_op;
        char *a, *b;
        op_ptr = optmp;
        *op_ptr++ = c;
        while (isop(( *op_ptr = getch())))op_ptr++;
        if(!strict)unget(*op_ptr);
        else if (*op_ptr != ' ')unget( *op_ptr);
        *op_ptr = '\0';
        s_op = op;
        b = optmp;
        while ((a = s_op->name) != 0){
                op_ptr = b;
                while ((*op_ptr == *a) && (*op_ptr != '\0')){
                        a++;
                        op_ptr++;
                }
                if (*a == '\0'){
                        keep(s_op);
                        opflag = s_op->setop;
                        if (*op_ptr != '\0'){
                                b = op_ptr;
                                s_op = op;
                                continue;
                        }
                        else break;
                }
                else s_op++;
        }
}
void
keep(struct op *o)
{
        char    *s;
        int ok;
        if(o->blanks == NEVER)ok = NO;
        else ok = YES;
        if (strict && ((o->blanks & ALWAYS)
            || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0)))
                putspace(' ',YES);
        for(s=o->name; *s != '\0'; s++){
                if(*(s+1) == '\0')putch(*s,ok);
                else
                        putch(*s,NO);
        }
        if (strict && ((o->blanks & ALWAYS)
            || ((opflag == 0 && o->blanks & SOMETIMES) && clev->tabs != 0))) putch(' ',YES);
}
int
getnl(void){
        int ch;
        char *savp;
        int gotcmt;
        gotcmt = 0;
        savp = p;
        while ((ch = getch()) == '\t' || ch == ' ')putch(ch,NO);
        if (ch == '/'){
                if ((ch = getch()) == '*'){
                        putch('/',NO);
                        putch('*',NO);
                        comment(NO);
                        ch = getch();
                        gotcmt=1;
                }
                else if (ch == '/') {
                        putch('/',NO);
                        putch('/',NO);
                        cpp_comment(NO);
                        ch = getch();
                        gotcmt = 1;
                }
                else {
                        if(inswitch)*(++lastplace) = ch;
                        else {
                                inswitch = 1;
                                *lastplace = ch;
                        }
                        unget('/');
                        return(0);
                }
        }
        if(ch == '\n'){
                if(gotcmt == 0)p=savp;
                return(1);
        }
        unget(ch);
        return(0);
}
void
ptabs(int n){
        int     i;
        int num;
        if(n > maxtabs){
                if(!folded){
                        Bprint(output, "/* code folded from here */\n");
                        folded = 1;
                }
                num = n-maxtabs;
        }
        else {
                num = n;
                if(folded){
                        folded = 0;
                        Bprint(output, "/* unfolding */\n");
                }
        }
        for (i = 0; i < num; i++)Bputc(output, '\t');
}
void
outs(int n){
        if (p > string){
                if (lbegin){
                        ptabs(n);
                        lbegin = 0;
                        if (split == 1){
                                split = 0;
                                if (clev->tabs > 0)Bprint(output, "\t");
                        }
                }
                *p = '\0';
                Bprint(output, "%s", string);
                lastlook = p = string;
        }
        else {
                if (lbegin != 0){
                        lbegin = 0;
                        split = 0;
                }
        }
}
void
putch(char c,int ok)
{
        int cc;
        if(p < &string[LINE-1]){
                if(count+TABLENG*clev->tabs >= maxleng && ok && !folded){
                        if(c != ' ')*p++ = c;
                        OUT;
                        split = 1;
                        if((cc=getch()) != '\n')unget(cc);
                }
                else {
                        *p++ = c;
                        count++;
                }
        }
        else {
                outs(clev->tabs);
                *p++ = c;
                count = 0;
        }
}
struct keyw *
lookup(char *first, char *last)
{
        struct keyw *ptr;
        char    *cptr, *ckey, *k;

        if(first == last || first == 0)return(0);
        cptr = first;
        while (*cptr == ' ' || *cptr == '\t')cptr++;
        if(cptr >= last)return(0);
        ptr = key;
        while ((ckey = ptr->name) != 0){
                for (k = cptr; (*ckey == *k && *ckey != '\0'); k++, ckey++);
                if(*ckey=='\0' && (k==last|| (k<last && !isalnum(*k)))){
                        opflag = 1;
                        lastlook = 0;
                        return(ptr);
                }
                ptr++;
        }
        return(0);
}
int
comment(int ok)
{
        int ch;
        int hitnl;

        hitnl = 0;
        while ((ch  = getch()) != Beof){
                putch(ch, NO);
                if (ch == '*'){
gotstar:
                        if ((ch  = getch()) == '/'){
                                putch(ch,NO);
                                return(hitnl);
                        }
                        putch(ch,NO);
                        if (ch == '*')goto gotstar;
                }
                if (ch == '\n'){
                        if(ok && !hitnl){
                                outs(clev->tabs);
                        }
                        else {
                                outs(0);
                        }
                        lbegin = 1;
                        count = 0;
                        hitnl = 1;
                }
        }
        return(hitnl);
}
int
cpp_comment(int ok)
{
        int ch;
        int hitnl;

        hitnl = 0;
        while ((ch = getch()) != -1) {
                if (ch == '\n') {
                        if (ok && !hitnl)
                                outs(clev->tabs);
                        else
                                outs(0);
                        lbegin = 1;
                        count = 0;
                        hitnl = 1;
                        break;
                }
                putch(ch, NO);
        }
        return hitnl;
}
void
putspace(char ch, int ok)
{
        if(p == string)putch(ch,ok);
        else if (*(p - 1) != ch) putch(ch,ok);
}
int
getch(void){
        char c;
        if(inswitch){
                if(next != '\0'){
                        c=next;
                        next = '\0';
                        return(c);
                }
                if(tptr <= lastplace){
                        if(*tptr != '\0')return(*tptr++);
                        else if(++tptr <= lastplace)return(*tptr++);
                }
                inswitch=0;
                lastplace = tptr = temp;
        }
        return(Bgetc(input));
}
void
unget(char c)
{
        if(inswitch){
                if(tptr != temp)
                        *(--tptr) = c;
                else next = c;
        }
        else Bungetc(input);
}
char *
getnext(int must){
        int c;
        char *beg;
        int prect,nlct;
        prect = nlct = 0;
        if(tptr > lastplace){
                tptr = lastplace = temp;
                err = 0;
                inswitch = 0;
        }
        tp = lastplace;
        if(inswitch && tptr <= lastplace)
                if (isalnum(*lastplace)||ispunct(*lastplace)||isop(*lastplace))return(lastplace);
space:
        while(isspace(c=Bgetc(input)))puttmp(c,1);
        beg = tp;
        puttmp(c,1);
        if(c == '/'){
                if(puttmp(Bgetc(input),1) == '*'){
cont:
                        while((c=Bgetc(input)) != '*'){
                                puttmp(c,0);
                                if(must == 0 && c == '\n')
                                        if(nlct++ > 2)goto done;
                        }
                        puttmp(c,1);
        star:
                        if(puttmp((c=Bgetc(input)),1) == '/'){
                                beg = tp;
                                puttmp((c=Bgetc(input)),1);
                        }
                        else if(c == '*')goto star;
                        else goto cont;
                }
                else goto done;
        }
        if(isspace(c))goto space;
        if(c == '#' && tp > temp+1 && *(tp-2) == '\n'){
                if(prect++ > 2)goto done;
                while(puttmp((c=Bgetc(input)),1) != '\n')
                        if(c == '\\')puttmp(Bgetc(input),1);
                goto space;
        }
        if(isalnum(c)){
                while(isalnum(c = Bgetc(input)))puttmp(c,1);
                Bungetc(input);
        }
done:
        puttmp('\0',1);
        lastplace = tp-1;
        inswitch = 1;
        return(beg);
}
void
copy(char *s)
{
        while(*s != '\0')putch(*s++,NO);
}
void
clearif(struct indent *cl)
{
        int i;
        for(i=0;i<IFLEVEL-1;i++)cl->ifc[i] = 0;
}
char 
puttmp(char c, int keep)
{
        if(tp < &temp[TEMP-120])
                *tp++ = c;
        else {
                if(keep){
                        if(tp >= &temp[TEMP-1]){
                                fprint(2,"can't look past huge comment - quiting\n");
                                exits("boom");
                        }
                        *tp++ = c;
                }
                else if(err == 0){
                        err++;
                        fprint(2,"truncating long comment\n");
                }
        }
        return(c);
}
void
error(char *s)
{
        fprint(2,"saw EOF while looking for %s\n",s);
        exits("boom");
}