⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mix_code_file.c

📁 汇编语言编程源代码
💻 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 + -