Annotation of 43BSD/contrib/B/src/bed/edit.c, revision 1.1.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.