home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / rayce27s / token.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-02  |  14.4 KB  |  725 lines

  1. /*
  2.  * token.c -- tokenizer to go with YACC/Bison pov scanner
  3.  * 
  4.  * (c) 1993, 1994 by Han-Wen Nienhuys <hanwen@stack.urc.tue.nl>
  5.  * 
  6.  * This program is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation;
  9.  * 
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  * 
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <stdlib.h>
  24. #include <stdarg.h>
  25. #include <string.h>
  26.  
  27. #include "ray.h"
  28. #include "extern.h"
  29. #include "proto.h"
  30. #include "parse.h"
  31.  
  32.  
  33. #if defined MSDOS || defined __MSDOS__ || defined msdos || defined __msdos__
  34. #include "rayparse.h"
  35. #else
  36. #include "rayparse.tab.h"
  37. #endif
  38.  
  39.  
  40. #define INDICATORCOUNT 25
  41.  
  42. /***************************************************************************
  43.  * PROTOS                                   *
  44.  ***************************************************************************/
  45.  
  46. PRIVATE int     inputlines;
  47. PUBLIC struct declare_tab *the_dectab;
  48.  
  49. /* file stack, for INCLUDES */
  50. struct file_stack_entry {
  51.     FILE           *fp;
  52.     int             lineno;
  53.     struct file_stack_entry *prev;
  54. };
  55.  
  56.  
  57. PRIVATE struct file_stack_entry *current_file;    /* info of the file we're
  58.                          * reading  */
  59. PRIVATE FILE   *infile;        /* the filepointer. */
  60. PRIVATE int     maxkey;        /* number of keywords + 1 */
  61.  
  62. struct keyword_ent {        /* for the keyword table */
  63.     char           *name;
  64.     int             tokcode;
  65. };
  66.  
  67. PRIVATE struct keyword_ent keyword_tab[] =
  68. {
  69.     "algebraic", ALGEBRAIC_T,
  70.     "alpha", ALPHA,
  71.     "ambient", AMBIENT,
  72.     "antialias", ANTIALIAS,
  73.     "aspect", ASPECT,
  74.     "atmosphere", ATMOSPHERE,
  75.     "attenuation", ATTENUATION,
  76.     "background", BACKGROUND,
  77.     "blue", BLUE,
  78.     "bounded_by", BOUNDED_BY,
  79.     "box", BOX_T,
  80.     "brilliance", BRILLIANCE,
  81.     "camera", CAMERA_T,
  82.     "clipped_by", CLIPPED_BY,
  83.     "closed", CLOSEDCURVE,
  84.     "color", COLOR,
  85.     "colour", COLOR,        /* just to be pov compatible */
  86.     "composite", COMPOSITE_T,
  87.     "cutoff", CUTOFF,
  88.     "cylinder", CYLINDER_T,
  89.     "declare", DECLARE,
  90.     "default", DEFAULTTEXT,
  91.     "depth", DEPTH,
  92.     "diffuse", DIFFUSE,
  93.     "direction", DIRECTION,
  94.     "disc", DISC_T,
  95.     "extrusion", EXTRUSION_T,
  96.     "fov", FOV,
  97.     "gif", GIF,
  98.     "green", GREEN,
  99.     "image_map", IMAGE_MAP,
  100.     "include", INCLUDE,
  101.     "interpolate", INTERPOLATE,
  102.     "intersection", INTERSECTION,
  103.     "inverse", INVERSE,
  104.     "ior", IOR,
  105.     "iterations", ITERATIONS,
  106.     "light_source", LIGHT_SOURCE_T,
  107.     "location", LOCATION,
  108.     "look_at", LOOK_AT,
  109.     "map_type", MAPTYPE,
  110.     "object", OBJECT,
  111.     "once", ONCE,
  112.     "open", OPEN,
  113.     "options", OPTIONS,
  114.     "plane", PLANE_T,
  115.     "point_at", POINT_AT,
  116.     "polygon", POLYGON_T,
  117.     "quadric", QUADRIC_T,
  118.     "radius", RADIUS,
  119.     "red", RED,
  120.     "reflect_angle", REFLECT_ANGLE,
  121.     "reflection", REFLECTION,
  122.     "refract_angle", REFRACT_ANGLE,
  123.     "refraction", REFRACTION,
  124.     "rgb", RGB,
  125.     "rotate", ROTATE,
  126.     "roughness", ROUGHNESS,
  127.     "scale", SCALE,
  128.     "sky", SKY,
  129.     "smooth_triangle", SMOOTH_TRIANGLE_T,
  130.     "specular", SPECULAR,
  131.     "speed", SPEED,
  132.     "sphere", SPHERE_T,
  133.     "spotlight", SPOTLIGHT,
  134.     "sturm", STURM,
  135.     "superq", SUPERQ_T,
  136.     "texture", TEXTURE,
  137.     "tga", TARGA,
  138.     "tightness", TIGHTNESS,
  139.     "time", TIME,
  140.     "tolerance", TOLERANCE,
  141.     "torus", TORUS_T,
  142.     "translate", TRANSLATE,
  143.     "triangle", TRIANGLE_T,
  144.     "union", UNION,
  145.     "uvoffset", UVOFFSET,
  146.     "uvrange", UVRANGE,
  147.     "uvswap", UVSWAP,
  148.     "x", X_T,
  149.     "y", Y_T,
  150.     "z", Z_T,
  151.     NULL, 0
  152. };
  153.  
  154.  
  155. /*
  156.  * PROTOS
  157.  */
  158. PRIVATE void    free_declare_tab(void);
  159. PRIVATE void    new_file(char *fn);
  160. PRIVATE void    get_quotedstring(char *s);
  161. PRIVATE void    get_word(char *cp);
  162. PRIVATE void    eat_junk(void);
  163. PRIVATE void    pushc(int c);
  164. PRIVATE int     popc(void);
  165. PRIVATE void    eat_comment(void);
  166. PRIVATE void    eat_linecomment(void);
  167.  
  168. /***************************************************************************
  169.  * PUBLICS                                   *
  170.  ***************************************************************************/
  171.  
  172.  
  173. /* prints an error message with linenumber to stdout and then dies */
  174. PUBLIC void
  175. errormsg(char *format,...)
  176. {
  177.     char            s1[100],
  178.                     s2[100];
  179.     va_list         arglist;
  180.  
  181.     if (infile != NULL)        /* line number appropriate? */
  182.     sprintf(s1, "\nerror (line %d): ", inputlines);
  183.     else
  184.     sprintf(s1, "\nerror: ");
  185.  
  186.     va_start(arglist, format);
  187.     vsprintf(s2, format, arglist);
  188.     va_end(arglist);
  189.  
  190.     fprintf(error_out, "%s%s\n", s1, s2);
  191.  
  192.     exit(1);
  193. }
  194.  
  195. /* prints a warning with linenumber to stdout */
  196. PUBLIC void
  197. warning(char *format,...)
  198. {
  199.     char            s1[100],
  200.                     s2[100];
  201.     va_list         arglist;
  202.  
  203.     if (infile != NULL)
  204.     sprintf(s1, "\nwarning (line %d): ", inputlines);
  205.     else
  206.     sprintf(s1, "\nwarning: ");
  207.  
  208.     va_start(arglist, format);
  209.     vsprintf(s2, format, arglist);
  210.     va_end(arglist);
  211.  
  212.     fprintf(error_out, "%s%s\n", s1, s2);
  213. }
  214.  
  215.  
  216. /* initialize this module */
  217. PUBLIC void
  218. set_input(char *fname)
  219. {
  220.     current_file = NULL;
  221.     infile = NULL;
  222.     for (maxkey = 0; keyword_tab[maxkey].name; maxkey++);
  223.  
  224.     new_file(fname);
  225. }
  226.  
  227. /* and leave it behind. */
  228. PUBLIC void
  229. close_input(void)
  230. {
  231.     free_declare_tab();
  232. }
  233.  
  234. /***************************************************************************
  235.  * PRIVATES                                   *
  236.  ***************************************************************************/
  237.  
  238. /*
  239.  * read the #include "xxx" part
  240.  */
  241. PRIVATE void
  242. handle_include(void)
  243. {
  244.     char            fn[100];
  245.  
  246.     get_quotedstring(fn);
  247.  
  248.     new_file(fn);
  249. }
  250.  
  251. /* push stuff to filestack */
  252. PRIVATE void
  253. new_file(char *fn)
  254. {
  255.     struct file_stack_entry *prev;
  256.  
  257.     infile = fopen(fn, "rt");
  258.     if (infile == NULL)
  259.     errormsg("can't open %s\n", fn);
  260.  
  261.     if (current_file != NULL)
  262.     current_file->lineno = inputlines;
  263.  
  264.     prev = current_file;
  265.  
  266.     current_file = ALLOC(struct file_stack_entry);
  267.  
  268.     CHECK_MEM(current_file, "file info");
  269.  
  270.     current_file->prev = prev;
  271.     current_file->fp = infile;
  272.     inputlines = current_file->lineno = 1;
  273.     printf("[%s ", fn);
  274. }
  275.  
  276. /* pop from file stack */
  277. PRIVATE void
  278. exit_file(void)
  279. {
  280.     struct file_stack_entry *p;
  281.  
  282.     if (current_file != NULL) {    /* we're not finished */
  283.     printf("]");        /* show that we closing */
  284.     fclose(current_file->fp);
  285.  
  286.     /* pop the stack */
  287.     p = current_file;
  288.     current_file = current_file->prev;
  289.     free(p);
  290.  
  291.     if (current_file == NULL) {    /* this was the Mother of all
  292.                      * includes */
  293.         printf("<end of scene>\n");
  294.         infile = NULL;
  295.     } else {
  296.         inputlines = current_file->lineno;
  297.         infile = current_file->fp;
  298.     }
  299.     }
  300. }
  301.  
  302.  
  303. PRIVATE long    dotcount = 0;
  304.  
  305. PRIVATE void
  306. free_declare_tab(void)
  307. {
  308.     struct declare_tab *p,
  309.                    *next;
  310.  
  311.     for (p = the_dectab; p != NULL; p = next) {
  312.     next = p->next;
  313.     free(p->name);
  314.     switch (p->type) {
  315.     case IDENTIFIER:
  316.         assert(FALSE);
  317.     case FLOAT_IDENTIFIER:
  318.         free_float(p->data);
  319.         break;
  320.     case TEXTURE_IDENTIFIER:
  321.         free_texture(p->data);
  322.         break;
  323.     case IMAGEMAP_IDENTIFIER:
  324.         free_image_map(p->data);
  325.         break;
  326.     case COLOR_IDENTIFIER:
  327.         free_color(p->data);
  328.         break;
  329.     case CAMERA_IDENTIFIER:
  330.         free_camera(p->data);
  331.         break;
  332.     case VECTOR_IDENTIFIER:
  333.         free_vector(p->data);
  334.         break;
  335.  
  336.     case QUADRIC_IDENTIFIER:
  337.     case SPHERE_IDENTIFIER:
  338.     case PLANE_IDENTIFIER:
  339.     case LIGHT_IDENTIFIER:
  340.     case BOX_IDENTIFIER:
  341.     case COMPOSITE_IDENTIFIER:
  342.     case UNION_IDENTIFIER:
  343.     case INTERSECTION_IDENTIFIER:
  344.     case TRIANGLE_IDENTIFIER:
  345.     case TORUS_IDENTIFIER:
  346.     case ALGEBRAIC_IDENTIFIER:
  347.     case SUPERQ_IDENTIFIER:
  348.     case POLYGON_IDENTIFIER:
  349.     case OBJECT_IDENTIFIER:
  350.         free_object((object *) p->data);
  351.         break;
  352.     default:
  353.         assert(FALSE);
  354.     }
  355.     free(p);
  356.     }
  357.     the_dectab = NULL;
  358.  
  359. }
  360.  
  361. PUBLIC void
  362. print_dectab(void)
  363. {
  364. #ifdef DEBUG
  365.     struct declare_tab *p;
  366.  
  367.     for (p = the_dectab; p != NULL; p = p->next) {
  368.     printf("\n\t\"%s\": ", p->name);
  369.     switch (p->type) {
  370.     case IDENTIFIER:
  371.         assert(FALSE);
  372.     case FLOAT_IDENTIFIER:
  373.         printf("%lf\n", *(double *) p->data);
  374.         break;
  375.     case COLOR_IDENTIFIER:
  376.         print_c("", *(color *) p->data);
  377.         break;
  378.     case VECTOR_IDENTIFIER:
  379.         print_v("", *(vector *) p->data);
  380.         break;
  381.     case TEXTURE_IDENTIFIER:
  382.         print_texture(p->data);
  383.         break;
  384.     case IMAGEMAP_IDENTIFIER:
  385.         print_image_map(p->data);
  386.         break;
  387.     case CAMERA_IDENTIFIER:
  388.         print_camera(p->data);
  389.         break;
  390.  
  391.     case QUADRIC_IDENTIFIER:
  392.     case SPHERE_IDENTIFIER:
  393.     case PLANE_IDENTIFIER:
  394.     case LIGHT_IDENTIFIER:
  395.     case BOX_IDENTIFIER:
  396.     case COMPOSITE_IDENTIFIER:
  397.     case UNION_IDENTIFIER:
  398.     case TORUS_IDENTIFIER:
  399.     case INTERSECTION_IDENTIFIER:
  400.     case ALGEBRAIC_IDENTIFIER:
  401.     case SUPERQ_IDENTIFIER:
  402.     case POLYGON_IDENTIFIER:
  403.         print_object((object *) p->data);
  404.         break;
  405.  
  406.     case OBJECT_IDENTIFIER:
  407.         printf("GENERIC OBJECT: ");
  408.         print_object((object *) p->data);
  409.         break;
  410.  
  411.     default:
  412.         assert(FALSE);
  413.     }
  414.     }
  415.  
  416. #endif
  417. }
  418.  
  419.  
  420. PRIVATE struct declare_tab *
  421. add_declare(char *name)
  422. {
  423.     struct declare_tab *p;
  424.  
  425.     p = the_dectab;
  426.  
  427.     /* alloc  one */
  428.     the_dectab = ALLOC(struct declare_tab);
  429.  
  430.     CHECK_MEM(the_dectab, "declaration");
  431.  
  432.     /* link it in */
  433.     the_dectab->next = p;
  434.  
  435.     /* copy the string */
  436.     the_dectab->name = malloc(strlen(name) + 1);
  437.     CHECK_MEM(the_dectab->name, "identifier name");
  438.     strcpy(the_dectab->name, name);
  439.  
  440.     /* init the declare */
  441.     the_dectab->type = IDENTIFIER;
  442.     the_dectab->data = NULL;
  443.  
  444.     return the_dectab;
  445. }
  446.  
  447. PRIVATE int
  448. search_keyword(char *s)
  449. {
  450.     int             lo,
  451.                     hi,
  452.                     cmp,
  453.                     result;
  454.  
  455.     lo = 0;
  456.     hi = maxkey;
  457.  
  458.     /* binary search */
  459.     do {
  460.     cmp = (lo + hi) / 2;
  461.  
  462.     result = strcmp(s, keyword_tab[cmp].name);
  463.  
  464.     if (result < 0)
  465.         hi = cmp;
  466.     else
  467.         lo = cmp;
  468.  
  469.     }
  470.     while (hi - lo > 1);
  471.     if (!strcmp(s, keyword_tab[lo].name))
  472.     return lo;
  473.     else
  474.     return -1;        /* not found */
  475. }
  476.  
  477. /* search declaration table for string s, return pointer to decl info. */
  478. PRIVATE struct declare_tab *
  479. search_declare(char *s)
  480. {
  481.     struct declare_tab *p;
  482.  
  483.     for (p = the_dectab; p != NULL; p = p->next)
  484.     if (!strcmp(p->name, s))
  485.         return p;
  486.     return NULL;
  487. }
  488.  
  489. /*
  490.  * The main tokenizer function. It's a bit hairy, but it's simple
  491.  * 
  492.  * get a char: is it an letter ([a-zA-Z_]), then read a word. *is it a
  493.  * keyword? yes: is it include ? yes: handle include, and call yylex()
  494.  * recursively no: return token code no: it's an identifier. Is it new?
  495.  * yes: add a declaration, no: return pointer to info
  496.  */
  497.  
  498. PUBLIC int
  499. yylex(void)
  500. {
  501.     int             c,
  502.                     t;
  503.     char            s[100];
  504.  
  505.     eat_junk();            /* eat up comments, and whitespace */
  506.     c = popc();            /* look at important char */
  507.  
  508.     if (isalpha(c) || c == '_') {    /* were looking at a word */
  509.     pushc(c);
  510.     get_word(s);
  511.     t = search_keyword(s);
  512.     if (t != -1) {        /* reserved word? */
  513.         if (keyword_tab[t].tokcode == INCLUDE) {    /* includes shouldn't be
  514.                              * seen by the parser */
  515.         handle_include();
  516. #ifdef DEBUG
  517.         if (debug_options & DEBUGTOK)
  518.             printf("INCLUDE");
  519. #endif
  520.         return yylex();
  521.         } else {
  522. #ifdef DEBUG
  523.         if (debug_options & DEBUGTOK)
  524.             printf("\nKEYWORD \"%s\"\n", s);
  525. #endif
  526.         return keyword_tab[t].tokcode;    /* a real keyword */
  527.         }
  528.     } else {
  529.         if ((yylval.dectabptr = search_declare(s)) == NULL) {    /* unknown identifer */
  530.         yylval.dectabptr = add_declare(s);
  531.  
  532. #ifdef DEBUG
  533.         if (debug_options & DEBUGTOK)
  534.             printf("NEW ");
  535. #endif
  536.  
  537.         }
  538. #ifdef DEBUG
  539.         if (debug_options & DEBUGTOK)
  540.         printf("IDENTIFIER: \"%s\"\n", s);
  541. #endif
  542.         return yylval.dectabptr->type;
  543.     }
  544.     } else if (isdigit(c) || c == '.') {    /* number */
  545.     pushc(c);
  546.     if (fscanf(infile, "%lf", &(yylval.doubleval)) != 1)
  547.         assert(FALSE);
  548. #ifdef DEBUG
  549.     if (debug_options & DEBUGTOK)
  550.         printf("\nread %lf\n", yylval.doubleval);
  551. #endif
  552.  
  553.     return FLOAT_CONST;
  554.     }
  555.     if (c == EOF) {
  556. #ifdef DEBUG
  557.     if (debug_options & DEBUGTOK)
  558.         printf("<EOF>");
  559. #endif
  560.  
  561.     if (infile == NULL)
  562.         return 0;
  563.  
  564.     exit_file();
  565.     return yylex();
  566.     }
  567.     if (c == '\"') {
  568.     pushc('\"');
  569.     get_quotedstring(yylval.stringval);
  570.  
  571. #ifdef DEBUG
  572.     if (debug_options & DEBUGTOK)
  573.         printf("STRING %s\n", yylval.stringval);
  574. #endif
  575.  
  576.     return STRING;
  577.     }
  578.     /* not a string, not a number, so it's a char; return it. */
  579.  
  580. #ifdef DEBUG
  581.     if (debug_options & DEBUGTOK)
  582.     printf("CHAR %c\n", c);
  583. #endif
  584.  
  585.     return c;
  586.  
  587. }
  588.  
  589. /*
  590.  * read a quoted string like "ad   sfj54%$%$5439yties" gobble the quotes.
  591.  */
  592. PRIVATE void
  593. get_quotedstring(char *s)
  594. {
  595.     int             c;
  596.  
  597.     eat_junk();
  598.     if ((c = popc()) != '\"')
  599.     errormsg("\" expected");
  600.  
  601.     while ((c = popc()) != EOF && c != '\"')
  602.     *s++ = c;
  603.  
  604.  
  605.     if (c != '\"')
  606.     errormsg("\" expected");
  607.     *s = 0;
  608. }
  609.  
  610. /* handle word; _ is a char too */
  611. PRIVATE void
  612. get_word(char *cp)
  613. {
  614.     int             c;
  615.  
  616.     while (1) {
  617.     c = popc();
  618.     if (!(isalnum(c) || c == '_')) {    /* OK, end of word */
  619.         *cp = 0;
  620.         pushc(c);
  621.         return;
  622.     }
  623.     *cp++ = c;
  624.     }
  625. }
  626.  
  627. /* strip comments, spaces etc */
  628. PRIVATE void
  629. eat_junk(void)
  630. {
  631.     int             c;
  632.  
  633.     while (1) {
  634.     c = popc();
  635.     if (c == '#' || c == '\r')    /* ignore '#' */
  636.         continue;
  637.  
  638.     if (c == '/') {        /* is this a comment? */
  639.         c = popc();
  640.         if (c == '*')
  641.         eat_comment();
  642.         else if (c == '/')
  643.         eat_linecomment();
  644.         else {        /* not a comment */
  645.         pushc(c);
  646.         pushc('/');
  647.         return;
  648.         }
  649.     } else if (!isspace(c)) {
  650.         pushc(c);
  651.         return;
  652.     }
  653.     }
  654.  
  655. }
  656.  
  657. /* eat a comment */
  658. PRIVATE void
  659. eat_comment(void)
  660. {
  661.     int             c;
  662.  
  663.     while (1) {
  664.     c = popc();
  665.     if (c == EOF)
  666.         return;
  667.  
  668.     if (c == '/') {
  669.         c = popc();
  670.         if (c != '*')
  671.         continue;
  672.         eat_comment();
  673.     } else if (c == '*')
  674.         if ((c = popc()) == '/')
  675.         return;
  676.         else
  677.         pushc(c);
  678.     }
  679. }
  680.  
  681. /* eat a // comment */
  682. PRIVATE void
  683. eat_linecomment(void)
  684. {
  685.     int             c;
  686.  
  687.     while (1) {
  688.     c = popc();
  689.     if (c == '\n' || c == EOF)
  690.         return;
  691.     }
  692. }
  693.  
  694.  
  695. /* i'm too lazy to type getc(infile); */
  696. PRIVATE int
  697. popc(void)
  698. {
  699.     int             c;
  700.  
  701.     if (current_file == NULL)
  702.     return EOF;
  703.  
  704.     c = getc(infile);
  705.  
  706.     if (c == '\n') {
  707.     if (!(dotcount++ % INDICATORCOUNT))
  708.         printf(".");
  709.     inputlines++;
  710.     }
  711.     return c;
  712. }
  713.  
  714. /* push back a char to the current infile */
  715. PRIVATE void
  716. pushc(int c)
  717. {
  718.     if (current_file == NULL)
  719.     return;
  720.  
  721.     if (c == '\n')
  722.     inputlines--;
  723.     ungetc(c, infile);
  724. }
  725.