#include #include #include #include #include #include #include // Parse extern definition fzl_node_t *pa_extern(fzl_parser_t *parser) { if (!parser || !peek(parser)) return NULL; fzl_token_t *kw = consume(parser); if (!kw || kw->type != FZL_TOKTYPE_EXTERN) { snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => expected 'extern' keyword", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } fzl_token_t *libname = consume(parser); if (!libname || libname->type != FZL_TOKTYPE_STR_LITERAL) { snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => expected library name after 'extern'", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } fzl_token_t *lbra = consume(parser); if (!lbra || lbra->type != FZL_TOKTYPE_LBRACE) { snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => expected '{' after library name", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } // Typedefs array size_t td_remainder = 2; size_t td_count = 0; fzl_node_t **td = malloc(td_remainder * sizeof(fzl_node_t *)); if (!td) { snprintf(plast_err, sizeof(plast_err), "out of memory"); return NULL; } // Functions array size_t fn_remainder = 2; size_t fn_count = 0; fzl_node_t **fn = malloc(fn_remainder * sizeof(fzl_node_t *)); if (!fn) { free(td); snprintf(plast_err, sizeof(plast_err), "out of memory"); return NULL; } bool error = false; while (peek(parser)) { if (is(parser, FZL_TOKTYPE_RBRACE)) break; if (td_remainder <= td_count) { td_remainder *= 2; fzl_node_t **newarr = realloc(td, td_remainder * sizeof(fzl_node_t *)); if (!newarr) { snprintf(plast_err, sizeof(plast_err), "out of memory"); error = true; break; } td = newarr; } if (fn_remainder <= fn_count) { fn_remainder *= 2; fzl_node_t **newarr = realloc(fn, fn_remainder * sizeof(fzl_node_t *)); if (!newarr) { snprintf(plast_err, sizeof(plast_err), "out of memory"); error = true; break; } fn = newarr; } if (is(parser, FZL_TOKTYPE_TYPEDEF)) { fzl_node_t *result = pa_typedef(parser); if (!result) { error = true; break; } td[td_count++] = result; } else if (is(parser, FZL_TOKTYPE_FUNCTION)) { fzl_node_t *result = pa_externfn(parser); if (!result) { error = true; break; } fn[fn_count++] = result; } else { snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => unexpected statement inside extern block", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); error = true; break; } fzl_token_t *sc = consume(parser); if (!sc || sc->type != FZL_TOKTYPE_SEMICOLON) { snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => missing ';'", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); error = true; break; } } if (error) { for (size_t i = 0; i < td_count; i++) fzl_freeast(td[i]); free(td); for (size_t i = 0; i < fn_count; i++) fzl_freeast(fn[i]); free(fn); return NULL; } fzl_token_t *rbra = consume(parser); if (!rbra || rbra->type != FZL_TOKTYPE_RBRACE) { for (size_t i = 0; i < td_count; i++) fzl_freeast(td[i]); free(td); for (size_t i = 0; i < fn_count; i++) fzl_freeast(fn[i]); free(fn); snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => expected '}' after extern block", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } fzl_node_t *node = fzl_mknode(FZL_NODETYPE_EXTERN, kw); if (!node) { for (size_t i = 0; i < td_count; i++) fzl_freeast(td[i]); free(td); for (size_t i = 0; i < fn_count; i++) fzl_freeast(fn[i]); free(fn); snprintf(plast_err, sizeof(plast_err), "out of memory"); return NULL; } node->ext.libname = (char *)libname->value; node->ext.typedefs = td; node->ext.typedefs_count = td_count; node->ext.fns = fn; node->ext.fns_count = fn_count; return node; }