#include #include #include struct type_helper { char *orig; char *new; }; /* types are simple enough (for now) that this works fine */ static int rewrite_type_ids(struct type *type, char *orig, char *new) { if (type->k == TYPE_ID && strcmp(type->id, orig) == 0) { char *r = strdup(new); free(type->id); type->id = r; } if (type->t0 && rewrite_type_ids(type->t0, orig, new)) return -1; if (type->n && rewrite_type_ids(type->n, orig, new)) return -1; return 0; } static int rewrite_type_visit(struct ast *node, struct type_helper *helper) { if (node->t2) return rewrite_type_ids(node->t2, helper->orig, helper->new); return 0; } int rewrite_types(struct ast *node, char *orig, char *new) { struct type_helper helper = {.orig = orig, .new = new}; return ast_visit((ast_callback_t)rewrite_type_visit, NULL, node, &helper); } /* not the fastest thing in the world but should work well enough for now */ static char *rewrite_hole(char *old, char *new) { /* skip "<>" */ size_t on = strlen(old) - 2; size_t nn = strlen(new); /* +1 for null terminator */ char *r = malloc(on + nn + 1); memcpy(r, new, nn); /* +2 to skip "<>", +1 for null terminator */ memcpy(r + nn, old + 2, on + 1); return r; } static int rewrite_type_holes(struct type *type, char *new) { if (type->id && strncmp(type->id, "<>", 2) == 0) { char *r = rewrite_hole(type->id, new); free(type->id); type->id = r; } if (type->t0 && rewrite_type_holes(type->t0, new)) return -1; if (type->n && rewrite_type_holes(type->n, new)) return -1; return 0; } static int rewrite_holes_visit(struct ast *node, char *new) { if (node->k == AST_CONST_STR) return 0; if (node->s && strncmp(node->s, "<>", 2) == 0) { char *r = rewrite_hole(node->s, new); free(node->s); node->s = r; } if (node->t2 && rewrite_type_holes(node->t2, new)) return -1; return 0; } int rewrite_holes(struct ast *node, char *new) { return ast_visit((ast_callback_t)rewrite_holes_visit, NULL, node, new); }