BRL-CAD
search.c
Go to the documentation of this file.
1 /* S E A R C H . 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/search.c
21  *
22  * GED wrapper around librt search functions
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <string.h>
29 #include <stdlib.h>
30 #include <ctype.h>
31 #include <time.h>
32 
33 #ifdef HAVE_SYS_PARAM_H
34 # include <sys/param.h>
35 #endif
36 
37 #include "bu/cmd.h"
38 #include "bu/getopt.h"
39 
40 #include "./ged_private.h"
41 
42 
43 struct ged_search {
44  struct directory **paths;
45  int path_cnt;
47 };
48 
49 
50 HIDDEN int
51 _path_scrub(struct bu_vls *path)
52 {
53  struct bu_vls tmp = BU_VLS_INIT_ZERO;
54  const char *normalized;
55  int islocal = 1;
56 
57  if (!path)
58  return 0;
59 
60  if (bu_vls_addr(path)[0] == '/')
61  islocal = 0;
62 
63  normalized = db_normalize(bu_vls_addr(path));
64 
65  if (normalized && !BU_STR_EQUAL(normalized, "/")) {
66  char *tbasename = (char *)bu_calloc(strlen(normalized), sizeof(char), "_path_scrub tbasename");
67  bu_basename(tbasename, normalized);
68  bu_vls_sprintf(&tmp, "%s", tbasename);
69  bu_free(tbasename, "free bu_basename string (caller's responsibility per bu/log.h)");
70  bu_vls_sprintf(path, "%s", bu_vls_addr(&tmp));
71  bu_vls_free(&tmp);
72  } else {
73  bu_vls_sprintf(path, "%s", "/");
74  }
75 
76  return islocal;
77 }
78 
79 
80 HIDDEN void
81 _ged_free_search_set(struct bu_ptbl *search_set)
82 {
83  int i;
84 
85  if (!search_set)
86  return;
87 
88  for (i = (int)BU_PTBL_LEN(search_set) - 1; i >= 0; i--) {
89  struct ged_search *search = (struct ged_search *)BU_PTBL_GET(search_set, i);
90 
91  if (search && search->paths)
92  bu_free(search->paths, "free search paths");
93 
94  if (search)
95  bu_free(search, "free search");
96  }
97 
98  if (search_set) {
99  bu_ptbl_free(search_set);
100  bu_free(search_set, "free search container");
101  }
102 }
103 
104 
105 /* Returns 1 if char string seems to be part of a plan,
106  * else return 0 */
107 HIDDEN int
108 _ged_plan_item(char *arg)
109 {
110  if (!arg)
111  return 0;
112 
113  if (arg[0] == '-') return 1;
114  if (arg[0] == '!') return 1;
115  if (arg[0] == '(') return 1;
116  return 0;
117 }
118 
119 
120 /* Wrapper to identify the various types of searches being requested. Returns:
121  *
122  * 0: path is invalid - db_lookup failed or null input or path normalized to nothing
123  * 1: valid search path
124  *
125  * The variables is_specific, is_local, and is_flat convey specifics about the search.
126  */
127 HIDDEN int
128 _ged_search_characterize_path(struct ged *gedp, const char *orig, struct bu_vls *normalized, int *is_specific, int *is_local, int *is_flat, int *flat_only)
129 {
130  struct directory *path_dp = NULL;
131  (*is_flat) = 0;
132  (*flat_only) = 0;
133  (*is_specific) = 0;
134  (*is_local) = 0;
135  if (!orig || !normalized) return 0;
136  if (BU_STR_EQUAL(orig, "/")) {
137  return 1;
138  }
139  if (BU_STR_EQUAL(orig, ".")) {
140  (*is_local) = 1;
141  return 1;
142  }
143  if (BU_STR_EQUAL(orig, "|")) {
144  (*flat_only) = 1;
145  return 1;
146  }
147  bu_vls_sprintf(normalized, "%s", orig);
148  if (bu_vls_addr(normalized)[0] == '|') {
149  (*is_flat) = 1;
150  bu_vls_nibble(normalized, 1);
151  }
152  if (BU_STR_EQUAL(bu_vls_addr(normalized), "/")) {
153  return 1;
154  }
155  if (BU_STR_EQUAL(bu_vls_addr(normalized), ".")) {
156  (*is_local) = 1;
157  return 1;
158  }
159  (*is_local) = _path_scrub(normalized);
160  if (!bu_vls_strlen(normalized)) return 0;
161  if (BU_STR_EQUAL(bu_vls_addr(normalized), "/")) {
162  return 1;
163  }
164  /* We've handled the toplevel special cases - now the only question
165  * is is the path valid */
166  (*is_specific) = 1;
167  path_dp = db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(normalized), LOOKUP_QUIET);
168  if (path_dp == RT_DIR_NULL) {
169  bu_vls_printf(normalized, " not found in database!");
170  return 0;
171  }
172  return 1;
173 }
174 
175 
176 HIDDEN int
177 _ged_search_localized_obj_list(struct ged *gedp, struct directory *path, struct directory ***path_list)
178 {
179  int path_cnt;
180  int j;
181  const char *comb_str = "-name *";
182  struct bu_ptbl *tmp_search;
183  BU_ALLOC(tmp_search, struct bu_ptbl);
184  (void)db_search(tmp_search, DB_SEARCH_RETURN_UNIQ_DP, comb_str, 1, &path, gedp->ged_wdbp->dbip);
185  path_cnt = (int)BU_PTBL_LEN(tmp_search);
186  (*path_list) = (struct directory **)bu_malloc(sizeof(char *) * (path_cnt+1), "object path array");
187  for (j = 0; j < path_cnt; j++) {
188  (*path_list)[j] = (struct directory *)BU_PTBL_GET(tmp_search, j);
189  }
190  (*path_list)[path_cnt] = RT_DIR_NULL;
191  bu_ptbl_free(tmp_search);
192  bu_free(tmp_search, "Free search table container");
193  return path_cnt;
194 }
195 
196 
197 int
198 ged_search(struct ged *gedp, int argc, const char *argv_orig[])
199 {
200  int i, c, optcnt;
201  int aflag = 0; /* flag controlling whether hidden objects are examined */
202  int wflag = 0; /* flag controlling whether to fail quietly or not */
203  int flags = 0;
204  int want_help = 0;
205  int plan_argv = 1;
206  int plan_found = 0;
207  int path_found = 0;
208  int all_local = 1;
209  int print_verbose_info = 0;
210  struct bu_vls argvls = BU_VLS_INIT_ZERO;
211  struct bu_vls search_string = BU_VLS_INIT_ZERO;
212  struct bu_ptbl *search_set;
213  const char *usage = "[-a] [-v] [-Q] [-h] [path] [expressions...]\n";
214  /* COPY argv_orig to argv; */
215  char **argv = NULL;
216 
217  /* Find how many options we have. Once we get support
218  * for long options, this logic will have to get more sophisticated
219  * (do db_lookup on things to see if they are paths, recognize
220  * toplevel path specifiers, etc. */
221  optcnt = 0;
222  for (i = 1; i < argc; i++) {
223  if ((argv_orig[i][0] == '-') && (strlen(argv_orig[i]) == 2)) {
224  optcnt++;
225  } else {
226  break;
227  }
228  }
229 
230  /* Options have to come before paths and search expressions, so don't look
231  * any further than the max possible option count */
232  bu_optind = 1;
233  while ((bu_optind < (optcnt + 1)) && ((c = bu_getopt(argc, (char * const *)argv_orig, "?aQhv")) != -1)) {
234  if (bu_optopt == '?') c='h';
235  switch (c) {
236  case 'a':
237  aflag = 1;
238  flags |= DB_SEARCH_HIDDEN;
239  break;
240  case 'v':
241  print_verbose_info |= DB_FP_PRINT_BOOL;
242  print_verbose_info |= DB_FP_PRINT_TYPE;
243  break;
244 
245  case 'Q':
246  wflag = 1;
247  flags |= DB_SEARCH_QUIET;
248  break;
249  case 'h':
250  want_help = 1;
251  break;
252  default:
253  bu_vls_sprintf(gedp->ged_result_str, "Error: option %s is unknown.\nUsage: %s", argv_orig[0], usage);
254  return GED_ERROR;
255  }
256  }
257 
258  argc -= (bu_optind - 1);
259  argv_orig += (bu_optind - 1);
260 
261  if (want_help || argc == 1) {
262  if (!wflag) {
263  bu_vls_sprintf(gedp->ged_result_str, "Usage: %s", usage);
264  } else {
265  bu_vls_trunc(gedp->ged_result_str, 0);
266  }
267  return GED_OK;
268  }
269 
270  /* COPY argv_orig to argv; */
271  argv = bu_dup_argv(argc, argv_orig);
272 
273  /* initialize search set */
274  BU_ALLOC(search_set, struct bu_ptbl);
275  bu_ptbl_init(search_set, 8, "initialize search set table");
276 
277 
279 
280  /* initialize result */
281  bu_vls_trunc(gedp->ged_result_str, 0);
282 
283  /* If any specific paths are specified before the plan, we need to identify
284  * them and construct search structs. */
285  while (!plan_found) {
286  if (!argv[plan_argv]) {
287  /* OK, no plan - will use default behavior */
288  plan_found = 1;
289  } else {
290  if (!(_ged_plan_item(argv[plan_argv]))) {
291  /* We seem to have a path - figure out what type of search it specifies */
292  int is_specific, is_local, is_flat, flat_only;
293  struct ged_search *new_search;
294  int search_path_type = _ged_search_characterize_path(gedp, argv[plan_argv], &argvls, &is_specific, &is_local, &is_flat, &flat_only);
295  path_found = 1;
296  if (search_path_type) {
297  BU_ALLOC(new_search, struct ged_search);
298  } else {
299  /* FIXME: confirm 'argvls' is the desired string to print */
300  if (!wflag) {
301  bu_vls_printf(gedp->ged_result_str, "Search path error:\n input: '%s' normalized: '%s' \n",
302  argv[plan_argv], bu_vls_addr(&argvls));
303  } else {
304  bu_vls_trunc(gedp->ged_result_str, 0);
305  }
306  bu_vls_free(&argvls);
307  bu_free_argv(argc, argv);
308  _ged_free_search_set(search_set);
309  return (wflag) ? GED_OK : GED_ERROR;
310  }
311  if (!is_specific) {
312  if (!is_flat && !aflag && !flat_only) new_search->path_cnt = db_ls(gedp->ged_wdbp->dbip, DB_LS_TOPS, NULL, &(new_search->paths));
313  if (!is_flat && aflag && !flat_only) new_search->path_cnt = db_ls(gedp->ged_wdbp->dbip, DB_LS_TOPS | DB_LS_HIDDEN, NULL, &(new_search->paths));
314  if (is_flat && !aflag && !flat_only) new_search->path_cnt = db_ls(gedp->ged_wdbp->dbip, 0, NULL, &(new_search->paths));
315  if (is_flat && aflag && !flat_only) new_search->path_cnt = db_ls(gedp->ged_wdbp->dbip, DB_LS_HIDDEN, NULL, &(new_search->paths));
316  } else {
317  /* _ged_search_characterize_path verified that the db_lookup will succeed */
318  struct directory *local_dp = db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(&argvls), LOOKUP_QUIET);
319  if (is_flat) {
320  new_search->path_cnt = _ged_search_localized_obj_list(gedp, local_dp, &(new_search->paths));
321  } else {
322  new_search->paths = (struct directory **)bu_malloc(sizeof(struct directory *) * 2, "object path array");
323  new_search->paths[0] = local_dp;
324  new_search->paths[1] = RT_DIR_NULL;
325  new_search->path_cnt = 1;
326  }
327  }
328  new_search->search_type = is_local;
329  if (flat_only) new_search->search_type = 2;
330  bu_ptbl_ins(search_set, (long *)new_search);
331  plan_argv++;
332  } else {
333  plan_found = 1;
334  if (!path_found) {
335  /* We have a plan but not path - in that case, do a non-full-path tops search */
336  struct ged_search *new_search;
337  BU_ALLOC(new_search, struct ged_search);
338  if (!aflag) new_search->path_cnt = db_ls(gedp->ged_wdbp->dbip, DB_LS_TOPS, NULL, &(new_search->paths));
339  if (aflag) new_search->path_cnt = db_ls(gedp->ged_wdbp->dbip, DB_LS_TOPS | DB_LS_HIDDEN, NULL, &(new_search->paths));
340  new_search->search_type = 1;
341  bu_ptbl_ins(search_set, (long *)new_search);
342  }
343  }
344  }
345  }
346 
347  /* re-assemble search plan into a string - the db search functions break it out themselves */
348  bu_vls_trunc(&search_string, 0);
349  while (argv[plan_argv]) {
350  bu_vls_printf(&search_string, " %s", argv[plan_argv]);
351  plan_argv++;
352  }
353 
354  /* If we have the quiet flag set, check now whether we have a valid plan. Search will handle
355  * an invalid plan string, but it will report why it is invalid. So in quiet mode,
356  * we need to identify the bad string and return now. */
357  if (wflag && db_search(NULL, flags, bu_vls_addr(&search_string), 0, NULL, NULL) != -1) {
358  bu_vls_free(&argvls);
359  bu_vls_free(&search_string);
360  bu_free_argv(argc, argv);
361  _ged_free_search_set(search_set);
362  bu_vls_trunc(gedp->ged_result_str, 0);
363  return (wflag) ? GED_OK : GED_ERROR;
364  }
365 
366  /* Check if all of our searches are local or not */
367  for (i = (int)BU_PTBL_LEN(search_set) - 1; i >= 0; i--) {
368  struct ged_search *search = (struct ged_search *)BU_PTBL_GET(search_set, i);
369  if (search->search_type != 1) all_local = 0;
370  }
371 
372  /* If all searches are local, use all supplied paths in the search to
373  * return one unique list of objects. If one or more paths are non-local,
374  * each path is treated as its own search */
375  if (all_local) {
376  struct bu_ptbl *uniq_db_objs;
377  BU_ALLOC(uniq_db_objs, struct bu_ptbl);
378  BU_PTBL_INIT(uniq_db_objs);
379  for (i = (int)BU_PTBL_LEN(search_set) - 1; i >= 0; i--) {
380  int path_cnt = 0;
381  struct ged_search *search = (struct ged_search *)BU_PTBL_GET(search_set, i);
382  struct directory *curr_path = search->paths[path_cnt];
383  while (path_cnt < search->path_cnt) {
384  flags |= DB_SEARCH_RETURN_UNIQ_DP;
385  (void)db_search(uniq_db_objs, flags, bu_vls_addr(&search_string), 1, &curr_path, gedp->ged_wdbp->dbip);
386  path_cnt++;
387  curr_path = search->paths[path_cnt];
388  }
389  }
390  /* For this return, we want a list of all unique leaf objects */
391  for (i = (int)BU_PTBL_LEN(uniq_db_objs) - 1; i >= 0; i--) {
392  struct directory *uniq_dp = (struct directory *)BU_PTBL_GET(uniq_db_objs, i);
393  bu_vls_printf(gedp->ged_result_str, "%s\n", uniq_dp->d_namep);
394  }
395  bu_ptbl_free(uniq_db_objs);
396  bu_free(uniq_db_objs, "free unique object container");
397  } else {
398  /* Search types are either mixed or all full path, so use the standard calls and print
399  * the full output of each search */
400  for (i = 0; i < (int)BU_PTBL_LEN(search_set); i++) {
401  int path_cnt = 0;
402  int j;
403  struct ged_search *search = (struct ged_search *)BU_PTBL_GET(search_set, i);
404  if (search && (search->path_cnt > 0 || search->search_type == 2)) {
405  if (search->search_type == 2) {
406  int k;
407  struct bu_ptbl *search_results;
408  flags |= DB_SEARCH_FLAT;
409  BU_ALLOC(search_results, struct bu_ptbl);
410  bu_ptbl_init(search_results, 8, "initialize search result table");
411  for (k = 0; k < RT_DBNHASH; k++) {
412  struct directory *dp;
413  for (dp = gedp->ged_wdbp->dbip->dbi_Head[k]; dp != RT_DIR_NULL; dp = dp->d_forw) {
414  if (dp->d_addr != RT_DIR_PHONY_ADDR) {
415  (void)db_search(search_results, flags, bu_vls_addr(&search_string), 1, &dp, gedp->ged_wdbp->dbip);
416  }
417  }
418  }
419  if (BU_PTBL_LEN(search_results) > 0) {
420  for (j = (int)BU_PTBL_LEN(search_results) - 1; j >= 0; j--) {
421  struct directory *uniq_dp = (struct directory *)BU_PTBL_GET(search_results, j);
422  bu_vls_printf(gedp->ged_result_str, "%s\n", uniq_dp->d_namep);
423  }
424  }
425  db_search_free(search_results);
426  bu_free(search_results, "free search container");
427  } else {
428  struct directory *curr_path = search->paths[path_cnt];
429  while (path_cnt < search->path_cnt) {
430  struct bu_ptbl *search_results;
431  struct bu_vls fullpath_string = BU_VLS_INIT_ZERO;
432  BU_ALLOC(search_results, struct bu_ptbl);
433  bu_ptbl_init(search_results, 8, "initialize search result table");
434  switch (search->search_type) {
435  case 0:
436  (void)db_search(search_results, flags, bu_vls_addr(&search_string), 1, &curr_path, gedp->ged_wdbp->dbip);
437  if (BU_PTBL_LEN(search_results) > 0) {
438  for (j = (int)BU_PTBL_LEN(search_results) - 1; j >= 0; j--) {
439  struct db_full_path *dfptr = (struct db_full_path *)BU_PTBL_GET(search_results, j);
440  bu_vls_trunc(&fullpath_string, 0);
441  db_fullpath_to_vls(&fullpath_string, dfptr, gedp->ged_wdbp->dbip, print_verbose_info);
442  bu_vls_printf(gedp->ged_result_str, "%s\n", bu_vls_addr(&fullpath_string));
443  }
444  }
445  break;
446  case 1:
447  flags |= DB_SEARCH_RETURN_UNIQ_DP;
448  (void)db_search(search_results, flags, bu_vls_addr(&search_string), 1, &curr_path, gedp->ged_wdbp->dbip);
449  for (j = (int)BU_PTBL_LEN(search_results) - 1; j >= 0; j--) {
450  struct directory *uniq_dp = (struct directory *)BU_PTBL_GET(search_results, j);
451  bu_vls_printf(gedp->ged_result_str, "%s\n", uniq_dp->d_namep);
452  }
453  break;
454  default:
455  bu_log("Warning - ignoring unknown search type %d\n", search->search_type);
456  break;
457  }
458  db_search_free(search_results);
459  bu_free(search_results, "free search container");
460  bu_vls_free(&fullpath_string);
461  path_cnt++;
462  curr_path = search->paths[path_cnt];
463  }
464  }
465  }
466  }
467  }
468 
469  /* Done - free memory */
470  bu_vls_free(&argvls);
471  bu_vls_free(&search_string);
472  bu_free_argv(argc, argv);
473  _ged_free_search_set(search_set);
474  return GED_OK;
475 }
476 
477 
478 /*
479  * Local Variables:
480  * tab-width: 8
481  * mode: C
482  * indent-tabs-mode: t
483  * c-file-style: "stroustrup"
484  * End:
485  * ex: shiftwidth=4 tabstop=8
486  */
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
struct directory ** paths
Definition: search.c:44
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
const char * db_normalize(const char *path)
Definition: db_path.c:64
#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
HIDDEN int _ged_search_characterize_path(struct ged *gedp, const char *orig, struct bu_vls *normalized, int *is_specific, int *is_local, int *is_flat, int *flat_only)
Definition: search.c:128
void db_search_free(struct bu_ptbl *search_results)
Definition: search.c:2089
#define DB_SEARCH_HIDDEN
Search using hidden objects.
Definition: search.h:112
int ged_search(struct ged *gedp, int argc, const char *argv_orig[])
Definition: search.c:198
#define DB_SEARCH_FLAT
Do a flat search without hierarchy.
Definition: search.h:111
void bu_free_argv(int argc, char *argv[])
Definition: argv.c:165
void db_fullpath_to_vls(struct bu_vls *vls, const struct db_full_path *full_path, const struct db_i *dbip, int fp_flags)
Definition: db_fullpath.c:254
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
void bu_vls_nibble(struct bu_vls *vp, off_t len)
Definition: vls.c:217
struct directory * db_lookup(const struct db_i *, const char *name, int noisy)
Definition: db_lookup.c:153
HIDDEN int _path_scrub(struct bu_vls *path)
Definition: search.c:51
#define DB_SEARCH_RETURN_UNIQ_DP
Return the set of unique directory pointers instead of full paths.
Definition: search.h:113
struct rt_wdb * ged_wdbp
Definition: ged.h:340
Header file for the BRL-CAD common definitions.
int bu_optind
Definition: globals.c:89
HIDDEN int _ged_plan_item(char *arg)
Definition: search.c:108
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
#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
Definition: ptbl.h:62
#define DB_FP_PRINT_BOOL
Definition: db_fullpath.h:107
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
int bu_optopt
Definition: globals.c:90
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
#define BU_PTBL_GET(ptbl, i)
Definition: ptbl.h:108
void bu_vls_sprintf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:707
#define LOOKUP_QUIET
Definition: raytrace.h:893
#define DB_LS_TOPS
Definition: raytrace.h:4657
#define DB_FP_PRINT_TYPE
Definition: db_fullpath.h:108
#define RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
#define BU_PTBL_INIT(_p)
Definition: ptbl.h:80
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
struct bu_vls * ged_result_str
Definition: ged.h:357
size_t db_ls(const struct db_i *dbip, int flags, const char *pattern, struct directory ***dpv)
Definition: ls.c:58
#define BU_PTBL_LEN(ptbl)
Definition: ptbl.h:107
void bu_ptbl_free(struct bu_ptbl *b)
Definition: ptbl.c:226
HIDDEN void _ged_free_search_set(struct bu_ptbl *search_set)
Definition: search.c:81
void bu_basename(char *basename, const char *path)
Definition: basename.c:30
struct directory * dbi_Head[RT_DBNHASH]
Definition: raytrace.h:814
#define DB_SEARCH_QUIET
Silence all warnings.
Definition: search.h:114
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
char ** bu_dup_argv(int argc, const char *argv[])
Definition: argv.c:207
int search_type
Definition: search.c:46
HIDDEN int _ged_search_localized_obj_list(struct ged *gedp, struct directory *path, struct directory ***path_list)
Definition: search.c:177
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
Definition: vls.h:56
void db_update_nref(struct db_i *dbip, struct resource *resp)
Definition: db_match.c:75
int path_cnt
Definition: search.c:45
#define DB_LS_HIDDEN
Definition: raytrace.h:4655
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126
int db_search(struct bu_ptbl *search_results, int search_flags, const char *plan_str, int input_path_cnt, struct directory **input_paths, struct db_i *dbip)
Search for objects in a geometry database using filters.
Definition: search.c:2232