BRL-CAD
move_all.c
Go to the documentation of this file.
1 /* M O V E _ A L L . 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/move_all.c
21  *
22  * The move_all command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "bu/cmd.h"
32 #include "bu/getopt.h"
33 #include "rtgeom.h"
34 
35 #include "./ged_private.h"
36 
37 HIDDEN int
38 move_all_func(struct ged *gedp, int nflag, const char *old_name, const char *new_name)
39 {
40  int i;
41  struct display_list *gdlp;
42  struct directory *dp;
43  struct rt_db_internal intern;
44  struct rt_comb_internal *comb;
45  struct bu_ptbl stack;
46 
47  /* rename the record itself */
48  if ((dp = db_lookup(gedp->ged_wdbp->dbip, old_name, LOOKUP_NOISY)) == RT_DIR_NULL)
49  return GED_ERROR;
50 
51  if (db_lookup(gedp->ged_wdbp->dbip, new_name, LOOKUP_QUIET) != RT_DIR_NULL) {
52  bu_vls_printf(gedp->ged_result_str, "%s: already exists", new_name);
53  return GED_ERROR;
54  }
55 
56  /* if this was a sketch, we need to look for all the extrude
57  * objects that might use it.
58  *
59  * This has to be done here, before we rename the (possible) sketch object
60  * because the extrude will do a rt_db_get on the sketch when we call
61  * rt_db_get_internal on it.
62  */
63  if (dp->d_major_type == DB5_MAJORTYPE_BRLCAD && \
64  dp->d_minor_type == DB5_MINORTYPE_BRLCAD_SKETCH) {
65 
66  struct directory *dirp;
67 
68  for (i = 0; i < RT_DBNHASH; i++) {
69  for (dirp = gedp->ged_wdbp->dbip->dbi_Head[i]; dirp != RT_DIR_NULL; dirp = dirp->d_forw) {
70 
71  if (dirp->d_major_type == DB5_MAJORTYPE_BRLCAD && \
72  dirp->d_minor_type == DB5_MINORTYPE_BRLCAD_EXTRUDE) {
73  struct rt_extrude_internal *extrude;
74 
75  if (rt_db_get_internal(&intern, dirp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) {
76  bu_log("Can't get extrude %s?\n", dirp->d_namep);
77  continue;
78  }
79  extrude = (struct rt_extrude_internal *)intern.idb_ptr;
80  RT_EXTRUDE_CK_MAGIC(extrude);
81 
82  if (BU_STR_EQUAL(extrude->sketch_name, old_name)) {
83  if (nflag) {
84  bu_vls_printf(gedp->ged_result_str, "%s ", dirp->d_namep);
85  rt_db_free_internal(&intern);
86  } else {
87  bu_free(extrude->sketch_name, "sketch name");
88  extrude->sketch_name = bu_strdup(new_name);
89 
90  if (rt_db_put_internal(dirp, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) {
91  bu_log("oops\n");
92  }
93  }
94  } else
95  rt_db_free_internal(&intern);
96  }
97  }
98  }
99  }
100 
101  if (!nflag) {
102  /* Change object name in the directory. */
103  if (db_rename(gedp->ged_wdbp->dbip, dp, new_name) < 0) {
104  bu_vls_printf(gedp->ged_result_str, "error in rename to %s, aborting", new_name);
105  return GED_ERROR;
106  }
107 
108  /* Change name in the file */
109  if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) {
110  bu_vls_printf(gedp->ged_result_str, "Database read error, aborting");
111  return GED_ERROR;
112  }
113 
114  if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, &intern, &rt_uniresource) < 0) {
115  bu_vls_printf(gedp->ged_result_str, "Database write error, aborting");
116  return GED_ERROR;
117  }
118  }
119 
120  bu_ptbl_init(&stack, 64, "combination stack for wdb_mvall_cmd");
121 
122 
123  /* Examine all COMB nodes */
124  for (i = 0; i < RT_DBNHASH; i++) {
125  for (dp = gedp->ged_wdbp->dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) {
126  if (nflag) {
127  union tree *comb_leaf;
128  int done=0;
129 
130  if (!(dp->d_flags & RT_DIR_COMB)) continue;
131  if (rt_db_get_internal(&intern, dp, gedp->ged_wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) continue;
132  comb = (struct rt_comb_internal *)intern.idb_ptr;
133  bu_ptbl_reset(&stack);
134  /* visit each leaf in the combination */
135  comb_leaf = comb->tree;
136  if (comb_leaf) {
137  while (!done) {
138  while (comb_leaf->tr_op != OP_DB_LEAF) {
139  bu_ptbl_ins(&stack, (long *)comb_leaf);
140  comb_leaf = comb_leaf->tr_b.tb_left;
141  }
142 
143  if (BU_STR_EQUAL(comb_leaf->tr_l.tl_name, old_name)) {
144  bu_vls_printf(gedp->ged_result_str, "%s ", dp->d_namep);
145  }
146 
147  if (BU_PTBL_END(&stack) < 1) {
148  done = 1;
149  break;
150  }
151  comb_leaf = (union tree *)BU_PTBL_GET(&stack, BU_PTBL_END(&stack)-1);
152  if (comb_leaf->tr_op != OP_DB_LEAF) {
153  bu_ptbl_rm(&stack, (long *)comb_leaf);
154  comb_leaf = comb_leaf->tr_b.tb_right;
155  }
156  }
157  }
158  rt_db_free_internal(&intern);
159  } else {
160  int comb_mvall_status = db_comb_mvall(dp, gedp->ged_wdbp->dbip, old_name, new_name, &stack);
161  if (!comb_mvall_status) continue;
162  if (comb_mvall_status == 2) {
163  bu_ptbl_free(&stack);
164  bu_vls_printf(gedp->ged_result_str, "Database write error, aborting");
165  return GED_ERROR;
166  }
167  }
168  }
169  }
170 
171  bu_ptbl_free(&stack);
172 
173  if (!nflag) {
174  /* Change object name anywhere in the display list path. */
175  for (BU_LIST_FOR(gdlp, display_list, gedp->ged_gdp->gd_headDisplay)) {
176  int first = 1;
177  int found = 0;
178  struct bu_vls new_path = BU_VLS_INIT_ZERO;
179  char *dupstr = strdup(bu_vls_addr(&gdlp->dl_path));
180  char *tok = strtok(dupstr, "/");
181 
182  while (tok) {
183  if (BU_STR_EQUAL(tok, old_name)) {
184  found = 1;
185 
186  if (first) {
187  first = 0;
188  bu_vls_printf(&new_path, "%s", new_name);
189  } else
190  bu_vls_printf(&new_path, "/%s", new_name);
191  } else {
192  if (first) {
193  first = 0;
194  bu_vls_printf(&new_path, "%s", tok);
195  } else
196  bu_vls_printf(&new_path, "/%s", tok);
197  }
198 
199  tok = strtok((char *)NULL, "/");
200  }
201 
202  if (found) {
203  bu_vls_free(&gdlp->dl_path);
204  bu_vls_printf(&gdlp->dl_path, "%s", bu_vls_addr(&new_path));
205  }
206 
207  free((void *)dupstr);
208  bu_vls_free(&new_path);
209  }
210  }
211 
212  return GED_OK;
213 }
214 
215 
216 HIDDEN int
217 move_all_file(struct ged *gedp, int nflag, const char *file)
218 {
219  FILE *fp;
220  char line[512];
221 
222  if ((fp=fopen(file, "r")) == NULL) {
223  bu_vls_printf(gedp->ged_result_str, "cannot open %s\n", file);
224  return GED_ERROR;
225  }
226 
227  while (bu_fgets(line, sizeof(line), fp) != NULL) {
228  char *cp;
229  char *new_av[3];
230 
231  /* Skip comments */
232  if ((cp = strchr(line, '#')) != NULL)
233  *cp = '\0';
234 
235  if (bu_argv_from_string(new_av, 2, line) != 2)
236  continue;
237 
238  move_all_func(gedp, nflag, (const char *)new_av[0], (const char *)new_av[1]);
239  }
240 
241  fclose(fp);
242 
243  return GED_OK;
244 }
245 
246 
247 int
248 ged_move_all(struct ged *gedp, int argc, const char *argv[])
249 {
250  int c;
251  int fflag = 0;
252  int nflag = 0;
253  static const char *usage = "[-n] {-f <mapping_file>|<from> <to>}";
254 
257  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
258 
259  /* initialize result */
260  bu_vls_trunc(gedp->ged_result_str, 0);
261 
262  /* must be wanting help */
263  if (argc == 1) {
264  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
265  return GED_HELP;
266  }
267 
268  if (argc < 3 || 4 < argc) {
269  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
270  return GED_ERROR;
271  }
272 
273  if (db_version(gedp->ged_wdbp->dbip) < 5 && (int)strlen(argv[2]) > NAMESIZE) {
274  bu_vls_printf(gedp->ged_result_str, "ERROR: name length limited to %zu characters in v4 databases\n", strlen(argv[2]));
275  return GED_ERROR;
276  }
277 
278  bu_optind = 1;
279  while ((c = bu_getopt(argc, (char * const *)argv, "fn")) != -1) {
280  switch (c) {
281  case 'f':
282  fflag = 1;
283  break;
284  case 'n':
285  nflag = 1;
286  break;
287  default:
288  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
289  return GED_ERROR;
290  }
291  }
292 
293  argc -= bu_optind;
294  argv += bu_optind;
295 
296  if (fflag) {
297  if (argc != 1) {
298  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
299  return GED_ERROR;
300  }
301 
302  return move_all_file(gedp, nflag, argv[0]);
303  }
304 
305  if (argc != 2) {
306  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
307  return GED_ERROR;
308  }
309 
310  return move_all_func(gedp, nflag, argv[0], argv[1]);
311 }
312 
313 
314 /*
315  * Local Variables:
316  * tab-width: 8
317  * mode: C
318  * indent-tabs-mode: t
319  * c-file-style: "stroustrup"
320  * End:
321  * ex: shiftwidth=4 tabstop=8
322  */
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
#define BU_LIST_FOR(p, structure, hp)
Definition: list.h:365
unsigned char d_major_type
object major type
Definition: raytrace.h:870
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
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
#define RT_DBNHASH
hash table is an array of linked lists with this many array pointer elements (Memory use for 32-bit: ...
Definition: raytrace.h:755
int rt_db_put_internal(struct directory *dp, struct db_i *dbip, struct rt_db_internal *ip, struct resource *resp)
Definition: dir.c:136
Definition: ged.h:338
struct db_i * dbip
Definition: raytrace.h:1266
void bu_ptbl_init(struct bu_ptbl *b, size_t len, const char *str)
Definition: ptbl.c:32
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
int db_rename(struct db_i *, struct directory *, const char *newname)
Definition: db_lookup.c:302
HIDDEN int move_all_func(struct ged *gedp, int nflag, const char *old_name, const char *new_name)
Definition: move_all.c:38
int db_version(struct db_i *dbip)
Definition: db5_scan.c:414
int bu_ptbl_rm(struct bu_ptbl *b, const long *p)
struct rt_wdb * ged_wdbp
Definition: ged.h:340
Header file for the BRL-CAD common definitions.
int bu_optind
Definition: globals.c:89
int bu_ptbl_ins(struct bu_ptbl *b, long *p)
struct directory * d_forw
link to next dir entry
Definition: raytrace.h:864
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
struct bu_list * gd_headDisplay
head of display list
Definition: ged.h:307
void bu_ptbl_reset(struct bu_ptbl *b)
Definition: ptbl.c:49
#define GED_ERROR
Definition: ged.h:61
#define HIDDEN
Definition: common.h:86
union tree * tb_left
Definition: raytrace.h:1149
Definition: ptbl.h:62
char * strchr(const char *sp, int c)
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
unsigned char d_minor_type
object minor type
Definition: raytrace.h:871
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
#define OP_DB_LEAF
Leaf of combination, db fmt.
Definition: raytrace.h:1139
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
#define LOOKUP_QUIET
Definition: raytrace.h:893
char * strtok(char *s, const char *delim)
int ged_move_all(struct ged *gedp, int argc, const char *argv[])
Definition: move_all.c:248
char * tl_name
Name of this leaf (bu_strdup'ed)
Definition: raytrace.h:1174
struct tree::tree_node tr_b
struct bu_vls dl_path
Definition: bview.h:48
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
struct bu_vls * ged_result_str
Definition: ged.h:357
struct ged_drawable * ged_gdp
Definition: ged.h:360
void bu_ptbl_free(struct bu_ptbl *b)
Definition: ptbl.c:226
struct tree::tree_db_leaf tr_l
union tree * tb_right
Definition: raytrace.h:1150
void * idb_ptr
Definition: raytrace.h:195
#define RT_DIR_COMB
combination
Definition: raytrace.h:884
struct directory * dbi_Head[RT_DBNHASH]
Definition: raytrace.h:814
#define BU_PTBL_END(ptbl)
Definition: ptbl.h:106
int db_comb_mvall(struct directory *dp, struct db_i *dbip, const char *old_name, const char *new_name, struct bu_ptbl *stack)
Definition: db_comb.c:1107
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
char * strdup(const char *cp)
HIDDEN int move_all_file(struct ged *gedp, int nflag, const char *file)
Definition: move_all.c:217
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
char * bu_fgets(char *s, int size, FILE *stream)
Definition: fgets.c:31
size_t bu_argv_from_string(char *argv[], size_t lim, char *lp)
Definition: argv.c:32
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
int d_flags
flags
Definition: raytrace.h:869
Definition: vls.h:56
double fastf_t
Definition: defines.h:300
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
#define bu_strdup(s)
Definition: str.h:71
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126