home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / me34src.zip / me3 / mc / token.c < prev    next >
C/C++ Source or Header  |  1995-01-14  |  12KB  |  488 lines

  1. /*
  2.  * token.c : piddle with tokens
  3.  */
  4.  
  5. /* Copyright 1990, 1991, 1992 Craig Durland
  6.  *   Distributed under the terms of the GNU General Public License.
  7.  *   Distributed "as is", without warranties of any kind, but comments,
  8.  *     suggestions and bug reports are welcome.
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <os.h>
  13. #include <const.h>
  14. #include <dtable.h>
  15. #include "mc.h"
  16. #include "mm.h"
  17. #include "opcode.h"
  18.  
  19. extern char
  20.   ebuf[],
  21.   *keyword_type_name(),        /* in supp.c */
  22.   *malloc(), *save_string(), *spoof();
  23.  
  24. /* ******************************************************************** */
  25. /* *************************** Token Tables *************************** */
  26. /* ******************************************************************** */
  27.  
  28.     /* Notes:
  29.      *   The tables don't need to be sorted.  Most of the lookups are done
  30.      *     through a hash table, others just walk the array.
  31.      */
  32.  
  33. oMuttCmd
  34.   omuttcmds[] =        /* the other Mutt commands, see other_Mutt_cmd() */
  35.   {
  36.     "ask",        ASK,        STRING,
  37.     "concat",        CONCAT,        STRING,
  38.     "extract-element",    EXTRACT_EL, UNKNOWN,
  39.     "extract-elements",    EXTRACT_ELS,UNKNOWN, /* !!!actually, same as first arg */
  40.     "insert-object",    INSERT_OBJ, UNKNOWN,
  41.     "msg",        MSG,        STRING,
  42.     "remove-elements",    REMOVE_ELS, VOID,
  43.   };
  44.  
  45.     /* holes: 22, 30, 32-41, 44-59, 74 */
  46. MuttCmd        /* all the Mutt keywords, including the omuttcmds[] */
  47.   muttcmds[] =        /* biggest # = 81 */
  48.   {
  49.     "!=",        0,
  50.     "*",        65,
  51.     "*=",        66,
  52.     "+",        3,
  53.     "+=",        63,
  54.     "-",        67,
  55.     "-=",        68,
  56.     "/",        69,
  57.     "/=",        70,
  58.     "<",        11,
  59.     "<=",        10,
  60.     "==",        12,
  61.     ">",        13,
  62.     ">=",        14,
  63.     "and",        80,
  64.     "arg",        43,
  65.     "array",        73,
  66.     "ask",        32,
  67.     "ask-user",        26,
  68.     "bool",        62,
  69.     "break",        7,
  70.     "byte",        75,
  71.     "concat",        33,
  72.     "cond",        1,
  73.     "const",        77,
  74.     "continue",        71,
  75.     "convert-to",    20,
  76.     "defun",        2,
  77.     "done",        9,
  78.     "extract-element",    24,
  79.     "extract-elements",    25,
  80.     "floc",        78,
  81.     "for",        76,
  82.     "goto",        6,
  83.     "halt",        16,
  84.     "if",        23,
  85.     "include",        64,
  86.     "insert-object",    18,
  87.     "int",        31,
  88.     "label",        8,
  89.     "length-of",    19,
  90.     "list",        27,
  91.     "loc",        79,
  92.     "msg",        34,
  93.     "nargs",        42,
  94.     "not",        28,
  95.     "novalue",        29,
  96.     "or",        81,
  97.     "pointer",        72,
  98.     "push-arg",        17,
  99.     "push-args",    15,
  100.     "remove-elements",    21,
  101.     "small-int",    61,
  102.     "string",        60,
  103.     "switch",        4,
  104.     "while",        5,
  105.   },
  106.   modifiers[] =            /* the pgm modifiers */
  107.   {
  108.     "HIDDEN",    HIDDEN,
  109.     "MAIN",    MAIN,
  110.   };
  111.  
  112. static int msize  = NITEMS(muttcmds), moders = NITEMS(modifiers);
  113. int omsize = NITEMS(omuttcmds);
  114.  
  115.  
  116.     /* Yuch !!! */
  117. oMuttCmd *id_to_oMutt(n)
  118. {
  119.   switch (n)
  120.   {
  121.     default: return NULL;
  122.     case 32: n = 0; break;    /* ask */
  123.     case 33: n = 1; break;    /* concat */
  124.     case 24: n = 2; break;    /* extract-element */
  125.     case 25: n = 3; break;    /* extract-elements */
  126.     case 18: n = 4; break;    /* insert-object */
  127.     case 34: n = 5; break;    /* msg */
  128.     case 21: n = 6; break;    /* remove-elements */
  129.   }
  130.  
  131.   return &omuttcmds[n];
  132. }
  133.  
  134. lookup_pgm_modifier(name) char *name;
  135. {
  136.   int i;
  137.  
  138.   for (i = 0; i < moders; i++)
  139.     if (0 == strcmp(name, modifiers[i].name)) return modifiers[i].token;
  140.   return -1;
  141. }
  142.  
  143. /* ******************************************************************** */
  144. /* ************************ Keyword Hash Table ************************ */
  145. /* ******************************************************************** */
  146.  
  147. #include "dhash.h"
  148.  
  149. /* static void *keyword_hash_table;    /*  */
  150. static declare_and_init_dTable(keyword_table,KeyWord);
  151. static int num_keywords = 0;
  152.  
  153.     /* Add a keyword to the global hash table.
  154.      * Input:
  155.      *   name : Pointer to name of keyword to add.  Must be allocated by
  156.      *     caller.
  157.      *   type:
  158.      *   token:  An int to be assocated with name.
  159.      *   collide:  What to do if name is all ready in the table.
  160.      * Returns:
  161.      *   TRUE : Name already in table.
  162.      *   FALSE : Unique name.
  163.      */
  164. int add_keyword(name, type, token, collide) char *name;
  165. {
  166.   ENTRY hkw, *it;
  167.   KeyWord *kw;
  168.  
  169. /*  htable(keyword_hash_table);        /*  */
  170.   hkw.key = name;
  171.   hkw.data = (void *)num_keywords;
  172.   if (!(it = hsearch(hkw,ENTER))) bail("add_keyword:  Out of memory!");
  173.   if (it->key && it->data != hkw.data)        /* already in the table */
  174.   {
  175.     switch (collide)
  176.     {
  177.       case 0:        /* No collision allowed */
  178.         moan("add_keyword1");    /* !!! */
  179.     return TRUE;
  180.       case 1:        /* Complain and ignore */
  181.         gripe(spoof(ebuf,"\"%s\":  Already in keyword table, ignoring."));
  182.     /* FALL THROUGH */
  183.       case 2:        /* Silent ignore */
  184.     return TRUE;
  185.       case 3:        /* Silent overwrite */
  186.     kw = &keyword_table.table[(int)it->data];
  187.     kw->type = type;
  188.     kw->token = token;
  189.     return TRUE;
  190.     }
  191.   }
  192.  
  193.   if (!xpand_dTable(&keyword_table, 1, 1000,200))
  194.     bail("Out of memory! Can't expand keyword table.\n");
  195.  
  196.   kw = &keyword_table.table[num_keywords];
  197.   kw->name  = name;
  198.   kw->type = type;
  199.   kw->token = token;
  200.  
  201.   num_keywords++;
  202.  
  203.   return FALSE;
  204. }
  205.  
  206. void hash_Mutt_keywords()
  207. {
  208.   int i;
  209.  
  210.     /* add all the Mutt keywords */
  211.   {
  212.     MuttCmd *ptr;
  213.     for (i = msize, ptr = muttcmds; i--; ptr++)
  214.       add_keyword(ptr->name, KWMutt, ptr->token, 0);
  215.   }
  216. }
  217.  
  218. void keyword_init()
  219. {
  220.   if (!hcreate(1000)) bail("keyword_init:  No memory for hash table!");
  221. /*  keyword_hash_table = htable((void *)NULL);    /*  */
  222.   hash_Mutt_keywords();
  223. }
  224.  
  225. KeyWord *global_look_up(name) char *name;
  226. {
  227.   ENTRY hkw, *found;
  228.   int i;
  229.  
  230. /*  htable(keyword_hash_table);        /*  */
  231.   hkw.key = name;
  232.   if (found = hsearch(hkw,FIND))
  233.   {
  234.     i = (int)found->data;
  235.     return &keyword_table.table[i];
  236.   }
  237.   return NULL;
  238. }
  239.  
  240. KeyWord *global_look_for(name, type) char *name;
  241. {
  242.   KeyWord *kw;
  243.  
  244.   if ((kw = global_look_up(name)) && kw->type == type) return kw;
  245.   return NULL;
  246. }
  247.  
  248. KeyWord *global_check(name) char *name;
  249. {
  250.   KeyWord *kw;
  251.  
  252.   if (kw = global_look_up(name))
  253.   {
  254. if (kw->type != KWXToken)    /* !!!??? */
  255. {
  256.     moan(spoof(ebuf,"\"%s\" already used (as a %s).",
  257.       name, keyword_type_name(kw->type)));
  258.     return kw;
  259. }
  260.   }
  261.   return NULL;
  262. }
  263.  
  264. /* ******************************************************************** */
  265. /* ************************* External Tokens ************************** */
  266. /* ******************************************************************** */
  267.  
  268. /*
  269.  * A token table is stored in a file.
  270.  *   Format:
  271.  *     <token number> <token name>
  272.  */
  273.  
  274. static declare_and_init_dTable(ext_token_table,MuttCmd);
  275.  
  276. void load_ext_token_table(fname) char *fname;
  277. {
  278.   char buf[90], *ptr;
  279.   int t;
  280.   FILE *fptr;
  281.  
  282.   new_ext(buf,fname,".tok");
  283.   if ((fptr = fopen(buf,"r")) == NULL)
  284.   {
  285.     moan(spoof(ebuf,"Can't open token file \"%s\"!",buf));
  286.     return;
  287.   }
  288.  
  289.   while ((ptr = fgets(buf,80,fptr)))
  290.   {
  291.     buf[strlen(buf)-1] = '\0';
  292.     t = atoi(ptr);
  293.     while (*ptr++ != ' ') ;
  294.     ptr = save_string(ptr);
  295.     add_keyword(ptr, KWXToken, t, 1);
  296.   }
  297. }
  298.  
  299.     /* Look for an external token by value.  Returns name.
  300.      * Input:
  301.      *   val:  token value to search for if name is NULL.
  302.      * Returns:
  303.      *   NULL : val not found
  304.      *   pointer to the token name
  305.      */
  306. char *lookup_ext_token_by_value(val)
  307. {
  308.   int j;
  309.   KeyWord *kw;
  310.  
  311.   kw = keyword_table.table;
  312.   for (j = num_keywords; j--; kw++)
  313.     if (KWXToken == kw->type && kw->token == val) return kw->name;
  314.  
  315.   return NULL;
  316. }
  317.  
  318. /* ******************************************************************** */
  319. /* *********************** Conversion Routines ************************ */
  320. /* ******************************************************************** */
  321.  
  322. int32 atoN(a) char *a;        /* convert string to NUMBER */
  323. {
  324.   char c, *b=a;
  325.   int minus = FALSE, base = 10, z;
  326.   int32 n = 0;
  327.  
  328.   if (*a == '-') { a++; minus = TRUE; }
  329.   if (*a == '0' && a[1] == 'x') { base = 16; a += 2; }
  330.   for (; *a; a++)
  331.   {
  332.     c = *a; z = 1000;
  333.     if ('0' <= c && c <= '9') z = c -'0';
  334.     else
  335.       if      ('a' <= c && c <= 'f') z = c -'a' +10;
  336.       else if ('A' <= c && c <= 'F') z = c -'A' +10;
  337.     if (z >= base) { moan(spoof(ebuf,"Invalid digit in %s",b)); break; }
  338.     n = n*base +z;
  339.   }
  340.   return minus ? -n : n;
  341. }
  342.  
  343. /* ******************************************************************** */
  344. /* ************************ Scanning Routines ************************* */
  345. /* ******************************************************************** */
  346.  
  347. #include <ctype.h>
  348.  
  349. extern char token[];            /* in mc.c */
  350. extern FILE *lstfile, *srcfile;        /* in mc.c */
  351. extern int srcline;            /* in mc.c */
  352. extern unsigned int class;
  353.  
  354. int num_lines_read = 0;
  355.  
  356. static char pgmtext[514], *xptr;
  357. static int looked = FALSE;
  358. static unsigned int proclass;
  359.  
  360. int btv = FALSE;    /* boolean token value - returned by get_token() */
  361.  
  362.     /* Move the pc to the next nonwhite character.
  363.      * Returns: TRUE if ok, FALSE if EoF.
  364.      * Notes:
  365.      *   A trailing newline (if any) is trimmed.
  366.      */
  367. getsrc()
  368. {
  369.   char *ptr;
  370.  
  371.   if ((xptr = fgets(pgmtext,512,srcfile)) == NULL) return FALSE;
  372.   if (*(ptr = xptr + strlen(xptr) -1) == '\n') *ptr = '\0';
  373.   num_lines_read++;
  374.   srcline++;
  375.   if (lstfile) fprintf(lstfile,"LINE %d: %s\n",srcline,xptr);
  376.   return TRUE;
  377. }
  378.  
  379.     /* skip comment => skip to next line */
  380.     /* EoF: Ok if comment is last thing in buffer/file */
  381. #define nocomment() getsrc()
  382.  
  383. static scan()
  384. {
  385. top:    /* incase got to get a new line */
  386.   while (isspace(*xptr)) xptr++;    /* delete leading white space */
  387.   if (*xptr == '\0')
  388.     if (getsrc()) goto top; else return FALSE;
  389.   if (*xptr == ';') if (nocomment()) goto top; else return FALSE;
  390.   return TRUE;
  391. }
  392.  
  393.     /* returns: TRUE (all ok), FALSE (something screwed up)
  394.      */
  395. void get_token()
  396. {
  397.   register char *ptr;
  398.  
  399.   if (looked) { looked = FALSE; class = proclass; return; }
  400.  
  401.   *(ptr = token) = '\0'; class = TOKEN;
  402.   if (!scan()) { class = proclass = SEOF; return; }
  403.   switch (*xptr)
  404.   {
  405.     case '\'':        /* string literal: 'string', ''=>' */
  406.       for (xptr++; *xptr && ptr < (token +250); xptr++)
  407.     if (*xptr == '\'' && *++xptr != '\'') goto uggg;
  408.     else *ptr++ = *xptr;
  409.       if (*xptr == '\0') bitch("String not terminated!");
  410.     uggg:
  411.       class = STRING;
  412.       break;
  413.     case '\"':        /* "string": knows about \ (quote), ^ (control) */
  414.       for (xptr++; *xptr && *xptr != '\"' && ptr < (token +250); xptr++)
  415.     switch (*xptr)
  416.     {
  417.       case '\\': *ptr++ = *++xptr; break;    /* \ : quote next char */
  418.       case '^':  *ptr++ = *++xptr ^ 0x40; break;    /* ^ => cntl char */
  419.       default:   *ptr++ = *xptr;
  420.     }
  421.       if (*xptr == '\0') bitch("String not terminated!");
  422.       xptr++; class = STRING;
  423.       break;
  424.     default:    /* get a token or number */
  425.       while (*xptr && !isspace(*xptr))
  426.       {
  427.     if (strchr("(){};",*xptr))
  428.     {
  429.       if (ptr == token)
  430.       {
  431.         class = DELIMITER;
  432.         if (  xptr[0] == '{' && xptr[1] == '{')
  433.          { *ptr++ = START_IPGM; xptr += 2; }
  434.         else
  435.           if (xptr[0] == '}' && xptr[1] == '}')
  436.          { *ptr++ = END_IPGM;   xptr += 2; }
  437.           else *ptr++ = *xptr++;
  438.       }
  439.       break;
  440.     }
  441.     *ptr++ = *xptr++;
  442.       }
  443.   }
  444.   *ptr = '\0';
  445.   if (class == TOKEN)
  446.   {
  447.     if ((isdigit(*token) || (*token == '-' && isdigit(*(token+1)))))
  448.     class = NUMBER;
  449.     else if (strcmp(token,"FALSE") == 0)     { class = BOOLEAN; btv = FALSE; }
  450.      else if (strcmp(token,"TRUE") == 0) { class = BOOLEAN; btv = TRUE; }
  451.   }
  452.   proclass = class;
  453.   return;
  454. }
  455.  
  456.     /* Note: gotta be careful class don't get trashed between
  457.      *   lookahead() & get_token()
  458.      */
  459. void lookahead()
  460. {
  461.   if (looked) { class = proclass; return; }
  462.   get_token(); looked = TRUE;
  463. }
  464.  
  465. typedef struct Inca { struct Inca *next; char fname[1]; } Inca;
  466. static Inca *inchead = NULL;
  467.  
  468. include(fname) char *fname;
  469. {
  470.   register Inca *ptr;
  471.  
  472.   for (ptr = inchead; ptr; ptr = ptr->next)
  473.     if (strcmp(ptr->fname,fname) == 0)
  474.     {
  475.       gripe(spoof(ebuf,"Already included: %s.  Ignoring.",fname));
  476.       nocomment();    /* bloto rest of line */
  477.       return UNKNOWN;
  478.     }
  479.   if (NULL == (ptr = (Inca *)malloc(sizeof(Inca) +strlen(fname))))
  480.     bail("Out of memory in include()");
  481.   strcpy(ptr->fname,fname);
  482.   ptr->next = inchead; inchead = ptr;
  483.   pilefile(fname,TRUE);
  484.   getsrc();    /* prime scan() */
  485.  
  486.   return UNKNOWN;
  487. }
  488.