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

📄 idelasm.c

📁 idel虚拟机源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Idel assembler. * Copyright (C) 2001-2002 Darius Bacon */#include <ctype.h>#include <errno.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "idel_private.h"/* Forward refs */static void syntax_error (const char *complaint, ...);/* Misc */static char *string_dup (const char *s){  size_t ss = strlen (s);  char *t = allot (ss + 1);  memcpy (t, s, ss);  t[ss] = '\0';  return t;}static char *string_cat (const char *s, const char *t){  size_t ss = strlen (s);  size_t ts = strlen (t);  char *u = allot (ss + ts + 1);  memcpy (u, s, ss);  memcpy (u + ss, t, ts);  u[ss + ts] = '\0';  return u;}/* Source locations */typedef struct Place {  int line;  int column;  const char *filename;} Place;static voidprint_place (Place place){  if (place.filename && place.filename[0] != '\0')    fprintf (stderr, "%s:", place.filename);  fprintf (stderr, "%d.%d: ", place.line, place.column);}/* This has a hard limit but it doesn't especially matter if you run into it. */static char place_filenames[16384];static int filename_ptr = 0;static const char *add_place_filename (const char *filename){  char *next_slot = place_filenames + filename_ptr;  int fs = strlen (filename) + 1;  if ((int) sizeof place_filenames < filename_ptr + fs)    return "(Too many files)";  memcpy (next_slot, filename, fs);  filename_ptr += fs;  return next_slot;}static Place the_place = { 0, 0, NULL };/* The code buffer *//* We're using the archaic traditional segment names here: */typedef enum {   text_segment,   data_segment,   bss_segment,  absolute} Segment;typedef struct Insn {  u8 opcode;  i32 operand;  Segment segment;  const struct Symbol *symbol;  Place place;} Insn;static int text_allotted;static Insn *text;static int text_ptr;static voidsetup_insns (void){  text_allotted = 1024;  text = allot (text_allotted * sizeof text[0]);  text_ptr = 0;}static voidgen_insn (u8 opcode, i32 operand, Segment segment, const struct Symbol *e){  if (text_allotted <= text_ptr)    {      text_allotted *= 2;      text = reallot (text, text_allotted * sizeof text[0]);    }  {    Insn *insn = &text[text_ptr++];    insn->opcode = opcode;    insn->operand = operand;    insn->segment = segment;    insn->symbol = e;    insn->place = the_place;  }}static voidgen2 (u8 opcode, i32 operand, Segment segment){  gen_insn (opcode, operand, segment, NULL);}static void gen (i32 opcode){  gen_insn (opcode, 0, absolute, NULL);}/* The data buffer */static int data_allotted;	/* Inv: == a positive multiple of word_size */static int data_ptr;		/* Inv: >= 0 and <= data_allotted */static i8 *data;		/* An allotted buffer of size data_alloted.				   All bytes at data_ptr and up (big-endian)				   are 0. */static int bss_ptr;		/* Inv: >= 0 */static int bss_start;		/* Inv: >= 0 and a multiple of word_size */static voidsetup_data_space (void){  data_allotted = 64 * word_size;  data_ptr = 0;  data = allot (data_allotted * sizeof data[0]);  memset (data, 0, data_allotted * sizeof data[0]);  bss_ptr = 0;}static voidensure_space_for_data (void){  if (data_allotted <= data_ptr)    {      int new_a = data_allotted * 2;      data = reallot (data, new_a);      memset (data + data_allotted, 0, data_allotted);      data_allotted = new_a;    }}static voidemit_byte (int value){  if (value < -128 || 255 < value)    syntax_error ("Byte literal out of range");  ensure_space_for_data ();  data [endianness ^ data_ptr++] = value;}static voidemit_int (int value){  data_ptr = word_align (data_ptr);  ensure_space_for_data ();  *(i32 *)(data + data_ptr) = value;  data_ptr += word_size;}/* The dictionary */enum { unbound = -1 };		/* must be distinct from all opcodes */typedef struct Symbol {  /* Print-name */  const char *name;			  /* Can be a primitive, CALL, LOCAL, PUSH, or unbound. */  int opcode;  /* Depending on type of symbol:     defn: -1 if not yet defined, else value of current_index at define time.     local var: index of variable (starting from 0 for outermost)     constant: constant value     primitive: N/A */  int index;  /* What segment the index value is relative to, if applicable. */  Segment segment;  /* Value of `text_ptr' at define time.     (Only relevant for a defn.) */  int start;  /* Value of `text_ptr' after fully defined.  -1 before fully defined.     (Only relevant for a defn.) */  int end;  /* Interleave-encoded stack effect for defn.  0 before it's defined.     (Only relevant for a defn.) */  u32 stack_effect;  /* Hash bucket list link */  struct Symbol *next;} Symbol;enum { num_buckets = 1024 };	/* must be a power of 2 */typedef struct Dictionary {  int size;			/* how many names bound */  int space;			/* how many slots allocated for stack */  Symbol **stack;		/* all names currently bound, oldest first */  Symbol *buckets[num_buckets];} Dictionary;static Dictionary globals, locals;static voidsetup_dictionary (Dictionary *d){  int i;  d->size = 0;  d->space = 16;  d->stack = allot (d->space * sizeof d->stack[0]);  for (i = 0; i < num_buckets; ++i)    d->buckets[i] = NULL;}static voidsetup_dictionaries (void){  setup_dictionary (&globals);  setup_dictionary (&locals);}static unsignedhash (const char *key){  /* One-at-a-Time Hash from http://burtleburtle.net/bob/hash/doobs.html */  unsigned hash = 0, i;  for (i = 0; key[i]; ++i)    {      hash += key[i];      hash += hash << 10;      hash ^= hash >> 6;    }  hash += hash << 3;  hash ^= hash >> 11;  hash += hash << 15;  return hash % num_buckets;}static Symbol *bucket_find (Symbol *e, const char *word){  for (; e != NULL; e = e->next)    if (0 == strcmp (e->name, word))      return e;  return NULL;}static Symbol *find (const Dictionary *d, const char *word){  return bucket_find (d->buckets[hash (word)], word);}static voidnew_header (Dictionary *d, const char *name, 	    int opcode, int index, Segment segment, u32 se){  unsigned b = hash (name);  Symbol *found = bucket_find (d->buckets[b], name);  Symbol *e = found;  if (found == NULL)    {      e = allot (sizeof *e);      e->next = d->buckets[b];      d->buckets[b] = e;    }  else if (found->opcode != unbound)    syntax_error ("Word redefined: `%s'", name); /* FIXME: locals should                                                    be redefinable */  e->name = name;  e->opcode = opcode;  e->index = index;  e->segment = segment;  e->start = text_ptr;  e->end = -1;  e->stack_effect = se;    if (d->size == d->space)    {      d->space *= 2;      d->stack = reallot (d->stack, d->space * sizeof d->stack[0]);    }  d->stack[d->size++] = e;}static voidunbind (Dictionary *d, int count){  int i;  for (i = 0; i < count; ++i)    {      Symbol *s = d->stack[d->size - i - 1];      s->opcode = unbound;      s->index = -1;    }  d->size -= count;}static int current_index = 0;static voidcreate (const char *name, u32 stack_effect){  Symbol *e = find (&globals, name); /* ugh */  if (e == NULL)    new_header (&globals, name, 		CALL, current_index, text_segment, stack_effect);  else if (e->index == -1)    {      e->index = current_index;      e->start = text_ptr;      e->stack_effect = stack_effect;    }  else    syntax_error ("Redefinition not allowed");}static voidstub (const char *name){  new_header (&globals, name, CALL, -1, text_segment, 0);}static voidcreated (const char *name){  Symbol *e = find (&globals, name);  assert (e->opcode == CALL);  assert (e->start <= text_ptr);  e->end = text_ptr;  ++current_index;}static voiddefine_local (const char *name){  new_header (&locals, string_dup (name), 	      LOCAL, locals.size, absolute, 0);}static voidinstall_primitive (const char *name, int opcode){  new_header (&globals, name, 	      opcode, 0, absolute, 0);}static voidsetup_primitives (void){#include "dict.inc"}/* The parser */static char *program = NULL;	/* text of the input program */static const char *line_start;  /* start of current line within program */static char *scan;		/* current position within program */static char ch;			/* current character being scanned */static char *token_text;	/* current token */static int   token_value;	/* used only for char-literal tokens */static voidsyntax_error (const char *complaint, ...){  va_list args;  print_place (the_place);  va_start(args, complaint);  vfprintf(stderr, complaint, args);  va_end(args);  fprintf(stderr, "\n");  exit (1);}static charnext (void){  assert (ch != '\0');  return ch = *++scan;}/* Try to parse token_text as a 32-bit number (either signed or unsigned).   Return true iff successful, and set *result to the value. */static intparse_number (int *result){  char *endptr;  int value;  if (token_text[0] == '\0')    return 0;  if (token_text[0] == '0' && token_text[1] == 'x')    {      errno = 0;      value = strtoul (token_text + 2, &endptr, 16);      if (*endptr != '\0' || errno == ERANGE)	return 0;    }  else if (token_text[0] == '\'')    value = token_value;	/* already parsed by gobble() */  else    {      errno = 0;      value = strtol (token_text, &endptr, 10);      if (*endptr != '\0' || errno == ERANGE)	{	  errno = 0;	  value = strtoul (token_text, &endptr, 10);	  if (*endptr != '\0' || errno == ERANGE)	    return 0;	}    }  *result = value;  return 1;}static inthex_digit (char c){  char lc = tolower (c);  if ('0' <= lc && lc <= '9')    return lc - '0';  if ('a' <= lc && lc <= 'f')    return lc - ('a' - 10);  syntax_error ("Not a hex digit: '%c'", c);  return 0;			/* to mollify the C compiler */}/* Parse the string at `scan' as an escape sequence.  (It must start   with a `\' character.)  Advance to the end of it and return the   character constant encoded. */static intscan_escape (void){  next ();  switch (ch)    {    case 'f':  return '\f';    case 'n':  return '\n';    case 'r':  return '\r';    case 't':  return '\t';    case '\\': return '\\';    case 'x':      {	char d1 = next ();	char d2 = (d1 == '\0' ? '\0' : next ());	return 16 * hex_digit (d1) + hex_digit (d2);      }    case '\0':       syntax_error ("Unterminated string constant");      return 0;    default:         syntax_error ("Unknown escape code in string: '%c'", ch);      return 0;    }}static voidgobble_char_literal (void) {  next ();  if (ch == '\0')    syntax_error ("Unterminated character constant");  else if (ch == '\\')    token_value = scan_escape ();  else    token_value = ch;  next ();  if (ch != '\'')    syntax_error ("Malformed character constant");  next ();  if (!isspace (ch))    syntax_error ("Malformed character constant");  *scan = '\0';}static voidgobble (void) {  token_text = scan;  if (ch == '\'')    gobble_char_literal ();  else    {      while (ch != '\0' && !isspace (ch))	next ();      *scan = '\0';    }}static voidskip_blanks (void){  while (isspace (ch) && ch != '\n')    next ();}static const char *scan_filename (void){  the_place.column = scan - line_start;  if (ch != '"')    syntax_error ("Bad # syntax");  next ();  token_text = scan;  while (ch != '\0' && ch != '"')    next ();  if (ch != '"')    syntax_error ("Bad # syntax");  *scan = '\0';  next ();  return token_text;}static voidscan_line_directive (void){  int line;  const char *filename;  next ();				/* skip over the '#' */  skip_blanks ();  gobble ();  if (!parse_number (&line))    syntax_error ("Bad # syntax");  skip_blanks ();  filename = scan_filename ();  skip_blanks ();  gobble ();  skip_blanks ();  if (ch != '\n' && ch != '\0')    syntax_error ("Bad # syntax");  if (ch) next ();    the_place.line = line;  the_place.filename = add_place_filename (filename);}static voidstart_line (void){  line_start = scan;  the_place.line++;  while (ch == '#')    scan_line_directive ();}/* Skip whitespace and comments and the C preprocessor's # lines. */static voidskip_preprocessor (void){  for (;;)    {      char c = ch;      while (isspace (c))	{	  next ();	  if (c == '\n')	    start_line ();	  c = ch;	}      if (c != '\\')		/* comment character */	break;      do { next (); } while (ch != '\n' && ch != '\0');    }}static voidadvance (void) {  skip_preprocessor ();  the_place.column = scan - line_start + 1;  gobble ();}static void

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -