1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
   2: 
   3: /*
   4:   $Header: b3scr.c,v 1.4 85/08/22 16:58:54 timo Exp $
   5: */
   6: 
   7: /* B input/output handling */
   8: 
   9: #include "b.h"
  10: #include "b0fea.h"
  11: #include "b1mem.h"
  12: #include "b1obj.h"
  13: #include "b0con.h" /*for CLEAR_EOF*/
  14: #include "b2nod.h"
  15: #include "b2syn.h"
  16: #include "b2par.h"
  17: #include "b3scr.h"
  18: #include "b3err.h"
  19: #include "b3fil.h"
  20: #include "b3typ.h"
  21: #include "b3env.h"
  22: #include "b3sem.h"
  23: #include "b3int.h"
  24: #ifdef SETJMP
  25: #include <setjmp.h>
  26: #endif
  27: 
  28: Visible bool interactive;
  29: Visible bool rd_interactive;
  30: Visible value iname= Vnil;  /* input name */
  31: Visible bool filtered= No;
  32: Visible bool outeractive;
  33: #ifdef SETJMP
  34: Visible bool awaiting_input= No;
  35: Visible jmp_buf read_interrupt;
  36: #endif
  37: Visible bool at_nwl= Yes;   /*Yes if currently at the start of an output line*/
  38: Hidden bool woa, wnwl;      /*was outeractive, was at_nwl */
  39: Hidden bool last_was_text= No;  /*Yes if last value written was a text*/
  40: 
  41: Visible bool Eof;
  42: FILE *ofile= stdout;
  43: FILE *ifile;        /* input file */
  44: FILE *sv_ifile;     /* copy of ifile for restoring after reading unit */
  45: 
  46: /******************************* Output *******************************/
  47: 
  48: #ifndef INTEGRATION
  49: 
  50: Hidden Procedure putch(c) char c; {
  51:     if (still_ok) {
  52:         putc(c, ofile);
  53:         if (c == '\n') at_nwl= Yes;
  54:         else at_nwl= No;
  55:     }
  56: }
  57: 
  58: #else
  59: 
  60: Hidden int ocol;    /* Current output column */
  61: 
  62: Hidden Procedure putch(c) char c; {
  63:     if (still_ok) {
  64:         putc(c, ofile);
  65:         if (c == '\n') { at_nwl= Yes; ocol= 0; }
  66:         else {
  67:             if (at_nwl) { ocol= 0; at_nwl= No;}
  68:             ++ocol;
  69:         }
  70:     }
  71: }
  72: 
  73: #endif
  74: 
  75: Visible Procedure newline() {
  76:     putch('\n');
  77:     fflush(stdout);
  78: }
  79: 
  80: Hidden Procedure line() {
  81:     if (!at_nwl) newline();
  82: }
  83: 
  84: Visible Procedure wri_space() {
  85:     putch(' ');
  86: }
  87: 
  88: Visible Procedure writ(v) value v; {
  89:     wri(v, Yes, Yes, No);
  90:     fflush(stdout);
  91: }
  92: 
  93: #define Putch_sp() {if (!perm) putch(' ');}
  94: 
  95: Hidden int intsize(v) value v; {
  96:     value s= size(v); int len=0;
  97:     if (large(s)) error(MESS(3800, "value too big to output"));
  98:     else len= intval(s);
  99:     release(s);
 100:     return len;
 101: }
 102: 
 103: Hidden bool lwt;
 104: 
 105: Visible Procedure wri(v, coll, outer, perm) value v; bool coll, outer, perm; {
 106:     if (outer && !at_nwl && (!Is_text(v) || !last_was_text)
 107:           && (!Is_compound(v) || !coll)) putch(' ');
 108:     lwt= No;
 109:     if (Is_number(v)) {
 110:         if (perm) printnum(ofile, v);
 111:         else {
 112:             string cp= convnum(v);
 113:             while(*cp && still_ok) putch(*cp++);
 114:         }
 115:     } else if (Is_text(v)) {
 116: #ifndef INTEGRATION
 117:         wrtext(putch, v, outer ? '\0' : '"');
 118: #else
 119:         value ch; char c; int k, len= Length(v);
 120: #define QUOTE '"'
 121:         if (!outer) putch(QUOTE);
 122:         for (k=0; k<len && still_ok; k++) {
 123:             ch= thof(k+1, v);
 124:             putch(c= charval(ch));
 125:             if (!outer && (c == QUOTE || c == '`'))
 126:                 putch(c);
 127:             release(ch);
 128:         }
 129:         if (!outer) putch(QUOTE);
 130: #endif
 131:         lwt= outer;
 132:     } else if (Is_compound(v)) {
 133:         intlet k, len= Nfields(v);
 134:         outer&= coll;
 135:         if (!coll) putch('(');
 136:         for (k=0; k<len && still_ok; k++) {
 137:             wri(*Field(v, k), No, outer, perm);
 138:             if (!Lastfield(k)) {
 139:                 if (!outer){
 140:                     putch(',');
 141:                     Putch_sp();
 142:                 }
 143:             }
 144:         }
 145:         if (!coll) putch(')');
 146:     } else if (Is_list(v) || Is_ELT(v)) {
 147:         value ve; int k, len= intsize(v);
 148:         putch('{');
 149:         for (k=0; k<len && still_ok; k++) {
 150:             wri(ve= thof(k+1, v), No, No, perm);
 151:             release(ve);
 152:             if (!Last(k)) {
 153:                 putch(';');
 154:                 Putch_sp();
 155:             }
 156:         }
 157:         putch('}');
 158:     } else if (Is_table(v)) {
 159:         int k, len= intsize(v);
 160:         putch('{');
 161:         for (k=0; k<len && still_ok; k++) {
 162:             putch('['); wri(*key(v, k), Yes, No, perm);
 163:             putch(']'); putch(':'); Putch_sp();
 164:             wri(*assoc(v, k), No, No, perm);
 165:             if (!Last(k)) {
 166:                 putch(';');
 167:                 Putch_sp();
 168:             }
 169:         }
 170:         putch('}');
 171:     } else {
 172:         if (bugs || testing) { putch('?'); putch(Type(v)); putch('?'); }
 173:         else syserr(MESS(3801, "writing value of unknown type"));
 174:     }
 175:     last_was_text= lwt;
 176: #ifdef IBMPC
 177:     if (interrupted) clearerr(ofile);
 178: #endif
 179: }
 180: 
 181: /***************************** Input ****************************************/
 182: 
 183: Hidden char cmbuf[CMBUFSIZE]; /* for commands */
 184: Hidden char rdbuf[RDBUFSIZE]; /* for READ EG/RAW */
 185: 
 186: #ifndef INTEGRATION
 187: Visible string cmd_prompt= ">>> "; /* commands  */
 188: Visible string eg_prompt=  "?\b";  /* READ EG   */
 189: Visible string raw_prompt= "?\b";  /* READ RAW  */
 190: Visible string qn_prompt=  "?\b";  /* questions */
 191: #else
 192: Hidden literal cmd_prompt= '>'; /* commands  */
 193: Hidden literal eg_prompt=  'E';  /* READ EG   */
 194: Hidden literal raw_prompt= 'R';  /* READ RAW  */
 195: Hidden literal qn_prompt= 'Y';  /* questions */
 196: Visible literal unit_prompt= ':'; /* units */
 197: Visible literal tar_prompt= '='; /* targets */
 198: #endif
 199: 
 200: /* Read a line; EOF only allowed if not interactive, in which case eof set */
 201: /* Returns the line input                                                  */
 202: /* This is the only place where a long jump is necessary                   */
 203: /* In other places, interrupts are just like procedure calls, and checks   */
 204: /* of still_ok and interrupted suffice: eventually the stack unwinds to the*/
 205: /* main loop in imm_command(). Here though, an interrupt must actually     */
 206: /* terminate the read. Hence the bool awaiting_input indicating if the     */
 207: /* long jump is necessary or not                                           */
 208: 
 209: #ifndef INTEGRATION
 210: 
 211: Hidden txptr read_line(should_prompt, prompt, cmd, eof, eof_message)
 212:  bool should_prompt, cmd, *eof; string prompt, eof_message; {
 213:     txptr buf, rp, bufend; intlet k; bool got= No;
 214:     FILE *f;
 215:     *eof= No;
 216:     if (cmd) { buf= cmbuf; bufend= &cmbuf[CMBUFSIZE-2]; }
 217:     else     { buf= rdbuf; bufend= &rdbuf[RDBUFSIZE-2]; }
 218: #ifdef SETJMP
 219:     if (setjmp(read_interrupt) != 0) {
 220:         awaiting_input= No;
 221:         return buf;
 222:     }
 223: #endif
 224:     while (!got) {
 225:         rp= buf;
 226: #ifdef SETJMP
 227:         awaiting_input= Yes;
 228: #endif
 229:         if (should_prompt) {
 230:             if (cmd) {
 231:                 if (outeractive) {
 232:                     line();
 233:                     at_nwl= No;
 234:                 }
 235:             }
 236:             fprintf(stderr, prompt); fflush(stderr);
 237:             f= stdin;
 238:         } else {
 239:             f= ifile;
 240:         }
 241:         while ((k= getc(f)) != EOF && k != '\n') {
 242:             *rp++= k;
 243:             if (rp >= bufend) syserr(MESS(3802, "buffer overflow"));
 244:         }
 245: #ifdef SETJMP
 246:         awaiting_input= No;
 247: #endif
 248:         got= Yes; *rp++= '\n'; *rp= '\0';
 249:         if (k == EOF) {
 250:             if (should_prompt) {
 251:                 if (filtered) {
 252:                     bye(0); /*Editor has died*/
 253:                 } else {
 254:                     fprintf(stderr, "\r*** %s\n", eof_message);
 255:                     CLEAR_EOF;
 256:                     if (outeractive) at_nwl= Yes;
 257:                     got= No;
 258:                 }
 259:             } else *eof= Yes;
 260:         }
 261:     }
 262:     if (should_prompt && outeractive && k == '\n') at_nwl= Yes;
 263:     return buf;
 264: }
 265: 
 266: #else INTEGRATION
 267: 
 268: Hidden intlet
 269: rd_fileline(nbuf, file, nbufend)
 270:     string nbuf, nbufend;
 271:     FILE *file;
 272: {
 273:     intlet k;
 274:     while ((k= getc(file)) != EOF && k != '\n') {
 275:         *nbuf++= k;
 276:         if (nbuf >= nbufend)
 277:             syserr(MESS(3803, "buffer overflow rd_fileline()"));
 278:     }
 279:     *nbuf++= '\n'; *nbuf= '\0';
 280:     return k;
 281: }
 282: 
 283: Hidden intlet
 284: rd_bufline(nbuf, obuf, nbufend)
 285:     string nbuf, *obuf, nbufend;
 286: {
 287:     while (**obuf && **obuf != '\n') {
 288:         *nbuf++= **obuf; ++*obuf;
 289:         if (nbuf >= nbufend)
 290:             syserr(MESS(3804, "buffer overflow rd_bufline()"));
 291:     }
 292:     *nbuf++= '\n'; *nbuf= '\0';
 293:     if (**obuf)  { ++*obuf; return '\n';}
 294:     else return EOF;
 295: }
 296: 
 297: Hidden string edcmdbuf;
 298: 
 299: Hidden txptr
 300: read_line(should_prompt, prompt, cmd, eof, eof_message)
 301:     bool should_prompt, cmd, *eof; literal prompt; string eof_message;
 302: {
 303:     txptr buf, rp, bufend; intlet k, indent= 0; bool got= No;
 304:     static string pedcmdbuf;
 305:     if (prompt == eg_prompt || prompt == raw_prompt) indent= ocol;
 306:     *eof= No;
 307:     if (cmd) { buf= cmbuf; bufend= &cmbuf[CMBUFSIZE-2]; }
 308:     else     { buf= rdbuf; bufend= &rdbuf[RDBUFSIZE-2]; }
 309: #ifdef SETJMP
 310:     if (setjmp(read_interrupt) != 0) {
 311:         awaiting_input= No;
 312:         return buf;
 313:     }
 314: #endif
 315:     while (!got) {
 316:         rp= buf; got= Yes;
 317: #ifdef SETJMP
 318:         awaiting_input= Yes;
 319: #endif
 320:         if (!should_prompt) {
 321:             k= rd_fileline(rp, ifile, bufend);
 322:             if (k == EOF) *eof= Yes;
 323:         } else {
 324:             if (!edcmdbuf) {
 325:                 if (cmd && outeractive) { line(); at_nwl= No; }
 326:                 btop(&edcmdbuf, 0, prompt, indent);
 327:                 pedcmdbuf= edcmdbuf;
 328:             }
 329:             k= rd_bufline(rp, &pedcmdbuf, bufend);
 330:             if (k == EOF) {
 331:                 freemem((ptr) edcmdbuf);
 332:                 edcmdbuf= (string) NULL;
 333:                 if (prompt != '>') got= No;
 334:             }
 335:         }
 336: #ifdef SETJMP
 337:         awaiting_input= No;
 338: #endif
 339:     }
 340: 
 341:     if (should_prompt && outeractive && k == '\n') at_nwl= Yes;
 342:     return buf;
 343: }
 344: 
 345: #endif INTEGRATION
 346: 
 347: /* Rather over-fancy routine to ask the user a question */
 348: /* Will anybody discover that you're only given 4 chances? */
 349: 
 350: Hidden char USE_YES_OR_NO[]=
 351:  "Answer with yes or no (or use interrupt to duck the question)";
 352: 
 353: Hidden char LAST_CHANCE[]=
 354:  "This is your last chance. Take it. I really don't know what you want.\n\
 355:     So answer the question";
 356: 
 357: Hidden char NO_THEN[]=
 358:  "Well, I shall assume that your refusal to answer the question means no!";
 359: 
 360: Visible bool is_intended(m) string m; {
 361:     char answer; intlet try; txptr tp; bool eof;
 362:     if (!interactive) return Yes;
 363:     if (outeractive) line();
 364:     for (try= 1; try<=4; try++){
 365:         if (try == 1 || try == 3) fprintf(stderr, "*** %s\n", m);
 366:         tp= read_line(Yes, qn_prompt, No, &eof, USE_YES_OR_NO);
 367:         skipsp(&tp);
 368:         answer= Char(tp);
 369:         if (answer == 'y' || answer == 'Y') return Yes;
 370:         if (answer == 'n' || answer == 'N') return No;
 371:         if (outeractive) line();
 372:         fprintf(stderr, "*** %s\n",
 373:             try == 1 ? "Please answer with yes or no" :
 374:             try == 2 ? "Just yes or no, please" :
 375:             try == 3 ? LAST_CHANCE :
 376:             NO_THEN);
 377:     } /* end for */
 378:     return No;
 379: }
 380: 
 381: /* Read_eg uses evaluation but it shouldn't.
 382:    Wait for a more general mechanism. */
 383: 
 384: Visible Procedure read_eg(l, t) loc l; btype t; {
 385:     context c; parsetree code;
 386:     parsetree r= NilTree; value rv= Vnil; btype rt= Vnil;
 387:     envtab svprmnvtab= Vnil;
 388:     txptr fcol_save= first_col, tx_save= tx;
 389:     do {
 390:         still_ok= Yes;
 391:         sv_context(&c);
 392:         if (cntxt != In_read) {
 393:             release(read_context.uname);
 394:             sv_context(&read_context);
 395:         }
 396:         svprmnvtab= prmnvtab == Vnil ? Vnil : prmnv->tab;
 397:         /* save scratch-pad copy because of following setprmnv() */
 398:         setprmnv();
 399:         cntxt= In_read;
 400:         first_col= tx= read_line(rd_interactive, eg_prompt, No,
 401:             &Eof, "use interrupt to abort READ command");
 402:         if (still_ok && Eof)
 403:             error(MESS(3805, "End of file encountered during READ command"));
 404:         if (!rd_interactive) f_lino++;
 405:         if (still_ok) {
 406:             findceol();
 407:             r= expr(ceol);
 408:             if (still_ok) fix_nodes(&r, &code);
 409:             rv= evalthread(code); release(r);
 410:             rt= still_ok ? valtype(rv) : Vnil;
 411:             if (svprmnvtab != Vnil) {
 412:                 prmnvtab= prmnv->tab;
 413:                 prmnv->tab= svprmnvtab;
 414:             }
 415:             set_context(&c);
 416:             if (still_ok) must_agree(t, rt,
 417:     MESS(3806, "type of expression does not agree with that of EG sample"));
 418:             release(rt);
 419:         }
 420:         if (!still_ok && rd_interactive && !interrupted)
 421:             fprintf(stderr, "*** Please try again\n");
 422:     } while (!interrupted && !still_ok && rd_interactive);
 423:     if (still_ok) put(rv, l);
 424:     first_col= fcol_save;
 425:     tx= tx_save;
 426:     release(rv);
 427: }
 428: 
 429: Visible Procedure read_raw(l) loc l; {
 430:     value r; bool eof;
 431:     txptr line= read_line(rd_interactive, raw_prompt, No, &eof,
 432:             "use interrupt to abort READ t RAW");
 433:     if (still_ok && eof) error(MESS(3807, "End of file encountered during READ t RAW"));
 434:     if (!rd_interactive) f_lino++;
 435:     if (still_ok) {
 436:         txptr rp= line;
 437:         while (*rp != '\n') rp++;
 438:         *rp= '\0';
 439:         r= mk_text(line);
 440:         put(r, l);
 441:         release(r);
 442:     }
 443: }
 444: 
 445: Visible txptr getline() {
 446:     bool should_prompt=
 447:         interactive && sv_ifile == ifile;
 448:     return read_line(should_prompt, cmd_prompt, Yes, &Eof,
 449:             "use QUIT to end session");
 450: }
 451: 
 452: /******************************* Files ******************************/
 453: 
 454: Visible Procedure redirect(of) FILE *of; {
 455:     ofile= of;
 456:     if (of == stdout) {
 457:         outeractive= woa;
 458:         at_nwl= wnwl;
 459:     } else {
 460:         woa= outeractive; outeractive= No;
 461:         wnwl= at_nwl; at_nwl= Yes;
 462:     }
 463: }
 464: 
 465: Visible Procedure vs_ifile() {
 466:     ifile= sv_ifile;
 467: }
 468: 
 469: Visible Procedure re_screen() {
 470:     sv_ifile= ifile;
 471:     interactive= f_interactive(ifile) || (ifile == stdin && filtered);
 472:     Eof= No;
 473: }
 474: 
 475: /* initscr is a reserved name of CURSES */
 476: Visible Procedure init_scr() {
 477:     outeractive= f_interactive(stdout) || filtered;
 478:     rd_interactive= f_interactive(stdin) || filtered;
 479:     rdbuf[0]= '\n'; tx= rdbuf;
 480: }
 481: 
 482: Visible Procedure
 483: endscr()
 484: {
 485: #ifdef INTEGRATION
 486:     if (edcmdbuf) {
 487:         freemem((ptr) edcmdbuf);
 488:         edcmdbuf= (string) NULL;
 489:     }
 490: #endif
 491: }

Defined functions

endscr defined in line 482; used 1 times
getline defined in line 445; used 2 times
init_scr defined in line 476; used 1 times
intsize defined in line 95; used 2 times
is_intended defined in line 360; used 8 times
line defined in line 80; used 7 times
putch defined in line 62; used 25 times
rd_bufline defined in line 283; used 1 times
rd_fileline defined in line 268; used 1 times
re_screen defined in line 469; used 1 times
read_eg defined in line 384; never used
read_line defined in line 299; used 4 times
read_raw defined in line 429; never used
redirect defined in line 454; used 2 times
vs_ifile defined in line 465; used 7 times
wri_space defined in line 84; used 1 times

Defined variables

Eof defined in line 41; used 4 times
LAST_CHANCE defined in line 353; used 1 times
NO_THEN defined in line 357; used 1 times
Procedure defined in line 454; never used
USE_YES_OR_NO defined in line 350; used 1 times
Visible defined in line 454; never used
at_nwl defined in line 37; used 15 times
awaiting_input defined in line 34; used 7 times
cmbuf defined in line 183; used 4 times
cmd_prompt defined in line 192; used 1 times
edcmdbuf defined in line 297; used 8 times
eg_prompt defined in line 193; used 2 times
filtered defined in line 31; used 4 times
iname defined in line 30; never used
interactive defined in line 28; used 3 times
last_was_text defined in line 39; used 2 times
lwt defined in line 103; used 3 times
ocol defined in line 60; used 4 times
outeractive defined in line 32; used 11 times
qn_prompt defined in line 195; used 1 times
raw_prompt defined in line 194; used 2 times
rd_interactive defined in line 29; used 7 times
rdbuf defined in line 184; used 6 times
read_interrupt defined in line 35; used 3 times
tar_prompt defined in line 197; never used
unit_prompt defined in line 196; never used
wnwl defined in line 38; used 2 times
woa defined in line 38; used 2 times

Defined macros

Putch_sp defined in line 93; used 4 times
QUOTE defined in line 120; used 3 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2779
Valid CSS Valid XHTML 1.0 Strict