BRL-CAD
glob.c
Go to the documentation of this file.
1 /* G L O B . 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/glob.c
21  *
22  * The glob command.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 
32 #include "./ged_private.h"
33 
34 
35 /**
36  * unescapes various special characters
37  */
38 static void
39 debackslash(struct bu_vls *dest, struct bu_vls *src)
40 {
41  char *ptr;
42 
43  ptr = bu_vls_addr(src);
44  while (*ptr) {
45  if (*ptr == '\\')
46  ++ptr;
47  if (*ptr == '\0')
48  break;
49  bu_vls_putc(dest, *ptr++);
50  }
51 }
52 
53 
54 /**
55  * escapes various special characters
56  */
57 static void
58 backslash(struct bu_vls *dest, struct bu_vls *src)
59 {
60  int backslashed;
61  char *ptr, buf[2];
62 
63  buf[1] = '\0';
64  backslashed = 0;
65  for (ptr = bu_vls_addr(src); *ptr; ptr++) {
66  if (*ptr == '[' && !backslashed)
67  bu_vls_strcat(dest, "\\[");
68  else if (*ptr == ']' && !backslashed)
69  bu_vls_strcat(dest, "\\]");
70  else if (backslashed) {
71  bu_vls_strcat(dest, "\\");
72  buf[0] = *ptr;
73  bu_vls_strcat(dest, buf);
74  backslashed = 0;
75  } else if (*ptr == '\\')
76  backslashed = 1;
77  else {
78  buf[0] = *ptr;
79  bu_vls_strcat(dest, buf);
80  }
81  }
82 }
83 
84 
85 int
86 ged_glob(struct ged *gedp, int argc, const char *argv[])
87 {
88  char *start, *end; /* Start and ends of words */
89  int regexp; /* Set to TRUE when word is a regexp */
90  int backslashed;
91  struct bu_vls word = BU_VLS_INIT_ZERO; /* Current word being processed */
92  struct bu_vls temp = BU_VLS_INIT_ZERO;
93  struct bu_vls src = BU_VLS_INIT_ZERO;
94  static const char *usage = "expression";
95 
96  /* Silently return */
97  if (gedp == GED_NULL)
98  return GED_ERROR;
99 
100  /* initialize result */
101  bu_vls_trunc(gedp->ged_result_str, 0);
102 
103  /* must be wanting help */
104  if (argc == 1) {
105  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
106  return GED_HELP;
107  }
108 
109  if (argc != 2) {
110  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
111  return GED_ERROR;
112  }
113 
114  bu_vls_strcat(&src, argv[1]);
115 
116  start = end = bu_vls_addr(&src);
117  while (*end != '\0') {
118  /* Run through entire string */
119 
120  /* First, pass along leading whitespace. */
121 
122  start = end; /* Begin where last word ended */
123  while (*start != '\0') {
124  if (*start == ' ' ||
125  *start == '\t' ||
126  *start == '\n')
127  bu_vls_putc(gedp->ged_result_str, *start++);
128  else
129  break;
130  }
131  if (*start == '\0')
132  break;
133 
134  /* Next, advance "end" pointer to the end of the word, while adding
135  each character to the "word" vls. Also make a note of any
136  unbackslashed wildcard characters. */
137 
138  end = start;
139  bu_vls_trunc(&word, 0);
140  regexp = 0;
141  backslashed = 0;
142  while (*end != '\0') {
143  if (*end == ' ' ||
144  *end == '\t' ||
145  *end == '\n')
146  break;
147  if ((*end == '*' || *end == '?' || *end == '[') && !backslashed)
148  regexp = 1;
149  if (*end == '\\' && !backslashed)
150  backslashed = 1;
151  else
152  backslashed = 0;
153  bu_vls_putc(&word, *end++);
154  }
155 
156  /* Now, if the word was suspected of being a wildcard, try to match
157  it to the database. */
158 
159  if (regexp) {
160  register int i, num;
161  register struct directory *dp;
162  /* No database to match against, so return. */
163  if (gedp->ged_wdbp == RT_WDB_NULL || gedp->ged_wdbp->dbip == DBI_NULL)
164  return GED_OK;
165 
166  bu_vls_trunc(&temp, 0);
167  for (i = num = 0; i < RT_DBNHASH; i++) {
168  for (dp = gedp->ged_wdbp->dbip->dbi_Head[i]; dp != RT_DIR_NULL; dp = dp->d_forw) {
169  if (bu_fnmatch(bu_vls_addr(&word), dp->d_namep, 0) != 0)
170  continue;
171  if (num == 0)
172  bu_vls_strcat(&temp, dp->d_namep);
173  else {
174  bu_vls_strcat(&temp, " ");
175  bu_vls_strcat(&temp, dp->d_namep);
176  }
177  ++num;
178  }
179  }
180 
181  if (num == 0) {
182  debackslash(&temp, &word);
183  backslash(gedp->ged_result_str, &temp);
184  } else
185  bu_vls_vlscat(gedp->ged_result_str, &temp);
186  } else {
187  debackslash(gedp->ged_result_str, &word);
188  }
189  }
190 
191  bu_vls_free(&temp);
192  bu_vls_free(&word);
193  bu_vls_free(&src);
194 
195  return GED_OK;
196 }
197 
198 
199 /*
200  * Local Variables:
201  * tab-width: 8
202  * mode: C
203  * indent-tabs-mode: t
204  * c-file-style: "stroustrup"
205  * End:
206  * ex: shiftwidth=4 tabstop=8
207  */
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 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
Definition: ged.h:338
struct db_i * dbip
Definition: raytrace.h:1266
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
struct rt_wdb * ged_wdbp
Definition: ged.h:340
Header file for the BRL-CAD common definitions.
int ged_glob(struct ged *gedp, int argc, const char *argv[])
Definition: glob.c:86
struct directory * d_forw
link to next dir entry
Definition: raytrace.h:864
#define GED_ERROR
Definition: ged.h:61
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
int bu_fnmatch(const char *pattern, const char *pathname, int flags)
Definition: fnmatch.c:311
#define GED_NULL
Definition: ged.h:72
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
struct bu_vls * ged_result_str
Definition: ged.h:357
struct directory * dbi_Head[RT_DBNHASH]
Definition: raytrace.h:814
#define DBI_NULL
Definition: raytrace.h:827
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 GED_HELP
Definition: ged.h:62
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
void bu_vls_vlscat(struct bu_vls *dest, const struct bu_vls *src)
Definition: vls.c:415
Definition: vls.h:56
void bu_vls_putc(struct bu_vls *vp, int c)
Definition: vls.c:666
#define RT_WDB_NULL
Definition: raytrace.h:1294