Beispiel #1
0
/*
 * Creates a literal symstr from a plain string.
 * Not used by the scanner/parser.
 */
struct symstr *
symstr_create(struct symbol_table *stab, char *s)
{
	struct symstr *ss;
	struct symbol *sym;
	char word[128];
	int i, j;

	i = 0;
	ss = symstr_new();
	while (s[i] != '\0') {
		while (isspace((int)s[i]) && s[i] != '\0')
			i++;
		if (s[i] == '\0')
			break;
		j = 0;
		while (!isspace((int)s[i]) && s[i] != '\0' && j < 128)
			word[j++] = s[i++];
		word[j] = '\0';
		if ((sym = symbol_lookup(stab, word)) == NULL)
			sym = symbol_define(stab, word, SYM_TYPE_LITERAL);
		symstr_append(ss, sym, NULL, 0, SYMSTR_OP_NOP);
	}

	return(ss);
}
Beispiel #2
0
SYMBOL* symbol_lookup(NODE* node, char* id)
{
	int result;

	if (!node)
		return NULL;

	result = strcmp(id, node->symbol->id);

	if (result < 0)
		return symbol_lookup(node->left,id);
	else if (result > 0)
		return symbol_lookup(node->right,id);

	return node->symbol;
}
Beispiel #3
0
static void
pf_function_def (PFunArgs)
{
  char *name = mhtml_evaluate_string (get_positional_arg (vars, 0));
  char *result = (char *)NULL;

  if (!empty_string_p (name))
    {
      Symbol *sym = symbol_lookup_in_package (mhtml_user_keywords, name);

      if (sym == (Symbol *)NULL)
	sym = symbol_lookup (name);

      if ((sym != (Symbol *)NULL) && (sym->type == symtype_USERFUN))
	result = mhtml_recompose_function (sym);
    }

  xfree (name);

  if (result != (char *)NULL)
    {
      int len = strlen (result);
      bprintf_insert (page, start, "%s", result);
      free (result);
      *newstart += len;
    }
}
Beispiel #4
0
symbol_handle symbol_define(const char *s){
  symbol_start();
  while(*s != '\000'){
    symbol_append(*s);
    s++;
  }
  return symbol_lookup();
}
        symbol_data const & find(const char * str, size_t strlen)
        {
            mutex.lock_shared();
            lookup_result_type lookup_result = symbol_lookup(str);
            mutex.unlock_shared();
            if (lookup_result.second)
                return *lookup_result.first;

            boost::unique_lock<nova::nonrecursive_rw_mutex> lock(mutex);
            lookup_result = symbol_lookup(str);
            if (lookup_result.second)
                return *lookup_result.first;

            std::pair<table_type::iterator, bool> inserted = table.insert(symbol_data(duplicate_string(str, strlen)));
            assert(inserted.second);
            return *inserted.first;
        }
Beispiel #6
0
SYMBOL* scope_local_lookup(SCOPE* scope, char *id, type_symbol type)
{
	SYMBOL* symbol = NULL;

	symbol = symbol_lookup(scope->node[type], id);
	if (!symbol && scope->parent && !scope->parent->global)
		return scope_lookup(scope->parent, id, type);

	return symbol;
}
Beispiel #7
0
SYMBOL* scope_lookup(SCOPE* scope, char *id)
{
	SYMBOL* symbol = NULL;

	symbol = symbol_lookup(scope->node, id);
	if (!symbol && scope->parent)
		return scope_lookup(scope->parent, id);

	return symbol;
}
Beispiel #8
0
ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *obj,
			   const char *sym, psaddr_t *addr)
{
  uintptr_t sym_addr;

  if (symbol_lookup(sym, &sym_addr) == RET_ERR)
    return PS_NOSYM;

  *addr = (psaddr_t) sym_addr;
  return PS_OK;
}
Beispiel #9
0
void show_function(void *addr)
{
	char buf[128];
	char *sym;

	sym = symbol_lookup((unsigned long) addr, buf, ARRAY_SIZE(buf));

	if (sym)
		trace_printf("%s\n", sym);
	else
		trace_printf("<unknown>\n");
}
Beispiel #10
0
const fexp* db_evaluate(closure* c, db* self, const fexp* expression)
{
  // TODO - VillageBus->request context should be coming in via the closure

  // debug
  /*printf("db_evaluate: ");
  send(message, s_print);
  printf("\n");*/

  // lazily initialize redis connection
  fexp* error = (fexp*)send(self, s_db_connect);
  if (error != fexp_nil) {
    return error;
  }

  // search for name in local context
  string* name    = (string*)send(expression, s_fexp_car);
  fexp*   message = (fexp*)send(expression, s_fexp_cdr);
  object* channel = symbol_lookup(0, _DB, name->buffer);
  if (channel) {
    return (fexp*)send(self, channel, message);
  } 

  // evaluate expression w/ default handlers
  Request* request = VillageBus->request;
  const fexp* reply = fexp_nil;
  switch (request->method) {
  case PUT:
    reply = (fexp*)send(self, s_db_getset, expression, request->data);
    break;
  case POST:
    reply = (fexp*)send(self, s_db_lpush, expression, request->data);
    break;
  case GET:
    reply = (fexp*)send(self, s_db_get, expression);
    break;
  case DELETE:
    reply = (fexp*)send(self, s_db_del, expression);
    break;
  default:
    reply = (fexp*)send(VillageBus, 
                        s_villagebus_error, 
                        L"mod_db has no registered handler for request method: %d", 
                        request->method);  // TODO method_to_string 
  }

  // close server connection & release resources
  send(self, s_db_close);

  return reply;
}
Beispiel #11
0
void
typecheck_visit_identifier (struct _Visitor *visitor, struct AstNode *node)
{
    Symbol *sym = symbol_lookup(symtab, node->symbol->name);
    Symbol *_sym = sym;

    // O atributo 'decl_linenum' > 0 indica que o identificador referencia
    // a declaracao de uma variavel/procedimento/funcao.

    void __fetch_symbol(struct AstNode *node, Symbol *sym) {
        symbol_table_destroy(node->symbol);
        node->symbol = sym;
        node->type = sym->type;
    }
Beispiel #12
0
const fexp* telephony_evaluate(closure* c, telephony* self, const fexp* expression)
{
  // TODO - VillageBus->request context should be coming in via the closure

  // search for name in local context
  string* name    = (string*)send(expression, s_fexp_car);
  fexp*   message = (fexp*)send(expression, s_fexp_cdr);
  object* channel = symbol_lookup(0, _Telephony, name->buffer);
  if (channel) {
    return (fexp*)send(self, channel, message);
  } 

  return (fexp*)send(VillageBus, 
                     s_villagebus_error, 
                     L"mod_telephony has no registered handler for requested name: %S", 
                     name->buffer);  
}
Beispiel #13
0
static size_t tb_snprint_symbol(char *buff, size_t buff_sz, void *addr) {
	char *p = buff;
	char *end = buff + buff_sz;
	const struct symbol *sym;
	const struct location *loc;

	size_t lineno_len;  /* including a colon */
	const char *fname;
	size_t fname_len;
	int fname_padding;

	p += tb_safe_snprintf(p, end-p, "%p", addr);

	sym = symbol_lookup(addr);
	if (!sym)
		goto out;

	p += tb_safe_snprintf(p, end-p, " <%s+%#tx> ",
		sym->name, (char *) addr - (char *) sym->addr);

	loc = &sym->loc;
	if (!loc->file)
		goto out;

	lineno_len = tb_decimal_width(loc->line) + 1;  /* including a colon */
	if (end-p <= strlen(ELLI) + lineno_len)
		goto out;

	fname = loc->file;
	fname_len = strlen(fname);
	fname_padding = (end-p) - (fname_len + lineno_len + 1);

	if (fname_padding < 0) {
		fname += strlen(ELLI) - fname_padding;
		p += tb_safe_snprintf(p, end-p, "%s", ELLI);
	} else {
		for (int i = 0; i < fname_padding; ++i)
			p += tb_safe_snprintf(p, end-p, " ");
	}

	p += tb_safe_snprintf(p, end-p, "%s:%d", fname, loc->line);

out:
	return end-p;
}
Beispiel #14
0
/* Insere um simbolo na tabela indicada.
 * Caso o simbolo ja exista, a memoria do
 * simbolo do parametro sera liberada.
 * Returns: O simbolo passado como parametro,
 * caso este ainda nao esteja na tabela,
 * ou um ponteiro para o simbolo encontrado.
 */
Symbol *
symbol_insert(Symbol *symtab, Symbol *symbol)
{
    Symbol *sym;

    if (symbol == NULL)
        return NULL;

    sym = symbol_lookup(symtab, symbol->name);

    if (sym != NULL) {
        free(symbol->name);
        free(symbol);
        return sym;
    }

    symbol->next = symtab->next;
    symtab->next = symbol;

    return symbol;
}
Beispiel #15
0
int
symstr_bind(struct symstr *str, struct symstr *pat, struct symbol_table *stab)
{
	struct symstr_component *strc, *patc;
	struct alphabet *alpha;
	struct symbol *tsym;

	strc = str->head;
	patc = pat->head;

	for (;;) {
		if (strc == NULL && patc == NULL)
			return(SYMSTR_BIND_OK);
		if (strc == NULL)
			return(SYMSTR_BIND_STRING_TOO_SHORT);
		if (patc == NULL)
			return(SYMSTR_BIND_PATTERN_TOO_SHORT);
		/* Some bogosity checking - str should not be a pattern! */
		if (strc->alphasym != NULL) {
			return(SYMSTR_BIND_BAD_STRING);
		}
		/* Compare components. */
		if (patc->alphasym == NULL) {
			/* The literal case. */
			if (strc->sym == patc->sym) {
				strc = strc->next;
				patc = patc->next;
				continue;
			} else {
				return(SYMSTR_BIND_LITERAL_MISMATCH);
			}
		} else {
			/* The 'free variable' case. */
			if (stab == NULL) {
				/*
				 * No symbol table was passed, so we really
				 * can't bind anything - assume that this
				 * only works with a literal (no-free-vars)
				 * pattern.
				 */
				return(SYMSTR_BIND_BAD_PATTERN);
			}

			alpha = patc->alphasym->alpha;

			/* Check to see that the symbol is in the given alphabet. */
			if (alphabet_lookup(alpha, strc->sym) == NULL)
				return(SYMSTR_BIND_OUTSIDE_ALPHABET);

			/* Bind it in the given symbol table. */
			tsym = symbol_lookup(stab, patc->sym->token);
			if (tsym != NULL) {
				tsym->data = symstr_new();
				if (patc->many) {
					/* while it is in the alphabet */
					while (strc != NULL &&
					    alphabet_lookup(alpha, strc->sym) != NULL) {
						symstr_append(tsym->data, strc->sym,
						    NULL, 0, SYMSTR_OP_NOP);
						strc = strc->next;
					}
				} else {
					/* just once */
					symstr_append(tsym->data, strc->sym,
					    NULL, 0, SYMSTR_OP_NOP);
					strc = strc->next;
				}
				patc = patc->next;
			} else {
				/* Bogosity!  It *should* be there. */
				return(SYMSTR_BIND_BAD_PATTERN);
			}
		}
	}
}
Beispiel #16
0
/* Get the value in PACKAGE of the variable named by TAG.
   Passing a PACKAGE of NULL is the same as calling forms_get_tag_value. */
char *
forms_get_tag_value_in_package (Package *package, char *tag)
{
  register int i, j;
  char *name = tag;
  int value_index = 0;
  int unarray = 0;
  char *value = (char *)NULL;
  Symbol *symbol;

  /* Does this variable ref contain an array indicator? */
  for (i = 0; tag[i] != '\0'; i++)
    if (tag[i] == '[')
      {
	/* Find out if this is a real array reference. */
#if MUST_BE_DIGITS
	for (j = i + 1; isdigit (tag[j]); j++);
	if (tag[j] == ']')
	  {
	    if (j == i + 1)
	      unarray = 1;
	    else
	      value_index = atoi (tag + i + 1);

	    name = strdup (tag);
	    name[i] = '\0';
	  }
#else /* !MUST_BE_DIGITS */
	int all_digits = 1;

	for (j = i + 1; tag[j] != '\0' && tag[j] != ']'; j++)
	  if (!isdigit (tag[j]))
	    all_digits = 0;

	if (tag[j] == ']')
	  {
	    if (j == i + 1)
	      unarray = 1;
	    else
	      {
		if (all_digits)
		  value_index = atoi (tag + i + 1);
		else
		  {
		    char *tv, *nv;

		    j--;
		    tv = (char *)xmalloc (1 + (j - i));
		    strncpy (tv, tag + i + 1, j - i);
		    tv[j - i] = '\0';
		    nv = forms_get_tag_value (tv);
		    if (nv)
		      value_index = atoi (nv);
		    free (tv);
		  }
	      }
	    name = strdup (tag);
	    name[i] = '\0';
	  }
#endif /* !MUST_BE_DIGITS */
	break;
      }

  /* Get the symbol for this name. */
  if (package != (Package *)NULL)
    symbol = symbol_lookup_in_package (package, name);
  else
    symbol = symbol_lookup (name);

  if (symbol != (Symbol *)NULL)
    {
      char **values = symbol->values;

      /* Now find the appropriate variable in that realm. */
      if ((values != (char **)NULL) && (symbol->type == symtype_STRING))
	{
	  if (unarray)
	    {
	      int length = 0;
	      char *temp;

	      for (i = 0; values[i] != (char *)NULL; i++)
		length += (2 + strlen (values[i]));

	      value = (char *)xmalloc (1 + length);
	      temp = value;
	      *value = '\0';

	      for (i = 0; values[i] != (char *)NULL; i++)
		{
		  strcpy (temp, values[i]);
		  temp += strlen (values[i]);
		  if (values[i + 1] != (char *)NULL)
		    {
		      *temp = '\n';
		      temp++;
		    }
		}
	      forms_gc_remember (value);
	    }
	  else
	    {
	      if ((value_index < symbol->values_index) &&
		  (value_index > -1))
		value = symbol->values[value_index];
	    }
	}
    }

  if (name != tag) free (name);
  return (value);
}
Beispiel #17
0
unsigned_t disasm_instr(FILE* f,symbol_table_t* symtab,
			unsigned_t addr,void* mem)
{
    void* p = (void*) ((uint8_t*)mem+addr);
    int32_t  imm=0;
    int      rd=0, rs1=0, rs2=0, rs3=0;
    int      j;
    uint32_t seq;
    symbol_t* sym;
    unsigned_t addr1;


#if BYTE_ORDER == LITTLE_ENDIAN
    uint32_t ins = ((uint16_t*)p)[0];
#else
    uint32_t ins = ((uint8_t*)p)[0] | ((((uint8_t*)p)[1]) << 8);
#endif

#if defined(RV32C)
    if (OPCODE_IS_16BIT(ins)) {
	addr1 = addr+2;
	goto decode;
    }
#endif

#if BYTE_ORDER == LITTLE_ENDIAN
    ins |= (((uint16_t*)p)[1] << 16);
#else
    ins |= (((uint8_t*)p)[2] | ((((uint8_t*)p)[3]) << 8)) << 16;
#endif
    addr1 = addr+4;

#if defined(RV32C)
decode:
#endif
    if ((sym = symbol_lookup(symtab, ins)) == NULL) {
	printf("%08x: %08x ???\n", addr, ins);
	return addr1;
    }

    fprintf(f, "%08x: ", addr);
    fprintf(f, "%08x m=%08x c=%08x ", ins, sym->mask, sym->code);
    fprintf(f, "%s ", sym->name);

    // extract arguments
    switch(sym->format) {
    case FORMAT_R:
	rd = bitfield_fetch(instr_r, rd, ins);
	rs1 = bitfield_fetch(instr_r, rs1, ins);
	rs2 = bitfield_fetch(instr_r, rs2, ins);	
	break;
    case FORMAT_R4:
	rd = bitfield_fetch(instr_r4, rd, ins);
	rs1 = bitfield_fetch(instr_r4, rs1, ins);
	rs2 = bitfield_fetch(instr_r4, rs2, ins);
	rs3 = bitfield_fetch(instr_r4, rs3, ins);	
	break;
    case FORMAT_I:
	rd = bitfield_fetch(instr_i, rd, ins);
	rs1 = bitfield_fetch(instr_i, rs1, ins);
	imm = bitfield_fetch(instr_i, imm11_0, ins);
	break;
    case FORMAT_S:
	rs1 = bitfield_fetch(instr_s, rs1, ins);
	rs2 = bitfield_fetch(instr_s, rs2, ins);
	imm = get_imm_s(ins);
	break;
    case FORMAT_SB:
	imm = get_imm_sb(ins);
	rs1 = bitfield_fetch(instr_sb, rs1, ins);
	rs2 = bitfield_fetch(instr_sb, rs2, ins);
	break;
    case FORMAT_U:
	rd = bitfield_fetch(instr_u, rd, ins);
	imm = bitfield_fetch(instr_u, imm31_12, ins);
	break;
    case FORMAT_UJ:
	rd = bitfield_fetch(instr_uj, rd, ins);
	imm = get_imm_uj(ins);
	break;
    case FORMAT_CR:
	rs2 = bitfield_fetch(instr_cr, rs2, ins);
	rd = bitfield_fetch(instr_cr, rd, ins);	
	break;
    case FORMAT_CI:
	rd = bitfield_fetch(instr_ci, rd, ins);
	imm = bitfield_fetch(instr_ci, imm6_2, ins) |
	    (bitfield_fetch(instr_ci, imm12, ins) << 5);
	break;
    case FORMAT_CSS:
	rs2 = bitfield_fetch(instr_css, rs2, ins);  // 5-bit
	imm = bitfield_fetch(instr_css, imm12_7, ins);
	break;
    case FORMAT_CIW:
	rd = bitfield_fetch(instr_ciw, rd, ins);  // 3-bit
	imm = bitfield_fetch(instr_ciw, imm12_5, ins);
	break;

    case FORMAT_CL:  // compressed load
	rd = bitfield_fetch(instr_cl, rd, ins);    // 3-bit
	rs1 = bitfield_fetch(instr_cl, rs1, ins);  // 3-bit
	// 3+2 bit immediate. must be permusted in most cases
	imm = ((bitfield_fetch(instr_cl, imm12_10, ins) << 2) |
	       bitfield_fetch(instr_cl, imm6_5, ins));
	break;
    case FORMAT_CS:
	rs2 = bitfield_fetch(instr_cs, rs2, ins);
	rd = bitfield_fetch(instr_cs, rd, ins);
	// 3+2 bit immediate. must be permusted in most cases
	imm = ((bitfield_fetch(instr_cl, imm12_10, ins) << 2) |
	       bitfield_fetch(instr_cl, imm6_5, ins));
	break;
    case FORMAT_CB:
	rs1 = bitfield_fetch(instr_cb, rs1, ins);
	imm = ((bitfield_fetch(instr_cb, imm12_10, ins)<<5) |
	       bitfield_fetch(instr_cb, imm6_2, ins));
	break;
    case FORMAT_CJ:
	imm = bitfield_fetch(instr_cj, imm12_2, ins);
	break;
    default:
	break;
    }

    seq = sym->sequence;
    j = 0;

#define NEXT_ARG if (j) { fprintf(f, ","); } else { j++; }
    // format arguments according to spec
    while(seq) {
	switch(seq & 0x1f) {
	case ASM_COPY_RD_RS1:  break;
	case ASM_CONST_0: break;
	case ASM_CONST_1: break;
	case ASM_CONST_MINUS_1: break;
	case ASM_RD_X0: break;
	case ASM_RD_X1: break;
	case ASM_REG_RD:
	    NEXT_ARG;
	    fprintf(f, "%s", register_abi_name(rd));
	    break;
	case ASM_REG_FRD:
	    NEXT_ARG;
	    fprintf(f, "%s", register_fabi_name(rd));
	    break;
	case ASM_REG_CRD:
	    NEXT_ARG;
	    fprintf(f, "%s", register_abi_name(rd+8));
	    break;
	case ASM_REG_RS1:
	    NEXT_ARG;
	    fprintf(f, "%s", register_abi_name(rs1));
	    break;
	case ASM_REG_CRS1:
	    NEXT_ARG;
	    fprintf(f, "%s", register_abi_name(rs1+8));
	    break;
	case ASM_REG_FRS1:
	    NEXT_ARG;
	    fprintf(f, "%s", register_fabi_name(rs1));
	    break;
	case ASM_REG_RS2:
	    NEXT_ARG;
	    fprintf(f, "%s", register_abi_name(rs2));
	    break;
	case ASM_REG_CRS2:
	    NEXT_ARG;
	    fprintf(f, "%s", register_abi_name(rs2+8));
	    break;
	case ASM_REG_FRS2:
	    NEXT_ARG;
	    fprintf(f, "%s", register_fabi_name(rs2));
	    break;
	case ASM_REG_FRS3:
	    NEXT_ARG;
	    fprintf(f, "%s", register_fabi_name(rs3));
	    break;
	case ASM_SHAMT_5:
	    NEXT_ARG;
	    fprintf(f, "%d", imm & 0x1f);
	    break;
	case ASM_IMM_6:
	case ASM_IMM_8:
	case ASM_IMM_12:
	    NEXT_ARG;
	    fprintf(f, "%d", imm);
	    break;
	case ASM_UIMM_20:  // load upper 20 bits
	    NEXT_ARG;
	    fprintf(f, "%d", imm << 12);
	    break;
	case ASM_REL_12:
	case ASM_REL_20:
	    NEXT_ARG;
	    fprintf(f, "%d", imm);
	    break;
	case ASM_IMM_12_RS1:  // optional imm12 (or 0) and rs1
	    NEXT_ARG;
	    if (imm == 0)
		fprintf(f, "(%s)", register_abi_name(rs1));
	    else
		fprintf(f, "%d(%s)", imm, register_abi_name(rs1));
	    break;
	case ASM_IMM_IORW:  // only works for two iorw arguments!
	    NEXT_ARG;
	    fprintf(f, "%s", iorw_name[(imm>>4)&0xf]);
	    imm <<= 4;
	    break;
	default:
	    fprintf(f, "?");
	    break;
	}
	seq >>= 5;
    }
    fprintf(f, "\n");

    return addr1;
}
Beispiel #18
0
short pass2( void )
{
    short int                i;
    unsigned short           reloc;
    register SCNHDR         *sec_hdr_ptr;
    register SEC_DATA       *sec_data_ptr;
    register unsigned long  size;
    SYMBOL                  *sym;
    long                     where_we_were;
    char                     section_name[SYMNMLEN + 1];

    pass = 2;
    size = 0;
    section_name[SYMNMLEN] = '\0';

    for( i = 1, sec_hdr_ptr = &section_header[1]; i <= (short) section_cnt; 
         ++i, ++sec_hdr_ptr )
    {
         strncpy( section_name, sec_hdr_ptr->s_name, SYMNMLEN);
         sym = symbol_lookup( section_name );
	 if( NULL == sym )
          FATAL_ERROR("Couldn't find section header in symbol table - pass2.c:pass2()");
	   
         sym->value = 0L;

         if( i > 1 )
             update_symbol_table( 0L, (long) size, (long) i );

         size  += (sec_hdr_ptr->s_size
                   / ((sec_hdr_ptr->s_flags & SECTION_PM) == SECTION_PM
                      ? PM_WORD_SIZE : DM_WORD_SIZE));
    }         

    if( (obj_fd = fopen( obj_name, UPDATE_BINARY )) == NULL )
    {
          FATAL_ERROR("Error opening object file");
    }

    header_ptr = ftell( obj_fd );

    /* Seek past the object file and section headers so we can write the
     * the raw data for each section.
     */

    fseek( obj_fd, (long)(header_ptr + FILHSZ + AOUTSZ + section_cnt *
                          SCNHSZ), 0 );

    glob_sym_fd = temp_file_create( WRITE_BINARY );
    glob_sym_temp_index = num_open_files - 1;

    stat_sym_fd = temp_file_create( WRITE_BINARY );
    stat_sym_temp_index = num_open_files - 1;

    sym_fd      = temp_file_create( WRITE_BINARY );
    sym_temp_index = num_open_files - 1;

    rel_fd      = temp_file_create( WRITE_BINARY );
    rel_temp_index = num_open_files - 1;

    line_fd     = temp_file_create( WRITE_BINARY );
    line_temp_index = num_open_files - 1;

    reloc = 0;
    size = 0;
    for( i = 1, sec_hdr_ptr = &section_header[1], sec_data_ptr =
         &section_data[1]; i <= (short) section_cnt; ++i, ++sec_hdr_ptr, ++sec_data_ptr )
    {
         num_line = 0;
         num_reloc = 0;

         /* Code generation time */

         code_process( temp_file[sec_data_ptr->temp_file_index], (long) size, i );

         sec_hdr_ptr->s_nlnno = (unsigned short) num_line;
         sec_hdr_ptr->s_nreloc = (unsigned short) num_reloc;
         reloc += sec_hdr_ptr->s_nreloc;
         size  += (sec_hdr_ptr->s_size
                   / ((sec_hdr_ptr->s_flags & SECTION_PM) == SECTION_PM
                      ? PM_WORD_SIZE : DM_WORD_SIZE));
    }

    fixup_symbol_table( sym_fd );
    flush_files();

    /* Write the finished table to the symbol table file */

    if( (glob_sym_fd = fopen(temp_file[glob_sym_temp_index], READ_BINARY )) == NULL )
         FATAL_ERROR("Error opening global symbol temp file");

    if( (stat_sym_fd = fopen(temp_file[stat_sym_temp_index], READ_BINARY )) == NULL )
         FATAL_ERROR("Error opening static symbol temp file");

    dump_symbols();
    fclose( glob_sym_fd );
    fclose( stat_sym_fd );

    fflush( sym_fd );
    fclose( sym_fd );

    /* Write the object file header and the section headers */

    where_we_were = ftell( obj_fd );
    fseek( obj_fd, 0L, 0 );
    object_headers();

    fseek( obj_fd, where_we_were, 0 );

    /* Write the relocation info to the object file */

    if( (rel_fd = fopen(temp_file[rel_temp_index], READ_BINARY)) == NULL )
         FATAL_ERROR("Error opening temp relocation file");
    write_all_relocation_info( (long) reloc );
    fclose( rel_fd );

    if( !check_if_errors() )
    {
        /* Append the line number entries, symbol table, and string table
         * to the end of the object file.
         */

        copy_section( temp_file[line_temp_index] );
        copy_section( temp_file[sym_temp_index] );

	write_string_table();

        fflush( obj_fd );
        fclose( obj_fd );

        delete_temp_files();
        return( 0 );
    }
    else
    {
        asm_exit( FATAL );
    }
}