home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / games / inform / compiler / source / c / inputs < prev    next >
Encoding:
Text File  |  1994-10-14  |  18.5 KB  |  512 lines

  1. /* ------------------------------------------------------------------------- */
  2. /*   "inputs" : Input routines, preprocessor, non-fatal errors               */
  3. /*                                                                           */
  4. /*   Part of Inform release 5                                                */
  5. /*                                                                           */
  6. /*   On non-ASCII machines, translate_to_ascii must be altered               */
  7. /* ------------------------------------------------------------------------- */
  8.  
  9. #include "header.h"
  10.  
  11. int32 marker_in_file;
  12. int  internal_line, total_source_line;
  13.  
  14. char *tokens;
  15.  
  16. char *forerrors_buff;
  17. int forerrors_line;
  18.  
  19. static char *tokens_p; static int32 **token_adds;
  20. static int *token_numbers;
  21.  
  22. static int32 **stack, **stack_longs;
  23. static int *stack_nos,
  24.            *stack_slot_free;
  25.  
  26. extern void inputs_allocate_arrays(void)
  27. {   forerrors_buff = my_malloc(BUFFER_LENGTH, "errors buffer");
  28.     token_adds = my_calloc(sizeof(char *), MAX_TOKENS, "token addresses");
  29.     token_numbers = my_calloc(sizeof(int), MAX_TOKENS, "token numbers");
  30.     stack = my_calloc(sizeof(char *), STACK_SIZE, "stack pointers");
  31.     stack_longs = my_calloc(sizeof(char *), STACK_LONG_SLOTS,
  32.         "stack long slot pointers");
  33.     stack_nos = my_calloc(sizeof(int), STACK_SIZE,
  34.         "stack numbers");
  35.     stack_slot_free = my_calloc(sizeof(int), STACK_SIZE,
  36.         "stack free space flags");
  37. }
  38.  
  39. extern void inputs_free_arrays(void)
  40. {   my_free(token_adds, "token addresses");
  41.     my_free(token_numbers, "token numbers");
  42. }
  43.  
  44. /* ------------------------------------------------------------------------- */
  45. /*   Preprocessor stack routines                                             */
  46. /*                                                                           */
  47. /*   This stack simulates inserting lines into the source, used when (eg) a  */
  48. /*   source line like                                                        */
  49. /*                     if 5*fish+2*loaves > multitude                        */
  50. /*                                                                           */
  51. /*   is replaced by assembly lines; the assembly lines are stacked up and    */
  52. /*   will be read in before the next source line.  Most of the complication  */
  53. /*   is to allow for these lines in turn to be rewritten back without them   */
  54. /*   falling out of order, as they would in a simple FIFO stack.             */
  55. /*                                                                           */
  56. /*   The stack needs a reasonable size (10 to 20 at the very minimum)        */
  57. /*   but almost all its lines will be used for short assembler instructions, */
  58. /*   so it needs little provision for full-blown lines (probably only one    */
  59. /*   "long slot" will ever be used, unless "write" is used).                 */
  60. /* ------------------------------------------------------------------------- */
  61.  
  62. static int entries=0, stack_next=0;
  63. static int ppstack_openb, ppstack_closeb;
  64.  
  65. extern void stack_create(void)
  66. {   int i; char *stackp;
  67.     stackp=my_malloc(STACK_SIZE*STACK_SHORT_LENGTH,"preprocessor stack");
  68.     for (i=0; i<STACK_SIZE; i++)
  69.         stack[i]=(int32 *) (stackp+i*STACK_SHORT_LENGTH);
  70.     stackp=my_malloc(STACK_LONG_SLOTS*BUFFER_LENGTH,"pp stack long slots");
  71.     for (i=0; i<STACK_LONG_SLOTS; i++)
  72.     {   stack_longs[i]=(int32 *) (stackp+i*BUFFER_LENGTH);
  73.         *(stack_longs[i])=0;
  74.     }
  75.     entries=0;
  76.     for (i=0; i<STACK_SIZE; i++) stack_slot_free[i]=1;
  77. }
  78.  
  79. extern void stack_line(char *p)
  80. {   int i, f, slot;
  81.  
  82.     for (i=0; (i<STACK_SIZE)&&(stack_slot_free[i]==0); i++);
  83.     if (i==STACK_SIZE)
  84.         memoryerror("STACK_SIZE", STACK_SIZE);
  85.  
  86.     slot=i; stack_slot_free[slot]=0;
  87.     for (i=entries; i>stack_next; i--)
  88.         stack_nos[i]=stack_nos[i-1];
  89.     stack_nos[stack_next++]=slot;
  90.     entries++;
  91.  
  92.     if (strlen(p)<STACK_SHORT_LENGTH)
  93.         strcpy((char *) stack[slot],p);
  94.     else
  95.     {   *(stack[slot])=0; f=0;
  96.         for (i=0; i<STACK_LONG_SLOTS; i++)
  97.             if ((*(stack_longs[i])==0)&&(f==0))
  98.             {   strcpy((char *)stack_longs[i],p);
  99.                 *(stack[slot]+1)=i;
  100.                 f=1;
  101.             }
  102.         if (f==0) {
  103.             memoryerror("STACK_LONG_SLOTS",STACK_LONG_SLOTS);
  104.         }
  105.     }
  106. }
  107.  
  108. static void destack_line(char *p)
  109. {   int i, slot;
  110.     stack_next=0;
  111.     slot=stack_nos[0];
  112.     stack_slot_free[slot]=1;
  113.     i= *(stack[slot]);
  114.     if (i!=0)
  115.         strcpy(p,(char *)stack[slot]);
  116.     else
  117.     {   i= *(stack[slot]+1);
  118.         strcpy(p,(char *)stack_longs[i]);
  119.         *(stack_longs[i])=0;
  120.     }
  121.     entries--;
  122.     for (i=0; i<entries; i++) stack_nos[i]=stack_nos[i+1];
  123. }
  124.  
  125. /* ------------------------------------------------------------------------- */
  126. /*   Character-level parsing and error reporting routines                    */
  127. /* ------------------------------------------------------------------------- */
  128.  
  129. static int firsthash_flag=1, recenthash_flag=0;
  130.  
  131. extern void input_begin_pass(void)
  132. {   total_source_line=0; total_files_read=1;
  133.     internal_line=0; endofpass_flag=0; marker_in_file=0;
  134. #ifdef USE_TEMPORARY_FILES
  135.     utf_zcode_p=zcode;
  136.     if (pass_number==2) open_temporary_files();
  137. #endif
  138.     ppstack_openb=0; ppstack_closeb=0;
  139.     firsthash_flag=1; recenthash_flag=0;
  140. }
  141.  
  142. static void print_hash(void)
  143. {   if (firsthash_flag==1) { printf("%d:",pass_number); firsthash_flag=0; }
  144.     printf("#"); recenthash_flag=1; fflush(stdout);
  145. }
  146.  
  147. static int errors[MAX_ERRORS];
  148. static char named_errors_buff[256];
  149.  
  150. static void message(int style, char *s)
  151. {   if (recenthash_flag==1) printf("\n");
  152.     recenthash_flag=0;
  153.     print_error_line();
  154.     printf("%s: %s\n",(style==1)?"Error":"Warning",s);
  155. #ifdef ARC_THROWBACK
  156.     throwback(style, s);
  157. #endif
  158.     if ((style==1)&&(concise_mode==0))
  159.     {   sprintf(forerrors_buff+68,"  ...etc");
  160.         printf("> %s\n",forerrors_buff);
  161.     }
  162. }
  163.  
  164. extern void error(char *s)
  165. {   int i;
  166.     if (no_errors==MAX_ERRORS) { fatalerror("Too many errors: giving up"); }
  167.     for (i=0; i<no_errors; i++)
  168.         if (errors[i]==internal_line) return;
  169.     errors[no_errors++]=internal_line;
  170.     message(1,s);
  171. }
  172.  
  173. extern void warning_named(char *s1, char *s2)
  174. {   int i;
  175.     i=strlen(s1)+strlen(s2)+3;
  176.     if (i>250) s2[247-strlen(s1)]=0;
  177.     sprintf(named_errors_buff,"%s \"%s\"",s1,s2);
  178.     no_warnings++;
  179.     message(2,named_errors_buff);
  180. }
  181.  
  182. extern void warning(char *s1)
  183. {   if (pass_number==1) return;
  184.     no_warnings++;
  185.     message(2,s1);
  186. }
  187.  
  188. extern void error_named(char *s1, char *s2)
  189. {   int i;
  190.     i=strlen(s1)+strlen(s2)+3;
  191.     if (i>250) s2[247-strlen(s1)]=0;
  192.     sprintf(named_errors_buff,"%s \"%s\"",s1,s2);
  193.     error(named_errors_buff);
  194. }
  195.  
  196. extern void no_such_label(char *lname)
  197. {   error_named("No such label as",lname);
  198. }
  199.  
  200. static void reached_new_line(void)
  201. {   total_source_line++;
  202.     advance_line();
  203.     if ((hash_mode==1)&&(total_source_line%100==0)) print_hash();
  204. }
  205.  
  206. static int not_line_end(int c)
  207. {   if (c=='\n') reached_new_line();
  208.     if ((c==0)||(c=='\n')) return(0);
  209.     return(1);
  210. }
  211.  
  212. static int quoted_mode;
  213. static int not_case_mode;
  214. static int one_quoted_mode;
  215. static int non_terminator(char c)
  216. {   if (c=='\n') reached_new_line();
  217.     if (quoted_mode!=0)
  218.     {   if ((c==0)||(c=='\\')) return(0);
  219.         return(1);
  220.     }
  221.     if ((c==0)||(c==';')||(c=='!')||(c=='\\')||(c=='{')||(c=='}')) return(0);
  222.     if ((c==':')&&(not_case_mode==0)&&(one_quoted_mode==0)) return(0);
  223.     return(1);
  224. }
  225.  
  226. /* ------------------------------------------------------------------------- */
  227. /*   The Tokeniser (18)... coming to cinemas near you                        */
  228. /*     incorporating the martial arts classic                                */
  229. /*   Tokeniser II - This Time It's Optimal,                                  */
  230. /*     with Dolph Lundgren as Dilip Sequeira and Gan as the two short planks */
  231. /*   (and now a somewhat sub-standard sequel,                                */
  232. /*     Tokeniser III: The Next Specification is Ugly)                        */
  233. /* ------------------------------------------------------------------------- */
  234.  
  235. static int no_tokens;
  236.  
  237. #define NUMBER_SEPARATORS 27
  238.  
  239. #define QUOTE_CODE    1000
  240. #define DQUOTE_CODE   1001
  241. #define NEWLINE_CODE  1002
  242. #define NULL_CODE     1003
  243. #define SPACE_CODE    1004
  244.  
  245. /*  This list can't safely be changed without also changing the header
  246.     separator #defines... */
  247.  
  248. static const char separators[NUMBER_SEPARATORS][4] = { 
  249.     "->", "-->", "--", "-", "++", "+", "*", "/", "%",
  250.     "||", "|", "&&","&",
  251.     "==", "=", "~=", ">=", ">", 
  252.     "<=", "<", "(", ")", ",", ".&", ".#", ".", ":" };
  253.  
  254. static int char_grid[256];
  255.  
  256. extern void make_s_grid(void)
  257. {   int i, j;
  258.     for (i=0; i<256; i++) char_grid[i]=0;
  259.     for (i=0; i<NUMBER_SEPARATORS; i++)
  260.     { j=separators[i][0];
  261.       if(char_grid[j]==0) char_grid[j]=i*16+1; else char_grid[j]++;
  262.     }
  263.     char_grid['\''] = QUOTE_CODE;
  264.     char_grid['\"'] = DQUOTE_CODE;
  265.     char_grid['\n'] = NEWLINE_CODE;
  266.     char_grid[0]    = NULL_CODE;
  267.     char_grid[' ']  = SPACE_CODE;
  268.     char_grid[TAB_CHARACTER]  = SPACE_CODE;
  269. }
  270.  
  271. extern void tokenise_line(void)
  272. {   char *p,*q; int i, j, k, bite, tok_l, tn=-1, next_tn=-1, quoted_size;
  273.     const char *r;
  274.     no_tokens=0; tokens_p=tokens; token_adds[0]=(int32 *) tokens_p;
  275.     p=buffer;
  276.     for (i=0, tok_l=0; i<MAX_TOKENS; i++)
  277.     { if(tok_l)
  278.       {   for(j=0;j<tok_l;j++) *tokens_p++= *p++; tok_l=0;
  279.           tn=next_tn; goto got_tok;
  280.       }
  281.       while(char_grid[*p]==SPACE_CODE) p++;
  282.       for(bite=0;1;)
  283.       { 
  284.         if ((*p=='-') && (isdigit(p[1])))
  285.         {
  286.             if (bite) { *tokens_p++=0;
  287.               token_numbers[no_tokens]=tn; tn=-1;
  288.               token_adds[++no_tokens]=(int32 *)tokens_p; }
  289.             *tokens_p++=*p++;
  290.             *tokens_p++=*p++;
  291.             while (isdigit(*p)) *tokens_p++=*p++;
  292.             bite=0; goto got_tok;
  293.         }
  294.         switch(char_grid[*p]) 
  295.         {  case 0:            *tokens_p++= *p++; bite=1; break;
  296.            case SPACE_CODE:   goto got_tok;
  297.            case DQUOTE_CODE:  quoted_size=0;
  298.                               do { *tokens_p++= *p++;
  299.                                    if (quoted_size++==MAX_QTEXT_SIZE)
  300.                                    {   
  301.                             error("Too much text for one pair of \"s to hold");
  302.                                        *p='\"'; break;
  303.                                    }
  304.                                  } while (*p && *p!='\n' && *p!='\"');
  305.                               if (*p=='\"') *tokens_p++= *p++; goto got_tok;
  306.            case NEWLINE_CODE: reached_new_line();
  307.                               if (bite) goto got_tok; return;
  308.            case QUOTE_CODE:   quoted_size=0;
  309.                               do { *tokens_p++= *p++;
  310.                                    if (quoted_size++==MAX_QTEXT_SIZE)
  311.                                    {   
  312.                             error("Too much text for one pair of 's to hold");
  313.                                        *p='\''; break;
  314.                                    }
  315.                                  } while (*p && *p!='\n' && *p!='\'');
  316.                               if (*p=='\'') *tokens_p++= *p++; goto got_tok;
  317.            case NULL_CODE:    if (bite) goto got_tok; return;
  318.            default:  for (j=char_grid[*p]>>4,k=j+(char_grid[*p]&15);j<k;j++) 
  319.                      {   for (q=p,r=separators[j];*q== *r && *r;q++,r++);
  320.                          if (!*r) 
  321.                          {   if(bite)
  322.                              {   tok_l=q-p; next_tn=j; }
  323.                              else
  324.                              {   while(p<q) *tokens_p++= *p++;
  325.                                  tn=j;
  326.                              }
  327.                              goto got_tok;
  328.                          }
  329.                      }
  330.                      *tokens_p++= *p++;bite=1;
  331.         }
  332.       }
  333.     got_tok:
  334.       *tokens_p++=0; token_numbers[no_tokens]=tn; tn=-1;
  335.       token_adds[++no_tokens]=(int32 *)tokens_p;
  336.     }
  337.     error("Too many tokens on line (note: to increase the maximum, \
  338. set $MAX_TOKENS=some-bigger-number on the Inform command line)");
  339.  
  340.     no_tokens=MAX_TOKENS-1;
  341. }
  342.  
  343. extern void word(char *b1, int32 w)
  344. {   if (w>no_tokens) { b1[0]=0; return; }
  345.     strcpy(b1, (char *)token_adds[w-1]);
  346. }
  347.  
  348. extern int word_token(int w)
  349. {   if (w>no_tokens) return(-1);
  350.     return(token_numbers[w-1]);
  351. }
  352.  
  353. extern void dequote_text(char *b1)
  354. {   int i;
  355.     if (*b1!='\"') error_named("Open quotes \" expected for text but found",b1);
  356.     for (i=0; b1[i]!=0; i++) b1[i]=b1[i+1];
  357.     i=i-2;
  358.     if (b1[i]!='\"')
  359.         error_named("Close quotes \" expected for text but found",b1);
  360.     b1[i]=0;
  361. }
  362.  
  363. extern void textword(char *b1, int w)
  364. {   word(b1,w); dequote_text(b1);
  365. }
  366.  
  367. /* ------------------------------------------------------------------------- */
  368. /*   Get the next line of input, and return 1 if it came from the            */
  369. /*   preprocessor stack and 0 if it really came from the source files.       */
  370. /*   So:                                                                     */
  371. /*     If something's waiting on the stack, send that.                       */
  372. /*     If there are braces to be opened or closed, send those.               */
  373. /*     If at the end of the source, send an "end" directive.                 */
  374. /*     Otherwise, keep going until a ; is reached which is not in 's or "s;  */
  375. /*       throw away everything on any text line after a comment ! character; */
  376. /*       fold out characters between a \ and the first non-space on the next */
  377. /*       line.                                                               */
  378. /* ------------------------------------------------------------------------- */
  379.  
  380. static int braces_level=0;
  381. static int inferred_braces[MAX_BLOCK_NESTING];
  382. static int ib_sp=0; 
  383.  
  384. static char first_tok[17];
  385.  
  386. extern int get_next_line(void)
  387. {   int i, j, k, ftp, first_token_mode,
  388.         block_expected=0, b_l, b_f; char d, d2;
  389.     internal_line++;
  390.  
  391.     quoted_mode=0; one_quoted_mode=0;
  392.     do
  393.     {   if (entries!=0) { destack_line(buffer); return(1); }
  394.         if (ppstack_openb>0)
  395.         {   strcpy(buffer,"{"); ppstack_openb--; braces_level++; return(1); }
  396.         if (ppstack_closeb>0)
  397.         {   strcpy(buffer,"}"); ppstack_closeb--; braces_level--;
  398.             if ((ib_sp>0)&&(braces_level-1==inferred_braces[ib_sp-1]))
  399.               {   ib_sp--; ppstack_closeb++; }
  400.             return(1);
  401.         }
  402.  
  403.         if (file_end(marker_in_file)==1) { strcpy(buffer,"#end"); return(1); }
  404.         i=0; j=0; first_token_mode=1; not_case_mode=0; ftp=0; block_expected=0;
  405.       GNLL:
  406.         for (; non_terminator(d=file_char(marker_in_file+i)); i++, j++)
  407.         {
  408.             if (j>=BUFFER_LENGTH-2)
  409.             {   error("Line too long (note: to increase the maximum length, \
  410. set $BUFFER_LENGTH=some-bigger-number on the Inform command line)");
  411.                 buffer[BUFFER_LENGTH-2]=0;
  412.                 if (pass_number==1)
  413.                 {   buffer[76]=0;
  414.                     printf("The overlong line began:\n<%s>\n",buffer);
  415.                 }
  416.                 return(0);
  417.             }
  418.             buffer[j]=d;
  419.             if (d=='\"' && one_quoted_mode==0) quoted_mode=1-quoted_mode;
  420.             if (d=='\'' && quoted_mode==0) one_quoted_mode=1-one_quoted_mode;
  421.             if ((d=='[') && (pass_number==2) && (quoted_mode==0)
  422.                 && (one_quoted_mode==0)) keep_routine_linenum();
  423.             if ((d==']') && (pass_number==2) && (quoted_mode==0)
  424.                 && (one_quoted_mode==0)) keep_re_linenum();
  425.             if (d=='(') not_case_mode=1;
  426.             if ((first_token_mode==1) && (d!=' ') && (d!='\n') && (d!='!')
  427.                                       && (d!=TAB_CHARACTER))
  428.             {   forerrors_line = current_source_line();
  429.                 first_token_mode=2;
  430.             }
  431.             if (first_token_mode==2)
  432.             {   if (!isalpha(d))
  433.                 {   first_token_mode=0;
  434.                     if (ftp>0)
  435.                     {   first_tok[ftp]=0;
  436.                         d2=first_tok[0];
  437.                         if (   ((d2=='o')&&(strcmp(first_tok, "objectloop")==0))
  438.                              ||((d2=='f')&&(strcmp(first_tok, "for")==0))
  439.                              ||((d2=='i')&&(strcmp(first_tok, "if")==0))
  440.                              ||((d2=='w')&&(strcmp(first_tok, "while")==0)) )
  441.                         {   block_expected=1; b_l=0; b_f=0; }
  442.                         else
  443.                         if (   ((d2=='d')&&(strcmp(first_tok, "do")==0))
  444.                              ||((d2=='e')&&(strcmp(first_tok, "else")==0))  )
  445.                             goto MakeBlock;
  446.                     }
  447.                 }
  448.                 else
  449.                 {   if (ftp==16) ftp=0;
  450.                     else if (isupper(d)) first_tok[ftp++]=tolower(d);
  451.                     else first_tok[ftp++]=d;
  452.                 }
  453.             }
  454.             if ((block_expected==1)&&(quoted_mode==0))
  455.             {
  456.                 if (d=='(') { b_l++; b_f=1; }
  457.                 else
  458.                     if ((b_f==0)&&(d!=' ')&&(d!='\n'))
  459.                     {   block_expected=0;
  460.                     }    
  461.                 if (d==')')
  462.                 {   b_l--;
  463.                     if (b_l==0)
  464.                     {   
  465.                         MakeBlock: j++; i++;
  466.                         buffer[j]=0;
  467.  
  468.                         ppstack_openb++; marker_in_file+=i; i=0;
  469.                         do
  470.                         {   d=file_char(marker_in_file+i++);
  471.                             if (d=='\n') reached_new_line();
  472.                         } while ((d==' ')||(d=='\n'));
  473.                         marker_in_file+=(i-1);
  474.                         if (d=='{') marker_in_file++;
  475.                         else inferred_braces[ib_sp++]=braces_level;
  476.  
  477.                         for (i=0; buffer[i]!=0; i++)
  478.                             if (buffer[i]=='\n') buffer[i]=' ';
  479.                         return(0);
  480.                     }
  481.                 }
  482.             }
  483.         }
  484.  
  485.         switch(d)
  486.         {   case '!': while (not_line_end(file_char(marker_in_file+i))) i++;
  487.                       i++; goto GNLL;
  488.             case '{': ppstack_openb++; break;
  489.             case '}': ppstack_closeb++; break;
  490.             case ':': buffer[j++]=':'; break;
  491.             case '\\':
  492.                 while (not_line_end(file_char(marker_in_file+i))) i++; i++;
  493.                 while ( ((k=file_char(marker_in_file+i))==' ')
  494.                         || (k==TAB_CHARACTER) ) i++; goto GNLL;
  495.         }
  496.  
  497.         buffer[j]=0;
  498.         marker_in_file+=i+1;
  499.  
  500.         for (i=0; buffer[i]!=0; i++)
  501.           if (buffer[i]=='\n') buffer[i]=' ';
  502.  
  503.         for (i=0; buffer[i]!=0; i++)
  504.           if (buffer[i]!=' ')
  505.           {   if ((ib_sp>0)&&(braces_level-1==inferred_braces[ib_sp-1]))
  506.               {   ib_sp--; ppstack_closeb++; }
  507.               return(0);
  508.           }
  509.     } while (1==1);
  510.     return(0);
  511. }
  512.