home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / AZTEC-C / COMND004.ARK / COMND.C < prev    next >
C/C++ Source or Header  |  1986-06-17  |  21KB  |  857 lines

  1. /*    comnd.c        COMND module; Main module.
  2.  
  3.     Copyright (C) 1985 Mark E. Mallett
  4.  
  5.     Permission is hereby granted to distribute this file indiscriminately.
  6.  
  7.     COMND.C, along with its associated files, contains routines which
  8.     provide command parsing facilities of the TOPS-20 style, with
  9.     command recognition, incremental help, and indirection.
  10.  
  11. Edit history
  12.  
  13. When    Who    What
  14. ------    ---    --------------------------------
  15. 84xxxx    MEM    Create file.
  16.  
  17.  
  18.     Routines included:
  19.  
  20.         COMND        The "user" call to parsing.
  21.         COMNDr        General support COMND call
  22.         CMDcab        Collect atom buffer
  23.         CMDspc        Skip leading spaces
  24.         CMDgcc        Get nth unparsed character
  25.         CMDcpt        Checkpoint parsed area
  26.         CMDcpl        Perform command completion
  27.         CMDhlp        Perform common help
  28.         CMDfill        Fill the command line.
  29.  
  30. */
  31.  
  32.  
  33. #include "stdio.h"            /* Standard system defs */
  34. #include "comnd.h"            /* COMND interface definitions */
  35. #include "comndi.h"            /* COMND internal definitions */
  36.  
  37.  
  38. /* External routines */
  39.  
  40. extern        CMDptc();
  41.  
  42. /* External data */
  43.  
  44.  
  45. /* Internal (public) routines */
  46.  
  47.  
  48.  
  49. /* Internal (public) data */
  50.  
  51.     int    CMDbel = {0};        /* Beep count */
  52.     int    CMDgvh = {0};        /* Gave-help count */
  53.     int    (*Cocrtc)() = {CMDptc};    /* Output char routine to call */
  54.  
  55.  
  56. /* Local (static) data */
  57.  
  58.  
  59. static    int    Echofl = {TRUE};    /* Echo on or off */
  60. /*
  61.  
  62. *//* COMND (CSBptr, CFBptr)
  63.  
  64.     The general command call
  65.  
  66. This routine processess a request to parse an element of a command.
  67.  
  68. Accepts :
  69.  
  70.     CSBptr        Address of Command State Block
  71.     CFBptr        Address of Command Function Block
  72.  
  73.  
  74. Returns :
  75.  
  76.     <value>        One of result codes _CRxxx as defined in
  77.               the comnd.h include file
  78.  
  79. */
  80.  
  81. int COMND (CSBptr, CFBptr)
  82.  
  83. CSB        *CSBptr;        /* Addr of command state block */
  84. CFB        *CFBptr;        /* Addr of command function block */
  85.  
  86. {
  87. return (COMNDr (CSBptr, CFBptr, 0));    /* Call comnd in non-support mode */
  88. }
  89. /*
  90.  
  91. *//* COMNDr (CSBptr, CFBptr, sflg)
  92.  
  93.     General COMND support call
  94.  
  95. This routine is the general COMND call, for use by extern or internal
  96. (support) routines.
  97.  
  98. Accepts :
  99.  
  100.     CSBptr        Address of Command State Block
  101.     CFBptr        Address of Command Function Block
  102.     sflg        0 if general call
  103.             1 if first through n-1st support call
  104.             2 if final support call
  105.  
  106.  
  107. Returns :
  108.  
  109.     <value>        One of result codes _CRxxx as defined in
  110.               the comnd.h include file
  111.  
  112.  
  113.  
  114. Notes:
  115.  
  116.     sflg may be set in order to make multiple calls to COMNDr appear
  117. function the same way as a single call to COMND with chained CFBs.  That
  118. is, each successive call to COMNDr in support mode passes a new CFB list
  119. which is a logical extention of the current list.
  120.  
  121.     Please note that routines setting sflg will be returned internal
  122. parse result codes (_CPxxx) rather than the usual external result codes
  123. (_CRxxx), in order to allow full handling of all conditions.
  124.  
  125. */
  126.  
  127. int COMNDr (CSBptr, CFBptr, sflg)
  128.  
  129. CSB        *CSBptr;        /* Addr of command state block */
  130. CFB        *CFBptr;        /* Addr of command function block */
  131. int        sflg;            /* Support-mode flag */
  132.  
  133. {
  134. IND    int    agn;            /* Try-again flag */
  135. IND    int    parse;            /* Parse result */
  136. IND    int    i;            /* Scratch */
  137.     CFB    *CFBcur;        /* Current CFB */
  138. IND    int    c,c1;            /* Char */
  139. IND    char    *sptr;            /* String pointer */
  140.     int    cix;            /* Char index */
  141.  
  142. CSBptr -> CSB_RFL &= (~_CFPFE);        /* Clear prev-was-escape-completed */
  143. if (CSBptr -> CSB_RFL & _CFESC)        /* If last WAS esc completed */
  144.     CSBptr -> CSB_RFL |= _CFPFE;    /*  then set it */
  145.  
  146. while (TRUE)                /* Loop until we have something
  147.                        to return to our gentle caller */
  148.     {
  149.     if (!sflg)                /* Reset things if not support mode */
  150.     {
  151.     CMDbel = 0;            /* Set beep counter to 0 */
  152.     CMDgvh = 0;            /* Set gave-help to 0 */
  153.     agn = FALSE;            /* Try-again to FALSE */
  154.     }
  155.     Echofl = !(CSBptr -> CSB_PFL & _CFNEC);
  156.                     /* Set echo on or off as desired */
  157.     CFBcur = CFBptr;            /* Start at beginning */
  158.     if (CSBptr -> CSB_FLN == -1)    /* If initial */
  159.     {
  160.     CMDfill (CSBptr, CFBptr);    /* Collect input */
  161.     continue;            /*  and skip to end of while loop */
  162.     }
  163.  
  164.     if (!sflg)                /* If not support mode */
  165.     {
  166.     if (CFBcur -> CFB_FLG & _CFDPP)    /* Check out default if any */
  167.         if (sptr = CFBcur -> CFB_DEF) /* (must be non-null ptr) */
  168.         {
  169.         cix = CMDspc (CSBptr);    /* Get inx after spaces */
  170.         c = CMDgcc(CSBptr, cix);
  171.                     /* Get first non-space non-tab */
  172.         cix = cix + CSBptr -> CSB_PRS; /* Get real index */
  173.         c1 = CSBptr -> CSB_BUF[cix]; /* Get real character there */
  174.         if ((c == _CCCMP) || (c == _CCEND))
  175.             {            /* If ok to default */
  176.             if (c == _CCEND)    /* If it was return */
  177.             if ((cix) && (CSBptr->CSB_BUF[cix-1] != ' '))
  178.                 CSBptr->CSB_BUF[cix++] = ' ';
  179.                     /* make sure space separation. */
  180.             strcpy (&CSBptr -> CSB_BUF[cix], sptr);
  181.             CSBptr -> CSB_FLN = cix = cix+strlen(sptr);
  182.             if (c == _CCCMP)    /* If completion */
  183.             {
  184.             CMDpzs (sptr);    /* Show it */
  185.             CMDfob();
  186.             }
  187.             CSBptr -> CSB_BUF[cix] = c1;
  188.             }
  189.         }
  190.     }
  191.  
  192.  
  193.     CSBptr -> CSB_RFL &= (~_CFESC);    /* Clear completed-with-escape */
  194.     while (CFBcur)            /* Go through... */
  195.     {
  196.     CSBptr -> CSB_CFB = CFBcur;    /* Remember which CFB we're at */
  197.     parse = CMDpf(CSBptr, CFBcur);
  198.                     /* Try parse on this function */
  199.     switch (parse)            /* Process the completion code */
  200.         {
  201.         case _CPCPE:        /* Completed with escape */
  202.         CSBptr -> CSB_RFL = _CFESC; /* Indicate to caller */
  203.         if (sflg)        /* If support... */
  204.             return (_CPCPE);    /*  return appropriate code */
  205.         return (_CROK);        /* Return OK */
  206.  
  207.  
  208.         case _CPSUCC:        /* Successfull */
  209.         if (sflg)        /* If support mode */
  210.             return (_CPSUCC);    /*  return success indication */
  211.         return (_CROK);        /*  Return OK */
  212.  
  213.         case _CPABT:        /* Abort */
  214.         if (sflg)        /* If supportmode */
  215.             return (_CPABT);    /*  return the abort flag */
  216.         return (CSBptr -> CSB_RCD); /* Pass back the return code */
  217.  
  218.         case _CPGVH:        /* Gave help */
  219.         CMDgvh++;        /* Count it and act like _CPAGN */
  220.  
  221.         case _CPAGN:        /* Try again... */
  222.         agn = TRUE;        /*  set to try again */
  223.         }
  224.  
  225.     CFBcur = CFBcur -> CFB_CFB;    /* Get next one */
  226.     }
  227.  
  228. /* Gone through all the function blocks.. take appropriate result action */
  229.  
  230.     if (CSBptr -> CSB_PRS == 0)        /* If nothing parsed */
  231.     {
  232.     cix = CMDspc (CSBptr);        /* Skip spaces */
  233.     if (CMDgcc (CSBptr, cix) == _CCEND) /* See if no input */
  234.         {
  235.         CSBptr -> CSB_FLN = -1;    /* Indicate reprompt */
  236.         continue;            /* Go to end of the while loop */
  237.         }
  238.     }
  239.  
  240.     if (!agn)                /* If not to try again */
  241.     {
  242.     if (sflg)            /* If support mode */
  243.         return (_CPNOP);        /*  return internal code */
  244.     return (_CRNOP);        /* Return no-parse */
  245.     }
  246.  
  247.     if (sflg)                /* If supportmode */
  248.     return (_CPAGN);        /*  return that we ought try agn */
  249.  
  250.     if (CMDgvh)                /* If gave help... */
  251.     {
  252.     CMDpoc ('\n');            /* give CR */
  253.     CMDpzs (CSBptr -> CSB_PMT);    /* Output prompt */
  254.     for (i = 0; i < CSBptr -> CSB_FLN; i++)
  255.         CMDpoc (CSBptr -> CSB_BUF[i]); /* Output text typed */
  256.     CMDfob();
  257.     CMDbel = 0;            /* Don't beep */
  258.     }
  259.  
  260.     if (CMDbel)                /* If wanted to beep */
  261.     {
  262.     CMDpoc ('\007');            /* Make a beep */
  263.     CMDfob();
  264.     }
  265.  
  266.     CMDfill (CSBptr, CFBptr);        /* do user editing */
  267.     if (CSBptr -> CSB_RFL & _CFRPT)    /* If reparse indicated */
  268.     {
  269.     CSBptr -> CSB_PRS = 0;        /* Reset the parse pointer */
  270.     if (CSBptr -> CSB_RSB)        /* If any setjmp buffer */
  271.         longjmp (CSBptr -> CSB_RSB, 1); /* Execute the longjump */
  272.     else                /* Otherwise */
  273.         return (_CRRPT);        /* Return re-parse */
  274.     }
  275.     }
  276. }
  277. /*
  278.  
  279. *//* CMDcab (CSBptr, buf, buflen, cctbl, ecptr, icix)
  280.  
  281.     Collect Atom Buffer
  282.  
  283. This routine collects characters from the input buffer into an atom
  284. buffer as specified by the caller.  It makes use of a character
  285. characteristic table, as described elsewhere.
  286.  
  287.  
  288. Accepts :
  289.  
  290.     CSBptr        Address of command state block
  291.     buf        Address of buffer to store data into
  292.     buflen        Length of buffer
  293.     cctbl        Address of character/characteristic table
  294.     ecptr        Where to store the ending character value
  295.     icix        Initial relative parse index
  296.  
  297. Returns :
  298.  
  299.     <value>        New character index relative to parse pointer, for
  300.             use in checkpointing if the parse is successful
  301.             at this point.
  302.     *ecptr        Value of character which caused the end of atom
  303.             collection.
  304.  
  305. */
  306.  
  307. CMDcab (CSBptr, buf, buflen, cctbl, ecptr, icix)
  308.  
  309. CSB        *CSBptr;        /* Addr of command state block */
  310. char        *buf;            /* Addr of buffer */
  311. int        buflen;            /* Length of buffer */
  312. WORD        *cctbl;            /* CC table */
  313. int        *ecptr;            /* Where to put ending char */
  314. int        icix;            /* Initial cix */
  315.  
  316. {
  317. IND    int    c;            /* Character */
  318. IND    int    cc;            /* CharChar value */
  319. IND    int    cix;            /* Relative parse index */
  320. IND    int    binx;            /* Buffer index */
  321.  
  322. cix = icix;                /* Init relative index */
  323. binx = 0;                /* Init buffer index */
  324. while (TRUE)                /* Get characters */
  325.     {
  326.     c = CMDgcc (CSBptr, cix);        /* Get char */
  327.     if ((c & 0xff00) != 0)        /* If special */
  328.     break;                /*  then we done. */
  329.  
  330.     cc = (cctbl[c/8]>>((7-(c%8))*2))&0x3;    /* Get cc value */
  331.     if ((cc == 0)            /* Invalid char */
  332.      || ((cc == 1) && (binx == 0)))    /*  or invalid first char */
  333.     {
  334.     c = _CCINV;            /* Return invalid char */
  335.     break;                /* Go return */
  336.     }
  337.  
  338.     if (cc == 3)            /* Break character */
  339.     break;                /*  then break. */
  340.  
  341.     buf[binx++] = c;            /* Store the char */
  342.     cix++;                /* Bump the parse index */
  343.     }
  344.  
  345. buf[binx] = NUL;            /* NUL-terminate the buffer */
  346. *ecptr = c;                /* Pass the ending char up */
  347. return (cix);                /* Return the index. */
  348. }
  349. /*
  350.  
  351. *//* CMDspc (CSBptr)
  352.  
  353.     Parse past spaces
  354.  
  355. This routine skips past spaces which are after the current parse point,
  356. and returns the relative parse index of the first non-space non-tab
  357. character.
  358.  
  359.  
  360. Accepts :
  361.  
  362.     CSBptr        Address of command state block
  363.  
  364.  
  365. Returns :
  366.  
  367.     <value>        Relative parse index of first non-space non-tab char.
  368.  
  369. */
  370.  
  371. CMDspc (CSBptr)
  372.  
  373. CSB        *CSBptr;        /* Addr of command state block */
  374.  
  375. {
  376. IND    int    c;            /* Character */
  377. IND    int    cix;            /* Command index */
  378.  
  379. cix = 0;                /* Set command index */
  380. while (TRUE)                /* Skip spaces/tabs */
  381.     {
  382.     c = CMDgcc (CSBptr, cix);        /* Get char */
  383.     if ((c != ' ') && (c != '\011'))
  384.     break;                /* Quit when got something other */
  385.     cix++;                /*  skip em */
  386.     }
  387.  
  388. return (cix);                /* Return the value */
  389. }
  390. /*
  391.  
  392. *//* CMDgcc (CSBptr, cix)
  393.  
  394.     Return unparsed character.
  395.  
  396. This routine returns the "cix"th unparsed character from the command
  397. line indicated by the command state block at CSBptr.
  398.  
  399.  
  400. Accepts :
  401.  
  402.     CSBptr        Address of command state block
  403.     cix        character index
  404.  
  405.  
  406. Returns
  407.  
  408.     <value>        character @ cix, or special code _CCxxx, as
  409.              defined in "comndi.h"
  410.  
  411. */
  412.  
  413. int CMDgcc (CSBptr, cix)
  414.  
  415. CSB        *CSBptr;        /* Command state block addr */
  416. int        cix;            /* Character index */
  417.  
  418. {
  419. IND    int    i;            /* Scratch */
  420. IND    int    c;            /* character */
  421.  
  422. i = CSBptr -> CSB_PRS + cix;        /* Get buffer index */
  423. if (i > CSBptr -> CSB_FLN)        /* If beyond filled space */
  424.     return (_CCEND);            /*  return END indicator */
  425. c = CSBptr -> CSB_BUF[i];        /* Get character there */
  426. if (i < CSBptr -> CSB_FLN)        /* If within filled area */
  427.     return (c);                /*  return it. */
  428. switch (c)                /* Dispatch on char found at end */
  429.     {
  430.     case '\r':                /* Return */
  431.     return (_CCEND);        /* Return end indication */
  432.  
  433.     case '?':                /* help ? */
  434.     return (_CCHLP);        /*  give help */
  435.  
  436.     case '\033':            /* Escape */
  437.     return (_CCCMP);        /* Completion */
  438.  
  439.     case '\006':            /* Control-F */
  440.     return (_CCCMP);        /* Completion */
  441.  
  442.     default:                /* Other */
  443.     return (_CCINC);        /* Just return incomplete */
  444.     }
  445. }
  446. /*
  447.  
  448. *//* CMDcpt (CSBptr, cix)
  449.  
  450.     Checkpoint parse index
  451.  
  452.  
  453. This routine checkpoints the parse by remembering that "cix" new
  454. characters have been parsed.
  455.  
  456.  
  457. Accepts :
  458.  
  459.     CSBptr        Address of command state block
  460.     cix        Character index past old parse point
  461.  
  462.  
  463. Returns
  464.  
  465.  
  466. */
  467.  
  468. int CMDcpt (CSBptr, cix)
  469.  
  470. CSB        *CSBptr;        /* Command state block addr */
  471. int        cix;            /* Character index */
  472.  
  473. {
  474. CSBptr -> CSB_PRS += cix;        /* Set checkpoint */
  475. }
  476. /*
  477.  
  478. *//* CMDcpl (CSBptr, str)
  479.  
  480.     Perform completion for a command string (element)
  481.  
  482. This routine attaches a string onto that already input, thus "completing"
  483. a portion of the input string.
  484.  
  485.  
  486. Accepts :
  487.  
  488.     CSBptr        Address of command state block
  489.     str        string to add to input string
  490.  
  491.  
  492. Returns :
  493.  
  494.  
  495. Notes :
  496.  
  497.     As a side-effect, the parse-pointer is set to the end of the
  498. string, since it is assumed that the completion was performed on the
  499. say-so of a parsing routine.
  500.  
  501.  
  502. */
  503.  
  504. CMDcpl (CSBptr, str)
  505.  
  506. CSB        *CSBptr;        /* Addr of command state block */
  507. char        *str;            /* Addr of string to add on */
  508.  
  509. {
  510. IND    int    i;            /* Index */
  511. IND    int    c;            /* Character */
  512.  
  513. i = CSBptr -> CSB_FLN;            /* Get filled length */
  514. while ((c = *str++) != NUL)        /* Swap chars */
  515.     {
  516.     if (i >= (CSBptr -> CSB_BSZ-1))    /* Make sure it fits */
  517.     {
  518.     CMDpoc ('\007');
  519.     break;
  520.     }
  521.     CSBptr -> CSB_BUF[i++] = c;        /*  store it. */
  522.     CMDpoc (c);                /* Show it */
  523.     }
  524. CSBptr -> CSB_BUF[i] = NUL;        /* Put marker under end of string */
  525. CSBptr -> CSB_FLN = i;            /* Update filled pointer */
  526. CSBptr -> CSB_PRS = i;            /* Update parse pointer */
  527. CMDfob();                /* Make it be seen */
  528. }
  529. /*
  530.  
  531. *//* CMDhlp (CFBptr, str)
  532.  
  533.     Assist in beginning to give help
  534.  
  535. Accepts :
  536.  
  537.     CFBptr        Address of command function block
  538.     str        String to print as "default".
  539.  
  540. Returns :
  541.  
  542.     <value>        TRUE if default help processing should continue
  543.             FALSE otherwise.
  544.  
  545. */
  546.  
  547. int CMDhlp (CFBptr, str)
  548.  
  549. CFB        *CFBptr;        /* Addr of command function block */
  550. char        *str;            /* String to print by default */
  551.  
  552. {
  553. IND    int    flg;            /* Flags from CFB */
  554.  
  555. flg = CFBptr -> CFB_FLG;        /* Get flags */
  556. if ((flg & _CFHPP) || !(flg & _CFSDH))    /* If help to be given */
  557.     {
  558.     if (CMDgvh)                /* See if we must give "or" */
  559.     CMDpzs ("\n or ");        /*  give it. */
  560.     else                /* Otherwise */
  561.     CMDpoc (' ');            /*  make sure we give a space */
  562.     }
  563.  
  564. if (flg & _CFHPP)            /* If any user help text */
  565.     if (CFBptr -> CFB_HLP)        /*  If any... */
  566.     CMDpzs (CFBptr -> CFB_HLP);    /*   print it */
  567.  
  568. if (flg & _CFSDH)            /* Suppress default ? */
  569.     {
  570.     CMDfob ();
  571.     return (FALSE);            /* Yup, indicate that by return */
  572.     }
  573. CMDpzs (str);                /* Print his string */
  574. CMDfob();
  575. return (TRUE);                /* Tell him to continue */
  576. }
  577. /*
  578.  
  579. *//* CMDfill (CSBptr, CFBptr)
  580.  
  581.     Fill the command line into the text buffer.
  582.  
  583. This routine is called to fill or to continue filling text into the command
  584. buffer which is indicated by the command state block.  It is responsible
  585. for rubout and other command line editing function.
  586.  
  587. Accepts :
  588.  
  589.     CSBptr        Address of the command state block
  590.  
  591.     CFBptr        Address of the first CFB in the CFB chain
  592.  
  593. Returns :
  594.  
  595.  
  596.  
  597. */
  598.  
  599. CMDfill (CSBptr, CFBptr)
  600.  
  601. CSB        *CSBptr;        /* Addr of CSB */
  602. CFB        *CFBptr;        /* Addr of first CFB */
  603.  
  604. {
  605. IND    int        c;        /* Character */
  606. IND    int        i;        /* Scratch */
  607. IND    int        col;        /* Column number */
  608. IND    int        col1;        /* Another column number */
  609. IND    int        recena;        /* Recovery enabled */
  610. IND    int        hlpena;        /* If help enabled */
  611.  
  612. recena = FALSE;                /* Set recovery not enabled */
  613. if (CSBptr -> CSB_FLN == -1)        /* but if it is */
  614.     {
  615.     CMDpzs (CSBptr -> CSB_PMT);        /* Output the prompt */
  616.     CMDfob();                /* Make sure it is seen */
  617.     CSBptr -> CSB_FLN = 0;        /* Reset filled length */
  618.     recena = TRUE;            /* Set recovery enable */
  619.     }
  620.  
  621. hlpena = TRUE;                /* Presume help is enabled */
  622. i = CFBptr -> CFB_FLG;            /* Get flags from CFB */
  623. if ((i & _CFSDH) && (!(i & _CFHPP)))    /* If no help provided for */
  624.     hlpena = FALSE;            /*  then set help not enabled */
  625.  
  626. CSBptr -> CSB_RFL = CSBptr -> CSB_RFL & (~_CFRPT);
  627.                     /* Clear bits we want cleared */
  628. col = CMDccol (CSBptr, CSBptr -> CSB_FLN); /* See what column we're at */
  629.  
  630. while (TRUE)
  631.     {
  632.     c = CMDgtc();            /* Get character */
  633.  
  634. /* Check specials */
  635.  
  636.     if (recena)                /* Recovery enabled ? */
  637.     {
  638.     recena = FALSE;            /* Not true after this */
  639.     if (c == '\010')        /* control-h */
  640.         {
  641.         CSBptr -> CSB_FLN = CSBptr -> CSB_PRS;
  642.                     /* Set filled length to parse inx */
  643.         for (i = 0; i < CSBptr -> CSB_FLN; i++)
  644.         CMDpoc (CSBptr -> CSB_BUF[i]);
  645.         CMDfob();            /* Show it */
  646.         col = CMDccol (CSBptr, CSBptr -> CSB_FLN);
  647.         CSBptr -> CSB_PRS = 0;    /* Parse from zero */
  648.         continue;
  649.         }
  650.     CSBptr -> CSB_PRS = 0;        /* Parse from zero */
  651.     }
  652.  
  653.     if ((c == '\010')            /* Backspace */
  654.        || (c == '\177')            /*  or rubout */
  655.        || (c == '\027')            /* or control-W */
  656.        || (c == '\030'))        /* or control-X */
  657.     {
  658.     if ((i = CSBptr -> CSB_FLN-1) >= 0)    /* If anything accumulated */
  659.         {
  660.         if (c == '\027')        /* If control-W */
  661.         {
  662.         for (; i > 0; i--)    /* Find beginning of "field" */
  663.             {
  664.             c = CSBptr -> CSB_BUF[i-1];
  665.             if ((!isalpha(c)) && (!isdigit(c)))
  666.             break;        /* Found it. */
  667.             }
  668.         }
  669.         else if (c == '\030')    /* If control-X */
  670.         i = 0;            /*  erase to beginning */
  671.         CSBptr -> CSB_FLN = i;    /* Set new index */
  672.         if (i <= CSBptr -> CSB_PRS)    /* If backed to parsed area */
  673.         CSBptr -> CSB_RFL |= _CFRPT; /* Set reparse flag */
  674.         if (Echofl)            /* If echoing... */
  675.         {
  676.         col1 = CMDccol (CSBptr, i);
  677.                     /* Find out what column to go to */
  678.         while (col > col1)    /* Wipe out back to there */
  679.             {
  680.             CMDpzs ("\010 \010"); /* <BSP><SPC><BSP> */
  681.             col--;
  682.             }
  683.         CMDfob();
  684.         }
  685.         }
  686.     }
  687.  
  688.  
  689.     else if (c == '\022')        /* Control-r */
  690.     {
  691.     if (Echofl)            /* If echoing */
  692.         {
  693.         CMDpzs ("^R\n");
  694.         CMDpzs (CSBptr -> CSB_PMT);    /* Output prompt */
  695.         for (i = 0; i < CSBptr -> CSB_FLN; i++)
  696.         CMDpoc (CSBptr -> CSB_BUF[i]);
  697.         CMDfob();
  698.         }
  699.     }
  700.  
  701.     else if (c == '\025')        /* Control-U */
  702.     {
  703.     CMDpzs ("^U\n");
  704.     CSBptr -> CSB_FLN = 0;        /* Filled length is zero */
  705.     if (Echofl)            /* If echoing */
  706.         CMDpzs (CSBptr -> CSB_PMT);    /*  re-issue prompt */
  707.     col = CMDccol (CSBptr, 0);    /* Get accurate column number */
  708.     CMDfob();
  709.     if (CSBptr -> CSB_PRS > 0)    /* If backed before parsed area */
  710.         CSBptr -> CSB_RFL |= _CFRPT; /* Set reparse flag */
  711.     }
  712.  
  713.     else                /* Anything else */
  714.     {
  715.     if (CSBptr -> CSB_PFL & _CFRAI) /* Raise lowercase? */
  716.         c = toupper(c);        /* Make it upper */
  717.     CSBptr -> CSB_BUF[CSBptr -> CSB_FLN] = c;
  718.                     /* Store char */
  719.  
  720.     if (c == '\r')            /* If return */
  721.         {
  722.         CMDpoc ('\n');
  723.         return;
  724.         }
  725.  
  726.     if (hlpena && (c == '?'))    /* Check for help request */
  727.         {
  728.         CMDpoc (c);
  729.         CMDfob();
  730.         return;
  731.         }
  732.  
  733.     if ((c == '\006')        /* control-F */
  734.      || (c == '\027')        /* Control-W */
  735.      || (c == '\033')        /* Escape */
  736.        )
  737.         return;            /* Return OK, go parse */
  738.  
  739.     if (c == '\026')        /* Control-V, literal next char */
  740.         {
  741.         c = CMDgtc();        /*  get another one */
  742.         CSBptr -> CSB_BUF[CSBptr -> CSB_FLN] = c;
  743.         }
  744.  
  745.     if (++(CSBptr -> CSB_FLN) >= (CSBptr -> CSB_BSZ-1))
  746.         {                /*  if full . . */
  747.         CMDpoc ('\007');        /*  beep at him */
  748.         CMDfob ();            /* Make sure it is heard */
  749.         CSBptr -> CSB_FLN--;    /* Don't store it. */
  750.         }
  751.  
  752.     else if (c == '\011')        /* tab... */
  753.         {
  754.         col = (col+8)&-8;        /* Compute next column */
  755.         if (Echofl)
  756.         {
  757.         CMDpoc (c);        /* Echo it if ok */
  758.         CMDfob();
  759.         }
  760.         }
  761.  
  762.     else if (c < ' ')        /* Control char ? */
  763.         {
  764.         col += 2;            /* Update col by 2 */
  765.         if (Echofl)            /* If echoing */
  766.         {
  767.         CMDpoc ('^');        /* Carat */
  768.         CMDpoc (c+'@');        /* Valid char */
  769.         CMDfob();
  770.         }
  771.         }
  772.  
  773.     else                /* Any other char */
  774.         {
  775.         col++;            /* Bump col */
  776.         if (Echofl)            /* If echoing */
  777.         {
  778.         CMDpoc (c);        /* echo it */
  779.         CMDfob();
  780.         }
  781.         }
  782.     }
  783.     }
  784. }
  785. /*
  786.  
  787. *//* CMDccol (CSBptr, cix)
  788.  
  789.     Count column position
  790.  
  791. This routine counts the column position for a particular point in the
  792. command buffer input stream.  The prompt buffer is included in this
  793. calculation.
  794.  
  795.  
  796. Accepts :
  797.  
  798.     CSBptr        Address of command state block
  799.     cix        Character index to consider
  800.  
  801. Returns :
  802.  
  803.     <value>        Column number, zero-based.
  804.  
  805. */
  806.  
  807. int CMDccol (CSBptr, cix)
  808.  
  809. CSB        *CSBptr;        /* Addr of CSB */
  810. int        cix;            /* Character index */
  811.  
  812. {
  813. IND    int    c;            /* Char */
  814. IND    int    w;            /* Which string being considered */
  815.                     /* 0 = prompt, 1 = text */
  816. IND    char    *sptr;            /* String pointer */
  817. IND    int    col;            /* Column # accumulator */
  818.  
  819.  
  820. col = 0;                /* Init col # */
  821. sptr = CSBptr -> CSB_PMT;        /* Look at prompt buffer first */
  822. for (w = 0; w < 2; w++)            /* Step through 2 strings */
  823.     {
  824.     while ((c = *sptr++) != NUL)    /* Look at the string */
  825.     {
  826.     if (w == 1)            /* If text string */
  827.         if (cix-- == 0)        /* If at desired index */
  828.         break;            /* be done */
  829.     if (c == '\011')        /* If tab */
  830.         col = (col+8)&(-8);        /* Calc next position */
  831.     else if (c < ' ')        /* Control char ? */
  832.         col += 2;            /*  count carat, and char */
  833.     else                /* anything else */
  834.         col++;            /* counts as one */
  835.     }
  836.     sptr = CSBptr -> CSB_BUF;        /* Do text buffer now */
  837.     }
  838.  
  839. return (col);                /* Return the value */
  840. }
  841.  
  842. /*
  843.  
  844. *//* CMDpoc(c)
  845.  
  846.     Output character.
  847.  
  848. */
  849.  
  850. CMDpoc(c)
  851.  
  852. int            c;
  853.  
  854. {
  855. (*Cocrtc)(c);
  856. }
  857.