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

##### Functions

    disrupt           X
    exec_b            X
    expect            X
    ffgetc            X
    ffgets            X
    getdevices        X
    intrchild         X
    makechild         X
    sleur             X
    start_b           X
    termchild         X
    waitchild         X

##### Variables

    Procedure         X
    Visible           X
    canjump           X
    fdown             X
    fup               X
    interpreter       X
    interrupted       X
    jumpback          X
    npushback         X
    pid               X
    pushback          X

##### Macros

    ESCAPE            X
    INTERPRETER       X
    INTRCHILD         X
    INTRMSG           X
    Moreinput         X
    RESYNC            X
    TABS              X

       1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
       2: static char rcsid[] = "$Header: comm.c,v 2.4 85/08/22 16:00:49 timo Exp $";
       3:
       4: /*
       5:  * B editor -- Communication with B interpreter.
       6:  */
       7:
       8: #include "feat.h"
       9: #ifdef BTOP
      10:
      11: #include <signal.h>
      12: #include <setjmp.h>
      13: #include <ctype.h>
      14:
      15: #include "b.h"
      16: #include "node.h"
      17: #include "supr.h"
      18: #include "unix.h"
      19: #include "cell.h" /* For winheight */
      20:
      21: #define TABS 8
      22:
      23: string unixerror();
      24:
      25:
      26: /*
      27:  * Communication to other modules (demo, getc, ...):
      28:  */
      29:
      30: Visible bool interrupted; /* Set when interrupt caught but not propagated */
      31: Visible bool canjump; /* Set when disrupt() can safely longjmp(jumpback) */
      32: Visible jmp_buf jumpback; /* Set by other module where to jump */
      33:
      34: /*
      35:  * Pipeline protocol with interpreter:
      36:  */
      37:
      38: #define ESCAPE '\001' /* Character signalling special function */
      39: #define RESYNC '\177' /* Character signalling acknowledge of interrupt */
      40: #define INTRCHILD SIGTRAP /* Signal to send as interrupt */
      41:
      42: #ifndef INTERPRETER
      43: #define INTERPRETER "/usr/new/lib/B/bint"
      44: #endif
      45:
      46: /*
      47:  * Local definitions:
      48:  */
      49:
      50: #ifndef INTRMSG
      51: #define INTRMSG "*** Interrupted" /* Acknowledges interrupt */
      52: #endif INTRMSG
      53:
      54: #define Moreinput(stream) ((stream)->_cnt > 0)
      55:
      56: Hidden int fdown[2]; /* File descriptors for pipe down */
      57: Hidden int fup[2]; /* Pipe up */
      58:
      59: Hidden int pid; /* Process id of child */
      60:
      61: Hidden FILE *pdown; /* FILE pointer for pipe down to child process */
      62: Hidden FILE *pup; /* Pipe up */
      63:
      64: Hidden string interpreter; /* Name of interpreter to be used */
      65:
      66:
      67: Hidden char pushback[100]; /* Limited pushback facility */
      68: Hidden int npushback; /* Number of characters pushed back */
      69:
      70:
      71: /*
      72:  * Routine to set canjump, do a getc, and clear canjump.
      73:  */
      74:
      75: Visible int
      76: ffgetc(fp)
      77:     FILE *fp;
      78: {
      79:     register int c;
      80:
      81:     canjump = Yes;
      82:     c = getc(fp);
      83:     canjump = No;
      84:     return c;
      85: }
      86:
      87:
      88: /*
      89:  * Similar for fgets.
      90:  */
      91:
      92: Visible string
      93: ffgets(buf, len, fp)
      94:     string buf;
      95:     int len;
      96:     FILE *fp;
      97: {
      98:     canjump = Yes;
      99:     buf = fgets(buf, len, fp);
     100:     canjump = No;
     101:     return buf;
     102: }
     103:
     104:
     105: /*
     106:  * Assign values to `fdown' and `fup'.
     107:  */
     108:
     109: Hidden Procedure
     110: getdevices()
     111: {
     112:     if (pipe(fdown) < 0 || pipe(fup) < 0)
     113:         syserr("%s", unixerror("can't pipe"));
     114: }
     115:
     116:
     117: /*
     118:  * Do the magic required for child-birth.
     119:  */
     120:
     121: Hidden Procedure
     122: makechild()
     123: {
     124: #ifdef VFORK
     125:     pid = vfork();
     126: #else VFORK
     127:     pid = fork();
     128: #endif VFORK
     129:     if (pid == -1)
     130:         syserr("%s", unixerror("can't fork"));
     131:     if (pid == 0) /* Child */
     132:         exec_b(); /* Does not return */
     133:     /* Parent */
     134:     close(fdown[0]);
     135:     close(fup[1]);
     136: }
     137:
     138:
     139: /*
     140:  * Code executed in the child process.  Never returns.
     141:  * Just dup the pipe ends to files 0, a and 2 (stdin, stdout and stderr),
     142:  * then close the original pipes.
     143:  */
     144:
     145: Hidden Procedure
     146: exec_b()
     147: {
     148:     close(fdown[1]), close(fup[0]);
     149:     close(0), close(1), close(2);
     150:     dup(fdown[0]), dup(fup[1]), dup(fup[1]);
     151:     close(fdown[0]), close(fup[1]);
     152:     execl(interpreter, interpreter, "-i", (char*)NULL);
     153:     fprintf(stderr, "*** ");
     154:     perror(interpreter);
     155:     _exit(1);
     156: }
     157:
     158:
     159: /*
     160:  * Interrupt handler.
     161:  * Usually only the flag `interrupted' is set.
     162:  *
     163:  * When `canjump' is on, it is cleared and we do a longjmp
     164:  * back to where jumpbuf leads us (usually done when a read
     165:  * system call is interrupted, as 4.2BSD tends to continue
     166:  * these rather than have them return with errno = EINTR).
     167:  */
     168:
     169: Hidden Procedure
     170: disrupt()
     171: {
     172:     interrupted = Yes;
     173:     signal(SIGINT, disrupt);
     174:     if (canjump) {
     175:         canjump = No;
     176:         longjmp(jumpback, 1);
     177:     }
     178: }
     179:
     180:
     181: /*
     182:  * Start the B interpreter as a subprocess.
     183:  * Set up communication pipes in pdown, pup.
     184:  */
     185:
     186: Visible Procedure
     187: start_b(ppdown, ppup)
     188:     FILE **ppdown;
     189:     FILE **ppup;
     190: {
     191:     interpreter = getenv("B_INTERPRETER");
     192:     if (!interpreter)
     193:         interpreter = INTERPRETER;
     194:     getdevices();
     195:     makechild();
     196:     pdown = fdopen(fdown[1], "w");
     197:     pup = fdopen(fup[0], "r");
     198:     if (!pdown || !pup)
     199:         syserr("%s", unixerror("can't fdopen"));
     200:     *ppdown = pdown;
     201:     *ppup = pup;
     202:     signal(SIGINT, disrupt);
     203: }
     204:
     205:
     206: /*
     207:  * Routine to be called after each line of data has been passed
     208:  * to the B interpreter; it checks whether the immediate next
     209:  * output is a request for an immediate command, and if so,
     210:  * eats the request and returns Yes.  Otherwise it pushes back the
     211:  * request for later processing by sleur(), and returns No.
     212:  * ***** The prompt parameter is a relict of old times. *****
     213:  */
     214:
     215: Visible bool
     216: expect(prompt)
     217:     string prompt; /* Only first char used; should be ">" */
     218: {
     219:     register int c;
     220:
     221:     fflush(pdown);
     222:     if (setjmp(jumpback))
     223:         return No;
     224:     if (npushback)
     225:         c = pushback[--npushback];
     226:     else
     227:         c = ffgetc(pup);
     228:     if (c != ESCAPE) {
     229:         if (c != EOF)
     230:             pushback[npushback++] = c;
     231:         return No;
     232:     }
     233:     if (npushback)
     234:         c = pushback[--npushback];
     235:     else
     236:         c = ffgetc(pup);
     237:     if (c == *prompt)
     238:         return Yes;
     239:     if (c != EOF)
     240:         pushback[npushback++] = c;
     241:     pushback[npushback++] = ESCAPE;
     242:     return No;
     243: }
     244:
     245:
     246: Visible int
     247: sleur()
     248: {
     249:     register int c;
     250:     register int x = 0;
     251:     bool show = Yes; /* No when looking for interrupt sync char */
     252:     bool idle = Yes; /* Yes when no output done yet this call */
     253:
     254:     fflush(pdown);
     255:
     256:     for (;;) {
     257:         if (interrupted) {
     258:             interrupted = No;
     259:             intrchild();
     260:             show = No;
     261:         }
     262:         if (show && npushback == 0 && !Moreinput(pup))
     263:             fflush(stdout);
     264:         if (setjmp(jumpback))
     265:             continue;
     266:         if (npushback > 0)
     267:             c = pushback[--npushback];
     268:         else
     269:             c = ffgetc(pup);
     270:         if (c == EOF) { /* End-of-file: B interpreter has terminated. */
     271:             fflush(stdout);
     272:             return EOF;
     273:         }
     274:         if (c == RESYNC) {
     275:             /* B interpreter acknowledges interrupt. */
     276:             if (!show) {
     277:                 if (x != 0) putchar('\n');
     278:                 fputs(INTRMSG, stdout);
     279:                 putchar('\n');
     280:                 x = 0;
     281:                 show = Yes;
     282:             }
     283:             continue;
     284:         }
     285:         if (show) {
     286:             if (c != ESCAPE) {
     287:                 putchar(c);
     288:                 switch (c) {
     289:                 case '\t':
     290:                     x = (x/TABS + 1)*TABS;
     291:                     break;
     292:                 case '\b':
     293:                     if (x > 0) --x;
     294:                     break;
     295:                 case '\r':
     296:                 case '\n':
     297:                     x = 0;
     298:                     break;
     299:                 default:
     300:                     if (isascii(c) && isprint(c)
     301:                         || c == ' ') ++x;
     302:                     break;
     303:                 }
     304:             }
     305:             else {
     306:                 /* Control-A: B interpreter needs input. */
     307:                 if (setjmp(jumpback))
     308:                     continue;
     309:                 if (npushback)
     310:                     c = pushback[--npushback];
     311:                 else {
     312:                     c = ffgetc(pup);
     313:                     if (c == EOF) {
     314:                         return EOF;
     315:                     }
     316:                 }
     317:                 if (c == '>') {
     318:                     /* Newline before command prompt */
     319:                     if (x != 0) putchar('\n');
     320:                     x = 0;
     321:                 }
     322:                 setindent(x);
     323:                 fflush(stdout);
     324:                 return c;
     325:             }
     326:         }
     327:     }
     328: }
     329:
     330:
     331: /*
     332:  * Send the child a termination signal (SIGTERM).
     333:  */
     334:
     335: Visible Procedure
     336: termchild()
     337: {
     338:     if (pid) {
     339:         kill(pid, SIGTERM);
     340:         pid = 0;
     341:     }
     342: }
     343:
     344:
     345: /*
     346:  * Send the child an interrupt signal.  (By convention, this is SIGTRAP).
     347:  */
     348:
     349: Visible Procedure
     350: intrchild()
     351: {
     352:     if (pid) {
     353:         kill(pid, INTRCHILD);
     354:         fflush(stdout);
     355:     }
     356: }
     357:
     358:
     359: /*
     360:  * Wait for child process and report abnormal exit statuses.
     361:  */
     362:
     363: Visible Procedure
     364: waitchild()
     365: {
     366:     int k;
     367:     int status;
     368:
     369:     if (pid) {
     370:         while ((k = wait(&status)) != -1) {
     371:             if (k != pid)
     372: #ifndef SMALLSYS
     373:                 fprintf(stderr, "*** [Pid %d status 0%o]\n", pid, status)
     374: #endif SMALLSYS
     375:                 ;
     376:             else {
     377: #ifndef SMALLSYS
     378:                 if (status&0377)
     379:                     fprintf(stderr, "*** Interpreter killed by signal %d%s\n",
     380:                         status&0177, status&0200 ? " - core dumped" : "");
     381:                 else if (status)
     382:                     fprintf(stderr, "*** Interpreter exit(%d)\n", status>>8);
     383: #endif SMALLSYS
     384:                 pid = 0;
     385:                 break;
     386:             }
     387:         }
     388: #ifndef SMALLSYS
     389:         if (pid)
     390:             fprintf(stderr, "*** Can't get interpreter status\n");
     391: #endif SMALLSYS
     392:         pid = 0;
     393:     }
     394: }
     395:
     396: #endif BTOP

#### Defined functions

disrupt defined in line 169; used 2 times

- in line 173, 202

exec_b defined in line 145; used 1 times

- in line 132

expect defined in line 215; used 2 times

- in /usr/src/new/PORT/B/src/bed/save.c line 66, 152

ffgetc defined in line 75; used 4 times

- in line 227, 236, 269, 312

ffgets defined in line 92; never used
getdevices defined in line 109; used 1 times

- in line 194

intrchild defined in line 349; used 1 times

- in line 259

makechild defined in line 121; used 1 times

- in line 195

sleur defined in line 246; used 1 times

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

start_b defined in line 186; used 1 times

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

termchild defined in line 335; used 2 times

- in /usr/src/new/PORT/B/src/bed/main.c line 208
- in /usr/src/new/PORT/B/src/bed/unix.c line 70

waitchild defined in line 363; used 1 times

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

#### Defined variables

Procedure defined in line 363; never used
Visible defined in line 363; never used
canjump defined in line 31; used 8 times

- in line 81-83(2), 98-100(2), 174-175(2)
- in /usr/src/new/PORT/B/src/bed/demo.c line 314-318(2)

fdown defined in line 56; used 6 times

- in line 112, 134, 148-151(3), 196

fup defined in line 57; used 7 times

- in line 112, 135, 148-151(4), 197

interpreter defined in line 64; used 6 times

- in line 152-154(3), 191-193(3)

interrupted defined in line 30; used 7 times

- in line 172, 257-258(2)
- in /usr/src/new/PORT/B/src/bed/demo.c line 134, 161, 299, 312

jumpback defined in line 32; used 5 times

- in line 176, 222, 264, 307
- in /usr/src/new/PORT/B/src/bed/demo.c line 312

npushback defined in line 68; used 12 times

- in line 224-234(5), 240-241(2), 262-267(3), 309-310(2)

pid defined in line 59; used 15 times

- in line 125-131(4), 338-340(3), 352-353(2), 369-373(3), 384-392(3)

pushback defined in line 67; used 7 times

- in line 225-234(3), 240-241(2), 267, 310

rcsid defined in line 2; never used

#### Defined macros

ESCAPE defined in line 38; used 3 times

- in line 228, 241, 286

INTERPRETER defined in line 43; used 2 times

- in line 42, 193

INTRCHILD defined in line 40; used 1 times

- in line 353

INTRMSG defined in line 51; used 2 times

- in line 50, 278

Moreinput defined in line 54; used 1 times

- in line 262

RESYNC defined in line 39; used 1 times

- in line 274

TABS defined in line 21; used 2 times

- in line 290(2)

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