void process_pragma(tree *expr) { tree *lhs; tree *rhs; switch (expr->tag) { case node_binop: lhs = expr->value.binop.p0; rhs = expr->value.binop.p1; if ((expr->value.binop.op != '=') || (lhs->tag != node_symbol)) { gp_error("unknown pragma"); } else { if (strcasecmp(lhs->value.symbol, "processor") == 0) { if (rhs->tag != node_symbol) { gp_error("invalid processor name"); } else { if (state.processor_chosen == false) { select_processor(rhs->value.symbol); } } } else { gp_error("unknown pragma \"%s\"", lhs->value.symbol); } } break; default: gp_error("unknown pragma"); } return; }
void yyerror(char *message) { gp_error("%s:%d:%s", state.src->name, state.src->line_number, message); }
void strip_all(void) { gp_section_type *section = state.object->sections; if (state.object->flags & F_EXEC) { while (section != NULL) { /* remove the line numbers, have too because the symbols will be removed */ section->num_lineno = 0; section->line_numbers = NULL; section->line_numbers_tail = NULL; /* remove the relocations, they should already be removed */ section->num_reloc = 0; section->relocations = NULL; section->relocations_tail = NULL; section = section->next; } /* remove all symbols */ state.object->num_symbols = 0; state.object->symbols = NULL; state.object->symbols_tail = NULL; } else { gp_error("can not strip all symbols because the object file is not executable"); } }
void select_processor(char *name) { struct px *found = NULL; if (state.cmd_processor) { gp_warning("processor superseded by command line"); } else { found = gp_find_processor(name); if (found) { if (state.processor == no_processor) { state.processor = found->tag; state.processor_info = found; /* FIXME: should the processor name be defined as a symbol? */ } else if (state.processor != found->tag ) { gp_warning("redefining processor"); } } else { gp_error("unknown processor \"%s\"", name); } /* load the instruction sets if necessary */ if ((state.processor_chosen == false) && (state.processor != no_processor)) { /* FIXME select the correct code generator */ state.processor_chosen = true; } } }
void select_mode(enum lib_modes mode) { if (state.mode == ar_null) { state.mode = mode; } else { gp_error("multiple library operations selected"); } }
void codegen_init_asm() { char buffer[BUFSIZ]; /* open output filename */ strncpy(state.asmfilename, state.basefilename, sizeof(state.asmfilename)); strncat(state.asmfilename, ".asm", sizeof(state.asmfilename)); state.output.f = fopen(state.asmfilename, "w"); if (state.output.f == NULL) { perror(state.asmfilename); exit(1); } label_number = 0; max_temp_number = 0; codegen_working_bytes = 1; codegen_size = size_uint8; codegen_bytes = prim_size(codegen_size); gp_date_string(buffer, sizeof(buffer)); fprintf(state.output.f, "; %s\n", state.asmfilename); fprintf(state.output.f, "; generated by %s on %s\n\n", GPAL_VERSION_STRING, buffer); fprintf(state.output.f, "#file \"%s\"\n\n", state.srcfilename); if (state.processor_chosen) { fprintf(state.output.f, " processor %s\n", state.processor_info->names[1]); fprintf(state.output.f, " include \"%s.inc\"\n\n", state.processor_info->names[1]); } else { gp_error("processor not selected"); } if (state.section.code) { if (state.section.code_addr_valid) { fprintf(state.output.f, "%s code %#x\n", state.section.code, state.section.code_addr); } else { fprintf(state.output.f, "%s code\n", state.section.code); } } else { if (state.section.code_addr_valid) { fprintf(state.output.f, ".code_%s code %#x\n", FILE_NAME(state.module), state.section.code_addr); } else { fprintf(state.output.f, ".code_%s code\n", FILE_NAME(state.module)); } } return; }
void read_block(unsigned char *block, int block_number) { int n; fseek(codefile, block_number * COD_BLOCK_SIZE, SEEK_SET); n = fread(block, 1, COD_BLOCK_SIZE, codefile); if (COD_BLOCK_SIZE != n) { gp_error("bad block number %d", block_number); } }
static void write_expression(tree *statement) { tree *lhs; tree *rhs; struct variable *var; char *lhs_name; fprintf(state.output.f, ";#CSRC %s %d\n", state.srcfilename, statement->line_number); if ((statement->tag != node_binop) || (statement->value.binop.op != '=')) { gp_error("invalid expression"); return; } lhs = statement->value.binop.p0; rhs = statement->value.binop.p1; if (lhs->tag != node_symbol) { gp_error("invalid lvalue in assignment"); return; } var = get_global(lhs->value.symbol); lhs_name = var->alias; temp_number = 0; gen_expr(rhs); if (var) gen_put_mem(lhs_name); if (temp_number > max_temp_number) max_temp_number = temp_number; }
struct variable * get_global(char *name) { struct symbol *sym; struct variable *var = NULL; sym = get_symbol(state.stGlobal, name); if (sym == NULL) { gp_error("undefined symbol \"%s\"", name); } else { var = get_symbol_annotation(sym); } return var; }
static void write_declarations(void) { entity *entity_list = NULL; tree *current = NULL; int first_time = 1; tree *list; tree *symbol; entity_list = state.list; while (entity_list != NULL) { current = entity_list->node; if ((current->tag == node_decl) && (current->value.decl.storage != EXTERN_STORAGE)) { if ((current->value.decl.type == CONST_TYPE) && (current->value.decl.storage != 0)) { gp_error("constants can't be public or volatile"); } /* FIXME: only bytes are supported so far */ assert(current->value.decl.size == BYTE_SIZE); if (first_time) { fprintf(state.output.f, "; declarations \n"); fprintf(state.output.f, " udata\n"); first_time = 0; } for (list = current->value.decl.expr; list; list = TAIL(list)) { symbol = HEAD(list); assert(symbol->tag == node_symbol); if (current->value.decl.type == VAR_TYPE) { fprintf(state.output.f, "%s res 1\n", symbol->value.symbol); if (current->value.decl.storage == PUBLIC_STORAGE) fprintf(state.output.f, " global %s\n", symbol->value.symbol); } add_global(symbol->value.symbol, symbol->value.symbol, current); } } entity_list = entity_list->next; } if (!first_time) fprintf(state.output.f, "\n"); }
void add_global(char *name, char *alias, tree *object) { struct symbol *sym; struct variable *var; sym = get_symbol(state.stGlobal, name); if (sym == NULL) { sym = add_symbol(state.stGlobal, name); var = malloc(sizeof(*var)); annotate_symbol(sym, var); var->node = object; var->alias = strdup(alias); var->is_public = false; var->is_external = false; } else { gp_error("duplicate symbol \"%s\"", name); } return; }
static void assemble(char *file_name, gp_boolean asm_source) { char command[BUFSIZ]; if ((gp_num_errors) || (state.compile_only == true)) return; if (state.processor_chosen == false) { gp_error("processor not selected"); exit(1); } strcpy(command, "gpasm -c "); if (gp_quiet) { strcat(command, "-q "); } strcat(command, file_name); strcat(command, ".asm "); if (!gp_quiet) { printf("%s\n", command); } if (system(command)) { gp_num_errors++; } else if (state.delete_temps == true) { if (asm_source == false) { sprintf(command, "%s.asm", file_name); unlink(command); } sprintf(command, "%s.lst", file_name); unlink(command); } return; }
int main(int argc, char *argv[]) { extern int optind; int i = 0; int c; gp_boolean usage = false; gp_boolean update_archive = false; gp_boolean no_index = false; gp_archive_type *object = NULL; gp_init(); /* symbols are case sensitive */ definition_tbl = push_symbol_table(NULL, false); symbol_index = push_symbol_table(NULL, false); while ((c = GETOPT_FUNC) != EOF) { switch (c) { case '?': case 'h': usage = true; break; case 'c': select_mode(ar_create); break; case 'd': select_mode(ar_delete); break; case 'n': no_index = true; break; case 'q': gp_quiet = true; break; case 'r': select_mode(ar_replace); break; case 's': select_mode(ar_symbols); break; case 't': select_mode(ar_list); break; case 'v': fprintf(stderr, "%s\n", GPLIB_VERSION_STRING); exit(0); break; case 'x': select_mode(ar_extract); break; } if (usage) break; } if (optind < argc) { /* fetch the library name */ state.filename = argv[optind++]; /* some operations require object filenames or membernames */ for ( ; optind < argc; optind++) { state.objectname[state.numobjects] = argv[optind]; if (state.numobjects >= MAX_OBJ_NAMES) { gp_error("exceeded maximum number of object files"); break; } state.numobjects++; } } else { usage = true; } /* User did not select an operation */ if (state.mode == ar_null) { usage = true; } /* User did not provide object names */ if ((state.mode != ar_list) && (state.mode != ar_symbols) && (state.numobjects == 0)) { usage = true; } if (usage) { show_usage(); } /* if we are not creating a new archive, we have to read an existing one */ if (state.mode != ar_create) { if (gp_identify_coff_file(state.filename) != archive_file) { gp_error("\"%s\" is not a valid archive file", state.filename); exit(1); } else { state.archive = gp_archive_read(state.filename); } } /* process the option */ i = 0; switch (state.mode) { case ar_create: case ar_replace: while (i < state.numobjects) { if (gp_identify_coff_file(state.objectname[i]) != object_file) { gp_error("\"%s\" is not a valid object file", state.objectname[i]); break; } else { state.archive = gp_archive_add_member(state.archive, state.objectname[i], object_name(state.objectname[i])); } i++; } update_archive = true; break; case ar_delete: while (i < state.numobjects) { if (has_path(state.objectname[i])) { gp_error("invalid object name \"%s\"", state.objectname[i]); break; } object = gp_archive_find_member(state.archive, state.objectname[i]); if (object == NULL) { gp_error("object \"%s\" not found", state.objectname[i]); break; } else { state.archive = gp_archive_delete_member(state.archive, state.objectname[i]); } i++; } update_archive = true; break; case ar_extract: while (i < state.numobjects) { if (has_path(state.objectname[i])) { gp_error("invalid object name \"%s\"", state.objectname[i]); break; } object = gp_archive_find_member(state.archive, state.objectname[i]); if (object == NULL) { gp_error("object \"%s\" not found", state.objectname[i]); break; } else { if (gp_archive_extract_member(state.archive, state.objectname[i])) { gp_error("can't write file \"%s\"", state.objectname[i]); break; } } i++; } break; case ar_list: gp_archive_list_members(state.archive); break; case ar_symbols: if (gp_archive_have_index(state.archive) == 0) { gp_error("this archive has no symbol index"); } else { gp_archive_read_index(symbol_index, state.archive); gp_archive_print_table(symbol_index); } break; case ar_null: default: assert(0); } /* If the archive is being modified remove the old symbol index */ if (update_archive) { state.archive = gp_archive_remove_index(state.archive); } /* check for duplicate symbols */ gp_archive_make_index(state.archive, definition_tbl); /* add the symbol index to the archive */ if (update_archive && (!no_index)) { state.archive = gp_archive_add_index(definition_tbl, state.archive); } /* write the new or modified archive */ if (update_archive && (gp_num_errors == 0)) { if (gp_archive_write(state.archive, state.filename)) gp_error("can't write the new archive file"); } if (gp_num_errors > 0) return EXIT_FAILURE; else return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { extern int optind; int c; int usage = 0; gp_init(); /* initalize */ verbose = false; state.strip_debug = false; state.preserve_dates = false; state.strip_all = false; state.strip_unneeded = false; state.discard_all = false; state.output_file = NULL; state.symbol_keep = push_symbol_table(NULL, false); state.symbol_remove = push_symbol_table(NULL, false); state.section_remove = push_symbol_table(NULL, false); while ((c = GETOPT_FUNC) != EOF) { switch (c) { case '?': case 'h': usage = 1; break; case 'g': state.strip_debug = true; break; case 'k': add_name(state.symbol_keep, optarg); break; case 'n': add_name(state.symbol_remove, optarg); break; case 'o': state.output_file = optarg; break; case 'p': state.preserve_dates = true; break; case 'r': add_name(state.section_remove, optarg); break; case 's': state.strip_all = true; break; case 'u': state.strip_unneeded = true; break; case 'x': state.discard_all = true; break; case 'V': verbose = true; break; case 'v': fprintf(stderr, "%s\n", GPSTRIP_VERSION_STRING); exit(0); } if (usage) break; } if ((optind == argc) || (usage)) { show_usage(); } for ( ; optind < argc; optind++) { state.input_file = argv[optind]; if (gp_identify_coff_file(state.input_file) != object_file_v2 && gp_identify_coff_file(state.input_file) != object_file) { gp_error("\"%s\" is not a valid object file", state.input_file); exit(1); } state.object = gp_read_coff(state.input_file); if (state.object) { remove_sections(); remove_symbols(); if (state.strip_all) { strip_all(); } if (state.strip_debug) { if (state.strip_all) { gp_message("strip debug ignored"); } else { strip_debug(); } } if (state.strip_unneeded) { if (state.strip_all) { gp_message("strip unneeded ignored"); } else { strip_unneeded(); } } if (state.discard_all) { if (state.strip_all) { gp_message("discard all ignored"); } else { discard_all(); } } if (state.output_file) { state.object->filename = state.output_file; } if (!state.preserve_dates) { /* FIXME: need to update the output file dates */ state.object->time = (long)time(NULL); } if (gp_num_errors == 0) { /* no errors have occured so write the file */ if (gp_write_coff(state.object, 0)) gp_error("system error while writing object file"); } else if (state.output_file) { /* a new file is being written, but errors have occurred, delete the file if it exists */ unlink(state.output_file); } /* FIXME: free state.output_file */ } } if (gp_num_errors) return EXIT_FAILURE; else return EXIT_SUCCESS; }
void process_args( int argc, char *argv[]) { extern char *optarg; extern int optind; int c; int usage = 0; while ((c = getopt_long(argc, argv, GET_OPTIONS, longopts, 0)) != EOF) { switch (c) { case '?': case 'h': usage = 1; break; case 'a': state.archive = true; break; case 'c': state.no_link = true; break; case 'd': gp_debug_disable = 0; break; case 'I': add_path(optarg); break; case 'k': state.options = optarg; break; case 'l': gp_dump_processor_list(); exit(0); break; case 'o': state.outfilename = strdup(optarg); break; case 'p': select_processor(optarg); state.cmd_processor = true; break; case 'q': gp_quiet = 1; break; case 'S': state.compile_only = true; break; case 't': state.delete_temps = false; break; case 'v': fprintf(stderr, "%s\n", GPAL_VERSION_STRING); exit(0); } if (usage) break; } if (optind < argc) { for ( ; optind < argc; optind++) { state.file_name[state.num_files] = argv[optind]; if (state.num_files >= MAX_FILE_NAMES) { gp_error("exceeded maximum number of source files"); break; } state.num_files++; } } else { usage = 1; } if (usage) { show_usage(); } }