Exemplo n.º 1
0
int
ged_concat(struct ged *gedp, int argc, const char *argv[])
{
    struct db_i *newdbp;
    struct directory *dp;
    Tcl_HashTable name_tbl;
    Tcl_HashTable used_names_tbl;
    Tcl_HashEntry *ptr;
    Tcl_HashSearch search;
    struct bu_attribute_value_set g_avs;
    const char *cp;
    char *colorTab;
    struct ged_concat_data cc_data;
    const char *oldfile;
    static const char *usage = "[-u] [-t] [-c] [-s|-p] file.g [suffix|prefix]";
    int importUnits = 0;
    int importTitle = 0;
    int importColorTable = 0;
    int saveGlobalAttrs = 0;
    int c;
    const char *commandName;

    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);

    if (argc < 2) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    bu_vls_init(&cc_data.affix);
    cc_data.copy_mode = 0;
    commandName = argv[0];

    /* process args */
    bu_optind = 1;
    bu_opterr = 0;
    while ((c=bu_getopt(argc, (char * const *)argv, "utcsp")) != -1) {
	switch (c) {
	    case 'u':
		importUnits = 1;
		break;
	    case 't':
		importTitle = 1;
		break;
	    case 'c':
		importColorTable = 1;
		break;
	    case 'p':
		cc_data.copy_mode |= AUTO_PREFIX;
		break;
	    case 's':
		cc_data.copy_mode |= AUTO_SUFFIX;
		break;
	    default: {
		    bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", commandName, usage);
		    bu_vls_free(&cc_data.affix);
		    return GED_ERROR;
		}
	}
    }
    argc -= bu_optind;
    argv += bu_optind;

    if (argc == 0) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", commandName, usage);
	return GED_ERROR;
    }

    oldfile = argv[0];

    argc--;
    argv++;

    if (cc_data.copy_mode) {
	/* specified suffix or prefix explicitly */

	if (cc_data.copy_mode & AUTO_PREFIX) {

	    if (argc == 0 || BU_STR_EQUAL(argv[0], "/")) {
		cc_data.copy_mode = NO_AFFIX | CUSTOM_PREFIX;
	    } else {
		(void)bu_vls_strcpy(&cc_data.affix, argv[0]);
		cc_data.copy_mode |= CUSTOM_PREFIX;
	    }

	} else if (cc_data.copy_mode & AUTO_SUFFIX) {

	    if (argc == 0 || BU_STR_EQUAL(argv[0], "/")) {
		cc_data.copy_mode = NO_AFFIX | CUSTOM_SUFFIX;
	    } else {
		(void)bu_vls_strcpy(&cc_data.affix, argv[0]);
		cc_data.copy_mode |= CUSTOM_SUFFIX;
	    }

	} else {
	    bu_vls_free(&cc_data.affix);
	    bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", commandName, usage);
	    return GED_ERROR;
	}

    } else {
	/* no prefix/suffix preference, use prefix */

	cc_data.copy_mode |= AUTO_PREFIX;

	if (argc == 0 || BU_STR_EQUAL(argv[0], "/")) {
	    cc_data.copy_mode = NO_AFFIX | CUSTOM_PREFIX;
	} else {
	    (void)bu_vls_strcpy(&cc_data.affix, argv[0]);
	    cc_data.copy_mode |= CUSTOM_PREFIX;
	}

    }

    if (db_version(gedp->ged_wdbp->dbip) < 5) {
	if (bu_vls_strlen(&cc_data.affix) > _GED_V4_MAXNAME-1) {
	    bu_log("ERROR: affix [%s] is too long for v%d\n", bu_vls_addr(&cc_data.affix), db_version(gedp->ged_wdbp->dbip));
	    bu_vls_free(&cc_data.affix);
	    return GED_ERROR;
	}
    }

    /* open the input file */
    if ((newdbp = db_open(oldfile, DB_OPEN_READONLY)) == DBI_NULL) {
	bu_vls_free(&cc_data.affix);
	perror(oldfile);
	bu_vls_printf(gedp->ged_result_str, "%s: Can't open geometry database file %s", commandName, oldfile);
	return GED_ERROR;
    }

    if (db_version(newdbp) > 4 && db_version(gedp->ged_wdbp->dbip) < 5) {
	bu_vls_free(&cc_data.affix);
	bu_vls_printf(gedp->ged_result_str, "%s: databases are incompatible, use dbupgrade on %s first",
		      commandName, gedp->ged_wdbp->dbip->dbi_filename);
	return GED_ERROR;
    }

    db_dirbuild(newdbp);

    cc_data.new_dbip = newdbp;
    cc_data.old_dbip = gedp->ged_wdbp->dbip;

    /* visit each directory pointer in the input database */
    Tcl_InitHashTable(&name_tbl, TCL_STRING_KEYS);
    Tcl_InitHashTable(&used_names_tbl, TCL_STRING_KEYS);

    if (importUnits || importTitle || importColorTable) {
	saveGlobalAttrs = 1;
    }
    FOR_ALL_DIRECTORY_START(dp, newdbp) {
	if (dp->d_major_type == DB5_MAJORTYPE_ATTRIBUTE_ONLY) {
	    if (saveGlobalAttrs) {
		if (db5_get_attributes(newdbp, &g_avs, dp)) {
		    bu_vls_printf(gedp->ged_result_str, "%s: Can't get global attributes from %s", commandName, oldfile);
		    return GED_ERROR;
		}
	    }
	    continue;
	}
	copy_object(gedp, dp, newdbp, gedp->ged_wdbp->dbip, &name_tbl, &used_names_tbl, &cc_data);
    } FOR_ALL_DIRECTORY_END;

    bu_vls_free(&cc_data.affix);
    rt_mempurge(&(newdbp->dbi_freep));

    /* Free all the directory entries, and close the input database */
    db_close(newdbp);

    if (importColorTable) {
	colorTab = bu_strdup(bu_avs_get(&g_avs, "regionid_colortable"));
	db5_import_color_table(colorTab);
	bu_free(colorTab, "colorTab");
    } else if (saveGlobalAttrs) {
	bu_avs_remove(&g_avs, "regionid_colortable");
    }

    if (importTitle) {
	if ((cp = bu_avs_get(&g_avs, "title")) != NULL) {
	    char *oldTitle = gedp->ged_wdbp->dbip->dbi_title;
	    gedp->ged_wdbp->dbip->dbi_title = bu_strdup(cp);
	    if (oldTitle) {
		bu_free(oldTitle, "old title");
	    }
	}
    } else if (saveGlobalAttrs) {
	bu_avs_remove(&g_avs, "title");
    }

    if (importUnits) {
	if ((cp = bu_avs_get(&g_avs, "units")) != NULL) {
	    double dd;
	    if (sscanf(cp, "%lf", &dd) != 1 || NEAR_ZERO(dd, VUNITIZE_TOL)) {
		bu_log("copy_object(%s): improper database, %s object attribute 'units'=%s is invalid\n",
		       oldfile, DB5_GLOBAL_OBJECT_NAME, cp);
		bu_avs_remove(&g_avs, "units");
	    } else {
		gedp->ged_wdbp->dbip->dbi_local2base = dd;
		gedp->ged_wdbp->dbip->dbi_base2local = 1 / dd;
	    }
	}
    } else if (saveGlobalAttrs) {
	bu_avs_remove(&g_avs, "units");
    }

    if (saveGlobalAttrs) {
	dp = db_lookup(gedp->ged_wdbp->dbip, DB5_GLOBAL_OBJECT_NAME, LOOKUP_NOISY);
	db5_update_attributes(dp, &g_avs, gedp->ged_wdbp->dbip);
    }

    db_sync(gedp->ged_wdbp->dbip);	/* force changes to disk */

    /* Free the Hash tables */
    ptr = Tcl_FirstHashEntry(&name_tbl, &search);
    while (ptr) {
	bu_free((char *)Tcl_GetHashValue(ptr), "new name");
	ptr = Tcl_NextHashEntry(&search);
    }
    Tcl_DeleteHashTable(&name_tbl);
    Tcl_DeleteHashTable(&used_names_tbl);

    return GED_OK;
}
Exemplo n.º 2
0
void
db_close(register struct db_i *dbip)
{
    register int i;
    register struct directory *dp, *nextdp;

    if (!dbip)
	return;

    RT_CK_DBI(dbip);
    if (RT_G_DEBUG&DEBUG_DB) bu_log("db_close(%s) %p uses=%d\n",
				    dbip->dbi_filename, (void *)dbip, dbip->dbi_uses);

    bu_semaphore_acquire(BU_SEM_LISTS);
    if ((--dbip->dbi_uses) > 0) {
	bu_semaphore_release(BU_SEM_LISTS);
	/* others are still using this database */
	return;
    }
    bu_semaphore_release(BU_SEM_LISTS);

    /* ready to free the database -- use count is now zero */

    /* free up any mapped files */
    if (dbip->dbi_mf) {
	/*
	 * We're using an instance of a memory mapped file.
	 * We have two choices:
	 * Either dissociate from the memory mapped file
	 * by clearing dbi_mf->apbuf, or
	 * keeping our already-scanned dbip ready for
	 * further use, with our dbi_uses counter at 0.
	 * For speed of re-open, at the price of some address space,
	 * the second choice is taken.
	 */
	bu_close_mapped_file(dbip->dbi_mf);
	bu_free_mapped_files(0);
	dbip->dbi_mf = (struct bu_mapped_file *)NULL;
    }

    /* try to ensure/encourage that the file is written out */
    db_sync(dbip);

    if (dbip->dbi_fp) {
	fclose(dbip->dbi_fp);
    }

    if (dbip->dbi_title)
	bu_free(dbip->dbi_title, "dbi_title");
    if (dbip->dbi_filename)
	bu_free(dbip->dbi_filename, "dbi_filename");

    db_free_anim(dbip);
    rt_color_free();		/* Free MaterHead list */

    /* Release map of database holes */
    rt_mempurge(&(dbip->dbi_freep));
    rt_memclose();

    dbip->dbi_inmem = NULL;		/* sanity */

    bu_ptbl_free(&dbip->dbi_clients);

    /* Free all directory entries */
    for (i = 0; i < RT_DBNHASH; i++) {
	for (dp = dbip->dbi_Head[i]; dp != RT_DIR_NULL;) {
	    RT_CK_DIR(dp);
	    nextdp = dp->d_forw;
	    RT_DIR_FREE_NAMEP(dp);	/* frees d_namep */

	    if ((dp->d_flags & RT_DIR_INMEM) && (dp->d_un.ptr != NULL)) {
		bu_free(dp->d_un.ptr, "db_close d_un.ptr");
		dp->d_un.ptr = NULL;
		dp->d_len    = 0;
	    }

	    /* Put 'dp' back on the freelist */
	    dp->d_forw = rt_uniresource.re_directory_hd;
	    rt_uniresource.re_directory_hd = dp;

	    /* null'ing the forward pointer here is a huge
	     * memory leak as it causes the loss of all
	     * nodes on the freelist except the first.
	     * (so don't do it)
	     */

	    dp = nextdp;
	}
	dbip->dbi_Head[i] = RT_DIR_NULL;	/* sanity*/
    }

    if (dbip->dbi_filepath != NULL) {
	bu_free_argv(2, dbip->dbi_filepath);
	dbip->dbi_filepath = NULL; /* sanity */
    }

    bu_free((char *)dbip, "struct db_i");
}
Exemplo n.º 3
0
int
ged_dup(struct ged *gedp, int argc, const char *argv[])
{
    struct db_i *newdbp = DBI_NULL;
    struct directory **dirp0 = (struct directory **)NULL;
    struct dir_check_stuff dcs;
    static const char *usage = "file.g prefix";

    GED_CHECK_DATABASE_OPEN(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;
    }

    if (argc > 3) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    bu_vls_trunc(&gedp->ged_wdbp->wdb_prestr, 0);
    if (argc == 3)
	(void)bu_vls_strcpy(&gedp->ged_wdbp->wdb_prestr, argv[2]);

    gedp->ged_wdbp->wdb_num_dups = 0;
    if (db_version(gedp->ged_wdbp->dbip) < 5) {
	if ((gedp->ged_wdbp->wdb_ncharadd = bu_vls_strlen(&gedp->ged_wdbp->wdb_prestr)) > 12) {
	    gedp->ged_wdbp->wdb_ncharadd = 12;
	    bu_vls_trunc(&gedp->ged_wdbp->wdb_prestr, 12);
	}
    } else {
	gedp->ged_wdbp->wdb_ncharadd = bu_vls_strlen(&gedp->ged_wdbp->wdb_prestr);
    }

    /* open the input file */
    if ((newdbp = db_open(argv[1], DB_OPEN_READONLY)) == DBI_NULL) {
	perror(argv[1]);
	bu_vls_printf(gedp->ged_result_str, "dup: Cannot open geometry database file %s", argv[1]);
	return GED_ERROR;
    }

    bu_vls_printf(gedp->ged_result_str,
		  "\n*** Comparing %s with %s for duplicate names\n",
		  gedp->ged_wdbp->dbip->dbi_filename, argv[1]);
    if (gedp->ged_wdbp->wdb_ncharadd) {
	bu_vls_printf(gedp->ged_result_str,
		      "  For comparison, all names in %s were prefixed with: %s\n",
		      argv[1], bu_vls_addr(&gedp->ged_wdbp->wdb_prestr));
    }

    /* Get array to hold names of duplicates */
    if ((dirp0 = _ged_getspace(gedp->ged_wdbp->dbip, 0)) == (struct directory **) 0) {
	bu_vls_printf(gedp->ged_result_str, "f_dup: unable to get memory\n");
	db_close(newdbp);
	return GED_ERROR;
    }

    /* Scan new database for overlaps */
    dcs.main_dbip = gedp->ged_wdbp->dbip;
    dcs.wdbp = gedp->ged_wdbp;
    dcs.dup_dirp = dirp0;
    if (db_version(newdbp) < 5) {
	if (db_scan(newdbp, dup_dir_check, 0, (void *)&dcs) < 0) {
	    bu_vls_printf(gedp->ged_result_str, "dup: db_scan failure");
	    bu_free((void *)dirp0, "_ged_getspace array");
	    db_close(newdbp);
	    return GED_ERROR;
	}
    } else {
	if (db5_scan(newdbp, dup_dir_check5, (void *)&dcs) < 0) {
	    bu_vls_printf(gedp->ged_result_str, "dup: db_scan failure");
	    bu_free((void *)dirp0, "_ged_getspace array");
	    db_close(newdbp);
	    return GED_ERROR;
	}
    }
    rt_mempurge(&(newdbp->dbi_freep));        /* didn't really build a directory */

    _ged_vls_col_pr4v(gedp->ged_result_str, dirp0, (int)(dcs.dup_dirp - dirp0), 0);
    bu_vls_printf(gedp->ged_result_str, "\n -----  %d duplicate names found  -----", gedp->ged_wdbp->wdb_num_dups);
    bu_free((void *)dirp0, "_ged_getspace array");
    db_close(newdbp);

    return GED_OK;
}