1: #ifndef NOICP
   2: 
   3: /*  C K U U S 5 --  "User Interface" for Unix Kermit, part 5  */
   4: 
   5: /*
   6:   Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
   7:   Columbia University Center for Computing Activities.
   8:   First released January 1985.
   9:   Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
  10:   York.  Permission is granted to any individual or institution to use this
  11:   software as long as it is not sold for profit.  This copyright notice must be
  12:   retained.  This software may not be included in commercial products without
  13:   written permission of Columbia University.
  14: */
  15: 
  16: /* Includes */
  17: 
  18: #include "ckcdeb.h"
  19: #include "ckcasc.h"
  20: #include "ckcker.h"
  21: #include "ckuusr.h"
  22: #include "ckcnet.h"
  23: #ifndef NOCSETS
  24: #include "ckcxla.h"
  25: #endif /* NOCSETS */
  26: #ifdef MAC
  27: #include "ckmasm.h"
  28: #endif /* MAC */
  29: 
  30: /* For formatted screens, "more?" prompting, etc. */
  31: 
  32: #define SCRNLEN 21          /* Screen length */
  33: #define SCRNWID 79          /* Screen width */
  34: 
  35: #ifdef FT18
  36: #define isxdigit(c) isdigit(c)
  37: #endif /* FT18 */
  38: 
  39: #ifdef MAC              /* Internal MAC file routines */
  40: #define feof mac_feof
  41: #define rewind mac_rewind
  42: #define fgets mac_fgets
  43: #define fopen mac_fopen
  44: #define fclose mac_fclose
  45: 
  46: int mac_feof();
  47: void mac_rewind();
  48: char *mac_fgets();
  49: FILE *mac_fopen();
  50: int mac_fclose();
  51: #endif /* MAC */
  52: 
  53: /* External variables */
  54: 
  55: extern int carrier, cdtimo, local, backgrd, bgset, sosi, suspend,
  56:   displa, binary, deblog, escape, xargs, flow, cmdmsk,
  57:   duplex, ckxech, pktlog, seslog, tralog, what,
  58:   keep, warn, tlevel, cwdf, nfuncs, unkcs, msgflg,
  59:   mdmtyp, zincnt, cmask, rcflag, success, xitsta, pflag, lf_opts, tnlm, tn_nlm;
  60: 
  61: extern char *ccntab[];
  62: 
  63: #ifndef NOFRILLS
  64: extern int en_cwd, en_del, en_dir, en_fin, en_bye,
  65:   en_get, en_hos, en_sen, en_set, en_spa, en_typ, en_who;
  66: #endif /* NOFRILLS */
  67: extern long vernum;
  68: extern int srvtim, srvdis, incase, inecho, intime, insilence, nvars, verwho;
  69: extern char *protv, *fnsv, *cmdv, *userv, *ckxv, *ckzv, *ckzsys, *xlav,
  70:  *cknetv, *clcmds;
  71: extern char *connv, *dialv, *loginv, *nvlook();
  72: 
  73: #ifndef NOSCRIPT
  74: extern int secho;
  75: #endif /* NOSCRIPT */
  76: 
  77: #ifndef NODIAL
  78: extern int nmdm;
  79: extern struct keytab mdmtab[];
  80: #endif /* NODIAL */
  81: 
  82: #ifdef NETCONN
  83: extern int tn_init, network, ttnproto;
  84: #endif /* NETCONN */
  85: 
  86: #ifdef OS2
  87: extern int tt_type, tt_arrow, tt_keypad, tt_wrap;
  88: #endif /* OS2 */
  89: extern int tt_crd;
  90: 
  91: #ifndef NOCSETS
  92: extern int language, nfilc, tcsr, tcsl;
  93: extern struct keytab fcstab[];
  94: #ifndef MAC
  95: extern struct keytab ttcstab[];
  96: #endif /* MAC */
  97: #endif /* NOCSETS */
  98: 
  99: extern int atcapr,
 100:   atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
 101:   attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso;
 102: 
 103: extern long speed;
 104: 
 105: extern char *DIRCMD, *PWDCMD, *DELCMD;
 106: #ifndef NOXMIT
 107: extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw;
 108: extern char xmitbuf[];
 109: #endif /* NOXMIT */
 110: 
 111: extern char **xargv, *versio, *ckxsys, *dftty, *cmarg, *lp;
 112: 
 113: #ifdef DCMDBUF
 114: extern char *cmdbuf, *atmbuf;       /* Command buffers */
 115: #ifndef NOSPL
 116: extern char *savbuf;            /* Command buffers */
 117: #endif /* NOSPL */
 118: #else
 119: extern char cmdbuf[], atmbuf[];     /* Command buffers */
 120: #ifndef NOSPL
 121: extern char savbuf[];           /* Command buffers */
 122: #endif /* NOSPL */
 123: #endif /* DCMDBUF */
 124: 
 125: extern char toktab[], ttname[], psave[];
 126: extern CHAR sstate;
 127: extern int cmflgs, techo, terror, repars, ncmd;
 128: extern struct keytab cmdtab[];
 129: 
 130: #ifndef MAC
 131: #ifndef NOSETKEY
 132: KEY *keymap;
 133: MACRO *macrotab;
 134: #endif /* NOSETKEY */
 135: #endif /* MAC */
 136: 
 137: #ifndef NOSPL
 138: extern struct mtab *mactab;
 139: extern struct keytab vartab[], fnctab[];
 140: extern int cmdlvl, maclvl, nmac, mecho, merror;
 141: #endif /* NOSPL */
 142: 
 143: FILE *tfile[MAXTAKE];           /* TAKE file stack */
 144: char *tfnam[MAXTAKE];
 145: 
 146: #ifndef NOSPL
 147: /* Local declarations */
 148: 
 149: int nulcmd = 0;         /* Flag for next cmd to be ignored */
 150: 
 151: /* Definitions for built-in macros */
 152: 
 153: /* First, the single line macros, installed with addmac()... */
 154: 
 155: /* IBM-LINEMODE macro */
 156: char *m_ibm = "set parity mark, set dupl half, set handsh xon, set flow none";
 157: 
 158: /* FATAL macro */
 159: char *m_fat = "if def \\%1 echo \\%1, if not = \\v(local) 0 hangup, stop 1";
 160: 
 161: #ifdef COMMENT
 162: /*
 163:   Long macro definitions were formerly done like this.  But some compilers
 164:   cannot handle continued string constants, others cannot handle string
 165:   constants that are this long.  So these definitions have been broken up
 166:   into pieces and put into arrays, see below.
 167: */
 168: char *m_forx = "if def _floop ass \\%9 \\fdef(_floop),else def \\%9,\
 169: ass _floop { _getargs,\
 170: define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,\
 171: \\%6,:inc, incr \\\\\\%1 \\%4,goto top,:bot,_putargs,return},\
 172: def break goto bot, def continue goto inc,\
 173: do _floop \\%1 \\%2 \\%3 \\%4 { \\%5 },assign _floop \\fcont(\\%9)";
 174: 
 175: char *m_while = "if def _wloop ass \\%9 \\fdef(_wloop),\
 176: ass _wloop {_getargs,:wtest,\\%1,\\%2,goto wtest,:wbot,_putargs,return},\
 177: def break goto wbot, def continue goto wtest,\
 178: do _wloop,assign _wloop \\fcont(\\%9)";
 179: 
 180: char *m_xif = "ass \\%9 \\fdef(_ify),ass _ify {_getargs, \\%1, _putargs},\
 181: do _ify,ass _ify \\fcont(\\%9)";
 182: #endif /* COMMENT */
 183: 
 184: /* Now the multiline macros, defined with addmmac()... */
 185: 
 186: /* FOR macro */
 187: char *for_def[] = { "_assign _for\\v(cmdlevel) { _getargs,",
 188: "define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,",
 189: "\\%6,:inc,incr \\\\\\%1 \\%4,goto top,:bot,_putargs},",
 190: "def break goto bot, def continue goto inc,",
 191: "do _for\\v(cmdlevel) \\%1 \\%2 \\%3 \\%4 { \\%5 },_assign _for\\v(cmdlevel)",
 192: ""};
 193: #ifdef COMMENT
 194: /*
 195:   This one didn't work right.  When an interior loop finished executing,
 196:   the definition of the enclosing loop was restored, but the new definition
 197:   could be in a different location in memory, so its macro execution pointer
 198:   could (and usually was) pointing at garbage.
 199: */
 200: char *old_for_def[] = { "if def _floop ass \\%9 \\fdef(_floop),else def \\%9,",
 201: "ass _floop { _getargs,",
 202: "define \\\\\\%1 \\%2,:top,if \\%5 \\\\\\%1 \\%3 goto bot,",
 203: "\\%6,:inc, incr \\\\\\%1 \\%4,goto top,:bot,_putargs,return},",
 204: "def break goto bot, def continue goto inc,",
 205: "do _floop \\%1 \\%2 \\%3 \\%4 { \\%5 },assign _floop \\fcont(\\%9)",
 206: ""};
 207: #endif /* COMMENT */
 208: 
 209: /* WHILE macro */
 210: char *whil_def[] = { "_assign _whi\\v(cmdlevel) {_getargs,",
 211: ":wtest,\\%1,\\%2,goto wtest,:wbot,_putargs},",
 212: "def break goto wbot, def continue goto wtest,",
 213: "do _whi\\v(cmdlevel),_assign _whi\\v(cmdlevel)",
 214: ""};
 215: #ifdef COMMENT
 216: /*
 217:   Same deal as FOR loop...
 218: */
 219: char *old_whil_def[] = { "if def _wloop asg \\%9 \\fdef(_wloop),",
 220: "asg _wloop {_getargs,:wtest,\\%1,\\%2,goto wtest,:wbot,_putargs,return},",
 221: "def break goto wbot, def continue goto wtest,",
 222: "do _wloop,assign _wloop \\fcont(\\%9)",
 223: ""};
 224: #endif /* COMMENT */
 225: 
 226: /* XIF macro */
 227: char *xif_def[] = {
 228: "_assign _if\\v(cmdlevel) {_getargs,\\%1,_putargs},",
 229: "do _if\\v(cmdlevel),_assign _if\\v(cmdlevel)",
 230: ""};
 231: #ifdef COMMENT
 232: /* Same deal */
 233: char *old_xif_def[] = {
 234: "asg \\%9 \\fdef(_ify),ass _ify {_getargs, \\%1, _putargs},",
 235: "do _ify,ass _ify \\fcont(\\%9)",
 236: ""};
 237: #endif /* COMMENT */
 238: 
 239: /* Variables declared here for use by other ckuus*.c modules */
 240: /* Space is allocated here to save room in ckuusr.c */
 241: 
 242: #ifdef DCMDBUF
 243: struct cmdptr *cmdstk;
 244: int *ifcmd, *count, *iftest;
 245: #else
 246: struct cmdptr cmdstk[CMDSTKL];
 247: int ifcmd[CMDSTKL], count[CMDSTKL], iftest[CMDSTKL];
 248: #endif /* DCMDBUF */
 249: 
 250: char *m_arg[MACLEVEL][NARGS];
 251: char *g_var[GVARS], *macp[MACLEVEL], *mrval[MACLEVEL];
 252: int macargc[MACLEVEL];
 253: char *macx[MACLEVEL];
 254: extern char varnam[];
 255: 
 256: char **a_ptr[27];           /* Array pointers, for arrays a-z */
 257: int a_dim[27];              /* Dimensions for each array */
 258: 
 259: char inpbuf[INPBUFSIZ] = { NUL };   /* Buffer for INPUT and REINPUT */
 260: char inpbufa[2] = { NUL, NUL };     /* Null terminators for INPUT buffer */
 261: char inchar[2] = { NUL, NUL };      /* Last character that was INPUT */
 262: int  incount = 0;           /* INPUT character count */
 263: 
 264: char lblbuf[50];            /* Buffer for labels */
 265: #endif /* NOSPL */
 266: 
 267: #ifdef DCMDBUF
 268: char *line;             /* Character buffer for anything */
 269: #else
 270: char line[LINBUFSIZ];
 271: #endif /* DCMDBUF */
 272: 
 273: #ifdef CK_CURSES
 274: #ifndef TRMBUFL
 275: #define TRMBUFL 1024
 276: #endif /* TRMBUFL */
 277: #ifdef DCMDBUF
 278: char *trmbuf;               /* Character buffer for termcap */
 279: #else
 280: char trmbuf[TRMBUFL];
 281: #endif /* DCMDBUF */
 282: #endif /* CK_CURSES */
 283: 
 284: extern char pktfil[],
 285: #ifdef DEBUG
 286:   debfil[],
 287: #endif /* DEBUG */
 288: #ifdef TLOG
 289:   trafil[],
 290: #endif /* TLOG */
 291:   sesfil[],
 292:   cmdstr[];
 293: #ifndef NOFRILLS
 294: extern int rmailf, rprintf;     /* REMOTE MAIL & PRINT items */
 295: extern char optbuf[];
 296: #endif /* NOFRILLS */
 297: 
 298: char *homdir = "";          /* Pointer to home directory string */
 299: 
 300: char tmpbuf[50], *tp;           /* Temporary buffer */
 301: char numbuf[20];            /* Buffer for numeric strings. */
 302: char kermrc[100];           /* Name of initialization file */
 303: int noinit = 0;             /* Flag for skipping init file */
 304: 
 305: #ifndef NOSPL
 306: _PROTOTYP( static long expon, (long, long) );
 307: _PROTOTYP( static long gcd, (long, long) );
 308: _PROTOTYP( static long fact, (long) );
 309: int                 /* Initialize macro data structures. */
 310: macini() {            /* Allocate mactab and preset the first element. */
 311:     if (!(mactab = (struct mtab *) malloc(sizeof(struct mtab) * MAC_MAX)))
 312:     return(-1);
 313:     mactab[0].kwd = NULL;
 314:     mactab[0].mval = NULL;
 315:     mactab[0].flgs = 0;
 316:     return(0);
 317: }
 318: #endif /* NOSPL */
 319: 
 320: /*  C M D I N I  --  Initialize the interactive command parser  */
 321: 
 322: VOID
 323: cmdini() {
 324:     int i, x, y, z;
 325: #ifndef NOSPL
 326: /*
 327:   On stack in case of recursion!
 328: */
 329:     char vnambuf[VNAML];        /* Buffer for variable names */
 330: #endif /* NOSPL */
 331: 
 332: #ifndef MAC
 333: #ifndef NOSETKEY            /* Allocate & initialize the keymap */
 334:     if (!(keymap = (KEY *) malloc(sizeof(KEY)*KMSIZE)))
 335:       fatal("cmdini: no memory for keymap");
 336:     if (!(macrotab = (MACRO *) malloc(sizeof(MACRO)*KMSIZE)))
 337:       fatal("cmdini: no memory for macrotab");
 338:     for ( i = 0; i < KMSIZE; i++ ) {
 339:     keymap[i] = i;
 340:     macrotab[i] = NULL;
 341:     }
 342: #ifdef OS2
 343:     keymapinit();
 344: #endif /* OS2 */
 345: #endif /* NOSETKEY */
 346: #endif /* MAC */
 347: 
 348: #ifdef DCMDBUF
 349:     if (cmsetup() < 0) fatal("Can't allocate command buffers!");
 350: #ifndef NOSPL
 351:     if (!(cmdstk = (struct cmdptr *) malloc(sizeof(struct cmdptr)*CMDSTKL)))
 352:     fatal("cmdini: no memory for cmdstk");
 353:     if (!(ifcmd = (int *) malloc(sizeof(int)*CMDSTKL)))
 354:     fatal("cmdini: no memory for ifcmd");
 355:     if (!(count = (int *) malloc(sizeof(int)*CMDSTKL)))
 356:     fatal("cmdini: no memory for count");
 357:     if (!(iftest = (int *) malloc(sizeof(int)*CMDSTKL)))
 358:     fatal("cmdini: no memory for iftest");
 359: #endif /* NOSPL */
 360: #ifdef CK_CURSES
 361: /*
 362:   Termcap buffer for fullscreen display, UNIX only.  VMS does it another way.
 363:   The fullscreen display is not supported on AOS/VS or OS-9, etc, yet, and
 364:   the Mac has its own built-in fullscreen display.
 365: */
 366: #ifdef UNIX
 367:     if (!(trmbuf = malloc(TRMBUFL+1)))
 368:     fatal("cmdini: no memory for termcap buffer");
 369: #endif /* UNIX */
 370: #endif /* CK_CURSES */
 371:     if (!(line = malloc(LINBUFSIZ)))
 372:     fatal("cmdini: no memory for line");
 373: #endif /* DCMDBUF */
 374: 
 375: #ifndef NOSPL
 376:     if (macini() < 0) fatal("Can't allocate macro buffers!");
 377: #endif /* NOSPL */
 378: 
 379: #ifdef AMIGA
 380:     if (tlevel < 0)
 381:       concb(escape);
 382: #endif /* AMIGA */
 383: 
 384: #ifndef NOSPL
 385:     cmdlvl = 0;             /* Start at command level 0 */
 386:     cmdstk[cmdlvl].src = CMD_KB;
 387:     cmdstk[cmdlvl].lvl = 0;
 388: #endif /* NOSPL */
 389: 
 390:     tlevel = -1;            /* Take file level = keyboard */
 391:     for (i = 0; i < MAXTAKE; i++)   /* Initialize command file names */
 392:       tfnam[i] = NULL;
 393: 
 394: #ifdef MAC
 395:     cmsetp("Mac-Kermit>");      /* Set default prompt */
 396: #else
 397:     cmsetp("C-Kermit>");        /* Set default prompt */
 398: #endif /* MAC */
 399: 
 400: #ifndef NOSPL
 401:     initmac();              /* Initialize macro table */
 402: /* Add one-line macros */
 403:     addmac("ibm-linemode",m_ibm);   /* Add built-in macros. */
 404:     addmac("fatal",m_fat);      /* FATAL macro. */
 405: /* Add multiline macros */
 406:     addmmac("_forx",for_def);       /* FOR macro. */
 407:     addmmac("_xif",xif_def);        /* XIF macro. */
 408:     addmmac("_while",whil_def);     /* WHILE macro. */
 409: /* Fill in command line argument vector */
 410:     sprintf(vnambuf,"\\&@[%d]",xargs);  /* Command line argument vector */
 411:     y = arraynam(vnambuf,&x,&z);    /* goes in array \&@[] */
 412:     if (y > -1) {
 413:     dclarray((char)x,z);        /* Declare the array */
 414:     for (i = 0; i < xargs; i++) {   /* Fill it */
 415:         sprintf(vnambuf,"\\&@[%d]",i);
 416:         addmac(vnambuf,xargv[i]);
 417:     }
 418:     }
 419:     *vnambuf = NUL;
 420: #endif /* NOSPL */
 421: 
 422: /* Get our home directory now.  This needed in lots of places. */
 423: 
 424:     homdir = zhome();
 425: 
 426: /* If skipping init file ('-Y' on Kermit command line), return now. */
 427: 
 428:     if (noinit) return;
 429: 
 430: #ifdef OS2
 431: /*
 432:   The -y init file must be fully specified or in the current directory.
 433:   KERMRC is looked for via INIT, PATH and DPATH in that order.  Finally, our
 434:   own executable file path is taken and the .EXE suffix is replaced by .INI
 435:   and this is tried as initialization file.
 436: */
 437:     if (rcflag) {
 438:     strcpy(line, kermrc);
 439:     } else {
 440:     _searchenv(kermrc,"INIT",line);
 441:     if (line[0] == 0)
 442:       _searchenv(kermrc,"PATH",line);
 443:     if (line[0] == 0)
 444:       _searchenv(kermrc,"DPATH",line);
 445:     if (line[0] == 0) {
 446:         char *pgmptr = GetLoadPath();
 447:         if (pgmptr) {
 448:           lp = strrchr(pgmptr, '.');
 449:           strncpy(line, pgmptr, lp - pgmptr);
 450:           strcpy(line + (lp - pgmptr), ".ini");
 451:         }
 452:     }
 453:     }
 454:     if ((tfile[0] = fopen(line,"r")) != NULL) {
 455:         tlevel = 0;
 456:     if (tfnam[tlevel] = malloc(strlen(line)+1))
 457:       strcpy(tfnam[tlevel],line);
 458: #ifndef NOSPL
 459:     cmdlvl++;
 460:     cmdstk[cmdlvl].src = CMD_TF;
 461:     cmdstk[cmdlvl].lvl = tlevel;
 462:     ifcmd[cmdlvl] = 0;
 463:     iftest[cmdlvl] = 0;
 464:     count[cmdlvl] = 0;
 465: #endif /* NOSPL */
 466:         debug(F110,"init file",line,0);
 467:     } else {
 468:         debug(F100,"no init file","",0);
 469:     }
 470: #else /* not OS2 */
 471:     lp = line;
 472:     lp[0] = '\0';
 473: #ifdef GEMDOS
 474:     zkermini(line,rcflag, kermrc);
 475: #else
 476: #ifdef VMS
 477:     zkermini(line,LINBUFSIZ,kermrc);
 478: #else /* not VMS */
 479:     if (rcflag) {           /* If init file name from cmd line */
 480:     strcpy(lp,kermrc);      /* use it */
 481:     } else {                /* otherwise */
 482:     if (homdir) {           /* look in home directory for it */
 483:         strcpy(lp,homdir);
 484:         if (lp[0] == '/') strcat(lp,"/");
 485:     }
 486:     strcat(lp,kermrc);      /* and use the default name */
 487:     }
 488: #endif /* VMS */
 489: #endif /* GEMDOS */
 490: 
 491: #ifdef AMIGA
 492:     reqoff();               /* disable requestors */
 493: #endif /* AMIGA */
 494: 
 495:     debug(F110,"ini file is",line,0);
 496:     if ((tfile[0] = fopen(line,"r")) != NULL) {
 497:     tlevel = 0;
 498:     if (tfnam[tlevel] = malloc(strlen(line)+1))
 499:       strcpy(tfnam[tlevel],line);
 500: #ifndef NOSPL
 501:     cmdlvl++;
 502:     ifcmd[cmdlvl] = 0;
 503:     iftest[cmdlvl] = 0;
 504:     count[cmdlvl] = 0;
 505:     debug(F101,"open ok","",cmdlvl);
 506:     cmdstk[cmdlvl].src = CMD_TF;
 507:     cmdstk[cmdlvl].lvl = tlevel;
 508: #endif /* NOSPL */
 509:     debug(F110,"init file",line,0);
 510:     }
 511:     if (homdir && (tlevel < 0)) {
 512:         strcpy(lp,kermrc);
 513:     if ((tfile[0] = fopen(line,"r")) != NULL) {
 514:         tlevel = 0;
 515:     if (tfnam[tlevel] = malloc(strlen(line)+1))
 516:       strcpy(tfnam[tlevel],line);
 517: #ifndef NOSPL
 518:         cmdlvl++;
 519:         cmdstk[cmdlvl].src = CMD_TF;
 520:         cmdstk[cmdlvl].lvl = tlevel;
 521:         ifcmd[cmdlvl] = 0;
 522:         iftest[cmdlvl] = 0;
 523:         count[cmdlvl] = 0;
 524: #endif /* NOSPL */
 525:     }
 526:     }
 527: #endif /* OS2 */
 528: #ifdef AMIGA
 529:     reqpop();               /* Restore requestors */
 530: #endif /* AMIGA */
 531: }
 532: 
 533: #ifndef NOSPL
 534: /*
 535:   G E T N C M
 536: 
 537:   Get next command from current macro definition.
 538: 
 539:   Moved to a separate routine in edit 181 to allow multiline GET
 540:   to work when issued in a macro.
 541: 
 542:   Command is copied into string pointed to by argument s, max length n.
 543:   Returns:
 544:    0 if a string was copied, -1 if there was no string to copy.
 545: */
 546: int
 547: getncm(s,n) char *s; int n; {
 548:     int y, kp = 0, pp = 0;
 549:     char *s2;
 550: 
 551:     s2 = s;
 552:     *s = NUL;               /* Copy next cmd to command buffer. */
 553: 
 554:     debug(F111,"getncm",s,n);
 555: 
 556:     for (y = 0;
 557:      macp[maclvl] && *macp[maclvl] && y < n;
 558:      y++, s++, macp[maclvl]++) {
 559: 
 560:     *s = *macp[maclvl];     /* Get next character */
 561:     debug(F000,"char","",*s);
 562: /*
 563:   Allow braces around macro definition to prevent commas from being turned to
 564:   end-of-lines and also treat any commas within parens as text so that
 565:   multiple-argument functions won't cause the command to break prematurely.
 566: */
 567:     if (*s == '{') kp++;        /* Count braces */
 568:     if (*s == '}') kp--;
 569:     if (*s == '(') pp++;        /* Count parentheses. */
 570:     if (*s == ')') pp--;
 571:     if (*s == ',' && pp <= 0 && kp <= 0) {
 572:         macp[maclvl]++;
 573:         debug(F110,"next cmd",s,0);
 574:         kp = pp = 0;
 575:         break;
 576:     }
 577:     }                   /* Reached end. */
 578:     if (*s2 == NUL) {           /* If nothing was copied, */
 579:     debug(F100,"getncm eom","",0);
 580:     popclvl();          /* pop command level. */
 581:     return(-1);
 582:     } else {                /* otherwise, tack CR onto end */
 583:     *s++ = CR;
 584:     *s = '\0';
 585:     if (mecho && pflag)
 586:       printf("%s\n",s2);
 587:     debug(F101,"getncm returns ptr to",s2,0);
 588:     }
 589:     return(0);
 590: }
 591: #endif /* NOSPL */
 592: 
 593: /*
 594:   G E T N C T
 595: 
 596:   Get next command from current TAKE file.
 597: 
 598:   Moved to a separate routine in edit 181 to allow multiline GET
 599:   to work when issued in a macro.
 600: 
 601:   Command is copied into string pointed to by argument s, max length n.
 602:   Returns:
 603:    0 if a string was copied,
 604:   -1 on EOF,
 605:   -2 on malloc failure
 606:   -3 if line not properly terminated
 607: */
 608: int
 609: getnct(s,n) char *s; int n; {
 610:     int i, j;
 611:     char c, *s2, *lp, *lp2;
 612: 
 613:     s2 = s;             /* Remember original pointer */
 614: 
 615:     debug(F101,"getnct","",n);
 616:     if (!(lp2 = (char *) malloc(n+1))) { /* Get a temporary buffer */
 617:     debug(F101,"getnct malloc failure","",0);
 618:     return(-2);
 619:     }
 620:     lp = lp2;               /* Make a working pointer */
 621:                     /* (lp2 must not change!) */
 622: 
 623:     while (1) {             /* Loop to read lines from file */
 624: 
 625:     if (fgets(lp2,n,tfile[tlevel]) == NULL) { /* EOF */
 626:         free(lp2);          /* Free temporary storage */
 627:         *s = NUL;           /* Make destination be empty */
 628:         return(-1);         /* Return failure code */
 629:     }
 630:     debug(F110,"Line from TAKE file",lp2,0); /* Got a line */
 631:     if (techo && pflag)     /* If TAKE ECHO ON, */
 632:       printf("%s",lp2);     /* echo it. */
 633: 
 634:     lp = lp2;           /* Make a working pointer */
 635: 
 636: /* Trim trailing whitespace */
 637: 
 638:     j = strlen(lp2) - 1;        /* Position of line terminator */
 639:     if (j < 0) j = 0;
 640:     c = lp2[j];         /* Value of line terminator */
 641:     if (c < LF || c > CR) {     /* It's not a terminator */
 642:         debug(F111,"getnct bad line",lp2,c);
 643:         if (feof(tfile[tlevel]) && j > 0 && j < n) {
 644:         printf("Warning: Last line of TAKE file lacks terminator\n");
 645:         c = lp2[++j] = '\n';
 646:         } else return(-3);
 647:     }
 648:     for (i = j - 1; i > -1; i--)    /* Back up over spaces and tabs */
 649:       if (lp2[i] != SP && lp2[i] != HT && lp2[i] != NUL)
 650:         break;
 651:     lp2[i+1] = c;           /* Move after last nonblank char */
 652:     lp2[i+2] = NUL;         /* Terminate the string */
 653:     while (*s++ = *lp++) {      /* Copy result to target buffer */
 654:         if (--n < 2) {
 655:         printf("?Command too long, maximum length: %d.\n",CMDBL);
 656:         free(lp2);
 657:         return(dostop());
 658:         }
 659: 
 660: /* Check for trailing comment, " ;" or " #" */
 661: 
 662:         if ((s > s2 + 1) &&
 663:         (*(s-1) == ';' || *(s-1) == '#') &&
 664:         (*(s-2) == SP  || *(s-2) == HT)) {
 665:         debug(F100,"Trailing comment","",0);
 666:         s -= 2;         /* Got one, back up buffer pointer */
 667:         n += 2;         /* and adjust free space count. */
 668:         while ((s >= s2)    /* Trim whitespace again. */
 669:                && (*s == SP || *s == HT))
 670:           s--, n++;
 671:         s++;            /* Point after last character */
 672:         *s++ = c;       /* Put back line terminator */
 673:         *s++ = NUL;     /* and string terminator */
 674:         n -= 3;         /* Adjust free count */
 675:         debug(F110,"Comment trimmed & terminated",s2,0);
 676:         break;
 677:         }
 678:     }
 679: 
 680: /* Check whether this line is continued */
 681: 
 682:     debug(F000,"Last char in line","",*(s-3));
 683:     if (*(s - 3) != CMDQ && *(s - 3) != '-') /* Line continued? */
 684:       break;                 /* No, done. */
 685:     s -= 3;                  /* No, back up pointer */
 686:     debug(F100,"Got continue char","",0);    /* and continue */
 687:     }
 688:     untab(s2);              /* Done, convert tabs to spaces */
 689:     free(lp2);              /* Free temporary storage */
 690:     return(0);              /* Return success */
 691: }
 692: 
 693: /*  P A R S E R  --  Top-level interactive command parser.  */
 694: 
 695: /*
 696:   Call with:
 697:     m = 0 for normal behavior: keep parsing and executing commands
 698:           until an action command is parsed, then return with a
 699:           Kermit start-state as the value of this function.
 700:     m = 1 to parse only one command, can also be used to call parser()
 701:           recursively.
 702:     m = 2 to read but do not execute one command.
 703:   In all cases, parser() returns:
 704:     0     if no Kermit protocol action required
 705:     > 0   with a Kermit protocol start-state.
 706:     < 0   upon error.
 707: */
 708: int
 709: parser(m) int m; {
 710:     int tfcode, xx, yy, zz;     /* Workers */
 711: 
 712: #ifndef NOSPL
 713:     int inlevel;            /* Level we were called at */
 714: #endif /* NOSPL */
 715:     char *cbp;              /* Command buffer pointer */
 716: #ifdef MAC
 717:     extern char *lfiles;        /* Fake extern cast */
 718: #endif /* MAC */
 719: 
 720: #ifdef AMIGA
 721:     reqres();           /* restore AmigaDOS requestors */
 722: #endif /* AMIGA */
 723: 
 724:     what = W_COMMAND;       /* Now we're parsing commands. */
 725: #ifndef NOSPL
 726:     if (cmdlvl == 0)        /* If at top (interactive) level, */
 727: #else
 728:     if (tlevel < 0)
 729: #endif /* NOSPL */
 730:       concb((char)escape);  /* put console in cbreak mode. */
 731: 
 732: #ifndef NOSPL
 733:     ifcmd[0] = 0;       /* Command-level related variables */
 734:     iftest[0] = 0;      /* initialize variables at top level */
 735:     count[0] = 0;       /* of stack... */
 736:     inlevel = cmdlvl;       /* Current macro level */
 737:     debug(F101,"&parser entry maclvl","",maclvl);
 738:     debug(F101,"&parser entry inlevel","",inlevel);
 739:     debug(F101,"&parser entry tlevel","",tlevel);
 740:     debug(F101,"&parser entry cmdlvl","",cmdlvl);
 741:     debug(F101,"&parser entry m","",m);
 742: #endif /* NOSPL */
 743: 
 744: /*
 745:   sstate becomes nonzero when a command has been parsed that requires some
 746:   action from the protocol module.  Any non-protocol actions, such as local
 747:   directory listing or terminal emulation, are invoked directly from below.
 748: */
 749: #ifdef COMMENT
 750:     if (local && pflag)         /* Just returned from connect? */
 751:       printf("\n");
 752: #endif /* COMMENT */
 753:     sstate = 0;             /* Start with no start state. */
 754: #ifndef NOFRILLS
 755:     rmailf = rprintf = 0;       /* MAIL and PRINT modifiers for SEND */
 756:     *optbuf = NUL;          /* MAIL and PRINT options */
 757: #endif /* NOFRILLS */
 758:     while (sstate == 0) {       /* Parse cmds until action requested */
 759:     debug(F100,"top of parse loop","",0);
 760: 
 761:     /* Take requested action if there was an error in the previous command */
 762: 
 763: #ifndef MAC
 764:     conint(trap,stptrap);       /* In case we were just fg'd */
 765:     bgchk();            /* Check background status */
 766: #endif /* MAC */
 767: 
 768:     debug(F101,"tlevel","",tlevel);
 769: #ifndef NOSPL               /* In case we just reached top level */
 770:     debug(F101,"cmdlvl","",cmdlvl);
 771:     if (cmdlvl == 0) concb((char)escape);
 772: #else
 773:     if (tlevel < 0) concb((char)escape);
 774: #endif /* NOSPL */
 775: 
 776: #ifndef NOSPL
 777:     if (success == 0) {
 778:         if (cmdstk[cmdlvl].src == CMD_TF && terror) {
 779:         printf("Command error: take file terminated.\n");
 780:         popclvl();
 781:         if (cmdlvl == 0) return(0);
 782:         }
 783:         if (cmdstk[cmdlvl].src == CMD_MD && merror) {
 784:         printf("Command error: macro terminated.\n");
 785:         popclvl();
 786:         if (m && (cmdlvl < inlevel))
 787:           return((int) sstate);
 788:         }
 789:     }
 790: 
 791:     nulcmd = (m == 2);
 792: #else
 793:     if (success == 0 && tlevel > -1 && terror) {
 794:         printf("Command error: take file terminated.\n");
 795:         popclvl();
 796:         cmini(ckxech);      /* Clear the cmd buffer. */
 797:         if (tlevel < 0)         /* Just popped out of cmd files? */
 798:           return(0);        /* End of init file or whatever. */
 799:     }
 800: #endif /* NOSPL */
 801: 
 802: #ifdef MAC
 803:     /* Check for TAKE initiated by menu. */
 804:     if ((tlevel == -1) && lfiles)
 805:         startlfile();
 806: #endif /* MAC */
 807: 
 808:         /* If in TAKE file, check for EOF */
 809: #ifndef NOSPL
 810: #ifdef MAC
 811:     if
 812: #else
 813:     while
 814: #endif /* MAC */
 815:       ((cmdstk[cmdlvl].src == CMD_TF)  /* If end of take file */
 816:            && (tlevel > -1)
 817:            && feof(tfile[tlevel])) {
 818:         popclvl();          /* pop command level */
 819:         cmini(ckxech);      /* and clear the cmd buffer. */
 820:         if (cmdlvl == 0)        /* Just popped out of all cmd files? */
 821:           return(0);        /* End of init file or whatever. */
 822:     }
 823: #ifdef MAC
 824:     miniparser(1);
 825:     if (sstate == 'a') {        /* if cmd-. cancel */
 826:         debug(F100, "parser: cancel take due to sstate", "", sstate);
 827:         sstate = '\0';
 828:         dostop();
 829:         return(0);          /* End of init file or whatever. */
 830:     }
 831: #endif /*  MAC */
 832: 
 833: #else /* NOSPL */
 834:     if ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
 835:         popclvl();          /* Pop up one level. */
 836:         cmini(ckxech);      /* and clear the cmd buffer. */
 837:         if (tlevel < 0)         /* Just popped out of cmd files? */
 838:           return(0);        /* End of init file or whatever. */
 839:     }
 840: #endif /* NOSPL */
 841: 
 842: #ifndef NOSPL
 843:         if (cmdstk[cmdlvl].src == CMD_MD) { /* Executing a macro? */
 844:         debug(F100,"parser macro","",0);
 845:         maclvl = cmdstk[cmdlvl].lvl; /* Get current level */
 846:         debug(F101,"parser maclvl","",maclvl);
 847:         cbp = cmdbuf;       /* Copy next cmd to command buffer. */
 848:         *cbp = NUL;
 849:         if (*savbuf) {      /* In case then-part of 'if' command */
 850:         strcpy(cbp,savbuf); /* was saved, restore it. */
 851:         *savbuf = '\0';
 852:         } else {            /* Else get next cmd from macro def */
 853:         if (getncm(cbp,CMDBL) < 0) {
 854:             if (m && (cmdlvl < inlevel))
 855:               return((int) sstate);
 856:             else /* if (!m) */ continue;
 857:         }
 858:         }
 859:         debug(F110,"cmdbuf from macro",cmdbuf,0);
 860: 
 861:     } else if (cmdstk[cmdlvl].src == CMD_TF)
 862: #else
 863:       if (tlevel > -1)
 864: #endif /* NOSPL */
 865:       {
 866: #ifndef NOSPL
 867:         if (*savbuf) {      /* In case THEN-part of IF command */
 868:         strcpy(cmdbuf,savbuf);  /* was saved, restore it. */
 869:         *savbuf = '\0';
 870:         } else
 871: #endif /* NOSPL */
 872: 
 873:           /* Get next line from TAKE file */
 874: 
 875:           if ((tfcode = getnct(cmdbuf,CMDBL)) < 0) {
 876:           if (tfcode < -1) {    /* Error */
 877:               printf("?Error in TAKE command file: %s\n",
 878:                  (tfcode == -2) ? "Memory allocation failure" :
 879:                  "Line too long or contains NUL characters"
 880:                  );
 881:               popclvl();
 882:           }
 883:           continue;     /* -1 means EOF */
 884:           }
 885: 
 886:         /* If interactive, get next command from user. */
 887: 
 888:     } else {            /* User types it in. */
 889:         if (pflag) prompt(xxstring);
 890:         cmini(ckxech);
 891:         }
 892: 
 893:         /* Now know where next command is coming from. Parse and execute it. */
 894: 
 895:     repars = 1;         /* 1 = command needs parsing */
 896:     displa = 0;         /* Assume no file transfer display */
 897: 
 898:     while (repars) {        /* Parse this cmd until entered. */
 899:         debug(F101,"parser top of while loop","",0);
 900:         cmres();            /* Reset buffer pointers. */
 901:         xx = cmkey2(cmdtab,ncmd,"Command","",toktab,xxstring);
 902:         debug(F101,"top-level cmkey2","",xx);
 903:         if (xx == -5) {
 904:         yy = chktok(toktab);
 905:         debug(F101,"top-level cmkey token","",yy);
 906:         ungword();
 907:         switch (yy) {
 908: #ifndef NOPUSH
 909:           case '!': xx = XXSHE; break; /* Shell escape */
 910: #endif /* NOPUSH */
 911:           case '#': xx = XXCOM; break; /* Comment */
 912:           case ';': xx = XXCOM; break; /* Comment */
 913: #ifndef NOSPL
 914:           case ':': xx = XXLBL; break; /* GOTO label */
 915: #endif /* NOSPL */
 916: #ifndef NOPUSH
 917:                   case '@': xx = XXSHE; break; /* Shell (DCL) escape */
 918: #endif /* NOPUSH */
 919:           default:
 920:             printf("\n?Invalid - %s\n",cmdbuf);
 921:             xx = -2;
 922:         }
 923:         }
 924: 
 925: #ifndef NOSPL
 926:             /* Special handling for IF..ELSE */
 927: 
 928:         if (ifcmd[cmdlvl])      /* Count stmts after IF */
 929:           ifcmd[cmdlvl]++;
 930:         if (ifcmd[cmdlvl] > 2 && xx != XXELS && xx != XXCOM)
 931:           ifcmd[cmdlvl] = 0;
 932: 
 933:         /* Execute the command and take action based on return code. */
 934: 
 935:         if (nulcmd) {       /* Ignoring this command? */
 936:         xx = XXCOM;     /* Make this command a comment. */
 937:         }
 938: #endif /* NOSPL */
 939: 
 940:         zz = docmd(xx); /* Parse rest of command & execute. */
 941:         debug(F101,"docmd returns","",zz);
 942: #ifdef MAC
 943:         if (tlevel > -1) {
 944:         if (sstate == 'a') {    /* if cmd-. cancel */
 945:             debug(F110, "parser: cancel take, sstate:", "a", 0);
 946:             sstate = '\0';
 947:             dostop();
 948:             return(0);      /* End of init file or whatever. */
 949:         }
 950:         }
 951: #endif /* MAC */
 952:         switch (zz) {
 953:         case -4:        /* EOF (e.g. on redirected stdin) */
 954:             doexit(GOOD_EXIT,xitsta); /* ...exit successfully */
 955:             case -1:        /* Reparse needed */
 956:             repars = 1;     /* Just set reparse flag and  */
 957:             continue;
 958:         case -6:        /* Invalid command given w/no args */
 959:             case -2:        /* Invalid command given w/args */
 960: #ifdef COMMENT
 961: #ifndef NOSPL
 962:             /* This is going to be really ugly... */
 963:             yy = mlook(mactab,atmbuf,nmac); /* Look in macro table */
 964:             if (yy > -1) {              /* If it's there */
 965:             if (zz == -2) {             /* insert "do" */
 966:                 char *mp;
 967:                 mp = malloc((int)strlen(cmdbuf) + 5);
 968:                 if (!mp) {
 969:                 printf("?malloc error 1\n");
 970:                 return(-2);
 971:                 }
 972:                 sprintf(mp,"do %s ",cmdbuf);
 973:                 strcpy(cmdbuf,mp);
 974:                 free(mp);
 975:             } else sprintf(cmdbuf,"do %s %c",atmbuf, CR);
 976:             if (ifcmd[cmdlvl] == 2) /* This one doesn't count! */
 977:               ifcmd[cmdlvl]--;
 978:             debug(F111,"stuff cmdbuf",cmdbuf,zz);
 979:             repars = 1; /* go for reparse */
 980:             continue;
 981:             } else {
 982:             char *p;
 983:             int n;
 984:             p = cmdbuf;
 985:             lp = line;
 986:             n = LINBUFSIZ;
 987:             if (cmflgs == 0) printf("\n");
 988:             if (xxstring(p,&lp,&n) > -1)
 989:               printf("?Invalid: %s\n",line);
 990:             else
 991:               printf("?Invalid: %s\n",cmdbuf);
 992:             } /* (fall thru...) */
 993: #else
 994:             printf("?Invalid: %s\n",cmdbuf);
 995: #endif /* NOSPL */
 996: #else
 997:             printf("?Invalid: %s\n",cmdbuf);
 998: #endif /* COMMENT */
 999: 
1000:         case -9:        /* Bad, error message already done */
1001:             success = 0;
1002:             debug(F110,"top-level cmkey failed",cmdbuf,0);
1003:             if (pflag == 0) /* if background, terminate */
1004:               fatal("Kermit command error in background execution");
1005:             cmini(ckxech);  /* (fall thru) */
1006: 
1007:             case -3:        /* Empty command OK at top level */
1008:             repars = 0;     /* Don't need to reparse. */
1009:             continue;       /* Go back and get another command. */
1010: 
1011:         default:        /* Command was successful. */
1012: #ifndef NOSPL
1013:             debug(F101,"parser preparing to continue","",maclvl);
1014: #endif /* NOSPL */
1015:             repars = 0;     /* Don't need to reparse. */
1016:             continue;       /* Go back and get another command. */
1017:         }
1018:     }
1019: #ifndef NOSPL
1020:     debug(F101,"parser breaks out of while loop","",maclvl);
1021:     if (m && (cmdlvl < inlevel))  return((int) sstate);
1022: #endif /* NOSPL */
1023:     }
1024: 
1025: /* Got an action command, return start state. */
1026: 
1027: #ifdef COMMENT
1028:     /* This is done in ckcpro.w instead, no need to do it twice. */
1029:     /* Interrupts off only if remote */
1030:     if (!local) connoi();
1031: #endif /* COMMENT */
1032:     return((int) sstate);
1033: }
1034: 
1035: #ifndef NOSPL
1036: /* OUTPUT command */
1037: 
1038: int                 /* This could easily become a macro */
1039: #ifdef CK_ANSIC
1040: xxout(char c)
1041: #else
1042: xxout(c) char c;
1043: #endif /* CK_ANSIC */
1044: /* xxout */ {               /* Function to output a character. */
1045:     debug(F101,"xxout","",c);
1046:     if (local)              /* If in local mode */
1047:       return(ttoc(c));          /* then to the external line */
1048:     else return(conoc(c));      /* otherwise to the console. */
1049: }
1050: 
1051: /* Returns 0 on failure, 1 on success */
1052: 
1053: int
1054: dooutput(s) char *s; {
1055:     int x, y, quote;
1056: 
1057:     if (local) {            /* Condition external line */
1058:     y = ttvt(speed,flow);
1059:     if (y < 0) return(0);
1060:     }
1061:     quote = 0;              /* Initialize backslash (\) quote */
1062: 
1063: #ifdef COMMENT
1064: /* This is done automatically in ttopen() now... */
1065: #ifdef TNCODE
1066:     if (network && ttnproto == NP_TELNET) /* If telnet connection, */
1067:       if (!tn_init++) tn_ini();           /* initialize it if necessary */
1068: #endif /* TNCODE */
1069: #endif /* COMMENT */
1070:     while (x = *s++) {          /* Loop through the string */
1071:     y = 0;              /* Error code, 0 = no error. */
1072:     if (x == CMDQ) {        /* Look for \b or \B in string */
1073:             quote++;            /* Got \ */
1074:         continue;           /* Get next character */
1075:     } else if (quote) {     /* This character is quoted */
1076:         if (quote == 1 && (x == 'b' || x == 'B')) { /* If \b or \B */
1077:         debug(F100,"OUTPUT BREAK","",0);
1078:         ttsndb();       /* send BREAK signal */
1079:         quote = 0;      /* Turn off quote flag */
1080:         continue;       /* and not the b or B */
1081: #ifdef CK_LBRK
1082:         } else if (quote == 1 && (x == 'l' || x == 'L')) { /* \l or \L */
1083:         debug(F100,"OUTPUT Long BREAK","",0);
1084:         ttsndlb();      /* send Long BREAK signal */
1085:         quote = 0;      /* Turn off quote flag */
1086:         continue;       /* and not the l or L */
1087: #endif /* CK_LBRK */
1088:         } else {            /* if \ not followed by b or B */
1089:         y = xxout(dopar(CMDQ)); /* output the backslash. */
1090:         quote = 0;      /* Turn off quote flag */
1091:         }
1092:     } else quote = 0;       /* Turn off quote flag */
1093:     y = xxout(dopar((char)x));  /* Output this character */
1094:     if (y < 0) {
1095:         printf("output error.\n");
1096:         return(0);
1097:     }
1098:     if (x == '\015') {      /* User typed carriage return */
1099:         if (tnlm            /* If TERMINAL NEWLINE-MODE is ON */
1100: #ifdef TNCODE
1101:         || (network &&      /* Or we have a network connection */
1102:             ttnproto == NP_TELNET && /* using TELNET protocol */
1103:             tn_nlm      /* and TELNET NEWLINE-MODE is ON */
1104:             )
1105: #endif /* TNCODE */
1106:         )
1107:           xxout(dopar('\012')); /* Send LF too (CR => CRLF) */
1108:     }
1109:     if (seslog && duplex)
1110:       if (zchout(ZSFILE,(char)x) < 0) seslog = 0;
1111:     }
1112:     return(1);
1113: }
1114: #endif /* NOSPL */
1115: 
1116: 
1117: /* Display version herald and initial prompt */
1118: 
1119: VOID
1120: herald() {
1121:     int x = 0;
1122:     if (bgset > 0 || (bgset != 0 && backgrd != 0)) x = 1;
1123:     debug(F101,"herald","",backgrd);
1124:     if (x == 0)
1125: #ifdef datageneral
1126:       printf("%s,%s\nType ? or HELP for help\n",versio,ckxsys);
1127: #else
1128:       printf("%s,%s\n\rType ? or HELP for help\n",versio,ckxsys);
1129: #endif /* datageneral */
1130: }
1131: #ifndef NOSPL
1132: /*  M L O O K  --  Lookup the macro name in the macro table  */
1133: 
1134: /*
1135:  Call this way:  v = mlook(table,word,n);
1136: 
1137:    table - a 'struct mtab' table.
1138:    word  - the target string to look up in the table.
1139:    n     - the number of elements in the table.
1140: 
1141:  The keyword table must be arranged in ascending alphabetical order, and
1142:  all letters must be lowercase.
1143: 
1144:  Returns the table index, 0 or greater, if the name was found, or:
1145: 
1146:   -3 if nothing to look up (target was null),
1147:   -2 if ambiguous,
1148:   -1 if not found.
1149: 
1150:  A match is successful if the target matches a keyword exactly, or if
1151:  the target is a prefix of exactly one keyword.  It is ambiguous if the
1152:  target matches two or more keywords from the table.
1153: */
1154: int
1155: mlook(table,cmd,n) struct mtab table[]; char *cmd; int n; {
1156: 
1157:     int i, v, cmdlen;
1158: 
1159: /* Lowercase & get length of target, if it's null return code -3. */
1160: 
1161:     if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
1162: 
1163: /* Not null, look it up */
1164: 
1165:     for (i = 0; i < n-1; i++) {
1166:         if (!strcmp(table[i].kwd,cmd) ||
1167:            ((v = !strncmp(table[i].kwd,cmd,cmdlen)) &&
1168:              strncmp(table[i+1].kwd,cmd,cmdlen))) {
1169:                 return(i);
1170:              }
1171:         if (v) return(-2);
1172:     }
1173: 
1174: /* Last (or only) element */
1175: 
1176:     if (!strncmp(table[n-1].kwd,cmd,cmdlen)) {
1177:         return(n-1);
1178:     } else return(-1);
1179: }
1180: 
1181: /* mxlook is like mlook, but an exact full-length match is required */
1182: 
1183: int
1184: mxlook(table,cmd,n) char *cmd; struct mtab table[]; int n; {
1185:     int i, cmdlen;
1186:     if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
1187:     for (i = 0; i < n; i++)
1188:       if (((int)strlen(table[i].kwd) == cmdlen) &&
1189:       (!strncmp(table[i].kwd,cmd,cmdlen))) return(i);
1190:     return(-1);
1191: }
1192: 
1193: /*
1194:   This routine is for the benefit of those compilers that can't handle
1195:   long string constants or continued lines within them.  Long predefined
1196:   macros like FOR, WHILE, and XIF have their contents broken up into
1197:   arrays of string pointers.  This routine concatenates them back into a
1198:   single string again, and then calls the real addmac() routine to enter
1199:   the definition into the macro table.
1200: */
1201: int
1202: addmmac(nam,s) char *nam, *s[]; {   /* Add a multiline macro definition */
1203:     int i, x, y; char *p;
1204:     x = 0;              /* Length counter */
1205:     for (i = 0; (y = (int)strlen(s[i])) > 0; i++) { /* Add up total length */
1206:         debug(F111,"addmmac line",s[i],y);
1207:     x += y;
1208:     }
1209:     debug(F101,"addmmac lines","",i);
1210:     debug(F101,"addmmac loop exit","",y);
1211:     debug(F111,"addmmac length",nam,x);
1212:     if (x < 0) return(-1);
1213: 
1214:     p = malloc(x+1);            /* Allocate space for all of it. */
1215:     if (!p) {
1216:     printf("?addmmac malloc error: %s\n",nam);
1217:     debug(F110,"addmmac malloc error",nam,0);
1218:     return(-1);
1219:     }
1220:     *p = '\0';              /* Start off with null string. */
1221:     for (i = 0; *s[i]; i++)     /* Concatenate them all together. */
1222:       strcat(p,s[i]);
1223:     y = (int)strlen(p);         /* Final precaution. */
1224:     debug(F111,"addmmac constructed string",p,y);
1225:     if (y == x) {
1226:     y = addmac(nam,p);      /* Add result to the macro table. */
1227:     } else {
1228:     debug(F100,"addmmac length mismatch","",0);
1229:     printf("\n!addmmac internal error!\n");
1230:     y = -1;
1231:     }
1232:     free(p);                /* Free the temporary copy. */
1233:     return(y);
1234: }
1235: 
1236: /* Here is the real addmac routine. */
1237: 
1238: int
1239: addmac(nam,def) char *nam, *def; {  /* Add a macro to the macro table */
1240:     int i, x, y, z, namlen, deflen;
1241:     char *p, c;
1242: 
1243:     if (!nam) return(-1);
1244:     namlen = (int)strlen(nam);      /* Get argument lengths */
1245:     debug(F111,"addmac nam",nam,namlen);
1246:     if (!def) {             /* Watch out for null pointer */
1247:     deflen = 0;
1248:     debug(F111,"addmac def","(null pointer)",deflen);
1249:     } else {
1250:     deflen = (int)strlen(def);
1251:     debug(F111,"addmac def",def,deflen);
1252:     }
1253:     if (deflen < 0) return(-1);     /* strlen() failure, fail. */
1254:     if (namlen < 1) return(-1);     /* No name given, fail. */
1255: 
1256:     if (*nam == CMDQ) nam++;        /* Backslash quote? */
1257:     if (*nam == '%') {          /* Yes, if it's a variable name, */
1258:     delmac(nam);            /* Delete any old value. */
1259:     if (!(c = *(nam + 1))) return(-1); /* Variable name letter or digit */
1260:     if (deflen < 1) {       /* Null definition */
1261:         p = NULL;           /* Better not malloc or strcpy! */
1262:     } else {            /* A substantial definition */
1263:         p = malloc(deflen + 1); /* Allocate space for it */
1264:         if (!p) {
1265:         printf("?addmac malloc error 2\n");
1266:         return(-1);
1267:         } else strcpy(p,def);   /* Copy definition into new space */
1268:     }
1269: 
1270:     /* Now p points to the definition, or is a null pointer */
1271: 
1272:     if (p)
1273:       debug(F110,"addmac p",p,0);
1274:     else
1275:       debug(F110,"addmac p","(null pointer)",0);
1276: 
1277:     if (c >= '0' && c <= '9') { /* Digit variable */
1278:         if (maclvl < 0) {       /* Are we calling or in a macro? */
1279:         g_var[c] = p;       /* No, it's a global "top level" one */
1280:         debug(F101,"addmac numeric global maclvl","",maclvl);
1281:         } else {            /* Yes, it's a macro argument */
1282:         m_arg[maclvl][c - '0'] = p;
1283:         debug(F101,"addmac macro arg maclvl","",maclvl);
1284:         }
1285:     } else {            /* It's a global variable */
1286:         if (c < 33 || c > GVARS) return(-1);
1287:         if (isupper(c)) c = tolower(c);
1288:         g_var[c] = p;       /* Put pointer in global-var table */
1289:         debug(F100,"addmac global","",0);
1290:     }
1291:     return(0);
1292:     } else if (*nam == '&') {       /* An array reference? */
1293:     char **q;
1294:     if ((y = arraynam(nam,&x,&z)) < 0) /* If syntax is bad */
1295:       return(-1);           /* return -1. */
1296:     if (chkarray(x,z) < 0)      /* If array not declared or */
1297:       return(-2);           /* subscript out of range, ret -2 */
1298:     delmac(nam);            /* Delete any current definition. */
1299:     x -= 96;            /* Convert name letter to index. */
1300:     if ((q = a_ptr[x]) == NULL) /* If array not declared, */
1301:       return(-3);           /* return -3. */
1302:     if (deflen > 0) {
1303:         if ((p = malloc(deflen+1)) == NULL) { /* Allocate space */
1304:         printf("addmac macro error 7: %s\n",nam);
1305:         return(-4);     /* for new def, return -4 on fail. */
1306:         }
1307:         strcpy(p,def);      /* Copy definition into new space. */
1308:     } else p = NULL;
1309:     q[z] = p;           /* Store pointer to it. */
1310:     return(0);          /* Done. */
1311:     } else debug(F110,"addmac macro def",nam,0);
1312: 
1313: /* Not a macro argument or a variable, so it's a macro definition */
1314: 
1315:     lower(nam);             /* Lowercase the name */
1316:     if (mxlook(mactab,nam,nmac) > -1)   /* Look up, requiring exact match */
1317:       delmac(nam);          /* if it's there, delete it. */
1318:     debug(F111,"addmac table size",nam,nmac);
1319:     for (y = 0;             /* Find the alphabetical slot */
1320:      y < MAC_MAX && mactab[y].kwd != NULL && strcmp(nam,mactab[y].kwd) > 0;
1321:      y++) ;
1322:     if (y == MAC_MAX) {         /* No more room. */
1323:     debug(F101,"addmac table overflow","",y);
1324:     return(-1);
1325:     } else debug(F111,"addmac position",nam,y);
1326:     if (mactab[y].kwd != NULL) {    /* Must insert */
1327:     for (i = nmac; i > y; i--) {    /* Move the rest down one slot */
1328:         mactab[i].kwd = mactab[i-1].kwd;
1329:         mactab[i].mval = mactab[i-1].mval;
1330:         mactab[i].flgs = mactab[i-1].flgs;
1331:     }
1332:     }
1333:     p = malloc(namlen + 1);     /* Allocate space for name */
1334:     if (!p) {
1335:     printf("?addmac malloc error 3: %s\n",nam);
1336:     return(-1);
1337:     }
1338:     strcpy(p,nam);          /* Copy name into new space */
1339:     mactab[y].kwd = p;          /* Add pointer to table */
1340: 
1341:     if (deflen > 0) {           /* Same deal for definition */
1342:     p = malloc(deflen + 1);     /* but watch out for null pointer */
1343:     if (p == NULL) {
1344:         printf("?addmac malloc error 5: %s\n", nam);
1345:         free(mactab[y].kwd);
1346:         mactab[y].kwd = NULL;
1347:         return(-1);
1348:     } else strcpy(p,def);       /* Copy the definition */
1349:     } else p = NULL;
1350:     mactab[y].mval = p;
1351:     mactab[y].flgs = 0;
1352:     nmac++;             /* Count this macro */
1353:     return(y);
1354: }
1355: 
1356: int
1357: delmac(nam) char *nam; {        /* Delete the named macro */
1358:     int i, x, z;
1359:     char *p, c;
1360: 
1361:     if (!nam) return(0);        /* Watch out for null pointer */
1362:     debug(F110,"delmac nam",nam,0);
1363:     if (*nam == CMDQ) nam++;
1364:     if (*nam == '%') {          /* If it's a variable name */
1365:     if (!(c = *(nam+1))) return(0); /* Get variable name letter or digit */
1366:     p = (char *)0;          /* Initialize value pointer */
1367:     if (maclvl > -1 && c >= '0' && c <= '9') { /* Digit? */
1368:         p = m_arg[maclvl][c - '0']; /* Get pointer from macro-arg table */
1369:         m_arg[maclvl][c - '0'] = NULL; /* Zero the table pointer */
1370:     } else {            /* It's a global variable */
1371:         if (c < 33 || c > GVARS) return(0);
1372:         p = g_var[c];       /* Get pointer from global-var table */
1373:         g_var[c] = NULL;        /* Zero the table entry */
1374:     }
1375:     if (p) {
1376:         debug(F110,"delmac def",p,0);
1377:         free(p);            /* Free the storage */
1378:     } else debug(F110,"delmac def","(null pointer)",0);
1379:     return(0);
1380:     }
1381: 
1382:     if (*nam == '&') {          /* An array reference? */
1383:     char **q;
1384:     if (arraynam(nam,&x,&z) < 0)    /* If syntax is bad */
1385:       return(-1);           /* return -1. */
1386:     x -= 96;            /* Convert name to number. */
1387:     if ((q = a_ptr[x]) == NULL) /* If array not declared, */
1388:       return(-2);           /* return -2. */
1389:     if (z > a_dim[x])       /* If subscript out of range, */
1390:       return(-3);           /* return -3. */
1391:     if (q[z]) {         /* If there is an old value, */
1392:         debug(F110,"delman def",q[z],0);
1393:         free(q[z]);         /* delete it. */
1394:         q[z] = NULL;
1395:     } else debug(F110,"delmac def","(null pointer)",0);
1396:     }
1397: 
1398:    /* Not a variable or an array, so it must be a macro. */
1399: 
1400:     if ((x = mlook(mactab,nam,nmac)) < 0) { /* Look it up */
1401:     debug(F111,"delmac mlook",nam,x);
1402:     return(x);
1403:     }
1404:     if (mactab[x].kwd)          /* Free the storage for the name */
1405:       free(mactab[x].kwd);
1406:     if (mactab[x].mval)         /* and for the definition */
1407:       free(mactab[x].mval);
1408: 
1409:     for (i = x; i < nmac; i++) {    /* Now move up the others. */
1410:     mactab[i].kwd = mactab[i+1].kwd;
1411:     mactab[i].mval = mactab[i+1].mval;
1412:     mactab[i].flgs = mactab[i+1].flgs;
1413:     }
1414:     nmac--;             /* One less macro */
1415:     mactab[nmac].kwd = NULL;        /* Delete last item from table */
1416:     mactab[nmac].mval = NULL;
1417:     mactab[nmac].flgs = 0;
1418:     return(0);
1419: }
1420: 
1421: VOID
1422: initmac() {             /* Init macro & variable tables */
1423:     int i, j;
1424: 
1425:     nmac = 0;               /* No macros */
1426:     for (i = 0; i < MAC_MAX; i++) { /* Initialize the macro table */
1427:     mactab[i].kwd = NULL;
1428:     mactab[i].mval = NULL;
1429:     mactab[i].flgs = 0;
1430:     }
1431:     for (i = 0; i < MACLEVEL; i++) {    /* Init the macro argument tables */
1432:     mrval[i] = NULL;
1433:     for (j = 0; j < 10; j++) {
1434:         m_arg[i][j] = NULL;
1435:     }
1436:     }
1437:     for (i = 0; i < GVARS; i++) {   /* And the global variables table */
1438:     g_var[i] = NULL;
1439:     }
1440:     for (i = 0; i < 26; i++) {      /* And the table of arrays */
1441:     a_ptr[i] = (char **) NULL;  /* Null pointer for each */
1442:     a_dim[i] = 0;           /* and a dimension of zero */
1443:     }
1444: }
1445: 
1446: int
1447: popclvl() {             /* Pop command level, return cmdlvl */
1448:     if (cmdlvl < 1) {           /* If we're already at top level */
1449:     cmdlvl = 0;         /* just make sure all the */
1450:     tlevel = -1;            /* stack pointers are set right */
1451:     maclvl = -1;            /* and return */
1452:     } else if (cmdstk[cmdlvl].src == CMD_TF) { /* Reading from TAKE file? */
1453:     if (tlevel > -1) {      /* Yes, */
1454:         if (tfnam[tlevel]) {
1455:         free(tfnam[tlevel]);
1456:         tfnam[tlevel] = NULL;
1457:         }
1458:         fclose(tfile[tlevel--]);    /* close it and pop take level */
1459:         cmdlvl--;           /* pop command level */
1460:     } else tlevel = -1;
1461:     } else if (cmdstk[cmdlvl].src == CMD_MD) { /* In a macro? */
1462:     if (maclvl > -1) {      /* Yes, */
1463:         debug(F111,"popclvl before",macx[maclvl],maclvl);
1464:         macp[maclvl] = "";      /* set macro pointer to null string */
1465:         *cmdbuf = '\0';     /* clear the command buffer */
1466:         if (mrval[maclvl+1]) {  /* Free any deeper return values. */
1467:         free(mrval[maclvl+1]);
1468:         mrval[maclvl+1] = NULL;
1469:         }
1470:         maclvl--;           /* pop macro level */
1471:         cmdlvl--;           /* and command level */
1472:         debug(F111,"popclvl after ",
1473:           macx[maclvl] ? macx[maclvl] : "",maclvl);
1474:     } else maclvl = -1;
1475:     }
1476: #ifndef MAC
1477:     if (cmdlvl < 1) {           /* If back at top level */
1478:     conint(trap,stptrap);       /* Fix interrupts */
1479:     bgchk();            /* Check background status */
1480:     concb((char)escape);        /* Go into cbreak mode */
1481:     }
1482: #endif /* MAC */
1483:     return(cmdlvl < 1 ? 0 : cmdlvl);    /* Return command level */
1484: }
1485: #else /* No script programming language */
1486: int popclvl() {             /* Just close current take file. */
1487:     if (tlevel > -1) {          /* if any... */
1488:     if (tfnam[tlevel]) {
1489:         free(tfnam[tlevel]);
1490:         tfnam[tlevel] = NULL;
1491:     }
1492:     fclose(tfile[tlevel--]);
1493:     }
1494:     if (tlevel == -1) {         /* And if back at top level */
1495:     conint(trap,stptrap);       /* check and set interrupts */
1496:         bgchk();            /* and background status */
1497:         concb((char)escape);        /* and go back into cbreak mode. */
1498:     }
1499:     return(tlevel + 1);
1500: }
1501: #endif /* NOSPL */
1502: 
1503: /* STOP - get back to C-Kermit prompt, no matter where from. */
1504: 
1505: int
1506: dostop() {
1507:     while ( popclvl() )  ;  /* Pop all macros & take files */
1508: #ifndef NOSPL
1509:     while (cmpop() > -1) ;  /* And all recursive cmd pkg invocations */
1510: #endif /* NOSPL */
1511:     cmini(ckxech);      /* Clear the command buffer. */
1512:     return(0);
1513: }
1514: 
1515: 
1516: /* Close the given log */
1517: 
1518: int
1519: doclslog(x) int x; {
1520:     int y;
1521:     switch (x) {
1522: #ifdef DEBUG
1523:     case LOGD:
1524:         if (deblog == 0) {
1525:         printf("?Debugging log wasn't open\n");
1526:         return(0);
1527:         }
1528:         *debfil = '\0';
1529:         deblog = 0;
1530:         return(zclose(ZDFILE));
1531: #endif /* DEBUG */
1532: 
1533:     case LOGP:
1534:         if (pktlog == 0) {
1535:         printf("?Packet log wasn't open\n");
1536:         return(0);
1537:         }
1538:         *pktfil = '\0';
1539:         pktlog = 0;
1540:         return(zclose(ZPFILE));
1541: 
1542:     case LOGS:
1543:         if (seslog == 0) {
1544:         printf("?Session log wasn't open\n");
1545:         return(0);
1546:         }
1547:         *sesfil = '\0';
1548:         seslog = 0;
1549:         return(zclose(ZSFILE));
1550: 
1551: #ifdef TLOG
1552:         case LOGT:
1553:         if (tralog == 0) {
1554:         printf("?Transaction log wasn't open\n");
1555:         return(0);
1556:         }
1557:         *trafil = '\0';
1558:         tralog = 0;
1559:         return(zclose(ZTFILE));
1560: #endif /* TLOG */
1561: 
1562: #ifndef NOSPL
1563:           case LOGW:            /* WRITE file */
1564:       case LOGR:            /* READ file */
1565:         y = (x == LOGR) ? ZRFILE : ZWFILE;
1566:         if (chkfn(y) < 1)       /* If no file to close */
1567:           return(1);        /* succeed silently. */
1568:         return(zclose(y));      /* Otherwise, close the file. */
1569: #endif /* NOSPL */
1570: 
1571:     default:
1572:         printf("\n?Unexpected log designator - %ld\n", x);
1573:         return(0);
1574:     }
1575: }
1576: 
1577: #ifndef NOSERVER
1578: #ifndef NOFRILLS
1579: static char *nm[] = { "disabled", "enabled" };
1580: #endif /* NOFRILLS */
1581: #endif /* NOSERVER */
1582: 
1583: static int slc = 0;         /* Screen line count */
1584: 
1585: #ifndef NOSHOW
1586: #ifndef NOFRILLS
1587: #define xxdiff(v,sys) strncmp(v,sys,strlen(sys))
1588: VOID
1589: shover() {
1590:     printf("\nVersions:\n %s\n Numeric: %ld",versio,vernum);
1591:     if (verwho) printf("-%d",verwho);
1592:     printf(xxdiff(ckxv,ckxsys) ? "\n %s for%s\n" : "\n %s\n",ckxv,ckxsys);
1593:     printf(xxdiff(ckzv,ckzsys) ? " %s for%s\n" : " %s\n",ckzv,ckzsys);
1594:     printf(" %s\n",protv);
1595:     printf(" %s\n",fnsv);
1596:     printf(" %s\n %s\n",cmdv,userv);
1597: #ifndef NOCSETS
1598:     printf(" %s\n",xlav);
1599: #endif /* NOCSETS */
1600: #ifndef MAC
1601:     printf(" %s\n",connv);
1602: #endif /* MAC */
1603: #ifndef NODIAL
1604:     printf(" %s\n",dialv);
1605: #endif /* NODIAL */
1606: #ifndef NOSCRIPT
1607:     printf(" %s\n",loginv);
1608: #endif /* NOSCRIPT */
1609: #ifdef NETCONN
1610:     printf(" %s\n",cknetv);
1611: #endif /* NETCONN */
1612:     printf("\n");
1613: }
1614: 
1615: VOID
1616: shofea() {
1617: #ifdef OS2
1618: #ifdef M_I286
1619:     printf("\nOS/2 16-bit.\n");
1620: #else
1621:     printf("\nOS/2 32-bit.\n");
1622: #endif /* M_I286 */
1623: #endif /* OS2 */
1624:     printf("\nSpecial features:\n");
1625: #ifdef NETCONN
1626:     printf(" Network support (type SHOW NET for further info)\n");
1627: #endif /* NETCONN */
1628: #ifndef NOCSETS
1629:     printf(" Latin-1 (West European) character-set translation\n");
1630: #ifdef LATIN2
1631:     printf(" Latin-2 (East European) character-set translation\n");
1632: #endif /* LATIN2 */
1633: #ifdef CYRILLIC
1634:     printf(" Cyrillic (Russian, Ukrainian, etc) character-set translation\n");
1635: #endif /* CYRILLIC */
1636: #ifdef KANJI
1637:     printf(" Kanji (Japanese) character-set translation\n");
1638: #endif /* KANJI */
1639: #endif /* NOCSETS */
1640: 
1641: #ifdef CK_CURSES
1642:     printf(" Fullscreen file transfer display\n");
1643: #endif /* CK_CURSES */
1644: 
1645:     printf("\nFeatures not included:\n");
1646: #ifndef CK_CURSES
1647: #ifndef MAC
1648:     printf(" No fullscreen file transfer display\n");
1649: #endif /* MAC */
1650: #endif /* CK_CURSES */
1651: #ifdef NOSERVER
1652:     printf(" No server mode\n");
1653: #endif /* NOSERVER */
1654: #ifdef NODEBUG
1655:     printf(" No debugging\n");
1656: #endif /* NODEBUG */
1657: #ifdef NOTLOG
1658:     printf(" No transaction log\n");
1659: #endif /* NOTLOG */
1660: #ifdef NOHELP
1661:     printf(" No built-in help\n");
1662: #endif /* NOHELP */
1663: #ifndef NETCONN
1664:     printf(" No network support\n");
1665: #endif /* NETCONN */
1666: #ifdef NOMSEND
1667:     printf(" No MSEND command\n");
1668: #endif /* NOMSEND */
1669: #ifdef NODIAL
1670:     printf(" No DIAL command\n");
1671: #else
1672: #ifdef MINIDIAL
1673:     printf(" DIAL command for modems other than Hayes, CCITT, and Unknown\n");
1674: #endif /* MINIDIAL */
1675: #endif /* NODIAL */
1676: #ifdef NOXMIT
1677:     printf(" No TRANSMIT command\n");
1678: #endif /* NOXMIT */
1679: #ifdef NOSCRIPT
1680:     printf(" No SCRIPT command\n");
1681: #endif /* NOSCRIPT */
1682: #ifdef NOSPL
1683:     printf(" No script programming features\n");
1684: #endif /* NOSPL */
1685: #ifdef NOCSETS
1686:     printf(" No character-set translation\n");
1687: #else
1688: #ifndef LATIN2
1689:     printf(" No Latin-2 character-set translation\n");
1690: #endif /* LATIN2 */
1691: #ifdef NOCYRIL
1692:     printf(" No Cyrillic character-set translation\n");
1693: #endif /* NOCYRIL */
1694: #ifndef KANJI
1695:     printf(" No Kanji character-set translation\n");
1696: #endif /* KANJI */
1697: #endif /* NOCSETS */
1698: #ifdef NOCMDL
1699:     printf(" No command-line arguments\n");
1700: #endif /* NOCMDL */
1701: #ifdef NOFRILLS
1702:     printf(" No frills\n");
1703: #endif /* NOFRILLS */
1704: #ifdef NOPUSH
1705:     printf(" No escape to system\n");
1706: #endif /* NOPUSH */
1707: #ifdef NOJC
1708: #ifdef UNIX
1709:     printf(" No UNIX job control\n");
1710: #endif /* UNIX */
1711: #endif /* NOJC */
1712: #ifdef NOSETKEY
1713:     printf(" No SET KEY command\n");
1714: #endif /* NOSETKEY */
1715: #ifdef NOESCSEQ
1716:     printf(" No ANSI escape sequence recognition\n");
1717: #endif /* NOESCSEQ */
1718: #ifndef PARSENSE
1719:     printf(" No automatic parity detection\n");
1720: #endif /* PARSENSE */
1721: /*
1722:   Print all of Kermit's compile-time options, as well as C preprocessor
1723:   predefined symbols that might affect us...
1724: */
1725:     printf("\nCompiler options:\n");
1726: #ifdef DEBUG
1727: #ifdef IFDEBUG
1728:     prtopt(" IFDEBUG");
1729: #else
1730:     prtopt(" DEBUG");
1731: #endif /* IFDEBUG */
1732: #endif /* DEBUG */
1733: #ifdef TLOG
1734:     prtopt(" TLOG");
1735: #endif /* TLOG */
1736: #ifdef NODIAL
1737:     prtopt(" NODIAL");
1738: #endif /* NODIAL */
1739: #ifdef MINIDIAL
1740:     prtopt(" MINIDIAL");
1741: #endif /* MINIDIAL */
1742: #ifdef DYNAMIC
1743:     prtopt(" DYNAMIC");
1744: #endif /* IFDEBUG */
1745: #ifndef NOSPL
1746:     sprintf(line," CMDDEP=%d",CMDDEP);
1747:     prtopt(line);
1748: #endif /* NOSPL */
1749: #ifdef UNIX
1750:     prtopt(" UNIX");
1751: #endif /* UNIX */
1752: #ifdef VMS
1753:     prtopt(" VMS");
1754: #endif /* VMS */
1755: #ifdef vms
1756:     prtopt(" vms");
1757: #endif /* vms */
1758: #ifdef VMSSHARE
1759:     prtopt(" VMSSHARE");
1760: #endif /* VMSSHARE */
1761: #ifdef datageneral
1762:     prtopt(" datageneral");
1763: #endif /* datageneral */
1764: #ifdef apollo
1765:     prtopt(" apollo");
1766: #endif /* apollo */
1767: #ifdef aegis
1768:     prtopt(" aegis");
1769: #endif /* aegis */
1770: #ifdef A986
1771:     prtopt(" A986");
1772: #endif /* A986 */
1773: #ifdef AMIGA
1774:     prtopt(" AMIGA");
1775: #endif /* AMIGA */
1776: #ifdef CONVEX9
1777:     prtopt(" CONVEX9");
1778: #endif /* CONVEX9 */
1779: #ifdef MAC
1780:     prtopt(" MAC");
1781: #endif /* MAC */
1782: #ifdef AUX
1783:     prtopt(" AUX");
1784: #endif /* AUX */
1785: #ifdef OS2
1786:     prtopt(" OS2");
1787: #endif /* OS2 */
1788: #ifdef OS9
1789:     prtopt(" OS9");
1790: #endif /* OS9 */
1791: #ifdef MSDOS
1792:     prtopt(" MSDOS");
1793: #endif /* MSDOS */
1794: #ifdef DIRENT
1795:     prtopt(" DIRENT");
1796: #endif /* DIRENT */
1797: #ifdef SDIRENT
1798:     prtopt(" SDIRENT");
1799: #endif /* SDIRENT */
1800: #ifdef NDIR
1801:     prtopt(" NDIR");
1802: #endif /* NDIR */
1803: #ifdef XNDIR
1804:     prtopt(" XNDIR");
1805: #endif /* XNDIR */
1806: #ifdef MATCHDOT
1807:     prtopt(" MATCHDOT");
1808: #endif /* MATCHDOT */
1809: #ifdef SAVEDUID
1810:     prtopt(" SAVEDUID");
1811: #endif /* SAVEDUID */
1812: #ifdef NOCCTRAP
1813:     prtopt(" NOCCTRAP");
1814: #endif /* NOCCTRAP */
1815: #ifdef SUNX25
1816:     prtopt(" SUNX25");
1817: #endif /* SUNX25 */
1818: #ifdef DECNET
1819:     prtopt(" DECNET");
1820: #endif /* DECNET */
1821: #ifdef ATT7300
1822:     prtopt(" ATT7300");
1823: #endif /* ATT7300 */
1824: #ifdef ATT6300
1825:     prtopt(" ATT6300");
1826: #endif /* ATT6300 */
1827: #ifdef HDBUUCP
1828:     prtopt(" HDBUUCP");
1829: #endif /* HDBUUCP */
1830: #ifdef NOUUCP
1831:     prtopt(" NOUUCP");
1832: #endif /* NOUUCP */
1833: #ifdef LONGFN
1834:     prtopt(" LONGFN");
1835: #endif /* LONGFN */
1836: #ifdef RDCHK
1837:     prtopt(" RDCHK");
1838: #endif /* RDCHK */
1839: #ifdef NAP
1840:     prtopt(" NAP");
1841: #endif /* NAP */
1842: #ifdef NAPHACK
1843:     prtopt(" NAPHACK");
1844: #endif /* NAPHACK */
1845: #ifdef NOIEXTEN
1846:     prtopt(" NOIEXTEN");
1847: #endif /* NOIEXTEN */
1848: #ifdef EXCELAN
1849:     prtopt(" EXCELAN");
1850: #endif /* EXCELAN */
1851: #ifdef PARAMH
1852:     prtopt(" PARAMH");
1853: #endif /* PARAMH */
1854: #ifdef INTERLAN
1855:     prtopt(" INTERLAN");
1856: #endif /* INTERLAN */
1857: #ifdef NOFILEH
1858:     prtopt(" NOFILEH");
1859: #endif /* NOFILEH */
1860: #ifdef NOSYSIOCTLH
1861:     prtopt(" NOSYSIOCTLH");
1862: #endif /* NOSYSIOCTLH */
1863: #ifdef DCLPOPEN
1864:     prtopt(" DCLPOPEN");
1865: #endif /* DCLPOPEN */
1866: #ifdef NOSETBUF
1867:     prtopt(" NOSETBUF");
1868: #endif /* NOSETBUF */
1869: #ifdef NOFDZERO
1870:     prtopt(" NOFDZERO");
1871: #endif /* NOFDZERO */
1872: #ifdef NOPOPEN
1873:     prtopt(" NOPOPEN");
1874: #endif /* NOPOPEN */
1875: #ifdef NOPARTIAL
1876:     prtopt(" NOPARTIAL");
1877: #endif /* NOPARTIAL */
1878: #ifdef NOSETREU
1879:     prtopt(" NOSETREU");
1880: #endif /* NOSETREU */
1881: #ifdef _POSIX_SOURCE
1882:     prtopt(" _POSIX_SOURCE");
1883: #endif /* _POSIX_SOURCE */
1884: #ifdef LCKDIR
1885:     prtopt(" LCKDIR");
1886: #endif /* LCKDIR */
1887: #ifdef ACUCNTRL
1888:     prtopt(" ACUCNTRL");
1889: #endif /* ACUCNTRL */
1890: #ifdef BSD4
1891:     prtopt(" BSD4");
1892: #endif /* BSD4 */
1893: #ifdef BSD44
1894:     prtopt(" BSD44");
1895: #endif /* BSD44 */
1896: #ifdef BSD41
1897:     prtopt(" BSD41");
1898: #endif /* BSD41 */
1899: #ifdef BSD43
1900:     prtopt(" BSD43");
1901: #endif /* BSD43 */
1902: #ifdef BSD29
1903:     prtopt(" BSD29");
1904: #endif /* BSD29 */
1905: #ifdef V7
1906:     prtopt(" V7");
1907: #endif /* V7 */
1908: #ifdef AIX370
1909:     prtopt(" AIX370");
1910: #endif /* AIX370 */
1911: #ifdef RTAIX
1912:     prtopt(" RTAIX");
1913: #endif /* RTAIX */
1914: #ifdef HPUX
1915:     prtopt(" HPUX");
1916: #endif /* HPUX */
1917: #ifdef HPUXPRE65
1918:     prtopt(" HPUXPRE65");
1919: #endif /* HPUXPRE65 */
1920: #ifdef DGUX
1921:     prtopt(" DGUX");
1922: #endif /* DGUX */
1923: #ifdef DGUX430
1924:     prtopt(" DGUX430");
1925: #endif /* DGUX430 */
1926: #ifdef DGUX540
1927:     prtopt(" DGUX540");
1928: #endif /* DGUX540 */
1929: #ifdef sony_news
1930:     prtopt(" sony_news");
1931: #endif /* sony_news */
1932: #ifdef CIE
1933:     prtopt(" CIE");
1934: #endif /* CIE */
1935: #ifdef XENIX
1936:     prtopt(" XENIX");
1937: #endif /* XENIX */
1938: #ifdef SCO_XENIX
1939:     prtopt(" SCO_XENIX");
1940: #endif /* SCO_XENIX */
1941: #ifdef ISIII
1942:     prtopt(" ISIII");
1943: #endif /* ISIII */
1944: #ifdef I386IX
1945:     prtopt(" I386IX");
1946: #endif /* I386IX */
1947: #ifdef RTU
1948:     prtopt(" RTU");
1949: #endif /* RTU */
1950: #ifdef PROVX1
1951:     prtopt(" PROVX1");
1952: #endif /* PROVX1 */
1953: #ifdef TOWER1
1954:     prtopt(" TOWER1");
1955: #endif /* TOWER1 */
1956: #ifdef UTEK
1957:     prtopt(" UTEK");
1958: #endif /* UTEK */
1959: #ifdef ZILOG
1960:     prtopt(" ZILOG");
1961: #endif /* ZILOG */
1962: #ifdef TRS16
1963:     prtopt(" TRS16");
1964: #endif /* TRS16 */
1965: #ifdef MINIX
1966:     prtopt(" MINIX");
1967: #endif /* MINIX */
1968: #ifdef C70
1969:     prtopt(" C70");
1970: #endif /* C70 */
1971: #ifdef AIXPS2
1972:     prtopt(" AIXPS2");
1973: #endif /* AIXPS2 */
1974: #ifdef AIXRS
1975:     prtopt(" AIXRS");
1976: #endif /* AIXRS */
1977: #ifdef UTSV
1978:     prtopt(" UTSV");
1979: #endif /* UTSV */
1980: #ifdef ATTSV
1981:     prtopt(" ATTSV");
1982: #endif /* ATTSV */
1983: #ifdef SVR3
1984:     prtopt(" SVR3");
1985: #endif /* SVR3 */
1986: #ifdef SVR4
1987:     prtopt(" SVR4");
1988: #endif /* SVR4 */
1989: #ifdef DELL_SVR4
1990:     prtopt(" DELL_SVR4");
1991: #endif /* DELL_SVR4 */
1992: #ifdef ICL_SVR4
1993:     prtopt(" ICL_SVR4");
1994: #endif /* ICL_SVR4 */
1995: #ifdef OSF
1996:     prtopt(" OSF");
1997: #endif /* OSF */
1998: #ifdef PTX
1999:     prtopt(" PTX");
2000: #endif /* PTX */
2001: #ifdef POSIX
2002:     prtopt(" POSIX");
2003: #endif /* POSIX */
2004: #ifdef SOLARIS
2005:     prtopt(" SOLARIS");
2006: #endif /* SOLARIS */
2007: #ifdef SUNOS4
2008:     prtopt(" SUNOS4");
2009: #endif /* SUNOS4 */
2010: #ifdef SUN4S5
2011:     prtopt(" SUN4S5");
2012: #endif /* SUN4S5 */
2013: #ifdef ENCORE
2014:     prtopt(" ENCORE");
2015: #endif /* ENCORE */
2016: #ifdef ultrix
2017:     prtopt(" ultrix");
2018: #endif
2019: #ifdef sxaE50
2020:     prtopt(" sxaE50");
2021: #endif
2022: #ifdef mips
2023:     prtopt(" mips");
2024: #endif
2025: #ifdef MIPS
2026:     prtopt(" MIPS");
2027: #endif
2028: #ifdef vax
2029:     prtopt(" vax");
2030: #endif
2031: #ifdef VAX
2032:     prtopt(" VAX");
2033: #endif
2034: #ifdef sun
2035:     prtopt(" sun");
2036: #endif
2037: #ifdef sun3
2038:     prtopt(" sun3");
2039: #endif
2040: #ifdef sun386
2041:     prtopt(" sun386");
2042: #endif
2043: #ifdef _SUN
2044:     prtopt(" _SUN");
2045: #endif
2046: #ifdef sun4
2047:     prtopt(" sun4");
2048: #endif
2049: #ifdef sparc
2050:     prtopt(" sparc");
2051: #endif
2052: #ifdef NEXT
2053:     prtopt(" NEXT");
2054: #endif
2055: #ifdef NeXT
2056:     prtopt(" NeXT");
2057: #endif
2058: #ifdef sgi
2059:     prtopt(" sgi");
2060: #endif
2061: #ifdef M_SYS5
2062:     prtopt(" M_SYS5");
2063: #endif
2064: #ifdef __SYSTEM_FIVE
2065:     prtopt(" __SYSTEM_FIVE");
2066: #endif
2067: #ifdef sysV
2068:     prtopt(" sysV");
2069: #endif
2070: #ifdef M_XENIX              /* SCO Xenix V and UNIX/386 */
2071:     prtopt(" M_XENIX");
2072: #endif
2073: #ifdef M_UNIX
2074:     prtopt(" M_UNIX");
2075: #endif
2076: #ifdef M_I386
2077:     prtopt(" M_I386");
2078: #endif
2079: #ifdef _M_I386
2080:     prtopt(" _M_I386");
2081: #endif
2082: #ifdef i386
2083:     prtopt(" i386");
2084: #endif
2085: #ifdef i286
2086:     prtopt(" i286");
2087: #endif
2088: #ifdef M_I286
2089:     prtopt(" M_I286");
2090: #endif
2091: #ifdef mc68000
2092:     prtopt(" mc68000");
2093: #endif
2094: #ifdef mc68010
2095:     prtopt(" mc68010");
2096: #endif
2097: #ifdef mc68020
2098:     prtopt(" mc68020");
2099: #endif
2100: #ifdef mc68030
2101:     prtopt(" mc68030");
2102: #endif
2103: #ifdef mc68040
2104:     prtopt(" mc68040");
2105: #endif
2106: #ifdef M_68000
2107:     prtopt(" M_68000");
2108: #endif
2109: #ifdef M_68010
2110:     prtopt(" M_68010");
2111: #endif
2112: #ifdef M_68020
2113:     prtopt(" M_68020");
2114: #endif
2115: #ifdef M_68030
2116:     prtopt(" M_68030");
2117: #endif
2118: #ifdef M_68040
2119:     prtopt(" M_68040");
2120: #endif
2121: #ifdef m68k
2122:     prtopt(" m68k");
2123: #endif
2124: #ifdef m88k
2125:     prtopt(" m88k");
2126: #endif
2127: #ifdef pdp11
2128:     prtopt(" pdp11");
2129: #endif
2130: #ifdef iAPX
2131:     prtopt(" iAPX");
2132: #endif
2133: #ifdef __hp9000s800
2134:     prtopt(" __hp9000s800");
2135: #endif
2136: #ifdef __hp9000s500
2137:     prtopt(" __hp9000s500");
2138: #endif
2139: #ifdef __hp9000s300
2140:     prtopt(" __hp9000s300");
2141: #endif
2142: #ifdef __hp9000s200
2143:     prtopt(" __hp9000s200");
2144: #endif
2145: #ifdef AIX
2146:     prtopt(" AIX");
2147: #endif
2148: #ifdef _AIXFS
2149:     prtopt(" _AIXFS");
2150: #endif
2151: #ifdef u370
2152:     prtopt(" u370");
2153: #endif
2154: #ifdef u3b
2155:     prtopt(" u3b");
2156: #endif
2157: #ifdef u3b2
2158:     prtopt(" u3b2");
2159: #endif
2160: #ifdef multimax
2161:     prtopt(" multimax");
2162: #endif
2163: #ifdef balance
2164:     prtopt(" balance");
2165: #endif
2166: #ifdef ibmrt
2167:     prtopt(" ibmrt");
2168: #endif
2169: #ifdef _IBMRT
2170:     prtopt(" _IBMRT");
2171: #endif
2172: #ifdef ibmrs6000
2173:     prtopt(" ibmrs6000");
2174: #endif
2175: #ifdef _AIX
2176:     prtopt(" _AIX");
2177: #endif /* _AIX */
2178: #ifdef _IBMR2
2179:     prtopt(" _IBMR2");
2180: #endif
2181: #ifdef __STRICT_BSD__
2182:     prtopt(" __STRICT_BSD__");
2183: #endif
2184: #ifdef __STRICT_ANSI__
2185:     prtopt(" __STRICT_ANSI__");
2186: #endif
2187: #ifdef _ANSI_C_SOURCE
2188:     prtopt(" _ANSI_C_SOURCE");
2189: #endif
2190: #ifdef __STDC__
2191:     prtopt(" __STDC__");
2192: #endif
2193: #ifdef __GNUC__             /* gcc in ansi mode */
2194:     prtopt(" __GNUC__");
2195: #endif
2196: #ifdef GNUC             /* gcc in traditional mode */
2197:     prtopt(" GNUC");
2198: #endif
2199: #ifdef CK_ANSIC
2200:     prtopt(" CK_ANSIC");
2201: #endif
2202: #ifdef CK_ANSILIBS
2203:     prtopt(" CK_ANSILIBS");
2204: #endif
2205: #ifdef _XOPEN_SOURCE
2206:     prtopt(" _XOPEN_SOURCE");
2207: #endif
2208: #ifdef _ALL_SOURCE
2209:     prtopt(" _ALL_SOURCE");
2210: #endif
2211: #ifdef _SC_JOB_CONTROL
2212:     prtopt(" _SC_JOB_CONTROL");
2213: #endif
2214: #ifdef _POSIX_JOB_CONTROL
2215:     prtopt(" _POSIX_JOB_CONTROL");
2216: #endif
2217: #ifdef SVR3JC
2218:     prtopt(" SVR3JC");
2219: #endif
2220: #ifdef _386BSD
2221:     prtopt(" _386BSD");
2222: #endif
2223: #ifdef _BSD
2224:     prtopt(" _BSD");
2225: #endif
2226: #ifdef TERMIOX
2227:     prtopt(" TERMIOX");
2228: #endif /* TERMIOX */
2229: #ifdef STERMIOX
2230:     prtopt(" STERMIOX");
2231: #endif /* STERMIOX */
2232: #ifdef CK_CURSES
2233:     prtopt(" CK_CURSES");
2234: #endif /* CK_CURSES */
2235: #ifdef CK_DTRCD
2236:     prtopt(" CK_DTRCD");
2237: #endif /* CK_DTRCD */
2238: #ifdef CK_DTRCTS
2239:     prtopt(" CK_DTRCTS");
2240: #endif /* CK_DTRCTS */
2241: #ifdef CK_RTSCTS
2242:     prtopt(" CK_RTSCTS");
2243: #endif /* CK_RTSCTS */
2244:     prtopt((char *)0);
2245:     printf("\n\n");
2246: }
2247: #endif /* NOFRILLS */
2248: #endif /* NOSHOW */
2249: 
2250: #ifdef VMS
2251: int
2252: sholbl() {
2253:     printf("VMS Labeled File Features:\n");
2254:     printf(" acl %s (ACL info %s)\n",
2255:        lf_opts & LBL_ACL ? "on " : "off",
2256:        lf_opts & LBL_ACL ? "preserved" : "discarded");
2257:     printf(" backup-date %s (backup date/time %s)\n",
2258:        lf_opts & LBL_BCK ? "on " : "off",
2259:        lf_opts & LBL_BCK ? "preserved" : "discarded");
2260:     printf(" name %s (original filename %s)\n",
2261:        lf_opts & LBL_NAM ? "on " : "off",
2262:        lf_opts & LBL_NAM ? "preserved" : "discarded");
2263:     printf(" owner %s (original file owner id %s)\n",
2264:        lf_opts & LBL_OWN ? "on " : "off",
2265:        lf_opts & LBL_OWN ? "preserved" : "discarded");
2266:     printf(" path %s (original file's disk:[directory] %s)\n",
2267:        lf_opts & LBL_PTH ? "on " : "off",
2268:        lf_opts & LBL_PTH ? "preserved" : "discarded");
2269: }
2270: #endif /* VMS */
2271: 
2272: #ifndef NOSHOW
2273: VOID
2274: shotcs(cs1,cs2) int cs1, cs2; {     /* Show terminal character set */
2275: #ifndef NOCSETS
2276: #ifndef MAC
2277:     int y;
2278:     char *s;
2279: #ifdef CK_ANSIC
2280:     int gettcs(int, int);
2281: #else
2282:     int gettcs();
2283: #endif /* CK_ANSIC */
2284: 
2285:     printf(" Terminal character-set");
2286:     if (cs1 == cs2) {
2287:     printf(": transparent\n");
2288:     } else {
2289:     s = "unknown";
2290:     for (y = 0; y <= nfilc; y++)    /* Look up name in keyword table */
2291:       if (ttcstab[y].kwval == cs2) {
2292:           if (ttcstab[y].flgs & CM_INV) /* Skip synonyms */
2293:         continue;
2294:           s = ttcstab[y].kwd;
2295:           break;
2296:       }
2297:     printf("s:\n   Remote: %s\n   Local:  ",s);
2298:     s = "unknown";
2299:     for (y = 0; y <= nfilc; y++)
2300:       if (ttcstab[y].kwval == cs1) {
2301:         if (ttcstab[y].flgs & CM_INV) /* Skip synonyms */
2302:           continue;
2303:         s = ttcstab[y].kwd;
2304:           break;
2305:       }
2306:     printf("%s",s);
2307:     if (cs2 != cs1) {
2308:         switch(gettcs(cs2,cs1)) {
2309:           case TC_USASCII:  s = "ascii";        break;
2310:           case TC_1LATIN:   s = "latin1-iso";   break;
2311:           case TC_2LATIN:   s = "latin2-iso";   break;
2312:           case TC_CYRILL:   s = "cyrillic-iso"; break;
2313:           case TC_JEUC:     s = "japanese-euc"; break;
2314:           default:          s = "transparent";  break;
2315:         }
2316:         printf("\n   Via:    %s\n",s);
2317:     }
2318:     }
2319: #endif /* MAC */
2320: #endif /* NOCSETS */
2321: }
2322: #endif /* NOSHOW */
2323: 
2324: #ifndef NOSHOW
2325: int
2326: doshow(x) int x; {
2327:     int y, i; long zz;
2328:     char *s;
2329: 
2330: #ifndef NOSETKEY
2331:     if (x == SHKEY) {           /* SHOW KEY */
2332:     int c;
2333:     KEY ch;
2334:     CHAR *s;
2335: 
2336:     if ((y = cmcfm()) < 0) return(y);
2337: #ifdef MAC
2338:     printf("Not implemented\n");
2339:     return(0);
2340: #else /* Not MAC */
2341:     printf(" Press key: ");
2342: #ifdef UNIX
2343: #ifdef NOSETBUF
2344:     fflush(stdout);
2345: #endif /* NOSETBUF */
2346: #endif /* UNIX */
2347:     conbin((char)escape);       /* Put terminal in binary mode */
2348:     c = congks(0);          /* Get character or scan code */
2349:     concb((char)escape);        /* Restore terminal to cbreak mode */
2350:     if (c < 0) {            /* Check for error */
2351:         printf("?Error reading key\n");
2352:         return(0);
2353:     }
2354: #ifndef OS2
2355: /*
2356:   Do NOT mask when it can be a raw scan code, perhaps > 255
2357: */
2358:     c &= cmdmsk;            /* Apply command mask */
2359: #endif /* OS2 */
2360:     printf("\n Key code \\%d => ",c);
2361:         if (macrotab[c]) {      /* See if there's a macro */
2362:         printf("String: ");     /* If so, display its definition */
2363:             s = macrotab[c];
2364:         while (ch = *s++)
2365:           if (ch < 32 || ch == 127
2366: /*
2367:   Systems whose native character sets have graphic characters in C1...
2368: */
2369: #ifndef NEXT                /* NeXT */
2370: #ifndef AUX             /* Macintosh */
2371: #ifndef XENIX               /* IBM PC */
2372: #ifndef OS2             /* IBM PC */
2373:           || (ch > 127 && ch < 160)
2374: #endif /* OS2 */
2375: #endif /* XENIX */
2376: #endif /* AUX */
2377: #endif /* NEXT */
2378:           )
2379:                 printf("\\{%d}",ch);    /* Display control characters */
2380:           else putchar((char) ch);  /* in backslash notation */
2381:         printf("\n");
2382:         } else {            /* No macro, show single character */
2383:         printf("Character: ");
2384:         ch = keymap[c];
2385:         if (ch < 32 || ch == 127 || ch > 255
2386: #ifndef NEXT
2387: #ifndef AUX
2388: #ifndef XENIX
2389: #ifndef OS2
2390:           || (ch > 127 && ch < 160)
2391: #endif /* OS2 */
2392: #endif /* XENIX */
2393: #endif /* AUX */
2394: #endif /* NEXT */
2395:         )
2396:           printf("\\%d",(unsigned int) ch);
2397:         else printf("%c \\%d",ch,(unsigned int) ch);
2398:     }
2399:     if (ch == (KEY) c)
2400:       printf(" (self, no translation)\n");
2401:     else printf("\n");
2402:     return(1);
2403: #endif /* MAC */
2404:     }
2405: #endif /* NOSETKEY */
2406: 
2407: #ifndef NOSPL
2408:     if (x == SHMAC) {           /* SHOW MACRO */
2409:     x = cmfld("Macro name, or carriage return to see them all","",&s,
2410:           NULL);
2411:     if (x == -3)            /* This means they want see all */
2412:       *line = '\0';
2413:     else if (x < 0)         /* Otherwise negative = parse error */
2414:       return(x);
2415:     else                /* 0 or greater */
2416:       strcpy(line,s);       /* means they typed something */
2417:     if ((y = cmcfm()) < 0) return(y); /* Get confirmation */
2418:     if (*line) {
2419:         slc = 0;            /* Initial SHO MAC line number */
2420:         x = mlook(mactab,s,nmac);   /* Look up what they typed */
2421:         switch (x) {
2422:           case -3:          /* Nothing to look up */
2423:         return(0);
2424:           case -1:          /* Not found */
2425:         printf("%s - not found\n",s);
2426:         return(0);
2427:           case -2:          /* Ambiguous, matches more than one */
2428:         y = (int)strlen(line);
2429:         slc = 1;
2430:         for (x = 0; x < nmac; x++)
2431:           if (!strncmp(mactab[x].kwd,line,y))
2432:             if (shomac(mactab[x].kwd,mactab[x].mval) < 0) break;
2433:         return(1);
2434:           default:          /* Matches one exactly */
2435:         shomac(mactab[x].kwd,mactab[x].mval);
2436:         return(1);
2437:         }
2438:     } else {            /* They want to see them all */
2439:         printf("Macros:\n");
2440:         slc = 1;
2441:         for (y = 0; y < nmac; y++)
2442:           if (shomac(mactab[y].kwd,mactab[y].mval) < 0) break;
2443:         return(1);
2444:     }
2445:     }
2446: #endif /* NOSPL */
2447: 
2448: /*
2449:   Other SHOW commands only have two fields.  Get command confirmation here,
2450:   then handle with big switch() statement.
2451: */
2452:     if ((y = cmcfm()) < 0) return(y);
2453:     switch (x) {
2454: 
2455: #ifdef SUNX25
2456:         case SHPAD:
2457:             shopad();
2458:             break;
2459: #endif /* SUNX25 */
2460: 
2461: #ifdef NETCONN
2462:     case SHNET:
2463:         shonet();
2464:         break;
2465: #endif /* NETCONN */
2466: 
2467:     case SHPAR:
2468:         shopar();
2469:         break;
2470: 
2471:         case SHATT:
2472:         shoatt();
2473:         break;
2474: 
2475: #ifndef NOSPL
2476:     case SHCOU:
2477:         printf(" %d\n",count[cmdlvl]);
2478:         break;
2479: #endif /* NOSPL */
2480: 
2481: #ifndef NOSERVER
2482:         case SHSER:         /* Show Server */
2483: #ifndef NOFRILLS
2484:         printf("Function           Status:\n");
2485:         printf(" GET                %s\n",nm[en_get]);
2486:         printf(" SEND               %s\n",nm[en_sen]);
2487:         printf(" REMOTE CD/CWD      %s\n",nm[en_cwd]);
2488:         printf(" REMOTE DELETE      %s\n",nm[en_del]);
2489:         printf(" REMOTE DIRECTORY   %s\n",nm[en_dir]);
2490:         printf(" REMOTE HOST        %s\n",nm[en_hos]);
2491:         printf(" REMOTE SET         %s\n",nm[en_set]);
2492:         printf(" REMOTE SPACE       %s\n",nm[en_spa]);
2493:         printf(" REMOTE TYPE        %s\n",nm[en_typ]);
2494:         printf(" REMOTE WHO         %s\n",nm[en_who]);
2495:         printf(" BYE                %s\n",nm[en_bye]);
2496:             printf(" FINISH             %s\n",nm[en_fin]);
2497: #endif /* NOFRILLS */
2498:         printf("Server timeout: %d\n",srvtim);
2499:         printf("Server display: %s\n\n", srvdis ? "on" : "off");
2500:         break;
2501: #endif /* NOSERVER */
2502: 
2503:         case SHSTA:         /* Status of last command */
2504:         printf( " %s\n", success ? "SUCCESS" : "FAILURE" );
2505:         return(0);          /* Don't change it */
2506: 
2507: #ifdef MAC
2508:     case SHSTK: {           /* Stack for MAC debugging */
2509:         long sp;
2510: 
2511:         sp = -1;
2512:         loadA0 ((char *)&sp);   /* set destination address */
2513:         SPtoaA0();          /* move SP to destination */
2514:         printf("Stack at 0x%x\n", sp);
2515:         show_queue();       /* more debugging */
2516:         break;
2517:     }
2518: #endif /* MAC */
2519: 
2520:     case SHTER:
2521:         printf(" Command bytesize:  %d bits\n",
2522:            (cmdmsk == 0377) ? 8 : 7);
2523:         printf(" Terminal bytesize: %d bits\n",
2524:            (cmask == 0377) ? 8 : 7);
2525: #ifdef OS2
2526:         printf(" Terminal type: %s\n",
2527:            (tt_type == TT_VT102) ? "VT102" : "VT52");
2528: 
2529: #endif /* OS2 */
2530:         printf(" Terminal echo: %s\n", duplex ? "local" : "remote");
2531:         printf(" Terminal locking-shift: %s\n", sosi ? "on" : "off");
2532:         printf(" Terminal newline-mode:  %s\n", tnlm ? "on" : "off");
2533:         printf(" Terminal cr-display:    %s\n",
2534:            tt_crd ? "crlf" : "normal");
2535: #ifdef OS2
2536: /* Should show cursor and colors here too... */
2537:         printf(" Terminal arrow-keys:    %s\n",
2538:            tt_arrow ? "cursor" : "application");
2539:         printf(" Terminal keypad-mode:   %s\n",
2540:            tt_keypad ? "numeric" : "application");
2541:         printf(" Terminal wrap:          %s\n", tt_wrap ? "on" : "off");
2542: #endif /* OS2 */
2543: 
2544: #ifndef NOCSETS
2545:         shotcs(tcsl,tcsr);
2546: #endif /* NOCSETS */
2547:         printf(" CONNECT-mode escape character: %d (Ctrl-%c, %s)\n",
2548:          escape,ctl(escape),(escape == 127 ? "DEL" : ccntab[escape]));
2549: #ifdef UNIX
2550:         printf(" Suspend: %s\n", suspend ? "on" : "off");
2551: #endif /* UNIX */
2552:         break;
2553: 
2554: #ifndef NOFRILLS
2555:     case SHVER:
2556:         shover();
2557:         break;
2558: #endif /* NOFRILLS */
2559: 
2560: #ifndef NOSPL
2561:     case SHBUI:         /* Built-in variables */
2562:         i = 0;
2563:         for (y = 0; y < nvars; y++) {
2564:         printf(" \\v(%s) = %s\n",vartab[y].kwd,nvlook(vartab[y].kwd));
2565:         if (++i > SCRNLEN) {    /* More than a screenful... */
2566:             if (!askmore())
2567:               break;
2568:             else
2569:               i = 0;
2570:         }
2571:         }
2572:             break;
2573: 
2574:     case SHFUN:         /* Functions */
2575:         for (y = 0; y < nfuncs; y++)
2576:           printf(" \\f%s()\n",fnctab[y].kwd);
2577:         break;
2578: 
2579:         case SHVAR:         /* Global variables */
2580:         x = 0;          /* Variable count */
2581:         slc = 1;            /* Screen line count for "more?" */
2582:         for (y = 33; y < GVARS; y++)
2583:           if (g_var[y]) {
2584:           if (x++ == 0) printf("Global variables:\n");
2585:           sprintf(line," \\%%%c",y);
2586:           if (shomac(line,g_var[y]) < 0) break;
2587:           }
2588:         if (!x) printf(" No variables defined\n");
2589:         break;
2590: 
2591:         case SHARG:         /* Args */
2592:         if (maclvl > -1) {
2593:         printf("Macro arguments at level %d\n",maclvl);
2594:         for (y = 0; y < 10; y++)
2595:           if (m_arg[maclvl][y])
2596:             printf(" \\%%%d = %s\n",y,m_arg[maclvl][y]);
2597:         } else {
2598:         printf(" No macro arguments at top level\n");
2599:         }
2600:         break;
2601: 
2602:         case SHARR:         /* Arrays */
2603:         x = 0;
2604:         for (y = 0; y < 27; y++)
2605:           if (a_ptr[y]) {
2606:           if (x == 0) printf("Declared arrays:\n");
2607:           x = 1;
2608:           printf(" \\&%c[%d]\n",(y == 0) ? 64 : y + 96, a_dim[y]);
2609:           }
2610:         if (!x) printf(" No arrays declared\n");
2611:         break;
2612: #endif /* NOSPL */
2613: 
2614:     case SHPRO:         /* Protocol parameters */
2615:         shoparp();
2616:         printf("\n");
2617:         break;
2618: 
2619:     case SHCOM:         /* Communication parameters */
2620:         printf("\n");
2621:         shoparc();
2622: #ifndef NODIAL
2623:         printf("\n");
2624: #ifdef NETCONN
2625:         if (!network)
2626: #endif /* NETCONN */
2627:           shodial();
2628: #endif /* NODIAL */
2629:         printf("\n");
2630:         shomdm();
2631:         printf("\n");
2632:         break;
2633: 
2634:     case SHFIL:         /* File parameters */
2635:         shoparf();
2636:         printf("\n");
2637:         break;
2638: 
2639: #ifndef NOCSETS
2640:     case SHLNG:         /* Languages */
2641:         shoparl();
2642:         break;
2643: #endif /* NOCSETS */
2644: 
2645: #ifndef NOSPL
2646:     case SHSCR:         /* Scripts */
2647:         printf(" Take  Echo:     %s\n", techo  ? "On" : "Off");
2648:         printf(" Take  Error:    %s\n", terror ? "On" : "Off");
2649:         printf(" Macro Echo:     %s\n", mecho  ? "On" : "Off");
2650:         printf(" Macro Error:    %s\n", merror ? "On" : "Off");
2651:         printf(" Input Case:     %s\n", incase ? "Observe" : "Ignore");
2652:         printf(" Input Echo:     %s\n", inecho ? "On" : "Off");
2653:             printf(" Input Silence:  %d\n", insilence);
2654:         printf(" Input Timeout:  %s\n", intime ? "Quit" : "Proceed");
2655: #ifndef NOSCRIPT
2656:         printf(" Script Echo:    %s\n", secho  ? "On" : "Off");
2657: #endif /* NOSCRIPT */
2658:         break;
2659: #endif /* NOSPL */
2660: 
2661: #ifndef NOXMIT
2662:       case SHXMI:
2663:         printf(" File type: %s\n", binary ? "binary" : "text");
2664: #ifndef NOCSETS
2665:         shotcs(tcsl,tcsr);
2666: #endif /* NOCSETS */
2667:         printf(" Terminal echo: %s\n", duplex ? "local" : "remote");
2668:             printf(" Transmit EOF: ");
2669:         if (*xmitbuf == NUL) {
2670:         printf("none\n");
2671:         } else {
2672:         char *p;
2673:         p = xmitbuf;
2674:         while (*p) {
2675:             if (*p < SP)
2676:               printf("^%c",ctl(*p));
2677:             else
2678:               printf("%c",*p);
2679:             p++;
2680:         }
2681:         printf("\n");
2682:         }
2683:         if (xmitf)
2684:           printf(" Transmit Fill: %d (fill character for blank lines)\n",
2685:            xmitf);
2686:         else printf(" Transmit Fill: none\n");
2687:         printf(" Transmit Linefeed: %s\n",
2688:            xmitl ? "on (send linefeeds too)" : "off");
2689:         if (xmitp)
2690:           printf(" Transmit Prompt: %d (host line end character)\n",xmitp);
2691:         else printf(" Transmit Prompt: none\n");
2692:         printf(" Transmit Echo: %s\n",
2693:            xmitx ? "on" : "off");
2694:         printf(" Transmit Locking-Shift: %s\n",xmits ? "on" : "off");
2695:         printf(" Transmit Pause: %d milliseconds\n", xmitw);
2696:         break;
2697: #endif /* NOXMIT */
2698: 
2699:       case SHMOD:           /* SHOW MODEM */
2700:         shmdmlin();
2701:         printf("\n");
2702:         shomdm();
2703:         break;
2704: 
2705: #ifndef MAC
2706:           case SHDFLT:
2707:         zsyscmd(PWDCMD);
2708:             break;
2709: #endif /* MAC */
2710: 
2711:           case SHESC:
2712:         printf(" Escape character: Ctrl-%c (ASCII %d, %s)\r\n",
2713:            ctl(escape), escape, (escape == 127 ? "DEL" : ccntab[escape]));
2714:         break;
2715: 
2716: #ifndef NODIAL
2717:       case SHDIA:
2718:         shmdmlin();
2719:         printf(", speed: ");
2720:         if ((zz = ttgspd()) < 0) {
2721:         printf("unknown\n");
2722:         } else {
2723:         if (zz == 8880) printf("75/1200\n"); else printf("%ld\n",zz);
2724:         }
2725:         doshodial();
2726:         if (carrier == CAR_OFF) s = "off";
2727:         else if (carrier == CAR_ON) s = "on";
2728:         else if (carrier == CAR_AUT) s = "auto";
2729:         else s = "unknown";
2730:         printf(" Carrier: %s", s);
2731:         if (carrier == CAR_ON) {
2732:         if (cdtimo) printf(", timeout: %d sec", cdtimo);
2733:         else printf(", timeout: none");
2734:         }
2735:         if (local
2736: #ifdef NETCONN
2737:         && !network
2738: #endif /* NETCONN */
2739:         ) {
2740:         printf("\n%s modem signals:\n",ttname);
2741:         shomdm();
2742:         } else printf("\n");
2743:         break;
2744: #endif /* NODIAL */
2745: 
2746: #ifdef VMS
2747:     case SHLBL:         /* Labeled file info */
2748:         sholbl();
2749:         break;
2750: #endif /* VMS */
2751: 
2752:     case SHCSE:         /* Character sets */
2753: #ifdef NOCSETS
2754:         printf(
2755: " Character set translation is not supported in this version of C-Kermit\n");
2756: #else
2757:         shocharset();
2758:             printf("\n Unknown-Char-Set: %s\n",
2759:            unkcs ? "Keep" : "Discard");
2760:         shotcs(tcsl,tcsr);
2761:         printf("\n");
2762: #endif /* NOCSETS */
2763:         break;
2764: 
2765: #ifndef NOFRILLS
2766:       case SHFEA:           /* Features */
2767:         shofea();
2768:         break;
2769: #endif /* NOFRILLS */
2770: 
2771:     default:
2772:         printf("\nNothing to show...\n");
2773:         return(-2);
2774:     }
2775:     return(success = 1);
2776: }
2777: 
2778: VOID
2779: shmdmlin() {                /* Briefly show modem & line */
2780:     int i;
2781: #ifndef NODIAL
2782: #ifndef MINIDIAL
2783:     extern int tbmodel;
2784:     _PROTOTYP( char * gtbmodel, (void) );
2785: #endif /* MINIDIAL */
2786: #endif /* NODIAL */
2787:     if (local)
2788:       printf(" Line: %s, Modem: ",ttname);
2789:     else
2790:       printf(" Communication device not yet selected with SET LINE\n Modem: ");
2791: #ifndef NODIAL
2792:     for (i = 0; i < nmdm; i++) {
2793:     if (mdmtab[i].kwval == mdmtyp) {
2794:         printf("%s",mdmtab[i].kwd);
2795:         break;
2796:     }
2797:     }
2798: #ifndef MINIDIAL
2799:     if (tbmodel) printf(" (%s)",gtbmodel()); /* Telebit model info */
2800: #endif /* MINIDIAL */
2801: #else
2802:     printf("(disabled)");
2803: #endif /* NODIAL */
2804: }
2805: #endif /* NOSHOW */
2806: 
2807: #ifdef GEMDOS
2808: isxdigit(c) int c; {
2809:     return(isdigit(c) ||
2810:        (c >= 'a' && c <= 'f') ||
2811:        (c >= 'A' && c <= 'F'));
2812: }
2813: #endif /* GEMDOS */
2814: 
2815: #ifndef NOSHOW
2816: #ifndef NOSPL
2817: int                 /* SHO MACROS */
2818: shomac(s1, s2) char *s1, *s2; {
2819:     int x, n, pp;
2820:     pp = 0;             /* Parenthesis counter */
2821: 
2822:     if (!s1)
2823:       return(0);
2824:     else
2825:       printf("\n%s = ",s1);     /* Print blank line and macro name */
2826:     slc++;              /* Count the line */
2827:     n = (int)strlen(s1) + 4;        /* Width of current line */
2828:     if (!s2) s2 = "(null definition)";
2829: 
2830:     while (x = *s2++) {         /* Loop thru definition */
2831:     if (x == '(') pp++;     /* Treat commas within parens */
2832:     if (x == ')') pp--;     /* as ordinary text */
2833:     if (pp < 0) pp = 0;     /* Outside parens, */
2834:     if (x == ',' && pp == 0) {  /* comma becomes comma-dash-NL. */
2835:         putchar(',');
2836:         putchar('-');
2837:         x = '\n';
2838:     }
2839:     putchar(x);         /* Output the character */
2840:     if (x == '\n') {        /* If it was a newline */
2841: #ifdef UNIX
2842: #ifdef NOSETBUF
2843:         fflush(stdout);
2844: #endif /* NOSETBUF */
2845: #endif /* UNIX */
2846:         putchar(' ');       /* Indent the next line 1 space */
2847:         while(*s2 == ' ') s2++; /* skip past leading blanks */
2848:         n = 2;          /* restart the character counter */
2849:         slc++;          /* and increment the line counter. */
2850:     } else if (++n > SCRNWID) { /* If line is too wide */
2851:         putchar('-');       /* output a dash */
2852:         putchar(NL);        /* and a newline */
2853: #ifdef UNIX
2854: #ifdef NOSETBUF
2855:         fflush(stdout);
2856: #endif /* NOSETBUF */
2857: #endif /* UNIX */
2858:         n = 1;          /* and restart the char counter */
2859:         slc++;          /* and increment the line counter */
2860:     }
2861:     if (n < 3 && slc > SCRNLEN) {   /* If new line and screen is full */
2862:         if (!askmore()) return(-1); /* ask if they want more. */
2863:         n = 1;          /* They do, start a new line */
2864:         slc = 0;            /* and restart line counter */
2865:     }
2866:     }
2867:     putchar(NL);            /* End of definition */
2868:     if (++slc > SCRNLEN) {
2869:     if (!askmore()) return(-1);
2870:     slc = 0;
2871:     }
2872:     return(0);
2873: }
2874: #endif /* NOSPL */
2875: #endif /* NOSHOW */
2876: 
2877: #ifndef NOSHOW
2878: int
2879: shoatt() {
2880:     printf("Attributes: %s\n", atcapr ? "On" : "Off");
2881:     if (!atcapr) return(0);
2882:     printf(" Blocksize: %s\n", atblki ? "On" : "Off");
2883:     printf(" Date: %s\n", atdati ? "On" : "Off");
2884:     printf(" Disposition: %s\n", atdisi ? "On" : "Off");
2885:     printf(" Encoding (Character Set): %s\n", atenci ? "On" : "Off");
2886:     printf(" Length: %s\n", atleni ? "On" : "Off");
2887:     printf(" Type (text/binary): %s\n", attypi ? "On" : "Off");
2888:     printf(" System ID: %s\n", atsidi ? "On" : "Off");
2889:     printf(" System Info: %s\n", atsysi ? "On" : "Off");
2890:     return(0);
2891: }
2892: #endif /* NOSHOW */
2893: 
2894: #ifndef NOSPL
2895: /* Evaluate an arithmetic expression. */
2896: /* Code adapted from ev, by Howie Kaye of Columbia U & others. */
2897: 
2898: static int xerror;
2899: static char *cp;
2900: static long tokval;
2901: static char curtok;
2902: static long expval;
2903: 
2904: #define LONGBITS (8*sizeof (long))
2905: #define NUMBER 'N'
2906: #define EOT 'E'
2907: 
2908: /*
2909:  Replacement for strchr() and index(), neither of which seem to be universal.
2910: */
2911: 
2912: static char *
2913: #ifdef CK_ANSIC
2914: windex(char * s, char c)
2915: #else
2916: windex(s,c) char *s, c;
2917: #endif /* CK_ANSIC */
2918: /* windex */ {
2919:     while (*s != NUL && *s != c) s++;
2920:     if (*s == c) return(s); else return(NULL);
2921: }
2922: 
2923: /*
2924:  g e t t o k
2925: 
2926:  Returns the next token.  If token is a NUMBER, sets tokval appropriately.
2927: */
2928: static char
2929: gettok() {
2930:     while (isspace(*cp)) cp++ ;
2931:     switch(*cp) {
2932:       case '$':             /* ??? */
2933:       case '+':             /* Add */
2934:       case '-':             /* Subtract or Negate */
2935:       case '@':             /* Greatest Common Divisor */
2936:       case '*':             /* Multiply */
2937:       case '/':             /* Divide */
2938:       case '%':             /* Modulus */
2939:       case '<':             /* Left shift */
2940:       case '>':             /* Right shift */
2941:       case '&':             /* And */
2942:       case '|':             /* Or */
2943:       case '#':             /* Exclusive Or */
2944:       case '~':             /* Not */
2945:       case '^':             /* Exponent */
2946:       case '!':             /* Factorial */
2947:       case '(':             /* Parens for grouping */
2948:       case ')': return(*cp++);      /* operator, just return it */
2949:       case '\n':
2950:       case '\0': return(EOT);       /* end of line, return that */
2951:     }
2952:     if (isxdigit(*cp)) {        /* digit, must be a number */
2953:     char tbuf[80],*tp;      /* buffer to accumulate number */
2954:     int radix = 10;         /* default radix */
2955:     for (tp=tbuf; isxdigit(*cp); cp++)
2956:       *tp++ = isupper(*cp) ? tolower(*cp) : *cp;
2957:     *tp = '\0';         /* end number */
2958:     switch(isupper(*cp) ? tolower(*cp) : *cp) { /* examine break char */
2959:       case 'h':
2960:       case 'x': radix = 16; cp++; break; /* if radix signifier... */
2961:       case 'o':
2962:       case 'q': radix = 8; cp++; break;
2963:       case 't': radix = 2; cp++; break;
2964:     }
2965:     for (tp=tbuf,tokval=0; *tp != '\0'; tp++)  {
2966:         int dig;
2967:         dig = *tp - '0';        /* convert number */
2968:         if (dig > 10) dig -= 'a'-'0'-10;
2969:         if (dig >= radix) {
2970:         xerror = 1;
2971:         if (cmdlvl == 0)
2972:           printf("invalid digit '%c' in number\n",*tp);
2973:         return(NUMBER);
2974:         }
2975:         tokval = radix*tokval + dig;
2976:     }
2977:     return(NUMBER);
2978:     }
2979:     if (cmdlvl == 0)
2980:       printf("Invalid character '%c' in input\n",*cp);
2981:     xerror = 1;
2982:     cp++;
2983:     return(gettok());
2984: }
2985: 
2986: static long
2987: #ifdef CK_ANSIC
2988: expon(long x, long y)
2989: #else
2990: expon(x,y) long x,y;
2991: #endif /* CK_ANSIC */
2992: /* expon */ {
2993:     long result = 1;
2994:     int sign = 1;
2995:     if (y < 0) return(0);
2996:     if (x < 0) {
2997:     x = -x;
2998:     if (y & 1) sign = -1;
2999:     }
3000:     while (y != 0) {
3001:     if (y & 1) result *= x;
3002:     y >>= 1;
3003:     if (y != 0) x *= x;
3004:   }
3005:   return(result * sign);
3006: }
3007: 
3008: /*
3009:  * factor ::= simple | simple ^ factor
3010:  *
3011:  */
3012: _PROTOTYP( static VOID simple, (void) );
3013: 
3014: static VOID
3015: factor() {
3016:     long oldval;
3017:     simple();
3018:     if (curtok == '^') {
3019:     oldval = expval;
3020:     curtok = gettok();
3021:     factor();
3022:     expval = expon(oldval,expval);
3023:     }
3024: }
3025: 
3026: /*
3027:  * termp ::= NULL | {*,/,%,&} factor termp
3028:  *
3029:  */
3030: static VOID
3031: termp() {
3032:     while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == '&') {
3033:     long oldval;
3034:     char op;
3035:     op = curtok;
3036:     curtok = gettok();      /* skip past operator */
3037:     oldval = expval;
3038:     factor();
3039:     switch(op) {
3040:       case '*': expval = oldval * expval; break;
3041:       case '/':
3042:         if (expval == 0) expval = -1; /* don't divide by 0 */
3043:         else expval = oldval / expval; break;
3044:       case '%': expval = oldval % expval; break;
3045:       case '&': expval = oldval & expval; break;
3046:     }
3047:     }
3048: }
3049: 
3050: static long
3051: #ifdef CK_ANSIC
3052: fact(long x)
3053: #else
3054: fact(x) long x;
3055: #endif /* CK_ANSIC */
3056: /* fact */ {                /* factorial */
3057:     long result = 1;
3058:     while (x > 1)
3059:       result *= x--;
3060:     return(result);
3061: }
3062: 
3063: /*
3064:  * term ::= factor termp
3065:  *
3066:  */
3067: static VOID
3068: term() {
3069:     factor();
3070:     termp();
3071: }
3072: 
3073: static long
3074: #ifdef CK_ANSIC
3075: gcd(long x, long y)
3076: #else
3077: gcd(x,y) long x,y;
3078: #endif /* CK_ANSIC */
3079: /* gcd */ {             /* Greatest Common Divisor */
3080:     int nshift = 0;
3081:     if (x < 0) x = -x;
3082:     if (y < 0) y = -y;          /* validate arguments */
3083:     if (x == 0 || y == 0) return(x + y);    /* this is bogus */
3084: 
3085:     while (!((x & 1) | (y & 1))) {  /* get rid of powers of 2 */
3086:     nshift++;
3087:     x >>= 1;
3088:     y >>= 1;
3089:     }
3090:     while (x != 1 && y != 1 && x != 0 && y != 0) {
3091:     while (!(x & 1)) x >>= 1;   /* eliminate unnecessary */
3092:     while (!(y & 1)) y >>= 1;   /* powers of 2 */
3093:     if (x < y) {            /* force x to be larger */
3094:         long t;
3095:         t = x;
3096:         x = y;
3097:         y = t;
3098:     }
3099:     x -= y;
3100:     }
3101:     if (x == 0 || y == 0) return((x + y) << nshift); /* gcd is non-zero one */
3102:     else return((long) 1 << nshift);    /* else gcd is 1 */
3103: }
3104: 
3105: /*
3106:  * exprp ::= NULL | {+,-,|,...} term exprp
3107:  *
3108:  */
3109: static VOID
3110: exprp() {
3111:     while (windex("+-|<>#@",curtok) != NULL) {
3112:     long oldval;
3113:     char op;
3114:     op = curtok;
3115:     curtok = gettok();      /* skip past operator */
3116:     oldval = expval;
3117:     term();
3118:     switch(op) {
3119:       case '+' : expval = oldval + expval; break;
3120:       case '-' : expval = oldval - expval; break;
3121:       case '|' : expval = oldval | expval; break;
3122:       case '#' : expval = oldval ^ expval; break;
3123:       case '@' : expval = gcd(oldval,expval); break;
3124:       case '<' : expval = oldval << expval; break;
3125:       case '>' : expval = oldval >> expval; break;
3126:     }
3127:     }
3128: }
3129: 
3130: /*
3131:  * expr ::= term exprp
3132:  *
3133:  */
3134: static VOID
3135: expr() {
3136:     term();
3137:     exprp();
3138: }
3139: 
3140: static long
3141: xparse() {
3142:     curtok = gettok();
3143:     expr();
3144: #ifdef COMMENT
3145:     if (curtok == '$') {
3146:     curtok = gettok();
3147:     if (curtok != NUMBER) {
3148:         if (cmdlvl == 0) printf("illegal radix\n");
3149:         return(0);
3150:     }
3151:     curtok = gettok();
3152:     }
3153: #endif /* COMMENT */
3154:     if (curtok != EOT) {
3155:     if (cmdlvl == 0)
3156:       printf("extra characters after expression\n");
3157:     xerror = 1;
3158:     }
3159:     return(expval);
3160: }
3161: 
3162: char *
3163: evala(s) char *s; {
3164:     char *p;                /* Return pointer */
3165:     long v;             /* Numeric value */
3166: 
3167:     xerror = 0;             /* Start out with no error */
3168:     cp = s;             /* Make the argument global */
3169:     v = xparse();           /* Parse the string */
3170:     p = numbuf;             /* Convert long number to string */
3171:     sprintf(p,"%ld",v);
3172:     return(xerror ? "" : p);        /* Return empty string on error */
3173: }
3174: 
3175: /*
3176:  * simplest ::= NUMBER | ( expr )
3177:  *
3178:  */
3179: static VOID
3180: simplest() {
3181:     if (curtok == NUMBER) expval = tokval;
3182:     else if (curtok == '(') {
3183:     curtok = gettok();      /* skip over paren */
3184:     expr();
3185:     if (curtok != ')') {
3186:         if (cmdlvl == 0) printf("missing right parenthesis\n");
3187:         xerror = 1;
3188:     }
3189:     }
3190:     else {
3191:     if (cmdlvl == 0) printf("operator unexpected\n");
3192:     xerror = 1;
3193:     }
3194:     curtok = gettok();
3195: }
3196: 
3197: /*
3198:  * simpler ::= simplest | simplest !
3199:  *
3200:  */
3201: static VOID
3202: simpler() {
3203:     simplest();
3204:     if (curtok == '!') {
3205:     curtok = gettok();
3206:     expval = fact(expval);
3207:     }
3208: }
3209: 
3210: /*
3211:  * simple ::= {-,~} simpler | simpler
3212:  *
3213:  */
3214: 
3215: static VOID
3216: simple() {
3217:     if (curtok == '-' || curtok == '~') {
3218:     int op = curtok;
3219:     curtok = gettok();      /* skip over - sign */
3220:     simpler();          /* parse the factor again */
3221:     expval = op == '-' ? -expval : ~expval;
3222:     } else simpler();
3223: }
3224: #endif /* NOSPL */
3225: 
3226: #ifndef NOSPL
3227: /*  D C L A R R A Y  --  Declare an array  */
3228: 
3229: int                 /* Declare an array of size n */
3230: #ifdef CK_ANSIC
3231: dclarray(char a, int n)
3232: #else
3233: dclarray(a,n) char a; int n;
3234: #endif /* CK_ANSIC */
3235: /* dclarray */ {
3236:     char **p; int i, n2;
3237: 
3238:     if (a > 63 && a < 96) a += 32;  /* Convert to lowercase */
3239:     if (a < 96 || a > 122) return(-1);  /* Verify name */
3240:     a -= 96;                /* Convert name to number */
3241:     if ((p = a_ptr[a]) != NULL) {   /* Delete old array of same name */
3242:     n2 = a_dim[a];
3243:     for (i = 0; i <= n2; i++)   /* First delete its elements */
3244:       if (p[i]) free(p[i]);
3245:     free(a_ptr[a]);         /* Then the element list */
3246:     a_ptr[a] = (char **) NULL;  /* Remove pointer to element list */
3247:     a_dim[a] = 0;           /* Set dimension at zero. */
3248:     }
3249:     if (n == 0) return(0);      /* If dimension 0, just deallocate. */
3250: 
3251:     p = (char **) malloc((n+1) * sizeof(char **)); /* Allocate for new array */
3252:     if (p == NULL) return(-1);      /* Check */
3253:     a_ptr[a] = p;           /* Save pointer to member list */
3254:     a_dim[a] = n;           /* Save dimension */
3255:     for (i = 0; i <= n; i++)        /* Initialize members to null */
3256:       p[i] = NULL;
3257:     return(0);
3258: }
3259: 
3260: /*  A R R A Y N A M  --  Parse an array name  */
3261: 
3262: /*
3263:   Call with pointer to string that starts with the array reference.
3264:   String may begin with either \& or just &.
3265:   On success,
3266:     Returns letter ID (always lowercase) in argument c,
3267:       which can also be accent grave (` = 96; '@' is converted to grave);
3268:     Dimension or subscript in argument n;
3269:     IMPORTANT: These arguments must be provided by the caller as addresses
3270:     of ints (not chars), for example:
3271:       char *s; int x, y;
3272:       arraynam(s,&x,&y);
3273:   On failure, returns a negative number, with args n and c set to zero.
3274: */
3275: int
3276: arraynam(ss,c,n) char *ss; int *c; int *n; {
3277:     int i, y, pp;
3278:     char x;
3279:     char *s, *p, *sx, *vnp;
3280:     char vnbuf[VNAML+1];        /* On stack to allow for */
3281:     char ssbuf[VNAML+1];        /* recursive calls... */
3282:     char sxbuf[VNAML+1];
3283: 
3284:     *c = *n = 0;            /* Initialize return values */
3285:     for (i = 0; i < (int)strlen(ss); i++) /* Check length */
3286:       if (ss[i] == ']')
3287:     break;
3288:     if (i > VNAML) {
3289:     printf("?Array reference too long - %s\n",ss);
3290:     return(-9);
3291:     }
3292:     strncpy(vnbuf,ss,VNAML);
3293:     vnp = vnbuf;
3294:     if (vnbuf[0] == CMDQ && vnbuf[1] == '&') vnp++;
3295:     if (*vnp != '&') {
3296:     printf("?Not an array - %s\n",vnbuf);
3297:     return(-9);
3298:     }
3299:     x = *(vnp + 1);         /* Fold case of array name */
3300:     /* We don't use isupper & tolower here on purpose because these */
3301:     /* would produce undesired effects with accented letters. */
3302:     if (x > 63 && x < 91) x  = *(vnp +1) = x + 32;
3303:     if ((x < 96) || (x > 122) || (*(vnp+2) != '[')) {
3304:     printf("?Invalid format for array name - %s\n",vnbuf);
3305:     return(-9);
3306:     }
3307:     *c = x;             /* Return the array name */
3308:     s = vnp+3;              /* Get dimension */
3309:     p = ssbuf;
3310:     pp = 1;             /* Bracket counter */
3311:     for (i = 0; i < VNAML && *s != NUL; i++) { /* Copy up to ] */
3312:     if (*s == '[') pp++;
3313:     if (*s == ']' && --pp == 0) break;
3314:     *p++ = *s++;
3315:     }
3316:     if (*s != ']') {
3317:     printf("?No closing bracket on array dimension - %s\n",vnbuf);
3318:     return(-9);
3319:     }
3320:     *p = NUL;               /* Terminate subscript with null */
3321:     p = ssbuf;              /* Point to beginning of subscript */
3322:     sx = sxbuf;             /* Where to put expanded subscript */
3323:     y = VNAML-1;
3324:     xxstring(p,&sx,&y);         /* Convert variables, etc. */
3325:     if (!chknum(sxbuf)) {       /* Make sure it's all digits */
3326:     printf("?Array dimension or subscript must be numeric - %s\n",sxbuf);
3327:     return(-9);
3328:     }
3329:     if ((y = atoi(sxbuf)) < 0) {
3330:         if (cmflgs == 0) printf("\n");
3331:         printf("?Array dimension or subscript must be positive or zero - %s\n",
3332:            sxbuf);
3333:     return(-9);
3334:     }
3335:     *n = y;             /* Return the subscript or dimension */
3336:     return(0);
3337: }
3338: 
3339: int
3340: chkarray(a,i) int a, i; {       /* Check if array is declared */
3341:     int x;              /* and if subscript is in range */
3342:     if (a == 64) a = 96;        /* Convert atsign to grave accent */
3343:     x = a - 96;             /* Values must be in range 96-122 */
3344:     if (x < 0 || x > 26) return(-2);    /* Not in range */
3345:     if (a_ptr[x] == NULL) return(-1);   /* Not declared */
3346:     if (i > a_dim[x]) return(-2);   /* Declared but out of range. */
3347:     return(a_dim[x]);           /* All ok, return dimension */
3348: }
3349: 
3350: char *
3351: arrayval(a,i) int a, i; {       /* Return value of \&a[i] */
3352:     int x; char **p;            /* (possibly NULL) */
3353: 
3354:     if (a == 64) a = 96;        /* Convert atsign to grave accent */
3355:     x = a - 96;             /* Values must be in range 96-122 */
3356:     if (x < 0 || x > 26) return(NULL);  /* Not in range */
3357:     if ((p = a_ptr[x]) == NULL)     /* Array not declared */
3358:       return(NULL);
3359:     if (i > a_dim[x])           /* Subscript out of range. */
3360:       return(NULL);
3361:     return(p[i]);           /* All ok, return pointer to value. */
3362: }
3363: #endif /* NOSPL */
3364: 
3365: #ifndef NOSPL
3366: /*  P A R S E V A R  --  Parse a variable name or array reference.  */
3367: /*
3368:  Call with:
3369:    s  = pointer to candidate variable name or array reference.
3370:    *c = address of integer in which to return variable ID.
3371:    *i = address of integer in which to return array subscript.
3372:  Returns:
3373:    -2:  syntax error in variable name or array reference.
3374:     1:  successful parse of a simple variable, with ID in c.
3375:     2:  successful parse of an array reference, w/ID in c and subscript in i.
3376: */
3377: int
3378: parsevar(s,c,i) char *s; int *c, *i; {
3379:     char *p;
3380:     int x,y,z;
3381: 
3382:     p = s;
3383:     if (*s == CMDQ) s++;        /* Point after backslash */
3384: 
3385:     if (*s != '%' && *s != '&') {   /* Make sure it's % or & */
3386:     printf("?Not a variable name - %s\n",p);
3387:     return(-9);
3388:     }
3389:     if ((int)strlen(s) < 2) {
3390:     printf("?Incomplete variable name - %s\n",p);
3391:     return(-9);
3392:     }
3393:     if (*s == '%' && *(s+2) != '\0') {
3394:     printf("?Only one character after '%%' in variable name, please\n");
3395:     return(-9);
3396:     }
3397:     if (*s == '&' && *(s+2) != '[') {
3398:     printf("?Array subscript expected - %s\n",p);
3399:     return(-9);
3400:     }
3401:     if (*s == '%') {            /* Simple variable. */
3402:     y = *(s+1);         /* Get variable ID letter/char */
3403:     if (isupper(y)) y -= ('a'-'A'); /* Convert upper to lower case */
3404:     *c = y;             /* Set the return values. */
3405:     *i = -1;            /* No array subscript. */
3406:     return(1);          /* Return 1 = simple variable */
3407:     }
3408:     if (*s == '&') {            /* Array reference. */
3409:     if (arraynam(s,&x,&z) < 0) { /* Go parse it. */
3410:         printf("?Invalid array reference - %s\n",p);
3411:         return(-9);
3412:     }
3413:     if (chkarray(x,z) < 0) {    /* Check if declared, etc. */
3414:         printf("?Array not declared or subscript out of range\n");
3415:         return(-9);
3416:     }
3417:     *c = x;             /* Return array letter */
3418:     *i = z;             /* and subscript. */
3419:     return(2);
3420:     }
3421:     return(-2);             /* None of the above. */
3422: }
3423: 
3424: #define VALN 20
3425: 
3426: /* Get the numeric value of a variable */
3427: /*
3428:   Call with pointer to variable name, pointer to int for return value.
3429:   Returns:
3430:     0 on success with second arg containing the value.
3431:    -1 on failure (bad variable syntax, variable not defined or not numeric).
3432: */
3433: int
3434: varval(s,v) char *s; int *v; {
3435:     char valbuf[VALN+1];        /* s is pointer to variable name */
3436:     char *p;
3437:     int y;
3438: 
3439:     p = valbuf;             /* Expand variable into valbuf. */
3440:     y = VALN;
3441:     if (xxstring(s,&p,&y) < 0) return(-1);
3442:     p = valbuf;             /* Make sure value is numeric */
3443:     if (!chknum(p)) return(-1);
3444:     *v = atoi(p);           /* Convert numeric string to int */
3445:     return(0);
3446: }
3447: 
3448: /* Increment or decrement a variable */
3449: /* Returns -1 on failure, 0 on success, with 4th argument set to result */
3450: 
3451: int
3452: incvar(s,x,z,r) char *s; int x, z, *r; { /* Increment a numeric variable */
3453:     char valbuf[VALN+1];        /* s is pointer to variable name */
3454:                     /* x is amount to increment by */
3455:     int n;              /* z != 0 means add */
3456:                     /* z = 0 means subtract */
3457: 
3458:     if (varval(s,&n) < 0)       /* Convert numeric string to int */
3459:       return(-1);
3460:     if (z)              /* Increment it by the given amount */
3461:       n += x;
3462:     else                /* or decrement as requested. */
3463:       n -= x;
3464:     sprintf(valbuf,"%d",n);     /* Convert back to numeric string */
3465:     addmac(s,valbuf);           /* Replace old variable */
3466:     *r = n;             /* Return the integer value */
3467:     return(0);
3468: }
3469: #endif /* NOSPL */
3470: 
3471: /* Functions moved here from ckuusr.c to even out the module sizes... */
3472: 
3473: #ifndef NOSPL               /* Need xwords() function to break */
3474: #define XWORDS              /* string up into words. */
3475: #endif /* NOSPL */
3476: #ifndef NODIAL
3477: #ifndef XWORDS
3478: #define XWORDS
3479: #endif /* XWORDS */
3480: #endif /* NODIAL */
3481: 
3482: #ifdef XWORDS
3483: /*
3484:   Breaks string s up into a list of up to max words.
3485:   Pointers to each word go into the array list[].
3486:   If list is NULL, then they are added to the macro table.
3487: */
3488: 
3489: VOID
3490: xwords(s,max,list) char *s; int max; char *list[]; {
3491:     char *p;
3492:     int b, k, y, z;
3493: #ifndef NOSPL
3494:     int macro;
3495:     macro = (list == NULL);
3496:     debug(F101,"xwords macro","",macro);
3497: #endif /* NOSPL */
3498: 
3499:     p = s;              /* Pointer to beginning of string */
3500:     b = 0;              /* Flag for outer brace removal */
3501:     k = 0;              /* Flag for in-word */
3502:     y = 0;              /* Brace nesting level */
3503:     z = 0;              /* Argument counter, 0 thru max */
3504: 
3505:     while (1) {             /* Go thru argument list */
3506:     if (!s || (*s == '\0')) {   /* No more characters? */
3507:         if (k != 0) {
3508:         if (z == max) break;    /* Only go up to max. */
3509:         z++;            /* Count it. */
3510: #ifndef NOSPL
3511:         if (macro) {
3512:             varnam[1] = z + '0'; /* Assign last argument */
3513:             addmac(varnam,p);
3514:         } else
3515: #endif /* NOSPL */
3516:           list[z] = p;
3517:         break;          /* And get out. */
3518:         } else break;
3519:     }
3520:     if (k == 0 && (*s == SP || *s == HT)) { /* Eat leading blanks */
3521:         s++;
3522:         continue;
3523:     } else if (*s == '{') {     /* An opening brace */
3524:         if (k == 0 && y == 0) { /* If leading brace */
3525:         p = s+1;        /* point past it */
3526:         b = 1;          /* and flag that we did this */
3527:         }
3528:         k = 1;          /* Flag that we're in a word */
3529:         y++;            /* Count the brace. */
3530:     } else if (*s == '}') {     /* A closing brace. */
3531:         y--;            /* Count it. */
3532:         if (y == 0 && b != 0) { /* If it matches the leading brace */
3533:         *s = SP;        /* change it to a space */
3534:         b = 0;          /* and we're not in braces any more */
3535:         } else if (y < 0) k = 1;    /* otherwise just start a new word. */
3536:     } else if (*s != SP && *s != HT) { /* Nonspace means we're in a word */
3537:         if (k == 0) p = s;      /* Mark the beginning */
3538:         k = 1;          /* Set in-word flag */
3539:     }
3540:     /* If we're not inside a braced quantity, and we are in a word, and */
3541:     /* we have hit whitespace, then we have an argument to assign. */
3542:     if ((y < 1) && (k != 0) && (*s == SP || *s == HT)) {
3543:         *s = '\0';          /* terminate the arg with null */
3544:         k = 0;          /* say we're not in a word any more */
3545:         y = 0;          /* start braces off clean again */
3546:         if (z == max) break;    /* Only go up to max. */
3547:         z++;            /* count this arg */
3548: #ifndef NOSPL
3549:         if (macro) {
3550:         varnam[1] = z + '0';    /* compute its name */
3551:         addmac(varnam,p);   /* add it to the macro table */
3552:         } else
3553: #endif /* NOSPL */
3554:           list[z] = p;
3555:         p = s+1;
3556:     }
3557:     s++;                /* Point past this character */
3558:     }
3559:     if ((z == 0) && (y > 1)) {      /* Extra closing brace(s) at end */
3560:     z++;
3561: #ifndef NOSPL
3562:     if (macro) {
3563:         varnam[1] = z + '0';    /* compute its name */
3564:         addmac(varnam,p);       /* Add rest of line to last arg */
3565:     } else
3566: #endif /* NOSPL */
3567:       list[z] = p;
3568:     }
3569: #ifndef NOSPL
3570:     if (macro) macargc[maclvl] = z + 1; /* Set \v(argc) variable */
3571: #endif /* NOSPL */
3572:     return;
3573: }
3574: #endif /* XWORDS */
3575: 
3576: #ifndef NOSPL
3577: /* D O D O  --  Do a macro */
3578: 
3579: /*
3580:   Call with x = macro table index, s = pointer to arguments.
3581:   Returns 0 on failure, 1 on success.
3582: */
3583: 
3584: int
3585: dodo(x,s) int x; char *s; {
3586:     int y;
3587: 
3588:     debug(F101,"dodo maclvl","",maclvl);
3589:     if (++maclvl > MACLEVEL) {      /* Make sure we have storage */
3590:         debug(F101,"dodo maclvl too deep","",maclvl);
3591:     --maclvl;
3592:     printf("Macros nested too deeply\n");
3593:     return(0);
3594:     }
3595:     macp[maclvl] = mactab[x].mval;  /* Point to the macro body */
3596:     macx[maclvl] = mactab[x].mval;  /* Remember where the beginning is */
3597:     debug(F111,"do macro",macp[maclvl],maclvl);
3598: 
3599:     cmdlvl++;               /* Entering a new command level */
3600:     if (cmdlvl > CMDSTKL) {     /* Too many macros + TAKE files? */
3601:         debug(F101,"dodo cmdlvl too deep","",cmdlvl);
3602:     cmdlvl--;
3603:     printf("?TAKE files and DO commands nested too deeply\n");
3604:     return(0);
3605:     }
3606: #ifdef VMS
3607:     conres();               /* So Ctrl-C, etc, will work. */
3608: #endif /* VMS */
3609:     ifcmd[cmdlvl] = 0;
3610:     iftest[cmdlvl] = 0;
3611:     count[cmdlvl] = 0;
3612:     cmdstk[cmdlvl].src = CMD_MD;    /* Say we're in a macro */
3613:     cmdstk[cmdlvl].lvl = maclvl;    /* and remember the macro level */
3614:     mrval[maclvl] = NULL;       /* Initialize return value */
3615: 
3616:     debug(F110,"do macro",mactab[x].kwd,0);
3617: 
3618: /* Clear old %0..%9 arguments */
3619: 
3620:     addmac("%0",mactab[x].kwd);     /* Define %0 = name of macro */
3621:     varnam[0] = '%';
3622:     varnam[2] = '\0';
3623:     for (y = 1; y < 10; y++) {      /* Clear args %1..%9 */
3624:     varnam[1] = y + '0';
3625:     delmac(varnam);
3626:     }
3627: 
3628: /* Assign the new args one word per arg, allowing braces to group words */
3629: 
3630:     xwords(s,9,NULL);
3631:     return(1);
3632: }
3633: 
3634: /* Insert "literal" quote around each comma-separated command to prevent */
3635: /* its premature expansion.  Only do this if object command is surrounded */
3636: /* by braces. */
3637: 
3638: static char* flit = "\\flit(";
3639: 
3640: int
3641: litcmd(src,dest) char **src, **dest; {
3642:     int bc = 0, pp = 0;
3643:     char *s, *lp, *ss;
3644: 
3645:     s = *src;
3646:     lp = *dest;
3647: 
3648:     while (*s == SP) s++;       /* strip extra leading spaces */
3649:     if (*s == '{') {
3650: 
3651:         pp = 0;             /* paren counter */
3652:     bc = 1;             /* count leading brace */
3653:     *lp++ = *s++;           /* copy it */
3654:     while (*s == SP) s++;       /* strip interior leading spaces */
3655:     ss = flit;          /* point to "\flit(" */
3656:     while (*lp++ = *ss++) ;     /* copy it */
3657:     lp--;               /* back up over null */
3658:     while (*s) {            /* go thru rest of text */
3659:         ss = flit;          /* point back to start of "\flit(" */
3660:         if (*s == '{') bc++;    /* count brackets */
3661:         if (*s == '(') pp++;    /* and parens */
3662:         if (*s == ')') pp--;
3663:         if (*s == '}') {        /* Closing brace. */
3664:         if (--bc == 0) {    /* Final one? */
3665:             *lp++ = ')';    /* Add closing paren for "\flit()" */
3666:             *lp++ = *s++;
3667:             break;
3668:         }
3669:         }
3670:         if (*s == ',' && pp == 0) { /* comma not inside of parens */
3671:         *lp++ = ')';        /* closing ) of \flit( */
3672:         *lp++ = ',';        /* insert the comma */
3673:         while (*lp++ = *ss++) ; /* start new "\flit(" */
3674:         lp--;           /* back up over null */
3675:         s++;            /* skip over comma in source string */
3676:         while (*s++ == SP); /* eat leading spaces again. */
3677:         s--;            /* back up over nonspace */
3678:         continue;
3679:         }
3680:             *lp++ = *s++;       /* Copy anything but comma here. */
3681:         }
3682:     *lp = NUL;
3683:     } else {                /* No brackets around, */
3684:     while (*lp++ = *s++) ;      /* just copy. */
3685:     lp--;
3686:     }
3687:     *src = s;
3688:     *dest = lp;
3689:     if (bc) return(-1);
3690:     else return(0);
3691: }
3692: #endif /* NOSPL */
3693: 
3694: int
3695: docd() {                /* Do the CD command */
3696:     int x;
3697:     char *s;
3698: 
3699: #ifdef GEMDOS
3700:     if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
3701:            NULL)) < 0 )
3702: #else
3703:     if ((x = cmdir("Name of local directory, or carriage return",homdir,&s,
3704:            xxstring)) < 0 )
3705: #endif /* GEMDOS */
3706:       return(x);
3707:     if (x == 2) {
3708:     printf("?Wildcards not allowed in directory name\n");
3709:     return(-9);
3710:     }
3711:     strcpy(line,s);         /* Make a safe copy */
3712:     s = line;
3713:     if ((x = cmcfm()) < 0)      /* Get confirmation */
3714:       return(x);
3715:     if (! zchdir(s)) {
3716:     cwdf = 0;
3717:     perror(s);
3718:     } else cwdf = 1;
3719: #ifdef OS2
3720:     printf("%s\n", zgtdir());
3721: #else /* Not OS2 */
3722: #ifndef MAC
3723:     zsyscmd(PWDCMD);            /* assume this works... */
3724: #endif /* MAC */
3725: #endif /* OS2 */
3726:     return(cwdf);
3727: }
3728: 
3729: VOID
3730: fixcmd() {          /* Fix command parser after interruption */
3731:     dostop();           /* Back to top level (also calls conint()). */
3732:     bgchk();            /* Check background status */
3733:     if (*psave) {       /* If old prompt saved, */
3734:     cmsetp(psave);      /* restore it. */
3735:     *psave = NUL;
3736:     }
3737:     success = 0;        /* Tell parser last command failed */
3738: }
3739: 
3740: VOID
3741: prtopt(s) char *s; {            /* Print an option */
3742:     static int x = 0;           /* (used by SHOW VER) */
3743:     int y;              /* Does word wrap. */
3744:     if (!s) { x = 0; return; }      /* Call with null pointer to */
3745:     y = (int)strlen(s);         /* reset horizontal position. */
3746:     x += y;
3747:     if (x > 79) {
3748:     printf("\n%s",s);
3749:     x = y;
3750:     } else printf("%s",s);
3751: }
3752: 
3753: #endif /* NOICP */

Defined functions

addmac defined in line 1238; used 15 times
addmmac defined in line 1201; used 6 times
arrayval defined in line 3350; used 1 times
chkarray defined in line 3339; used 5 times
cmdini defined in line 322; used 2 times
dclarray defined in line 3229; used 2 times
delmac defined in line 1356; used 7 times
dooutput defined in line 1053; used 1 times
doshow defined in line 2325; used 1 times
dostop defined in line 1505; used 5 times
evala defined in line 3162; used 1 times
expon defined in line 2986; used 2 times
expr defined in line 3134; used 2 times
exprp defined in line 3109; used 1 times
fact defined in line 3050; used 2 times
factor defined in line 3014; used 3 times
fixcmd defined in line 3729; used 1 times
gcd defined in line 3073; used 2 times
getncm defined in line 546; used 3 times
getnct defined in line 608; used 3 times
gettok defined in line 2928; used 11 times
herald defined in line 1119; used 1 times
incvar defined in line 3451; used 1 times
initmac defined in line 1421; used 1 times
isxdigit defined in line 2808; never used
litcmd defined in line 3640; used 4 times
macini defined in line 309; used 1 times
mxlook defined in line 1183; used 2 times
parsevar defined in line 3377; used 4 times
popclvl defined in line 1486; used 16 times
prtopt defined in line 3740; used 173 times
shmdmlin defined in line 2778; used 2 times
shoatt defined in line 2878; used 1 times
shofea defined in line 1615; used 1 times
sholbl defined in line 2251; used 1 times
shomac defined in line 2817; used 4 times
shotcs defined in line 2273; used 3 times
shover defined in line 1588; used 1 times
simple defined in line 3215; used 2 times
simpler defined in line 3201; used 2 times
simplest defined in line 3179; used 1 times
term defined in line 3067; used 2 times
termp defined in line 3030; used 1 times
varval defined in line 3433; used 1 times
windex defined in line 2912; used 1 times
xparse defined in line 3140; used 1 times
xwords defined in line 3489; used 2 times
xxout defined in line 1038; used 3 times

Defined variables

VOID defined in line 3740; never used
a_dim defined in line 257; used 12 times
a_ptr defined in line 256; used 13 times
cp defined in line 2899; used 19 times
curtok defined in line 2901; used 28 times
expval defined in line 2902; used 36 times
flit defined in line 3638; used 2 times
for_def defined in line 187; used 2 times
g_var defined in line 251; used 14 times
homdir defined in line 298; used 6 times
ifcmd defined in line 247; used 18 times
iftest defined in line 247; used 10 times
inchar defined in line 261; used 3 times
incount defined in line 262; used 4 times
inpbuf defined in line 259; used 9 times
inpbufa defined in line 260; never used
kermrc defined in line 302; used 12 times
keymap defined in line 132; used 9 times
lblbuf defined in line 264; used 2 times
line defined in line 270; used 192 times
m_fat defined in line 159; used 1 times
m_forx defined in line 168; never used
m_ibm defined in line 156; used 1 times
m_while defined in line 175; never used
m_xif defined in line 180; never used
macp defined in line 251; used 9 times
macrotab defined in line 133; used 12 times
macx defined in line 253; used 5 times
mrval defined in line 251; used 13 times
nm defined in line 1579; used 12 times
noinit defined in line 303; used 3 times
nulcmd defined in line 149; used 2 times
numbuf defined in line 301; used 1 times
old_for_def defined in line 200; never used
old_whil_def defined in line 219; never used
old_xif_def defined in line 233; never used
slc defined in line 1583; used 11 times
tfnam defined in line 144; used 19 times
tokval defined in line 2900; used 4 times
tp defined in line 300; used 50 times
trmbuf defined in line 280; used 2 times
whil_def defined in line 210; used 2 times
xerror defined in line 2898; used 7 times
xif_def defined in line 227; used 2 times

Defined macros

EOT defined in line 2906; used 2 times
LONGBITS defined in line 2904; never used
NUMBER defined in line 2905; used 4 times
SCRNLEN defined in line 32; used 3 times
SCRNWID defined in line 33; used 1 times
TRMBUFL defined in line 275; used 3 times
VALN defined in line 3424; used 3 times
XWORDS defined in line 3478; used 2 times
fclose defined in line 44; used 2 times
feof defined in line 40; used 3 times
fgets defined in line 42; used 1 times
fopen defined in line 43; used 3 times
isxdigit defined in line 36; used 2 times
rewind defined in line 41; never used
xxdiff defined in line 1587; used 2 times
Last modified: 1992-11-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 15642
Valid CSS Valid XHTML 1.0 Strict