Example #1
0
int main(int argc, char *argv[])
{
  clock_t rdp_finish_time, rdp_start_time = clock();
  int
    rdp_symbol_statistics = 0,    /* show symbol_ table statistics flag */
    rdp_line_echo_all = 0,        /* make a listing on all passes flag */
    rdp_filter = 0,               /* filter flag */
    rdp_line_echo = 0,            /* make listing flag */

    rdp_lexicalise = 0;            /* print lexicalised output flag */

  unsigned long rdp_textsize = 35000l;   /* size of scanner text array */

  unsigned long rdp_tabwidth = 8l;   /* tab expansion width */

  char* rdp_vcg_filename = NULL;      /* filename for -V option */

  rdp_tree_node_data* rdp_tree = (rdp_tree_node_data*) graph_insert_graph("RDP derivation tree");  /* hook for derivation tree */
  rdp_tree_node_data* rdp_tree_root;

  arg_message("Minitree compiler V1.50 (c) Adrian Johnstone 1997\n" RDP_STAMP "\n\n""Usage: minitree [options] source[.m]");

  arg_message("");
  arg_boolean('f', "Filter mode (read from stdin and write to stdout)", &rdp_filter);
  arg_boolean('l', "Make a listing", &rdp_line_echo);
  arg_boolean('L', "Print lexicalised source file", &rdp_lexicalise);
  arg_string ('o', "Write output to filename", &rdp_outputfilename);
  arg_boolean('s', "Echo each scanner symbol as it is read", &rdp_symbol_echo);
  arg_boolean('S', "Print summary symbol table statistics", &rdp_symbol_statistics);
  arg_numeric('t', "Tab expansion width (default 8)", &rdp_tabwidth);
  arg_numeric('T', "Text buffer size in bytes for scanner (default 20000)", &rdp_textsize);
  arg_boolean('v', "Set verbose mode", &rdp_verbose);
  arg_string ('V', "Write derivation tree to filename in VCG format", &rdp_vcg_filename);

  rdp_sourcefilenames = arg_process(argc, argv);

  /* Fix up filetypes */
  for (rdp_sourcefilenumber = 0; rdp_sourcefilenames[rdp_sourcefilenumber] != NULL; rdp_sourcefilenumber++)
    rdp_sourcefilenames[rdp_sourcefilenumber] = text_default_filetype(rdp_sourcefilenames[rdp_sourcefilenumber], "m");

  if (rdp_filter)
  {
    rdp_sourcefilenames[0] = "-";
    rdp_outputfilename = "-";
    rdp_sourcefilenames[1] = NULL;     /* make sure no further filenames are taken from the array */

  }
  if ((rdp_sourcefilename = rdp_sourcefilenames[0]) == NULL)
     arg_help("no source files specified");

  if (rdp_sourcefilenames[1] != NULL)
    text_message(TEXT_FATAL, "multiple source files not allowed\n");
  text_init(rdp_textsize, 25, 100, (int) rdp_tabwidth);
  scan_init(0, 0, 0, rdp_symbol_echo, rdp_tokens);
  if (rdp_lexicalise)
    scan_lexicalise();
  mini = symbol_new_table("mini", 101, 31, symbol_compare_string, symbol_hash_string, symbol_print_string);
  rdp_set_initialise();
  rdp_load_keywords();
  if (rdp_verbose)
     text_printf("\nMinitree compiler V1.50 (c) Adrian Johnstone 1997\n" RDP_STAMP "\n\n");
  for (rdp_pass = 1; rdp_pass <= RDP_PASSES; rdp_pass++)
  {
    rdp_tree_update = rdp_pass == RDP_PASSES;
    text_echo(rdp_line_echo_all || (rdp_line_echo && rdp_pass == RDP_PASSES));

    for (rdp_sourcefilenumber = 0; (rdp_sourcefilename = rdp_sourcefilenames[rdp_sourcefilenumber]) != NULL; rdp_sourcefilenumber++)
    {
      if (text_open(rdp_sourcefilename) == NULL)
        arg_help("unable to open source file");

      text_get_char();
      scan_();

      program(rdp_tree_root = rdp_add_node("program", rdp_tree));            /* call parser at top level */
      if (text_total_errors() != 0)
        text_message(TEXT_FATAL, "error%s detected in source file ''\n", text_total_errors() == 1 ? "" : "s", rdp_sourcefilename);   /* crash quietly */ 
      graph_epsilon_prune_rdp_tree(rdp_tree_root, sizeof(rdp_tree_edge_data));
    }
  }

  rdp_sourcefilename = rdp_sourcefilenames[0];     /* Reset filename to first file in the list */

  graph_set_root(rdp_tree, rdp_tree_root);
  if (rdp_vcg_filename != NULL)
  {
    FILE *rdp_vcg_file;

    if (*rdp_vcg_filename == '\0')   /* No filename supplied */
      rdp_vcg_filename = "rdparser";
    rdp_vcg_file = fopen((rdp_vcg_filename = text_default_filetype(rdp_vcg_filename, "vcg")), "w");

    if (rdp_vcg_file == NULL)
      text_message(TEXT_FATAL, "unable to open VCG file '%s' for write\n", rdp_vcg_filename);

    if (rdp_verbose)
      text_message(TEXT_INFO, "Dumping derivation tree to VCG file '%s'\n", rdp_vcg_filename);

    text_redirect(rdp_vcg_file);
    graph_vcg(rdp_tree, NULL, scan_vcg_print_node, scan_vcg_print_edge);
    text_redirect(stdout);
    fclose(rdp_vcg_file);
  }

   code_generate(rdp_sourcefilename, rdp_outputfilename, rdp_tree); 
  if (rdp_symbol_statistics)
  {
    symbol_print_all_table_statistics(11);
    symbol_print_all_table();

  }
  text_print_total_errors();
  if (rdp_verbose)
  {
    rdp_finish_time = clock();
    text_message(TEXT_INFO, "%.3f CPU seconds used\n", ((double) (rdp_finish_time-rdp_start_time)) / CLOCKS_PER_SEC);
  }
  return rdp_error_return;
}
Example #2
0
static void parse_switch_spec(assembly_operand switch_value, int label,
                              int action_switch)
{
    int i, j, label_after = -1, spec_sp = 0;
    int max_equality_args = ((!glulx_mode) ? 3 : 1);

    sequence_point_follows = FALSE;

    do
    {   if (spec_sp == 32)
        {   error("At most 32 values can be given in a single 'switch' case");
            panic_mode_error_recovery();
            return;
        }

        if (action_switch)
        {   get_next_token();
            if (token_type == SQ_TT || token_type == DQ_TT) {
                ebf_error("action (or fake action) name", token_text);
                continue;
            }
            spec_stack[spec_sp] = action_of_name(token_text);

            if (spec_stack[spec_sp].value == -1)
            {   spec_stack[spec_sp].value = 0;
                ebf_error("action (or fake action) name", token_text);
            }
        }
        else
            spec_stack[spec_sp] =
                code_generate(parse_expression(CONSTANT_CONTEXT), CONSTANT_CONTEXT, -1);

        misc_keywords.enabled = TRUE;
        get_next_token();
        misc_keywords.enabled = FALSE;

        spec_type[spec_sp++] = switch_sign();
        switch(spec_type[spec_sp-1])
        {
        case 0:
            if (action_switch)
                ebf_error("',' or ':'", token_text);
            else ebf_error("',', ':' or 'to'", token_text);
            panic_mode_error_recovery();
            return;
        case 1:
            goto GenSpecCode;
        case 3:
            if (label_after == -1) label_after = next_label++;
        }
    } while(TRUE);

GenSpecCode:

    if ((spec_sp > max_equality_args) && (label_after == -1))
        label_after = next_label++;

    if (label_after == -1)
    {   compile_alternatives(switch_value, spec_sp, 0, label, FALSE);
        return;
    }

    for (i=0; i<spec_sp;)
    {
        j=i;
        while ((j<spec_sp) && (spec_type[j] != 3)) j++;

        if (j > i)
        {   if (j-i > max_equality_args) j=i+max_equality_args;

            if (j == spec_sp)
                compile_alternatives(switch_value, j-i, i, label, FALSE);
            else
                compile_alternatives(switch_value, j-i, i, label_after, TRUE);

            i=j;
        }
        else
        {
            if (!glulx_mode) {
                if (i == spec_sp - 2)
                {   assemblez_2_branch(jl_zc, switch_value, spec_stack[i],
                                       label, TRUE);
                    assemblez_2_branch(jg_zc, switch_value, spec_stack[i+1],
                                       label, TRUE);
                }
                else
                {   assemblez_2_branch(jl_zc, switch_value, spec_stack[i],
                                       next_label, TRUE);
                    assemblez_2_branch(jg_zc, switch_value, spec_stack[i+1],
                                       label_after, FALSE);
                    assemble_label_no(next_label++);
                }
            }
            else {
                if (i == spec_sp - 2)
                {   assembleg_2_branch(jlt_gc, switch_value, spec_stack[i],
                                       label);
                    assembleg_2_branch(jgt_gc, switch_value, spec_stack[i+1],
                                       label);
                }
                else
                {   assembleg_2_branch(jlt_gc, switch_value, spec_stack[i],
                                       next_label);
                    assembleg_2_branch(jle_gc, switch_value, spec_stack[i+1],
                                       label_after);
                    assemble_label_no(next_label++);
                }
            }
            i = i+2;
        }
    }

    assemble_label_no(label_after);
}
Example #3
0
void parse_program(char *filename)
{
	printf("parsing file: %s\n", filename);

	yyfiles = list_new(NULL, &free);
	log_assert(yyfiles);
	list_push_back(yyfiles, filename);
	yyclibs = list_new(NULL, &free);
	log_assert(yyclibs);

	yyincludes = hasht_new(8, true, NULL, NULL, NULL);
	log_assert(yyincludes);


	/* open file for lexer */
	yyin = fopen(filename, "r");
	if (yyin == NULL)
		log_error("could not open input file: %s", filename);

	/* push buffer state for lexer */
	yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));

	/* setup yytypes table for lexer */
	yytypes = hasht_new(8, true, NULL, NULL, &free_typename);
	log_assert(yytypes);

	/* reset library flags */
	libs.usingstd	= false;
	libs.cstdlib	= false;
	libs.cmath	= false;
	libs.ctime	= false;
	libs.cstring	= false;
	libs.fstream	= false;
	libs.iostream	= false;
	libs.string	= false;
	libs.iomanip	= false;

	log_debug("invoking Bison");
	int result = yyparse();
	if (result != 0)
		exit(2);

	/* print syntax tree */
	if (arguments.tree)
		tree_traverse(yyprogram, 0, &print_tree, NULL, NULL);

	/* initialize scope stack */
	log_debug("setting up for semantic analysis");
	yyscopes = list_new(NULL, NULL);
	log_assert(yyscopes);

	struct hasht *global = hasht_new(32, true, NULL, NULL, &symbol_free);
	log_assert(global);
	list_push_back(yyscopes, global);

	/* build the symbol tables */
	log_debug("populating symbol tables");
	region = GLOBE_R;
	offset = 0;
	symbol_populate(yyprogram);
	log_debug("global scope had %zu symbols", hasht_used(global));

	/* constant symbol table put in front of stack for known location */
	struct hasht *constant = hasht_new(32, true, NULL, NULL, &symbol_free);
	log_assert(constant);
	list_push_front(yyscopes, constant);

	region = CONST_R;
	offset = 0;
	log_debug("type checking");
	type_check(yyprogram);

	/* generating intermediate code */
	log_debug("generating intermediate code");
	yylabels = 0; /* reset label counter */
	code_generate(yyprogram);
	struct list *code = ((struct node *)yyprogram->data)->code;

	/* iterate to get correct size of constant region */
	size_t string_size = 0;
	for (size_t i = 0; i < constant->size; ++i) {
		struct hasht_node *slot = constant->table[i];
		if (slot && !hasht_node_deleted(slot)) {
			struct typeinfo *v = slot->value;
			if (v->base == FLOAT_T)
				string_size += 8;
			else if (v->base == CHAR_T && v->pointer)
				string_size += v->token->ssize;
		}
	}

	/* print intermediate code file if debugging */
	if (arguments.debug) {
		char *output_file;
		asprintf(&output_file, "%s.ic", filename);
		FILE *ic = fopen(output_file, "w");
		if (ic == NULL)
			log_error("could not save to output file: %s",
			          output_file);

		fprintf(ic, ".file \"%s\"\n", filename);

		/* print .string region */
		fprintf(ic, ".string %zu\n", string_size);
		/* iterate to print everything but ints, chars, and bools */
		for (size_t i = 0; i < constant->size; ++i) {
			struct hasht_node *slot = constant->table[i];
			if (slot && !hasht_node_deleted(slot)) {
				struct typeinfo *v = slot->value;
				if (v->base == FLOAT_T
				    || (v->base == CHAR_T && v->pointer)) {
					fprintf(ic, "    ");
					print_typeinfo(ic, slot->key, v);
					fprintf(ic, "\n");
				}
			}
		}

		/* print .data region */
		fprintf(ic, ".data\n");
		for (size_t i = 0; i < global->size; ++i) {
			struct hasht_node *slot = global->table[i];
			if (slot && !hasht_node_deleted(slot)) {
				struct typeinfo *value = slot->value;
				if (value->base != FUNCTION_T) {
					fprintf(ic, "    ");
					print_typeinfo(ic, slot->key, value);
					fprintf(ic, "\n");
				}
			}
		}
		fprintf(ic, ".code\n");
		print_code(ic, code);
		fclose(ic);
		free(output_file);
	}

	log_debug("generating final code");
	/* copy because Wormulon */
	char *copy = strdup(filename);
	char *base = basename(copy);
	free(copy);
	char *output_file;
	asprintf(&output_file, "%s.c", base);
	FILE *fc = fopen(output_file, "w");
	if (fc == NULL)
		log_error("could not save to output file: %s", output_file);

	time_t t = time(NULL);
	struct tm *local = localtime(&t);
	char timestamp[60];
	strftime(timestamp, sizeof(timestamp), "%F %T", local);
	fprintf(fc, "/*\n");
	fprintf(fc, " * %s - 120++ Three-Address C Code\n", output_file);
	fprintf(fc, " * Generated @ %s\n", timestamp);
	fprintf(fc, " *\n");
	fprintf(fc, " * Created by Andrew Schwartzmeyer's 120++ Compiler\n");
	fprintf(fc, " * Project located @ https://github.com/andschwa/uidaho-cs445\n");
	fprintf(fc, " */\n\n");

	fprintf(fc, "/* Required includes for TAC-C */\n");
	fprintf(fc, "#include <stdlib.h>\n");
	fprintf(fc, "#include <stdbool.h>\n");
	fprintf(fc, "#include <string.h>\n");
	if (libs.usingstd && libs.iostream)
		fprintf(fc, "#include <stdio.h>\n");
	fprintf(fc, "\n");

	/* include passed-through C headers */
	fprintf(fc, "/* Source-file C headers */\n");
	struct list_node *iter = list_head(yyclibs);
	while (!list_end(iter)) {
		fprintf(fc, "#include %s\n", (char *)iter->data);
		iter = iter->next;
	}
	fprintf(fc, "\n");

	/* get maximum param size for faux stack */
	size_t max_param_size = 0;
	iter = list_head(code);
	while (!list_end(iter)) {
		struct op *op = iter->data;
		if (op->code == PROC_O) {
			size_t param_size = op->address[0].offset;
			if (param_size > max_param_size)
				max_param_size = param_size;
		}
		iter = iter->next;
	}

	fprintf(fc, "/* Memory regions */\n");
	fprintf(fc, "char constant[%zu];\n", string_size);
	fprintf(fc, "char global[%zu];\n", global->size);
	fprintf(fc, "char stack[%zu];\n", max_param_size);
	fprintf(fc, "\n");

	fprintf(fc, "/* Final Three-Address C Generated Code */\n");
	final_code(fc, code);
	fclose(fc);

	/* remove TAC-C "assembler" code */
	if (!arguments.assemble) {
		/* compile object files */
		char *command;
		asprintf(&command, "gcc -c %s", output_file);
		int status = system(command);
		if (status != 0)
			log_error("command failed: %s", command);

		remove(output_file);
	}

	free(output_file);

	/* clean up */
	log_debug("cleaning up");
	tree_free(yyprogram);
	yylex_destroy();
	hasht_free(yytypes);
	free(yyincludes); /* values all referenced elsewhere */
	list_free(yyfiles);
	list_free(yyclibs);
	list_free(yyscopes);
}