BRL-CAD
tcl.c
Go to the documentation of this file.
1 /* T C L . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1998-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 
21 #include "common.h"
22 
23 #include <stdlib.h>
24 #include <math.h>
25 #include <string.h>
26 #include <ctype.h>
27 
28 #include "tcl.h"
29 #include "bu/cmd.h"
30 #include "bu/color.h"
31 #include "bu/debug.h"
32 #include "bu/file.h"
33 #include "bu/malloc.h"
34 #include "bu/str.h"
35 #include "bu/units.h"
36 #include "bu/bu_tcl.h"
37 #include "vmath.h"
38 
39 
40 /*XXX Temporary global interp */
41 Tcl_Interp *brlcad_interp = (Tcl_Interp *)0;
42 
43 #define TINYBUFSIZ 32
44 #define SMALLBUFSIZ 256
45 
46 
47 /**
48  * A wrapper for bu_mem_barriercheck.
49  *
50  * @param clientData - associated data/state
51  * @param argc - number of elements in argv
52  * @param argv - command name and arguments
53  *
54  * @return BRLCAD_OK if successful, otherwise, BRLCAD_ERROR.
55  */
56 HIDDEN int
57 tcl_bu_mem_barriercheck(void *UNUSED(clientData),
58  int argc,
59  const char **argv)
60 {
61  int ret;
62 
63  if (argc > 1) {
64  bu_log("Usage: %s\n", argv[0]);
65  return BRLCAD_ERROR;
66  }
67 
68  ret = bu_mem_barriercheck();
69  if (UNLIKELY(ret < 0)) {
70  bu_log("bu_mem_barriercheck() failed\n");
71  return BRLCAD_ERROR;
72  }
73  return BRLCAD_OK;
74 }
75 
76 
77 /**
78  * A wrapper for bu_prmem. Prints map of memory currently in use, to
79  * stderr.
80  *
81  * @param clientData - associated data/state
82  * @param argc - number of elements in argv
83  * @param argv - command name and arguments
84  *
85  * @return BRLCAD_OK if successful, otherwise, BRLCAD_ERROR.
86  */
87 HIDDEN int
88 tcl_bu_prmem(void *UNUSED(clientData),
89  int argc,
90  const char **argv)
91 {
92  if (argc != 2) {
93  bu_log("Usage: bu_prmem title\n");
94  return BRLCAD_ERROR;
95  }
96 
97  bu_prmem(argv[1]);
98  return BRLCAD_OK;
99 }
100 
101 
102 /**
103  * Given arguments of alternating keywords and values and a specific
104  * keyword ("Iwant"), return the value associated with that keyword.
105  *
106  * example: bu_get_value_by_keyword Iwant az 35 elev 25 temp 9.6
107  *
108  * If only one argument is given after the search keyword, it is
109  * interpreted as a list in the same format.
110  *
111  * example: bu_get_value_by_keyword Iwant {az 35 elev 25 temp 9.6}
112  *
113  * Search order is left-to-right, only first match is returned.
114  *
115  * Sample use:
116  * bu_get_value_by_keyword V8 [concat type [.inmem get box.s]]
117  *
118  * @param clientData - associated data/state
119  * @param argc - number of elements in argv
120  * @param argv - command name and arguments
121  *
122  * @return BRLCAD_OK if successful, otherwise, BRLCAD_ERROR.
123  */
124 HIDDEN int
126  int argc,
127  const char **argv)
128 {
129  Tcl_Interp *interp = (Tcl_Interp *)clientData;
130  int i = 0;
131  int listc = 0;
132  const char *iwant = (const char *)NULL;
133  const char **listv = (const char **)NULL;
134  const char **tofree = (const char **)NULL;
135 
136  if (argc < 3) {
137  char buf[TINYBUFSIZ];
138  snprintf(buf, TINYBUFSIZ, "%d", argc);
139  bu_log("bu_get_value_by_keyword: wrong # of args (%s).\n"
140  "Usage: bu_get_value_by_keyword iwant {list}\n"
141  "Usage: bu_get_value_by_keyword iwant key1 val1 key2 val2 ... keyN valN\n", buf);
142  return BRLCAD_ERROR;
143  }
144 
145  iwant = argv[1];
146 
147  if (argc == 3) {
148  if (Tcl_SplitList(interp, argv[2], &listc, (const char ***)&listv) != TCL_OK) {
149  bu_log("bu_get_value_by_keyword: iwant='%s', unable to split '%s'\n", iwant, argv[2]);
150  return BRLCAD_ERROR;
151  }
152  tofree = listv;
153  } else {
154  /* Take search list from remaining arguments */
155  listc = argc - 2;
156  listv = argv + 2;
157  }
158 
159  if ((listc & 1) != 0) {
160  char buf[TINYBUFSIZ];
161  snprintf(buf, TINYBUFSIZ, "%d", listc);
162  bu_log("bu_get_value_by_keyword: odd # of items in list (%s).\n", buf);
163 
164  if (tofree)
165  Tcl_Free((char *)tofree); /* not bu_free() */
166  return BRLCAD_ERROR;
167  }
168 
169  for (i=0; i < listc; i += 2) {
170  if (BU_STR_EQUAL(iwant, listv[i])) {
171  /* If value is a list, don't nest it in another list */
172  if (listv[i+1][0] == '{') {
173  struct bu_vls str = BU_VLS_INIT_ZERO;
174 
175  /* Skip leading { */
176  bu_vls_strcat(&str, &listv[i+1][1]);
177  /* Trim trailing } */
178  bu_vls_trunc(&str, -1);
179  Tcl_AppendResult(interp, bu_vls_addr(&str), NULL);
180  bu_vls_free(&str);
181  } else {
182  Tcl_AppendResult(interp, listv[i+1], NULL);
183  }
184 
185  if (tofree)
186  Tcl_Free((char *)tofree); /* not bu_free() */
187  return BRLCAD_OK;
188  }
189  }
190 
191  /* Not found */
192 
193  if (tofree)
194  Tcl_Free((char *)tofree); /* not bu_free() */
195  return BRLCAD_ERROR;
196 }
197 
198 
199 /**
200  * A wrapper for bu_rgb_to_hsv.
201  *
202  * @param clientData - associated data/state
203  * @param argc - number of elements in argv
204  * @param argv - command name and arguments
205  *
206  * @return BRLCAD_OK if successful, otherwise, BRLCAD_ERROR.
207  */
208 HIDDEN int
209 tcl_bu_rgb_to_hsv(void *clientData,
210  int argc,
211  const char **argv)
212 {
213  Tcl_Interp *interp = (Tcl_Interp *)clientData;
214  int rgb_int[3];
215  unsigned char rgb[3];
216  fastf_t hsv[3];
217  struct bu_vls result = BU_VLS_INIT_ZERO;
218 
219  if (argc != 4) {
220  bu_log("Usage: bu_rgb_to_hsv R G B\n");
221  return BRLCAD_ERROR;
222  }
223  if (sscanf(argv[1], "%d", &rgb_int[0]) != 1
224  || sscanf(argv[2], "%d", &rgb_int[1]) != 1
225  || sscanf(argv[3], "%d", &rgb_int[2]) != 1
226  || (rgb_int[0] < 0) || (rgb_int[0] > 255)
227  || (rgb_int[1] < 0) || (rgb_int[1] > 255)
228  || (rgb_int[2] < 0) || (rgb_int[2] > 255)) {
229  bu_vls_printf(&result, "bu_rgb_to_hsv: Bad RGB (%s, %s, %s)\n",
230  argv[1], argv[2], argv[3]);
231  bu_log("ERROR: %s", bu_vls_addr(&result));
232  bu_vls_free(&result);
233  return BRLCAD_ERROR;
234  }
235  rgb[0] = rgb_int[0];
236  rgb[1] = rgb_int[1];
237  rgb[2] = rgb_int[2];
238 
239  bu_rgb_to_hsv(rgb, hsv);
240  bu_vls_printf(&result, "%g %g %g", hsv[0], hsv[1], hsv[2]);
241  Tcl_AppendResult(interp, bu_vls_addr(&result), NULL);
242  bu_vls_free(&result);
243  return BRLCAD_OK;
244 
245 }
246 
247 
248 /**
249  * A wrapper for bu_hsv_to_rgb.
250  *
251  * @param clientData - associated data/state
252  * @param argc - number of elements in argv
253  * @param argv - command name and arguments
254  *
255  * @return BRLCAD_OK if successful, otherwise, BRLCAD_ERROR.
256  */
257 HIDDEN int
258 tcl_bu_hsv_to_rgb(void *clientData,
259  int argc,
260  const char **argv)
261 {
262  Tcl_Interp *interp = (Tcl_Interp *)clientData;
263 
264  double vals[3];
265  fastf_t hsv[3];
266  unsigned char rgb[3];
267  struct bu_vls result = BU_VLS_INIT_ZERO;
268 
269  if (argc != 4) {
270  bu_log("Usage: bu_hsv_to_rgb H S V\n");
271  return BRLCAD_ERROR;
272  }
273  if (sscanf(argv[1], "%lf", &vals[0]) != 1
274  || sscanf(argv[2], "%lf", &vals[1]) != 1
275  || sscanf(argv[3], "%lf", &vals[2]) != 1)
276  {
277  bu_log("Bad HSV parsing (%s, %s, %s)\n", argv[1], argv[2], argv[3]);
278  return BRLCAD_ERROR;
279  }
280 
281  VMOVE(hsv, vals);
282  if (bu_hsv_to_rgb(hsv, rgb) == 0) {
283  bu_log("HSV to RGB conversion failed (%s, %s, %s)\n", argv[1], argv[2], argv[3]);
284  return BRLCAD_ERROR;
285  }
286 
287  bu_vls_printf(&result, "%d %d %d", rgb[0], rgb[1], rgb[2]);
288  Tcl_AppendResult(interp, bu_vls_addr(&result), NULL);
289  bu_vls_free(&result);
290  return BRLCAD_OK;
291 
292 }
293 
294 /**
295  * A wrapper for bu_brlcad_dir.
296  *
297  * @param clientData - associated data/state
298  * @param argc - number of elements in argv
299  * @param argv - command name and arguments
300  *
301  * @return BRLCAD_OK if successful, otherwise, BRLCAD_ERROR.
302  */
303 HIDDEN int
304 tcl_bu_brlcad_dir(void *clientData,
305  int argc,
306  const char **argv)
307 {
308  Tcl_Interp *interp = (Tcl_Interp *)clientData;
309  if (argc != 2) {
310  bu_log("Usage: bu_brlcad_dir dirkey\n");
311  return BRLCAD_ERROR;
312  }
313  Tcl_AppendResult(interp, bu_brlcad_dir(argv[1], 1), NULL);
314  return BRLCAD_OK;
315 }
316 
317 /**
318  * A wrapper for bu_brlcad_root.
319  *
320  * @param clientData - associated data/state
321  * @param argc - number of elements in argv
322  * @param argv - command name and arguments
323  *
324  * @return BRLCAD_OK if successful, otherwise, BRLCAD_ERROR.
325  */
326 HIDDEN int
327 tcl_bu_brlcad_root(void *clientData,
328  int argc,
329  const char **argv)
330 {
331  Tcl_Interp *interp = (Tcl_Interp *)clientData;
332  if (argc != 2) {
333  bu_log("Usage: bu_brlcad_root subdir\n");
334  return BRLCAD_ERROR;
335  }
336  Tcl_AppendResult(interp, bu_brlcad_root(argv[1], 1), NULL);
337  return BRLCAD_OK;
338 }
339 
340 
341 /**
342  * A wrapper for bu_brlcad_data.
343  *
344  * @param clientData - associated data/state
345  * @param argc - number of elements in argv
346  * @param argv - command name and arguments
347  *
348  * @return BRLCAD_OK if successful, otherwise, BRLCAD_ERROR.
349  */
350 HIDDEN int
351 tcl_bu_brlcad_data(void *clientData,
352  int argc,
353  const char **argv)
354 {
355  Tcl_Interp *interp = (Tcl_Interp *)clientData;
356  if (argc != 2) {
357  bu_log("Usage: bu_brlcad_data subdir\n");
358  return BRLCAD_ERROR;
359  }
360  Tcl_AppendResult(interp, bu_brlcad_data(argv[1], 1), NULL);
361  return BRLCAD_OK;
362 }
363 
364 
365 /**
366  * A wrapper for bu_units_conversion.
367  *
368  * @param clientData - associated data/state
369  * @param argc - number of elements in argv
370  * @param argv - command name and arguments
371  *
372  * @return BRLCAD_OK if successful, otherwise, BRLCAD_ERROR.
373  */
374 HIDDEN int
375 tcl_bu_units_conversion(void *clientData,
376  int argc,
377  const char **argv)
378 {
379  Tcl_Interp *interp = (Tcl_Interp *)clientData;
380  double conv_factor;
381  struct bu_vls result = BU_VLS_INIT_ZERO;
382 
383  if (argc != 2) {
384  bu_log("Usage: bu_units_conversion units_string\n");
385  return BRLCAD_ERROR;
386  }
387 
388  conv_factor = bu_units_conversion(argv[1]);
389  if (conv_factor <= 0.0) {
390  bu_log("ERROR: bu_units_conversion: Unrecognized units string: %s\n", argv[1]);
391  return BRLCAD_ERROR;
392  }
393 
394  bu_vls_printf(&result, "%.12e", conv_factor);
395  Tcl_AppendResult(interp, bu_vls_addr(&result), NULL);
396  bu_vls_free(&result);
397  return BRLCAD_OK;
398 }
399 
400 
401 static int
402 wrapper_func(ClientData data, Tcl_Interp *interp, int argc, const char *argv[])
403 {
404  struct bu_cmdtab *ctp = (struct bu_cmdtab *)data;
405 
406  return ctp->ct_func(interp, argc, argv);
407 }
408 
409 
410 static void
411 register_cmds(Tcl_Interp *interp, struct bu_cmdtab *cmds)
412 {
413  struct bu_cmdtab *ctp = NULL;
414 
415  for (ctp = cmds; ctp->ct_name != (char *)NULL; ctp++) {
416  (void)Tcl_CreateCommand(interp, ctp->ct_name, wrapper_func, (ClientData)ctp, (Tcl_CmdDeleteProc *)NULL);
417  }
418 }
419 
420 
421 int
422 Bu_Init(void *p)
423 {
424  Tcl_Interp *interp = (Tcl_Interp *)p;
425 
426  static struct bu_cmdtab cmds[] = {
427  {"bu_units_conversion", tcl_bu_units_conversion},
428  {"bu_brlcad_data", tcl_bu_brlcad_data},
429  {"bu_brlcad_dir", tcl_bu_brlcad_dir},
430  {"bu_brlcad_root", tcl_bu_brlcad_root},
431  {"bu_mem_barriercheck", tcl_bu_mem_barriercheck},
432  {"bu_prmem", tcl_bu_prmem},
433  {"bu_get_value_by_keyword", tcl_bu_get_value_by_keyword},
434  {"bu_rgb_to_hsv", tcl_bu_rgb_to_hsv},
435  {"bu_hsv_to_rgb", tcl_bu_hsv_to_rgb},
436  {(const char *)NULL, BU_CMD_NULL}
437  };
438 
439  /*XXX Use of brlcad_interp is temporary */
441 
442  register_cmds(interp, cmds);
443 
444  Tcl_SetVar(interp, "BU_DEBUG_FORMAT", BU_DEBUG_FORMAT, TCL_GLOBAL_ONLY);
445  Tcl_LinkVar(interp, "bu_debug", (char *)&bu_debug, TCL_LINK_INT);
446 
447  return BRLCAD_OK;
448 }
449 
450 
451 /*
452  * Local Variables:
453  * mode: C
454  * tab-width: 8
455  * indent-tabs-mode: t
456  * c-file-style: "stroustrup"
457  * End:
458  * ex: shiftwidth=4 tabstop=8
459  */
Definition: cmd.h:48
#define BU_DEBUG_FORMAT
Definition: debug.h:79
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
int bu_hsv_to_rgb(fastf_t *hsv, unsigned char *rgb)
Definition: color.c:121
ustring interp
void bu_prmem(const char *str)
Definition: malloc.c:516
int Bu_Init(void *p)
Definition: tcl.c:422
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
Header file for the BRL-CAD common definitions.
#define BU_CMD_NULL
Definition: cmd.h:37
#define HIDDEN
Definition: common.h:86
void bu_rgb_to_hsv(unsigned char *rgb, fastf_t *hsv)
Definition: color.c:60
HIDDEN int tcl_bu_hsv_to_rgb(void *clientData, int argc, const char **argv)
Definition: tcl.c:258
const char * bu_brlcad_data(const char *rhs, int fail_quietly)
Definition: brlcad_path.c:405
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
COMPLEX data[64]
Definition: fftest.c:34
double bu_units_conversion(const char *str)
Definition: units.c:234
#define BRLCAD_OK
Definition: defines.h:71
HIDDEN int tcl_bu_brlcad_dir(void *clientData, int argc, const char **argv)
Definition: tcl.c:304
#define UNUSED(parameter)
Definition: common.h:239
const char * ct_name
Definition: cmd.h:49
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
int bu_mem_barriercheck(void)
Definition: malloc.c:660
const char * bu_brlcad_dir(const char *dirkey, int fail_quietly)
Definition: brlcad_path.c:231
int bu_debug
Definition: globals.c:87
HIDDEN int tcl_bu_brlcad_data(void *clientData, int argc, const char **argv)
Definition: tcl.c:351
HIDDEN int tcl_bu_units_conversion(void *clientData, int argc, const char **argv)
Definition: tcl.c:375
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
#define TINYBUFSIZ
Definition: tcl.c:43
HIDDEN int tcl_bu_mem_barriercheck(void *clientData, int argc, const char **argv)
Definition: tcl.c:57
int(* ct_func)(void *data, int argc, const char *argv[])
Definition: cmd.h:50
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
const char * bu_brlcad_root(const char *rhs, int fail_quietly)
Definition: brlcad_path.c:292
Definition: vls.h:56
#define BRLCAD_ERROR
Definition: defines.h:72
double fastf_t
Definition: defines.h:300
HIDDEN int tcl_bu_brlcad_root(void *clientData, int argc, const char **argv)
Definition: tcl.c:327
HIDDEN int tcl_bu_rgb_to_hsv(void *clientData, int argc, const char **argv)
Definition: tcl.c:209
HIDDEN int tcl_bu_prmem(void *clientData, int argc, const char **argv)
Definition: tcl.c:88
Tcl_Interp * brlcad_interp
Definition: tcl.c:41
#define UNLIKELY(expression)
Definition: common.h:282
HIDDEN int tcl_bu_get_value_by_keyword(void *clientData, int argc, const char **argv)
Definition: tcl.c:125
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126