static attribute *parse_attr_cleanup(symtable *scope, const char *ident) { char *sp; where ident_loc; attribute *attr = NULL; struct symtab_entry ent; (void)ident; EAT(token_open_paren); if(curtok != token_identifier) die_at(NULL, "identifier expected for cleanup function"); where_cc1_current(&ident_loc); sp = token_current_spel(); EAT(token_identifier); if(symtab_search(scope, sp, NULL, &ent) && ent.type == SYMTAB_ENT_DECL) { attr = attribute_new(attr_cleanup); attr->bits.cleanup = ent.bits.decl; } else { warn_at_print_error(&ident_loc, "function '%s' not found", sp); fold_had_error = 1; } EAT(token_close_paren); return attr; }
static int symtab_get_matches(jl_sym_t *tree, const char *str, char **answer) { int x, plen, count=0; ios_t ans; plen = strlen(str); while (tree != NULL) { x = common_prefix(str, tree->name); if (x == plen) { ios_mem(&ans, 0); symtab_search(tree, &count, &ans, str, plen); size_t nb; *answer = ios_takebuf(&ans, &nb); return count; } else { x = strcmp(str, tree->name); if (x < 0) tree = tree->left; else tree = tree->right; } } return 0; }
static void check_implicit_funcall(expr *e, symtable *stab, char **const psp) { struct symtab_entry ent; funcargs *args; decl *df, *owning_func; type *func_ty; if(e->expr->in_parens || !expr_kind(e->expr, identifier) /* not folded yet, hence no 'e->expr->bits.ident.type != IDENT_NORM' */ /* get the spel that parse stashes in the identifier expr: */ || !((*psp) = e->expr->bits.ident.bits.ident.spel)) { return; } /* check for implicit function */ if(symtab_search(stab, *psp, NULL, &ent) && ent.type == SYMTAB_ENT_DECL) { e->expr->bits.ident.bits.ident.sym = ent.bits.decl->sym; return; } args = funcargs_new(); /* set up the funcargs as if it's "x()" - i.e. any args */ funcargs_empty(args); func_ty = type_func_of( type_nav_btype(cc1_type_nav, type_int), args, symtab_new(stab, &e->where) /*new symtable for args*/); cc1_warn_at(&e->expr->where, implicit_func, "implicit declaration of function \"%s\"", *psp); df = decl_new(); memcpy_safe(&df->where, &e->where); df->ref = func_ty; df->spel = e->expr->bits.ident.bits.ident.spel; df->flags |= DECL_FLAGS_IMPLICIT; fold_decl(df, stab); /* update calling conv, for e.g. */ df->sym->type = sym_global; e->expr->bits.ident.bits.ident.sym = df->sym; e->expr->tree_type = func_ty; owning_func = symtab_func(stab); if(owning_func) symtab_insert_before(symtab_root(stab), owning_func, df); else symtab_add_to_scope(symtab_root(stab), df); /* function call at global scope */ }
static int symtab_get_matches(jl_sym_t *tree, const char *str, char **answer) { int x, plen, count=0; ios_t ans; // given str "X.Y.a", set module := X.Y and name := "a" jl_module_t *module = NULL; char *name = NULL, *strcopy = strdup(str); for (char *s=strcopy, *r=NULL;; s=NULL) { char *t = strtok_r(s, ".", &r); if (!t) { if (str[strlen(str)-1] == '.') { // this case is "Module." if (name) { if (!module) module = jl_current_module; module = find_submodule_named(module, name); if (!module) goto symtab_get_matches_exit; } name = ""; } break; } if (name) { if (!module) module = jl_current_module; module = find_submodule_named(module, name); if (!module) goto symtab_get_matches_exit; } name = t; } if (!name) goto symtab_get_matches_exit; plen = strlen(name); while (tree != NULL) { x = common_prefix(name, tree->name); if (x == plen) { ios_mem(&ans, 0); symtab_search(tree, &count, &ans, module, str, name, plen); size_t nb; *answer = ios_takebuf(&ans, &nb); break; } else { x = strcmp(name, tree->name); if (x < 0) tree = tree->left; else tree = tree->right; } } symtab_get_matches_exit: free(strcopy); return count; }
static void symtab_search(jl_sym_t *tree, int *pcount, ios_t *result, const char *prefix, int plen) { do { if (common_prefix(prefix, tree->name) == plen && jl_boundp(jl_system_module, tree)) { ios_puts(tree->name, result); ios_putc('\n', result); (*pcount)++; } if (tree->left) symtab_search(tree->left, pcount, result, prefix, plen); tree = tree->right; } while (tree != NULL); }
static void symtab_search(jl_sym_t *tree, int *pcount, ios_t *result, jl_module_t *module, const char *str, const char *prefix, int plen) { do { if (common_prefix(prefix, tree->name) == plen && (module ? jl_defines_or_exports_p(module, tree) : jl_boundp(jl_current_module, tree))) { ios_puts(str, result); ios_puts(tree->name + plen, result); ios_putc('\n', result); (*pcount)++; } if (tree->left) symtab_search(tree->left, pcount, result, module, str, prefix, plen); tree = tree->right; } while (tree != NULL); }
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); } } }