/*! Create a new vector, initialize the first element to the contents of 'var' * * @param[in] var cg_var to clone and add to vector * @retval cvec allocated cvec */ cvec * cvec_from_var(cg_var *cv) { cvec *newvec = NULL; cg_var *tail = NULL; if (cv && (newvec = cvec_new(0))) { if ((tail = cvec_append_var(newvec, cv)) == NULL) { cvec_free(newvec); newvec = NULL; } } return newvec; }
/*! Recursively copy callback structure to all terminal nodes in the parse-tree. * XXX: Actually copies to every node, even if not terminal * Problem is that the argument is modified according to reference rule * @param[in] pt Parse-tree * @param[in] cc0 This is the parameter (calling) callback. eg fn in @sub,fn(). * * The function installs the calling callback in all executable non-terminal nodes. * That is, it only install callbacks in non-terminal with NULL child which is * where a ';' is in the syntax, eg: * a ;{} # Here a is executable * b {} # But b is not * Somewhat strange semantics though: * - Always replace (or add if empty) original callback in co0 * - Use local argument-list _unless_ there is none, then use callback list from cc0 */ static int pt_callback_reference(parse_tree pt, struct cg_callback *cc0) { int i; cg_obj *co; parse_tree *ptc; int retval = -1; struct cg_callback *cc; cg_var *cv; for (i=0; i<pt.pt_len; i++){ if ((co = pt.pt_vec[i]) == NULL) continue; ptc = &co->co_pt; /* Filter out non-executable non-terminals. */ if (ptc->pt_len && ptc->pt_vec[0] == NULL){ /* Copy the callback from top */ if ((cc = co->co_callbacks) == NULL){ if (co_callback_copy(cc0, &co->co_callbacks) < 0) return -1; } else { #ifdef CALLBACK_SINGLEARG cc->cc_fn = cc0->cc_fn; /* iterate */ #endif cc->cc_fn_vec = cc0->cc_fn_vec; /* */ if (cc0->cc_fn_str){ if (cc->cc_fn_str) free (cc->cc_fn_str); cc->cc_fn_str = strdup(cc0->cc_fn_str); } /* Append original parameters to end of call */ if (cc0->cc_cvec){ cv = NULL; while ((cv = cvec_each(cc0->cc_cvec, cv)) != NULL) cvec_append_var(cc->cc_cvec, cv); } } } if (pt_callback_reference(co->co_pt, cc0) < 0) goto done; } retval = 0; done: return retval; }