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

📄 idelasm.c

📁 idel虚拟机源码
💻 C
📖 第 1 页 / 共 2 页
字号:
compile_number (void){  int value;  if (parse_number (&value))    gen2 (PUSH, value, absolute);  else    {      stub (string_dup (token_text));      gen_insn (CALL, 0, text_segment, find (&globals, token_text));    }}static void compile_token (void){  const Symbol *e = find (&locals, token_text);  if (e && e->opcode != unbound)    gen2 (LOCAL, locals.size - 1 - e->index, absolute);  else    {      const Symbol *e = find (&globals, token_text);      if (e == NULL)	compile_number ();      else	switch (e->opcode)	  {	  case CALL:  gen_insn (CALL, 0, e->segment, e); break;	  case PUSH:  gen2 (PUSH, e->index, e->segment); break;	  case LOCAL: unreachable (); break;	  default:    gen (e->opcode); break;	  }    }}static intseeing (const char *string){  return 0 == strcmp (token_text, string);}static voidexpect (const char *string){  if (!seeing (string))    syntax_error ("Missing `%s'", string);}static voideat (const char *string){  expect (string);  advance ();}static intsee_locals (void){  int before = locals.size;  for (;;)    {      advance ();      if (seeing ("--"))	break;      else if (seeing ("}"))	syntax_error ("Missing `--'");      else	define_local (token_text);    }  return locals.size - before;}static voidnest (void){  for (;;)    {      advance ();      if (seeing ("{"))	{	  int count = see_locals ();	  if (count != 0)	    gen (BEGIN);	  nest ();	  expect ("}");	  if (count != 0)	    gen2 (DROP, count, absolute);	  unbind (&locals, count);	}      else if (seeing ("}"))	break;      else if (seeing ("if"))	{	  gen (BEGIN);	  nest ();	  if (seeing ("else"))	    {	      gen (ELSE);	      nest ();	    }	  expect ("then");	  gen (THEN);	}      else if (seeing ("else"))	break;      else if (seeing ("then"))	break;      else if (seeing (";"))	break;      else if (seeing (""))	break;      else	compile_token ();    }}static u32parse_stack_effect (void){  int popping, pushing;  advance ();  if (!parse_number (&popping))    syntax_error ("Number expected (pushing)");  advance ();  if (!parse_number (&pushing))    syntax_error ("Number expected (popping)");  return interleave_bits (popping, pushing);}static voidcolon (void){  u32 se = parse_stack_effect ();  advance ();  if (seeing ("")) syntax_error ("Name expected");  {    const char *name = string_dup (token_text);    create (name, se);    nest ();    eat (";");    created (name);  }}static voidcompile_bytes (void){  int token_value;  while (parse_number (&token_value))    {      emit_byte (token_value);      advance ();    }}static voidcompile_ints (void){  int token_value;  while (parse_number (&token_value))    {      emit_int (token_value);      advance ();    }}static voidparse_bytes (void){  advance ();  if (seeing ("")) syntax_error ("Name expected");  {    const char *name = string_dup (token_text);    new_header (&globals, name, 		PUSH, data_ptr, data_segment, 0);    advance ();    compile_bytes ();    eat (";bytes");  }}static voidparse_ints (void){  advance ();  if (seeing ("")) syntax_error ("Name expected");  {    const char *name = string_dup (token_text);    data_ptr = word_align (data_ptr);    new_header (&globals, name, 		PUSH, data_ptr, data_segment, 0);    advance ();    compile_ints ();    eat (";ints");  }}static voidcompile_string_constant (void){  skip_preprocessor ();  if (ch != '"')    syntax_error ("Expected a string constant");  next ();  for (; ch != '"'; next ())    if (ch == '\0')      syntax_error ("Unterminated string constant");    else if (ch == '\\')      emit_byte (scan_escape ());    else      emit_byte (ch);  next ();}static voidparse_string (void){  advance ();  if (seeing ("")) syntax_error ("Name expected");  {    const char *addr_name = string_cat (token_text, ".addr");    const char *size_name = string_cat (token_text, ".size");    int start = data_ptr;    new_header (&globals, addr_name, 		PUSH, start, data_segment, 0);    compile_string_constant ();    new_header (&globals, size_name, 		PUSH, data_ptr - start, data_segment, 0);    advance ();  }}static voidparse_bss_data (void){  int value;  advance ();  if (seeing ("")) syntax_error ("Name expected");  {    const char *name = string_dup (token_text);    new_header (&globals, name, 		PUSH, bss_ptr, bss_segment, 0);    advance ();    if (!parse_number (&value))      syntax_error ("Integer expected");    if (value < 0)      syntax_error ("Negative count");    advance ();    if (bss_ptr + value < bss_ptr)      syntax_error ("BSS space overflow");    bss_ptr += value;  }}static voidcompile_program (void){  scan = program;  ch = *scan;  start_line ();  advance ();  while (!seeing (""))    {      if (seeing ("def"))	colon ();      else if (seeing ("bytes:"))	parse_bytes ();      else if (seeing ("ints:"))	parse_ints ();      else if (seeing ("string:"))	parse_string ();      else if (seeing ("bss-data:"))	parse_bss_data ();      else	syntax_error ("Definition expected");    }}/* Output */static voidpush_insn (OW *ow, const Insn *insn, int this_index){  int op = insn->opcode;  switch (op)    {    case DROP:     case LOCAL:      push_u32 (ow, insn->operand);      break;    case PUSH:       if (insn->segment == bss_segment)	push_i32 (ow, bss_start + insn->operand);      else	push_i32 (ow, insn->operand);      break;    case CALL:      if (insn->symbol->index == -1)	{	  the_place = insn->place;	  syntax_error ("Unresolved reference to %s", insn->symbol->name);	}      push_i32 (ow, insn->symbol->index - this_index);      break;    }  push_u8 (ow, op);}static voidpush_defn (OW *ow, const Symbol *e){  int mark = start_subfile (ow);  int i;  for (i = e->start; i < e->end; ++i)    push_insn (ow, &text[i], e->index);  end_subfile (ow, mark);}static Symbol **defns_fill (void){  int d, i;  Symbol **defn_symbol = allot (current_index * sizeof defn_symbol[0]);  for (d = 0; d < current_index; ++d)    defn_symbol[d] = NULL;  for (i = 0; i < globals.size; ++i)    {      Symbol *e = globals.stack[i];      if (e->opcode == CALL && e->index != -1)	{	  assert (0 <= e->index && e->index < current_index);	  defn_symbol[e->index] = e;	}    }  return defn_symbol;}  static Symbol *defns_ref (Symbol **defn_symbol, int i){  assert (0 <= i && i < current_index);  if (defn_symbol[i] == NULL)    die ("Unresolved defn");	/* This can't happen (right?) */  return defn_symbol[i];}static voidpush_defns (OW *ow){  int mark = start_subfile (ow);  Symbol **defn_symbol = defns_fill ();  int i;  for (i = current_index - 1; 0 <= i; --i)    push_defn (ow, defns_ref (defn_symbol, i));  for (i = current_index - 1; 0 <= i; --i)    push_u32 (ow, defns_ref (defn_symbol, i)->stack_effect);  free (defn_symbol);  push_u32 (ow, current_index);  end_subfile (ow, mark);  push_tag (ow, tag_defns);}static voidpush_int_run (OW *ow, int top, int bottom){  int mark = start_subfile (ow);  while (bottom < top)    {      top -= word_size;      push_i32 (ow, *(i32 *)(data + top));    }  end_subfile (ow, mark);  push_tag (ow, tag_ints);}static voidpush_byte_run (OW *ow, int top, int bottom){  int mark = start_subfile (ow);  while (bottom < top)    {      top -= 1;      push_u8 (ow, data[endianness ^ top]);    }  end_subfile (ow, mark);  push_tag (ow, tag_bytes);}static voidpush_run (OW *ow, int top, int bottom, int int_encoded_size){  if (int_encoded_size < top - bottom)    push_int_run (ow, top, bottom);  else    push_byte_run (ow, top, bottom);}static intblock_size (int byte_count){  return 1 + u32_encoded_size (byte_count) + byte_count;}static boolshould_join (int top, int bot1, int size1, int bot2, int size2){  if (size1 < top - bot1)    return size2 < block_size (bot1 - bot2);  else    return bot1 - bot2 < block_size (size2);}/* Traverse the run of data words ending at index `top' whose sizes   when int-encoded are either all >= word_size or all <= word_size.   Set *bottom to the index of the start of the run, and   *int_encoded_size to the size as encoded.   Pre: `top' points to a word boundary > 0. */static voidfind_run (int *bottom, int *int_encoded_size, int top){  int bot = top;  int sum = 0;		/* sum of the sizes from bot to top */  int L, variety;  /* Go through any initial run of size=word_size words */  do {      bot -= word_size;      L = i32_encoded_size (*(i32 *)(data + bot));      sum += L;  } while (0 < bot && word_size != L);  /* Now we know which variety of run we're looking for */  variety = (L <= word_size);  /* So go through the ensuing run of that type, and we're done */  while (0 < bot)    {      L = i32_encoded_size (*(i32 *)(data + bot - word_size));      if (variety != (L <= word_size))	break;      bot -= word_size, sum += L;    }  *bottom = bot;  *int_encoded_size = sum;}/* Push a Zeroes block if needed to pad out to the total space, and   return the address of the top of the nonzero data. */static intpush_zeroes (OW *ow){  int top = word_align (data_ptr);  int space = top + word_align (bss_ptr);  /* Skip down over any zeroes at the top of the data segment */  while (0 < top && 0 == *(i32 *)(data + top - 4))    top -= 4;  if (top < space)    {      int mark = start_subfile (ow);      push_i32 (ow, space - top);      end_subfile (ow, mark);      push_tag (ow, tag_zeroes);    }  return top;}/* Push all the static data onto `ow'.  Produces a combination of int   and byte sections for space efficiency -- it's essentially doing   run-length encoding on the int-encoded sizes of the data words.   This lets us encode both arrays of small integers and arrays of   random bytes with reasonable efficiency. */static voidpush_data (OW *ow){  int top = push_zeroes (ow);  int bot1, size1;  int bot2, size2;  if (top == 0)    return;  find_run (&bot1, &size1, top);  while (0 < bot1)    {      find_run (&bot2, &size2, bot1);      /* There's a run-boundary at bot1 now.  If switching the run         type is too expensive we instead join the following two runs         into the topmost one. */      if (should_join (top, bot1, size1, bot2, size2))	{	  bot1 = bot2, size1 += size2;	  if (0 < bot1)	    {	      find_run (&bot2, &size2, bot1);	      bot1 = bot2, size1 += size2;	    }	}      else	{	  push_run (ow, top, bot1, size1);	  top = bot1, bot1 = bot2, size1 = size2;	}    }  push_run (ow, top, bot1, size1);}static voidwrite_program (const char *comment){  OW *ow = ow_make ();  bss_start = word_align (data_ptr);  push_data (ow);  push_defns (ow);  push_header (ow, comment);  ow_write (stdout, ow);  ow_unmake (ow);}/* The main program */static voidprocess_file (const char *filename){  int size;  FILE *input = open_file (filename, "r");  the_place.filename = (input == stdin ? NULL : filename);  the_place.line = the_place.column = 0;  read_file (&program, &size, input);  fclose (input);  compile_program ();  free (program);}static voidshow_version (void){  printf ("idelasm version %s\n", idel_version_string);  exit (0);}static voidshow_help (void){  printf ("Usage: %s [option]... [file]...\n", program_name);  printf ("where the legal options are:\n""  -comment <string>\n""  -help\n""  -version\n");  exit (0);}static const char *parse_comment (const char *comment){  if (strchr (comment, '\n'))    die ("Comment contains a newline: %s", comment);  return comment;}const char *program_name;intmain (int argc, char **argv){  const char *comment = NULL;  program_name = argv[0];  setup_dictionaries ();  setup_primitives ();  setup_insns ();  setup_data_space ();  /* Parse command-line options */  for (;;)    {      if (1 < argc)	{	  if (0 == strcmp ("-version", argv[1]))	    show_version ();	  if (0 == strcmp ("-help", argv[1]))	    show_help ();	}      if (2 < argc)	{	  if (0 == strcmp ("-comment", argv[1]))	    comment = parse_comment (argv[2]);	  else	    break;	  argc -= 2, argv += 2;	  	}      else	break;    }  if (argc == 1)    process_file ("-");  else    for (; 1 < argc; ++argv, --argc)      process_file (argv[1]);  write_program (comment);  return 0;}

⌨️ 快捷键说明

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