home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / lib / addr / ap_lex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  7.2 KB  |  258 lines

  1. #include "util.h"
  2. #include "ap.h"
  3. #include "ap_lex.h"
  4.  
  5. /*  Perform lexical analysis on input stream
  6.  
  7.     The stream is assumed to be "unfolded" and the <crlf>/<lwsp> sequence
  8.     is NOT checked for.  This must be done by the character-acquisition
  9.     routine, if necessary.  In fact, space, tab and newline all return the
  10.     same lexical token.  Due to a number of bagbiting mail systems on the
  11.     net which cannot handle having a space within a mailbox name, period
  12.     (.) has been equated with space.
  13.  
  14.     Letters, numbers, and other graphics, except specials, also all return
  15.     the same token.
  16.  
  17.     Note that only printable characters and format effectors are legal.
  18.     All others cause an error return.
  19.  
  20.     Only COMMENTs and WORDs have data associated with them.
  21.  
  22. */
  23.  
  24. /*  < 1978  B. Borden       Wrote initial version of parser code
  25.  *  78-80   D. Crocker      Reworked parser into current form
  26.  *  Apr 81  K. Harrenstein  Hacked for SRI
  27.  *  Jun 81  D. Crocker      Back in the fold.  Finished v7 conversion
  28.  *                          minor cleanups.
  29.  */
  30.  
  31. extern char ap_lxtable[];         /* ascii chars -> symbolic terminals    */
  32. extern int ap_intype;
  33. int     ap_peek = -1;             /* one-character look-ahead             */
  34. char    ap_llex;                  /* last lexeme returned by ap_lex ()    */
  35.  
  36. #if DEBUG > 1
  37. extern int debug;
  38. char   *namtab[] =
  39. {
  40.     "eo-data",                    /* LV_EOD          0                    */
  41.     "error",                      /* LV_ERROR        1                    */
  42.     "comma",                      /* LV_COMMA        2                    */
  43.     "at",                         /* LV_AT           3                    */
  44.     "colon",                      /* LV_COLON        4                    */
  45.     "semi",                       /* LV_SEMI         5                    */
  46.     "comment",                    /* LV_COMMENT      6                    */
  47.     "less",                       /* LV_LESS         7                    */
  48.     "grtr",                       /* LV_GRTR         8                    */
  49.     "word",                       /* LV_WORD         9                    */
  50.     "from",                       /* LV_FROM        10                    */
  51.     "domain-literal"              /* LV_DLIT        11                    */
  52. };
  53. #endif
  54.  
  55. /* */
  56.  
  57. ap_lex (lexval)
  58. char    lexval[];
  59. {
  60.     register char   c,
  61.            *lexptr;
  62.     register int    retval;
  63.  
  64.     while ((retval = ap_lxtable[c = ap_char ()]) == LT_SPC)
  65.     ;                         /* Skip space, tab and newline          */
  66.     lexptr = lexval;
  67.     *lexptr++ = c;
  68.  
  69.     switch (retval)
  70.     {
  71.     case LT_ERR:              /* Bad Character */
  72.         retval = LV_ERROR;
  73.         break;
  74.  
  75.     case LT_EOD:              /* End Of Data stream */
  76.         retval = LV_EOD;
  77.         break;
  78.  
  79.     case LT_COM:              /* comma ","  -- addr list separator    */
  80.         retval = LV_COMMA;
  81.         break;
  82.  
  83.     case LT_AT:               /* At sign "@"  -- node separator       */
  84.         retval = LV_AT;
  85.         break;
  86.  
  87.  
  88. /*  *******************  DATA TYPES AND GROUP LIST  ******************** */
  89.  
  90.     case LT_COL:              /* colon  ":" -- data type / group      */
  91.         retval = LV_COLON;
  92.         break;
  93.  
  94.     case LT_SEM:              /* semicolon ";" -- group end           */
  95.         retval = LV_SEMI;
  96.         break;
  97.  
  98.  
  99.  
  100. /* ***********************  PERSON ADDRESS LIST  ************************ */
  101.  
  102.     case LT_LES:              /* less-than-sign "<"  -- person list   */
  103.         if (ap_lxtable[c = ap_char ()] == LT_LES)
  104.         retval = LV_FROM; /* << implies redirection               */
  105.         else {
  106.         ap_peek = c;      /* restore xtra char                    */
  107.         retval = LV_LESS;
  108.         }
  109.         break;
  110.  
  111.     case LT_GTR:              /* greater-than-sign ">" -- end person  */
  112.         retval = LV_GRTR;
  113.         break;
  114. /*  *******************  QUOTED & UNQUOTED WORDS  ********************** */
  115.  
  116.     case LT_LSQ:            /* left bracket */
  117.     case LT_LTR:              /* letters                              */
  118.     case LT_SQT:              /* single-quote "'"  -- just char, here */
  119.     case LT_RPR:              /* right paren ")" -- just char, here   */
  120.         for (;;) {
  121.         switch (ap_lxtable[*lexptr++ = c = ap_char ()]) {
  122.             case LT_LTR:
  123.             case LT_SQT:
  124.             case LT_RPR:
  125.             case LT_LSQ:
  126.             case LT_RSQ:
  127.             continue;
  128.  
  129.             case LT_ERR:
  130.             retval = LV_ERROR;
  131.             break;
  132.  
  133.             case LT_EOD:  /* permit eod to end string            */
  134.             default:      /* non-member character                 */
  135.             ap_peek = c;
  136.             lexptr--;
  137. #ifdef notdef /* no more " at " == '@' */
  138.             if (ap_intype == AP_733 &&
  139.                   lexptr == &lexval[2] &&
  140.                 uptolow (lexval[0]) == 'a' &&
  141.                 uptolow (lexval[1]) == 't'   )
  142.                 retval = LV_AT;
  143.             else
  144. #endif /* notdef */
  145.                 retval = LV_WORD;
  146.         }
  147.         break;
  148.         }
  149.         break;
  150.  
  151.     case LT_QOT:              /* double quote "\""  => string         */
  152.         retval = LV_WORD;
  153.         --lexptr;           /* don't put quotes into obvalue  - SEK   */
  154.         for (;;) {
  155.         switch (ap_lxtable[*lexptr++ = c = ap_char ()]) {
  156.             case LT_QOT:
  157.             --lexptr;
  158.             break;
  159.             case LT_SQT:  /* include next char w/out interpeting  */
  160.                   /* and drop on through                  */
  161.             *(lexptr - 1) = ap_char ();
  162.             default:
  163.             continue;
  164.             case LT_EOD:
  165.             retval = LV_ERROR;
  166.         }
  167.         break;
  168.         }
  169.         break;
  170. /*  *************************  COMMENT  ******************************** */
  171.  
  172.     case LT_LPR:              /* left paren "("  -- comment start     */
  173.         lexptr--;             /* remove left-most paren */
  174.         for (retval = 0;;) {  /* retval is count of comment nesting   */
  175.         switch (ap_lxtable[*lexptr++ = c = ap_char ()]) {
  176.             case LT_LPR:  /* nested comments                      */
  177.             retval++; /* just drop on through                 */
  178.             default: 
  179.             continue;
  180.             case LT_SQT:  /* include next char w/out interpeting  */
  181.             *(lexptr - 1) = ap_char ();
  182.             continue;
  183.             case LT_RPR: 
  184.             if (--retval > 0)
  185.                 break;
  186.             lexptr--;       /* remove right-most paren */
  187.             retval = LV_COMMENT;
  188.             break;
  189.             case LT_EOD: 
  190.             case LT_ERR: 
  191.             retval = LV_ERROR;
  192.             break;
  193.         }
  194.         break;
  195.         }
  196.         break;
  197.  
  198.  
  199. /*  *********************  DOMAIN LITERAL  ***************************** */
  200. /*
  201.     case LT_LSQ:              ?* left squar bracket "["               *?
  202.         FOREVER
  203.         {
  204.         switch (ap_lxtable[*lexptr++ = c = ap_char ()])
  205.         {
  206.             default: 
  207.             continue;
  208.             case LT_SQT:  ?* include next char w/out interpeting  *?
  209.             *(lexptr - 1) = ap_char ();
  210.             continue;
  211.             case LT_RSQ:
  212.             retval = LV_DLIT;
  213.             break;
  214.             case LT_EOD: 
  215.             case LT_ERR: 
  216.             retval = LV_ERROR;
  217.             break;
  218.         }
  219.         break;
  220.         }
  221.         break;
  222. */
  223.     }
  224.  
  225.  
  226. /* ***********************  CLEANUP AND RETURN  ************************* */
  227.  
  228.     *lexptr = '\0';
  229.  
  230. #if DEBUG > 1
  231.     if (debug)
  232.     printf (" %s", namtab[retval]);
  233. #endif
  234.  
  235.     return (ap_llex = retval);
  236. }
  237. /*  *******************  GET NEXT INPUT CHARACTER  ********************* */
  238.  
  239. ap_char ()
  240. {                                 /* handle lookahead and 8th bit         */
  241.     extern int  (*ap_gfunc) ();   /* Ptr to character get fn              */
  242.     register int    i;
  243.  
  244.     if (ap_peek == 0)
  245.     return (0);
  246.     if ((i = ap_peek) > 0) {
  247.     ap_peek = -1;
  248.     return (i);
  249.     }
  250.  
  251.     if ((i = ((*ap_gfunc) ())) == -1)
  252.     return (0);               /*  EOD                                 */
  253.  
  254.     return ((isascii (i)) ? i : '\177');
  255.                   /* force error, if eighth bit is on     */
  256. }
  257.  
  258.