BRL-CAD
edcodes.c
Go to the documentation of this file.
1 /* E D C O D E S . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2008-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file libged/edcodes.c
21  *
22  * The edcodes command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 
32 #include "bu/getopt.h"
33 #include "bu/sort.h"
34 #include "./ged_private.h"
35 
36 
37 #define EDCODES_OK GED_OK
38 #define EDCODES_NOTOK GED_ERROR
39 #define EDCODES_HALT -99
40 
41 
42 HIDDEN int
43 edcodes_id_compare(const void *p1, const void *p2, void *UNUSED(arg))
44 {
45  int id1, id2;
46 
47  id1 = atoi(*(char **)p1);
48  id2 = atoi(*(char **)p2);
49 
50  return id1 - id2;
51 }
52 
53 
54 HIDDEN int
55 edcodes_reg_compare(const void *p1, const void *p2, void *UNUSED(arg))
56 {
57  char *reg1, *reg2;
58 
59  reg1 = strchr(*(char **)p1, '/');
60  reg2 = strchr(*(char **)p2, '/');
61 
62  return bu_strcmp(reg1, reg2);
63 }
64 
65 
66 HIDDEN int edcodes_collect_regnames(struct ged *, struct directory *, int);
67 
68 HIDDEN void
69 edcodes_traverse_node(struct db_i *dbip, struct rt_comb_internal *UNUSED(comb), union tree *comb_leaf, void *user_ptr1, void *user_ptr2, void *user_ptr3, void *UNUSED(user_ptr4))
70 {
71  int ret;
72  int *pathpos;
73  struct directory *nextdp;
74  struct ged *gedp;
75 
76  RT_CK_DBI(dbip);
77  RT_CK_TREE(comb_leaf);
78 
79  if ((nextdp=db_lookup(dbip, comb_leaf->tr_l.tl_name, LOOKUP_NOISY)) == RT_DIR_NULL)
80  return;
81 
82  pathpos = (int *)user_ptr1;
83  gedp = (struct ged *)user_ptr2;
84 
85  /* recurse on combinations */
86  if (nextdp->d_flags & RT_DIR_COMB) {
87  int *status = (int *)user_ptr3;
88  ret = edcodes_collect_regnames(gedp, nextdp, (*pathpos)+1);
89  if (status && ret == EDCODES_HALT)
90  *status = EDCODES_HALT;
91  }
92 }
93 
94 
95 HIDDEN int
96 edcodes_collect_regnames(struct ged *gedp, struct directory *dp, int pathpos)
97 {
98  int id;
99  int status = 0;
100  struct rt_db_internal intern;
101  struct rt_comb_internal *comb;
102 
103  if (!(dp->d_flags & RT_DIR_COMB))
104  return EDCODES_OK;
105 
106  if ((id=rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip,
107  (matp_t)NULL, &rt_uniresource)) < 0) {
109  "Cannot get records for %s\n", dp->d_namep);
110  return EDCODES_NOTOK;
111  }
112 
113  if (id != ID_COMBINATION) {
114  intern.idb_meth->ft_ifree(&intern);
115  return EDCODES_OK;
116  }
117 
118  comb = (struct rt_comb_internal *)intern.idb_ptr;
119  RT_CK_COMB(comb);
120 
121  if (comb->region_flag) {
122  bu_vls_printf(gedp->ged_result_str, " %s", dp->d_namep);
123  intern.idb_meth->ft_ifree(&intern);
124  return EDCODES_OK;
125  }
126 
127  if (comb->tree) {
128  db_tree_funcleaf(gedp->ged_wdbp->dbip, comb, comb->tree, edcodes_traverse_node, (void *)&pathpos, (void *)gedp, (void *)&status, (void *)NULL);
129  }
130 
131  intern.idb_meth->ft_ifree(&intern);
132 
133  if (status == EDCODES_HALT)
134  return EDCODES_HALT;
135  return EDCODES_OK;
136 }
137 
138 
139 int
140 ged_edcodes(struct ged *gedp, int argc, const char *argv[])
141 {
142  int i;
143  int nflag = 0;
144  int status;
145  int sort_by_ident=0;
146  int sort_by_region=0;
147  int c;
148  char **av;
149  FILE *fp = NULL;
150  char tmpfil[MAXPATHLEN] = {0};
151  const char *editstring = NULL;
152 
153  static const char *usage = "[-i|-n|-r|-E editor] object(s)";
154 
157  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
158 
159  /* initialize result */
160  bu_vls_trunc(gedp->ged_result_str, 0);
161 
162  /* must be wanting help */
163  if (argc == 1) {
164  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
165  return GED_HELP;
166  }
167 
168  bu_optind = 1;
169  while ((c = bu_getopt(argc, (char * const *)argv, "E:inr")) != -1) {
170  switch (c) {
171  case 'E' :
172  editstring = bu_optarg;
173  break;
174  case 'i':
175  sort_by_ident = 1;
176  break;
177  case 'n':
178  nflag = 1;
179  break;
180  case 'r':
181  sort_by_region = 1;
182  break;
183  }
184  }
185 
186  if ((nflag + sort_by_ident + sort_by_region) > 1) {
187  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
188  return GED_ERROR;
189  }
190 
191  argc -= bu_optind - 1;
192  argv += bu_optind - 1;
193 
194  if (nflag) {
195  struct directory *dp;
196 
197  for (i = 1; i < argc; ++i) {
198  if ((dp = db_lookup(gedp->ged_wdbp->dbip, argv[i], LOOKUP_NOISY)) != RT_DIR_NULL) {
199  status = edcodes_collect_regnames(gedp, dp, 0);
200 
201  if (status != EDCODES_OK) {
202  if (status == EDCODES_HALT)
203  bu_vls_printf(gedp->ged_result_str, "%s: nesting is too deep\n", argv[0]);
204 
205  return GED_ERROR;
206  }
207  }
208  }
209 
210  return GED_OK;
211  }
212 
213  fp = bu_temp_file(tmpfil, MAXPATHLEN);
214  if (!fp)
215  return GED_ERROR;
216 
217  av = (char **)bu_malloc(sizeof(char *)*(argc + 2), "ged_edcodes av");
218  av[0] = "wcodes";
219  av[1] = tmpfil;
220  for (i = 2; i < argc + 1; ++i)
221  av[i] = (char *)argv[i-1];
222 
223  av[i] = NULL;
224 
225  (void)fclose(fp);
226 
227  if (ged_wcodes(gedp, argc + 1, (const char **)av) == GED_ERROR) {
228  bu_file_delete(tmpfil);
229  bu_free((void *)av, "ged_edcodes av");
230  return GED_ERROR;
231  }
232 
233  if (sort_by_ident || sort_by_region) {
234  char **line_array;
235  char aline[RT_MAXLINE];
236  FILE *f_srt;
237  int line_count=0;
238  int j;
239 
240  if ((f_srt=fopen(tmpfil, "r+")) == NULL) {
241  bu_vls_printf(gedp->ged_result_str, "%s: Failed to open temp file for sorting\n", argv[0]);
242  bu_file_delete(tmpfil);
243  return GED_ERROR;
244  }
245 
246  /* count lines */
247  while (bu_fgets(aline, RT_MAXLINE, f_srt)) {
248  line_count++;
249  }
250 
251  /* build array of lines */
252  line_array = (char **)bu_calloc(line_count, sizeof(char *), "edcodes line array");
253 
254  /* read lines and save into the array */
255  rewind(f_srt);
256  line_count = 0;
257  while (bu_fgets(aline, RT_MAXLINE, f_srt)) {
258  line_array[line_count] = bu_strdup(aline);
259  line_count++;
260  }
261 
262  /* sort the array of lines */
263  if (sort_by_ident) {
264  bu_sort((void *)line_array, line_count, sizeof(char *), edcodes_id_compare, NULL);
265  } else {
266  bu_sort((void *)line_array, line_count, sizeof(char *), edcodes_reg_compare, NULL);
267  }
268 
269  /* rewrite the temp file using the sorted lines */
270  rewind(f_srt);
271  for (j = 0; j < line_count; j++) {
272  fprintf(f_srt, "%s", line_array[j]);
273  bu_free(line_array[j], "ged_edcodes line array element");
274  }
275  bu_free((char *)line_array, "ged_edcodes line array");
276  fclose(f_srt);
277  }
278 
279  if (_ged_editit(editstring, tmpfil)) {
280  av[0] = "rcodes";
281  av[2] = NULL;
282  status = ged_rcodes(gedp, 2, (const char **)av);
283  } else
284  status = GED_ERROR;
285 
286  bu_file_delete(tmpfil);
287  bu_free((void *)av, "ged_edcodes av");
288  return status;
289 }
290 
291 
292 /*
293  * Local Variables:
294  * tab-width: 8
295  * mode: C
296  * indent-tabs-mode: t
297  * c-file-style: "stroustrup"
298  * End:
299  * ex: shiftwidth=4 tabstop=8
300  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_OK
Definition: ged.h:55
char * d_namep
pointer to name string
Definition: raytrace.h:859
Definition: raytrace.h:800
int rt_db_get_internal(struct rt_db_internal *ip, const struct directory *dp, const struct db_i *dbip, const mat_t mat, struct resource *resp)
Definition: dir.c:76
char region_flag
!0 ==> this COMB is a REGION
Definition: raytrace.h:939
Definition: ged.h:338
void(* ft_ifree)(struct rt_db_internal *)
Definition: raytrace.h:2159
#define EDCODES_HALT
Definition: edcodes.c:39
struct db_i * dbip
Definition: raytrace.h:1266
HIDDEN int edcodes_reg_compare(const void *p1, const void *p2, void *arg)
Definition: edcodes.c:55
#define RT_MAXLINE
Definition: raytrace.h:1255
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
#define RT_CK_COMB(_p)
Definition: raytrace.h:955
struct rt_wdb * ged_wdbp
Definition: ged.h:340
char * bu_optarg
Definition: globals.c:91
Header file for the BRL-CAD common definitions.
int bu_optind
Definition: globals.c:89
#define ID_COMBINATION
Combination Record.
Definition: raytrace.h:499
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
#define GED_ERROR
Definition: ged.h:61
#define HIDDEN
Definition: common.h:86
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
int ged_edcodes(struct ged *gedp, int argc, const char *argv[])
Definition: edcodes.c:140
char * strchr(const char *sp, int c)
HIDDEN int edcodes_collect_regnames(struct ged *, struct directory *, int)
Definition: edcodes.c:96
#define EDCODES_NOTOK
Definition: edcodes.c:38
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
int ged_wcodes(struct ged *gedp, int argc, const char *argv[])
Definition: wcodes.c:128
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
const struct rt_functab * idb_meth
for ft_ifree(), etc.
Definition: raytrace.h:194
FILE * bu_temp_file(char *filepath, size_t len)
Definition: temp.c:180
void bu_sort(void *array, size_t nummemb, size_t sizememb, int(*compare)(const void *, const void *, void *), void *context)
Definition: sort.c:110
HIDDEN int edcodes_id_compare(const void *p1, const void *p2, void *arg)
Definition: edcodes.c:43
char * tl_name
Name of this leaf (bu_strdup'ed)
Definition: raytrace.h:1174
#define UNUSED(parameter)
Definition: common.h:239
struct bu_vls * ged_result_str
Definition: ged.h:357
HIDDEN void edcodes_traverse_node(struct db_i *dbip, struct rt_comb_internal *comb, union tree *comb_leaf, void *user_ptr1, void *user_ptr2, void *user_ptr3, void *user_ptr4)
Definition: edcodes.c:69
#define EDCODES_OK
Definition: edcodes.c:37
#define RT_CK_DBI(_p)
Definition: raytrace.h:829
int bu_strcmp(const char *string1, const char *string2)
Definition: str.c:171
struct tree::tree_db_leaf tr_l
int _ged_editit(char *editstring, const char *filename)
Definition: editit.c:49
void * idb_ptr
Definition: raytrace.h:195
int ged_rcodes(struct ged *gedp, int argc, const char *argv[])
Definition: rcodes.c:36
#define RT_DIR_COMB
combination
Definition: raytrace.h:884
union tree * tree
Leading to tree_db_leaf leaves.
Definition: raytrace.h:938
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define RT_DIR_NULL
Definition: raytrace.h:875
#define LOOKUP_NOISY
Definition: raytrace.h:892
#define GED_HELP
Definition: ged.h:62
void db_tree_funcleaf(struct db_i *dbip, struct rt_comb_internal *comb, union tree *comb_tree, void(*leaf_func)(struct db_i *, struct rt_comb_internal *, union tree *, void *, void *, void *, void *), void *user_ptr1, void *user_ptr2, void *user_ptr3, void *user_ptr4)
Definition: db_tree.c:640
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define RT_CK_TREE(_p)
Definition: raytrace.h:1182
char * bu_fgets(char *s, int size, FILE *stream)
Definition: fgets.c:31
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
int d_flags
flags
Definition: raytrace.h:869
#define bu_strdup(s)
Definition: str.h:71
int bu_file_delete(const char *path)
Definition: file.c:278
#define MAXPATHLEN
Definition: defines.h:113