enum funcargs_cmp funcargs_cmp(funcargs *args_to, funcargs *args_from) { int count_to; int count_from; if(args_to == args_from) return FUNCARGS_EXACT_EQUAL; if(FUNCARGS_EMPTY_NOVOID(args_to) || FUNCARGS_EMPTY_NOVOID(args_from)) { /* a() or b() */ return FUNCARGS_IMPLICIT_CONV; } count_to = dynarray_count(args_to->arglist); count_from = dynarray_count(args_from->arglist); /* still do prototype checks for old_proto functions */ /*if(args_to->args_old_proto || args_from->args_old_proto) return FUNCARGS_IMPLICIT_CONV;*/ if(!(args_to->variadic ? count_to <= count_from : count_to == count_from)) return FUNCARGS_MISMATCH_COUNT; if(count_to){ unsigned i; for(i = 0; args_to->arglist[i]; i++){ switch(type_cmp(args_to->arglist[i]->ref, args_from->arglist[i]->ref, 0)){ case TYPE_EQUAL: case TYPE_QUAL_ADD: /* f(const int) and f(int) */ case TYPE_QUAL_SUB: /* f(int) and f(const int) */ case TYPE_EQUAL_TYPEDEF: break; case TYPE_QUAL_POINTED_ADD: case TYPE_QUAL_POINTED_SUB: case TYPE_QUAL_NESTED_CHANGE: case TYPE_CONVERTIBLE_EXPLICIT: case TYPE_CONVERTIBLE_IMPLICIT: case TYPE_NOT_EQUAL: return FUNCARGS_MISMATCH_TYPES; } } } return FUNCARGS_EXACT_EQUAL; }
static char *find_arg(macro *m, char *word, char **args, int *alloced) { *alloced = 0; if(!strcmp(word, VA_ARGS_STR)){ if(args){ size_t i = dynarray_count(m->args); /* if count(args) < i then args[i] is NULL, * which str_join handles */ *alloced = 1; return str_join(args + i, ", "); }else{ return ""; } } if(m->args){ char *w; size_t i; for(i = 0; (w = m->args[i]); i++) if(!strcmp(w, word)) return args[i]; /* don't expand */ } /* word not found, we use the given identifier */ return word; }
/* * Function: DHCPLeaseListWrite * * Purpose: * Write the last DHCP lease in the list for the given interface/client_id. * We only save the last (current) lease. See the comments for * DHCPLeaseListRead above for more information. */ void DHCPLeaseListWrite(DHCPLeaseListRef list_p, const char * ifname, uint8_t cid_type, const void * cid, int cid_length) { int count; char filename[PATH_MAX]; CFDictionaryRef lease_dict; DHCPLeaseRef lease_p; if (DHCPLeaseListGetPath(ifname, cid_type, cid, cid_length, filename, sizeof(filename)) == FALSE) { return; } DHCPLeaseListRemoveStaleLeases(list_p); count = dynarray_count(list_p); if (count == 0) { unlink(filename); return; } lease_p = dynarray_element(list_p, count - 1); lease_dict = DHCPLeaseCopyDictionary(lease_p); if (my_CFPropertyListWriteFile(lease_dict, filename, 0644) < 0) { /* * An ENOENT error is expected on a read-only filesystem. All * other errors should be reported. */ if (errno != ENOENT) { my_log(LOG_ERR, "my_CFPropertyListWriteFile(%s) failed, %s", filename, strerror(errno)); } } my_CFRelease(&lease_dict); return; }
char *func_mangle(const char *name, type *fnty) { char *pre, suff[8]; pre = fopt_mode & FOPT_LEADING_UNDERSCORE ? "_" : ""; *suff = '\0'; if(fnty){ funcargs *fa = type_funcargs(fnty); switch(fa->conv){ case conv_fastcall: pre = "@"; case conv_stdcall: snprintf(suff, sizeof suff, "@%d", dynarray_count(fa->arglist) * platform_word_size()); case conv_x64_sysv: case conv_x64_ms: case conv_cdecl: break; } } if(*pre || *suff){ return ustrprintf("%s%s%s", pre, name, suff); } return (char *)name; }
/* * Function: DHCPLeaseListRemoveStaleLeases * Purpose: * Scans the list of leases removing any that are no longer valid. */ static void DHCPLeaseListRemoveStaleLeases(DHCPLeaseListRef list_p) { int count; absolute_time_t current_time; int i; count = dynarray_count(list_p); if (count == 0) { return; } current_time = timer_current_secs(); i = 0; while (i < count) { DHCPLeaseRef lease_p = dynarray_element(list_p, i); /* check the lease expiration */ if (lease_p->lease_length != DHCP_INFINITE_LEASE && current_time >= (lease_p->lease_start + lease_p->lease_length)) { /* lease is expired */ if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "Removing Stale Lease " IP_FORMAT " Router " IP_FORMAT, IP_LIST(&lease_p->our_ip), IP_LIST(&lease_p->router_ip)); } dynarray_free_element(list_p, i); count--; } else { i++; } } return; }
/* checks case duplicates, not default */ static void fold_switch_dups(stmt *sw) { typedef int (*qsort_f)(const void *, const void *); struct { numeric start, end; stmt *cse; } *vals; size_t n = dynarray_count(sw->bits.switch_.cases); size_t i = 0; stmt **titer; if(n == 0) return; vals = malloc(n * sizeof *vals); /* gather all switch values */ ITER_SWITCH(sw, titer){ stmt *cse = *titer; vals[i].cse = cse; const_fold_integral(cse->expr, &vals[i].start); if(stmt_kind(cse, case_range)) const_fold_integral(cse->expr2, &vals[i].end); else memcpy(&vals[i].end, &vals[i].start, sizeof vals[i].end); i++; }
static int check_arg_counts( funcargs *args_from_decl, unsigned count_decl, expr **exprargs, expr *fnexpr, char *sp) { where *const loc = &fnexpr->where; /* this block is purely count checking */ if(!FUNCARGS_EMPTY_NOVOID(args_from_decl)){ const unsigned count_arg = dynarray_count(exprargs); if(count_decl != count_arg && (args_from_decl->variadic ? count_arg < count_decl : 1)) { decl *call_decl; /* may be args_old_proto but also args_void if copied from * another prototype elsewhere */ int warn = args_from_decl->args_old_proto && !args_from_decl->args_void; int warning_emitted = 1; #define common_warning \ "too %s arguments to function %s%s(got %d, need %d)",\ count_arg > count_decl ? "many" : "few", \ sp ? sp : "", \ sp ? " " : "", \ count_arg, count_decl if(warn){ warning_emitted = cc1_warn_at(loc, funcall_argcount, common_warning); }else{ warn_at_print_error(loc, common_warning); } #undef common_warning if(warning_emitted && (call_decl = expr_to_declref(fnexpr->expr, NULL))) { note_at(&call_decl->where, "'%s' declared here", call_decl->spel); } if(!warn){ fold_had_error = 1; return 1; } } }else if(args_from_decl->args_void_implicit && exprargs){ cc1_warn_at(loc, funcall_argcount, "too many arguments to implicitly (void)-function"); } return 0; }
/* * Function: ifl_first_broadcast_inet * * Purpose: * Return the first non-loopback, broadcast capable interface. */ interface_t * ifl_first_broadcast_inet(interface_list_t * list_p) { int i; for (i = 0; i < list_p->count; i++) { interface_t * if_p = list_p->list + i; if (dynarray_count(&if_p->inet) > 0 && !(if_p->flags & IFF_LOOPBACK) && (if_p->flags & IFF_BROADCAST)) return (list_p->list + i); } return (NULL); }
static void sentinel_check(where *w, expr *e, expr **args, const int variadic, const int nstdargs, symtable *stab) { #define ATTR_WARN_RET(w, ...) \ do{ cc1_warn_at(w, attr_sentinel, __VA_ARGS__); return; }while(0) attribute *attr = func_or_builtin_attr_present(e, attr_sentinel); int i, nvs; expr *sentinel; if(!attr) return; if(!variadic) return; /* warning emitted elsewhere, on the decl */ if(attr->bits.sentinel){ consty k; FOLD_EXPR(attr->bits.sentinel, stab); const_fold(attr->bits.sentinel, &k); if(k.type != CONST_NUM || !K_INTEGRAL(k.bits.num)) die_at(&attr->where, "sentinel attribute not reducible to integer constant"); i = k.bits.num.val.i; }else{ i = 0; } nvs = dynarray_count(args) - nstdargs; if(nvs == 0) ATTR_WARN_RET(w, "not enough variadic arguments for a sentinel"); UCC_ASSERT(nvs >= 0, "too few args"); if(i >= nvs) ATTR_WARN_RET(w, "sentinel index is not a variadic argument"); sentinel = args[(nstdargs + nvs - 1) - i]; /* must be of a pointer type, printf("%p\n", 0) is undefined */ if(!expr_is_null_ptr(sentinel, NULL_STRICT_ANY_PTR)) ATTR_WARN_RET(&sentinel->where, "sentinel argument expected (got %s)", type_to_str(sentinel->tree_type)); #undef ATTR_WARN_RET }
static void gen_inits_terms1( decl **ar, void (*declare)(decl *), int (*cmp)(const void *, const void *)) { size_t n = dynarray_count(ar); decl **i; if(!n) return; qsort(ar, n, sizeof *ar, cmp); for(i = ar; *i; i++) declare(*i); }
STATIC RTADVSocketRef RTADVSocketFind(int if_index) { int i; for (i = 0; i < dynarray_count(&S_globals->sockets); i++) { interface_t * if_p; RTADVSocketRef sock; sock = dynarray_element(&S_globals->sockets, i); if_p = RTADVSocketGetInterface(sock); if (if_index == if_link_index(if_p)) { return (sock); } } return (NULL); }
/* * Function: DHCPLeaseListFindLease * Purpose: * Find a lease corresponding to the supplied information. */ int DHCPLeaseListFindLease(DHCPLeaseListRef list_p, struct in_addr our_ip, struct in_addr router_ip, const uint8_t * router_hwaddr, int router_hwaddr_length) { int count; int i; bool private_ip = ip_is_private(our_ip); count = dynarray_count(list_p); for (i = 0; i < count; i++) { DHCPLeaseRef lease_p = dynarray_element(list_p, i); if (lease_p->our_ip.s_addr != our_ip.s_addr) { /* IP doesn't match */ continue; } if (private_ip == FALSE) { /* lease for public IP is unique */ return (i); } if (lease_p->router_ip.s_addr != router_ip.s_addr) { /* router IP doesn't match (or one is set the other isn't)*/ continue; } if (router_ip.s_addr == 0) { /* found lease with no router information */ return (i); } if (lease_p->router_hwaddr_length != router_hwaddr_length) { /* one has router hwaddr, other doesn't */ continue; } if (router_hwaddr == NULL || router_hwaddr_length == 0) { /* found lease with router IP but no router hwaddr */ return (i); } if (bcmp(lease_p->router_hwaddr, router_hwaddr, router_hwaddr_length) == 0) { /* exact match on IP, router IP, router hwaddr */ return (i); } } return (-1); }
static void DHCPv6SocketDemux(int if_index, const DHCPv6PacketRef pkt, int pkt_len) { DHCPv6SocketReceiveData data; DHCPv6OptionErrorString err; int i; if (pkt_len < DHCPV6_PACKET_HEADER_LENGTH) { return; } data.pkt = pkt; data.pkt_len = pkt_len; data.options = DHCPv6OptionListCreateWithPacket(pkt, pkt_len, &err); if (data.options == NULL) { my_log(LOG_NOTICE, "DHCPv6Socket: options parse failed, %s", err.str); return; } for (i = 0; i < dynarray_count(&S_globals->sockets); i++) { DHCPv6SocketRef client; client = dynarray_element(&S_globals->sockets, i); if (if_index != if_link_index(DHCPv6SocketGetInterface(client))) { continue; } if (S_verbose) { CFMutableStringRef str; str = CFStringCreateMutable(NULL, 0); DHCPv6PacketPrintToString(str, pkt, pkt_len); if (data.options != NULL) { DHCPv6OptionListPrintToString(str, data.options); } my_log(-LOG_DEBUG, "[%s] Receive %@", if_name(DHCPv6SocketGetInterface(client)), str); CFRelease(str); } if (client->receive_func != NULL) { (*client->receive_func)(client->receive_arg1, client->receive_arg2, &data); } } DHCPv6OptionListRelease(&data.options); return; }
static void DHCPLeaseListLog(DHCPLeaseListRef list_p) { int count; int i; CFMutableStringRef str; str = CFStringCreateMutable(NULL, 0); count = dynarray_count(list_p); for (i = 0; i < count; i++) { DHCPLeaseRef lease_p = dynarray_element(list_p, i); STRING_APPEND(str, "\n%d. ", i + 1); DHCPLeasePrintToString(str, lease_p); } my_log(~LOG_DEBUG, "DHCPLeaseList has %d element(s)%@", count, str); CFRelease(str); return; }
interface_t * ifl_find_ip(interface_list_t * list_p, struct in_addr iaddr) { int i; for (i = 0; i < list_p->count; i++) { interface_t * if_p = list_p->list + i; int j; for (j = 0; j < dynarray_count(&if_p->inet); j++) { inet_addrinfo_t * info; info = dynarray_element(&if_p->inet, j); if (info->addr.s_addr == iaddr.s_addr) return (if_p); } } return (NULL); }
const out_val *gen_expr_stmt(const expr *e, out_ctx *octx) { size_t n; const out_val *ret; struct out_dbg_lbl *pushed_lbls[2]; gen_stmt_code_m1(e->code, 1, pushed_lbls, octx); n = dynarray_count(e->code->bits.code.stmts); if(n > 0 && stmt_kind(e->code->bits.code.stmts[n-1], expr)) ret = gen_expr(e->code->bits.code.stmts[n - 1]->expr, octx); else ret = out_new_noop(octx); /* this is skipped by gen_stmt_code_m1( ... 1, ... ) */ gen_stmt_code_m1_finish(e->code, pushed_lbls, octx); return ret; }
interface_t * ifl_find_subnet(interface_list_t * list_p, struct in_addr iaddr) { int i; u_long addr_hl = iptohl(iaddr); for (i = 0; i < list_p->count; i++) { interface_t * if_p = list_p->list + i; int j; for (j = 0; j < dynarray_count(&if_p->inet); j++) { inet_addrinfo_t * info = dynarray_element(&if_p->inet, j); u_long ifnetaddr_hl = iptohl(info->netaddr); u_long ifmask_hl = iptohl(info->mask); if ((addr_hl & ifmask_hl) == ifnetaddr_hl) return (if_p); } } return (NULL); }
void fold_expr_stmt(expr *e, symtable *stab) { stmt *last_stmt; int last; (void)stab; last = dynarray_count(e->code->bits.code.stmts); if(last){ last_stmt = e->code->bits.code.stmts[last - 1]; last_stmt->freestanding = 1; /* allow the final to be freestanding */ last_stmt->expr_no_pop = 1; } fold_stmt(e->code); /* symtab should've been set by parse */ if(last && stmt_kind(last_stmt, expr)){ expr *last_expr = last_stmt->expr; e->tree_type = last_expr->tree_type; if(fold_check_expr(e, FOLD_CHK_ALLOW_VOID, "({ ... }) statement")) { return; } switch(expr_is_lval(last_expr)){ case LVALUE_NO: break; case LVALUE_STRUCT: case LVALUE_USER_ASSIGNABLE: e->f_islval = expr_is_lval_struct; } }else{ e->tree_type = type_nav_btype(cc1_type_nav, type_void); } e->freestanding = 1; /* ({ ... }) on its own is freestanding */ }
/* * Function: DHCPLeaseListUpdateLease * * Purpose: * Update the lease entry for the given lease in the in-memory lease database. */ void DHCPLeaseListUpdateLease(DHCPLeaseListRef list_p, struct in_addr our_ip, struct in_addr router_ip, const uint8_t * router_hwaddr, int router_hwaddr_length, absolute_time_t lease_start, dhcp_lease_time_t lease_length, const uint8_t * pkt, int pkt_size, CFStringRef ssid) { int count; int i; DHCPLeaseRef lease_p; boolean_t private_ip = ip_is_private(our_ip); lease_p = DHCPLeaseCreate(our_ip, router_ip, router_hwaddr, router_hwaddr_length, lease_start, lease_length, pkt, pkt_size, ssid); /* scan lease list to eliminate NAK'd, incomplete, and duplicate leases */ count = dynarray_count(list_p); for (i = 0; i < count; i++) { DHCPLeaseRef scan_p = dynarray_element(list_p, i); if (DHCPLeaseShouldBeRemoved(scan_p, lease_p, private_ip)) { dynarray_free_element(list_p, i); i--; count--; } } dynarray_add(list_p, lease_p); if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "Saved lease for " IP_FORMAT, IP_LIST(&lease_p->our_ip)); if (G_IPConfiguration_verbose) { DHCPLeaseListLog(list_p); } } return; }
static void check_standard_funcs(const char *name, expr **args) { const size_t nargs = dynarray_count(args); if(!strcmp(name, "free") && nargs == 1){ c_func_check_free(args[0]); }else{ static const struct { const char *name; unsigned nargs; int szarg; int ptrargs[2]; } memfuncs[] = { { "memcpy", 3, 2, { 0, 1 } }, { "memset", 3, 2, { 0, -1 } }, { "memmove", 3, 2, { 0, 1 } }, { "memcmp", 3, 2, { 0, 1 } }, { 0 } }; for(int i = 0; memfuncs[i].name; i++){ if(nargs == memfuncs[i].nargs && !strcmp(name, memfuncs[i].name)){ expr *ptrargs[countof(memfuncs[0].ptrargs) + 1] = { 0 }; unsigned arg; for(arg = 0; arg < countof(memfuncs[0].ptrargs); arg++){ if(memfuncs[i].ptrargs[arg] == -1) break; ptrargs[arg] = args[memfuncs[i].ptrargs[arg]]; } c_func_check_mem(ptrargs, args[memfuncs[i].szarg], memfuncs[i].name); break; } } } }
PRIVATE_EXTERN void RTADVSocketRelease(RTADVSocketRef * sock_p) { RTADVSocketRef sock = *sock_p; int i; if (sock == NULL) { return; } i = dynarray_index(&S_globals->sockets, sock); if (i != -1) { dynarray_remove(&S_globals->sockets, i, NULL); } else { my_log(LOG_NOTICE, "RTADVSocketRelease: %s not in list?", if_name(sock->if_p)); } RTADVSocketFreeElement(sock); *sock_p = NULL; if (dynarray_count(&S_globals->sockets) == 0) { RTADVSocketReleaseGlobals(&S_globals); } return; }
void DHCPv6SocketRelease(DHCPv6SocketRef * sock_p) { DHCPv6SocketRef sock = *sock_p; int i; if (sock == NULL) { return; } i = dynarray_index(&S_globals->sockets, sock); if (i != -1) { dynarray_remove(&S_globals->sockets, i, NULL); } else { my_log(LOG_ERR, "DHCPv6SocketRelease: %s not in list?", if_name(sock->if_p)); } DHCPv6SocketFreeElement(sock); *sock_p = NULL; if (dynarray_count(&S_globals->sockets) == 0) { DHCPv6SocketReleaseGlobals(&S_globals); } return; }
static void runner(int local, char *path, char **args) { pid_t pid; if(show){ int i; if(wrapper) fprintf(stderr, "WRAPPER='%s' ", wrapper); fprintf(stderr, "%s ", path); for(i = 0; args[i]; i++) fprintf(stderr, "%s ", args[i]); fputc('\n', stderr); } if(noop) return; /* if this were to be vfork, all the code in case-0 would need to be done in the parent */ pid = fork(); switch(pid){ case -1: die("fork():"); case 0: { int nargs = dynarray_count(args); int i_in = 0, i_out = 0; char **argv; /* -wrapper gdb,--args */ if(wrapper){ char *p; nargs++; for(p = wrapper; *p; p++) nargs += *p == ','; } /* * path, * { args } * NULL-term */ argv = umalloc((2 + nargs) * sizeof *argv); /* wrapper */ if(wrapper){ char *p, *last; for(p = last = wrapper; *p; p++) if(*p == ','){ *p = '\0'; argv[i_out++] = last; last = p + 1; } if(last != p) argv[i_out++] = last; } argv[i_out++] = local ? actual_path("../", path) : path; while(args[i_in]) argv[i_out++] = args[i_in++]; argv[i_out++] = NULL; #ifdef DEBUG fprintf(stderr, "%s:\n", *argv); for(int i = 0; argv[i]; i++) fprintf(stderr, " [%d] = \"%s\",\n", i, argv[i]); #endif if(wrapper) local = 0; (local ? execv : execvp)(argv[0], argv); die("execv(\"%s\"):", argv[0]); } default: { int status, i; if(wait(&status) == -1) die("wait()"); if(WIFEXITED(status) && (i = WEXITSTATUS(status)) != 0){ die("%s returned %d", path, i); }else if(WIFSIGNALED(status)){ int sig = WTERMSIG(status); fprintf(stderr, "%s caught signal %d\n", path, sig); /* exit with propagating status */ exit(128 + sig); } } } }
boolean_t if_inet_valid(interface_t * if_p) { return (dynarray_count(&if_p->inet) > 0); }
int if_inet_count(interface_t * if_p) { return (dynarray_count(&if_p->inet)); }
/* * Function: DHCPLeaseListCopyARPAddressInfo * Purpose: * Returns a list of arp_address_info_t's corresponding to each * discoverable lease. */ arp_address_info_t * DHCPLeaseListCopyARPAddressInfo(DHCPLeaseListRef list_p, CFStringRef ssid, absolute_time_t * start_time_threshold_p, bool tentative_ok, int * ret_count) { int arp_info_count; arp_address_info_t * arp_info_p; int count; int i; arp_address_info_t * info_p; DHCPLeaseListRemoveStaleLeases(list_p); count = dynarray_count(list_p); if (count == 0) { *ret_count = 0; return (NULL); } arp_info_p = (arp_address_info_t *)malloc(sizeof(*arp_info_p) * count); arp_info_count = 0; info_p = arp_info_p; for (i = 0; i < count; i++) { DHCPLeaseRef lease_p = dynarray_element(list_p, i); if (ssid != NULL) { if (lease_p->ssid == NULL || !CFEqual(lease_p->ssid, ssid)) { if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "ignoring lease with SSID %@", lease_p->ssid); continue; } } } if (lease_p->router_ip.s_addr == 0 || lease_p->router_hwaddr_length == 0) { /* can't use this with ARP discovery */ if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "ignoring lease for " IP_FORMAT, IP_LIST(&lease_p->our_ip)); } continue; } if (lease_p->tentative && tentative_ok == FALSE) { /* ignore tentative lease */ continue; } if (start_time_threshold_p != NULL && lease_p->lease_start < *start_time_threshold_p) { if (G_IPConfiguration_verbose) { my_log(LOG_DEBUG, "start time on lease " IP_FORMAT " too old (%ld < %ld)", IP_LIST(&lease_p->our_ip), lease_p->lease_start, *start_time_threshold_p); } continue; } info_p->sender_ip = lease_p->our_ip; info_p->target_ip = lease_p->router_ip; bcopy(lease_p->router_hwaddr, info_p->target_hardware, lease_p->router_hwaddr_length); arp_info_count++; info_p++; } if (arp_info_count == 0) { free(arp_info_p); arp_info_p = NULL; } *ret_count = arp_info_count; return (arp_info_p); }
void fold_expr_funcall(expr *e, symtable *stab) { type *func_ty; funcargs *args_from_decl; char *sp = NULL; unsigned count_decl; check_implicit_funcall(e, stab, &sp); FOLD_EXPR(e->expr, stab); func_ty = e->expr->tree_type; if(!type_is_callable(func_ty)){ warn_at_print_error(&e->expr->where, "%s-expression (type '%s') not callable", expr_str_friendly(e->expr, 0), type_to_str(func_ty)); fold_had_error = 1; e->tree_type = type_nav_btype(cc1_type_nav, type_int); return; } e->tree_type = type_func_call(func_ty, &args_from_decl); /* func count comparison, only if the func has arg-decls, or the func is f(void) */ UCC_ASSERT(args_from_decl, "no funcargs for decl %s", sp); count_decl = dynarray_count(args_from_decl->arglist); if(check_arg_counts(args_from_decl, count_decl, e->funcargs, e, sp)) return; if(e->funcargs){ check_arg_voidness_and_nonnulls( e, stab, args_from_decl, count_decl, e->funcargs, sp); } if(!FUNCARGS_EMPTY_NOVOID(args_from_decl)) check_arg_types(args_from_decl, e->funcargs, stab, sp, &e->where); if(e->funcargs) default_promote_args(e->funcargs, count_decl, stab); if(type_is_s_or_u(e->tree_type)){ /* handled transparently by the backend */ e->f_islval = expr_is_lval_struct; cc1_warn_at(&e->expr->where, aggregate_return, "called function returns aggregate (%s)", type_to_str(e->tree_type)); } /* attr */ { type *fnty = e->expr->tree_type; /* look through decays */ if(expr_kind(e->expr, cast) && expr_cast_is_lval2rval(e->expr)) fnty = expr_cast_child(e->expr)->tree_type; format_check_call(fnty, e->funcargs, args_from_decl->variadic); sentinel_check( &e->where, e, e->funcargs, args_from_decl->variadic, count_decl, stab); } /* check the subexp tree type to get the funcall attributes */ if(func_or_builtin_attr_present(e, attr_warn_unused)) e->freestanding = 0; /* needs use */ if(sp && !cc1_fopt.freestanding) check_standard_funcs(sp, e->funcargs); }
static void asm_declare_init(enum section_type sec, decl_init *init, type *tfor) { type *r; if(init == DYNARRAY_NULL) init = NULL; if(!init){ /* don't initialise flex-arrays */ if(!type_is_incomplete_array(tfor)){ asm_declare_pad(sec, type_size(tfor, NULL), "null init"/*, type_to_str(tfor)*/); }else{ asm_out_section(sec, ASM_COMMENT " flex array init skipped\n"); } }else if((r = type_is_primitive(tfor, type_struct))){ /* array of stmts for each member * assumes the ->bits.inits order is member order */ struct_union_enum_st *const sue = r->bits.type->sue; sue_member **mem; decl_init **i; unsigned end_of_last = 0; struct bitfield_val *bitfields = NULL; unsigned nbitfields = 0; decl *first_bf = NULL; expr *copy_from_exp; UCC_ASSERT(init->type == decl_init_brace, "unbraced struct"); #define DEBUG(s, ...) /*fprintf(f, "\033[35m" s "\033[m\n", __VA_ARGS__)*/ i = init->bits.ar.inits; /* check for compound-literal copy-init */ if((copy_from_exp = decl_init_is_struct_copy(init, sue))){ decl_init *copy_from_init; copy_from_exp = expr_skip_lval2rval(copy_from_exp); /* the only struct-expression that's possible * in static context is a compound literal */ assert(expr_kind(copy_from_exp, compound_lit) && "unhandled expression init"); copy_from_init = copy_from_exp->bits.complit.decl->bits.var.init.dinit; assert(copy_from_init->type == decl_init_brace); i = copy_from_init->bits.ar.inits; } /* iterate using members, not inits */ for(mem = sue->members; mem && *mem; mem++) { decl *d_mem = (*mem)->struct_member; decl_init *di_to_use = NULL; if(i){ int inc = 1; if(*i == NULL) inc = 0; else if(*i != DYNARRAY_NULL) di_to_use = *i; if(inc){ i++; if(!*i) i = NULL; /* reached end */ } } DEBUG("init for %ld/%s, %s", mem - sue->members, d_mem->spel, di_to_use ? di_to_use->bits.expr->f_str() : NULL); /* only pad if we're not on a bitfield or we're on the first bitfield */ if(!d_mem->bits.var.field_width || !first_bf){ DEBUG("prev padding, offset=%d, end_of_last=%d", d_mem->struct_offset, end_of_last); UCC_ASSERT( d_mem->bits.var.struct_offset >= end_of_last, "negative struct pad, sue %s, member %s " "offset %u, end_of_last %u", sue->spel, decl_to_str(d_mem), d_mem->bits.var.struct_offset, end_of_last); asm_declare_pad(sec, d_mem->bits.var.struct_offset - end_of_last, "prev struct padding"); } if(d_mem->bits.var.field_width){ if(!first_bf || d_mem->bits.var.first_bitfield){ if(first_bf){ DEBUG("new bitfield group (%s is new boundary), old:", d_mem->spel); /* next bitfield group - store the current */ bitfields_out(sec, bitfields, &nbitfields, first_bf->ref); } first_bf = d_mem; } bitfields = bitfields_add( bitfields, &nbitfields, d_mem, di_to_use); }else{ if(nbitfields){ DEBUG("at non-bitfield, prev-bitfield out:", 0); bitfields_out(sec, bitfields, &nbitfields, first_bf->ref); first_bf = NULL; } DEBUG("normal init for %s:", d_mem->spel); asm_declare_init(sec, di_to_use, d_mem->ref); } if(type_is_incomplete_array(d_mem->ref)){ UCC_ASSERT(!mem[1], "flex-arr not at end"); }else if(!d_mem->bits.var.field_width || d_mem->bits.var.first_bitfield){ unsigned last_sz = type_size(d_mem->ref, NULL); end_of_last = d_mem->bits.var.struct_offset + last_sz; DEBUG("done with member \"%s\", end_of_last = %d", d_mem->spel, end_of_last); } } if(nbitfields) bitfields_out(sec, bitfields, &nbitfields, first_bf->ref); free(bitfields); /* need to pad to struct size */ asm_declare_pad(sec, sue_size(sue, NULL) - end_of_last, "struct tail"); }else if((r = type_is(tfor, type_array))){ size_t i, len; decl_init **p; type *next = type_next(tfor); UCC_ASSERT(init->type == decl_init_brace, "unbraced struct"); if(type_is_incomplete_array(tfor)){ len = dynarray_count(init->bits.ar.inits); }else{ UCC_ASSERT(type_is_complete(tfor), "incomplete array/type init"); len = type_array_len(tfor); } for(i = len, p = init->bits.ar.inits; i > 0; i--) { decl_init *this = NULL; if(*p){ this = *p++; if(this != DYNARRAY_NULL && this->type == decl_init_copy){ /*fprintf(f, "# copy from %lu\n", DECL_INIT_COPY_IDX(this, init));*/ struct init_cpy *icpy = *this->bits.range_copy; /* resolve the copy */ this = icpy->range_init; } } asm_declare_init(sec, this, next); } }else if((r = type_is_primitive(tfor, type_union))){ /* union inits are decl_init_brace with spaces up to the first union init, * then NULL/end of the init-array */ struct_union_enum_st *sue = type_is_s_or_u(r); unsigned i, sub = 0; decl_init *u_init; UCC_ASSERT(init->type == decl_init_brace, "brace init expected"); /* skip the empties until we get to one */ for(i = 0; init->bits.ar.inits[i] == DYNARRAY_NULL; i++); if((u_init = init->bits.ar.inits[i])){ decl *mem = sue->members[i]->struct_member; type *mem_r = mem->ref; /* union init, member at index `i' */ if(mem->bits.var.field_width){ /* we know it's integral */ struct bitfield_val bfv; ASSERT_SCALAR(u_init); bitfield_val_set(&bfv, u_init->bits.expr, mem->bits.var.field_width); asm_declare_init_bitfields(sec, &bfv, 1, mem_r); }else{ asm_declare_init(sec, u_init, mem_r); } sub = type_size(mem_r, NULL); } /* else null union init */ asm_declare_pad(sec, type_size(r, NULL) - sub, "union extra"); }else{ /* scalar */ expr *exp = init->bits.expr; UCC_ASSERT(init->type == decl_init_scalar, "scalar init expected"); /* exp->tree_type should match tfor */ { char buf[TYPE_STATIC_BUFSIZ]; UCC_ASSERT( type_cmp(exp->tree_type, tfor, TYPE_CMP_ALLOW_TENATIVE_ARRAY) != TYPE_NOT_EQUAL, "mismatching init types: %s and %s", type_to_str_r(buf, exp->tree_type), type_to_str(tfor)); } /* use tfor, since "abc" has type (char[]){(int)'a', (int)'b', ...} */ DEBUG(" scalar init for %s:", type_to_str(tfor)); static_val(sec, tfor, exp); } }