# 2.11BSD#431 - /usr/src/new/PORT/B/src/bed/edit.c

##### Functions

    edit              X
    editindentation   X
    editqueue         X
    readnode          X
    readsym           X
    readtext          X
    skipsp            X

##### Variables

    spacesused        X
    tabsused          X

##### Macros

    INDENT            X
    TABSIZE           X

       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

#### Defined functions

edit defined in line 61; used 1 times

- in /usr/src/new/PORT/B/src/bed/demo.c line 241

editindentation defined in line 126; used 1 times

- in line 102

editqueue defined in line 362; used 3 times

- in /usr/src/new/PORT/B/src/bed/demo.c line 28, 76, 192

readnode defined in line 298; used 2 times

- in line 325, 373

readsym defined in line 265; used 1 times

- in line 314

readtext defined in line 195; used 1 times

- in line 349

skipsp defined in line 177; used 5 times

- in line 224, 233, 308, 324, 378

#### Defined variables

rcsid defined in line 2; never used
spacesused defined in line 48; used 3 times

- in line 79, 116, 137

tabsused defined in line 49; used 3 times

- in line 79, 116, 141

#### Defined macros

INDENT defined in line 46; used 2 times

- in line 148(2)

TABSIZE defined in line 43; used 2 times

- in line 142(2)

Last modified: 1985-08-27 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1064 |