/* * fieldset_copy * * Copy-constructor for field sets. In the copy, * the nameref's must point to the entries in the * newly-constructed scope. */ static int fieldset_copy (void *vctx, name_t *dst, void *dp, name_t *src, void *sp) { namereflist_t *drefs = dp; namereflist_t *srefs = sp; expr_ctx_t ctx = vctx; scopectx_t dscope = name_scope(dst); namectx_t namectx = expr_namectx(ctx); nameref_t *ref; name_t *np; for (ref = namereflist_head(srefs); ref != 0; ref = ref->tq_next) { if (ref->np == 0) { // XXX should never happen continue; } strdesc_t *str = name_string(ref->np); np = name_search(dscope, str->ptr, str->len, 0); namereflist_instail(drefs, nameref_alloc(namectx, np)); } return 1; } /* fieldset_copy */
/* * macro_copydata * * Copy-constructor for macros. */ static int macro_copydata (void *vctx, name_t *dst, void *dp, name_t *src, void *sp) { struct macrodecl_s *srcm = sp; struct macrodecl_s *dstm = dp; nameref_t *ref; expr_ctx_t ctx = vctx; namectx_t namectx = expr_namectx(ctx); lexctx_t lctx = expr_lexmemctx(ctx); lexseq_init(&dstm->body); lexseq_copy(lctx, &dstm->body, &srcm->body); dstm->ptable = scope_copy(srcm->ptable, 0); namereflist_init(&dstm->plist); namereflist_init(&dstm->ilist); dstm->type = srcm->type; // We can't just copy the namereflists over verbatim; the copied // list has to reference the names in the copied name table, not // the original. for (ref = namereflist_head(&srcm->plist); ref != 0; ref = ref->tq_next) { name_t *np; if (ref->np == 0) { np = 0; } else { strdesc_t *namestr = name_string(ref->np); np = name_search(dstm->ptable, namestr->ptr, namestr->len, 0); } namereflist_instail(&dstm->plist, nameref_alloc(namectx, np)); } for (ref = namereflist_head(&srcm->ilist); ref != 0; ref = ref->tq_next) { name_t *np; if (ref->np == 0) { np = 0; } else { strdesc_t *namestr = name_string(ref->np); np = name_search(dstm->ptable, namestr->ptr, namestr->len, 0); } namereflist_instail(&dstm->ilist, nameref_alloc(namectx, np)); } return 1; } /* macro_copydata */
/* * structure_copy * * Copy-constructor for a structure cell. Handles * the fact that name references must point to the * newly-constructed scope tables, rather than the * originals. */ static int structure_copy (void *vctx, name_t *dst, void *dp, name_t *src, void *sp) { expr_ctx_t ctx = vctx; lexctx_t lctx = expr_lexmemctx(ctx); strudef_t *dstru = dp; strudef_t *sstru = sp; namectx_t namectx = expr_namectx(ctx); nameref_t *ref; name_t *np; dstru->acctbl = scope_copy(sstru->acctbl, 0); dstru->allotbl = scope_copy(sstru->allotbl, 0); for (ref = namereflist_head(&sstru->accformals); ref != 0; ref = ref->tq_next) { if (ref->np == 0) { np = 0; } else { strdesc_t *str = name_string(ref->np); np = name_search(dstru->acctbl, str->ptr, str->len, 0); } namereflist_instail(&dstru->accformals, nameref_alloc(namectx, np)); } for (ref = namereflist_head(&sstru->alloformals); ref != 0; ref = ref->tq_next) { if (ref->np == 0) { np = 0; } else { strdesc_t *str = name_string(ref->np); np = name_search(dstru->allotbl, str->ptr, str->len, 0); } namereflist_instail(&dstru->alloformals, nameref_alloc(namectx, np)); } lexseq_copy(lctx, &dstru->accbody, &sstru->accbody); lexseq_copy(lctx, &dstru->allobody, &sstru->allobody); return 1; } /* structure_copy */
static void cut_env(t_all *all, char ***env_dup) { char *name; int ret; ret = 0; name = get_name(all->ch_arg[2]); ret = name_search(ft_strdup(name), all); if (ret != -1) { write_value(env_dup, ret); ft_strdel(&name); } }
/* * macro_expand * * Expands a macro. */ static int macro_expand (macroctx_t mctx, name_t *macroname, lexseq_t *result) { struct macrodecl_s *macro = name_extraspace(macroname); expr_ctx_t ctx = mctx->ectx; parse_ctx_t pctx = expr_parse_ctx(ctx); lexctx_t lctx = parser_lexmemctx(pctx); expansion_t *curexp = expansion_alloc(mctx); expansion_t *prev_exp; lextype_t lt; lexeme_t *lex; lexseq_t extras; name_t *np; scopectx_t expscope; int which; int nactuals; punctclass_t pcl; lextype_t psep; lextype_t terms[3]; static strdesc_t comma = STRDEF(","); if (macro == 0 || curexp == 0) { expr_signal(ctx, STC__INTCMPERR, "macro_expand"); return 1; } memset(curexp, 0, sizeof(struct expansion_s)); // We save the punctuation class here, since it will get // munged by the parsing of the macro parameters. parser_punctclass_get(pctx, &pcl, &psep); prev_exp = 0; if (macro->type == MACRO_COND) { for (prev_exp = mctx->curexp; prev_exp != 0 && prev_exp->curmacro != macroname; prev_exp = prev_exp->next); } nactuals = 0; lexseq_init(&extras); // Simple macros with no formal arguments get no processing // of parameter lists whatsoever. if (macro->type == MACRO_SIMPLE && namereflist_length(¯o->plist) == 0) { expscope = 0; which = 3; } else { // For keyword macros, prime the scope with the declared // formals, so we can inherit the default values. if (macro->type == MACRO_KWD) { expscope = scope_copy(macro->ptable, 0); } else { expscope = scope_begin(scope_namectx(parser_scope_get(pctx)), 0); } lt = parser_next(pctx, QL_NORMAL, &lex); if (macro->type == MACRO_KWD) { if (lt != LEXTYPE_DELIM_LPAR) { expr_signal(ctx, STC__DELIMEXP, "("); parser_insert(pctx, lex); return 1; } which = 0; lexeme_free(lctx, lex); } else { for (which = 0; lt != openers[which] && which < 3; which++); if (which >= 3 && namereflist_length(¯o->plist) > 0) { expr_signal(ctx, STC__DELIMEXP, "("); parser_insert(pctx, lex); return 1; } if (which >= 3) { parser_insert(pctx, lex); } else { lexeme_free(lctx, lex); } } } // If we had a match on an opener, process // the actual parameters. if (which < 3) { nameref_t *formal; lexseq_t val; terms[0] = LEXTYPE_DELIM_COMMA; terms[1] = closers[which]; formal = namereflist_head(¯o->plist); while (1) { // Keyword macro actuals are of the form name=value // For positionals, grab the next formal-parameter name, // or set np to NULL to add the actual to %REMAINING. if (macro->type == MACRO_KWD) { lt = parser_next(pctx, QL_NAME, &lex); if (lexeme_boundtype(lex) != LEXTYPE_NAME) { expr_signal(ctx, STC__NAMEEXP); lexeme_free(lctx, lex); break; } np = name_search(macro->ptable, lex->text.ptr, lex->text.len, 0); if (np == 0) { expr_signal(ctx, STC__INTCMPERR, "macro_expand[2]"); } lexeme_free(lctx, lex); if (!parser_expect(pctx, QL_NORMAL, LEXTYPE_OP_ASSIGN, 0, 1)) { expr_signal(ctx, STC__OPEREXP, "="); break; } } else if (nactuals < namereflist_length(¯o->plist)) { np = formal->np; formal = formal->tq_next; } else { np = 0; } lexseq_init(&val); // Now parse the actual-parameter, which can be an expression if (!parse_lexeme_seq(pctx, 0, QL_NAME, terms, 2, &val, <)) { lexseq_free(lctx, &val); break; } // If we are recursively expanding a conditional macro and // there are no parameters, we're done - no expansion. if (prev_exp != 0 && lexseq_length(&val) == 0 && nactuals == 0) { scope_end(expscope); free(curexp); return 1; } if (np == 0) { if (lexseq_length(&extras) > 0) { lexseq_instail(&extras, lexeme_create(lctx, LEXTYPE_DELIM_COMMA, &comma)); } lexseq_append(&extras, &val); } else { name_t *actual; // Associate the actual with the formal. For keyword // macros, the scope_copy() above sets a special "no check" // flag that allows each name to be redeclared once. // name_declare() clears this flag, so we can catch genuine // redeclarations. actual = macparam_special(expscope, name_string(np), &val); if (actual == 0) { expr_signal(ctx, STC__INTCMPERR, "macro_expand[3]"); } lexseq_free(lctx, &val); } nactuals += 1; if (lt == closers[which]) { break; } if (lt != LEXTYPE_DELIM_COMMA) { expr_signal(ctx, STC__DELIMEXP, ","); break; } } /* while (1) */ if (lt != closers[which]) { expr_signal(ctx, STC__DELIMEXP, "closer"); lexseq_free(lctx, &extras); scope_end(expscope); return 1; } if (nactuals < namereflist_length(¯o->plist)) { name_t *anp; while (formal != 0) { anp = macparam_special(expscope, name_string(formal->np), 0); if (anp == 0) { expr_signal(ctx, STC__INTCMPERR, "macro_expand[4]"); } formal = formal->tq_next; } } } /* if which < 3 */ // The macro actual parameters are now processed; hook // the scope into the current hierarchy, restore the punctuation // class to what it was before we parsed the actuals, and // generate the expansion sequence. parser_punctclass_set(pctx, pcl, psep); curexp->count = (prev_exp == 0 ? 0 : prev_exp->count); curexp->expscope = expscope; curexp->curmacro = macroname; curexp->next = mctx->curexp; curexp->nactuals = nactuals; lexseq_append(&curexp->remaining, &extras); mctx->curexp = curexp; return prepare_body(mctx, curexp, result); } /* macro_expand */