/* T A B L E S . C * BRL-CAD * * Copyright (c) 2008-2012 United States Government as represented by * the U.S. Army Research Laboratory. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this file; see the file named COPYING for more * information. */ /** @file libged/tables.c * * The tables command. * */ #include "common.h" #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_PWD_H # include #endif #include #include #include "bio.h" #include "./ged_private.h" #define BUFF 1024 #define MAX_RESULT_LEN 1024 ///ADDED void GetStr(char *ix, char* Result) //call to get second number in function { char *spacing; //iterator to traverse spacing = ix; //iterator = pos of ix int LEN = 0; //length and offset int Offset = 0; while(*spacing != ' ') //while not at end of first num { Offset++; //offset is more spacing++; } spacing++; //go one ahead of the space Offset++; while(*spacing != ' ') //while not end of second number { spacing++; Offset++; LEN++; //length of number } if (LEN > MAX_RESULT_LEN - 1) { LEN = MAX_RESULT_LEN - 1; } strncpy(Result, ix + (Offset - LEN),LEN); Result[LEN] = '\0'; } int sort(const void* a, const void* b) { char *ia = *(char**)a; char *ib = *(char**)b; char Str[MAX_RESULT_LEN]; char Str2[MAX_RESULT_LEN]; GetStr(ia, Str); GetStr(ib, Str2); int n1 = atoi(Str); int n2 = atoi(Str2); return (n2 - n1); } /* structure to distinguish new solids from existing (old) solids */ struct identt { int i_index; char i_name[NAMESIZE+1]; mat_t i_mat; }; #define ABORTED -99 #define OLDSOLID 0 #define NEWSOLID 1 #define SOL_TABLE 1 #define REG_TABLE 2 #define ID_TABLE 3 static int idfd = 0; static int rd_idfd = 0; static FILE *tabptr = NULL; HIDDEN int tables_check(char *a, char *b) { int c= sizeof(struct identt); while (c--) if (*a++ != *b++) return 0; /* no match */ return 1; /* match */ } HIDDEN int tables_sol_number(const matp_t matrix, char *name, int *old, long *numsol) { int i; struct identt idbuf1, idbuf2; static struct identt identt = {0, {0}, MAT_INIT_ZERO}; int readval; memset(&idbuf1, 0, sizeof(struct identt)); bu_strlcpy(idbuf1.i_name, name, sizeof(idbuf1.i_name)); MAT_COPY(idbuf1.i_mat, matrix); for (i = 0; i < *numsol; i++) { (void)lseek(rd_idfd, i*(long)sizeof identt, 0); readval = read(rd_idfd, &idbuf2, sizeof identt); if (readval < 0) { perror("READ ERROR"); } idbuf1.i_index = i + 1; if (tables_check((char *)&idbuf1, (char *)&idbuf2) == 1) { *old = 1; return idbuf2.i_index; } } (*numsol)++; idbuf1.i_index = *numsol; (void)lseek(idfd, (off_t)0L, 2); i = write(idfd, &idbuf1, sizeof identt); if (i < 0) perror("write"); *old = 0; return idbuf1.i_index; } HIDDEN void tables_new(struct ged *gedp, struct directory *dp, struct bu_ptbl *cur_path, const fastf_t *old_mat, int flag, long *numreg, long *numsol) { struct rt_db_internal intern; struct rt_comb_internal *comb; struct rt_tree_array *tree_list; size_t node_count; size_t actual_count; size_t i, k; RT_CK_DIR(dp); BU_CK_PTBL(cur_path); if (!(dp->d_flags & RT_DIR_COMB)) return; if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) { bu_vls_printf(gedp->ged_result_str, "Database read error, aborting\n"); return; } comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB(comb); if (comb->tree && db_ck_v4gift_tree(comb->tree) < 0) { db_non_union_push(comb->tree, &rt_uniresource); if (db_ck_v4gift_tree(comb->tree) < 0) { bu_vls_printf(gedp->ged_result_str, "Cannot flatten tree for editing\n"); intern.idb_meth->ft_ifree(&intern); return; } } if (!comb->tree) { /* empty combination */ intern.idb_meth->ft_ifree(&intern); return; } node_count = db_tree_nleaves(comb->tree); tree_list = (struct rt_tree_array *)bu_calloc(node_count, sizeof(struct rt_tree_array), "tree list"); /* flatten tree */ actual_count = (struct rt_tree_array *)db_flatten_tree(tree_list, comb->tree, OP_UNION, 0, &rt_uniresource) - tree_list; BU_ASSERT_SIZE_T(actual_count, ==, node_count); if (dp->d_flags & RT_DIR_REGION) { (*numreg)++; (void)fprintf(tabptr, " %-4ld %4ld %4ld %4ld %4ld ", *numreg, comb->region_id, comb->aircode, comb->GIFTmater, comb->los); for (k = 0; k < BU_PTBL_LEN(cur_path); k++) { struct directory *path_dp; path_dp = (struct directory *)BU_PTBL_GET(cur_path, k); RT_CK_DIR(path_dp); (void)fprintf(tabptr, "/%s", path_dp->d_namep); } (void)fprintf(tabptr, "/%s:\n", dp->d_namep); if (flag == ID_TABLE) goto out; for (i = 0; i < actual_count; i++) { char op; int nsoltemp=0; struct rt_db_internal sol_intern; struct directory *sol_dp; mat_t temp_mat; int old; switch (tree_list[i].tl_op) { case OP_UNION: op = 'u'; break; case OP_SUBTRACT: op = '-'; break; case OP_INTERSECT: op = '+'; break; default: bu_log("unrecognized operation in region %s\n", dp->d_namep); op = '?'; break; } if ((sol_dp=db_lookup(gedp->ged_wdbp->dbip, tree_list[i].tl_tree->tr_l.tl_name, LOOKUP_QUIET)) != RT_DIR_NULL) { if (sol_dp->d_flags & RT_DIR_COMB) { (void)fprintf(tabptr, " RG %c %s\n", op, sol_dp->d_namep); continue; } else if (!(sol_dp->d_flags & RT_DIR_SOLID)) { (void)fprintf(tabptr, " ?? %c %s\n", op, sol_dp->d_namep); continue; } else { if (tree_list[i].tl_tree->tr_l.tl_mat) { bn_mat_mul(temp_mat, old_mat, tree_list[i].tl_tree->tr_l.tl_mat); } else { MAT_COPY(temp_mat, old_mat); } if (rt_db_get_internal(&sol_intern, sol_dp, gedp->ged_wdbp->dbip, temp_mat, &rt_uniresource) < 0) { bu_log("Could not import %s\n", tree_list[i].tl_tree->tr_l.tl_name); nsoltemp = 0; } nsoltemp = tables_sol_number((matp_t)temp_mat, tree_list[i].tl_tree->tr_l.tl_name, &old, numsol); (void)fprintf(tabptr, " %c [%d] ", op, nsoltemp); } } else { nsoltemp = tables_sol_number((matp_t)old_mat, tree_list[i].tl_tree->tr_l.tl_name, &old, numsol); (void)fprintf(tabptr, " %c [%d] ", op, nsoltemp); continue; } if (flag == REG_TABLE || old) { (void) fprintf(tabptr, "%s\n", tree_list[i].tl_tree->tr_l.tl_name); continue; } else (void) fprintf(tabptr, "%s: ", tree_list[i].tl_tree->tr_l.tl_name); if (!old && (sol_dp->d_flags & RT_DIR_SOLID)) { /* if we get here, we must be looking for a solid table */ struct bu_vls tmp_vls = BU_VLS_INIT_ZERO; if (!rt_functab[sol_intern.idb_type].ft_describe || rt_functab[sol_intern.idb_type].ft_describe(&tmp_vls, &sol_intern, 1, gedp->ged_wdbp->dbip->dbi_base2local, &rt_uniresource, gedp->ged_wdbp->dbip) < 0) { bu_vls_printf(gedp->ged_result_str, "%s describe error\n", tree_list[i].tl_tree->tr_l.tl_name); } fprintf(tabptr, "%s", bu_vls_addr(&tmp_vls)); bu_vls_free(&tmp_vls); } if (nsoltemp && (sol_dp->d_flags & RT_DIR_SOLID)) rt_db_free_internal(&sol_intern); } } else if (dp->d_flags & RT_DIR_COMB) { int cur_length; bu_ptbl_ins(cur_path, (long *)dp); cur_length = BU_PTBL_END(cur_path); for (i = 0; i < actual_count; i++) { struct directory *nextdp; mat_t new_mat; nextdp = db_lookup(gedp->ged_wdbp->dbip, tree_list[i].tl_tree->tr_l.tl_name, LOOKUP_NOISY); if (nextdp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "\tskipping this object\n"); continue; } /* recurse */ if (tree_list[i].tl_tree->tr_l.tl_mat) { bn_mat_mul(new_mat, old_mat, tree_list[i].tl_tree->tr_l.tl_mat); } else { MAT_COPY(new_mat, old_mat); } tables_new(gedp, nextdp, cur_path, new_mat, flag, numreg, numsol); bu_ptbl_trunc(cur_path, cur_length); } } else { bu_vls_printf(gedp->ged_result_str, "Illegal flags for %s skipping\n", dp->d_namep); return; } out: bu_free((char *)tree_list, "new_tables: tree_list"); intern.idb_meth->ft_ifree(&intern); return; } int ged_tables(struct ged *gedp, int argc, const char *argv[]) { //static const char sortcmd_orig[] = "sort -n +1 -2 -o /tmp/ord_id "; //static const char sortcmd_long[] = "sort --numeric --key=2, 2 --output /tmp/ord_id "; static const char catcmd[] = "cat /tmp/ord_id >> "; struct bu_vls tmp_vls = BU_VLS_INIT_ZERO; struct bu_vls cmd = BU_VLS_INIT_ZERO; struct bu_ptbl cur_path; char * TempStr; int flag; int status; char *timep; time_t now; int i; int LineLength; char ** DataArray; const char *usage = "file object(s)"; FILE * TMP = NULL; FILE *tabprtSrt = NULL; long int numreg = 0; long int numsol = 0; 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_ptbl_init(&cur_path, 8, "f_tables: cur_path"); status = GED_OK; /* find out which ascii table is desired */ if (BU_STR_EQUAL(argv[0], "solids")) { /* complete summary - down to solids/paremeters */ flag = SOL_TABLE; } else if (BU_STR_EQUAL(argv[0], "regions")) { /* summary down to solids as members of regions */ flag = REG_TABLE; } else if (BU_STR_EQUAL(argv[0], "idents")) { /* summary down to regions */ flag = ID_TABLE; } else { /* should never reach here */ bu_vls_printf(gedp->ged_result_str, "%s: input error\n", argv[0]); status = GED_ERROR; goto end; } /* open the file */ if ((tabptr=fopen(argv[1], "w+")) == NULL) { bu_vls_printf(gedp->ged_result_str, "%s: Can't open %s\n", argv[0], argv[1]); status = GED_ERROR; goto end; } if (flag == SOL_TABLE || flag == REG_TABLE) { /* temp file for discrimination of solids */ /* !!! this needs to be a bu_temp_file() */ if ((idfd = creat("/tmp/mged_discr", 0600)) < 0) { perror("/tmp/mged_discr"); status = GED_ERROR; goto end; } rd_idfd = open("/tmp/mged_discr", 2); } (void)time(&now); timep = ctime(&now); timep[24] = '\0'; (void)fprintf(tabptr, "1 -8 Summary Table {%s} (written: %s)\n", argv[0], timep); (void)fprintf(tabptr, "2 -7 file name : %s\n", gedp->ged_wdbp->dbip->dbi_filename); (void)fprintf(tabptr, "3 -6 \n"); (void)fprintf(tabptr, "4 -5 \n"); #ifndef _WIN32 (void)fprintf(tabptr, "5 -4 user : %s\n", getpwuid(getuid())->pw_gecos); #else { char uname[256]; DWORD dwNumBytes = 256; if (GetUserName(uname, &dwNumBytes)) (void)fprintf(tabptr, "5 -4 user : %s\n", uname); else (void)fprintf(tabptr, "5 -4 user : UNKNOWN\n"); } #endif (void)fprintf(tabptr, "6 -3 target title : %s\n", gedp->ged_wdbp->dbip->dbi_title); (void)fprintf(tabptr, "7 -2 target units : %s\n", bu_units_string(gedp->ged_wdbp->dbip->dbi_local2base)); (void)fprintf(tabptr, "8 -1 objects :"); for (i = 2; i < argc; i++) { if ((i%8) == 0) (void)fprintf(tabptr, "\n "); (void)fprintf(tabptr, " %s", argv[i]); } (void)fprintf(tabptr, "\n\n"); /* make the tables */ for (i = 2; i < argc; i++) { struct directory *dp; bu_ptbl_reset(&cur_path); if ((dp = db_lookup(gedp->ged_wdbp->dbip, argv[i], LOOKUP_NOISY)) != RT_DIR_NULL) tables_new(gedp, dp, &cur_path, (const fastf_t *)bn_mat_identity, flag, &numreg, &numsol); else bu_vls_printf(gedp->ged_result_str, "%s: skip this object\n", argv[i]); } bu_vls_printf(gedp->ged_result_str, "Summary written in: %s\n", argv[1]); if (flag == SOL_TABLE || flag == REG_TABLE) { bu_file_delete("/tmp/mged_discr\0"); (void)fprintf(tabptr, "\n\nNumber Primitives = %ld Number Regions = %ld\n", numsol, numreg); bu_vls_printf(gedp->ged_result_str, "Processed %d Primitives and %d Regions\n", numsol, numreg); (void)fclose(tabptr); } else { int ret; (void)fprintf(tabptr, "* 9999999\n* 9999999\n* 9999999\n* 9999999\n* 9999999\n"); (void)fclose(tabptr); tabprtSrt = fopen(argv[1],"r"); //open file to read TempStr = (char*)malloc(BUFF); //allocate memory for string //while line grab from file is successful while(fgets(TempStr, sizeof(TempStr), tabprtSrt) != NULL) { LineLength++; } //allocate string to hold data DataArray = (char**)malloc(LineLength * sizeof(char*)); int g; for(g = 0; g < LineLength; g++) { DataArray[g] = (char*)malloc(BUFF); } int Count = 0; //replicate for loop, provide counter while(fgets(TempStr, sizeof(TempStr), tabprtSrt) != NULL) { strcpy(DataArray[Count],TempStr); //copy data from file Count++; //increment counter } fclose(tabprtSrt); //close file used free(TempStr); //free memory //call sort on array qsort(DataArray, LineLength, sizeof(char *),sort); TMP = fopen("/tmp/ord_id","w+"); //open temp file to write to int k; for(k = 0; k < LineLength; k++) //write contents of sorted array to file { fprintf(TMP,"%s\n",DataArray[k]); } fclose(TMP); //close file bu_vls_printf(gedp->ged_result_str, "Processed %d Regions\n", numreg); /* make ordered idents - tries newer gnu 'sort' syntax if not successful */ //bu_vls_strcpy(&cmd, sortcmd_orig); //bu_vls_strcat(&cmd, argv[1]); //bu_vls_strcat(&cmd, " 2> /dev/null"); //if (system(bu_vls_addr(&cmd)) != 0) { //bu_vls_trunc(&cmd, 0); //bu_vls_strcpy(&cmd, sortcmd_long); //bu_vls_strcat(&cmd, argv[1]); //ret = system(bu_vls_addr(&cmd)); //if (ret != 0) //bu_log("WARNING: sort failure detected\n"); bu_vls_printf(gedp->ged_result_str, "%V\n", &cmd); bu_vls_trunc(&cmd, 0); bu_vls_strcpy(&cmd, catcmd); bu_vls_strcat(&cmd, argv[1]); bu_vls_printf(gedp->ged_result_str, "%V\n", &cmd); ret = system(bu_vls_addr(&cmd)); if (ret != 0) bu_log("WARNING: cat failure detected\n"); int h; for(h = 0; h < LineLength; h++) //free memory used by array free(ArrayData[h]); free(ArrayData); bu_file_delete("/tmp/ord_id\0"); } end: bu_vls_free(&cmd); bu_vls_free(&tmp_vls); bu_ptbl_free(&cur_path); return status; } /* * Local Variables: * tab-width: 8 * mode: C * indent-tabs-mode: t * c-file-style: "stroustrup" * End: * ex: shiftwidth=4 tabstop=8 */