/*
 * Description: Process the extern definition in first transition.
 * 				Adds it into the symbol table
 * Input:		1. Current transition
 */
void first_transition_process_extern(transition_data* transition) {
	symbol_node_ptr p_symbol = NULL;

	char* extern_name = get_next_word(transition);

	/* If we have an extern*/
	if (extern_name) {
		symbol_node_ptr p_searched_symbol = search_symbol(extern_name);

		/* Extern does not exists in symbol table */
		if (!p_searched_symbol) {
			/* Create new symbol in table or die */
			p_symbol = create_symbol(extern_name, NO_ADDRESS, true, true);
			if (p_symbol) {
				add_symbol_to_list(p_symbol);

				/* Make sure that the line does not contain left overs */
				if (!is_end_of_data_in_line(transition->current_line_information)) {
					print_compiler_error("Invalid tokens after extern definition", transition->current_line_information);
					transition->is_compiler_error = true;
					return;
				}
			}
			/* Could not allocat memory, die*/
			else {
				transition->is_runtimer_error = true;
				free(extern_name);
				return;
			}
		}
		/* Extern is already in table */
		else {
			print_compiler_error("Each extern can be defined only once", transition->current_line_information);
			transition->is_compiler_error = true;
			return;
		}
	}
}
/*
 * Description: Processes a line in input file
 * Input:		1. Current transition data
 * 				2. Output files
 */
void second_transition_process_line(transition_data* transition, compiler_output_files* output_files) {
    char* type = NULL;
    int index;

    /* Step 3 - Skips label if exists */
    skip_label(transition->current_line_information);

    index = transition->current_line_information->current_index;

    /* Read line type */
    type = get_next_word(transition);

    /* Step 4 - Handle line type */
    if (type == NULL) {
        print_compiler_error("Invalid line", transition->current_line_information);
        transition->is_compiler_error = true;
    }
    /* Line is data initialization - Ignores it */
    else if ((strcmp(type, DATA_OPERATION) == 0) || (strcmp(type, STRING_OPERATION) == 0)) {
        /* Ignore */
    }
    /* Step 5 - Line is extern */
    else if (strcmp(type, EXTERN_OPERATION) == 0) {
        create_extern_output_file_if_needed(output_files, transition->current_line_information->file_name);

        if (output_files->extern_file == NULL) {
            transition->is_runtimer_error  = true;
        }
    } else if (strcmp(type, ENTRY_OPERATION) == 0) {
        /* Process entry */
        second_transition_process_entry(transition, output_files);
    } else  {
        /* Process operation */
        transition->current_line_information->current_index = index;
        second_transition_process_operation(transition, output_files);
    }

    if (type != NULL) {
        free(type);
    }
}
Beispiel #3
0
/**
* Will attempt to parse the rest of the input line according to the
* restrictions given by the format string. The format string is used to
* specify, in the given order, how to parse the next token. The following
* format is accepted (strictly):
*
* 	s -> Source register
* 	d -> Destination register
* 	l -> Label
* 	c -> Constant
* 	n -> Literal number
* 	t -> Place an empty term after this term
* 	[ -> Start 'or' expression (non-recursive)
* 	] -> End 'or' expression
*
* Note that the or expression works as expected, so "[lcn]" translates to
* "take whichever successfully parses first, either a label, constant, or
* a number".
*
* If the or condition fails, or any parsing fails, an error is printed
* and all processing stops (the function does however return instead of
* calling exit()).
*
* @param prog 		Contains general program information thus far gathered,
* 					and is used for handling error reporting.
* @param opcode 	The binary operation that this line started with.
* @param fmt 		The format string for what arguments to expect.
* @param misc 		Any bits that need to be added as the last child to the
* 					opcode term.
*/
void process_instruction(struct program *prog, char *opcode, const char *fmt,
		char *misc){

	// create a term for this instruction
	struct Term *t = create_term(opcode, strlen(opcode), 0);
	if(!t){
		#ifdef DEBUG
			fprintf(stderr, "whoops! Looks like a nul-pointer...\n");
		#endif
		prog->error_code = -1;
		return;
	}
	t->trans = 1;
	struct Term *child;
	prog->term_count++;
	t->pos = prog->term_count;

	#ifdef DEBUG
		fprintf(stderr, "OPCODE: '%s'\n", opcode);
	#endif

	// add term to our program
	if(prog->terms){
		prog->end_term->next_term = t;
		prog->end_term = t;
	}
	else{
		prog->terms = t;
		prog->end_term = t;
	}

	if(!*opcode)
		return;


	#ifdef DEBUG
	fprintf(stderr, "FMT CODE: '%s'.\n", fmt);
	#endif

	// opcode argument parsing
	short reg = -1;
	char *iden = 0;
	char *tok = 0;
	int c = 0, or = 0, val = -1;
	while(fmt[c]){
		if(fmt[c] == 't'){
			prog->end_term->next_term = create_term(0, 0, 0);
			prog->end_term = prog->end_term->next_term;
			prog->term_count++;
			prog->end_term->pos = prog->term_count;
			prog->end_term->absolute_pos = prog->line_count;
		}
		else if(or && ( (reg != -1) | (iden ? 1 : 0) | (val != -1) ) 
				&&fmt[c] != ']'){
			// do nothing...
		}
		else if(fmt[c] == '['){
			or = 1;
		}
		else if(fmt[c] == ']'){
			or = 0;

			// if all options failed, report parse error
			if(!reg && !iden && !val){
				// TODO: create standardized error reporting....
				print_compiler_error(prog, RED_C);
				print_asterisk(RED_C, stderr);
				fprintf(stderr, "\tUnexpected opcode argument.\n");
				prog->error_code = GARBAGE;
				return;
			}

			// reset everything
			reg = -1;
			iden = 0;
			tok = 0;
		}
		else if(fmt[c] == 's'){
			reg = read_src_reg(prog, or);
			if(!or && reg == -1){
				return;
			}
		}
		else if(fmt[c] == 'd'){
			reg = read_dst_reg(prog, or);
			if(!or && reg == -1){
				return;
			}
		}
		else if(fmt[c] == 'l'){
			if(!tok && or){
				tok = strtok(0, ", \t");
				iden = tok;
			}
			else if(!or){
				iden = strtok(0, ", \t");
			}
			else{
				iden = tok;
			}
			
			// create the term and add to the end
			struct Term *nt = create_term(iden, strlen(iden), 0);
			prog->term_count++;
			nt->pos = prog->term_count;
			prog->end_term->next_term = nt;
			prog->end_term = nt;
			nt->absolute_pos = prog->line_count;
			#ifdef DEBUG
			fprintf(stderr, "GOTS A LABEL!\n");
			#endif
		}
		else if(fmt[c] == 'n'){
			if(!tok && or){
				tok = strtok(0, ", \t");
				iden = tok;
			}
			else if(!or){
				iden = strtok(0, ", \t");
			}
			else{
				iden = tok;
			}
			if(!check_explicit_literal(iden, prog)){
				if(!or){
					print_expected_literal(iden, prog);
					return;
				}
				iden = 0;
			}
			else{
				val = process_literal(iden, MAX_INT);
				iden = 0;
				if(val < 0){
					print_literal_too_large(iden, prog);
					return;
				}
				else{

					#ifdef DEBUG
						fprintf(stderr, "GOTS A LITERAL!\n");
					#endif

					// create the term and add to the end
					struct Term *nt = create_term(numtob(val, WORD_SIZE), 
							strlen(iden), 0);
					nt->trans = 1;
					prog->term_count++;
					nt->pos = prog->term_count;
					prog->end_term->next_term = nt;
					prog->end_term = nt;
					nt->absolute_pos = prog->line_count;
				}
			}
		}
		else if(fmt[c] == 'c'){
			if(!tok && or){
				tok = strtok(0, ", \t");
				iden = tok;
			}
			else if(!or){
				iden = strtok(0, ", \t");
			}
			else{
				iden = tok;
			}

			if(!check_const(iden, prog)){
				if(!or){
					print_expected_const(iden, prog);
					return;
				}
				iden = 0;
			}
			else{

				#ifdef DEBUG
					fprintf(stderr, "GOTS A CONSTANT!\n");
				#endif

				// create the term and add to the end
				struct Term *nt = create_term(iden, strlen(iden), 0);
				prog->term_count++;
				nt->pos = prog->term_count;
				prog->end_term->next_term = nt;
				prog->end_term = nt;
				nt->absolute_pos = prog->line_count;
			}
		}
		else{
			fprintf(stderr, " * Error In Compiler!!!\n\tStrange format code: "
					"'%c'.\n", fmt[c]);
		}

		if(reg != -1){
			child = create_single_char_term(dtoc(reg-1), 0);
			child->absolute_pos = prog->line_count;
			child->trans = 1;
			add_child_term(child, t, prog);
			if(!or)
				reg = -1;
		}
		c++;
	}

	// Finally, add miscellaneous bits to the end
	if(misc){
		struct Term *mt = create_term(misc, strlen(misc), 0);
		mt->trans = 1;
		mt->absolute_pos = prog->line_count;
		add_child_term(mt, t, prog);
	}
}