📄 mix_code_file.c
字号:
/* -*-c-*- -------------- mix_code_file.c : * Implementation of the functions declared in mix_code_file.h * ------------------------------------------------------------------ * $Id: mix_code_file.c,v 1.3 2002/03/24 01:22:03 jao Exp $ * ------------------------------------------------------------------ * Copyright (C) 2000, 2002 Free Software Foundation, Inc. * * 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 2 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */#include <string.h>#include "mix.h"#include "xmix_io.h"#include "mix_code_file.h"/* mix_code_file_t type */static const gint32 SIGNATURE_ = 0xDEADBEEF; /* release files */ static const gint32 SIGNATURE_D_ = 0xBEEFDEAD; /* debug files */#define IS_DEBUG_(file) ((file)->header.signature == SIGNATURE_D_)#define IS_RELEASE_(file) ((file)->header.signature == SIGNATURE_)typedef struct mix_cfheader_t mix_cfheader_t;struct mix_cfheader_t{ gint32 signature; gint mj_ver; gint mn_ver; gint16 start; size_t path_len;};struct mix_code_file_t { mix_file_t *file; /* the underlying disk file */ mix_address_t address; /* current address while reading */ mix_cfheader_t header; /* file header */ gchar *source_path; /* variable length part of the header*/ mix_symbol_table_t *symbol_table; /* code files with debug info fill it*/};#define to_io_(cf) MIX_IOCHANNEL (cf->file)/* Code files are lists of tagged words. A MIX_INS_TAG_ denotes * that the word is an instruction, whose address is the next to * the previous instruction's one, while a MIX_ADDR_TAG_ indicates * that the word is a new address origin for the next instructions. * The tags are stored as bit patterns in bit 31 of the mix word. */#define MIX_ADDR_TAG_ (MIX_WORD_SIGN_BIT<<1)#define is_ins_(word) (((word)&MIX_ADDR_TAG_) == MIX_WORD_ZERO)#define is_addr_(word) (((word)&MIX_ADDR_TAG_) == MIX_ADDR_TAG_)#define tag_ins_(word) (word)#define tag_addr_(word) ((word)|MIX_ADDR_TAG_)#define extract_ins_(tagged) (tagged)#define extract_addr_(tagged) ((tagged)&MIX_SHORT_MAX)/* mix code files have a default extension (.mix) which is customizable */static const gchar *DEFEXT_ = NULL;const gchar *mix_code_file_get_defext (void){ return DEFEXT_;}gbooleanmix_code_file_set_defext (const gchar *ext){ if (DEFEXT_ != NULL) g_free ((void *)DEFEXT_); DEFEXT_ = (ext != NULL)? g_strdup (ext):NULL; return (DEFEXT_ != NULL || ext == NULL);}/* create/destroy code files for read or write */static mix_code_file_t *mix_code_file_new_ (const gchar *name, mix_fmode_t mode){ mix_code_file_t *result = g_new (mix_code_file_t, 1); if ( result != NULL ) { result->file = mix_file_new_with_def_ext (name, mode, DEFEXT_); result->address = MIX_SHORT_ZERO; result->symbol_table = NULL; } if ( result != NULL && result->file == NULL ) { g_free (result); result = NULL; } return result;}mix_code_file_t *mix_code_file_new_read (const gchar *name){ mix_code_file_t *result = mix_code_file_new_ (name, mix_io_READ); mix_cfheader_t *header; FILE *file; gboolean check; if ( result == NULL ) return NULL; file = mix_file_to_FILE (result->file); header = &(result->header); check = fread (header, sizeof (mix_cfheader_t), 1, file); if ( check ) check = IS_RELEASE_ (result) || IS_DEBUG_ (result); /* disable check to avoid breaking old files: 0.x and 1.x use the same bytecode */#if 0 if ( check ) { gint major, minor; sscanf (VERSION, "%d.%d", &major, &minor); check = header->mj_ver == major && header->mn_ver <= minor; }#endif if ( check ) {/* get source path */ result->source_path = g_strnfill (1 + header->path_len, '\0'); check = result->source_path != NULL && fgets (result->source_path, 1 + header->path_len, file) != NULL; } if ( check && IS_DEBUG_ (result) ) {/* read symbol table */ result->symbol_table = mix_symbol_table_new_from_file (file); check = result->symbol_table != NULL; } if ( !check ) { mix_code_file_delete (result); return NULL; } return result;}mix_code_file_t *mix_code_file_new_write(const gchar *name, mix_address_t addr, const gchar *source_path, gboolean debug, const mix_symbol_table_t *table){ mix_code_file_t *result; FILE *file; gboolean check; result = mix_code_file_new_ (name, mix_io_WRITE); if ( result == NULL || ( file = mix_file_to_FILE (result->file) ) == NULL ) return NULL; else if ( source_path != NULL ) { result->source_path = g_strdup (source_path/*, MAX_PATH_LEN_*/); if ( result->source_path == NULL ) { mix_code_file_delete (result); return NULL; } } else result->source_path = NULL; result->header.signature = debug? SIGNATURE_D_:SIGNATURE_; sscanf (VERSION, "%d.%d", &result->header.mj_ver, &result->header.mn_ver); result->header.start = (gint16) addr; result->header.path_len = strlen (result->source_path); check = write_data_ (to_io_ (result), &result->header, 1); if ( check && result->source_path != NULL ) check = fputs (result->source_path, file) != EOF; if ( check && debug ) mix_symbol_table_print (table, MIX_SYM_LINE, file, TRUE); if ( !check ) { mix_code_file_delete (result); return NULL; } return result;}voidmix_code_file_delete (mix_code_file_t *file) { g_return_if_fail (file != NULL); mix_file_delete (file->file); if ( file->source_path ) g_free (file->source_path); g_free (file);}/* get general parameters from a code file */gbooleanmix_code_file_is_debug (const mix_code_file_t *file){ return (file == NULL ) ? FALSE : IS_DEBUG_ (file);}gintmix_code_file_major_version (const mix_code_file_t *file){ g_return_val_if_fail (file != NULL, 0); return file->header.mj_ver;}gintmix_code_file_minor_version (const mix_code_file_t *file){ g_return_val_if_fail (file != NULL, 0); return file->header.mn_ver;}mix_address_tmix_code_file_get_start_addr (const mix_code_file_t *file){ g_return_val_if_fail (file != NULL, MIX_SHORT_ZERO); return mix_short_new (file->header.start);}mix_symbol_table_t *mix_code_file_get_symbol_table(mix_code_file_t *file){ mix_symbol_table_t *result = NULL; g_return_val_if_fail (file != NULL, NULL); result = file->symbol_table; file->symbol_table = NULL; return result;}/* read instructions from a code file */gbooleanmix_code_file_is_eof (mix_code_file_t *file){ return is_eof_ (to_io_ (file));}gbooleanmix_code_file_get_ins (mix_code_file_t *file, mix_ins_desc_t *desc){ mix_word_t next; g_return_val_if_fail (file != NULL, FALSE); g_return_val_if_fail (desc != NULL, FALSE); while (TRUE) { if ( ! mix_io_read_word_array (to_io_ (file), &next, 1) ) return FALSE; if ( is_addr_ (next) ) file->address = extract_addr_ (next); else if ( is_ins_ (next) ) { desc->ins = extract_ins_ (next); desc->address = (file->address)++; if ( IS_DEBUG_ (file) ) { mix_short_t lineno; if ( !mix_io_read_short_array (to_io_ (file), &lineno, 1) ) return FALSE; desc->lineno = mix_short_magnitude (lineno); } else desc->lineno = 0; return TRUE; } else { g_assert_not_reached (); return FALSE; } };}/* Write instructions to a code file */gbooleanmix_code_file_write_ins (mix_code_file_t *file, const mix_ins_desc_t *desc){ g_return_val_if_fail (desc != NULL, FALSE); return ( mix_code_file_set_address (file, desc->address) && mix_code_file_write_next_ins (file, desc->ins, desc->lineno) );}gbooleanmix_code_file_write_next_ins (mix_code_file_t *file, mix_word_t ins, guint lineno){ g_return_val_if_fail (file != NULL, FALSE); if ( mix_io_write_word (to_io_ (file), tag_ins_ (ins)) && ( IS_RELEASE_ (file) || mix_io_write_short (to_io_ (file), mix_short_new (lineno)) ) ) { ++(file->address); return TRUE; } else return FALSE;}gbooleanmix_code_file_set_address (mix_code_file_t *file, mix_address_t address){ g_return_val_if_fail(file != NULL, FALSE); if ( file->address != address ) { if ( !mix_io_write_word (to_io_ (file), tag_addr_ (mix_short_to_word_fast (address))) ) return FALSE; file->address = address; } return TRUE;} /* get details about the source file */const gchar *mix_code_file_get_source_path (const mix_code_file_t *file){ g_return_val_if_fail (file != NULL, NULL); return file->source_path;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -