/* * 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); } }
/** * 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); } }