stage1_2/iec_flex.ll
changeset 756 634f476cb60f
parent 737 f6bc5230aadd
child 757 f1fc4aa6f0e3
--- a/stage1_2/iec_flex.ll	Mon Nov 26 16:38:15 2012 +0000
+++ b/stage1_2/iec_flex.ll	Tue Nov 27 14:49:08 2012 +0000
@@ -247,6 +247,8 @@
  * but first return to the stream an additional character to mark the end of the token. 
  */
 void unput_and_mark(const char c);
+
+void include_file(const char *include_filename);
 %}
 
 
@@ -867,38 +869,8 @@
 <include_beg>{file_include_pragma_beg}	BEGIN(include_filename);
 
 <include_filename>{file_include_pragma_filename}	{
-			  /* got the include file name */
-			  int i;
-
-			  if (include_stack_ptr >= MAX_INCLUDE_DEPTH) {
-			    fprintf(stderr, "Includes nested too deeply\n");
-			    exit( 1 );
-			  }
-			  include_stack[include_stack_ptr].buffer_state = YY_CURRENT_BUFFER;
-			  include_stack[include_stack_ptr].env = current_tracking;
-			  include_stack[include_stack_ptr].filename = current_filename;
-			  
-			  for (i = 0, yyin = NULL; (INCLUDE_DIRECTORIES[i] != NULL) && (yyin == NULL); i++) {
-			    char *full_name = strdup3(INCLUDE_DIRECTORIES[i], "/", yytext);
-			    if (full_name == NULL) {
-			      fprintf(stderr, "Out of memory!\n");
-			      exit( 1 );
-			    }
-			    yyin = fopen(full_name, "r");
-			    free(full_name);
-			  }
-
-			  if (!yyin) {
-			    fprintf(stderr, "Error opening included file %s\n", yytext);
-			    exit( 1 );
-			  }
-
-			  current_filename = strdup(yytext);
-			  current_tracking = GetNewTracking(yyin);
-			  include_stack_ptr++;
-
-			  /* switch input buffer to new file... */
-			  yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+			  /* set the internal state variables of lexical analyser to process a new include file */
+			  include_file(yytext);
 			  /* switch to whatever state was active before the include file */
 			  yy_pop_state();
 			  /* now process the new file... */
@@ -947,6 +919,8 @@
 			}
 
 <include_end>{file_include_pragma_end}	yy_pop_state();
+	/* handle the artificial file includes created by include_string(), which do not end with a '}' */
+<include_end>.				unput_text(0); yy_pop_state(); 
 
 
 	/*********************************/
@@ -1690,6 +1664,79 @@
 }
 
 
+
+/* set the internal state variables of lexical analyser to process a new include file */
+void handle_include_file_(FILE *filehandle, const char *filename) {
+  if (include_stack_ptr >= MAX_INCLUDE_DEPTH) {
+    fprintf(stderr, "Includes nested too deeply\n");
+    exit( 1 );
+  }
+  
+  yyin = filehandle;
+  
+  include_stack[include_stack_ptr].buffer_state = YY_CURRENT_BUFFER;
+  include_stack[include_stack_ptr].env = current_tracking;
+  include_stack[include_stack_ptr].filename = current_filename;
+  
+  current_filename = strdup(filename);
+  current_tracking = GetNewTracking(yyin);
+  include_stack_ptr++;
+
+  /* switch input buffer to new file... */
+  yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+}
+
+
+
+/* insert the code (in <source_code>) into the source code we are parsing.
+ * This is done by creating an artificial file with that new source code, and then 'including' the file
+ */
+void include_string(const char *source_code) {
+  FILE *tmp_file = tmpfile();
+  
+  if(tmp_file == NULL) {
+    perror("Error creating temp file.");
+    exit(EXIT_FAILURE);
+  }
+
+  fwrite((void *)source_code, 1, strlen(source_code), tmp_file);
+  rewind(tmp_file);
+
+  /* now parse the tmp file, by asking flex to handle it as if it had been included with the (*#include ... *) pragma... */
+  handle_include_file_(tmp_file, "");
+//fclose(tmp_file);  /* do NOT close file. It must only be closed when we finish reading from it! */
+}
+
+
+
+/* Open an include file, and set the internal state variables of lexical analyser to process a new include file */
+void include_file(const char *filename) {
+  FILE *filehandle = NULL;
+  
+  for (int i = 0; (INCLUDE_DIRECTORIES[i] != NULL) && (filehandle == NULL); i++) {
+    char *full_name;
+    full_name = strdup3(INCLUDE_DIRECTORIES[i], "/", filename);
+    if (full_name == NULL) {
+      fprintf(stderr, "Out of memory!\n");
+      exit( 1 );
+    }
+    filehandle = fopen(full_name, "r");
+    free(full_name);
+  }
+
+  if (NULL == filehandle) {
+    fprintf(stderr, "Error opening included file %s\n", filename);
+    exit( 1 );
+  }
+
+  /* now process the new file... */
+  handle_include_file_(filehandle, filename);
+}
+
+
+
+
+
 /* return all the text in the current token back to the input stream, except the first n chars. */
 void unput_text(unsigned int n) {
   /* it seems that flex has a bug in that it will not correctly count the line numbers