📄 gbc_output.c
字号:
/*************************************************************************** output.c The object file creator (c) 2000-2004 Beno� Minisini <gambas@users.sourceforge.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __GBC_OUTPUT_C#include "gb_common.h"#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <ctype.h>#include "gb_error.h"#include "gb_alloc.h"#include "gb_str.h"#include "gb_file.h"#include "gbc_compile.h"#include "gb_magic.h"#include "gbc_output.h"/*#define DEBUG*//*#define DEBUG_MORE*/PRIVATE FILE *File;PRIVATE CLASS *Class;PRIVATE long StringAddr;PRIVATE TABLE *StringTable;PRIVATE int NSection;PRIVATE long PosStartSection;PRIVATE int SizeSection;PRIVATE bool _swap;/*#define START_SECTION() long pos = write_long(0);#define END_SECTION() write_pad(); write_long_at(pos, get_pos() - pos - sizeof(long));*/PRIVATE void output_init(void){ TABLE_create(&StringTable, sizeof(OUTPUT_SYMBOL), TF_NORMAL); StringAddr = 0; NSection = 0;}PRIVATE void output_exit(void){ TABLE_delete(&StringTable);}PRIVATE long get_string(const char *string, int len){ OUTPUT_SYMBOL *sym; if (len < 0) len = strlen(string); if (!TABLE_add_symbol(StringTable, string, len, (SYMBOL **)&sym, NULL)) { sym->value = StringAddr; StringAddr += len + 1; } #ifdef DEBUG printf("'%.*s' -> %ld\n", len, string, sym->value); #endif return sym->value;}PRIVATE long get_pos(void){ return ftell(File);}PRIVATE void write_byte(unsigned char val){ #ifdef DEBUG_MORE printf("%ld : b %u 0x%X\n", get_pos(), val, val); #endif /* MSB & LSB */ if (fwrite(&val, sizeof(char), 1, File) != 1) THROW("Write error");}PRIVATE void write_short(unsigned short val){ #ifdef DEBUG_MORE printf("%ld : i %u 0x%X\n", get_pos(), val, val); #endif if (_swap) val = (val >> 8) | (val << 8); /* MSB & LSB */ if (fwrite(&val, sizeof(val), 1, File) != 1) THROW("Write error");}static void write_type(TYPE type){ write_byte(type.t.flag); write_byte(type.t.id); write_short(type.t.value);}PRIVATE long write_long(unsigned long val){ long pos = get_pos(); #ifdef DEBUG_MORE printf("%ld : l %lu 0x%lX\n", get_pos(), val, val); #endif if (_swap) val = (val >> 24) | ((val >> 8) & 0xFF00) | ((val << 8) & 0xFF0000) | (val << 24); /* MSB & LSB */ if (fwrite(&val, sizeof(val), 1, File) != 1) THROW("Write error"); return pos;}PRIVATE void write_long_at(long pos, unsigned long val){ long prev = get_pos(); fseek(File, pos, SEEK_SET); #ifdef DEBUG_MORE printf("@ "); #endif write_long(val); fseek(File, prev, SEEK_SET);}PRIVATE void write_string(const char *str, int len){ #ifdef DEBUG_MORE printf("%ld : s \"%.*s\"\n", get_pos(), len, str); #endif if (fwrite(str, sizeof(char), len, File) != len) THROW("Write error"); write_byte(0);}PRIVATE void write_buffer(void *str, long len){ #ifdef DEBUG_MORE printf("%ld : buffer %ld octets\n", get_pos(), len); #endif if (len == 0) return; if (fwrite(str, sizeof(char), len, File) != len) THROW("Write error");}PRIVATE void write_pad(void){ while (get_pos() & 0x3) write_byte(0);}PRIVATE void begin_section(const char *name, int size){ NSection++; #ifdef DEBUG printf("Section #%d : %s\n", NSection, name); #endif if (size) PosStartSection = write_long(0); else PosStartSection = 0; SizeSection = size;}PRIVATE void end_section(void){ long len; if (PosStartSection) { write_pad(); len = get_pos() - PosStartSection - sizeof(long); write_long_at(PosStartSection, len); #ifdef DEBUG printf("==> %ld %s\n", len / SizeSection, (SizeSection == 1) ? "bytes" : "elements"); if (len % SizeSection) printf("*** remain %ld bytes\n", len % SizeSection); #endif }}PRIVATE void output_header(void){ begin_section("Header", 0); /* magic */ write_long(OUTPUT_MAGIC); /* version */ write_long(OUTPUT_VERSION); /* endianess */ write_long(OUTPUT_ENDIAN); /* flag */ if (JOB->debug) write_long(1); else write_long(0); end_section();}PRIVATE void output_class(void){ begin_section("Class", 1); /* classe parente */ write_short(Class->parent); /* reserved */ write_short(0); /* size_static */ write_long(Class->size_stat); /* size_dynamic */ write_long(Class->size_dyn); end_section();}PRIVATE void output_desc(void){ int i, n, nn = 0; CLASS_SYMBOL *csym; TYPE type; short out_type; n = TABLE_count(Class->table); begin_section("Description", 6 * sizeof(long)); for (i = 0; i < n; i++) { csym = (CLASS_SYMBOL *)TABLE_get_symbol(Class->table, i); csym = (CLASS_SYMBOL *)TABLE_get_symbol(Class->table, csym->symbol.sort); type = csym->global.type; if (TYPE_is_public(type)) { nn++; /* name */ write_long(get_string(csym->symbol.name, csym->symbol.len)); switch (TYPE_get_kind(type)) { case TK_VARIABLE: /* type de donn�s */ write_type((csym->global.type)); /* offset */ write_long(csym->global.value); /* read */ write_long(0); /* write */ write_long(0); if (TYPE_is_static(type)) out_type = CD_STATIC_VARIABLE_ID; else out_type = CD_VARIABLE_ID; break; case TK_PROPERTY: /* type de donn�s */ write_type((csym->global.type)); /* read */ write_long(Class->prop[csym->global.value].read); /* write */ write_long(Class->prop[csym->global.value].write); /* flag */ write_long(0); if (TYPE_is_static(type)) out_type = CD_STATIC_PROPERTY_ID; else out_type = CD_PROPERTY_ID; break; case TK_CONST: /* type de donn�s */ write_type((csym->global.type)); /* param */ write_long(csym->global.value); /* read */ write_long(0); /* write */ write_long(0); out_type = CD_CONSTANT_ID; break; case TK_FUNCTION: /* type de la valeur de retour */ write_type((csym->global.type)); /* exec */ write_long(csym->global.value); /* signature */ write_long(0); /* nparam */ write_long(0); if (TYPE_is_static(type)) out_type = CD_STATIC_METHOD_ID; else out_type = CD_METHOD_ID; break; case TK_EVENT: /* type de la valeur de retour */ write_type((csym->global.type)); /* exec */ write_long(csym->global.value); /* signature */ write_long(0); /* nparam */ write_long(0); out_type = CD_EVENT_ID; break; default: ERROR_panic("output_desc: unknown symbol type"); continue; } /* type de symbole */ write_long(out_type); } } end_section();}PRIVATE void output_constant(void){ int i, n; CONSTANT *constant; SYMBOL *sym; TABLE *table; n = ARRAY_count(Class->constant); begin_section("Constants", 3 * sizeof(long)); for (i = 0; i < n; i++) { constant = &Class->constant[i]; /* type */ write_type((constant->type)); /* value */ if (TYPE_can_be_long(constant->type)) { write_long(constant->value); write_long(0); } else { if (TYPE_get_id(constant->type) == T_STRING || TYPE_get_id(constant->type) == T_CSTRING) table = Class->string; else table = Class->table; sym = TABLE_get_symbol(table, constant->value); write_long(get_string(sym->name, sym->len)); write_long(sym->len); } } end_section();}PRIVATE void output_class_ref(void){ int i, n; SYMBOL *sym; n = ARRAY_count(Class->class); begin_section("External classes", sizeof(long)); for (i = 0; i < n; i++) { sym = TABLE_get_symbol(Class->table, Class->class[i]); write_long(get_string(sym->name, sym->len)); } end_section();}PRIVATE void output_unknown_ref(void){ int i, n; SYMBOL *sym; n = ARRAY_count(Class->unknown); begin_section("External symbols", sizeof(long)); for (i = 0; i < n; i++) { sym = TABLE_get_symbol(Class->table, Class->unknown[i]); write_long(get_string(sym->name, sym->len)); } end_section();}PRIVATE void output_static(void){ int i, n; VARIABLE *var; n = ARRAY_count(Class->stat); begin_section("Static variables", 2 * sizeof(long)); for (i = 0; i < n; i++) { var = &Class->stat[i]; /* type */ write_type((var->type)); /* addr */ write_long(var->pos); } end_section();}PRIVATE void output_dynamic(void){ int i, n; VARIABLE *var; n = ARRAY_count(Class->dyn); begin_section("Dynamic variables", 2 * sizeof(long)); for (i = 0; i < n; i++) { var = &Class->dyn[i]; /* type */ write_type((var->type)); /* addr */ write_long(var->pos); } end_section();}PRIVATE void output_event(void){ int i, n; EVENT *event; SYMBOL *sym; n = ARRAY_count(Class->event); begin_section("Events", 4 * sizeof(long)); for (i = 0; i < n; i++) { event = &Class->event[i]; /* type */ write_type((event->type)); /* n_param */ write_short(event->nparam); /* reserved */ write_short(0); /* desc_param */ write_long(0); /* name */ sym = TABLE_get_symbol(Class->table, event->name); write_long(get_string(sym->name, sym->len)); } end_section();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -