Annotation of 43BSD/contrib/B/src/bed/edit.c, revision 1.1

1.1     ! root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
        !             2: static char rcsid[] = "$Header: edit.c,v 2.5 85/08/22 16:01:43 timo Exp $";
        !             3: 
        !             4: /*
        !             5:  * B editor -- Read unit from file.
        !             6:  */
        !             7: 
        !             8: #include <ctype.h>
        !             9: 
        !            10: #include "b.h"
        !            11: #include "feat.h"
        !            12: #include "erro.h"
        !            13: #include "bobj.h"
        !            14: #include "node.h"
        !            15: #include "tabl.h"
        !            16: #include "gram.h"
        !            17: #include "supr.h"
        !            18: #include "queu.h"
        !            19: 
        !            20: string unixerror();
        !            21: 
        !            22: /*
        !            23:  * TABSIZE sets the number of spaces equivalent to a tab character
        !            24:  * read from the input; INDENT sets the number of spaces for one indentation
        !            25:  * level.
        !            26:  * The definitions here are unrelated to the definition of TABS
        !            27:  * in eval.h (used by show.c and eval.c).  The definition here only
        !            28:  * defines how many spaces must be equivalenced to a tab stop when read
        !            29:  * from a file; tab stops must be caused by editing a unit with another
        !            30:  * editor (vi, ed, ex, emacs), since "save.c" always writes spaces,
        !            31:  * not tabs.  The value '4' is best suited for people at the CWI who
        !            32:  * may have workspaces with units edited with the previous version of
        !            33:  * the B editor, which emitted a tab for each indentation level (and
        !            34:  * assumed 4 spaces for a tab stop on input).
        !            35:  *
        !            36:  * The variables 'spacesused' and 'tabsused' are kept to see if mixed use
        !            37:  * of spaces and tabs was made; this can cause indentation errors.
        !            38:  */
        !            39: 
        !            40: #ifdef CWI
        !            41: #define TABSIZE 4
        !            42: #else
        !            43: #define TABSIZE 8
        !            44: #endif
        !            45: 
        !            46: #define INDENT 4
        !            47: 
        !            48: Hidden bool spacesused;
        !            49: Hidden bool tabsused;
        !            50: 
        !            51: 
        !            52: /*
        !            53:  * Read (edit) parse tree from file into the focus.
        !            54:  * Rather ad hoc, we use ins_string for each line
        !            55:  * and do some magic tricks to get the indentation right
        !            56:  * (most of the time).
        !            57:  * If line > 0, position the focus at that line, if possible;
        !            58:  * otherwise the focus is left at the end of the inserted text.
        !            59:  */
        !            60: 
        !            61: Visible bool
        !            62: edit(ep, filename, line)
        !            63:        register environ *ep;
        !            64:        string filename;
        !            65:        int line;
        !            66: {
        !            67:        int lines = 0;
        !            68:        register FILE *fp = fopen(filename, "r");
        !            69:        register int c;
        !            70:        char buf[BUFSIZ];
        !            71:        auto string cp;
        !            72:        auto queue q = Qnil;
        !            73: 
        !            74:        if (!fp) {
        !            75:                error("%s", unixerror(filename));
        !            76:                return No;
        !            77:        }
        !            78: 
        !            79:        spacesused = tabsused = No;
        !            80:        do {
        !            81:                do {
        !            82:                        for (cp = buf; cp < buf + sizeof buf - 1; ++cp) {
        !            83:                                c = getc(fp);
        !            84:                                if (c == EOF || c == '\n')
        !            85:                                        break;
        !            86:                                if (c < ' ' || c >= 0177)
        !            87:                                        c = ' ';
        !            88:                                *cp = c;
        !            89:                        }
        !            90:                        if (cp > buf) {
        !            91:                                *cp = 0;
        !            92:                                if (!ins_string(ep, buf, &q, 0) || !emptyqueue(q)) {
        !            93:                                        qrelease(q);
        !            94:                                        error(EDIT_BAD);
        !            95:                                        fclose(fp);
        !            96:                                        return No;
        !            97:                                }
        !            98:                                qrelease(q);
        !            99:                        }
        !           100:                } while (c != EOF && c != '\n');
        !           101:                ++lines;
        !           102:                if (c != EOF && !editindentation(ep, fp)) {
        !           103:                        fclose(fp);
        !           104:                        return No;
        !           105:                }
        !           106:        } while (c != EOF);
        !           107:        fclose(fp);
        !           108:        if (ep->mode == FHOLE || ep->mode == VHOLE && (ep->s1&1)) {
        !           109:                cp = "";
        !           110:                soften(ep, &cp, 0);
        !           111:        }
        !           112:        if (lines > 1 && line > 0) {
        !           113:                gotoyx(ep, line-1, 0);
        !           114:                oneline(ep);
        !           115:        }
        !           116:        if (spacesused && tabsused)
        !           117:                error(EDIT_TABS);
        !           118:        return Yes;
        !           119: }
        !           120: 
        !           121: 
        !           122: /*
        !           123:  * Do all the footwork required to get the indentation proper.
        !           124:  */
        !           125: 
        !           126: Hidden Procedure
        !           127: editindentation(ep, fp)
        !           128:        register environ *ep;
        !           129:        register FILE *fp;
        !           130: {
        !           131:        register int tabs = 0;
        !           132:        auto int level;
        !           133:        register int c;
        !           134: 
        !           135:        while ((c = getc(fp)) == ' ' || c == '\t') {
        !           136:                if (c == ' ') {
        !           137:                        spacesused = Yes;
        !           138:                        ++tabs;
        !           139:                }
        !           140:                else {
        !           141:                        tabsused = Yes;
        !           142:                        tabs = (tabs/TABSIZE + 1)*TABSIZE;
        !           143:                }
        !           144:        }
        !           145:        ungetc(c, fp);
        !           146:        if (c == EOF || c == '\n')
        !           147:                return Yes;
        !           148:        tabs = (tabs+(INDENT/2))/INDENT; /* Transform to tab stops */
        !           149:        if (!ins_newline(ep)) {
        !           150: #ifndef NDEBUG
        !           151:                debug("[Burp! Can't insert a newline.]");
        !           152: #endif NDEBUG
        !           153:                return No;
        !           154:        }
        !           155:        level = Level(ep->focus);
        !           156:        for (; tabs < level; --level) {
        !           157:                if (!ins_newline(ep)) {
        !           158: #ifndef NDEBUG
        !           159:                        debug("[Burp, burp! Can't decrease indentation.]");
        !           160: #endif NDEBUG
        !           161:                        return No;
        !           162:                }
        !           163:        }
        !           164:        fixit(ep);
        !           165:        return Yes;
        !           166: }
        !           167: 
        !           168: 
        !           169: /* ------------------------------------------------------------ */
        !           170: 
        !           171: #ifdef SAVEBUF
        !           172: 
        !           173: /*
        !           174:  * Read the next non-space character.
        !           175:  */
        !           176: 
        !           177: Hidden int
        !           178: skipsp(fp)
        !           179:        register FILE *fp;
        !           180: {
        !           181:        register int c;
        !           182: 
        !           183:        do {
        !           184:                c = getc(fp);
        !           185:        } while (c == ' ');
        !           186:        return c;
        !           187: }
        !           188: 
        !           189: 
        !           190: /*
        !           191:  * Read a text in standard B format when the initial quote has already
        !           192:  * been read.
        !           193:  */
        !           194: 
        !           195: Hidden value
        !           196: readtext(fp, quote)
        !           197:        register FILE *fp;
        !           198:        register char quote;
        !           199: {
        !           200:        auto value v = Vnil;
        !           201:        char buf[BUFSIZ];
        !           202:        register string cp = buf;
        !           203:        register int c;
        !           204:        auto int i;
        !           205: 
        !           206:        for (; ; ++cp) {
        !           207:                c = getc(fp);
        !           208:                if (!isascii(c) || c != ' ' && !isprint(c)) {
        !           209:                        if (c == EOF)
        !           210:                                debug("readtext: EOF");
        !           211:                        else
        !           212:                                debug("readtext: bad char (0%02o)", c);
        !           213:                        release(v);
        !           214:                        return Vnil; /* Bad character or EOF */
        !           215:                }
        !           216:                if (c == quote) {
        !           217:                        c = getc(fp);
        !           218:                        if (c != quote) {
        !           219:                                ungetc(c, fp);
        !           220:                                break;
        !           221:                        }
        !           222:                }
        !           223:                else if (c == '`') {
        !           224:                        c = skipsp(fp);
        !           225:                        if (c == '$') {
        !           226:                                i = 0;
        !           227:                                if (fscanf(fp, "%d", &i) != 1
        !           228:                                        || i == 0 || !isascii(i)) {
        !           229:                                        debug("readtext: error in conversion");
        !           230:                                        release(v);
        !           231:                                        return Vnil;
        !           232:                                }
        !           233:                                c = skipsp(fp);
        !           234:                        }
        !           235:                        else
        !           236:                                i = '`';
        !           237:                        if (c != '`') {
        !           238:                                if (c == EOF)
        !           239:                                        debug("readtext: EOF in conversion");
        !           240:                                else
        !           241:                                        debug("readtext: bad char in conversion (0%o)", c);
        !           242:                                release(v);
        !           243:                                return Vnil;
        !           244:                        }
        !           245:                        c = i;
        !           246:                }
        !           247:                if (cp >= &buf[sizeof buf - 1]) {
        !           248:                        *cp = 0;
        !           249:                        if (v)
        !           250:                                concato(&v, buf);
        !           251:                        else
        !           252:                                v = mk_text(buf);
        !           253:                        cp = buf;
        !           254:                }
        !           255:                *cp = c;
        !           256:        }
        !           257:        *cp = 0;
        !           258:        if (!v)
        !           259:                return mk_text(buf);
        !           260:        concato(&v, buf);
        !           261:        return v;
        !           262: }
        !           263: 
        !           264: 
        !           265: Hidden int
        !           266: readsym(fp)
        !           267:        register FILE *fp;
        !           268: {
        !           269:        register int c;
        !           270:        char buf[100];
        !           271:        register string bufp;
        !           272: 
        !           273:        for (bufp = buf; ; ++bufp) {
        !           274:                c = getc(fp);
        !           275:                if (c == EOF)
        !           276:                        return -1;
        !           277:                if (!isascii(c) || !isalnum(c) && c != '_') {
        !           278:                        if (ungetc(c, fp) == EOF)
        !           279:                                syserr("readsym: ungetc failed");
        !           280:                        break;
        !           281:                }
        !           282:                *bufp = c;
        !           283:        }
        !           284:        *bufp = 0;
        !           285:        if (isdigit(buf[0]))
        !           286:                return atoi(buf);
        !           287:        if (strcmp(buf, "Required") == 0) /***** Compatibility hack *****/
        !           288:                return Hole;
        !           289:        return nametosym(buf);
        !           290: }
        !           291: 
        !           292: 
        !           293: /*
        !           294:  * Read a node in internal format (recursively).
        !           295:  * Return nil pointer if EOF or error.
        !           296:  */
        !           297: 
        !           298: Hidden node
        !           299: readnode(fp)
        !           300:        FILE *fp;
        !           301: {
        !           302:        int c;
        !           303:        int nch;
        !           304:        node ch[MAXCHILD];
        !           305:        node n;
        !           306:        int sym;
        !           307: 
        !           308:        c = skipsp(fp);
        !           309:        switch (c) {
        !           310:        case EOF:
        !           311:                return Nnil; /* EOF hit */
        !           312: 
        !           313:        case '(':
        !           314:                sym = readsym(fp);
        !           315:                if (sym < 0) {
        !           316:                        debug("readnode: missing symbol");
        !           317:                        return Nnil; /* No number as first item */
        !           318:                }
        !           319:                if (sym < 0 || sym > Hole) {
        !           320:                        debug("readnode: bad symbol (%d)", sym);
        !           321:                        return Nnil;
        !           322:                }
        !           323:                nch = 0;
        !           324:                while ((c = skipsp(fp)) == ',' && nch < MAXCHILD) {
        !           325:                        n = readnode(fp);
        !           326:                        if (!n) {
        !           327:                                for (; nch > 0; --nch)
        !           328:                                        noderelease(ch[nch-1]);
        !           329:                                return Nnil; /* Error encountered in child */
        !           330:                        }
        !           331:                        ch[nch] = n;
        !           332:                        ++nch;
        !           333:                }
        !           334:                if (c != ')') {
        !           335:                        if (c == ',')
        !           336:                                debug("readnode: node too long (sym=%d)", sym);
        !           337:                        else
        !           338:                                debug("readnode: no ')' where expected (sym=%d)", sym);
        !           339:                        for (; nch > 0; --nch)
        !           340:                                noderelease(ch[nch-1]);
        !           341:                        return Nnil; /* Not terminated with ')' or too many children */
        !           342:                }
        !           343:                if (nch == 0)
        !           344:                        return gram(sym); /* Saves space for Optional/Hole nodes */
        !           345:                return newnode(nch, sym, ch);
        !           346: 
        !           347:        case '\'':
        !           348:        case '"':
        !           349:                return (node) readtext(fp, c);
        !           350: 
        !           351:        default:
        !           352:                debug("readnode: bad initial character");
        !           353:                return Nnil; /* Bad initial character */
        !           354:        }
        !           355: }
        !           356: 
        !           357: 
        !           358: /*
        !           359:  * Read a node written in a more or less internal format.
        !           360:  */
        !           361: 
        !           362: Visible value
        !           363: editqueue(filename)
        !           364:        string filename;
        !           365: {
        !           366:        register FILE *fp = fopen(filename, "r");
        !           367:        auto queue q = Qnil;
        !           368:        register node n;
        !           369: 
        !           370:        if (!fp)
        !           371:                return Vnil;
        !           372:        do {
        !           373:                n = readnode(fp);
        !           374:                if (!n)
        !           375:                        break; /* EOF or error */
        !           376:                addtoqueue(&q, n);
        !           377:                noderelease(n);
        !           378:        } while (skipsp(fp) == '\n');
        !           379:        fclose(fp);
        !           380:        return (value)q;
        !           381: }
        !           382: #endif SAVEBUF

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.