home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mm / mm-ccmd-0.91-20031009.tar.gz / mm-ccmd-0.91-20031009.tar / work / ccmd / cmnoi.c < prev    next >
C/C++ Source or Header  |  2002-02-18  |  11KB  |  332 lines

  1. /*
  2.  Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  the City of New York.  Permission is granted to any individual or
  4.  institution to use, copy, or redistribute this software so long as it
  5.  is not sold for profit, provided this copyright notice is retained.
  6.  
  7.  Author: Andrew Lowry
  8. */
  9. /* cmnoi
  10. **
  11. ** This module contains the default break table and handlers for
  12. ** parsing noise words.  Parsing succeeds if the current input
  13. ** begins with a left paren, then matches the given noise word
  14. ** modulo case and whitespace, then closes with a right paren.
  15. ** If the current input begins with anything other than a left
  16. ** paren, parsing also succeeds, but no characters are consumed.
  17. ** Unusual handling is performed when the current input is empty
  18. ** and the CM_PFE flag is on in the CSB.  In this case, the noise
  19. ** word with parentheses is stuffed into the command buffer, and
  20. ** another parse attempt is requested.  (We cannot merely succeed,
  21. ** since the characters we stuff into the buffer are not in the
  22. ** text buffer that was passed to us.  The caller must rebuild
  23. ** this text buffer for us.)  Another unusual case is when the
  24. ** input is empty and the CM_ACT flag is on in the CSB, indicating
  25. ** that action is pending.  In this case, the parse succeeds,
  26. ** consuming no characters, so that the action will apply to
  27. ** the next real field, not to the noise word.  Finally, 
  28. ** noise word parses do not affect the atom buffer.
  29. **
  30. ** Completion can only occur with a non-empty buffer (due to the
  31. ** special action with CM_ACT and an empty buffer just described).
  32. ** (This is not true if completion is immediate on some key, but if
  33. ** that's the case, something strange is probably going on anyway.)
  34. ** The completion text consists of the remainder of the noise word,
  35. ** with closing paren and trailing space.  Partial completion will
  36. ** complete only up to and including the next punctuation, and will
  37. ** not add a trailing blank.
  38. **
  39. ** Help, like completion, should never occur at the beginning of
  40. ** a noise word.  It consists of the string, "Noise word."
  41. **
  42. ** The break table has no effect on the parsing of a noise word.
  43. ** The default is set to include only the printing characters
  44. ** other than question mark, so that standard actions will be
  45. ** active.  For first character, everything but left paren breaks,
  46. ** so that CM_WKF parsing will work correctly.
  47. **/
  48.  
  49. #define    NOIERR            /* declare cmnoi parse errors here */
  50.  
  51. #include "ccmdlib.h"        /* get ccmd package symbols */
  52. #include "cmfncs.h"        /* and internal symbols */
  53.  
  54. /* Forward declarations of handlers */
  55.  
  56. PASSEDSTATIC int noiprs(), noihlp(), noicplt();
  57. static int fndnoi(char *text, int textlen, char *noise,
  58.           char **cplt, char **term);
  59. static int skipws(char **text, int *textlen, int mandatory);
  60.  
  61.  
  62. static brktab noibrk = {
  63.   {                    /* only open paren allowed first */
  64.     0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff,
  65.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  66.   },
  67.   {                    /* all print chars but '?' */
  68.     0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
  69.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
  70.   }
  71. };
  72.  
  73. ftspec ft_noi = { noiprs, noihlp, noicplt, 0, &noibrk }; /* handler structure */
  74.  
  75.  
  76.  
  77. /* noiprs - If current input is empty and CM_PFE is on, stuff the noise
  78. ** word and ask for another try.  If empty and CM_ACT is on, succeed
  79. ** consuming nothing.  If nonempty and 1st char is not paren, succeed
  80. ** consuming nothing.  Otherwise succeed if the rest matches the noise
  81. ** word string followed by a right paren and another character.
  82. **/
  83.  
  84. PASSEDSTATIC int
  85. noiprs(text,textlen,fdbp,parselen,value)
  86. char *text;
  87. int textlen,*parselen;
  88. fdb *fdbp;
  89. pval *value;
  90. {
  91.   int ret;            /* results of stuffs */
  92.   char *term;            /* pointer to char after close paren */
  93.   char *cplt;            /* unused arg to fndnoi */
  94.   char tmp[BUFSIZ];        /* hold noise string */
  95.  
  96.   cmcsb._cmflg |= CM_NAC;    /* protect the atom buffer */
  97.   if (textlen == 0) {        /* empty buffer? */
  98.     if (cmcsb._cmflg & CM_PFE) {/* and prior field got completion? */
  99.       cmcsb._cmflg |= (CM_ACT|CM_ESC);    /* keep the action going. */
  100.       return(CMxINC);
  101.     }
  102.     else if (cmcsb._cmflg & CM_ACT) { /* empty and action waiting? */
  103.       *parselen = 0;        /* consume nothing */
  104.       return(CMxOK);        /* and succeed */
  105.     }
  106.     else
  107.       return(CMxINC);        /* empty, no PFE, no action waiting */
  108.   }
  109.                 /* find noise in the input */
  110.   ret = fndnoi(text,textlen,(char *) fdbp->_cmdat,&cplt,&term);
  111.   if (ret == NOIxNP) {        /* not a noise word */
  112.     *parselen = 0;        /* consume nothing */
  113.     if (cmcsb._cmcur != cmcsb._cmptr + cmcsb._cminc)
  114.     cmcsb._cmflg |= CM_ACT;    /* keep the action going. */
  115.     return(CMxOK);        /* and succeed */
  116.   }
  117.   if (ret != CMxOK) {
  118.     return(ret);        /* propagate errors */
  119.   }
  120.   if (term == NULL)
  121.     return(CMxINC);        /* not terminated -- need more input */
  122.   *parselen = term-text;    /* compute length of noise */
  123.   return(CMxOK);        /* and succeed */
  124. }
  125.  
  126.  
  127.  
  128. /* noihlp - Always print "Noise word" */
  129.  
  130. PASSEDSTATIC int
  131. noihlp(text,textlen,fdbp,cust,lines)
  132. char *text;
  133. int textlen,cust;
  134. fdb *fdbp;
  135. int lines;
  136. {
  137.   cmxputs("noise word");
  138.   return(lines-1);
  139. }
  140.  
  141.  
  142.  
  143. /* noicplt - Just finish up the noise where the current input
  144. ** leaves off.  Full completion also adds a space, partial
  145. ** completion never does.
  146. **/
  147.  
  148. PASSEDSTATIC int
  149. noicplt(text,textlen,fdbp,full,cplt,cpltlen)
  150. char *text,**cplt;
  151. int textlen,full,*cpltlen;
  152. fdb *fdbp;
  153. {
  154.   int ret;            /* return code from aux routine */
  155.   char *term;            /* char after noise word if any */
  156.   char c;            /* chars in completion */  
  157.   static char *work = NULL;    /* dynamic area to build completion */
  158.   char *cp;            /* for copying completion text */
  159.   char *malloc();        /* declare non-int library routine */
  160.   int badalc = FALSE;        /* true if malloc fails below */
  161.  
  162.   if (work != NULL) {        /* buffer hanging around from last time? */
  163.     free(work);            /* get rid of it */
  164.     work = NULL;        /* and mark it released */
  165.   }
  166.                 /* find noise in the input */
  167.   if (textlen == 0) {
  168.     work = malloc(strlen(fdbp->_cmdat) + 3);
  169.     sprintf(work, "(%s)", fdbp->_cmdat);
  170.     *cpltlen = strlen(work);
  171.     *cplt = work;
  172.   }
  173.   else {
  174.     ret = fndnoi(text,textlen,(char *) fdbp->_cmdat,cplt,&term);
  175.  
  176.     *cpltlen = -1;        /* always complete to end of string */
  177.     if (*cplt == NULL) {    /* noise is all there */
  178.       if (ret == CMxINC)    /* no closing paren */
  179.     *cplt = ")";        /* so give them one */
  180.     }
  181.     else {            /* noise not all there */
  182.       work = malloc(strlen(*cplt)+2); /* noise, paren, and null */
  183.       if (work != NULL) {    /* allocation succeeded? */
  184.     cp = work;        /* point to work space */
  185.     while (*cp++ = *(*cplt)++); /* copy remainder of noise word */
  186.     *(--cp) = ')';        /* finish with right paren */
  187.     *(++cp) = NULCHAR;    /* and tie off with a null */
  188.     *cplt = work;        /* point to constructed text */
  189.       }
  190.       else
  191.     badalc = TRUE;        /* flag allocation failure */
  192.     }
  193.   }
  194.   if (full)            /* full completion */
  195.     if (badalc)
  196.       return(0);        /* just fill in if allocation failed */
  197.     else
  198.       return(CMP_SPC | CMP_GO);    /* otherwise add a space and a wakeup */
  199.   else
  200.     return(CMP_PNC);        /* partial - complete to punctuation */
  201. }
  202.  
  203.  
  204.  
  205. /* fndnoi - Auxiliary routine for noise word handlers 
  206. **
  207. ** Determines how much of the noise word is in the input buffer,
  208. ** and indicates where completion, if any, should start.
  209. **
  210. ** Input parameters:
  211. **   text - The input text to be parsed.
  212. **   textlen - Size of the input text.
  213. **   noise - Pointer to the noise word.
  214. **
  215. ** Output parameters:
  216. **   cplt - A pointer to the start of completion text within the noise.
  217. **   term - A pointer to the character following the right paren if there
  218. **     was one in the input.
  219. **
  220. ** Returns: Standard error code.  CMxOK means complete noise word with
  221. **   following terminator.  CMxINC means good match so far, but needs
  222. **   more for a CMxOK.  Anything else is error.
  223. **/
  224.  
  225. static int
  226. fndnoi(char *text, int textlen, char *noise, char **cplt, char **term)
  227. {
  228.   char cc,tc;            /* completion and text chars */
  229.   int ret;
  230.   int inws = FALSE;        /* TRUE during whitespace in completion */
  231.  
  232.   *term = NULL;            /* assume no terminator */
  233.   *cplt = noise;        /* start completion all the way back */
  234.  
  235.   if (*text == '(') {        /* noise starts with a paren */
  236.     text++;
  237.     textlen--;
  238.   }
  239.   else {
  240.     return(NOIxNP);        /* then bad parse */
  241.   }
  242.  
  243.   ret = skipws(&text,&textlen,FALSE); /* optional space after open paren */
  244.   if (ret != CMxOK)
  245.     return(ret);            /* propagate errors */
  246.   
  247.   while ((cc = **cplt) != NULCHAR) /* loop to end of noise */
  248.     if ((cc == SPACE) || (cc == TAB)) /* hit some white space */
  249.       if (inws)
  250.     (*cplt)++;        /* already in it... keep looking */
  251.       else {
  252.     ret = skipws(&text,&textlen,TRUE); /* mandatory ws in text */
  253.     if (ret != CMxOK)
  254.       return(ret);        /* propagate problems */
  255.         inws = TRUE;        /* don't need it again */
  256.     (*cplt)++;        /* and consume the character */
  257.       }
  258.     else if (textlen == 0)    /* more noise and no more text? */
  259.       return(CMxINC);        /* yup, ask for more text */
  260.     else {
  261.       inws = FALSE;        /* no longer in white space */
  262.       tc = (*text++) & CC_CHR;    /* try to match noise */
  263.       if ((cc >= 'a') && (cc <= 'z'))
  264.     cc -= 'a'-'A';        /* uppercase both chars */
  265.       if ((tc >= 'a') && (tc <= 'z'))
  266.     tc -= 'a'-'A';
  267.       if (cc != tc)        /* different chars? */
  268.     return(NOIxNP);        /* then no parse */
  269.       textlen--;        /* else update counts and pointers */
  270.       (*cplt)++;
  271.     }                /* and keep looping */
  272.  
  273.   *cplt = NULL;            /* got through whole noise - no completion */
  274.  
  275.   ret = skipws(&text,&textlen,FALSE); /* optional space before closing */
  276.   if (ret != CMxOK)
  277.     return(ret);
  278.  
  279.   if (textlen == 0)        /* nothing left? */
  280.     return(CMxINC);        /* we still need a closing paren */
  281.   else if ((*text & CC_CHR) != ')') /* next char not closing paren? */
  282.     return(NOIxNP);        /* then bad parse */
  283.   else {
  284.     if (textlen > 1)        /* something after closing paren? */
  285.       *term = text+1;        /* yup, give them a pointer to it */
  286.     return(CMxOK);        /* entire noise word parsed ok */
  287.   }
  288. }
  289.  
  290.  
  291.  
  292. /* skipws - aux routine for fndnoi.
  293. **
  294. ** Purpose:
  295. **   Skips spaces and tabs in the input text.  Fails if there are none
  296. **   and the mandatory flag was on in the call.
  297.  
  298. ** Input parameters:
  299. **   text - Pointer to text to be scanned.
  300. **   textlen - Number of chars in text.
  301. **   mandatory - TRUE if an error should result if no space is there.
  302. **
  303. ** Output parameters:
  304. **   text, textlen - updated according to chars skipped.
  305. **
  306. ** Returns: Standard error code.
  307. **/
  308.  
  309. static int
  310. skipws(char **text, int *textlen, int mandatory)
  311. {
  312.   char c;
  313.   while (*textlen > 0) {    /* scan whole text */
  314.     c = **text & CC_CHR;    /* get next char */
  315.     if ((c == SPACE) || (c == TAB)) {
  316.       (*text)++;        /* found white space - skip it */
  317.       (*textlen)--;        /* count it */
  318.       mandatory = FALSE;    /* and no longer mandatory */
  319.     }
  320.     else
  321.       break;            /* exit loop when non-ws found */
  322.   }
  323.  
  324.   if (mandatory)        /* no ws found and it was required? */
  325.     if (*textlen == 0)        /* yes, no input? */
  326.       return(CMxINC);        /* then it's incomplete */
  327.     else
  328.       return(NOIxNP);        /* otherwise bad parse */
  329.   else
  330.     return(CMxOK);        /* otherwise it's fine */
  331. }
  332.