static void param_declarator(node_t ** ty, struct token **id) { if (token->id == '*') { node_t *pty = ptr_decl(); prepend_type(ty, pty); } if (token->id == '(') { if (first_decl(lookahead())) { abstract_declarator(ty); } else { node_t *type1 = *ty; node_t *rtype = NULL; expect('('); param_declarator(&rtype, id); expect(')'); if (token->id == '(' || token->id == '[') { node_t *faty; cc_assert(id); if (*id) { faty = func_or_array(false, NULL); } else { faty = func_or_array(true, NULL); } attach_type(&faty, type1); attach_type(&rtype, faty); } *ty = rtype; } } else if (token->id == '[') { abstract_declarator(ty); } else if (token->id == ID) { declarator(ty, id, NULL); } }
static void fields(node_t * sym) { int follow[] = {INT, CONST, '}', IF, 0}; node_t *sty = SYM_TYPE(sym); if (!first_decl(token)) { error("expect type name or qualifiers"); return; } struct vector *v = vec_new(); do { node_t *basety = specifiers(NULL, NULL); for (;;) { node_t *field = new_field(); if (token->id == ':') { bitfield(field); FIELD_TYPE(field) = basety; } else { node_t *ty = NULL; struct token *id = NULL; declarator(&ty, &id, NULL); attach_type(&ty, basety); if (token->id == ':') bitfield(field); FIELD_TYPE(field) = ty; if (id) { for (int i = 0; i < vec_len(v); i++) { node_t *f = vec_at(v, i); if (FIELD_NAME(f) && !strcmp(FIELD_NAME(f), id->name)) { errorf(id->src, "redefinition of '%s'", id->name); break; } } FIELD_NAME(field) = id->name; AST_SRC(field) = id->src; } } vec_push(v, field); if (token->id != ',') break; expect(','); ensure_field(field, vec_len(v), false); } match(';', follow); ensure_field(vec_tail(v), vec_len(v), isstruct(sty) && !first_decl(token)); } while (first_decl(token)); TYPE_FIELDS(sty) = (node_t **) vtoa(v); set_typesize(sty); }
static node_t *func_or_array(bool abstract, int *params) { node_t *ty = NULL; int follow[] = { '[', ID, IF, 0 }; for (; token->id == '(' || token->id == '[';) { if (token->id == '[') { node_t *atype; expect('['); atype = arrays(abstract); match(']', follow); attach_type(&ty, atype); } else { node_t *ftype = func_type(); expect('('); TYPE_PARAMS(ftype) = parameters(ftype, params); match(')', follow); attach_type(&ty, ftype); } } return ty; }
static void declarator(node_t ** ty, struct token **id, int *params) { int follow[] = { ',', '=', IF, 0 }; cc_assert(ty && id); if (token->id == '*') { node_t *pty = ptr_decl(); prepend_type(ty, pty); } if (token->id == ID) { *id = token; expect(ID); if (token->id == '[' || token->id == '(') { node_t *faty = func_or_array(false, params); prepend_type(ty, faty); } } else if (token->id == '(') { node_t *type1 = *ty; node_t *rtype = NULL; expect('('); declarator(&rtype, id, params); match(')', follow); if (token->id == '[' || token->id == '(') { node_t *faty = func_or_array(false, params); attach_type(&faty, type1); attach_type(&rtype, faty); } else { attach_type(&rtype, type1); } *ty = rtype; } else { error("expect identifier or '('"); } }
static struct vector *decls(declfun_p * dcl) { struct vector *v = vec_new(); node_t *basety; int sclass, fspec; int level = SCOPE; int follow[] = {STATIC, INT, CONST, IF, '}', 0}; basety = specifiers(&sclass, &fspec); if (token->id == ID || token->id == '*' || token->id == '(') { struct token *id = NULL; node_t *ty = NULL; int params = 0; // for functioness // declarator if (level == GLOBAL) declarator(&ty, &id, ¶ms); else declarator(&ty, &id, NULL); attach_type(&ty, basety); if (level == GLOBAL && params) { if (first_funcdef(ty)) { vec_push(v, funcdef(id, ty, sclass, fspec)); return v; } else { exit_params(); } } for (;;) { if (id) { int kind; if (dcl == globaldecl) kind = GLOBAL; else if (dcl == paramdecl) kind = PARAM; else kind = LOCAL; node_t *decl = make_decl(id, ty, sclass, fspec, dcl); if (token->id == '=') decl_initializer(decl, sclass, kind); ensure_decl(decl, sclass, kind); vec_push(v, decl); } if (token->id != ',') break; expect(','); id = NULL; ty = NULL; // declarator declarator(&ty, &id, NULL); attach_type(&ty, basety); } } else if (isenum(basety) || isstruct(basety) || isunion(basety)) { // struct/union/enum int node_id; node_t *decl; if (isstruct(basety)) node_id = STRUCT_DECL; else if (isunion(basety)) node_id = UNION_DECL; else node_id = ENUM_DECL; decl = ast_decl(node_id); DECL_SYM(decl) = TYPE_TSYM(basety); vec_push(v, decl); } else { error("invalid token '%s' in declaration", token->name); } match(';', follow); return v; }
struct attach * attach_get(struct mail *m, char **ptr, size_t *len, const char *b, int *last) { struct attach *atr, *at; char *name = NULL, *b2 = NULL; size_t bl, bl2; int last2; u_int n; bl = strlen(b); atr = xmalloc(sizeof *atr); memset(atr, 0, sizeof *atr); TAILQ_INIT(&atr->children); atr->data = *ptr - m->data; while (*ptr != NULL) { if (*len >= 13 && strncasecmp(*ptr, "content-type:", 13) == 0) break; line_next(m, ptr, len); } if (*ptr == NULL) goto error; atr->type = attach_type(m, *ptr, "name", &name); if (atr->type == NULL) { if (name != NULL) xfree(name); goto error; } atr->name = name; if (strncasecmp(atr->type, "multipart/", 10) != 0) { /* Skip the remaining headers. */ while (*ptr != NULL && *len > 1) line_next(m, ptr, len); if (*ptr == NULL) goto error; atr->body = *ptr - m->data; for (;;) { line_next(m, ptr, len); if (*ptr == NULL) break; if (*len < 3 || (*ptr)[0] != '-' || (*ptr)[1] != '-') continue; if (*len - 5 == bl && strncmp(*ptr + 2, b, bl) == 0 && strncmp(*ptr + bl + 2, "--", 2) == 0) { *last = 1; break; } if (*len - 3 == bl && strncmp(*ptr + 2, b, bl) == 0) break; } if (*ptr == NULL) goto error; atr->size = *ptr - m->data - atr->data; } else { /* XXX avoid doing this twice. */ xfree(atr->type); atr->type = attach_type(m, *ptr, "boundary", &b2); if (b2 == NULL) goto error; bl2 = strlen(b2); /* Find the first boundary. */ while (*ptr != NULL) { if ((*ptr)[0] == '-' && (*ptr)[1] == '-') { if (*len - 3 == bl2 && strncmp(*ptr + 2, b2, bl2) == 0) break; } line_next(m, ptr, len); } if (ptr == NULL) goto error; /* Now iterate over the rest. */ last2 = 0; n = 0; while (*ptr != NULL && !last2) { at = attach_get(m, ptr, len, b2, &last2); if (at == NULL) goto error; at->idx = n++; at->parent = atr; TAILQ_INSERT_TAIL(&atr->children, at, entry); } /* And skip on to the end of the multipart. */ while (*ptr != NULL) { if ((*ptr)[0] == '-' && (*ptr)[1] == '-') { if (*len - 5 == bl2 && strncmp(*ptr + 2, b2, bl2) == 0) break; } line_next(m, ptr, len); } if (*ptr == NULL) goto error; line_next(m, ptr, len); xfree(b2); } return (atr); error: if (b2 != NULL) xfree(b2); attach_free(atr); return (NULL); }
struct attach * attach_build(struct mail *m) { struct attach *atr = NULL, *at; char *hdr, *ptr, *b = NULL, *type; size_t len, bl; int last; u_int n; hdr = find_header(m, "content-type", &len, 0); if (hdr == NULL) return (NULL); type = attach_type(m, hdr, "boundary", &b); if (type == NULL || b == NULL) { if (type != NULL) xfree(type); goto error; } if (strncasecmp(type, "multipart/", 10) != 0) { xfree(type); goto error; } bl = strlen(b); atr = xmalloc(sizeof *atr); memset(atr, 0, sizeof *atr); TAILQ_INIT(&atr->children); atr->type = type; /* Find the first boundary. */ line_init(m, &ptr, &len); while (ptr != NULL) { if (ptr[0] == '-' && ptr[1] == '-') { if (len - 3 == bl && strncmp(ptr + 2, b, bl) == 0) break; } line_next(m, &ptr, &len); } if (ptr == NULL) goto error; /* Now iterate over the rest. */ last = 0; n = 0; while (ptr != NULL && !last) { if (ptr[0] == '-' && ptr[1] == '-') { if (len - 5 == bl && strncmp(ptr + 2, b, bl) == 0) break; } at = attach_get(m, &ptr, &len, b, &last); if (at == NULL) goto error; at->idx = n++; at->parent = atr; TAILQ_INSERT_TAIL(&atr->children, at, entry); } if (ptr == NULL) goto error; xfree(b); return (atr); error: if (atr != NULL) attach_free(atr); if (b != NULL) xfree(b); return (NULL); }