int ged_killall(struct ged *gedp, int argc, const char *argv[]) { int nflag; int ret; static const char *usage = "[-n] object(s)"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_DRAWABLE(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } /* Process the -n option */ if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'n' && argv[1][2] == '\0') { int i; nflag = 1; /* Objects that would be killed are in the first sublist */ bu_vls_printf(gedp->ged_result_str, "{"); for (i = 2; i < argc; i++) bu_vls_printf(gedp->ged_result_str, "%s ", argv[i]); bu_vls_printf(gedp->ged_result_str, "} {"); } else nflag = 0; gedp->ged_internal_call = 1; if ((ret = ged_killrefs(gedp, argc, argv)) != GED_OK) { gedp->ged_internal_call = 0; bu_vls_printf(gedp->ged_result_str, "KILL skipped because of earlier errors.\n"); return ret; } gedp->ged_internal_call = 0; if (nflag) { /* Close the sublist of objects that reference the would-be killed objects. */ bu_vls_printf(gedp->ged_result_str, "}"); return GED_OK; } /* ALL references removed...now KILL the object[s] */ /* reuse argv[] */ argv[0] = "kill"; return ged_kill(gedp, argc, argv); }
int ged_killtree(struct ged *gedp, int argc, const char *argv[]) { struct directory *dp; int i; int c; struct killtree_data gktd; static const char *usage = "[-a|-f|-n] object(s)"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } gktd.gedp = gedp; gktd.killrefs = 0; gktd.print = 0; gktd.force = 0; gktd.ac = 1; gktd.top = NULL; gktd.av = (char **)bu_calloc(1, sizeof(char *) * AV_STEP, "alloc av"); gktd.av_capacity = AV_STEP; BU_ASSERT(gktd.ac + argc + 2 < AV_STEP); /* potential -n opts */ gktd.av[0] = "killrefs"; gktd.av[1] = (char *)0; bu_optind = 1; while ((c = bu_getopt(argc, (char * const *)argv, "afn")) != -1) { switch (c) { case 'a': gktd.killrefs = 1; break; case 'n': gktd.print = 1; gktd.av[gktd.ac++] = bu_strdup("-n"); gktd.av[gktd.ac] = (char *)0; break; case 'f': gktd.force = 1; break; default: bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); bu_free(gktd.av, "free av (error)"); gktd.av = NULL; return GED_ERROR; } } argc -= (bu_optind - 1); argv += (bu_optind - 1); /* Objects that would be killed are in the first sublist */ if (gktd.print) bu_vls_printf(gedp->ged_result_str, "{"); for (i = 1; i < argc; i++) { if ((dp = db_lookup(gedp->ged_wdbp->dbip, argv[i], LOOKUP_NOISY)) == RT_DIR_NULL) continue; /* ignore phony objects */ if (dp->d_addr == RT_DIR_PHONY_ADDR) continue; /* stash the what's killed so we can find refs elsewhere */ gktd.top = argv[i]; db_functree(gedp->ged_wdbp->dbip, dp, killtree_callback, killtree_callback, gedp->ged_wdbp->wdb_resp, (void *)&gktd); } /* Close the sublist of would-be killed objects. Also open the * sublist of objects that reference the would-be killed objects. */ if (gktd.print) bu_vls_printf(gedp->ged_result_str, "} {"); if (gktd.killrefs && gktd.ac > 1) { gedp->ged_internal_call = 1; (void)ged_killrefs(gedp, gktd.ac, (const char **)gktd.av); gedp->ged_internal_call = 0; for (i = 1; i < gktd.ac; i++) { if (!gktd.print) bu_vls_printf(gedp->ged_result_str, "Freeing %s\n", gktd.av[i]); bu_free((void *)gktd.av[i], "killtree_data"); gktd.av[i] = NULL; } } if (gktd.print) bu_vls_printf(gedp->ged_result_str, "}"); bu_free(gktd.av, "free av"); gktd.av = NULL; return GED_OK; }