Noble Ape
The Central Directories of the Noble Ape Simulation.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
parse.c
Go to the documentation of this file.
1 /****************************************************************
2 
3  parse.c
4 
5  =============================================================
6 
7  Copyright 1996-2014 Tom Barbalet. All rights reserved.
8 
9  Permission is hereby granted, free of charge, to any person
10  obtaining a copy of this software and associated documentation
11  files (the "Software"), to deal in the Software without
12  restriction, including without limitation the rights to use,
13  copy, modify, merge, publish, distribute, sublicense, and/or
14  sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following
16  conditions:
17 
18  The above copyright notice and this permission notice shall be
19  included in all copies or substantial portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  OTHER DEALINGS IN THE SOFTWARE.
29 
30  This software and Noble Ape are a continuing work of Tom Barbalet,
31  begun on 13 June 1996. No apes or cats were harmed in the writing
32  of this software.
33 
34  ****************************************************************/
35 
40 #include "noble.h"
41 
42 #if defined(ROUGH_CODE_OUT) || defined(COMMAND_LINE_DEBUG)
43 
44 #include "stdio.h"
45 
46 #endif
47 
48 #define SYNTAX_NUM 19
49 #define SYNTAX_WIDTH 4
50 static const n_byte syntax_codes[SYNTAX_NUM][SYNTAX_WIDTH]=
51 {
52  "-",
53  "+",
54  "*",
55  "&",
56  "^",
57  "|",
58 
59  ">",
60  "<",
61  "==",
62  "!=",
63  "&&",
64  "||",
65  "/",
66 
67  "%",
68 
69  ">>",
70  "<<",
71 
72  "<=",
73  ">=",
74 
75  "="
76 };
77 
78 static n_int variable_num;
79 static n_int number_num;
80 
81 static n_int quote_up;
82 
83 #ifdef SCRIPT_DEBUG
84 
85 static n_int tab_step = 0;
86 static variable_string * local_var_codes;
87 
89 static n_int single_entry = 1;
90 
91 static void * writable_selection;
92 
94 {
95  return io_file_ready(single_entry, file_debug);
96 }
97 
99 {
100  io_file_cleanup(&single_entry, &file_debug);
101 }
102 
103 void scdebug_writeon(void * ptr)
104 {
105  writable_selection = ptr;
106  io_file_writeon(&single_entry, &file_debug, 1);
107 }
108 
109 void scdebug_writeoff(void * ptr)
110 {
111  if (ptr != writable_selection) return;
112 
113  io_file_writeoff(&single_entry, file_debug);
114 }
115 
116 void scdebug_string(void * ptr,n_constant_string string)
117 {
118  if (ptr != writable_selection) return;
119 
120  io_file_string(single_entry, file_debug, string);
121 }
122 
124 {
125  n_string return_value = 0L;
126  if((variable < VARIABLE_MAX)
127 #ifndef COMMAND_LINE_DEBUG
128  && (file_debug != 0L)
129 #endif
130  )
131  {
132  return_value = (n_string) local_var_codes[variable];
133  }
134  return return_value;
135 }
136 
137 void scdebug_int(void * ptr, n_int number)
138 {
139  if (single_entry == 0) return;
140 
141  if (ptr != writable_selection) return;
142 
143 #ifndef COMMAND_LINE_DEBUG
144  if(file_debug != 0L)
145  {
146  io_writenumber(file_debug, number, 1, 0);
147  }
148 #else
149  printf("%d",(int)number);
150 #endif
151 }
152 
153 void scdebug_newline(void * ptr)
154 {
155  if (single_entry == 0) return;
156 
157  if (ptr != writable_selection) return;
158 
159 #ifndef COMMAND_LINE_DEBUG
160  if(file_debug != 0L)
161 #endif
162  {
163  n_int loop = 0;
164 #ifndef COMMAND_LINE_DEBUG
165  io_write(file_debug, "", 1);
166 #else
167  printf("\n");
168 #endif
169  if(tab_step > 0)
170  {
171  while(loop<tab_step)
172  {
173 #ifndef COMMAND_LINE_DEBUG
174  io_write(file_debug," ",0);
175 #else
176  printf(" ");
177 #endif
178  loop++;
179  }
180  }
181  }
182 }
183 
184 void scdebug_tabstep(void * ptr, n_int steps)
185 {
186  if (ptr != writable_selection) return;
187 
188 #ifndef COMMAND_LINE_DEBUG
189  if(file_debug != 0L)
190 #endif
191  {
192  tab_step += steps;
193  }
194 }
195 #endif
196 
197 
198 static n_int parse_number_add(n_interpret * interpret, n_int out_value)
199 {
200  n_int loop = 0;
201 
202  /* is this number already stored? */
203  while(loop < number_num)
204  {
205  if(interpret->number_buffer[loop] == out_value)
206  return loop;
207  loop++;
208  }
209  /* if not, add it to the number store */
210  interpret->number_buffer[loop] = out_value;
211  if(number_num < NUMBER_MAX)
212  {
213  number_num++;
214  }
215  else
216  {
218  }
219  return loop;
220 }
221 
222 /* outputs the number of bytes to advance in the interpret stream */
223 static n_int parse_number(n_interpret * interpret, const n_byte * number)
224 {
225  n_int out_value = 0;
226  n_int point_counter = 0;
227 
228  /* read out the number from the interpret stream */
229  do
230  {
231  n_byte temp = number[point_counter++];
232  if((!ASCII_NUMBER(temp)) && (temp != 0))
233  {
234  return io_apescript_error(0L, AE_NUMBER_EXPECTED); /* this error should never occur */
235  }
236  out_value = (out_value * 10) + (temp - '0');
237  }
238  while((number[point_counter]!=0) && (out_value>-1));
239 
240  if((out_value < 0) || (out_value > 0x7fffffff))
241  {
243  }
244 
245  return parse_number_add(interpret, out_value);
246 }
247 
248 static n_int parse_quoted_string(n_interpret * interpret, n_constant_string string)
249 {
250  return parse_number_add(interpret, (n_int)math_hash_fnv1(string));
251 }
252 
253 static n_byte parse_character(n_byte temp)
254 {
255  if(ASCII_QUOTE(temp))
256  {
257  quote_up ^= 1;
258  return APESCRIPT_STRING;
259  }
260 
261  if (quote_up)
262  {
263  return APESCRIPT_STRING;
264  }
265  if(ASCII_BRACES(temp) || ASCII_BRACKET(temp))
266  {
267  return temp;
268  }
269  if((ASCII_EQUAL(temp) || ASCII_LOGICAL(temp))||(ASCII_ARITHMETIC(temp) || ASCII_DIRECTIONAL(temp)))
270  {
271  return APESCRIPT_OPERATOR;
272  }
273  if(ASCII_NUMBER(temp))
274  {
275  return APESCRIPT_NUMBER;
276  }
277  if(ASCII_TEXT(temp))
278  {
279  return APESCRIPT_TEXT;
280  }
281  if(ASCII_SEMICOLON(temp))
282  {
283  return APESCRIPT_SEMICOLON;
284  }
285  return APESCRIPT_FAILURE;
286 }
287 
288 static n_int parse_write_code(n_interpret * final_prog, n_byte value, n_byte code)
289 {
290 #ifdef ROUGH_CODE_OUT
291  printf("%c ",value);
292 #endif
293 
294  if (io_file_write(final_prog->binary_code, value) == -1)
295  {
297  }
298  if (CODE_VALUE_REQUIRED(value))
299  {
300  if(io_file_write(final_prog->binary_code, code) == -1)
301  {
303  }
304 
305 #ifdef ROUGH_CODE_OUT
306  printf("%d ",code);
307 #endif
308  }
309 
310 #ifdef ROUGH_CODE_OUT
311  if (value == APESCRIPT_SEMICOLON || value == APESCRIPT_OPEN_BRACE || value == APESCRIPT_CLOSE_BRACE)
312  {
313  printf("\n");
314  }
315 #endif
316  return 0;
317 }
318 
319 static n_int parse_string(const n_byte * test, const n_byte * compare, n_int number)
320 {
321  n_int loop = 0;
322  while(loop<number)
323  {
324  if(test[loop] != compare[loop])
325  return -1;
326  loop++;
327  }
328  return 1;
329 }
330 
331 static n_int parse_buffer(n_interpret * final_prog, n_byte previous, const n_byte * buffer)
332 {
333  variable_string *variable_codes = final_prog->variable_strings;
334  n_int result = -1;
335  n_int loop = 0;
336  switch(previous)
337  {
338  case (APESCRIPT_NUMBER):
339  result = parse_number(final_prog, buffer); /* this loads the number into the number buffer */
340  if(result == -1)
341  {
342  return -1;
343  }
344  if(parse_write_code(final_prog, previous, (n_byte)result) == -1) /* this writes the number allocation code */
345  {
346  return -1;
347  }
348  break;
349 
350  case (APESCRIPT_STRING):
351  result = parse_quoted_string(final_prog, (n_constant_string)buffer); /* this loads the number into the number buffer */
352  if(result == -1)
353  {
354  return -1;
355  }
356  if(parse_write_code(final_prog, APESCRIPT_NUMBER, (n_byte)result) == -1) /* this writes the number allocation code */
357  {
358  return -1;
359  }
360  break;
361  case (APESCRIPT_TEXT):
362  while((loop < variable_num) && (result == -1))
363  {
364  if(parse_string(variable_codes[loop], buffer, VARIABLE_WIDTH) == 1)
365  {
366  result = loop;
367  }
368  loop++;
369  }
370  if(result == -1)
371  {
372  if(variable_num < VARIABLE_MAX)
373  {
374  n_int loop2 = 0;
375  while(loop2 < (VARIABLE_WIDTH))
376  {
377  variable_codes[variable_num][loop2] = buffer[loop2];
378  loop2++;
379  }
380  variable_num++;
381  }
382  else
383  {
385  }
386  result = loop;
387  }
388  if(parse_write_code(final_prog, previous, (n_byte)result) == -1)
389  {
390  return -1;
391  }
392  break;
393  case (APESCRIPT_OPERATOR):
394  while((loop < SYNTAX_NUM) && (result == -1))
395  {
396  if(parse_string(syntax_codes[loop],buffer,SYNTAX_WIDTH) == 1)
397  {
398  result = loop;
399  }
400  loop++;
401  }
402  if(result == -1) /* no error reported up until now */
403  {
405  }
406  if(parse_write_code(final_prog, previous, (n_byte)result) == -1)
407  {
408  return -1;
409  }
410  break;
411  default:
412  {
413  n_byte value;
414  while((value = buffer[loop++]) != 0)
415  {
416  if(parse_write_code(final_prog, value, 0) == -1)
417  {
418  return -1;
419  }
420  }
421  }
422  break;
423  }
424  return 0;
425 }
426 
436 n_interpret * parse_convert(n_file * input, n_int main_entry, variable_string * variables)
437 {
438  n_interpret * final_prog = 0L;
439  n_byte * local_data;
440  n_uint end_loop;
441  n_uint loop = 0;
442  n_int * local_number;
443  n_byte buffer[ VARIABLE_WIDTH ];
444  n_int buffer_size = 0;
445  n_byte previous = 0;
446 
447  /* remove the white space from the input file */
448 
449  io_whitespace(input);
450 
451  /* perform the initial allocations */
452 
453  if((final_prog = io_new(sizeof(n_interpret))) == 0L)
454  {
455  return 0L;
456  }
457 
458  if((final_prog->binary_code = io_file_new())== 0L)
459  {
460  io_free((void **)&final_prog);
461  return 0L;
462  }
463 
464  if(final_prog->binary_code->data == 0L)
465  {
466  interpret_cleanup(&final_prog);
467  return 0L;
468  }
469 
470  /* allow for the space for the size to be written after everything else has been written/calculated */
471 
473 
474  final_prog->variable_strings = variables;
475  final_prog->special_less = (VARIABLE_IF + 1);
476  final_prog->main_entry = main_entry;
477 
478  local_number = final_prog->number_buffer;
479 
480  variable_num = main_entry + 1;
481 
482  number_num = 1;
483 
484  quote_up = 0;
485 
486  /* clear everything initially */
487 
488  while(loop < NUMBER_MAX)
489  {
490  local_number[ loop++ ] = 0;
491  }
492  loop = 0;
493  io_erase(buffer, VARIABLE_WIDTH);
494 
495  local_data = input->data;
496  end_loop = input->size;
497 
498  /* work through each character in the input file */
499 
500  while(loop < end_loop)
501  {
502  n_byte temp = local_data[ loop++ ];
503  /* each character has a particular type */
504  n_byte convert = parse_character(temp);
505  /* if it is a failure type i.e. not to be used, then fail */
506  if (convert == APESCRIPT_FAILURE)
507  {
508  interpret_cleanup(&final_prog);
510  return 0L;
511  }
512  /* if there is a change in type, then parse the previous buffer */
513  if ((previous != convert) && (previous != 0))
514  {
515  if(parse_buffer(final_prog, previous, buffer) == -1)
516  {
517  interpret_cleanup(&final_prog);
518  return 0L;
519  }
520 
521  /* clear the buffer for new characters coming in */
522  buffer_size = 0;
523  io_erase(buffer, VARIABLE_WIDTH);
524  }
525 
526  /* add the character to the buffer */
527  buffer[buffer_size++] = temp;
528 
529  /* if the buffer gets to big, it's a problem */
530  if (buffer_size == (VARIABLE_WIDTH - 1))
531  {
532  interpret_cleanup(&final_prog);
534  return 0L;
535  }
536 
537  /* track the previous type */
538  previous = convert;
539  }
540  /* handle the last type case at the end of the input file */
541  if (parse_buffer(final_prog, previous, buffer) == -1)
542  {
543  interpret_cleanup(&final_prog);
544  return 0L;
545  }
546  {
547  n_byte local_numbers[SIZEOF_NUMBER_WRITE];
548  n_uint loop_sizeof_number;
549  /* this is the one special case for direct writing as the original stamp size was allowed */
550  io_int_to_bytes(final_prog->binary_code->location,final_prog->binary_code->data); /* write the basic size header */
551  end_loop = number_num;
552  loop = 1;
553  io_int_to_bytes(number_num,local_numbers); /* write the number of numbers */
554  loop_sizeof_number = 0;
555  while (loop_sizeof_number < SIZEOF_NUMBER_WRITE)
556  {
557  if(io_file_write(final_prog->binary_code, local_numbers[loop_sizeof_number]) == -1)
558  {
559  interpret_cleanup(&final_prog);
560  return 0L;
561  }
562  loop_sizeof_number++;
563  }
564  while (loop<end_loop)
565  {
566  io_int_to_bytes((final_prog->number_buffer[loop]),local_numbers); /* write the numbers */
567  loop_sizeof_number = 0;
568  while (loop_sizeof_number < SIZEOF_NUMBER_WRITE)
569  {
570  if(io_file_write(final_prog->binary_code, local_numbers[loop_sizeof_number]) == -1)
571  {
572  interpret_cleanup(&final_prog);
573  return 0L;
574  }
575  loop_sizeof_number++;
576  }
577  loop++;
578  }
579  }
580 #ifdef SCRIPT_DEBUG
581  local_var_codes = variables;
582 #endif
583  return final_prog;
584 }
585