home *** CD-ROM | disk | FTP | other *** search
/ ftptest.leeds.ac.uk / 2015.02.ftptest.leeds.ac.uk.tar / ftptest.leeds.ac.uk / bionet / CAE-GROUP / SCL-WIN3x / FED_PLUS.EXE / LEXACT.C < prev    next >
C/C++ Source or Header  |  1994-07-25  |  14KB  |  543 lines

  1. static char rcsid[] = "$Id: lexact.c,v 1.3 1994/05/11 19:51:24 libes Exp $";
  2.  
  3. /*
  4.  * This software was developed by U.S. Government employees as part of
  5.  * their official duties and is not subject to copyright.
  6.  *
  7.  * $Log: lexact.c,v $
  8.  * Revision 1.3  1994/05/11  19:51:24  libes
  9.  * numerous fixes
  10.  *
  11.  * Revision 1.2  1993/10/15  18:48:48  libes
  12.  * CADDETC certified
  13.  *
  14.  * Revision 1.7  1993/02/22  21:48:00  libes
  15.  * added decl for strdup
  16.  *
  17.  * Revision 1.6  1993/01/19  22:44:17  libes
  18.  * *** empty log message ***
  19.  *
  20.  * Revision 1.5  1992/08/27  23:40:58  libes
  21.  * remove connection between scanner and rest of EXPRESSinitializations
  22.  *
  23.  * Revision 1.4  1992/08/18  17:13:43  libes
  24.  * rm'd extraneous error messages
  25.  *
  26.  * Revision 1.3  1992/06/08  18:06:57  libes
  27.  * prettied up interface to print_objects_when_running
  28.  */
  29.  
  30. #define LEXACT_C
  31. #include <ctype.h>
  32. #include "lexact.h"
  33.  
  34. #include <string.h>
  35. #include "linklist.h"
  36. #include "stack.h"
  37. #include "hash.h"
  38. #include "express.h"
  39. #include "expparse.h"
  40. #include "dict.h"
  41. #include "memory.h"
  42.  
  43. extern int        yylineno;
  44. extern exp_YYSTYPE    exp_yylval;
  45. extern FILE*        yyin;
  46.  
  47. #ifdef FLEX
  48. extern char*        exp_yytext;
  49. #else /* LEX */
  50. extern char        exp_yytext[];
  51. #endif /*FLEX*/
  52.  
  53. #if 0
  54. static Hash_Table    macros;
  55. #endif
  56.  
  57. /* keyword lookup table */
  58.  
  59. static Hash_Table    keyword_dictionary;
  60.  
  61. static struct keyword_entry {
  62.     char *key;
  63.     int  token;
  64. } keywords[] = {
  65.     { "ABS",        TOK_BUILTIN_FUNCTION },
  66.     { "ABSTRACT",        TOK_ABSTRACT },
  67.     { "ACOS",        TOK_BUILTIN_FUNCTION },
  68.     { "AGGREGATE",        TOK_AGGREGATE },
  69.     { "ALIAS",        TOK_ALIAS },
  70.     { "AND",        TOK_AND },
  71.     { "ANDOR",        TOK_ANDOR },
  72.     { "ARRAY",        TOK_ARRAY },
  73.     { "AS",            TOK_AS },
  74.     { "ASIN",        TOK_BUILTIN_FUNCTION },
  75.     { "ATAN",        TOK_BUILTIN_FUNCTION },
  76.     { "BAG",        TOK_BAG },
  77.     { "BEGIN",        TOK_BEGIN },
  78.     { "BINARY",        TOK_BINARY },
  79.     { "BLENGTH",        TOK_BUILTIN_FUNCTION },
  80.     { "BOOLEAN",        TOK_BOOLEAN },
  81.     { "BY",            TOK_BY },
  82.     { "CASE",        TOK_CASE },
  83.     { "CONST_E",        TOK_E },
  84.     { "CONSTANT",        TOK_CONSTANT },
  85.     { "CONTEXT",        TOK_CONTEXT },
  86.     { "COS",        TOK_BUILTIN_FUNCTION },
  87.     { "DERIVE",        TOK_DERIVE },
  88.     { "DIV",        TOK_DIV },
  89.     { "ELSE",        TOK_ELSE },
  90.     { "END",        TOK_END },
  91.     { "END_ALIAS",        TOK_END_ALIAS },
  92.     { "END_CASE",        TOK_END_CASE },
  93.     { "END_CONSTANT",    TOK_END_CONSTANT },
  94.     { "END_CONTEXT",    TOK_END_CONTEXT },
  95.     { "END_ENTITY",        TOK_END_ENTITY },
  96.     { "END_FUNCTION",    TOK_END_FUNCTION },
  97.     { "END_IF",        TOK_END_IF },
  98.     { "END_LOCAL",        TOK_END_LOCAL },
  99.     { "END_MODEL",        TOK_END_MODEL },
  100.     { "END_PROCEDURE",    TOK_END_PROCEDURE },
  101.     { "END_REPEAT",        TOK_END_REPEAT },
  102.     { "END_RULE",        TOK_END_RULE },
  103.     { "END_SCHEMA",        TOK_END_SCHEMA },
  104.     { "END_TYPE",        TOK_END_TYPE },
  105.     { "ENTITY",        TOK_ENTITY },
  106.     { "ENUMERATION",    TOK_ENUMERATION },
  107.     { "ESCAPE",        TOK_ESCAPE },
  108.     { "EXISTS",        TOK_BUILTIN_FUNCTION },
  109.     { "EXP",        TOK_BUILTIN_FUNCTION },
  110.     { "FALSE",        TOK_LOGICAL_LITERAL },
  111.     { "FIXED",        TOK_FIXED },
  112.     { "FOR",        TOK_FOR },
  113.     { "FORMAT",        TOK_BUILTIN_FUNCTION },
  114.     { "FROM",        TOK_FROM },
  115.     { "FUNCTION",        TOK_FUNCTION },
  116.     { "GENERIC",        TOK_GENERIC },
  117.     { "HIBOUND",        TOK_BUILTIN_FUNCTION },
  118.     { "HIINDEX",        TOK_BUILTIN_FUNCTION },
  119.     { "IF",            TOK_IF },
  120.     { "IN",            TOK_IN },
  121.     { "INCLUDE",        TOK_INCLUDE },
  122.     { "INSERT",        TOK_BUILTIN_PROCEDURE },
  123.     { "INTEGER",        TOK_INTEGER },
  124.     { "INVERSE",        TOK_INVERSE },
  125.     { "LENGTH",        TOK_BUILTIN_FUNCTION },
  126.     { "LIKE",        TOK_LIKE },
  127.     { "LIST",        TOK_LIST },
  128.     { "LOBOUND",        TOK_BUILTIN_FUNCTION },
  129.     { "LOCAL",        TOK_LOCAL },
  130.     { "LOG",        TOK_BUILTIN_FUNCTION },
  131.     { "LOG10",        TOK_BUILTIN_FUNCTION },
  132.     { "LOG2",        TOK_BUILTIN_FUNCTION },
  133.     { "LOGICAL",        TOK_LOGICAL },
  134.     { "LOINDEX",        TOK_BUILTIN_FUNCTION },
  135.     { "MOD",        TOK_MOD },
  136.     { "MODEL",        TOK_MODEL },
  137.     { "NOT",        TOK_NOT },
  138.     { "NUMBER",        TOK_NUMBER },
  139.     { "NVL",        TOK_BUILTIN_FUNCTION },
  140.     { "ODD",        TOK_BUILTIN_FUNCTION },
  141.     { "OF",            TOK_OF },
  142.     { "ONEOF",        TOK_ONEOF },
  143.     { "OPTIONAL",        TOK_OPTIONAL },
  144.     { "OR",            TOK_OR },
  145.     { "OTHERWISE",        TOK_OTHERWISE },
  146.     { "PI",            TOK_PI },
  147.     { "PROCEDURE",        TOK_PROCEDURE },
  148.     { "QUERY",        TOK_QUERY },
  149.     { "REAL",        TOK_REAL },
  150.     { "REFERENCE",        TOK_REFERENCE },
  151.     { "REMOVE",        TOK_BUILTIN_PROCEDURE },
  152.     { "REPEAT",        TOK_REPEAT },
  153.     { "RETURN",        TOK_RETURN },
  154.     { "ROLESOF",        TOK_BUILTIN_FUNCTION },
  155.     { "RULE",        TOK_RULE },
  156.     { "SCHEMA",        TOK_SCHEMA },
  157.     { "SELECT",        TOK_SELECT },
  158.     { "SELF",        TOK_SELF },
  159.     { "SET",        TOK_SET },
  160.     { "SIN",        TOK_BUILTIN_FUNCTION },
  161.     { "SIZEOF",        TOK_BUILTIN_FUNCTION },
  162.     { "SKIP",        TOK_SKIP },
  163.     { "SQRT",        TOK_BUILTIN_FUNCTION },
  164.     { "STRING",        TOK_STRING },
  165.     { "SUBTYPE",        TOK_SUBTYPE },
  166.     { "SUPERTYPE",        TOK_SUPERTYPE },
  167.     { "TAN",        TOK_BUILTIN_FUNCTION },
  168.     { "THEN",        TOK_THEN },
  169.     { "TO",            TOK_TO },
  170.     { "TRUE",        TOK_LOGICAL_LITERAL },
  171.     { "TYPE",        TOK_TYPE },
  172.     { "TYPEOF",        TOK_BUILTIN_FUNCTION },
  173.     { "UNIQUE",        TOK_UNIQUE },
  174.     { "UNKNOWN",        TOK_LOGICAL_LITERAL },
  175.     { "UNTIL",        TOK_UNTIL },
  176.     { "USE",        TOK_USE },
  177.     { "USEDIN",        TOK_BUILTIN_FUNCTION },
  178.     { "VALUE",        TOK_BUILTIN_FUNCTION },
  179.     { "VAR",        TOK_VAR },
  180.     { "WHERE",        TOK_WHERE },
  181.     { "WHILE",        TOK_WHILE },
  182.     { "XOR",        TOK_XOR },
  183.     { 0,            0}
  184. };  
  185.  
  186. int
  187. SCANnextchar(char* buffer)
  188. {
  189.     extern Boolean SCANread(void);
  190.  
  191.     if (SCANtext_ready || SCANread()) {
  192.         buffer[0] = *(SCANcurrent++);
  193.         if (!isascii(buffer[0])) {
  194.             ERRORreport_with_line(ERROR_nonascii_char,yylineno,
  195.                 0xff & buffer[0]);
  196.             buffer[0] = ' ';    /* substitute space */
  197.         }
  198.         return 1;
  199.     } else
  200.     return 0;
  201. }
  202.  
  203.  
  204.  
  205. static
  206. void
  207. SCANpush_buffer(char *filename,FILE *fp)
  208. {
  209.     SCANbuffer.savedPos = SCANcurrent;
  210.     SCANbuffer.lineno = yylineno;
  211.     yylineno = 1;
  212.     ++SCAN_current_buffer;
  213.     *(SCANcurrent = SCANbuffer.text) = '\0';
  214.     SCANbuffer.readEof = false;
  215.     SCANbuffer.file = fp;
  216.     SCANbuffer.filename = current_filename = filename;
  217. }
  218.  
  219. static
  220. void
  221. SCANpop_buffer()
  222. {
  223.     if (SCANbuffer.file != NULL)
  224.         fclose(SCANbuffer.file);
  225.     --SCAN_current_buffer;
  226.     SCANcurrent = SCANbuffer.savedPos;
  227.     yylineno = SCANbuffer.lineno;    /* DEL */
  228.     current_filename = SCANbuffer.filename;
  229. }
  230.  
  231.  
  232. /*
  233. ** Requires:    yyin has been set
  234. */
  235.  
  236. void
  237. SCANinitialize(void)
  238. {
  239.     struct keyword_entry *k;
  240.  
  241.     keyword_dictionary = HASHcreate(100);    /* not exact */
  242.     for (k=keywords;k->key;k++) {
  243.         DICTdefine(keyword_dictionary,k->key,(Generic)k,0,OBJ_UNKNOWN);
  244.         /* not "unknown", but certainly won't be looked up by type! */
  245.     }
  246.  
  247. #if 0
  248.     /* init macro table, destroy old one if any */
  249.     if (macros) HASHdestroy(macros);
  250.     macros = HASHcreate(16);
  251. #endif
  252.  
  253.     /* set up errors on first time through */
  254.     if (ERROR_include_file == ERROR_none) {
  255.     ERROR_include_file =
  256.     ERRORcreate("Could not open include file `%s'.", SEVERITY_ERROR);
  257.     ERROR_unmatched_close_comment =
  258.     ERRORcreate("unmatched close comment", SEVERITY_ERROR);
  259.     ERROR_unmatched_open_comment =
  260.     ERRORcreate("unmatched open comment", SEVERITY_ERROR);
  261.     ERROR_unterminated_string =
  262.     ERRORcreate("unterminated string literal", SEVERITY_ERROR);
  263.     ERROR_encoded_string_bad_digit = ERRORcreate(
  264. "non-hex digit (%c) in encoded string literal", SEVERITY_ERROR);
  265.     ERROR_encoded_string_bad_count = ERRORcreate(
  266. "number of digits (%d) in encoded string literal is not divisible by 8",SEVERITY_ERROR);
  267.     ERROR_bad_identifier = ERRORcreate(
  268. "identifier (%s) cannot start with underscore",SEVERITY_ERROR);
  269.     ERROR_unexpected_character = ERRORcreate(
  270. "character (%c) is not a valid lexical element by itself",SEVERITY_ERROR);
  271.     ERROR_nonascii_char = ERRORcreate(
  272. "character (0x%x) is not in the EXPRESS character set",SEVERITY_ERROR);
  273.    }
  274. }
  275.  
  276. int
  277. SCANprocess_real_literal(void)
  278. {
  279.     sscanf(exp_yytext, "%lf", &(exp_yylval.rVal));
  280.     return TOK_REAL_LITERAL;
  281. }
  282.  
  283. int
  284. SCANprocess_integer_literal(void)
  285. {
  286.     sscanf(exp_yytext, "%d", &(exp_yylval.iVal));
  287.     return TOK_INTEGER_LITERAL;
  288. }
  289.  
  290. int
  291. SCANprocess_binary_literal(void)
  292. {
  293.     exp_yylval.binary = SCANstrdup(exp_yytext+1); /* drop '%' prefix */
  294.     return TOK_BINARY_LITERAL;
  295. }
  296.  
  297. int
  298. SCANprocess_logical_literal(char * string)
  299. {
  300.     switch (string[0]) {
  301.     case 'T':    exp_yylval.logical = Ltrue;    break;
  302.     case 'F':    exp_yylval.logical = Lfalse;    break;
  303.     default:    exp_yylval.logical = Lunknown;    break;
  304.     /* default will actually be triggered by 'UNKNOWN' keyword */
  305.     }
  306.     free(string);
  307.     return TOK_LOGICAL_LITERAL;
  308. }
  309.  
  310. void
  311. SCANlowerize(char *s)
  312. {
  313.     for (;*s;s++) {
  314.         if (isupper(*s)) *s = tolower(*s);
  315.     }
  316. }
  317.  
  318. void
  319. SCANupperize(char *s)
  320. {
  321.     for (;*s;s++) {
  322.         if (islower(*s)) *s = toupper(*s);
  323.     }
  324. }
  325.  
  326. int
  327. SCANprocess_identifier_or_keyword(void)
  328. {
  329.     char *test_string;
  330.     struct keyword_entry *k;
  331.  
  332.     int len;
  333.     char *src, *dest;
  334.  
  335.     /* make uppercase copy */
  336.     len = strlen(exp_yytext);
  337.     dest = test_string = (char *)malloc(len+1);
  338.     for (src=exp_yytext;*src;src++,dest++) {
  339.         *dest = (islower(*src)?toupper(*src):*src);
  340.     }
  341.     *dest = '\0';
  342.  
  343.     /* check for language keywords */
  344.     k = (struct keyword_entry *)DICTlookup(keyword_dictionary,test_string);
  345.     if (k) {
  346.     switch (k->token) {
  347.     case TOK_BUILTIN_FUNCTION:
  348.     case TOK_BUILTIN_PROCEDURE:
  349.         break;
  350.     case TOK_LOGICAL_LITERAL:
  351.         return SCANprocess_logical_literal(test_string);
  352.     default:
  353.         free(test_string);
  354.         return k->token;
  355.     }
  356.     }
  357.  
  358.     /* now we have an identifier token */
  359. #if 0
  360.     /* if macro invocation */
  361.     /*    SCANpush_buffer(); */
  362.     /*    strcpy(SCANbuffer.text, macro_expansion); */
  363.     /*    return exp_yylex(); */
  364.     /* else */
  365.     element.key = test_string;
  366.     if ((found = HASHsearch(macros, &element, HASH_FIND)) != NULL) {
  367.     free(test_string);
  368.     SCANpush_buffer();
  369.     STRINGcopy_into(SCANbuffer.text, found->data);
  370.     return exp_yylex();
  371.       printf("\nexp_yylex = %s, scanbuffer.text=%s\n",exp_yylex(),SCANbuffer.text);
  372.     } else {
  373. #endif
  374.  
  375.     exp_yylval.symbol =SYMBOLcreate(test_string,yylineno,current_filename);
  376.     if (k) {
  377.         /* built-in function/procedure */
  378.         return(k->token);
  379.     } else {
  380.         /* plain identifier */
  381.         /* translate back to lower-case */
  382.         SCANlowerize(test_string);
  383.         return TOK_IDENTIFIER;
  384.     }
  385. #if 0
  386.     return (k?k->token:TOK_IDENTIFIER);
  387. #endif
  388.  
  389.  
  390.  
  391. #if 0
  392.     }
  393. #endif
  394. }
  395.  
  396. int
  397. SCANprocess_string(void)
  398. {
  399.     char *s, *d;    /* source, destination */
  400.  
  401.     /* strip off quotes */
  402.     exp_yylval.string = SCANstrdup(exp_yytext+1); /* remove 1st single quote */
  403.  
  404.     s = strrchr(exp_yylval.string,'\'');
  405.     if (s) *s = '\0';            /* remove last single quote */
  406.     /* if string was unterminated, there will be no quote to remove */
  407.     /* in which case the scanner has already complained about it */
  408.  
  409.     /* change pairs of quotes to single quotes */
  410.     for (s = d = exp_yylval.string;*s;) {
  411.         if (*s != '\'') {
  412.             *d++ = *s++;
  413.         } else if (0 == strncmp(s,"''",2)) {
  414.             *d++ = '\'';
  415.             s += 2;
  416.         }
  417.     }
  418.     *d = '\0';
  419.  
  420.     return TOK_STRING_LITERAL;
  421. }
  422.  
  423. int
  424. SCANprocess_encoded_string(void)
  425. {
  426.     char *s, *d;    /* source, destination */
  427.     int count;
  428.  
  429.     /* strip off quotes */
  430.     exp_yylval.string = SCANstrdup(exp_yytext+1); /* remove 1st double quote */
  431.  
  432.     s = strrchr(exp_yylval.string,'"');
  433.     if (s) *s = '\0';            /* remove last double quote */
  434.     /* if string was unterminated, there will be no quote to remove */
  435.     /* in which case the scanner has already complained about it */
  436.  
  437.     count = 0;
  438.     for (s = exp_yylval.string;*s;s++,count++) {
  439.         if (!isxdigit(*s)) {
  440.             ERRORreport_with_line(ERROR_encoded_string_bad_digit,yylineno,*s);
  441.         }
  442.     }
  443.  
  444.     if (0 != (count%8)) {
  445.         ERRORreport_with_line(ERROR_encoded_string_bad_count,yylineno,count);
  446.     }
  447.  
  448.     return TOK_STRING_LITERAL_ENCODED;
  449. }
  450.  
  451. Boolean
  452. SCANread(void)
  453. {
  454.     int        numRead;
  455.     Boolean    done;
  456.  
  457.     do {
  458.     /* this loop is guaranteed to terminate, since buffer[0] is on yyin */
  459.     while (SCANbuffer.file == NULL) {
  460.         SCANpop_buffer();
  461.         if (SCANtext_ready)
  462.         return true;
  463.     }
  464.  
  465.     /* now we have a file buffer */
  466.  
  467.     /* check for more stuff already buffered */
  468.     if (SCANtext_ready)
  469.         return true;
  470.  
  471.     /* check whether we've seen eof on this file */
  472.     if (!SCANbuffer.readEof) {
  473.         numRead = fread(SCANbuffer.text,sizeof(char),SCAN_BUFFER_SIZE,SCANbuffer.file);
  474.         if (numRead < SCAN_BUFFER_SIZE) SCANbuffer.readEof = true;
  475. #if 0
  476.         /* avoid read - nonportable */
  477.         SCANbuffer.readEof =
  478.         ((numRead = read(fileno(SCANbuffer.file),
  479.                  SCANbuffer.text,
  480.                  SCAN_BUFFER_SIZE))
  481.          < SCAN_BUFFER_SIZE);
  482. #endif
  483.         SCANbuffer.text[numRead] = '\0';
  484.         SCANcurrent = SCANbuffer.text;
  485.     }
  486.  
  487.     if (!(done = SCANtext_ready)) {
  488.         if (SCAN_current_buffer == 0) {
  489.             done = true;
  490.             fclose(SCANbuffer.file); /* close yyin (I think) */
  491.         } else {
  492.             SCANpop_buffer();
  493.         }
  494.     }
  495.     } while (!done);
  496.     return SCANtext_ready;
  497. }
  498.  
  499. #if macros_bit_the_dust
  500. void
  501. SCANdefine_macro(char * name, char * expansion)
  502. {
  503.     Element    element;
  504.     int        len;
  505.  
  506.     HMALLOC(element, Element, "hash table entry in SCANdefine_macro");
  507.     element->key = STRINGcopy(name);
  508.     len = STRINGlength(expansion);
  509.     STRALLOC(element->data, len + 1, "macro expansion in SCANdefine_macro");
  510.     STRINGcopy_into(element->data, expansion);
  511.     element->data[len] = '\n';
  512.     element->data[len + 1] = '\0';
  513.     HASHsearch(macros, element, HASH_INSERT);
  514. }
  515. #endif
  516.  
  517. void
  518. SCANinclude_file(char *filename)
  519. {
  520.     extern int print_objects_while_running;
  521.     FILE *fp;
  522.  
  523.     if ((fp = fopen(filename, "r")) == NULL) {
  524.         ERRORreport_with_line(ERROR_include_file, yylineno);
  525.     } else {
  526.         if (print_objects_while_running & OBJ_SCHEMA_BITS) {
  527.             fprintf(stderr,"parse: including %s at line %d of %s\n",
  528.                 filename,yylineno,SCANbuffer.filename);
  529.         }
  530.         SCANpush_buffer(filename,fp);
  531.     }
  532. }
  533.  
  534. char *
  535. SCANstrdup(char *s)
  536. {
  537.     char *s2 = (char *)malloc(strlen(s)+1);
  538.     if (!s2) return 0;
  539.  
  540.     strcpy(s2,s);
  541.     return s2;
  542. }
  543.