Example #1
0
void
vari_def (void)
{
  firstentry = symtab_nextentry;
  match (VAR);
  {
    symtab_add (lexeme);
  }
  match (ID);
  while (lookahead == ',')
    {
      match (',');
      {
	symtab_add (lexeme);
      }
      match (ID);
    }
  match (':');
  vartype ();
  match (';');
  while (lookahead == ID)
    {
      match (ID);
      while (lookahead == ',')
	{
	  match (',');
	  match (ID);
	}
      match (':');
      vartype ();
      match (';');
    }
}
Example #2
0
void check_declr(SymTab *st, Declr* d) {
  switch(d->tag) {
    case DECLR_VAR:
      {
        if(st->prev)
	  check_array_sizes(d->type);
        else
          check_array_empty(d->type);
	if(!symtab_add(st, d))
	  print_error("double declaration of variable", d->line);
	break;
      }
    case DECLR_FUNC:
      {
	check_array_empty(d->type);
	if(d->u.func.block) {
	  Declr *proto;
	  SymTab *param;
	  
	  proto = symtab_find(st, d->u.func.name);
	  if(!proto) {
	    symtab_add(st, d);
	    proto = d;
	  } else if(proto->u.func.block) {
	    print_error("double declaration of function", d->line);
	  } else {
	    proto->u.func.block = d->u.func.block;
	  }
	  return_type = d->type;
	  param = symtab_new(st);
	  check_paramlist(param, proto->u.func.params, d->line);
	  check_block(param, proto->u.func.block);
	  symtab_free(param);
	}
	else {
	  if(!symtab_add(st, d))
	    print_error("double declaration of function prototype", d->line);
	}
	break;
      }
    default: print_error("bug in compiler!", 0);
  }
}
void
varspecs(void)
{
     /**/ int       initial,
                    final /**/;
    while (lookahead == VAR) {
        match(VAR);
        do {
             /**/ initial = symtab_nextentry /**/;
             /**/ final = symtab_add(lexeme) /**/;
            match(ID);
            while (lookahead == ',') {
                match(',');
                 /**/ final = symtab_add(lexeme) /**/;
                match(ID);
            }
            match(':');
            typespec(VARIABLE, initial, final);
            match(';');
        } while (lookahead == ID);
Example #4
0
bool ffi_get_decl(typecheck_t* t, ast_t* ast, ast_t** out_decl,
  pass_opt_t* opt)
{
  pony_assert(t != NULL);
  pony_assert(ast != NULL);
  pony_assert(out_decl != NULL);

  const char* ffi_name = ast_name(ast_child(ast));

  // Get the symbol table for our containing ifdef (if any) directly. We can't
  // just search up through scopes as normal since FFI declarations in outer
  // scopes may not be valid within our ifdef.
  ast_t* ifdef = t->frame->ifdef_clause;
  pony_assert(ifdef != NULL);

  symtab_t* symtab = ast_get_symtab(ifdef);
  sym_status_t status;
  ast_t* decl = symtab_find(symtab, ffi_name, &status);

  if(status == SYM_ERROR)
    // We've already found an error with that FFI name in this context.
    return false;

  if(status == SYM_NONE)
  {
    // We've not looked that up yet.
    pony_assert(decl == NULL);
    if(!find_ffi_decl(ast, t->frame->package, t->frame->ifdef_cond, &decl, opt))
    {
      // That went wrong. Record that so we don't try again.
      symtab_add(symtab, ffi_name, NULL, SYM_ERROR);
      return false;
    }

    // Store declaration found for next time, including if we found nothing.
    symtab_add(symtab, ffi_name, decl, SYM_FFIDECL);
  }

  *out_decl = decl;
  return true;
}
Example #5
0
void check_paramlist(SymTab *st, DeclrListNode* pln, int line) {
  while(pln) {
    if(pln->declr == NULL) {
      if(pln->next != NULL)
        print_error("... must be the last parameter of a function", line);
      break;
    } else {
      check_array_empty(pln->declr->type);
      if(!symtab_add(st, pln->declr)) print_error("parameter declared twice", line);
      pln = pln->next;
    }
  }
}
Example #6
0
// Add a sub-tree name definition
static bool add_subtree_name(build_parser_t* builder, const char* name,
  ast_t* subtree)
{
  assert(builder != NULL);
  assert(builder->defs != NULL);

  if(!symtab_add(builder->defs, name, subtree, SYM_NONE))
  {
    build_error(builder, "Multiple {def %s} attributes", name);
    return false;
  }

  return true;
}
Example #7
0
bool symtab_merge_public(symtab_t* dst, symtab_t* src)
{
  size_t i = HASHMAP_BEGIN;
  symbol_t* sym;

  while((sym = symtab_next(src, &i)) != NULL)
  {
    if((sym->name[0] == '_') || (sym->status == SYM_NOCASE))
      continue;

    if(!symtab_add(dst, sym->name, sym->value, sym->status))
      return false;
  }

  return true;
}
Example #8
0
bool symtab_merge_public(symtab_t* dst, symtab_t* src)
{
  size_t i = HASHMAP_BEGIN;
  symbol_t* sym;

  while((sym = symtab_next(src, &i)) != NULL)
  {
    if(is_name_private(sym->name) ||
      (sym->status == SYM_NOCASE) ||
      !strcmp(sym->name, "Main"))
      continue;

    if(!symtab_add(dst, sym->name, sym->def, sym->status))
      return false;
  }

  return true;
}
Example #9
0
// Add the given method to the relevant name list in the given symbol table
static bool add_method_to_list(ast_t* method, methods_t* method_info,
  const char *entity_name)
{
  assert(method != NULL);
  assert(method_info != NULL);
  assert(entity_name != NULL);

  const char* name = ast_name(ast_childidx(method, 1));
  assert(name != NULL);

  symtab_t* symtab = method_info->symtab;
  assert(symtab != NULL);

  // Entity doesn't yet have method, add it to our list for later
  ast_t* list = (ast_t*)symtab_find(symtab, name, NULL);

  if(list == NULL)
  {
    ast_t* case_clash = (ast_t*)symtab_find_case(symtab, name, NULL);

    if(case_clash != NULL)
    {
      ast_error(case_clash, "in %s method name differs only in case",
        entity_name);
      ast_error(method, "previous definition is here");
      return false;
    }

    // First instance of this name
    list = ast_blank(TK_ID);
    ast_set_name(list, name);
    symtab_add(symtab, name, (void*)list, SYM_NONE);

    if(method_info->last_list == NULL)
      ast_add(method_info->name_lists, list);
    else
      ast_add_sibling(method_info->last_list, list);

    method_info->last_list = list;
  }

  ast_add(list, method);
  return true;
}
Example #10
0
bool ast_set(ast_t* ast, const char* name, ast_t* value, sym_status_t status,
  bool allow_shadowing)
{
  while(ast->symtab == NULL)
    ast = ast->parent;

  if(allow_shadowing)
  {
    // Only check the local scope.
    if(symtab_find_case(ast->symtab, name, NULL) != NULL)
      return false;
  } else {
    // Check the local scope and all parent scopes.
    if(ast_get_case(ast, name, NULL) != NULL)
      return false;
  }

  return symtab_add(ast->symtab, name, value, status);
}
Example #11
0
// Process all our sub-tree references
static bool process_refs(build_parser_t* builder)
{
  assert(builder != NULL);
  assert(builder->defs != NULL);

  for(builder_ref_t* p = builder->refs; p != NULL; p = p->next)
  {
    assert(p->name != NULL);
    assert(p->node != NULL);

    ast_t* subtree = (ast_t*)symtab_find(builder->defs, p->name, NULL);

    if(subtree == NULL)
    {
      build_error(builder, "Attribute {def %s} not found", p->name);
      return false;
    }

    if(p->symtab == NULL)
    {
      // Set node data
      ast_setdata(p->node, subtree);
    }
    else
    {
      // Add subtree to node's symtab
      symtab_t* symtab = ast_get_symtab(p->node);
      assert(symtab != NULL);
      if(!symtab_add(symtab, p->symtab, subtree, SYM_NONE))
      {
        build_error(builder, "Duplicate name %s in symbol table", p->name);
        return false;
      }
    }
  }

  return true;
}
Example #12
0
/*
 * XXX: btrie插入操作有其特殊性
 *      对rule匹配规则而言,它是松散的,count表示了str[]的总项数,valids表示有效的str项,end_index
 *            则表示最后一个有效str项的索引值,end_index可能大于valids。
 *      对host匹配规则而言,它是连续的,count依然表示str[]的总项数,但由于是连续,end_index总是等于
 *            valids-1。
 *      valids用于指导分配btrie_node,end_index则用于最后的检查工作。
 */
btrie_node_t *btrie_insert(btrie_ctx_t *ctx,
                           btrie_node_t **ptr_root,
                           unsigned long count,
                           string_t str[],
                           unsigned long valids,
                           int end_index)
{
    int node_cnt = 0, node_used = 0;
    btrie_node_t *new_node_array, *node, *wildcard;
    int i, found = 0;
    btrie_node_t **proot, *root, *ret = NULL;
    btrie_node_t **pcurr, *curr; /* 注意: 用于算法内部临时查找,而非当前处理节点 */

    if (ctx == NULL || ptr_root == NULL || count == 0 || str == NULL || valids > count || valids == 0) {
        return NULL;
    }
    if (end_index < 0 || end_index >= count) {
        return NULL;
    }

    node_cnt = valids * 2; /* 预留通配符节点,节点分配数量翻倍 */
    /* 注意: new_node_array必须是连续分配的,且严格的从头开始连续使用,以便连续释放空闲的 */
    new_node_array = btrie_node_alloc(ctx, node_cnt);
    if (new_node_array == NULL) {
        NOTICE();
        return NULL;
    }

    proot = ptr_root; /* 存放root的位置,方便修改root的值 */
    root = *proot;
    for (i = 0; i < count; i++) {
        if (str[i].len == 0) {
            continue;
        }
        if (str[i].len == BTRIE_NO_VALUE_MAGIC_LEN) {
            /* 对str是no val型,恢复其正确值0。 */
            str[i].len = 0;
        }
again:
        if (node_used >= node_cnt) {
            /* BUG: 使用量已经超过分配的数量 */
            BUG();
            return NULL;
        }
        if (root == NULL) {
            node = &new_node_array[node_used];
            node->index = i;
            if (str[i].len == BTRIE_WILDCARD_MAGIC_LEN) {
                node->flags = BTRIE_FLAG_WILDCARD;
            } else {
                if ((str[i].len > 0)
                        && (symtab_add(ctx->symtab, &str[i], &node->str) != 0)) {
                    goto err_out;
                }
            }
            node_used++;
            *proot = node;

            ret = node;
            proot = &node->child;
            root = node->child;
        } else if (root->index == i) {
            for (pcurr = proot, curr = root;
                    (curr != NULL) && (curr->flags != BTRIE_FLAG_WILDCARD);
                    pcurr = &curr->sibling, curr = curr->sibling) {
                if (string_is_equal(&curr->str, &str[i])) {
                    found = 1;
                    break;
                }
            }
            if (found) {
                found = 0;
                proot = &curr->child;
                root = curr->child;
                ret = curr;
                continue;
            }

            if (str[i].len == BTRIE_WILDCARD_MAGIC_LEN) {
                if (curr == NULL) {
                    /* 通配符节点不存在,首先创建通配符节点 */
                    node = &new_node_array[node_used];
                    node->index = i;
                    node->flags = BTRIE_FLAG_WILDCARD;
                    node_used++;
                    /* 然后将通配符节点加入树中 */
                    node->sibling = curr;
                    *pcurr = node;
                    curr = node;
                }

                proot = &curr->child;
                root = curr->child;
                ret = curr;
                continue;
            } else {
                node = &new_node_array[node_used];
                node->index = i;
                if ((str[i].len > 0)
                        && (symtab_add(ctx->symtab, &str[i], &node->str) != 0)) {
                    goto err_out;
                }
                node_used++;

                node->sibling = curr;
                *pcurr = node;
                proot = &node->child;
                root = node->child;
                ret = node;
                continue;
            }
        } else if (root->index > i) {
            /* root节点等级比待加入节点低 */
            if (str[i].len == BTRIE_WILDCARD_MAGIC_LEN) {
                /* XXX: 目前只有host涉及到通配符,其不可能进入本分支 */
                BUG();
                goto err_out;
            }
            node = &new_node_array[node_used];
            node->index = i;
            if ((str[i].len > 0)
                    && (symtab_add(ctx->symtab, &str[i], &node->str) != 0)) {
                goto err_out;
            }
            node_used++;

            wildcard = &new_node_array[node_used++];
            wildcard->flags = BTRIE_FLAG_WILDCARD;
            wildcard->index = i;

            node->sibling = wildcard;
            wildcard->child = root;
            *proot = node;

            ret = node;
            proot = &node->child;
            root = node->child;
        } else {
            /* root节点等级比待加入节点高 root->index < i */
            if (str[i].len == BTRIE_WILDCARD_MAGIC_LEN) {
                /* XXX: 目前只有host涉及到通配符,其不可能进入本分支 */
                BUG();
                goto err_out;
            }
            for (pcurr = proot, curr = root;
                    (curr != NULL) && (curr->flags != BTRIE_FLAG_WILDCARD);
                    pcurr = &curr->sibling, curr = curr->sibling) {
                (void)0;
            }
            if (curr == NULL) {
                wildcard = &new_node_array[node_used++];
                wildcard->flags = BTRIE_FLAG_WILDCARD;
                wildcard->index = root->index;

                *pcurr = wildcard;
                curr = wildcard;
            }
            proot = &curr->child;
            root = curr->child;
            goto again;
        }
    }

    /* 对ret的有效性做检查 */
    if ((ret != NULL) && (ret->index != end_index)) {
        /* BUG: 竟然有ret,但还未到末尾的节点 */
        BUG();
        goto err_out;
    }
    /* XXX: 如果添加相同的RULE或者HOST,则ret中data不为NULL,认定为出错 */
    if ((ret != NULL) && (ret->data != NULL)) {
        NOTICE();
        goto err_out;
    }

    /* 释放未使用的mnode */
    btrie_node_free(ctx, (node_cnt - node_used));

    return ret;

err_out:
    /* 释放掉还未加入查找树中的节点,已加入的就不删除了 */
    btrie_node_free(ctx, (node_cnt - node_used));

    return NULL;
}
Example #13
0
void fold_expr_funcall(expr *e, symtable *stab)
{
	decl *df;
	funcargs *args_exp;

	if(expr_kind(e->expr, identifier) && e->expr->spel){
		char *const sp = e->expr->spel;

		e->sym = symtab_search(stab, sp);
		if(!e->sym){
			df = decl_new_where(&e->where);

			df->type->primitive = type_int;
			df->type->spec     |= spec_extern;

			cc1_warn_at(&e->where, 0, WARN_IMPLICIT_FUNC, "implicit declaration of function \"%s\"", sp);

			df->spel = sp;

			df->funcargs = funcargs_new();

			if(e->funcargs)
				/* set up the funcargs as if it's "x()" - i.e. any args */
				function_empty_args(df->funcargs);

			e->sym = symtab_add(symtab_root(stab), df, sym_global, SYMTAB_WITH_SYM, SYMTAB_PREPEND);
		}else{
			df = e->sym->decl;
		}

		fold_expr(e->expr, stab);
	}else{
		fold_expr(e->expr, stab);

		/*
		 * convert int (*)() to remove the deref
		 */
		if(decl_is_func_ptr(e->expr->tree_type)){
			/* XXX: memleak */
			e->expr = e->expr->lhs;
			fprintf(stderr, "FUNCPTR\n");
		}else{
			fprintf(stderr, "decl %s\n", decl_to_str(e->expr->tree_type));
		}

		df = e->expr->tree_type;

		if(!decl_is_callable(df)){
			die_at(&e->expr->where, "expression %s (%s) not callable",
					e->expr->f_str(),
					decl_to_str(df));
		}
	}

	e->tree_type = decl_copy(df);
	/*
	 * int (*x)();
	 * (*x)();
	 * evaluates to tree_type = int;
	 */
	decl_func_deref(e->tree_type);


	if(e->funcargs){
		expr **iter;
		for(iter = e->funcargs; *iter; iter++)
			fold_expr(*iter, stab);
	}

	/* func count comparison, only if the func has arg-decls, or the func is f(void) */
	args_exp = decl_funcargs(e->tree_type);

	UCC_ASSERT(args_exp, "no funcargs for decl %s", df->spel);

	if(args_exp->arglist || args_exp->args_void){
		expr **iter_arg;
		decl **iter_decl;
		int count_decl, count_arg;

		count_decl = count_arg = 0;

		for(iter_arg  = e->funcargs;       iter_arg  && *iter_arg;  iter_arg++,  count_arg++);
		for(iter_decl = args_exp->arglist; iter_decl && *iter_decl; iter_decl++, count_decl++);

		if(count_decl != count_arg && (args_exp->variadic ? count_arg < count_decl : 1)){
			die_at(&e->where, "too %s arguments to function %s (got %d, need %d)",
					count_arg > count_decl ? "many" : "few",
					df->spel, count_arg, count_decl);
		}

		if(e->funcargs){
			funcargs *argument_decls = funcargs_new();

			for(iter_arg = e->funcargs; *iter_arg; iter_arg++)
				dynarray_add((void ***)&argument_decls->arglist, (*iter_arg)->tree_type);

			fold_funcargs_equal(args_exp, argument_decls, 1, &e->where, "argument", df->spel);
			funcargs_free(argument_decls, 0);
		}
	}
}
Example #14
0
File: ldrdf.c Project: aosm/nasm
/*
 * processmodule()
 *
 * step through each segment, determine what exactly we're doing with
 * it, and if we intend to keep it, determine (a) which segment to
 * put it in and (b) whereabouts in that segment it will end up.
 * (b) is fairly easy, because we're now keeping track of how big each
 * segment in our output file is...
 */
void processmodule(const char *filename, struct modulenode *mod)
{
    struct segconfig sconf;
    int seg, outseg;
    void *header;
    rdfheaderrec *hr;
    long bssamount = 0;
    int bss_was_referenced = 0;

    for (seg = 0; seg < mod->f.nsegs; seg++) {
        /*
         * get the segment configuration for this type from the segment
         * table. getsegconfig() is a macro, defined in ldsegs.h.
         */
        getsegconfig(sconf, mod->f.seg[seg].type);

        if (options.verbose > 1) {
            printf("%s %04x [%04x:%10s] ", filename,
                   mod->f.seg[seg].number, mod->f.seg[seg].type,
                   sconf.typedesc);
        }
        /*
         * sconf->dowhat tells us what to do with a segment of this type.
         */
        switch (sconf.dowhat) {
        case SEG_IGNORE:
            /*
             * Set destination segment to -1, to indicate that this segment
             * should be ignored for the purpose of output, ie it is left
             * out of the linked executable.
             */
            mod->seginfo[seg].dest_seg = -1;
            if (options.verbose > 1)
                printf("IGNORED\n");
            break;

        case SEG_NEWSEG:
            /*
             * The configuration tells us to create a new segment for
             * each occurrence of this segment type.
             */
            outseg = allocnewseg(sconf.mergetype,
                                 mod->f.seg[seg].reserved);
            mod->seginfo[seg].dest_seg = outseg;
            mod->seginfo[seg].reloc = 0;
            outputseg[outseg].length = mod->f.seg[seg].length;
            if (options.verbose > 1)
                printf("=> %04x:%08lx (+%04lx)\n", outseg,
                       mod->seginfo[seg].reloc, mod->f.seg[seg].length);
            break;

        case SEG_MERGE:
            /*
             * The configuration tells us to merge the segment with
             * a previously existing segment of type 'sconf.mergetype',
             * if one exists. Otherwise a new segment is created.
             * This is handled transparently by 'findsegment()'.
             */
            outseg = findsegment(sconf.mergetype,
                                 mod->f.seg[seg].reserved);
            mod->seginfo[seg].dest_seg = outseg;

            /*
             * We need to add alignment to these segments.
             */
            if (outputseg[outseg].length % options.align != 0)
                outputseg[outseg].length +=
                    options.align -
                    (outputseg[outseg].length % options.align);

            mod->seginfo[seg].reloc = outputseg[outseg].length;
            outputseg[outseg].length += mod->f.seg[seg].length;

            if (options.verbose > 1)
                printf("=> %04x:%08lx (+%04lx)\n", outseg,
                       mod->seginfo[seg].reloc, mod->f.seg[seg].length);
        }

    }

    /*
     * extract symbols from the header, and dump them into the
     * symbol table
     */
    header = malloc(mod->f.header_len);
    if (!header) {
        fprintf(stderr, "ldrdf: not enough memory\n");
        exit(1);
    }
    if (rdfloadseg(&mod->f, RDOFF_HEADER, header)) {
        rdfperror("ldrdf", filename);
        exit(1);
    }

    while ((hr = rdfgetheaderrec(&mod->f))) {
        switch (hr->type) {
        case RDFREC_IMPORT:    /* imported symbol */
        case RDFREC_FARIMPORT:
            /* Define with seg = -1 */
            symtab_add(hr->i.label, -1, 0);
            break;

        case RDFREC_GLOBAL:{   /* exported symbol */
                int destseg;
                long destreloc;

                if (hr->e.segment == 2) {
                    bss_was_referenced = 1;
                    destreloc = bss_length;
                    if (destreloc % options.align != 0)
                        destreloc +=
                            options.align - (destreloc % options.align);
                    destseg = 2;
                } else {
                    if ((destseg =
                         mod->seginfo[(int)hr->e.segment].dest_seg) == -1)
                        continue;
                    destreloc = mod->seginfo[(int)hr->e.segment].reloc;
                }
                symtab_add(hr->e.label, destseg, destreloc + hr->e.offset);
                break;
            }

        case RDFREC_BSS:       /* BSS reservation */
            /*
             * first, amalgamate all BSS reservations in this module
             * into one, because we allow this in the output format.
             */
            bssamount += hr->b.amount;
            break;

        case RDFREC_COMMON:{   /* Common variable */
                symtabEnt *ste = symtabFind(symtab, hr->c.label);

                /* Is the symbol already in the table? */
                if (ste)
                    break;

                /* Align the variable */
                if (bss_length % hr->c.align != 0)
                    bss_length += hr->c.align - (bss_length % hr->c.align);
                if (options.verbose > 1) {
                    printf("%s %04x common '%s' => 0002:%08lx (+%04lx)\n",
                           filename, hr->c.segment, hr->c.label,
                           bss_length, hr->c.size);
                }

                symtab_add(hr->c.label, 2, bss_length);
                mod->bss_reloc = bss_length;
                bss_length += hr->c.size;
                break;
            }
        }
    }

    if (bssamount != 0 || bss_was_referenced) {
        /*
         * handle the BSS segment - first pad the existing bss length
         * to the correct alignment, then store the length in bss_reloc
         * for this module. Then add this module's BSS length onto
         * bss_length.
         */
        if (bss_length % options.align != 0)
            bss_length += options.align - (bss_length % options.align);

        mod->bss_reloc = bss_length;
        if (options.verbose > 1) {
            printf("%s 0002 [            BSS] => 0002:%08lx (+%04lx)\n",
                   filename, bss_length, bssamount);
        }
        bss_length += bssamount;
    }
#ifdef STINGY_MEMORY
    /*
     * we free the header buffer here, to save memory later.
     * this isn't efficient, but probably halves the memory usage
     * of this program...
     */
    mod->f.header_loc = NULL;
    free(header);

#endif

}