home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Lib / addr / ap_lex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  7.8 KB  |  382 lines

  1. /* ap_lex.c: lexical analyser for address parser */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_lex.c,v 6.0 1991/12/18 20:21:24 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Lib/addr/RCS/ap_lex.c,v 6.0 1991/12/18 20:21:24 jpo Rel $
  9.  *
  10.  * $Log: ap_lex.c,v $
  11.  * Revision 6.0  1991/12/18  20:21:24  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. /*
  19. Perform lexical analysis on input stream
  20.  
  21. The stream is assumed to be "unfolded" and the <crlf>/<lwsp> sequence
  22. is NOT checked for.  This must be done by the character-acquisition
  23. routine, if necessary.  In fact, space, tab and newline all return the
  24. same lexical token.  Due to a number of bagbiting mail systems on the
  25. net which cannot handle having a space within a mailbox name, period
  26. (.) has been equated with space.
  27.  
  28. Letters, numbers, and other graphics, except specials, also all return
  29. the same token.
  30.  
  31. Note that only printable characters and format effectors are legal.
  32. All others cause an error return.
  33.  
  34. Only COMMENTs and WORDs have data associated with them.
  35.  
  36. */
  37.  
  38. /*
  39. < 1978  B. Borden       Wrote initial version of parser code
  40. 78-80   D. Crocker      Reworked parser into current form
  41. Apr 81  K. Harrenstein  Hacked for SRI
  42. Jun 81  D. Crocker      Back in the fold.  Finished v7 conversion
  43.  */
  44.  
  45.  
  46. #include "util.h"
  47. #include "ap.h"
  48. #include "ap_lex.h"
  49.  
  50.  
  51. extern char     ap_lxtable[],
  52.         ap_lxtable_per[];   /* ascii chars -> symbolic terminals */
  53. extern int      ap_intype;
  54. int             ap_peek = -1;   /* one-character look-ahead */
  55. char            ap_llex;        /* last lexeme returned by ap_lex() */
  56.  
  57. #ifdef AP_DEBUG
  58. extern char     ap_debug;
  59. char   *namtab[] =
  60. {
  61.     "eo-data",                  /* LV_EOD       0    */
  62.     "error",                    /* LV_ERROR     1    */
  63.     "comma",                    /* LV_COMMA     2    */
  64.     "at",                       /* LV_AT        3    */
  65.     "colon",                    /* LV_COLON     4    */
  66.     "semi",                     /* LV_SEMI      5    */
  67.     "comment",                  /* LV_COMMENT   6    */
  68.     "less",                     /* LV_LESS      7    */
  69.     "grtr",                     /* LV_GRTR      8    */
  70.     "word",                     /* LV_WORD      9    */
  71.     "from",                     /* LV_FROM      10   */
  72.     "domain-literal"            /* LV_DLIT      11   */
  73. };
  74. #endif
  75.  
  76.  
  77.  
  78. /* ---------------------  Begin  Routines  -------------------------------- */
  79.  
  80. static int ap_char ();
  81. int ap_lex_percent = FALSE;
  82.  
  83. void ap_use_percent()
  84. {
  85.     ap_lex_percent = TRUE;
  86. }
  87.  
  88. int ap_lex (lexval, siz)
  89. char    lexval[];
  90. int    siz;
  91. {
  92.     register char   c,
  93.             *lexptr;
  94.     register int    retval;
  95.     char    *lex_table = (ap_lex_percent == FALSE) ? ap_lxtable : ap_lxtable_per;
  96.  
  97.     siz--; /* need one for terminating '\0' */
  98.     /* -- Skips space, tab and newline -- */
  99.     while ((retval = lex_table[c = ap_char()]) == LT_SPC)
  100.         continue;
  101.  
  102.     lexptr = lexval;
  103.     *lexptr++ = c;
  104.  
  105.     switch (retval) {
  106.     case LT_ERR:
  107.         /* -- bad character -- */
  108.         retval = LV_ERROR;
  109.         break;
  110.  
  111.     case LT_EOD:
  112.         /* -- end of data stream -- */
  113.         retval = LV_EOD;
  114.         break;
  115.  
  116.     case LT_COM:
  117.         /* -- comma ","  the addr list separator -- */
  118.         retval = LV_COMMA;
  119.         break;
  120.  
  121.     case LT_AT:
  122.         /* -- At sign "@"  the  node separator -- */
  123.         retval = LV_AT;
  124.         break;
  125.  
  126.  
  127. /* ---------------------  data types and group list  -------------------- */
  128.  
  129.     case LT_COL:
  130.         /* -- colon  ":"  the data type / group -- */
  131.         retval = LV_COLON;
  132.         break;
  133.  
  134.     case LT_SEM:
  135.         /* -- semicolon ";"  the group end -- */
  136.         retval = LV_SEMI;
  137.         break;
  138.  
  139.  
  140.  
  141. /* -----------------------  person address list  ------------------------ */
  142.  
  143.     case LT_LES:
  144.         /* -- less-than-sign "<"  the person list -- */
  145.  
  146.         if (lex_table[c = ap_char()] == LT_LES)
  147.             /* -- << implies redirection -- */
  148.             retval = LV_FROM;
  149.         else {
  150.             /* -- restore xtra char -- */
  151.             ap_peek = c;
  152.             retval = LV_LESS;
  153.         }
  154.         break;
  155.  
  156.  
  157.     case LT_GTR:
  158.         /* -- greater-than-sign ">" the end person -- */
  159.         retval = LV_GRTR;
  160.         break;
  161.  
  162.  
  163. /* ---------------------  quoted & unquoted words  ------------------------ */
  164.  
  165.     case LT_SQT:
  166.         /* -- back slash at start of atom - illegal -- */
  167.         retval = LV_ERROR;
  168.         break;
  169.         
  170.     case LT_LTR:
  171.         /* -- letters -- */
  172.     case LT_RPR:
  173.         /* -- right paren ")"  its just char, here -- */
  174.  
  175.         for (;;) {
  176.             if ((int) (lexptr - &(lexval[0])) >= siz)
  177.                 /* too long */
  178.                 retval = LV_ERROR;
  179.             else {
  180.                 switch (lex_table[*lexptr++ = c = ap_char()]) {
  181.                     case LT_LTR:
  182.                     case LT_SQT:
  183.                     case LT_RPR:
  184.                     continue;
  185.  
  186.                     case LT_ERR:
  187.                     retval = LV_ERROR;
  188.                     break;
  189.  
  190.                     case LT_EOD:
  191.                     /* -- permit eod to end string -- */
  192.                     default:
  193.                     /* -- non-member character -- */
  194.                     ap_peek = c;
  195.                     lexptr--;
  196. #ifdef AP_733_AT
  197.                     if (ap_lex_percent == TRUE &&
  198.                         lexptr == &lexval[2] &&
  199.                         uptolow (lexval[0]) == 'a' &&
  200.                         uptolow (lexval[1]) == 't' )
  201.                         retval = LV_AT;
  202.                     else
  203. #endif
  204.                         retval = LV_WORD;
  205.                 }
  206.             }
  207.             break;
  208.         };
  209.         break;
  210.  
  211.  
  212.     case LT_QOT:
  213.         /* -- double quote "\""  => string -- */
  214.         retval = LV_WORD;
  215.  
  216.         /* -- don't put quotes into obvalue  -- */
  217.         --lexptr;
  218.  
  219.         for (;;) {
  220.             if ((int) (lexptr - &(lexval[0])) >= siz) 
  221.                 /* too long */
  222.                 retval = LV_ERROR;
  223.             else {
  224.                 switch (lex_table[*lexptr++ = c = ap_char()]) {
  225.                     case LT_QOT:
  226.                     --lexptr;
  227.                     break;
  228.  
  229.                     case LT_SQT:
  230.                     /* -- include next char w/out interpeting --*/
  231.                     /* -- and drop on through -- */
  232.                     --lexptr;
  233.                     *lexptr++ = ap_char();
  234.  
  235.                     case LT_RPR:
  236.                     case LT_LPR:
  237.                     case LT_ERR:
  238.                     default:
  239.                     continue;
  240.  
  241.                     case LT_EOD:
  242.                     retval = LV_ERROR;
  243.                 }
  244.             }
  245.             break;
  246.         }
  247.  
  248.         break;
  249.  
  250.  
  251. /* ---------------------------  comment  ---------------------------------- */
  252.  
  253.  
  254.     case LT_LPR:
  255.         /* -- left paren "("  -- comment start -- */
  256.  
  257.         /* -- remove left-most paren -- */
  258.         lexptr--;
  259.  
  260.         for (retval = 0;;) {
  261.             /* -- retval is count of comment nesting -- */
  262.             if ((int) (lexptr - &(lexval[0])) >= siz) {
  263.                 /* too long */
  264.                 retval = LV_ERROR;
  265.             } else {
  266.                 switch (lex_table[*lexptr++ = c = ap_char()]) {
  267.                     case LT_LPR:
  268.                     /* -- nested comments -- */
  269.                     /* -- just drop on through -- */
  270.                     retval++;
  271.  
  272.                     default:
  273.                     continue;
  274.  
  275.                     case LT_SQT:
  276.                     /* -- include next char w/out interpeting --*/
  277.                     --lexptr;
  278.                     *lexptr++ = ap_char();
  279.                     continue;
  280.  
  281.                     case LT_RPR:
  282.                     if (retval-- > 0)
  283.                         continue;
  284.                     /* -- remove right-most paren -- */
  285.                     lexptr--;
  286.                     retval = LV_COMMENT;
  287.                     break;
  288.  
  289.                     case LT_EOD:
  290.                     case LT_ERR:
  291.                     retval = LV_ERROR;
  292.                     break;
  293.                 }
  294.             }
  295.             break;
  296.         }
  297.  
  298.         break;
  299.  
  300.  
  301.  
  302. /* ------------------------ domain literal  ------------------------------- */
  303.  
  304.  
  305.  
  306.     case LT_LSQ:
  307.         /* -- left squar bracket "[" -- */
  308.  
  309.         for(;;) {
  310.             if ((int) (lexptr - &(lexval[0])) >= siz) 
  311.                 /* too long */
  312.                 retval = LV_ERROR;
  313.             else {
  314.                 switch (lex_table[*lexptr++ = c = ap_char()]) {
  315.                     default:
  316.                     continue;
  317.                     case LT_SQT:
  318.                     /* -- include next char w/out interpeting --*/
  319.                     --lexptr;
  320.                     *lexptr++ = ap_char();
  321.                     continue;
  322.                     case LT_RSQ:
  323.                     retval = LV_DLIT;
  324.                     break;
  325.                     case LT_EOD:
  326.                     case LT_ERR:
  327.                     retval = LV_ERROR;
  328.                     break;
  329.                 }
  330.             }
  331.             break;
  332.         }
  333.  
  334.         break;
  335.     }
  336.  
  337.  
  338.  
  339.  
  340. /* -----------------------  cleanup and return  --------------------------- */
  341.  
  342.     *lexptr = '\0';
  343.  
  344. #ifdef AP_DEBUG
  345.     if (ap_debug)
  346.         PP_DBG ((" %s", namtab[retval]));
  347. #endif
  348.  
  349.     return (ap_llex = retval);
  350. }
  351.  
  352.  
  353. /* ---------------------  Static Routines  -------------------------------- */
  354.  
  355.  
  356. /*
  357. get next input character
  358. */
  359.  
  360. static int ap_char()
  361. {
  362.     /* -- handle lookahead and 8th bit -- */
  363.  
  364.     extern int      (*ap_gfunc)();  /* -- ptr to character get fn -- */
  365.     register int    i;
  366.  
  367.     if (ap_peek == 0)
  368.         return (0);
  369.  
  370.     if ((i = ap_peek) > 0) {
  371.         ap_peek = -1;
  372.         return (i);
  373.     }
  374.  
  375.     /*  -- EOD -- */
  376.     if ((i = ((*ap_gfunc)())) == -1)
  377.         return (0);
  378.  
  379.     /* -- force error, if eighth bit is on -- */
  380.     return ((isascii (i)) ? i : '\177');
  381. }
  382.