Annotation of coherent/e/bin/cku179/ckucmd.c, revision 1.1

1.1     ! root        1: int cmdmsk = 127; /* Command-terminal-to-C-Kermit character mask */
        !             2: 
        !             3: #include "ckcdeb.h"                     /* Formats for debug(), etc. */
        !             4: _PROTOTYP( int unhex, (char) );
        !             5: 
        !             6: #ifndef NOICP     /* The rest only if interactive command parsing selected */
        !             7: 
        !             8: char *cmdv = "Command package 5A(048), 8 Feb 92";
        !             9:  
        !            10: /*  C K U C M D  --  Interactive command package for Unix  */
        !            11: 
        !            12: /*
        !            13:  Author: Frank da Cruz ([email protected], [email protected]),
        !            14:  Columbia University Center for Computing Activities.
        !            15:  First released January 1985.
        !            16:  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New 
        !            17:  York.  Permission is granted to any individual or institution to use, copy, or
        !            18:  redistribute this software so long as it is not sold for profit, provided this
        !            19:  copyright notice is retained. 
        !            20: */
        !            21: 
        !            22: /*
        !            23: Modelled after the DECSYSTEM-20 command parser (the COMND JSYS), RIP.
        !            24: Features:
        !            25: . parses and verifies keywords, filenames, text strings, numbers, other data
        !            26: . displays appropriate menu or help message when user types "?"
        !            27: . does keyword and filename completion when user types ESC or TAB
        !            28: . does partial filename completion
        !            29: . accepts any unique abbreviation for a keyword
        !            30: . allows keywords to have attributes, like "invisible" and "abbreviation"
        !            31: . can supply defaults for fields omitted by user
        !            32: . provides command line editing (character, word, and line deletion)
        !            33: . accepts input from keyboard, command files, or redirected stdin
        !            34: . allows for full or half duplex operation, character or line input
        !            35: . settable prompt, protected from deletion
        !            36: 
        !            37: Functions:
        !            38:  cmsetp - Set prompt (cmprom is prompt string)
        !            39:  cmsavp - Save current prompt
        !            40:  prompt - Issue prompt
        !            41:  cmini - Clear the command buffer (before parsing a new command)
        !            42:  cmres - Reset command buffer pointers (before reparsing)
        !            43:  cmkey - Parse a keyword
        !            44:  cmnum - Parse a number
        !            45:  cmifi - Parse an input file name
        !            46:  cmofi - Parse an output file name
        !            47:  cmdir - Parse a directory name (UNIX only)
        !            48:  cmfld - Parse an arbitrary field
        !            49:  cmtxt - Parse a text string
        !            50:  cmcfm - Parse command confirmation (end of line)
        !            51: 
        !            52: Return codes:
        !            53:  -3: no input provided when required
        !            54:  -2: input was invalid (e.g. not a number when a number was required)
        !            55:  -1: reparse required (user deleted into a preceding field)
        !            56:   0 or greater: success
        !            57: See individual functions for greater detail.
        !            58: 
        !            59: Before using these routines, the caller should #include ckucmd.h, and set the
        !            60: program's prompt by calling cmsetp().  If the file parsing functions cmifi,
        !            61: cmofi, or cmdir are to be used, this module must be linked with a ck?fio file
        !            62: system support module for the appropriate system, e.g. ckufio for Unix.  If
        !            63: the caller puts the terminal in character wakeup ("cbreak") mode with no echo,
        !            64: then these functions will provide line editing -- character, word, and line
        !            65: deletion, as well as keyword and filename completion upon ESC and help
        !            66: strings, keyword, or file menus upon '?'.  If the caller puts the terminal
        !            67: into character wakeup/noecho mode, care should be taken to restore it before
        !            68: exit from or interruption of the program.  If the character wakeup mode is not
        !            69: set, the system's own line editor may be used.
        !            70: 
        !            71: NOTE: Contrary to expectations, many #ifdef's have been added to this module.
        !            72: Any operation requiring an #ifdef (like clear screen, get character from
        !            73: keyboard, erase character from screen, etc) should eventually be turned into a
        !            74: call to a function that is defined in ck?tio.c, but then all the ck?tio.c
        !            75: modules would have to be changed...
        !            76: */
        !            77: 
        !            78: /* Includes */
        !            79: 
        !            80: #include "ckcker.h"                    /* (===OS2 addition===) */
        !            81: #include "ckcasc.h"                    /* ASCII character symbols */
        !            82: #include "ckucmd.h"                     /* Command parsing definitions */
        !            83: #include <errno.h>                     /* Error number symbols */
        !            84: 
        !            85: #ifdef OSK
        !            86: #define cc ccount                      /* OS-9/68K compiler bug */
        !            87: #endif /* OSK */
        !            88: 
        !            89: #ifdef GEMDOS                          /* Atari ST */
        !            90: #ifdef putchar
        !            91: #undef putchar
        !            92: #endif /* putchar */
        !            93: #define putchar(x) conoc(x)            /* Why doesn't everyone do this? */
        !            94: #endif /* GEMDOS */
        !            95: 
        !            96: /* Local variables */
        !            97:  
        !            98: int psetf = 0,                          /* Flag that prompt has been set */
        !            99:     cc = 0,                             /* Character count */
        !           100:     dpx = 0;                            /* Duplex (0 = full) */
        !           101:  
        !           102: int hw = HLPLW,                         /* Help line width */
        !           103:     hc = HLPCW,                         /* Help line column width */
        !           104:     hh,                                 /* Current help column number */
        !           105:     hx;                                 /* Current help line position */
        !           106:  
        !           107: #define PROML 160                       /* Maximum length for prompt */
        !           108:  
        !           109: char cmprom[PROML+1];                   /* Program's prompt */
        !           110: char cmprxx[PROML+1];                   /* Program's prompt, unevaluated */
        !           111: char *dfprom = "Command? ";             /* Default prompt */
        !           112:  
        !           113: int cmflgs;                             /* Command flags */
        !           114: int cmfsav;                            /* A saved version of them */
        !           115:  
        !           116: #ifdef DCMDBUF
        !           117: char *cmdbuf;                          /* Command buffer */                
        !           118: char *savbuf;                          /* Help string buffer */            
        !           119: char *hlpbuf;                          /* Atom buffer */                   
        !           120: char *atmbuf;                          /* File name buffer */              
        !           121: char *atxbuf;                          /* For expanding the atom buffer */ 
        !           122: int atxn;                              /* Length of expansion buffer */    
        !           123: char *atybuf;                          /* For copying atom buffer */       
        !           124: char *filbuf;                          /* Buffer to save copy of command */
        !           125: #else
        !           126: char cmdbuf[CMDBL+4];                   /* Command buffer */                
        !           127: char hlpbuf[HLPBL+4];                   /* Help string buffer */            
        !           128: char atmbuf[ATMBL+4];                   /* Atom buffer */                   
        !           129: char filbuf[ATMBL+4];                   /* File name buffer */              
        !           130: char atxbuf[CMDBL+4];                   /* For expanding the atom buffer */ 
        !           131: int atxn;                              /* Length of expansion buffer */    
        !           132: char atybuf[ATMBL+4];                   /* For copying atom buffer */       
        !           133: char savbuf[CMDBL+4];                   /* Buffer to save copy of command */
        !           134: #endif /* COMMENT */
        !           135:  
        !           136: /* Command buffer pointers */
        !           137:  
        !           138: static char *bp,                        /* Current command buffer position */
        !           139:     *pp,                                /* Start of current field */
        !           140:     *np;                                /* Start of next field */
        !           141:  
        !           142: static int ungw;                       /* For ungetting words */
        !           143: 
        !           144: _PROTOTYP( VOID addhlp, (char *) );
        !           145: _PROTOTYP( VOID clrhlp, (void) );
        !           146: _PROTOTYP( VOID dmphlp, (void) );
        !           147: _PROTOTYP( int gtword, (void) );
        !           148: _PROTOTYP( int addbuf, (char *) );
        !           149: _PROTOTYP( int setatm, (char *) );
        !           150: _PROTOTYP( int cmdgetc, (void) );
        !           151: _PROTOTYP( VOID cmdnewl, (char) );
        !           152: _PROTOTYP( VOID cmdchardel, (void) );
        !           153: _PROTOTYP( VOID cmdecho, (char, int) );
        !           154: _PROTOTYP( static int test, (int, int) );
        !           155: 
        !           156: /*  T E S T  --  Bit test  */
        !           157:  
        !           158: static int
        !           159: test(x,m) int x, m; { /*  Returns 1 if any bits from m are on in x, else 0  */
        !           160:     return((x & m) ? 1 : 0);
        !           161: }
        !           162: 
        !           163: /*  C M S E T U P  --  Set up command buffers  */
        !           164: 
        !           165: #ifdef DCMDBUF
        !           166: int
        !           167: cmsetup() {
        !           168:     if (!(cmdbuf = malloc(CMDBL + 4))) return(-1);
        !           169:     if (!(savbuf = malloc(CMDBL + 4))) return(-1);
        !           170:     savbuf[0] = '\0';
        !           171:     if (!(hlpbuf = malloc(HLPBL + 4))) return(-1);
        !           172:     if (!(atmbuf = malloc(ATMBL + 4))) return(-1);
        !           173:     if (!(atxbuf = malloc(CMDBL + 4))) return(-1);
        !           174:     if (!(atybuf = malloc(ATMBL + 4))) return(-1);
        !           175:     if (!(filbuf = malloc(ATMBL + 4))) return(-1);
        !           176:     return(0);
        !           177: }
        !           178: #endif /* COMMENT */ 
        !           179: 
        !           180: /*  C M S E T P  --  Set the program prompt.  */
        !           181:  
        !           182: VOID
        !           183: cmsetp(s) char *s; {
        !           184:     strncpy(cmprxx,s,PROML - 1);
        !           185:     cmprxx[PROML] = NUL;
        !           186:     psetf = 1;                          /* Flag that prompt has been set. */
        !           187: }
        !           188: /*  C M S A V P  --  Save a copy of the current prompt.  */
        !           189:  
        !           190: VOID
        !           191: #ifdef CK_ANSIC
        !           192: cmsavp(char s[], int n)
        !           193: #else
        !           194: cmsavp(s,n) int n; char s[];
        !           195: #endif /* CK_ANSIC */
        !           196: /* cmsavp */ {
        !           197:     strncpy(s,cmprxx,n-1);
        !           198:     s[n-1] = NUL;
        !           199: }
        !           200:  
        !           201: /*  P R O M P T  --  Issue the program prompt.  */
        !           202:  
        !           203: VOID
        !           204: prompt(f) xx_strp f; {
        !           205:     char *sx, *sy; int n;
        !           206: 
        !           207:     if (psetf == 0) cmsetp(dfprom);     /* If no prompt set, set default. */
        !           208: 
        !           209:     sx = cmprxx;                       /* Unevaluated copy */
        !           210:     if (f) {                           /* If conversion function given */
        !           211:        sy = cmprom;                    /* Evaluate it */
        !           212:        n = PROML;
        !           213:        if ((*f)(sx,&sy,&n) < 0)        /* If evaluation failed */
        !           214:          sx = cmprxx;                  /* revert to unevaluated copy */
        !           215:        else
        !           216:          sx = cmprom;
        !           217:     }
        !           218: #ifdef OSK
        !           219:     fputs(sx, stdout);
        !           220: #else
        !           221: #ifdef MAC
        !           222:     printf("%s", sx);
        !           223: #else
        !           224:     printf("\r%s",sx);                 /* Print the prompt. */
        !           225:     fflush(stdout);                    /* Now! */
        !           226: #endif /* MAC */
        !           227: #endif /* OSK */
        !           228: }
        !           229:  
        !           230: #ifndef NOSPL
        !           231: VOID
        !           232: pushcmd() {                            /* For use with IF command. */
        !           233:     strcpy(savbuf,np);                 /* Save the dependent clause,  */
        !           234:     cmres();                           /* and clear the command buffer. */
        !           235:     debug(F110, "pushcmd: savbuf:", savbuf, 0);
        !           236: }
        !           237: #endif /* NOSPL */
        !           238: 
        !           239: #ifdef COMMENT
        !           240: /* no longer used... */
        !           241: VOID
        !           242: popcmd() {
        !           243:     strcpy(cmdbuf,savbuf);             /* Put back the saved material */
        !           244:     *savbuf = '\0';                    /* and clear the save buffer */
        !           245:     cmres();
        !           246: }
        !           247: #endif /* COMMENT */
        !           248: 
        !           249: /*  C M R E S  --  Reset pointers to beginning of command buffer.  */
        !           250:  
        !           251: VOID
        !           252: cmres() {  
        !           253:     cc = 0;                             /* Reset character counter. */
        !           254:     pp = np = bp = cmdbuf;              /* Point to command buffer. */
        !           255:     cmflgs = -5;                        /* Parse not yet started. */
        !           256:     ungw = 0;                          /* Don't need to unget a word. */
        !           257: }
        !           258:  
        !           259: /*  C M I N I  --  Clear the command and atom buffers, reset pointers.  */
        !           260:  
        !           261: /*
        !           262: The argument specifies who is to echo the user's typein --
        !           263:   1 means the cmd package echoes
        !           264:   0 somebody else (system, front end, terminal) echoes
        !           265: */
        !           266: VOID
        !           267: cmini(d) int d; {
        !           268:     for (bp = cmdbuf; bp < cmdbuf+CMDBL; bp++) *bp = NUL;
        !           269:     *atmbuf = NUL;
        !           270:     dpx = d;
        !           271:     cmres();
        !           272: }
        !           273:  
        !           274: #ifndef NOSPL
        !           275: /* The following bits are to allow the command package to call itself */
        !           276: /* in the middle of a parse.  To do this, begin by calling cmpush, and */
        !           277: /* end by calling cmpop. */
        !           278: 
        !           279: #ifdef DCMDBUF
        !           280: struct cmp {
        !           281:     int i[5];                          /* stack for integers */
        !           282:     char *c[3];                                /* stack for pointers */
        !           283:     char *b[8];                                /* stack for buffer contents */
        !           284: };
        !           285: struct cmp *cmp = 0;
        !           286: #else
        !           287: int cmp_i[CMDDEP+1][5];                        /* Stack for integers */
        !           288: char *cmp_c[CMDDEP+1][5];              /* for misc pointers */
        !           289: char *cmp_b[CMDDEP+1][7];              /* for buffer contents pointers */
        !           290: #endif /* DCMDBUF */
        !           291: 
        !           292: int cmddep = -1;                       /* Current stack depth */
        !           293: 
        !           294: int
        !           295: cmpush() {                             /* Save the command environment */
        !           296:     char *cp;                          /* Character pointer */
        !           297: 
        !           298:     if (++cmddep > CMDDEP) return(-1); /* Enter a new command depth */
        !           299:     debug(F101,"&cmpush","",cmddep);
        !           300: 
        !           301: #ifdef DCMDBUF
        !           302:     /* allocate memory for cmp if not already done */
        !           303:     if (!cmp && !(cmp = (struct cmp *) malloc(sizeof(struct cmp)*(CMDDEP+1))))
        !           304:       fatal("cmpush: no memory for cmp");
        !           305:     cmp[cmddep].i[0] = cmflgs;         /* First do the global ints */
        !           306:     cmp[cmddep].i[1] = cmfsav;
        !           307:     cmp[cmddep].i[2] = atxn;
        !           308:     cmp[cmddep].i[3] = ungw;
        !           309: 
        !           310:     cmp[cmddep].c[0] = bp;             /* Then the global pointers */
        !           311:     cmp[cmddep].c[1] = pp;
        !           312:     cmp[cmddep].c[2] = np; 
        !           313: #else
        !           314:     cmp_i[cmddep][0] = cmflgs;         /* First do the global ints */
        !           315:     cmp_i[cmddep][1] = cmfsav;
        !           316:     cmp_i[cmddep][2] = atxn;
        !           317:     cmp_i[cmddep][3] = ungw;
        !           318: 
        !           319:     cmp_c[cmddep][0] = bp;             /* Then the global pointers */
        !           320:     cmp_c[cmddep][1] = pp;
        !           321:     cmp_c[cmddep][2] = np; 
        !           322: #endif /* DCMDBUF */
        !           323: 
        !           324:     /* Now the buffers themselves.  A lot of repititious code... */
        !           325: 
        !           326: #ifdef DCMDBUF
        !           327:     cp = malloc((int)strlen(cmdbuf)+1);        /* 0: Command buffer */
        !           328:     if (cp) strcpy(cp,cmdbuf);
        !           329:     cmp[cmddep].b[0] = cp;
        !           330:     if (cp == NULL) return(-1);
        !           331: 
        !           332:     cp = malloc((int)strlen(savbuf)+1);        /* 1: Save buffer */
        !           333:     if (cp) strcpy(cp,savbuf);
        !           334:     cmp[cmddep].b[1] = cp;
        !           335:     if (cp == NULL) return(-1);
        !           336: 
        !           337:     cp = malloc((int)strlen(hlpbuf)+1);        /* 2: Help string buffer */
        !           338:     if (cp) strcpy(cp,hlpbuf);
        !           339:     cmp[cmddep].b[2] = cp;
        !           340:     if (cp == NULL) return(-1);
        !           341: 
        !           342:     cp = malloc((int)strlen(atmbuf)+1);        /* 3: Atom buffer */
        !           343:     if (cp) strcpy(cp,atmbuf);
        !           344:     cmp[cmddep].b[3] = cp;
        !           345:     if (cp == NULL) return(-1);
        !           346: 
        !           347:     cp = malloc((int)strlen(atxbuf)+1);        /* 4: Expansion buffer */
        !           348:     if (cp) strcpy(cp,atxbuf);
        !           349:     cmp[cmddep].b[4] = cp;
        !           350:     if (cp == NULL) return(-1);
        !           351: 
        !           352:     cp = malloc((int)strlen(atybuf)+1);        /* 5: Atom buffer copy */
        !           353:     if (cp) strcpy(cp,atybuf);
        !           354:     cmp[cmddep].b[5] = cp;
        !           355:     if (cp == NULL) return(-1);
        !           356: 
        !           357:     cp = malloc((int)strlen(filbuf)+1);        /* 6: File name buffer */
        !           358:     if (cp) strcpy(cp,filbuf);
        !           359:     cmp[cmddep].b[6] = cp;
        !           360:     if (cp == NULL) return(-1);
        !           361: #else
        !           362:     cp = malloc((int)strlen(cmdbuf)+1);        /* 0: Command buffer */
        !           363:     if (cp) strcpy(cp,cmdbuf);
        !           364:     cmp_b[cmddep][0] = cp;
        !           365:     if (cp == NULL) return(-1);
        !           366: 
        !           367:     cp = malloc((int)strlen(savbuf)+1);        /* 1: Save buffer */
        !           368:     if (cp) strcpy(cp,savbuf);
        !           369:     cmp_b[cmddep][1] = cp;
        !           370:     if (cp == NULL) return(-1);
        !           371: 
        !           372:     cp = malloc((int)strlen(hlpbuf)+1);        /* 2: Help string buffer */
        !           373:     if (cp) strcpy(cp,hlpbuf);
        !           374:     cmp_b[cmddep][2] = cp;
        !           375:     if (cp == NULL) return(-1);
        !           376: 
        !           377:     cp = malloc((int)strlen(atmbuf)+1);        /* 3: Atom buffer */
        !           378:     if (cp) strcpy(cp,atmbuf);
        !           379:     cmp_b[cmddep][3] = cp;
        !           380:     if (cp == NULL) return(-1);
        !           381: 
        !           382:     cp = malloc((int)strlen(atxbuf)+1);        /* 4: Expansion buffer */
        !           383:     if (cp) strcpy(cp,atxbuf);
        !           384:     cmp_b[cmddep][4] = cp;
        !           385:     if (cp == NULL) return(-1);
        !           386: 
        !           387:     cp = malloc((int)strlen(atybuf)+1);        /* 5: Atom buffer copy */
        !           388:     if (cp) strcpy(cp,atybuf);
        !           389:     cmp_b[cmddep][5] = cp;
        !           390:     if (cp == NULL) return(-1);
        !           391: 
        !           392:     cp = malloc((int)strlen(filbuf)+1);        /* 6: File name buffer */
        !           393:     if (cp) strcpy(cp,filbuf);
        !           394:     cmp_b[cmddep][6] = cp;
        !           395:     if (cp == NULL) return(-1);
        !           396: #endif /* DCMDBUF */
        !           397: 
        !           398:     cmini(dpx);                                /* Initize the command parser */
        !           399:     return(0);
        !           400: }
        !           401: 
        !           402: int
        !           403: cmpop() {                              /* Restore the command environment */
        !           404:     debug(F101,"&cmpop","",cmddep);
        !           405:     if (cmddep < 0) return(-1);                /* Don't pop too much! */
        !           406: 
        !           407: #ifdef DCMDBUF
        !           408:     cmflgs = cmp[cmddep].i[0];         /* First do the global ints */
        !           409:     cmfsav = cmp[cmddep].i[1];
        !           410:     atxn = cmp[cmddep].i[2];
        !           411:     ungw = cmp[cmddep].i[3];
        !           412: 
        !           413:     bp = cmp[cmddep].c[0];             /* Then the global pointers */
        !           414:     pp = cmp[cmddep].c[1];
        !           415:     np = cmp[cmddep].c[2]; 
        !           416: #else
        !           417:     cmflgs = cmp_i[cmddep][0];         /* First do the global ints */
        !           418:     cmfsav = cmp_i[cmddep][1];
        !           419:     atxn = cmp_i[cmddep][2];
        !           420:     ungw = cmp_i[cmddep][3];
        !           421: 
        !           422:     bp = cmp_c[cmddep][0];             /* Then the global pointers */
        !           423:     pp = cmp_c[cmddep][1];
        !           424:     np = cmp_c[cmddep][2]; 
        !           425: #endif /* DCMDBUF */
        !           426: 
        !           427:     /* Now the buffers themselves. */
        !           428: 
        !           429: #ifdef DCMDBUF
        !           430:     if (cmp[cmddep].b[0]) {
        !           431:        strcpy(cmdbuf,cmp[cmddep].b[0]); /* 0: Command buffer */
        !           432:        free(cmp[cmddep].b[0]);
        !           433:        cmp[cmddep].b[0] = NULL;
        !           434:     }
        !           435:     if (cmp[cmddep].b[1]) {
        !           436:        strcpy(savbuf,cmp[cmddep].b[1]); /* 1: Save buffer */
        !           437:        free(cmp[cmddep].b[1]);
        !           438:        cmp[cmddep].b[1] = NULL;
        !           439:     }
        !           440:     if (cmp[cmddep].b[2]) {
        !           441:        strcpy(hlpbuf,cmp[cmddep].b[2]); /* 2: Help buffer */
        !           442:        free(cmp[cmddep].b[2]);
        !           443:        cmp[cmddep].b[2] = NULL;
        !           444:     }
        !           445:     if (cmp[cmddep].b[3]) {
        !           446:        strcpy(atmbuf,cmp[cmddep].b[3]); /* 3: Atomic buffer! */
        !           447:        free(cmp[cmddep].b[3]);
        !           448:        cmp[cmddep].b[3] = NULL;
        !           449:     }
        !           450:     if (cmp[cmddep].b[4]) {
        !           451:        strcpy(atxbuf,cmp[cmddep].b[4]); /* 4: eXpansion buffer */
        !           452:        free(cmp[cmddep].b[4]);
        !           453:        cmp[cmddep].b[4] = NULL;
        !           454:     }
        !           455:     if (cmp[cmddep].b[5]) {
        !           456:        strcpy(atybuf,cmp[cmddep].b[5]); /* 5: Atom buffer copY */
        !           457:        free(cmp[cmddep].b[5]);
        !           458:        cmp[cmddep].b[5] = NULL;
        !           459:     }
        !           460:     if (cmp[cmddep].b[6]) {
        !           461:        strcpy(filbuf,cmp[cmddep].b[6]); /* 6: Filename buffer */
        !           462:        free(cmp[cmddep].b[6]);
        !           463:        cmp[cmddep].b[6] = NULL;
        !           464:     }
        !           465: #else
        !           466:     if (cmp_b[cmddep][0]) {
        !           467:        strcpy(cmdbuf,cmp_b[cmddep][0]); /* 0: Command buffer */
        !           468:        free(cmp_b[cmddep][0]);
        !           469:        cmp_b[cmddep][0] = NULL;
        !           470:     }
        !           471:     if (cmp_b[cmddep][1]) {
        !           472:        strcpy(savbuf,cmp_b[cmddep][1]); /* 1: Save buffer */
        !           473:        free(cmp_b[cmddep][1]);
        !           474:        cmp_b[cmddep][1] = NULL;
        !           475:     }
        !           476:     if (cmp_b[cmddep][2]) {
        !           477:        strcpy(hlpbuf,cmp_b[cmddep][2]); /* 2: Help buffer */
        !           478:        free(cmp_b[cmddep][2]);
        !           479:        cmp_b[cmddep][2] = NULL;
        !           480:     }
        !           481:     if (cmp_b[cmddep][3]) {
        !           482:        strcpy(atmbuf,cmp_b[cmddep][3]); /* 3: Atomic buffer! */
        !           483:        free(cmp_b[cmddep][3]);
        !           484:        cmp_b[cmddep][3] = NULL;
        !           485:     }
        !           486:     if (cmp_b[cmddep][4]) {
        !           487:        strcpy(atxbuf,cmp_b[cmddep][4]); /* 4: eXpansion buffer */
        !           488:        free(cmp_b[cmddep][4]);
        !           489:        cmp_b[cmddep][4] = NULL;
        !           490:     }
        !           491:     if (cmp_b[cmddep][5]) {
        !           492:        strcpy(atybuf,cmp_b[cmddep][5]); /* 5: Atom buffer copY */
        !           493:        free(cmp_b[cmddep][5]);
        !           494:        cmp_b[cmddep][5] = NULL;
        !           495:     }
        !           496:     if (cmp_b[cmddep][6]) {
        !           497:        strcpy(filbuf,cmp_b[cmddep][6]); /* 6: Filename buffer */
        !           498:        free(cmp_b[cmddep][6]);
        !           499:        cmp_b[cmddep][6] = NULL;
        !           500:     }
        !           501: #endif /* DCMDBUF */
        !           502: 
        !           503:     cmddep--;                          /* Rise, rise */
        !           504:     debug(F101,"&cmpop","",cmddep);
        !           505:     return(cmddep);
        !           506: }
        !           507: #endif /* NOSPL */
        !           508: 
        !           509: #ifdef COMMENT
        !           510: VOID
        !           511: stripq(s) char *s; {                    /* Function to strip '\' quotes */
        !           512:     char *t;
        !           513:     while (*s) {
        !           514:         if (*s == CMDQ) {
        !           515:             for (t = s; *t != '\0'; t++) *t = *(t+1);
        !           516:         }
        !           517:         s++;
        !           518:     }
        !           519: }
        !           520: #endif /* COMMENT */
        !           521: 
        !           522: /* Convert tabs to spaces, one for one */
        !           523: VOID
        !           524: untab(s) char *s; {
        !           525:     while (*s) {
        !           526:        if (*s == HT) *s = SP;
        !           527:        s++;
        !           528:     }
        !           529: }
        !           530: 
        !           531: /*  C M N U M  --  Parse a number in the indicated radix  */
        !           532:  
        !           533: /* 
        !           534:  The only radix allowed in unquoted numbers is 10.
        !           535:  Parses unquoted numeric strings in base 10.
        !           536:  Parses backslash-quoted numbers in the radix indicated by the quote:
        !           537:    \nnn = \dnnn = decimal, \onnn = octal, \xnn = Hexadecimal.
        !           538:  If these fail, then if a preprocessing function is supplied, that is applied 
        !           539:  and then a second attempt is made to parse an unquoted decimal string. 
        !           540: 
        !           541:  Returns:
        !           542:    -3 if no input present when required,
        !           543:    -2 if user typed an illegal number,
        !           544:    -1 if reparse needed,
        !           545:     0 otherwise, with argument n set to the number that was parsed
        !           546: */
        !           547: int
        !           548: cmnum(xhlp,xdef,radix,n,f) char *xhlp, *xdef; int radix, *n; xx_strp f; {
        !           549:     int x; char *s, *zp, *zq;
        !           550:  
        !           551:     if (radix != 10) {                  /* Just do base 10 */
        !           552:         printf("cmnum: illegal radix - %d\n",radix);
        !           553:         return(-1);
        !           554:     }
        !           555:     x = cmfld(xhlp,xdef,&s,(xx_strp)0);
        !           556:     debug(F101,"cmnum: cmfld","",x);
        !           557:     if (x < 0) return(x);              /* Parse a field */
        !           558:     zp = atmbuf;
        !           559: 
        !           560:     if (chknum(zp)) {                  /* Check for decimal number */
        !           561:         *n = atoi(zp);                 /* Got one, we're done. */
        !           562:        debug(F101,"cmnum 1st chknum ok","",*n);
        !           563:         return(0);
        !           564:     } else if ((x = xxesc(&zp)) > -1) {        /* Check for backslash escape */
        !           565:        *n = x;
        !           566:        debug(F101,"cmnum xxesc ok","",*n);
        !           567:        return(*zp ? -2 : 0);
        !           568:     } else if (f) {                    /* If conversion function given */
        !           569:         zp = atmbuf;                   /* Try that */
        !           570:        zq = atxbuf;
        !           571:        atxn = CMDBL;
        !           572:        (*f)(zp,&zq,&atxn);             /* Convert */
        !           573:        zp = atxbuf;
        !           574:     }
        !           575:     debug(F110,"cmnum zp",zp,0);
        !           576:     if (chknum(zp)) {                  /* Check again for decimal number */
        !           577:         *n = atoi(zp);                 /* Got one, we're done. */
        !           578:        debug(F101,"cmnum 2nd chknum ok","",*n);
        !           579:         return(0);
        !           580:     } else {                           /* Not numeric */
        !           581:        return(-2);     
        !           582:     }
        !           583: }
        !           584: 
        !           585: /*  C M O F I  --  Parse the name of an output file  */
        !           586:  
        !           587: /*
        !           588:  Depends on the external function zchko(); if zchko() not available, use
        !           589:  cmfld() to parse output file names.
        !           590:  
        !           591:  Returns
        !           592:    -3 if no input present when required,
        !           593:    -2 if permission would be denied to create the file,
        !           594:    -1 if reparse needed,
        !           595:     0 or 1 otherwise, with xp pointing to name.
        !           596: */
        !           597: int
        !           598: cmofi(xhlp,xdef,xp,f) char *xhlp, *xdef, **xp; xx_strp f; {
        !           599:     int x; char *s, *zq;
        !           600: #ifdef DTILDE
        !           601:     _PROTOTYP( char * tilde_expand, (char *) );
        !           602:     char *dirp;
        !           603: #endif 
        !           604: 
        !           605:     if (*xhlp == NUL) xhlp = "Output file";
        !           606:     *xp = "";
        !           607:  
        !           608:     if ((x = cmfld(xhlp,xdef,&s,(xx_strp)0)) < 0) return(x);
        !           609: 
        !           610:     if (f) {                           /* If a conversion function is given */
        !           611:        zq = atxbuf;
        !           612:        atxn = CMDBL;
        !           613:        if ((x = (*f)(s,&zq,&atxn)) < 0) return(-2);
        !           614:        s = atxbuf;
        !           615:     }
        !           616: 
        !           617: #ifdef DTILDE
        !           618:     dirp = tilde_expand(s);            /* Expand tilde, if any, */
        !           619:     if (*dirp != '\0') setatm(dirp);   /* right in the atom buffer. */
        !           620:     s = atmbuf;
        !           621: #endif
        !           622: 
        !           623:     if (iswild(s)) {
        !           624:         printf("?Wildcards not allowed - %s\n",s);
        !           625:         return(-2);
        !           626:     }
        !           627:     if (strcmp(s,CTTNAM) && (zchko(s) < 0)) { /* ok to write to tty */
        !           628:         printf("?Write permission denied - %s\n",s);
        !           629:         return(-9);
        !           630:     } else {
        !           631:         *xp = s;
        !           632:         return(x);
        !           633:     }
        !           634: }
        !           635: 
        !           636:  
        !           637: /*  C M I F I  --  Parse the name of an existing file  */
        !           638:  
        !           639: /*
        !           640:  This function depends on the external functions:
        !           641:    zchki()  - Check if input file exists and is readable.
        !           642:    zxpand() - Expand a wild file specification into a list.
        !           643:    znext()  - Return next file name from list.
        !           644:  If these functions aren't available, then use cmfld() to parse filenames.
        !           645: */
        !           646: /*
        !           647:  Returns
        !           648:    -4 EOF
        !           649:    -3 if no input present when required,
        !           650:    -2 if file does not exist or is not readable,
        !           651:    -1 if reparse needed,
        !           652:     0 or 1 otherwise, with:
        !           653:         xp pointing to name,
        !           654:         wild = 1 if name contains '*' or '?', 0 otherwise.
        !           655: */
        !           656: int
        !           657: cmifi(xhlp,xdef,xp,wild,f) char *xhlp, *xdef, **xp; int *wild; xx_strp f; {
        !           658:     int i, x, xc; long y; char *sp, *zq, *sv;
        !           659: #ifdef DTILDE
        !           660:     char *tilde_expand(), *dirp;
        !           661: #endif
        !           662: 
        !           663: 
        !           664: #ifndef NOPARTIAL
        !           665:     extern char *mtchs[];
        !           666: #endif 
        !           667: 
        !           668:     cc = xc = 0;                        /* Initialize counts & pointers */
        !           669:     *xp = "";
        !           670:     if ((x = cmflgs) != 1) {            /* Already confirmed? */
        !           671:         x = gtword();                   /* No, get a word */
        !           672:     } else {
        !           673:         cc = setatm(xdef);              /* If so, use default, if any. */
        !           674:     }
        !           675: 
        !           676:     *xp = atmbuf;                       /* Point to result. */
        !           677:  
        !           678:     while (1) {
        !           679:         xc += cc;                       /* Count the characters. */
        !           680:         debug(F111,"cmifi gtword",atmbuf,xc);
        !           681:         switch (x) {
        !           682:             case -4:                    /* EOF */
        !           683:             case -2:                    /* Out of space. */
        !           684:             case -1:                    /* Reparse needed */
        !           685:                 return(x);
        !           686:             case 0:                     /* SP or NL */
        !           687:             case 1:
        !           688:                 if (xc == 0) *xp = xdef;     /* If no input, return default. */
        !           689:                 if (**xp == NUL) return(-3); /* If field empty, return -3. */
        !           690: 
        !           691:                if (f) {                /* If a conversion function is given */
        !           692:                    zq = atxbuf;        /* ... */
        !           693:                    atxn = CMDBL;
        !           694:                    if ((x = (*f)(*xp,&zq,&atxn)) < 0) return(-2);
        !           695:                    *xp = atxbuf;
        !           696:                }
        !           697:                debug(F110,"cmifi atxbuf",atxbuf,0);
        !           698: #ifdef COMMENT
        !           699: /* don't need this stuff, zxpand does it now. */
        !           700: #ifdef DTILDE
        !           701: 
        !           702:                dirp = tilde_expand(*xp);    /* Expand tilde, if any, */
        !           703:                if (*dirp != '\0') setatm(dirp); /* right in atom buffer. */
        !           704:                *xp = atmbuf;
        !           705: #endif /* DTILDE */
        !           706: 
        !           707:                 /* If filespec is wild, see if there are any matches */
        !           708: 
        !           709:                 *wild = iswild(*xp);
        !           710:                 debug(F101,"cmifi wild","",*wild);
        !           711:                 if (*wild != 0) {
        !           712: #endif /* COMMENT */
        !           713:                    sv = malloc((int)strlen(*xp)+1); /* Make a safe copy */
        !           714:                    if (!sv) {
        !           715:                        printf("?malloc error 73, cmifi\n");
        !           716:                        return(-9);
        !           717:                    }
        !           718:                    strcpy(sv,*xp);
        !           719:                    debug(F110,"cmifi sv",sv,0);
        !           720:                     y = zxpand(*xp);
        !           721:                    *wild = (y > 1);
        !           722:                    debug(F111,"cmifi sv wild",sv,*wild);
        !           723:                     if (y == 0) {
        !           724:                         printf("?No files match - %s\n",*xp);
        !           725:                         return(-9);
        !           726:                     } else if (y < 0) {
        !           727:                         printf("?Too many files match - %s\n",*xp);
        !           728:                         return(-9);
        !           729:                    } else if (y > 1) return(x);
        !           730: #ifdef COMMENT
        !           731:                 }
        !           732: #endif
        !           733:                 /* If not wild, see if it exists and is readable. */
        !           734:  
        !           735:                debug(F111,"cmifi sv not wild",sv,*wild);
        !           736: 
        !           737:                znext(*xp);             /* Get first (only?) matching file */
        !           738:                 y = zchki(*xp);                /* Check its accessibility */
        !           739:                zxpand(sv);             /* Rewind so next znext() gets 1st */
        !           740:                free(sv);               /* done with this */
        !           741:                 if (y == -3) {
        !           742:                     printf("?Read permission denied - %s\n",*xp);
        !           743:                     return(-9);
        !           744:                 } else if (y == -2) {
        !           745:                     printf("?File not readable - %s\n",*xp);
        !           746:                     return(-9);
        !           747:                 } else if (y < 0) {
        !           748:                     printf("?File not found - %s\n",*xp);
        !           749:                     return(-9);
        !           750:                 }
        !           751:                 return(x);
        !           752: 
        !           753: #ifndef MAC
        !           754:             case 2:                     /* ESC */
        !           755:                debug(F101,"cmifi esc, xc","",xc);
        !           756:                 if (xc == 0) {
        !           757:                     if (*xdef != '\0') {
        !           758:                         printf("%s ",xdef); /* If at beginning of field, */
        !           759: #ifdef GEMDOS
        !           760:                        fflush(stdout);
        !           761: #endif /* GEMDOS */
        !           762:                         addbuf(xdef);   /* supply default. */
        !           763:                         cc = setatm(xdef);
        !           764:                     } else {            /* No default */
        !           765:                         putchar(BEL);
        !           766:                     }
        !           767:                     break;
        !           768:                 } 
        !           769:                if (f) {                /* If a conversion function is given */
        !           770:                    zq = atxbuf;        /* ... */
        !           771:                    atxn = CMDBL;
        !           772:                    if ((x = (*f)(*xp,&zq,&atxn)) < 0) return(-2);
        !           773:                     /* reduce cc by number of \\ consumed by conversion */
        !           774:                    /* function (needed for OS/2, where \ is path separator) */
        !           775:                     cc -= (strlen(*xp) - strlen(atxbuf));
        !           776:                    *xp = atxbuf;
        !           777:                }
        !           778: /* #ifdef COMMENT */
        !           779: #ifdef DTILDE
        !           780:                dirp = tilde_expand(*xp);    /* Expand tilde, if any, */
        !           781:                if (*dirp != '\0') setatm(dirp); /* in the atom buffer. */
        !           782:                 *xp = atmbuf;
        !           783: #endif /* DTILDE */
        !           784: /* #endif */
        !           785:                 sp = *xp + cc;
        !           786: #ifdef datageneral
        !           787:                 *sp++ = '+';           /* Data General AOS wildcard */
        !           788: #else
        !           789:                 *sp++ = '*';           /* Others */
        !           790: #endif /* datageneral */
        !           791:                 *sp-- = '\0';
        !           792:                 y = zxpand(*xp);       /* Add wildcard and expand list. */
        !           793:                if (y > 0) strcpy(filbuf,mtchs[0]);
        !           794:                else *filbuf = '\0';
        !           795:                 *sp = '\0';             /* Remove wildcard. */
        !           796:                *wild = (y > 1);
        !           797:                 if (y == 0) {
        !           798:                     printf("?No files match - %s\n",atmbuf);
        !           799:                     return(-9);
        !           800:                 } else if (y < 0) {
        !           801:                     printf("?Too many files match - %s\n",atmbuf);
        !           802:                     return(-9);
        !           803:                 } else if (y > 1) {     /* Not unique. */
        !           804: #ifndef NOPARTIAL
        !           805: /* Partial filename completion */
        !           806:                    int i, j, k; char c;
        !           807:                    k = 0;
        !           808:                    debug(F111,"cmifi partial",filbuf,cc);
        !           809:                    for (i = cc; (c = filbuf[i]); i++) {
        !           810:                        for (j = 1; j < y; j++)
        !           811:                          if (mtchs[j][i] != c) break;
        !           812:                        if (j == y) k++;
        !           813:                        else filbuf[i] = filbuf[i+1] = NUL;
        !           814:                    }
        !           815:                    debug(F111,"cmifi partial k",filbuf,k);
        !           816:                    if (k > 0) {        /* Got more characters */
        !           817:                        sp = filbuf + cc; /* Point to new ones */
        !           818: #ifdef VMS
        !           819:                        for (i = 0; i < cc; i++) {
        !           820:                            cmdchardel(); /* Back up over old partial spec */
        !           821:                            bp--;
        !           822:                        }
        !           823:                        sp = filbuf;    /* Point to new word start */
        !           824:                        debug(F100,"cmifi vms erase ok","",0);
        !           825: #endif /* VMS */
        !           826:                        cc = k;         /* How many new ones we just got */
        !           827:                        printf("%s",sp);        /* Print them */
        !           828:                        while (*bp++ = *sp++) ; /* Copy to command buffer */
        !           829:                        bp--;                   /* Back up over NUL */
        !           830:                        debug(F110,"cmifi partial cmdbuf",cmdbuf,0);
        !           831:                        setatm(filbuf);
        !           832:                        debug(F111,"cmifi partial atmbuf",atmbuf,cc);
        !           833:                        *xp = atmbuf;
        !           834:                    }
        !           835: #endif /* NOPARTIAL */
        !           836:                    putchar(BEL);       /* Beep because not unique. */
        !           837:                 } else {                /* Unique, complete it.  */
        !           838:                     sp = filbuf + cc;   /* Point past what user typed. */
        !           839: #ifdef VMS
        !           840:                    for (i = 0; i < cc; i++) {
        !           841:                        cmdchardel();   /* Back up over old partial spec */
        !           842:                        bp--;
        !           843:                    }
        !           844:                    sp = filbuf;        /* Point to new word start */
        !           845: #endif /* VMS */
        !           846:                     printf("%s ",sp);   /* Complete the name. */
        !           847: #ifdef GEMDOS
        !           848:                    fflush(stdout);
        !           849: #endif /* GEMDOS */
        !           850:                     addbuf(sp);         /* Add the characters to cmdbuf. */
        !           851:                     setatm(filbuf);    /* And to atmbuf. */
        !           852:                     *xp = atmbuf;       /* Return pointer to atmbuf. */
        !           853: 
        !           854:                     return(cmflgs = 0);
        !           855:                 }
        !           856:                 break;
        !           857:  
        !           858:             case 3:                     /* Question mark */
        !           859:                 if (*xhlp == NUL)
        !           860:                  printf(" Input file specification");
        !           861:                 else
        !           862:                  printf(" %s",xhlp);
        !           863: #ifdef GEMDOS
        !           864:                fflush(stdout);
        !           865: #endif /* GEMDOS */
        !           866:                 if (xc > 0) {
        !           867:                    if (f) {            /* If a conversion function is given */
        !           868:                        zq = atxbuf;    /* ... */
        !           869:                        atxn = CMDBL;
        !           870:                        if ((x = (*f)(*xp,&zq,&atxn)) < 0) return(-2);
        !           871:                        *xp = atxbuf;
        !           872:                    }
        !           873: #ifdef DTILDE
        !           874:                    dirp = tilde_expand(*xp);    /* Expand tilde, if any */
        !           875:                    if (*dirp != '\0') setatm(dirp);
        !           876:                    *xp = atmbuf;
        !           877: #endif
        !           878:                    debug(F111,"cmifi ? *xp, cc",*xp,cc);
        !           879:                     sp = *xp + cc;     /* Insert "*" at end */
        !           880: #ifdef datageneral
        !           881:                     *sp++ = '+';        /* Insert +, the DG wild card */
        !           882: #else
        !           883:                     *sp++ = '*';
        !           884: #endif
        !           885:                     *sp-- = '\0';
        !           886:                    debug(F110,"cmifi ? wild",*xp,0);
        !           887:                     y = zxpand(*xp);
        !           888:                     *sp = '\0';
        !           889:                     if (y == 0) {                   
        !           890:                         printf("?No files match - %s\n",atmbuf);
        !           891:                         return(-9);
        !           892:                     } else if (y < 0) {
        !           893:                         printf("?Too many files match - %s\n",atmbuf);
        !           894:                         return(-9);
        !           895:                     } else {
        !           896:                         printf(", one of the following:\n");
        !           897:                         clrhlp();
        !           898:                         for (i = 0; i < y; i++) {
        !           899:                             znext(filbuf);
        !           900: #ifdef VMS
        !           901:                            printf(" %s\n",filbuf); /* VMS names can be long */
        !           902: #else
        !           903:                             addhlp(filbuf);
        !           904: #endif /* VMS */
        !           905:                         }
        !           906:                         dmphlp();
        !           907:                     }
        !           908:                 } else printf("\n");
        !           909:                 printf("%s%s",cmprom,cmdbuf);
        !           910:                fflush(stdout);
        !           911:                 break;
        !           912: #endif /* MAC */
        !           913:         }
        !           914:     x = gtword();
        !           915:     *xp = atmbuf;
        !           916:     }
        !           917: }
        !           918: 
        !           919: /*  C M D I R  --  Parse a directory specification  */
        !           920:  
        !           921: /*
        !           922:  This function depends on the external functions:
        !           923:    zchki()  - Check if input file exists and is readable.
        !           924:  If these functions aren't available, then use cmfld() to parse dir names.
        !           925:  Note: this function quickly cobbled together, mainly by deleting lots of
        !           926:  lines from cmifi().  It seems to work, but various services are missing,
        !           927:  like completion, lists of matching directories on "?", etc.
        !           928: */
        !           929: /*
        !           930:  Returns
        !           931:    -4 EOF
        !           932:    -3 if no input present when required,
        !           933:    -2 if out of space or other internal error,
        !           934:    -1 if reparse needed,
        !           935:     0 or 1, with xp pointing to name, if directory specified,
        !           936:     2 if a wildcard was included.
        !           937: */
        !           938: int
        !           939: cmdir(xhlp,xdef,xp,f) char *xhlp, *xdef, **xp; xx_strp f; {
        !           940:     int x, xc; char *zq;
        !           941: #ifdef DTILDE
        !           942:     char *tilde_expand(), *dirp;
        !           943: #endif /* DTILDE */
        !           944: 
        !           945:     cc = xc = 0;                        /* Initialize counts & pointers */
        !           946:     *xp = "";
        !           947:     if ((x = cmflgs) != 1) {            /* Already confirmed? */
        !           948:         x = gtword();                   /* No, get a word */
        !           949:     } else {
        !           950:         cc = setatm(xdef);              /* If so, use default, if any. */
        !           951:     }
        !           952:     *xp = atmbuf;                       /* Point to result. */
        !           953:     while (1) {
        !           954:         xc += cc;                       /* Count the characters. */
        !           955:         debug(F111,"cmdir gtword",atmbuf,xc);
        !           956:         switch (x) {
        !           957:             case -4:                    /* EOF */
        !           958:             case -2:                    /* Out of space. */
        !           959:             case -1:                    /* Reparse needed */
        !           960:                 return(x);
        !           961:             case 0:                     /* SP or NL */
        !           962:             case 1:
        !           963:                 if (xc == 0) *xp = xdef;     /* If no input, return default. */
        !           964:                else *xp = atmbuf;
        !           965:                 if (**xp == NUL) return(-3); /* If field empty, return -3. */
        !           966: 
        !           967:                if (f) {                /* If a conversion function is given */
        !           968:                    zq = atxbuf;        /* ... */
        !           969:                    atxn = CMDBL;
        !           970:                    if ((x = (*f)(*xp,&zq,&atxn)) < 0) return(-2);
        !           971:                    *xp = atxbuf;
        !           972:                    cc = (int)strlen(atxbuf);
        !           973:                }
        !           974: #ifdef DTILDE
        !           975: /*
        !           976:   This is ugly, and for UNIX only.
        !           977:   Normally, we wouldn't call tilde_expand from a place like this anyway,
        !           978:   but rather let zxpand() take care of it.  But in this case we might want 
        !           979:   a hybrid result -- a string with the tilde expanded, but with wildcards
        !           980:   left unexpanded.
        !           981: */
        !           982:                dirp = tilde_expand(*xp); /* Expand tilde, if any, */
        !           983:                if (*dirp == '~') {     /* Still starts with tilde? */
        !           984:                    char *tp;           /* Yes, convert to lowercase */
        !           985:                    tp = *xp;           /* and try again. */
        !           986:                    while (*tp) {
        !           987:                        if (isupper(*tp)) *tp = tolower(*tp);
        !           988:                        tp++;
        !           989:                    }
        !           990:                }
        !           991:                dirp = tilde_expand(*xp); /* Expand tilde, if any, */
        !           992:                if (*dirp != '\0') setatm(dirp); /* in the atom buffer. */
        !           993:                *xp = atmbuf;
        !           994: #endif /* DTILDE */
        !           995:                if (iswild(*xp)) return(2);
        !           996:                else return(x);
        !           997: 
        !           998:             case 2:                     /* ESC */
        !           999:                putchar(BEL);
        !          1000:                break;
        !          1001: 
        !          1002:             case 3:                     /* Question mark */
        !          1003:                 if (*xhlp == NUL)
        !          1004:                     printf(" Directory name");
        !          1005:                 else
        !          1006:                     printf(" %s",xhlp);
        !          1007:                 printf("\n%s%s",cmprom,cmdbuf);
        !          1008:                fflush(stdout);
        !          1009:                 break;
        !          1010:         }
        !          1011:     x = gtword();
        !          1012: /*  *xp = atmbuf;  */
        !          1013:     }
        !          1014: }
        !          1015:  
        !          1016: /*  C M F L D  --  Parse an arbitrary field  */
        !          1017: /*
        !          1018:  Returns
        !          1019:    -3 if no input present when required,
        !          1020:    -2 if field too big for buffer,
        !          1021:    -1 if reparse needed,
        !          1022:     0 otherwise, xp pointing to string result.
        !          1023: */
        !          1024: int
        !          1025: cmfld(xhlp,xdef,xp,f) char *xhlp, *xdef, **xp; xx_strp f; {
        !          1026:     int x, xc;
        !          1027:     char *zq;
        !          1028: 
        !          1029:     cc = xc = 0;                        /* Initialize counts & pointers */
        !          1030:     *xp = "";
        !          1031:     if ((x = cmflgs) != 1) {            /* Already confirmed? */
        !          1032:         x = gtword();                   /* No, get a word */
        !          1033:     } else {
        !          1034:         cc = setatm(xdef);              /* If so, use default, if any. */
        !          1035:     }
        !          1036:     *xp = atmbuf;                       /* Point to result. */
        !          1037:  
        !          1038:     while (1) {
        !          1039:         xc += cc;                       /* Count the characters. */
        !          1040:         debug(F111,"cmfld: gtword",atmbuf,xc);
        !          1041:         debug(F101,"cmfld x","",x);
        !          1042:         switch (x) {
        !          1043:             case -4:                    /* EOF */
        !          1044:             case -2:                    /* Out of space. */
        !          1045:             case -1:                    /* Reparse needed */
        !          1046:                 return(x);
        !          1047:             case 0:                     /* SP or NL */
        !          1048:             case 1:
        !          1049:                 if (xc == 0)           /* If no input, return default. */
        !          1050:                  cc = setatm(xdef);
        !          1051:                *xp = atmbuf;
        !          1052:                if (f) {                /* If a conversion function is given */
        !          1053:                    zq = atxbuf;        /* ... */
        !          1054:                    atxn = CMDBL;
        !          1055:                    if ((*f)(*xp,&zq,&atxn) < 0) return(-2);
        !          1056:                    cc = setatm(atxbuf);
        !          1057:                    *xp = atmbuf;
        !          1058:                }
        !          1059:                 if (**xp == NUL) {     /* If variable evaluates to null */
        !          1060:                    cc = setatm(xdef);  /* Stick in the default again. */
        !          1061:                    if (**xp == NUL) x = -3; /* If still empty, return -3. */
        !          1062:                }
        !          1063: #ifdef COMMENT
        !          1064: /* The following is apparently not necessary. */
        !          1065: /* Remove it if nothing is broken, esp. TAKE file with trailing comments */
        !          1066:                xx = *xp;
        !          1067:                debug(F111,"cmfld before trim",*xp,x);
        !          1068:                for (i = (int)strlen(xx) - 1; i > 0; i--)
        !          1069:                  if (xx[i] != SP)      /* Trim trailing blanks */
        !          1070:                    break;
        !          1071:                  else
        !          1072:                    xx[i] = NUL;
        !          1073:                debug(F111,"cmfld returns",*xp,x); 
        !          1074: #endif /* COMMENT */
        !          1075:                debug(F101,"cmfld: returns","",x);
        !          1076:                 return(x);
        !          1077:             case 2:                     /* ESC */
        !          1078:                 if (xc == 0 && *xdef != NUL) {
        !          1079:                     printf("%s ",xdef); /* If at beginning of field, */
        !          1080: #ifdef GEMDOS
        !          1081:                    fflush(stdout);
        !          1082: #endif /* GEMDOS */
        !          1083:                     addbuf(xdef);       /* supply default. */
        !          1084:                     cc = setatm(xdef);  /* Return as if whole field */
        !          1085:                     return(0);          /* typed, followed by space. */
        !          1086:                 } else {
        !          1087:                     putchar(BEL);       /* Beep if already into field. */
        !          1088:                 }                   
        !          1089:                 break;
        !          1090:             case 3:                     /* Question mark */
        !          1091:                 if (*xhlp == NUL)
        !          1092:                     printf(" Please complete this field");
        !          1093:                 else
        !          1094:                     printf(" %s",xhlp);
        !          1095:                 printf("\n%s%s",cmprom,cmdbuf);
        !          1096:                fflush(stdout);
        !          1097:                 break;
        !          1098:         }
        !          1099:     x = gtword();
        !          1100: /*  *xp = atmbuf; */
        !          1101:     }
        !          1102: }
        !          1103: 
        !          1104:  
        !          1105: /*  C M T X T  --  Get a text string, including confirmation  */
        !          1106:  
        !          1107: /*
        !          1108:   Print help message 'xhlp' if ? typed, supply default 'xdef' if null
        !          1109:   string typed.  Returns
        !          1110:  
        !          1111:    -1 if reparse needed or buffer overflows.
        !          1112:     1 otherwise.
        !          1113:  
        !          1114:   with cmflgs set to return code, and xp pointing to result string.
        !          1115: */
        !          1116: int
        !          1117: cmtxt(xhlp,xdef,xp,f) char *xhlp; char *xdef; char **xp; xx_strp f; {
        !          1118:  
        !          1119:     int x, i;
        !          1120:     char *xx, *zq;
        !          1121:     static int xc;
        !          1122:  
        !          1123:     debug(F101,"cmtxt, cmflgs","",cmflgs);
        !          1124:     cc = 0;                             /* Start atmbuf counter off at 0 */
        !          1125:     if (cmflgs == -1) {                 /* If reparsing, */
        !          1126:         xc = (int)strlen(*xp);         /* get back the total text length, */
        !          1127:     } else {                            /* otherwise, */
        !          1128:         *xp = "";                       /* start fresh. */
        !          1129:         xc = 0;
        !          1130:     }
        !          1131:     *atmbuf = NUL;                      /* And empty the atom buffer. */
        !          1132:     if ((x = cmflgs) != 1) {
        !          1133:         x = gtword();                   /* Get first word. */
        !          1134:         *xp = pp;                       /* Save pointer to it. */
        !          1135:     }
        !          1136:     debug(F101,"cmtxt (*f)","", f);
        !          1137:     while (1) {                                /* Loop for each word in text. */
        !          1138:         xc += cc;                       /* Char count for all words. */
        !          1139:         debug(F111,"cmtxt: gtword",atmbuf,xc);
        !          1140:         debug(F101," x","",x);
        !          1141:         switch (x) {
        !          1142:          case -9:                      /* Buffer overflow */
        !          1143:          case -4:                      /* EOF */
        !          1144: #ifdef MAC
        !          1145:          case -3:                      /* Quit/Timeout */
        !          1146: #endif /* MAC */
        !          1147:          case -2:                      /* Overflow */
        !          1148:          case -1:                      /* Deletion */
        !          1149:            return(x);
        !          1150:          case 0:                       /* Space */
        !          1151:            xc++;                       /* Just count it */
        !          1152:            break;
        !          1153:          case 1:                       /* CR or LF */
        !          1154:            if (xc == 0) *xp = xdef;
        !          1155:            if (f) {                    /* If a conversion function is given */
        !          1156:                zq = atxbuf;            /* Point to the expansion buffer */
        !          1157:                atxn = CMDBL;           /* specify its length */
        !          1158:                debug(F110,"cmtxt calling (*f)",*xp,0);
        !          1159:                if ((x = (*f)(*xp,&zq,&atxn)) < 0) return(-2);
        !          1160:                cc = (int)strlen(atxbuf);
        !          1161:                *xp = atxbuf;           /* and return pointer to it. */
        !          1162:                debug(F111,"cmtxt (*f) returns",*xp,cc);
        !          1163:            }
        !          1164:            xx = *xp;
        !          1165:            for (i = (int)strlen(xx) - 1; i > 0; i--)
        !          1166:              if (xx[i] != SP)          /* Trim trailing blanks */
        !          1167:                break;
        !          1168:              else
        !          1169:                xx[i] = NUL;
        !          1170:            return(x);
        !          1171:          case 2:                       /* ESC */
        !          1172:            if (xc == 0) {
        !          1173:                printf("%s ",xdef);
        !          1174: #ifdef GEMDOS
        !          1175:                fflush(stdout);
        !          1176: #endif /* GEMDOS */
        !          1177:                cc = addbuf(xdef);
        !          1178:            } else {
        !          1179:                putchar(BEL);
        !          1180:            }
        !          1181:            break;
        !          1182:          case 3:                       /* Question Mark */
        !          1183:            if (*xhlp == NUL)
        !          1184:              printf(" Text string");
        !          1185:            else
        !          1186:              printf(" %s",xhlp);
        !          1187:            printf("\n%s%s",cmprom,cmdbuf);
        !          1188:            fflush(stdout);
        !          1189:            break;
        !          1190:          default:
        !          1191:            printf("?Unexpected return code from gtword() - %d\n",x);
        !          1192:            return(-2);
        !          1193:         }
        !          1194:         x = gtword();
        !          1195:     }
        !          1196: }
        !          1197: 
        !          1198:  
        !          1199: /*  C M K E Y  --  Parse a keyword  */
        !          1200:  
        !          1201: /*
        !          1202:  Call with:
        !          1203:    table    --  keyword table, in 'struct keytab' format;
        !          1204:    n        --  number of entries in table;
        !          1205:    xhlp     --  pointer to help string;
        !          1206:    xdef     --  pointer to default keyword;
        !          1207:  
        !          1208:  Returns:
        !          1209:    -3       --  no input supplied and no default available
        !          1210:    -2       --  input doesn't uniquely match a keyword in the table
        !          1211:    -1       --  user deleted too much, command reparse required
        !          1212:     n >= 0  --  value associated with keyword
        !          1213: */
        !          1214: int 
        !          1215: cmkey(table,n,xhlp,xdef,f)
        !          1216: /* cmkey */  struct keytab table[]; int n; char *xhlp, *xdef; xx_strp f; {
        !          1217:     return(cmkey2(table,n,xhlp,xdef,"",f));
        !          1218: }
        !          1219: int
        !          1220: cmkey2(table,n,xhlp,xdef,tok,f)
        !          1221:     struct keytab table[]; int n; char *xhlp, *xdef; char *tok; xx_strp f; {
        !          1222: 
        !          1223:     int i, tl, y, z, zz, xc;
        !          1224:     char *xp, *zq;
        !          1225:  
        !          1226:     tl = (int)strlen(tok);
        !          1227:     xc = cc = 0;                        /* Clear character counters. */
        !          1228:  
        !          1229:     if ((zz = cmflgs) == 1)             /* Command already entered? */
        !          1230:       setatm(xdef);                    /* Yes, copy default into atom buf */
        !          1231:     else zz = gtword();                        /* Otherwise get a command word */
        !          1232:  
        !          1233: debug(F101,"cmkey: table length","",n);
        !          1234: debug(F101," cmflgs","",cmflgs);
        !          1235: debug(F101," zz","",zz);
        !          1236: while (1) {
        !          1237:     xc += cc;
        !          1238:     debug(F111,"cmkey: gtword",atmbuf,xc);
        !          1239:  
        !          1240:     switch(zz) {
        !          1241:         case -4:                        /* EOF */
        !          1242: #ifdef MAC
        !          1243:        case -3:                        /* Quit/Timeout */
        !          1244: #endif /* MAC */
        !          1245:         case -2:                        /* Buffer overflow */
        !          1246:         case -1:                        /* Or user did some deleting. */
        !          1247:             return(zz);
        !          1248:  
        !          1249:         case 0:                         /* User terminated word with space */
        !          1250:         case 1:                         /* or newline */
        !          1251:             if (cc == 0) setatm(xdef); /* Supply default if user typed nada */
        !          1252:            if (f) {                    /* If a conversion function is given */
        !          1253:                zq = atxbuf;            /* apply it */
        !          1254:                atxn = CMDBL;
        !          1255:                if ((*f)(atmbuf,&zq,&atxn) < 0) return(-2);
        !          1256:                debug(F110,"cmkey atxbuf after *f",atxbuf,0);
        !          1257:                cc = setatm(atxbuf);
        !          1258:            }
        !          1259:             y = lookup(table,atmbuf,n,&z); /* Look up the word in the table */
        !          1260:             switch (y) {
        !          1261:                 case -2:               /* Ambiguous */
        !          1262:                     printf("?Ambiguous - %s\n",atmbuf);
        !          1263:                    cmflgs = -2;
        !          1264:                     return(-9);
        !          1265:                 case -1:               /* Not found at all */
        !          1266:                    if (tl) {
        !          1267:                        for (i = 0; i < tl; i++) /* Check for token */
        !          1268:                          if (tok[i] == *atmbuf) { /* Got one */
        !          1269:                              ungword();  /* Put back the following word */
        !          1270:                              return(-5); /* Special return code for token */
        !          1271:                          }
        !          1272:                    }
        !          1273:                    /* Kludge alert... only print error if */
        !          1274:                    /* we were called as cmkey2, but not cmkey... */
        !          1275:                    /* This doesn't seem to always work. */
        !          1276:                    if (tl == 0) {
        !          1277:                        printf("?No keywords match - %s\n",atmbuf); /* cmkey */
        !          1278:                        return(cmflgs = -9);
        !          1279:                    } else { 
        !          1280:                        if (cmflgs == 1) return(cmflgs = -6); /* cmkey2 */
        !          1281:                        else return(cmflgs = -2);
        !          1282:                        /* The -6 code is to let caller try another table */
        !          1283:                    }
        !          1284:                 default:
        !          1285:                     break;
        !          1286:                }
        !          1287:             return(y);
        !          1288:  
        !          1289:         case 2:                         /* User terminated word with ESC */
        !          1290:             if (cc == 0) {
        !          1291:                 if (*xdef != NUL) {     /* Nothing in atmbuf */
        !          1292:                     printf("%s ",xdef); /* Supply default if any */
        !          1293: #ifdef GEMDOS
        !          1294:                    fflush(stdout);
        !          1295: #endif /* GEMDOS */
        !          1296:                     addbuf(xdef);
        !          1297:                     cc = setatm(xdef);
        !          1298:                     debug(F111,"cmkey: default",atmbuf,cc);
        !          1299:                 } else {
        !          1300:                     putchar(BEL);       /* No default, just beep */
        !          1301:                     break;
        !          1302:                 }
        !          1303:             }
        !          1304:            if (f) {                    /* If a conversion function is given */
        !          1305:                zq = atxbuf;            /* apply it */
        !          1306:                atxn = CMDBL;
        !          1307:                if ((*f)(atmbuf,&zq,&atxn) < 0) return(-2);
        !          1308:                cc = setatm(atxbuf);
        !          1309:            }
        !          1310:             y = lookup(table,atmbuf,n,&z); /* Something in atmbuf */
        !          1311:             debug(F111,"cmkey: esc",atmbuf,y);
        !          1312:             if (y == -2) {
        !          1313:                 putchar(BEL);
        !          1314:                 break;
        !          1315:             }
        !          1316:             if (y == -1) {
        !          1317:                 /* if (tl == 0) */ printf("?No keywords match - %s\n",atmbuf);
        !          1318:                cmflgs = -2;
        !          1319:                 return(-9);
        !          1320:             }
        !          1321:             xp = table[z].kwd + cc;
        !          1322:             printf("%s ",xp);
        !          1323: #ifdef GEMDOS
        !          1324:            fflush(stdout);
        !          1325: #endif /* GEMDOS */
        !          1326:             addbuf(xp);
        !          1327:             debug(F110,"cmkey: addbuf",cmdbuf,0);
        !          1328:             return(y);
        !          1329:  
        !          1330:         case 3:                         /* User terminated word with "?" */
        !          1331:            if (f) {                    /* If a conversion function is given */
        !          1332:                zq = atxbuf;
        !          1333:                atxn = CMDBL;
        !          1334:                if ((*f)(atmbuf,&zq,&atxn) < 0) return(-2);
        !          1335:                cc = setatm(atxbuf);
        !          1336:            }
        !          1337:             y = lookup(table,atmbuf,n,&z);
        !          1338: 
        !          1339:            if (y == -1) {
        !          1340:                 /* if (tl == 0) */ printf(" No keywords match\n");
        !          1341:                cmflgs = -2;
        !          1342:                 return(-9);
        !          1343:             } else if (y > -1 && !test(table[z].flgs,CM_ABR)) {
        !          1344:                 printf(" %s\n%s%s",table[z].kwd,cmprom,cmdbuf);
        !          1345:                fflush(stdout);
        !          1346:                 break;
        !          1347:             } 
        !          1348:             if (*xhlp == NUL)
        !          1349:                 printf(" One of the following:\n");
        !          1350:             else
        !          1351:                 printf(" %s, one of the following:\n",xhlp);
        !          1352:  
        !          1353:             clrhlp();
        !          1354:             for (i = 0; i < n; i++) {   
        !          1355:                 if (!strncmp(table[i].kwd,atmbuf,cc)
        !          1356:                    && !test(table[i].flgs,CM_INV)
        !          1357:                    )
        !          1358:                     addhlp(table[i].kwd);
        !          1359:             }
        !          1360:             dmphlp();
        !          1361:            if (*atmbuf == NUL) {
        !          1362:                if (tl == 1)
        !          1363:                  printf("or the token '%c'\n",*tok);
        !          1364:                else if (tl > 1) printf("or one of the tokens '%s'\n",tok);
        !          1365:            }
        !          1366:             printf("%s%s", cmprom, cmdbuf);
        !          1367:            fflush(stdout);
        !          1368:             break;
        !          1369:  
        !          1370:         default:            
        !          1371:             printf("\n%d - Unexpected return code from gtword\n",zz);
        !          1372:             return(cmflgs = -2);
        !          1373:         }
        !          1374:         zz = gtword();
        !          1375:     }
        !          1376: }
        !          1377: int
        !          1378: chktok(tlist) char *tlist; {
        !          1379:     char *p;
        !          1380:     p = tlist;
        !          1381:     while (*p != NUL && *p != *atmbuf) p++;
        !          1382:     return((*p) ? (int) *p : 0);
        !          1383: }
        !          1384: 
        !          1385: /*  C M C F M  --  Parse command confirmation (end of line)  */
        !          1386:  
        !          1387: /*
        !          1388:  Returns
        !          1389:    -2: User typed anything but whitespace or newline
        !          1390:    -1: Reparse needed
        !          1391:     0: Confirmation was received
        !          1392: */
        !          1393: int 
        !          1394: cmcfm() {
        !          1395:     int x, xc;
        !          1396:  
        !          1397:     debug(F101,"cmcfm: cmflgs","",cmflgs);
        !          1398:  
        !          1399:     xc = cc = 0;
        !          1400:     if (cmflgs == 1) return(0);
        !          1401:  
        !          1402:     while (1) {
        !          1403:         x = gtword();
        !          1404:         xc += cc;
        !          1405:         debug(F111,"cmcfm: gtword",atmbuf,xc);
        !          1406:         switch (x) {
        !          1407:             case -4:                    /* EOF */
        !          1408:             case -2:
        !          1409:             case -1:
        !          1410:                 return(x);
        !          1411:  
        !          1412:             case 1:                     /* End of line */
        !          1413:                 if (xc > 0) {
        !          1414:                     printf("?Not confirmed - %s\n",atmbuf);
        !          1415:                     return(-9);
        !          1416:                 } else return(0);                   
        !          1417:             case 2:                    /* ESC */
        !          1418:                if (xc == 0) {
        !          1419:                    putchar(BEL);       /* beep & continue */
        !          1420:                    continue;           /* or fall thru. */
        !          1421:                }
        !          1422:             case 0:                     /* Space */
        !          1423:                if (xc == 0)            /* If no chars type, continue, */
        !          1424:                  continue;             /* else fall thru. */
        !          1425:             case 3:                    /* Question mark */
        !          1426:                 if (xc > 0) {
        !          1427:                     printf("?Not confirmed - %s\n",atmbuf);
        !          1428:                     return(-9);
        !          1429:                 }
        !          1430:                 printf("\n Type a carriage return to confirm the command\n");
        !          1431:                 printf("%s%s",cmprom,cmdbuf);
        !          1432:                fflush(stdout);
        !          1433:                 continue;
        !          1434:         }
        !          1435:     }
        !          1436: }
        !          1437: 
        !          1438: /* Keyword help routines */
        !          1439:  
        !          1440:  
        !          1441: /*  C L R H L P -- Initialize/Clear the help line buffer  */
        !          1442:  
        !          1443: VOID
        !          1444: clrhlp() {                              /* Clear the help buffer */
        !          1445:     hlpbuf[0] = NUL;
        !          1446:     hh = hx = 0;
        !          1447: }
        !          1448:  
        !          1449:  
        !          1450: /*  A D D H L P  --  Add a string to the help line buffer  */
        !          1451:  
        !          1452: VOID
        !          1453: addhlp(s) char *s; {                    /* Add a word to the help buffer */
        !          1454:     int j;
        !          1455:  
        !          1456:     hh++;                               /* Count this column */
        !          1457:  
        !          1458:     for (j = 0; (j < hc) && (*s != NUL); j++) { /* Fill the column */
        !          1459:         hlpbuf[hx++] = *s++;
        !          1460:     }
        !          1461:     if (*s != NUL)                      /* Still some chars left in string? */
        !          1462:         hlpbuf[hx-1] = '+';             /* Mark as too long for column. */
        !          1463:  
        !          1464:     if (hh < (hw / hc)) {               /* Pad col with spaces if necessary */
        !          1465:         for (; j < hc; j++) {
        !          1466:             hlpbuf[hx++] = SP;
        !          1467:         }
        !          1468:     } else {                            /* If last column, */
        !          1469:         hlpbuf[hx++] = NUL;             /* no spaces. */
        !          1470:         dmphlp();                       /* Print it. */
        !          1471:         return;
        !          1472:     }
        !          1473: }
        !          1474:  
        !          1475:  
        !          1476: /*  D M P H L P  --  Dump the help line buffer  */
        !          1477:  
        !          1478: VOID
        !          1479: dmphlp() {                              /* Print the help buffer */
        !          1480:     hlpbuf[hx++] = NUL;
        !          1481:     printf(" %s\n",hlpbuf);
        !          1482:     clrhlp();
        !          1483: }
        !          1484: 
        !          1485:  
        !          1486: /*  G T W O R D  --  Gets a "word" from the command input stream  */
        !          1487:  
        !          1488: /*
        !          1489: Usage: retcode = gtword();
        !          1490:  
        !          1491: Returns:
        !          1492:  -4 if end of file (e.g. pipe broken)
        !          1493:  -2 if command buffer overflows
        !          1494:  -1 if user did some deleting
        !          1495:   0 if word terminates with SP or tab
        !          1496:   1 if ... CR
        !          1497:   2 if ... ESC
        !          1498:   3 if ... ? (question mark)
        !          1499:  
        !          1500: With:
        !          1501:   pp pointing to beginning of word in buffer
        !          1502:   bp pointing to after current position
        !          1503:   atmbuf containing a copy of the word
        !          1504:   cc containing the number of characters in the word copied to atmbuf
        !          1505: */
        !          1506: 
        !          1507: int
        !          1508: ungword() {                            /* unget a word */
        !          1509:     if (ungw) return(0);
        !          1510:     cmfsav = cmflgs;
        !          1511:     debug(F101,"ungword cmflgs","",cmflgs);
        !          1512:     ungw = 1;
        !          1513:     cmflgs = 0;
        !          1514:     return(0);
        !          1515: }
        !          1516: 
        !          1517: int
        !          1518: gtword() {
        !          1519:     int c;                              /* Current char */
        !          1520:     static int inword = 0;              /* Flag for start of word found */
        !          1521:     int quote = 0;                      /* Flag for quote character */
        !          1522:     int echof = 0;                      /* Flag for whether to echo */
        !          1523:     int chsrc = 0;                     /* Source of character, 1 = tty */
        !          1524:     int comment = 0;                   /* Flag for in comment */
        !          1525:     char *cp = NULL;                   /* Comment pointer */
        !          1526: 
        !          1527: #ifdef RTU
        !          1528:     extern int rtu_bug;
        !          1529: #endif /* RTU */
        !          1530: 
        !          1531: #ifdef datageneral
        !          1532:     extern int termtype;                /* DG terminal type flag */
        !          1533:     extern int con_reads_mt;            /* Console read asynch is active */
        !          1534:     if (con_reads_mt) connoi_mt();      /* Task would interfere w/cons read */
        !          1535: #endif /* datageneral */
        !          1536:  
        !          1537:     if (ungw) {                                /* Have a word saved? */
        !          1538:        debug(F110,"gtword ungetting from pp",pp,0);
        !          1539:        while (*pp++ == SP) ;
        !          1540:        setatm(pp);
        !          1541:        ungw = 0;
        !          1542:        cmflgs = cmfsav;
        !          1543:        debug(F111,"gtword returning atmbuf",atmbuf,cmflgs);
        !          1544:        return(cmflgs);
        !          1545:     }
        !          1546:     pp = np;                            /* Start of current field */
        !          1547: 
        !          1548: #ifdef COMMENT
        !          1549:     debug(F111,"gtword: cmdbuf",cmdbuf,(int) cmdbuf);
        !          1550:     debug(F111," bp",bp,(int) bp);
        !          1551:     debug(F111," pp",pp,(int) pp);
        !          1552: #endif /* COMMENT */
        !          1553:  
        !          1554:     while (bp < cmdbuf+CMDBL) {         /* Big get-a-character loop */
        !          1555:        echof = 0;                      /* Assume we don't echo because */
        !          1556:        chsrc = 0;                      /* character came from reparse buf. */
        !          1557: 
        !          1558:         if ((c = *bp) == NUL) {         /* If no char waiting in reparse buf */
        !          1559:             if (dpx) echof = 1;         /* must get from tty, set echo flag. */
        !          1560:            c = cmdgetc();              /* Read a character from the tty. */
        !          1561:            chsrc = 1;                  /* Remember character source is tty. */
        !          1562: #ifdef MAC
        !          1563:            if (c == -3)                /* If null command... */
        !          1564:              return(-3);
        !          1565: #endif /* MAC */
        !          1566:             if (c == EOF) {            /* This can happen if stdin not tty. */
        !          1567: #ifdef EINTR
        !          1568:                if (errno == EINTR)     /* This is for when bg'd process is */
        !          1569:                  continue;             /* fg'd again. */
        !          1570: #endif /* EINTR */
        !          1571:                return(-4);
        !          1572:            }
        !          1573:            c &= cmdmsk;                /* Strip any parity bit */
        !          1574:        }                               /* if desired. */
        !          1575: #ifndef MAC
        !          1576:        debug(F000,"gtword char","",c);
        !          1577: #endif /* MAC */
        !          1578: 
        !          1579: /* Now we have the next character */
        !          1580: 
        !          1581:         if (quote == 0) {              /* If this is not a quoted character */
        !          1582:             if (c == CMDQ) {           /* Got the quote character itself */
        !          1583:                if (!comment) quote = 1; /* Flag it if not in a comment */
        !          1584:             }
        !          1585:            if (c == FF) {              /* Formfeed. */
        !          1586:                 c = NL;                 /* Replace with newline */
        !          1587: #ifdef COMMENT
        !          1588: /* No more screen clearing... */
        !          1589:                cmdclrscn();            /* Clear the screen */
        !          1590: #endif
        !          1591:             }
        !          1592:            if (c == HT) {              /* Tab */
        !          1593:                if (comment)            /* If in comment, */
        !          1594:                  c = SP;               /* substitute space */
        !          1595:                else                    /* otherwise */
        !          1596:                  c = ESC;              /* substitute ESC (for completion) */
        !          1597:            }
        !          1598:            if (c == ';' || c == '#') { /* Trailing comment */
        !          1599:                if (inword == 0) {      /* If we're not in a word */
        !          1600:                    comment = 1;        /* start a comment. */
        !          1601:                    cp = bp;            /* remember where it starts. */
        !          1602:                }
        !          1603:            }
        !          1604:            if (!comment && c == SP) {  /* Space */
        !          1605:                 *bp++ = c;             /* deposit in buffer if not already */
        !          1606:                 if (echof) putchar(c);  /* echo it. */
        !          1607:                 if (inword == 0) {      /* If leading, gobble it. */
        !          1608:                     pp++;
        !          1609:                     continue;
        !          1610:                 } else {                /* If terminating, return. */
        !          1611:                     np = bp;
        !          1612:                     setatm(pp);
        !          1613:                     inword = 0;
        !          1614:                    return(cmflgs = 0);
        !          1615:                 }
        !          1616:             }
        !          1617:             if (c == NL || c == CR) {   /* CR or LF. */
        !          1618:                if (echof) cmdnewl((char)c); /* Echo it. */
        !          1619:                if (*(bp-1) == '-') {   /* Is this line continued? */
        !          1620:                    if (chsrc) {        /* If reading from tty, */
        !          1621:                        bp--;           /* back up the buffer pointer, */
        !          1622:                        *bp = NUL;      /* erase the dash, */
        !          1623:                        continue;       /* and go back for next char now. */
        !          1624:                    }
        !          1625:                } else {                /* No, a command has been entered. */
        !          1626:                    *bp = NUL;          /* Terminate the command string. */
        !          1627:                    if (comment) {      /* If we're in a comment, */
        !          1628:                        comment = 0;    /* Say we're not any more, */
        !          1629:                        *cp = NUL;      /* cut it off. */
        !          1630:                    }
        !          1631:                    np = bp;            /* Where to start next field. */
        !          1632:                    setatm(pp);         /* Copy this field to atom buffer. */
        !          1633:                    inword = 0;         /* Not in a word any more. */
        !          1634:                    return(cmflgs = 1);
        !          1635:                }
        !          1636:             }
        !          1637:             if (!comment && echof && (c == '?')) { /* Question mark */
        !          1638:                 putchar(c);
        !          1639:                 *bp = NUL;
        !          1640:                 setatm(pp);
        !          1641:                 return(cmflgs = 3);
        !          1642:             }
        !          1643:             if (c == ESC) {            /* ESC */
        !          1644:                if (!comment) {
        !          1645:                    *bp = NUL;
        !          1646:                    setatm(pp);
        !          1647:                    return(cmflgs = 2);
        !          1648:                } else {
        !          1649:                    putchar(BEL);
        !          1650:                    continue;
        !          1651:                }
        !          1652:             }
        !          1653:             if (c == BS || c == RUB) {  /* Character deletion */
        !          1654:                 if (bp > cmdbuf) {      /* If still in buffer... */
        !          1655:                    cmdchardel();       /* erase it. */
        !          1656:                     bp--;               /* point behind it, */
        !          1657:                     if (*bp == SP) inword = 0; /* Flag if current field gone */
        !          1658:                     *bp = NUL;          /* Erase character from buffer. */
        !          1659:                 } else {                /* Otherwise, */
        !          1660:                     putchar(BEL);       /* beep, */
        !          1661:                     cmres();            /* and start parsing a new command. */
        !          1662:                 }
        !          1663:                 if (pp < bp) continue;
        !          1664:                 else return(cmflgs = -1);
        !          1665:             }
        !          1666:             if (c == LDEL) {            /* ^U, line deletion */
        !          1667:                 while ((bp--) > cmdbuf) {
        !          1668:                     cmdchardel();
        !          1669:                     *bp = NUL;
        !          1670:                 }
        !          1671:                 cmres();                /* Restart the command. */
        !          1672:                 inword = 0;
        !          1673:                 return(cmflgs = -1);
        !          1674:             }
        !          1675:             if (c == WDEL) {            /* ^W, word deletion */
        !          1676:                 if (bp <= cmdbuf) {     /* Beep if nothing to delete */
        !          1677:                     putchar(BEL);
        !          1678:                     cmres();
        !          1679:                     return(cmflgs = -1);
        !          1680:                 }
        !          1681:                 bp--;
        !          1682:                 for ( ; (bp >= cmdbuf) && (*bp == SP) ; bp--) {
        !          1683:                     cmdchardel();
        !          1684:                     *bp = NUL;
        !          1685:                 }
        !          1686:                 for ( ; (bp >= cmdbuf) && (*bp != SP) ; bp--) {
        !          1687:                     cmdchardel();
        !          1688:                     *bp = NUL;
        !          1689:                 }
        !          1690:                 bp++;
        !          1691:                 inword = 0;
        !          1692:                 return(cmflgs = -1);
        !          1693:             }
        !          1694:             if (c == RDIS) {            /* ^R, redisplay */
        !          1695:                 *bp = NUL;
        !          1696:                 printf("\n%s%s",cmprom,cmdbuf);
        !          1697:                fflush(stdout);
        !          1698:                 continue;
        !          1699:             }
        !          1700:            if (c < SP && quote == 0) { /* Any other unquoted ctrl char */
        !          1701:                if (!chsrc) bp++;       /* If cmd file, point past it */
        !          1702:                else putchar(BEL);      /* otherwise just beep and */
        !          1703:                continue;               /* continue, don't put in buffer */
        !          1704:            }
        !          1705:         } else {                       /* This character was quoted. */
        !          1706:            quote = 0;                  /* Unset the quote flag. */
        !          1707:            /* Quote character at this level is only for SP, ?, and controls */
        !          1708:             /* If anything else was quoted, leave quote in, and let */
        !          1709:            /* the command-specific parsing routines handle it, e.g. \007 */
        !          1710:            if (c > 32 && c != '?' && c != RUB && chsrc != 0)
        !          1711:              *bp++ = CMDQ;             /* Deposit \ if it came from tty */
        !          1712:            debug(F110,"gtword quote",cmdbuf,0);
        !          1713:        }
        !          1714:         if (echof) cmdecho((char) c,quote); /* Echo what was typed. */
        !          1715:         if (!comment) inword = 1;      /* Flag we're in a word. */
        !          1716:        if (quote) continue;            /* Don't deposit quote character. */
        !          1717:         if (c != NL) *bp++ = c;                /* Deposit command character. */
        !          1718:         /*** debug(F110,"gtword deposit",cmdbuf,0); ***/
        !          1719:     }                                   /* End of big while */
        !          1720:     putchar(BEL);                       /* Get here if... */
        !          1721:     printf("?Command too long, maximum length: %d.\n",CMDBL);
        !          1722:     cmflgs = -2;
        !          1723:     return(-9);
        !          1724: }
        !          1725: 
        !          1726: /* Utility functions */
        !          1727:  
        !          1728: /* A D D B U F  -- Add the string pointed to by cp to the command buffer  */
        !          1729:  
        !          1730: int
        !          1731: addbuf(cp) char *cp; {
        !          1732:     int len = 0;
        !          1733:     while ((*cp != NUL) && (bp < cmdbuf+CMDBL)) {
        !          1734:         *bp++ = *cp++;                  /* Copy and */
        !          1735:         len++;                          /* count the characters. */
        !          1736:     }   
        !          1737:     *bp++ = SP;                         /* Put a space at the end */
        !          1738:     *bp = NUL;                          /* Terminate with a null */
        !          1739:     np = bp;                            /* Update the next-field pointer */
        !          1740:     return(len);                        /* Return the length */
        !          1741: }
        !          1742:  
        !          1743: /*  S E T A T M  --  Deposit a token in the atom buffer.  */
        !          1744: /*  Break on space, newline, carriage return, or null. */
        !          1745: /*  Null-terminate the result. */
        !          1746: /*  If the source pointer is the atom buffer itself, do nothing. */
        !          1747: /*  Return length of token, and also set global "cc" to this length. */
        !          1748: 
        !          1749: int
        !          1750: setatm(cp) char *cp; {
        !          1751:     char *ap, *xp;
        !          1752: 
        !          1753:     cc = 0;                            /* Character counter */
        !          1754:     ap = atmbuf;                       /* Address of atom buffer */
        !          1755: 
        !          1756:     if (cp == ap) {                    /* In case source is atom buffer */
        !          1757:        xp = atybuf;                    /* make a copy */
        !          1758:        strcpy(xp,ap);                  /* so we can copy it back, edited. */
        !          1759:        cp = xp;
        !          1760:     }
        !          1761:     *ap = NUL;                         /* Zero the atom buffer */
        !          1762: 
        !          1763:     while (*cp == SP) cp++;            /* Trim leading spaces */
        !          1764:     while ((*cp != SP) && (*cp != NL) && (*cp != NUL) && (*cp != CR)) {
        !          1765:         *ap++ = *cp++;                 /* Copy up to SP, NL, CR, or end */
        !          1766:         cc++;                          /* and count */
        !          1767:     }
        !          1768:     *ap = NUL;                         /* Terminate the string. */
        !          1769:     return(cc);                         /* Return length. */
        !          1770: }
        !          1771:  
        !          1772: /*  R D I G I T S  -- Verify that all the characters in line ARE DIGITS  */
        !          1773:  
        !          1774: int
        !          1775: rdigits(s) char *s; {
        !          1776:     while (*s) {
        !          1777:         if (!isdigit(*s)) return(0);
        !          1778:         s++;
        !          1779:     }
        !          1780:     return(1);
        !          1781: }
        !          1782: 
        !          1783: /* These functions attempt to hide system dependencies from the mainline */
        !          1784: /* code in gtword().  Ultimately they should be moved to ck?tio.c, where */
        !          1785: /* ? = each and every system supported by C-Kermit. */
        !          1786: 
        !          1787: int
        !          1788: cmdgetc() {                            /* Get a character from the tty. */
        !          1789:     int c;
        !          1790: 
        !          1791: #ifdef datageneral
        !          1792:     {
        !          1793:        char ch;
        !          1794:        c = dgncinb(0,&ch,1);           /* -1 is EOF, -2 TO, 
        !          1795:                                          * -c is AOS/VS error */
        !          1796:        if (c == -2) {                  /* timeout was enabled? */
        !          1797:            resto(channel(0));          /* reset timeouts */
        !          1798:            c = dgncinb(0,&ch,1);       /* retry this now! */
        !          1799:        }
        !          1800:        if (c < 0) return(-4);          /* EOF or some error */
        !          1801:        else c = (int) ch & 0177;       /* Get char without parity */
        !          1802: /*     echof = 1; */
        !          1803:     }
        !          1804: #else /* Not datageneral */
        !          1805: #ifdef GEMDOS
        !          1806:     c = isatty(0) ? coninc(0) : getchar();
        !          1807: #else
        !          1808: #ifdef OS2
        !          1809:     c = isatty(0) ? coninc(0) : getchar();
        !          1810:     if (c < 0) return(-4);
        !          1811: #else /* Not OS2 */
        !          1812:     c = getchar();                     /* or from tty. */
        !          1813: #ifdef RTU
        !          1814:     if (rtu_bug) {
        !          1815:        c = getchar();                  /* RTU doesn't discard the ^Z */
        !          1816:        rtu_bug = 0;
        !          1817:     }
        !          1818: #endif /* RTU */
        !          1819: #endif /* OS2 */
        !          1820: #endif /* GEMDOS */
        !          1821: #endif /* datageneral */
        !          1822:     return(c);                         /* Return what we got */
        !          1823: }
        !          1824: 
        !          1825: 
        !          1826: #ifdef COMMENT
        !          1827: /*
        !          1828:   No more screen clearing.  If you wanna clear the screen, define a macro
        !          1829:   to do it, like "define cls write screen \27[;H\27[2J".
        !          1830: */
        !          1831: cmdclrscn() {                          /* Clear the screen */
        !          1832: 
        !          1833: #ifdef aegis
        !          1834:     putchar(FF);
        !          1835: #else
        !          1836: #ifdef AMIGA
        !          1837:     putchar(FF);
        !          1838: #else
        !          1839: #ifdef OSK
        !          1840:     putchar(FF);
        !          1841: #else
        !          1842: #ifdef datageneral
        !          1843:     putchar(FF);
        !          1844: #else
        !          1845: #ifdef OS2
        !          1846:     zsystem("cls");
        !          1847: #else
        !          1848:     zsystem("clear");
        !          1849: #endif /* OS2 */
        !          1850: #endif /* datageneral */
        !          1851: #endif /* OSK */
        !          1852: #endif /* AMIGA */
        !          1853: #endif /* aegis */
        !          1854: }
        !          1855: #endif /* COMMENT */
        !          1856: 
        !          1857: VOID                                   /* What to echo at end of command */
        !          1858: #ifdef CK_ANSIC
        !          1859: cmdnewl(char c)
        !          1860: #else
        !          1861: cmdnewl(c) char c;
        !          1862: #endif /* CK_ANSIC */
        !          1863: /* cmdnewl */ {
        !          1864:     putchar(c);                                /* c is the terminating character */
        !          1865: #ifdef OS2
        !          1866:     if (c == CR) putchar(NL);
        !          1867: #endif /* OS2 */
        !          1868: #ifdef aegis
        !          1869:     if (c == CR) putchar(NL);
        !          1870: #endif /* aegis */
        !          1871: #ifdef AMIGA
        !          1872:     if (c == CR) putchar(NL);
        !          1873: #endif /* AMIGA */
        !          1874: #ifdef datageneral
        !          1875:     if (c == CR) putchar(NL);
        !          1876: #endif /* datageneral */
        !          1877: #ifdef GEMDOS
        !          1878:     if (c == CR) putchar(NL);
        !          1879: #endif /* GEMDOS */
        !          1880: }
        !          1881: 
        !          1882: VOID
        !          1883: cmdchardel() {                         /* Erase a character from the screen */
        !          1884: #ifdef datageneral
        !          1885:     /* DG '\b' is EM (^y or \031) */
        !          1886:     if (termtype == 1)
        !          1887:       /* Erase a character from non-DG screen, */
        !          1888:       dgncoub(1,"\010 \010",3);
        !          1889:     else
        !          1890: #endif
        !          1891:       printf("\b \b");
        !          1892: #ifdef GEMDOS
        !          1893:     fflush(stdout);
        !          1894: #endif /* GEMDOS */
        !          1895: }
        !          1896: 
        !          1897: VOID
        !          1898: #ifdef CK_ANSIC
        !          1899: cmdecho(char c, int quote)
        !          1900: #else
        !          1901: cmdecho(c,quote) char c; int quote;
        !          1902: #endif /* CK_ANSIC */
        !          1903: { /* cmdecho */
        !          1904:     /* Echo tty input character c */
        !          1905:     putchar(c);
        !          1906: #ifdef OS2
        !          1907:     if (quote==1 && c==CR) putchar(NL);
        !          1908: #endif /* OS2 */
        !          1909: }
        !          1910: 
        !          1911: #endif /* NOICP */
        !          1912: 
        !          1913: #ifdef NOICP
        !          1914: #include "ckcdeb.h"
        !          1915: #include "ckucmd.h"
        !          1916: #include "ckcasc.h"
        !          1917: /*** #include <ctype.h> (ckcdeb.h already includes this) ***/
        !          1918: #endif /* NOICP */
        !          1919: 
        !          1920: /*  X X E S C  --  Interprets backslash codes  */
        !          1921: /*  Returns the int value of the backslash code if it is > -1 and < 256 */
        !          1922: /*  and updates the string pointer to first character after backslash code. */
        !          1923: /*  If the argument is invalid, leaves pointer unchanged and returns -1. */
        !          1924: 
        !          1925: int
        !          1926: xxesc(s) char **s; {                   /* Expand backslash escapes */
        !          1927:     int x, y, brace, radix;            /* Returns the int value */
        !          1928:     char hd = '9';                     /* Highest digit in radix */
        !          1929:     char *p;
        !          1930: 
        !          1931:     p = *s;                            /* pointer to beginning */
        !          1932:     if (!p) return(-1);                        /* watch out for null pointer */
        !          1933:     x = *p++;                          /* character at beginning */
        !          1934:     if (x != CMDQ) return(-1);         /* make sure it's a backslash code */
        !          1935: 
        !          1936:     x = *p;                            /* it is, get the next character */
        !          1937:     if (x == '{') {                    /* bracketed quantity? */
        !          1938:        p++;                            /* begin past bracket */
        !          1939:        x = *p;
        !          1940:        brace = 1;
        !          1941:     } else brace = 0;
        !          1942:     switch (x) {                       /* Start interpreting */
        !          1943:       case 'd':                                /* Decimal radix indicator */
        !          1944:       case 'D':
        !          1945:        p++;                            /* Just point past it and fall thru */
        !          1946:       case '0':                                /* Starts with digit */
        !          1947:       case '1':
        !          1948:       case '2':  case '3':  case '4':  case '5':
        !          1949:       case '6':  case '7':  case '8':  case '9':
        !          1950:        radix = 10;                     /* Decimal */
        !          1951:        hd = '9';                       /* highest valid digit */
        !          1952:        break;
        !          1953:       case 'o':                                /* Starts with o or O */
        !          1954:       case 'O':
        !          1955:        radix = 8;                      /* Octal */
        !          1956:        hd = '7';                       /* highest valid digit */
        !          1957:        p++;                            /* point past radix indicator */
        !          1958:        break;
        !          1959:       case 'x':                                /* Starts with x or X */
        !          1960:       case 'X':
        !          1961:        radix = 16;                     /* Hexadecimal */
        !          1962:        p++;                            /* point past radix indicator */
        !          1963:        break;
        !          1964:       default:                         /* All others */
        !          1965: #ifdef COMMENT
        !          1966:        *s = p+1;                       /* Treat as quote of next char */
        !          1967:        return(*p);
        !          1968: #else
        !          1969:        return(-1);
        !          1970: #endif /* COMMENT */
        !          1971:     }
        !          1972:     /* For OS/2, there are "wide" characters required for the keyboard
        !          1973:      * binding, i.e \644 and similar codes larger than 255 (byte).
        !          1974:      * For this purpose, give up checking for < 256. If someone means
        !          1975:      * \266 should result in \26 followed by a "6" character, he should
        !          1976:      * always write \{26}6 anyway.  Now, return only the lower byte of
        !          1977:      * the result, i.e. 10, but eat up the whole \266 sequence and
        !          1978:      * put the wide result 266 into a global variable.  Yes, that's not
        !          1979:      * the most beautiful programming style but requires the least
        !          1980:      * amount of changes to other routines.
        !          1981:      */
        !          1982:     if (radix <= 10) {                 /* Number in radix 8 or 10 */
        !          1983:        for ( x = y = 0;
        !          1984:              (*p) && (*p >= '0') && (*p <= hd)
        !          1985: #ifdef OS2
        !          1986:                    && (y < 4) && (x*radix < 768);
        !          1987:               /* the maximum needed value \767 is still only 3 digits long */
        !          1988:               /* while as octal it requires \1377, i.e. 4 digits */
        !          1989: #else
        !          1990:                    && (y < 3) && (x*radix < 256);
        !          1991: #endif /* OS2 */
        !          1992:              p++,y++) {
        !          1993:            x = x * radix + (int) *p - 48;
        !          1994:        }
        !          1995: #ifdef OS2
        !          1996:         wideresult = x;                        /* Remember wide result */
        !          1997:         x &= 255;
        !          1998: #endif /* OS2 */
        !          1999:        if (y == 0 || x > 255) {        /* No valid digits? */
        !          2000:            *s = p;                     /* point after it */
        !          2001:            return(-1);                 /* return failure. */
        !          2002:        }
        !          2003:     } else if (radix == 16) {          /* Special case for hex */
        !          2004:        if ((x = unhex(*p++)) < 0) { *s = p - 1; return(-1); }
        !          2005:        if ((y = unhex(*p++)) < 0) { *s = p - 2; return(-1); }
        !          2006:        x = ((x << 4) & 0xF0) | (y & 0x0F);
        !          2007: #ifdef OS2
        !          2008:         if ((y = unhex(*p)) >= 0) {
        !          2009:            p++;
        !          2010:           wideresult = ((x << 4) & 0xFF0) | (y & 0x0F);
        !          2011:            x = wideresult & 255;
        !          2012:         }
        !          2013: #endif /* OS2 */
        !          2014:     } else x = -1;
        !          2015:     if (brace && *p == '}' && x > -1)  /* Point past closing brace, if any */
        !          2016:       p++;
        !          2017:     *s = p;                            /* Point to next char after sequence */
        !          2018:     return(x);                         /* Return value of sequence */
        !          2019: }
        !          2020: 
        !          2021: int                                    /* Convert hex string to int */
        !          2022: #ifdef CK_ANSIC
        !          2023: unhex(char x)
        !          2024: #else
        !          2025: unhex(x) char x;
        !          2026: #endif /* CK_ANSIC */
        !          2027: /* unhex */ {
        !          2028: 
        !          2029:     if (x >= '0' && x <= '9')          /* 0-9 is offset by hex 30 */
        !          2030:       return(x - 0x30);
        !          2031:     else if (x >= 'A' && x <= 'F')     /* A-F offset by hex 37 */
        !          2032:       return(x - 0x37);
        !          2033:     else if (x >= 'a' && x <= 'f')     /* a-f offset by hex 57 */
        !          2034:       return(x - 0x57);                        /* (obviously ASCII dependent) */
        !          2035:     else return(-1);
        !          2036: }
        !          2037: 
        !          2038: /* See if argument string is numeric */
        !          2039: /* Returns 1 if OK, zero if not OK */
        !          2040: /* If OK, string should be acceptable to atoi() */
        !          2041: /* Allows leading space, sign */
        !          2042: 
        !          2043: int
        !          2044: chknum(s) char *s; {                   /* Check Numeric String */
        !          2045:     int x = 0;                         /* Flag for past leading space */
        !          2046:     int y = 0;                         /* Flag for digit seen */
        !          2047:     char c;
        !          2048:     debug(F110,"chknum",s,0);
        !          2049:     while (c = *s++) {                 /* For each character in the string */
        !          2050:        switch (c) {
        !          2051:          case SP:                      /* Allow leading spaces */
        !          2052:          case HT:
        !          2053:            if (x == 0) continue;
        !          2054:            else return(0);
        !          2055:          case '+':                     /* Allow leading sign */
        !          2056:          case '-':
        !          2057:            if (x == 0) x = 1;
        !          2058:            else return(0);
        !          2059:            break;
        !          2060:          default:                      /* After that, only decimal digits */
        !          2061:            if (c >= '0' && c <= '9') {
        !          2062:                x = y = 1;
        !          2063:                continue;
        !          2064:            } else return(0);
        !          2065:        }
        !          2066:     }
        !          2067:     return(y);
        !          2068: }
        !          2069: 
        !          2070: /*  L O W E R  --  Lowercase a string  */
        !          2071:  
        !          2072: int
        !          2073: lower(s) char *s; {
        !          2074:     int n = 0;
        !          2075:     while (*s) {
        !          2076:         if (isupper(*s)) *s = tolower(*s);
        !          2077:         s++, n++;
        !          2078:     }
        !          2079:     return(n);
        !          2080: }
        !          2081: 
        !          2082: /*  L O O K U P  --  Lookup the string in the given array of strings  */
        !          2083:  
        !          2084: /*
        !          2085:  Call this way:  v = lookup(table,word,n,&x);
        !          2086:  
        !          2087:    table - a 'struct keytab' table.
        !          2088:    word  - the target string to look up in the table.
        !          2089:    n     - the number of elements in the table.
        !          2090:    x     - address of an integer for returning the table array index.
        !          2091:  
        !          2092:  The keyword table must be arranged in ascending alphabetical order, and
        !          2093:  all letters must be lowercase.
        !          2094:  
        !          2095:  Returns the keyword's associated value ( zero or greater ) if found,
        !          2096:  with the variable x set to the array index, or:
        !          2097:  
        !          2098:   -3 if nothing to look up (target was null),
        !          2099:   -2 if ambiguous,
        !          2100:   -1 if not found.
        !          2101:  
        !          2102:  A match is successful if the target matches a keyword exactly, or if
        !          2103:  the target is a prefix of exactly one keyword.  It is ambiguous if the
        !          2104:  target matches two or more keywords from the table.
        !          2105: */
        !          2106:  
        !          2107: int
        !          2108: lookup(table,cmd,n,x) char *cmd; struct keytab table[]; int n, *x; {
        !          2109:  
        !          2110:     int i, v, cmdlen;
        !          2111:  
        !          2112: /* Lowercase & get length of target, if it's null return code -3. */
        !          2113:  
        !          2114:     if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3);
        !          2115:  
        !          2116: /* Not null, look it up */
        !          2117:  
        !          2118:     for (i = 0; i < n-1; i++) {
        !          2119:         if (!strcmp(table[i].kwd,cmd) ||
        !          2120:            ((v = !strncmp(table[i].kwd,cmd,cmdlen)) &&
        !          2121:              strncmp(table[i+1].kwd,cmd,cmdlen))) {
        !          2122:                 *x = i;
        !          2123:                 return(table[i].kwval);
        !          2124:              }
        !          2125:         if (v) return(-2);
        !          2126:     }   
        !          2127:  
        !          2128: /* Last (or only) element */
        !          2129:  
        !          2130:     if (!strncmp(table[n-1].kwd,cmd,cmdlen)) {
        !          2131:         *x = n-1;
        !          2132:         return(table[n-1].kwval);
        !          2133:     } else return(-1);
        !          2134: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.