bu_tcl.c

Go to the documentation of this file.
00001 /*                        B U _ T C L . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1998-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** \addtogroup butcl */
00023 /*@{*/
00024 /** @file bu_tcl.c
00025  * @brief
00026  *      Tcl interfaces to all the LIBBU Basic BRL-CAD Utility routines.
00027  *
00028  *      Remember that in MGED you need to say "set glob_compat_mode 0"
00029  *      to get [] to work with TCL semantics rather than MGED glob semantics.
00030  *
00031  * @author Michael John Muuss
00032  *
00033  * @par Source -
00034  *      The U. S. Army Research Laboratory                      @n
00035  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00036  */
00037 
00038 #ifndef lint
00039 static const char libbu_bu_tcl_RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbu/bu_tcl.c,v 14.15 2006/08/31 05:50:24 lbutler Exp $ (ARL)";
00040 #endif
00041 
00042 #include "common.h"
00043 
00044 #include <stdlib.h>
00045 #include <stdio.h>
00046 #include <math.h>
00047 #ifdef HAVE_STRING_H
00048 #  include <string.h>
00049 #else
00050 #  include <strings.h>
00051 #endif
00052 #include <ctype.h>
00053 
00054 #include "tcl.h"
00055 #include "machine.h"
00056 #include "cmd.h"                /* this includes bu.h */
00057 #include "vmath.h"
00058 #include "bn.h"
00059 #include "bu.h"
00060 
00061 /* defined in libbu/cmdhist_obj.c */
00062 extern int Cho_Init(Tcl_Interp *interp);
00063 
00064 static struct bu_cmdtab bu_cmds[] = {
00065         {"bu_units_conversion",         bu_tcl_units_conversion},
00066         {"bu_brlcad_data",              bu_tcl_brlcad_data},
00067         {"bu_brlcad_path",              bu_tcl_brlcad_path},
00068         {"bu_brlcad_root",              bu_tcl_brlcad_root},
00069         {"bu_mem_barriercheck",         bu_tcl_mem_barriercheck},
00070         {"bu_ck_malloc_ptr",            bu_tcl_ck_malloc_ptr},
00071         {"bu_malloc_len_roundup",       bu_tcl_malloc_len_roundup},
00072         {"bu_prmem",                    bu_tcl_prmem},
00073         {"bu_printb",                   bu_tcl_printb,},
00074         {"bu_get_all_keyword_values",   bu_get_all_keyword_values},
00075         {"bu_get_value_by_keyword",     bu_get_value_by_keyword},
00076         {"bu_rgb_to_hsv",               bu_tcl_rgb_to_hsv},
00077         {"bu_hsv_to_rgb",               bu_tcl_hsv_to_rgb},
00078         {"bu_key_eq_to_key_val",        bu_tcl_key_eq_to_key_val},
00079         {"bu_shader_to_tcl_list",       bu_tcl_shader_to_key_val},
00080         {"bu_key_val_to_key_eq",        bu_tcl_key_val_to_key_eq},
00081         {"bu_shader_to_key_eq",         bu_tcl_shader_to_key_eq},
00082         {(char *)NULL,  (int (*)())0 }
00083 };
00084 
00085 /**
00086  *      b u _ b a d m a g i c _ t c l
00087  * 
00088  *      Support routine for BU_CKMAG_TCL macro. As used by
00089  *      BU_CKMAG_TCL, this routine is not called unless there
00090  *      is trouble with the pointer. When called, an appropriate
00091  *      message is added to interp indicating the problem.
00092  *
00093  * 
00094  *      @param interp   - tcl interpreter where result is stored
00095  *      @param ptr      - pointer to a data structure
00096  *      @param magic    - the correct/desired magic number
00097  *      @param str      - usually indicates the data structure name
00098  *      @param file     - file where this routine was called
00099  *      @param line     - line number in the above file
00100  *
00101  *      @return
00102  *              void
00103  */
00104 
00105 void
00106 bu_badmagic_tcl(Tcl_Interp      *interp,
00107                 const long      *ptr,
00108                 unsigned long   magic,
00109                 const char      *str,
00110                 const char      *file,
00111                 int             line)
00112 {
00113         char    buf[256];
00114 
00115         if (!(ptr)) {
00116                 sprintf(buf, "ERROR: NULL %s pointer in TCL interface, file %s, line %d\n",
00117                         str, file, line);
00118                 Tcl_AppendResult(interp, buf, NULL);
00119                 return;
00120         }
00121         if (*((long *)(ptr)) != (magic)) {
00122                 sprintf(buf, "ERROR: bad pointer in TCL interface x%lx: s/b %s(x%lx), was %s(x%lx), file %s, line %d\n",
00123                         (long)ptr,
00124                         str, magic,
00125                         bu_identify_magic( *(ptr) ), *(ptr),
00126                         file, line);
00127                 Tcl_AppendResult(interp, buf, NULL);
00128                 return;
00129         }
00130         Tcl_AppendResult(interp, "bu_badmagic_tcl() mysterious error condition, ", str, " pointer, ", file, "\n", NULL);
00131 }
00132 
00133 
00134 /**
00135  *
00136  * 
00137  *      bu_structparse_get_terse_form
00138  *
00139  * 
00140  *      Convert the "form" of a bu_structparse table into a TCL result string,
00141  *      with parameter-name data-type pairs:
00142  *
00143  *              V {%f %f %f} A {%f %f %f}
00144  *
00145  *      A different routine should build a more general 'form', along the
00146  *      lines of {V {%f %f %f} default {help}} {A {%f %f %f} default# {help}}
00147  *
00148  * 
00149  *      @param interp   - tcl interpreter
00150  *      @param sp       - structparse table
00151  *
00152  *      @return
00153  *              void
00154  */
00155 void
00156 bu_structparse_get_terse_form(Tcl_Interp                        *interp,
00157                               const struct bu_structparse       *sp)
00158 {
00159         struct bu_vls   str;
00160         int             i;
00161 
00162         bu_vls_init(&str);
00163 
00164         while (sp->sp_name != NULL) {
00165                 Tcl_AppendElement(interp, sp->sp_name);
00166                 bu_vls_trunc(&str, 0);
00167                 /* These types are specified by lengths, e.g. %80s */
00168                 if (strcmp(sp->sp_fmt, "%c") == 0 ||
00169                     strcmp(sp->sp_fmt, "%s") == 0 ||
00170                     strcmp(sp->sp_fmt, "%S") == 0) {
00171                         if (sp->sp_count > 1) {
00172                                 /* Make them all look like %###s */
00173                                 bu_vls_printf(&str, "%%%lds", sp->sp_count);
00174                         } else {
00175                                 /* Singletons are specified by their actual character */
00176                                 bu_vls_printf(&str, "%%c");
00177                         }
00178                 } else {
00179                         /* Vectors are specified by repetition, e.g. {%f %f %f} */
00180                         bu_vls_printf(&str, "%s", sp->sp_fmt);
00181                         for (i = 1; i < sp->sp_count; i++)
00182                                 bu_vls_printf(&str, " %s", sp->sp_fmt);
00183                 }
00184                 Tcl_AppendElement(interp, bu_vls_addr(&str));
00185                 ++sp;
00186         }
00187         bu_vls_free(&str);
00188 }
00189 
00190 /**
00191  *
00192  * NAME
00193  *      BU_SP_SKIP_SEP
00194  * 
00195  *      Skip the separator(s) (i.e. whitespace and open-braces)
00196  * 
00197  *      @param _cp      - character pointer
00198  */
00199 #define BU_SP_SKIP_SEP(_cp)     \
00200         { while( *(_cp) && (*(_cp) == ' ' || *(_cp) == '\n' || \
00201                 *(_cp) == '\t' || *(_cp) == '{' ) )  ++(_cp); }
00202 
00203 /**
00204  *
00205  *      bu_structparse_argv
00206  *
00207  * 
00208  *      Support routine for db adjust and db put.  Much like the bu_struct_parse routine
00209  *      which takes its input as a bu_vls. This routine, however, takes the arguments
00210  *      as lists, a more Tcl-friendly method. Also knows about the Tcl result string,
00211  *      so it can make more informative error messages.
00212  *
00213  *      Operates on argv[0] and argv[1], then on argv[2] and argv[3], ...
00214  *
00215  * 
00216  *      @param interp   - tcl interpreter
00217  *      @param argc     - number of elements in argv
00218  *      @param argv     - contains the keyword-value pairs
00219  *      @param desc     - structure description
00220  *      @param base     - base addr of users struct
00221  *
00222  *      @retval TCL_OK if successful, 
00223  *      @retval TCL_ERROR on failure
00224  */
00225 int
00226 bu_structparse_argv(Tcl_Interp                  *interp,
00227                     int                         argc,
00228                     char                        **argv,
00229                     const struct bu_structparse *desc,
00230                     char                        *base)
00231 {
00232         register char                           *cp, *loc;
00233         register const struct bu_structparse    *sdp;
00234         register int                             j;
00235         register int                            ii;
00236         struct bu_vls                            str;
00237 
00238         if (desc == (struct bu_structparse *)NULL) {
00239                 bu_log("bu_structparse_argv: NULL desc pointer\n");
00240                 Tcl_AppendResult(interp, "NULL desc pointer", (char *)NULL);
00241                 return TCL_ERROR;
00242         }
00243 
00244         /* Run through each of the attributes and their arguments. */
00245 
00246         bu_vls_init(&str);
00247         while (argc > 0) {
00248                 /* Find the attribute which matches this argument. */
00249                 for (sdp = desc; sdp->sp_name != NULL; sdp++) {
00250                         if (strcmp(sdp->sp_name, *argv) != 0)
00251                                 continue;
00252 
00253                         /* if we get this far, we've got a name match
00254                          * with a name in the structure description
00255                          */
00256 
00257 #if CRAY && !__STDC__
00258                         loc = (char *)(base+((int)sdp->sp_offset*sizeof(int)));
00259 #else
00260                         loc = (char *)(base+((int)sdp->sp_offset));
00261 #endif
00262                         if (sdp->sp_fmt[0] != '%') {
00263                                 bu_log("bu_structparse_argv: unknown format\n");
00264                                 bu_vls_free(&str);
00265                                 Tcl_AppendResult(interp, "unknown format",
00266                                                  (char *)NULL);
00267                                 return TCL_ERROR;
00268                         }
00269 
00270                         --argc;
00271                         ++argv;
00272 
00273                         switch (sdp->sp_fmt[1]) {
00274                         case 'c':
00275                         case 's':
00276                                 /* copy the string, converting escaped
00277                                  * double quotes to just double quotes
00278                                  */
00279                                 if (argc < 1) {
00280                                         bu_vls_trunc(&str, 0);
00281                                         bu_vls_printf(&str,
00282                                                       "not enough values for \"%s\" argument: should be %ld",
00283                                                       sdp->sp_name,
00284                                                       sdp->sp_count);
00285                                         Tcl_AppendResult(interp,
00286                                                          bu_vls_addr(&str),
00287                                                          (char *)NULL);
00288                                         bu_vls_free(&str);
00289                                         return TCL_ERROR;
00290                                 }
00291                                 for (ii = j = 0;
00292                                      j < sdp->sp_count && argv[0][ii] != '\0';
00293                                      loc[j++] = argv[0][ii++])
00294                                         ;
00295                                 if (ii < sdp->sp_count)
00296                                         loc[ii] = '\0';
00297                                 if (sdp->sp_count > 1) {
00298                                         loc[sdp->sp_count-1] = '\0';
00299                                         Tcl_AppendResult(interp,
00300                                                          sdp->sp_name, " ",
00301                                                          loc, " ",
00302                                                          (char *)NULL);
00303                                 } else {
00304                                         bu_vls_trunc(&str, 0);
00305                                         bu_vls_printf(&str, "%s %c ",
00306                                                       sdp->sp_name, *loc);
00307                                         Tcl_AppendResult(interp,
00308                                                          bu_vls_addr(&str),
00309                                                          (char *)NULL);
00310                                 }
00311                                 break;
00312                         case 'S': {
00313                                 struct bu_vls *vls = (struct bu_vls *)loc;
00314                                 bu_vls_init_if_uninit( vls );
00315                                 bu_vls_strcpy(vls, *argv);
00316                                 break;
00317                         }
00318                         case 'i':
00319 #if 0
00320                                 bu_log(
00321                          "Error: %%i not implemented. Contact developers.\n" );
00322                                 Tcl_AppendResult( interp,
00323                                                   "%%i not implemented yet",
00324                                                   (char *)NULL );
00325                                 bu_vls_free( &str );
00326                                 return TCL_ERROR;
00327 #else
00328                                 {
00329                                 register short *sh = (short *)loc;
00330                                 register int tmpi;
00331                                 register char const *cp;
00332 
00333                                 if( argc < 1 ) { /* XXX - when was ii defined */
00334                                         bu_vls_trunc( &str, 0 );
00335                                         bu_vls_printf( &str,
00336       "not enough values for \"%s\" argument: should have %ld",
00337                                                        sdp->sp_name,
00338                                                        sdp->sp_count);
00339                                         Tcl_AppendResult( interp,
00340                                                           bu_vls_addr(&str),
00341                                                           (char *)NULL );
00342                                         bu_vls_free( &str );
00343                                         return TCL_ERROR;
00344                                 }
00345 
00346                                 Tcl_AppendResult( interp, sdp->sp_name, " ",
00347                                                   (char *)NULL );
00348 
00349                                 /* Special case:  '=!' toggles a boolean */
00350                                 if( argv[0][0] == '!' ) {
00351                                         *sh = *sh ? 0 : 1;
00352                                         bu_vls_trunc( &str, 0 );
00353                                         bu_vls_printf( &str, "%hd ", *sh );
00354                                         Tcl_AppendResult( interp,
00355                                                           bu_vls_addr(&str),
00356                                                           (char *)NULL );
00357                                         break;
00358                                 }
00359                                 /* Normal case: an integer */
00360                                 cp = *argv;
00361                                 for( ii = 0; ii < sdp->sp_count; ++ii ) {
00362                                         if( *cp == '\0' ) {
00363                                                 bu_vls_trunc( &str, 0 );
00364                                                 bu_vls_printf( &str,
00365                       "not enough values for \"%s\" argument: should have %ld",
00366                                                                sdp->sp_name,
00367                                                                sdp->sp_count );
00368                                                 Tcl_AppendResult( interp,
00369                                                             bu_vls_addr(&str),
00370                                                             (char *)NULL );
00371                                                 bu_vls_free( &str );
00372                                                 return TCL_ERROR;
00373                                         }
00374 
00375                                         BU_SP_SKIP_SEP(cp);
00376                                         tmpi = atoi( cp );
00377                                         if( *cp && (*cp == '+' || *cp == '-') )
00378                                                 cp++;
00379                                         while( *cp && isdigit(*cp) )
00380                                                 cp++;
00381                                         /* make sure we actually had an
00382                                          * integer out there
00383                                          */
00384 
00385                                         if( cp == *argv ||
00386                                             (cp == *argv+1 &&
00387                                              (argv[0][0] == '+' ||
00388                                               argv[0][0] == '-')) ) {
00389                                                 bu_vls_trunc( &str, 0 );
00390                                                 bu_vls_printf( &str,
00391                                "value \"%s\" to argument %s isn't an integer",
00392                                                                argv[0],
00393                                                                sdp->sp_name );
00394                                                 Tcl_AppendResult( interp,
00395                                                             bu_vls_addr(&str),
00396                                                             (char *)NULL );
00397                                                 bu_vls_free( &str );
00398                                                 return TCL_ERROR;
00399                                         } else {
00400                                                 *(sh++) = tmpi;
00401                                         }
00402                                         BU_SP_SKIP_SEP(cp);
00403                                 }
00404                                 Tcl_AppendResult( interp,
00405                                                   sdp->sp_count > 1 ? "{" : "",
00406                                                   argv[0],
00407                                                   sdp->sp_count > 1 ? "}" : "",
00408                                                   " ", (char *)NULL);
00409                                 break; }
00410 
00411 #endif
00412                         case 'd': {
00413                                 register int *ip = (int *)loc;
00414                                 register int tmpi;
00415                                 register char const *cp;
00416 
00417                                 if( argc < 1 ) { /* XXX - when was ii defined */
00418                                         bu_vls_trunc( &str, 0 );
00419                                         bu_vls_printf( &str,
00420       "not enough values for \"%s\" argument: should have %ld",
00421                                                        sdp->sp_name,
00422                                                        sdp->sp_count);
00423                                         Tcl_AppendResult( interp,
00424                                                           bu_vls_addr(&str),
00425                                                           (char *)NULL );
00426                                         bu_vls_free( &str );
00427                                         return TCL_ERROR;
00428                                 }
00429 
00430                                 Tcl_AppendResult( interp, sdp->sp_name, " ",
00431                                                   (char *)NULL );
00432 
00433                                 /* Special case:  '=!' toggles a boolean */
00434                                 if( argv[0][0] == '!' ) {
00435                                         *ip = *ip ? 0 : 1;
00436                                         bu_vls_trunc( &str, 0 );
00437                                         bu_vls_printf( &str, "%d ", *ip );
00438                                         Tcl_AppendResult( interp,
00439                                                           bu_vls_addr(&str),
00440                                                           (char *)NULL );
00441                                         break;
00442                                 }
00443                                 /* Normal case: an integer */
00444                                 cp = *argv;
00445                                 for( ii = 0; ii < sdp->sp_count; ++ii ) {
00446                                         if( *cp == '\0' ) {
00447                                                 bu_vls_trunc( &str, 0 );
00448                                                 bu_vls_printf( &str,
00449                       "not enough values for \"%s\" argument: should have %ld",
00450                                                                sdp->sp_name,
00451                                                                sdp->sp_count );
00452                                                 Tcl_AppendResult( interp,
00453                                                             bu_vls_addr(&str),
00454                                                             (char *)NULL );
00455                                                 bu_vls_free( &str );
00456                                                 return TCL_ERROR;
00457                                         }
00458 
00459                                         BU_SP_SKIP_SEP(cp);
00460                                         tmpi = atoi( cp );
00461                                         if( *cp && (*cp == '+' || *cp == '-') )
00462                                                 cp++;
00463                                         while( *cp && isdigit(*cp) )
00464                                                 cp++;
00465                                         /* make sure we actually had an
00466                                          * integer out there
00467                                          */
00468 
00469                                         if( cp == *argv ||
00470                                             (cp == *argv+1 &&
00471                                              (argv[0][0] == '+' ||
00472                                               argv[0][0] == '-')) ) {
00473                                                 bu_vls_trunc( &str, 0 );
00474                                                 bu_vls_printf( &str,
00475                                "value \"%s\" to argument %s isn't an integer",
00476                                                                argv[0],
00477                                                                sdp->sp_name );
00478                                                 Tcl_AppendResult( interp,
00479                                                             bu_vls_addr(&str),
00480                                                             (char *)NULL );
00481                                                 bu_vls_free( &str );
00482                                                 return TCL_ERROR;
00483                                         } else {
00484                                                 *(ip++) = tmpi;
00485                                         }
00486                                         BU_SP_SKIP_SEP(cp);
00487                                 }
00488                                 Tcl_AppendResult( interp,
00489                                                   sdp->sp_count > 1 ? "{" : "",
00490                                                   argv[0],
00491                                                   sdp->sp_count > 1 ? "}" : "",
00492                                                   " ", (char *)NULL);
00493                                 break; }
00494                         case 'f': {
00495                                 int             dot_seen;
00496                                 double          tmp_double;
00497                                 register double *dp;
00498                                 char            *numstart;
00499 
00500                                 dp = (double *)loc;
00501 
00502                                 if( argc < 1 ) {
00503                                         bu_vls_trunc( &str, 0 );
00504                                         bu_vls_printf( &str,
00505        "not enough values for \"%s\" argument: should have %ld, only %d given",
00506                                                        sdp->sp_name,
00507                                                        sdp->sp_count, argc );
00508                                         Tcl_AppendResult( interp,
00509                                                           bu_vls_addr(&str),
00510                                                           (char *)NULL );
00511                                         bu_vls_free( &str );
00512                                         return TCL_ERROR;
00513                                 }
00514 
00515                                 Tcl_AppendResult( interp, sdp->sp_name, " ",
00516                                                   (char *)NULL );
00517 
00518                                 cp = *argv;
00519                                 for( ii = 0; ii < sdp->sp_count; ii++ ) {
00520                                         if( *cp == '\0' ) {
00521                                                 bu_vls_trunc( &str, 0 );
00522                                                 bu_vls_printf( &str,
00523        "not enough values for \"%s\" argument: should have %ld, only %d given",
00524                                                                sdp->sp_name,
00525                                                                sdp->sp_count,
00526                                                                ii );
00527                                                 Tcl_AppendResult( interp,
00528                                                             bu_vls_addr(&str),
00529                                                             (char *)NULL );
00530                                                 bu_vls_free( &str );
00531                                                 return TCL_ERROR;
00532                                         }
00533 
00534                                         BU_SP_SKIP_SEP(cp);
00535                                         numstart = cp;
00536                                         if( *cp == '-' || *cp == '+' ) cp++;
00537 
00538                                         /* skip matissa */
00539                                         dot_seen = 0;
00540                                         for( ; *cp ; cp++ ) {
00541                                                 if( *cp == '.' && !dot_seen ) {
00542                                                         dot_seen = 1;
00543                                                         continue;
00544                                                 }
00545                                                 if( !isdigit(*cp) )
00546                                                         break;
00547                                         }
00548 
00549                                         /* If no mantissa seen,
00550                                            then there is no float here */
00551                                         if( cp == (numstart + dot_seen) ) {
00552                                                 bu_vls_trunc( &str, 0 );
00553                                                 bu_vls_printf( &str,
00554                                    "value \"%s\" to argument %s isn't a float",
00555                                                                argv[0],
00556                                                                sdp->sp_name );
00557                                                 Tcl_AppendResult( interp,
00558                                                             bu_vls_addr(&str),
00559                                                             (char *)NULL );
00560                                                 bu_vls_free( &str );
00561                                                 return TCL_ERROR;
00562                                         }
00563 
00564                                         /* there was a mantissa,
00565                                            so we may have an exponent */
00566                                         if( *cp == 'E' || *cp == 'e' ) {
00567                                                 cp++;
00568 
00569                                                 /* skip exponent sign */
00570                                                 if (*cp == '+' || *cp == '-')
00571                                                         cp++;
00572                                                 while( isdigit(*cp) )
00573                                                         cp++;
00574                                         }
00575 
00576                                         bu_vls_trunc( &str, 0 );
00577                                         bu_vls_strcpy( &str, numstart );
00578                                         bu_vls_trunc( &str, cp-numstart );
00579                                         if( sscanf(bu_vls_addr(&str),
00580                                                    "%lf", &tmp_double) != 1 ) {
00581                                                 bu_vls_trunc( &str, 0 );
00582                                                 bu_vls_printf( &str,
00583                                   "value \"%s\" to argument %s isn't a float",
00584                                                                numstart,
00585                                                                sdp->sp_name );
00586                                                 Tcl_AppendResult( interp,
00587                                                             bu_vls_addr(&str),
00588                                                             (char *)NULL );
00589                                                 bu_vls_free( &str );
00590                                                 return TCL_ERROR;
00591                                         }
00592 
00593                                         *dp++ = tmp_double;
00594 
00595                                         BU_SP_SKIP_SEP(cp);
00596                                 }
00597                                 Tcl_AppendResult( interp,
00598                                                   sdp->sp_count > 1 ? "{" : "",
00599                                                   argv[0],
00600                                                   sdp->sp_count > 1 ? "}" : "",
00601                                                   " ", (char *)NULL );
00602                                 break; }
00603                         default: {
00604                                 struct bu_vls vls;
00605 
00606                                 bu_vls_init(&vls);
00607                                 bu_vls_printf(&vls,
00608                                 "%s line:%d Parse error, unknown format: '%s' for element \"%s\"",
00609                                 __FILE__, __LINE__, sdp->sp_fmt,
00610                                 sdp->sp_name);
00611 
00612                                 Tcl_AppendResult( interp, bu_vls_addr(&vls),
00613                                         (char *)NULL );
00614 
00615                                 bu_vls_free( &vls );
00616                                 return TCL_ERROR;
00617                                 }
00618                         }
00619 
00620                         if( sdp->sp_hook )  {
00621                                 sdp->sp_hook( sdp, sdp->sp_name, base, *argv);
00622 
00623                         }
00624                         --argc;
00625                         ++argv;
00626 
00627 
00628                         break;
00629                 }
00630 
00631 
00632                 if( sdp->sp_name == NULL ) {
00633                         bu_vls_trunc( &str, 0 );
00634                         bu_vls_printf( &str, "invalid attribute %s\n", argv[0] );
00635                         Tcl_AppendResult( interp, bu_vls_addr(&str),
00636                                           (char *)NULL );
00637                         bu_vls_free( &str );
00638                         return TCL_ERROR;
00639                 }
00640         }
00641         return TCL_OK;
00642 }
00643 
00644 /**
00645  *
00646  *      bu_tcl_mem_barriercheck
00647  *
00648  *      A tcl wrapper for bu_mem_barriercheck.
00649  *
00650  * 
00651  * @param clientData    - associated data/state
00652  * @param interp                - tcl interpreter in which this command was registered.
00653  * @param argc          - number of elements in argv
00654  * @param argv          - command name and arguments
00655  *
00656  * @return TCL_OK if successful, otherwise, TCL_ERROR.
00657  */
00658 int
00659 bu_tcl_mem_barriercheck(ClientData      clientData,
00660                         Tcl_Interp      *interp,
00661                         int             argc,
00662                         char            **argv)
00663 {
00664         int     ret;
00665 
00666         ret = bu_mem_barriercheck();
00667         if (ret < 0) {
00668                 Tcl_AppendResult(interp, "bu_mem_barriercheck() failed\n", NULL);
00669                 return TCL_ERROR;
00670         }
00671         return TCL_OK;
00672 }
00673 
00674 /**
00675  *
00676  *      bu_tcl_ck_malloc_ptr
00677  *
00678  *      A tcl wrapper for bu_ck_malloc_ptr.
00679  *
00680  *      @param clientData       - associated data/state
00681  *      @param interp           - tcl interpreter in which this command was registered.
00682  *      @param argc             - number of elements in argv
00683  *      @param argv             - command name and arguments
00684  * 
00685  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
00686  */
00687 int
00688 bu_tcl_ck_malloc_ptr(ClientData         clientData,
00689                      Tcl_Interp         *interp,
00690                      int                argc,
00691                      char               **argv)
00692 {
00693         if( argc != 3 )  {
00694                 Tcl_AppendResult( interp, "Usage: bu_ck_malloc_ptr ascii-ptr description\n");
00695                 return TCL_ERROR;
00696         }
00697         bu_ck_malloc_ptr( (genptr_t)atol(argv[1]), argv[2] );
00698         return TCL_OK;
00699 }
00700 
00701 /**
00702  *
00703  *      bu_tcl_malloc_len_roundup
00704  *
00705  * 
00706  *      A tcl wrapper for bu_malloc_len_roundup.
00707  *
00708  * 
00709  *      @param clientData       - associated data/state
00710  *      @param interp           - tcl interpreter in which this command was registered.
00711  *      @param argc             - number of elements in argv
00712  *      @param argv             - command name and arguments
00713  *
00714  * 
00715  *      @Return TCL_OK if successful, otherwise, TCL_ERROR.
00716  */
00717 int
00718 bu_tcl_malloc_len_roundup(ClientData    clientData,
00719                           Tcl_Interp    *interp,
00720                           int           argc,
00721                           char          **argv)
00722 {
00723         int     val;
00724 
00725         if( argc != 2 )  {
00726                 Tcl_AppendResult(interp, "Usage: bu_malloc_len_roundup nbytes\n", NULL);
00727                 return TCL_ERROR;
00728         }
00729         val = bu_malloc_len_roundup(atoi(argv[1]));
00730         sprintf(interp->result, "%d", val);
00731         return TCL_OK;
00732 }
00733 
00734 /**
00735  *
00736  * 
00737  *      bu_tcl_prmem
00738  *
00739  * 
00740  *      A tcl wrapper for bu_prmem. Prints map of
00741  *      memory currently in use, to stderr.
00742  *
00743  * 
00744  *      @param clientData       - associated data/state
00745  *      @param interp           - tcl interpreter in which this command was registered.
00746  *      @param argc             - number of elements in argv
00747  *      @param argv             - command name and arguments
00748  *
00749  * 
00750  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
00751  */
00752 int
00753 bu_tcl_prmem(ClientData clientData,
00754              Tcl_Interp *interp,
00755              int        argc,
00756              char       **argv)
00757 {
00758         if (argc != 2) {
00759                 Tcl_AppendResult(interp, "Usage: bu_prmem title\n");
00760                 return TCL_ERROR;
00761         }
00762         bu_prmem(argv[1]);
00763         return TCL_OK;
00764 }
00765 
00766 /**
00767  *
00768  * 
00769  *      bu_tcl_printb
00770  *
00771  * 
00772  *      A tcl wrapper for bu_vls_printb.
00773  *
00774  * 
00775  *      @param clientData       - associated data/state
00776  *      @param interp           - tcl interpreter in which this command was registered.
00777  *      @param argc             - number of elements in argv
00778  *      @param argv             - command name and arguments
00779  * 
00780  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
00781  */
00782 int
00783 bu_tcl_printb(ClientData        clientData,
00784               Tcl_Interp        *interp,
00785               int               argc,
00786               char              **argv)
00787 {
00788         struct bu_vls   str;
00789 
00790         if (argc != 4) {
00791                 Tcl_AppendResult(interp, "Usage: bu_printb title integer-to-format bit-format-string\n", NULL);
00792                 return TCL_ERROR;
00793         }
00794         bu_vls_init(&str);
00795         bu_vls_printb(&str, argv[1], atoi(argv[2]), argv[3]);
00796         Tcl_SetResult(interp, bu_vls_addr(&str), TCL_VOLATILE);
00797         bu_vls_free(&str);
00798         return TCL_OK;
00799 }
00800 
00801 /**
00802  *
00803  * 
00804  *      bu_get_value_by_keyword
00805  *
00806  * 
00807  *      Given arguments of alternating keywords and values
00808  *      and a specific keyword ("Iwant"),
00809  *      return the value associated with that keyword.
00810  *
00811  *      example:  bu_get_value_by_keyword Iwant az 35 elev 25 temp 9.6
00812  *
00813  *      If only one argument is given after the search keyword, it is interpreted
00814  *      as a list in the same format.
00815  *
00816  *      example:  bu_get_value_by_keyword Iwant {az 35 elev 25 temp 9.6}
00817  *
00818  *      Search order is left-to-right, only first match is returned.
00819  *
00820  *      Sample use:
00821  *              bu_get_value_by_keyword V8 [concat type [.inmem get box.s]]
00822  *
00823  * 
00824  *      @param clientData       - associated data/state
00825  *      @param interp           - tcl interpreter in which this command was registered.
00826  *      @param argc             - number of elements in argv
00827  *      @param argv             - command name and arguments
00828  *
00829  * 
00830  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
00831  */
00832 int
00833 bu_get_value_by_keyword(ClientData      clientData,
00834                         Tcl_Interp      *interp,
00835                         int             argc,
00836                         char            **argv)
00837 {
00838         int     listc;
00839         char    **listv;
00840         register char   *iwant;
00841         char    **tofree = (char **)NULL;
00842         int     i;
00843 
00844         if( argc < 3 )  {
00845                 char    buf[32];
00846                 sprintf(buf, "%d", argc);
00847                 Tcl_AppendResult( interp,
00848                         "bu_get_value_by_keyword: wrong # of args (", buf, ").\n",
00849                         "Usage: bu_get_value_by_keyword iwant {list}\n",
00850                         "Usage: bu_get_value_by_keyword iwant key1 val1 key2 val2 ... keyN valN\n",
00851                         (char *)NULL );
00852                 return TCL_ERROR;
00853         }
00854 
00855         iwant = argv[1];
00856 
00857         if( argc == 3 )  {
00858                 if( Tcl_SplitList( interp, argv[2], &listc, (const char ***)&listv ) != TCL_OK )  {
00859                         Tcl_AppendResult( interp,
00860                                 "bu_get_value_by_keyword: iwant='", iwant,
00861                                 "', unable to split '",
00862                                 argv[2], "'\n", (char *)NULL );
00863                         return TCL_ERROR;
00864                 }
00865                 tofree = listv;
00866         } else {
00867                 /* Take search list from remaining arguments */
00868                 listc = argc - 2;
00869                 listv = argv + 2;
00870         }
00871 
00872         if( (listc & 1) != 0 )  {
00873                 char    buf[32];
00874                 sprintf(buf, "%d", listc);
00875                 Tcl_AppendResult( interp,
00876                         "bu_get_value_by_keyword: odd # of items in list (", buf, ").\n",
00877                         (char *)NULL );
00878                 if(tofree) free( (char *)tofree );      /* not bu_free() */
00879                 return TCL_ERROR;
00880         }
00881 
00882         for( i=0; i < listc; i += 2 )  {
00883                 if( strcmp( iwant, listv[i] ) == 0 )  {
00884                         /* If value is a list, don't nest it in another list */
00885                         if( listv[i+1][0] == '{' )  {
00886                                 struct bu_vls   str;
00887                                 bu_vls_init( &str );
00888                                 /* Skip leading { */
00889                                 bu_vls_strcat( &str, &listv[i+1][1] );
00890                                 /* Trim trailing } */
00891                                 bu_vls_trunc( &str, -1 );
00892                                 Tcl_AppendResult( interp,
00893                                         bu_vls_addr(&str), (char *)NULL );
00894                                 bu_vls_free( &str );
00895                         } else {
00896                                 Tcl_AppendResult( interp, listv[i+1], (char *)NULL );
00897                         }
00898                         if(tofree) free( (char *)tofree );      /* not bu_free() */
00899                         return TCL_OK;
00900                 }
00901         }
00902 
00903         /* Not found */
00904         Tcl_AppendResult( interp, "bu_get_value_by_keyword: keyword '",
00905                 iwant, "' not found in list\n", (char *)NULL );
00906         if(tofree) free( (char *)tofree );      /* not bu_free() */
00907         return TCL_ERROR;
00908 }
00909 
00910 /*****f* libbu/bu_tcl.c
00911  *
00912  * 
00913  *      bu_get_all_keyword_values
00914  *
00915  * 
00916  *      Given arguments of alternating keywords and values,
00917  *      establish local variables named after the keywords, with the
00918  *      indicated values. Returns in interp a list of the variable
00919  *      names that were assigned to. This lets you detect at runtime
00920  *      what assignments were actually performed.
00921  *
00922  *      example:  bu_get_all_keyword_values az 35 elev 25 temp 9.6
00923  *
00924  *      This is much faster than writing this in raw Tcl 8 as:
00925  *
00926  *      foreach {keyword value} $list {
00927  *              set $keyword $value
00928  *              lappend retval $keyword
00929  *      }
00930  *
00931  *      If only one argument is given it is interpreted
00932  *      as a list in the same format.
00933  *
00934  *      example:  bu_get_all_keyword_values {az 35 elev 25 temp 9.6}
00935  *
00936  *      For security reasons, the name of the local variable assigned to
00937  *      is that of the input keyword with "key_" prepended.
00938  *      This prevents a playful user from overriding variables inside
00939  *      the function, e.g. loop iterator "i", etc.
00940  *      This could be even worse when called in global context.
00941  *
00942  *      Processing order is left-to-right, rightmost value for a repeated
00943  *      keyword will be the one used.
00944  *
00945  *      Sample use:
00946  *              bu_get_all_keyword_values [concat type [.inmem get box.s]]
00947  *
00948  * 
00949  *      @param clientData       - associated data/state
00950  *      @param interp           - tcl interpreter in which this command was registered.
00951  *      @param argc             - number of elements in argv
00952  *      @param argv             - command name and arguments
00953  *
00954  * 
00955  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
00956  */
00957 int
00958 bu_get_all_keyword_values(ClientData    clientData,
00959                           Tcl_Interp    *interp,
00960                           int           argc,
00961                           char          **argv)
00962 {
00963         struct bu_vls   variable;
00964         int     listc;
00965         char    **listv;
00966         char    **tofree = (char **)NULL;
00967         int     i;
00968 
00969         if( argc < 2 )  {
00970                 char    buf[32];
00971                 sprintf(buf, "%d", argc);
00972                 Tcl_AppendResult( interp,
00973                         "bu_get_all_keyword_values: wrong # of args (", buf, ").\n",
00974                         "Usage: bu_get_all_keyword_values {list}\n",
00975                         "Usage: bu_get_all_keyword_values key1 val1 key2 val2 ... keyN valN\n",
00976                         (char *)NULL );
00977                 return TCL_ERROR;
00978         }
00979 
00980         if( argc == 2 )  {
00981                 if( Tcl_SplitList( interp, argv[1], &listc, (const char ***)&listv ) != TCL_OK )  {
00982                         Tcl_AppendResult( interp,
00983                                 "bu_get_all_keyword_values: unable to split '",
00984                                 argv[1], "'\n", (char *)NULL );
00985                         return TCL_ERROR;
00986                 }
00987                 tofree = listv;
00988         } else {
00989                 /* Take search list from remaining arguments */
00990                 listc = argc - 1;
00991                 listv = argv + 1;
00992         }
00993 
00994         if( (listc & 1) != 0 )  {
00995                 char    buf[32];
00996                 sprintf(buf, "%d", listc);
00997                 Tcl_AppendResult( interp,
00998                         "bu_get_all_keyword_values: odd # of items in list (",
00999                         buf, "), aborting.\n",
01000                         (char *)NULL );
01001                 if(tofree) free( (char *)tofree );      /* not bu_free() */
01002                 return TCL_ERROR;
01003         }
01004 
01005 
01006         /* Process all the pairs */
01007         bu_vls_init( &variable );
01008         for( i=0; i < listc; i += 2 )  {
01009                 bu_vls_strcpy( &variable, "key_" );
01010                 bu_vls_strcat( &variable, listv[i] );
01011                 /* If value is a list, don't nest it in another list */
01012                 if( listv[i+1][0] == '{' )  {
01013                         struct bu_vls   str;
01014                         bu_vls_init( &str );
01015                         /* Skip leading { */
01016                         bu_vls_strcat( &str, &listv[i+1][1] );
01017                         /* Trim trailing } */
01018                         bu_vls_trunc( &str, -1 );
01019                         Tcl_SetVar( interp, bu_vls_addr(&variable),
01020                                 bu_vls_addr(&str), 0);
01021                         bu_vls_free( &str );
01022                 } else {
01023                         Tcl_SetVar( interp, bu_vls_addr(&variable),
01024                                 listv[i+1], 0 );
01025                 }
01026                 Tcl_AppendResult( interp, bu_vls_addr(&variable),
01027                         " ", (char *)NULL );
01028                 bu_vls_trunc( &variable, 0 );
01029         }
01030 
01031         /* All done */
01032         bu_vls_free( &variable );
01033         if(tofree) free( (char *)tofree );      /* not bu_free() */
01034         return TCL_OK;
01035 }
01036 
01037 /**
01038  *
01039  * 
01040  *      bu_tcl_rgb_to_hsv
01041  *
01042  * 
01043  *      A tcl wrapper for bu_rgb_to_hsv.
01044  *
01045  * 
01046  *      @param clientData       - associated data/state
01047  *      @param interp           - tcl interpreter in which this command was registered.
01048  *      @param argc             - number of elements in argv
01049  *      @param argv             - command name and arguments
01050  * 
01051  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01052  */
01053 int
01054 bu_tcl_rgb_to_hsv(ClientData    clientData,
01055                   Tcl_Interp    *interp,
01056                   int           argc,
01057                   char          **argv)
01058 {
01059         int             rgb_int[3];
01060         unsigned char   rgb[3];
01061         fastf_t         hsv[3];
01062         struct bu_vls   result;
01063 
01064         bu_vls_init(&result);
01065         if( argc != 4 )  {
01066                 Tcl_AppendResult( interp, "Usage: bu_rgb_to_hsv R G B\n",
01067                     (char *)NULL );
01068                 return TCL_ERROR;
01069         }
01070         if (( Tcl_GetInt( interp, argv[1], &rgb_int[0] ) != TCL_OK )
01071             || ( Tcl_GetInt( interp, argv[2], &rgb_int[1] ) != TCL_OK )
01072             || ( Tcl_GetInt( interp, argv[3], &rgb_int[2] ) != TCL_OK )
01073             || ( rgb_int[0] < 0 ) || ( rgb_int[0] > 255 )
01074             || ( rgb_int[1] < 0 ) || ( rgb_int[1] > 255 )
01075             || ( rgb_int[2] < 0 ) || ( rgb_int[2] > 255 )) {
01076                 bu_vls_printf(&result, "bu_rgb_to_hsv: Bad RGB (%s, %s, %s)\n",
01077                               argv[1], argv[2], argv[3]);
01078                 Tcl_AppendResult(interp, bu_vls_addr(&result), (char *)NULL);
01079                 bu_vls_free(&result);
01080                 return TCL_ERROR;
01081         }
01082         rgb[0] = rgb_int[0];
01083         rgb[1] = rgb_int[1];
01084         rgb[2] = rgb_int[2];
01085 
01086         bu_rgb_to_hsv( rgb, hsv );
01087         bu_vls_printf(&result, "%g %g %g", V3ARGS(hsv));
01088         Tcl_AppendResult(interp, bu_vls_addr(&result), (char *)NULL);
01089         bu_vls_free(&result);
01090         return TCL_OK;
01091 
01092 }
01093 
01094 /**
01095  *
01096  * 
01097  *      bu_tcl_hsv_to_rgb
01098  *
01099  * 
01100  *      A tcl wrapper for bu_hsv_to_rgb.
01101  *
01102  * 
01103  *      @param clientData       - associated data/state
01104  *      @param interp           - tcl interpreter in which this command was registered.
01105  *      @param argc             - number of elements in argv
01106  *      @param argv             - command name and arguments
01107  *
01108  * 
01109  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01110  */
01111 int
01112 bu_tcl_hsv_to_rgb(ClientData    clientData,
01113                   Tcl_Interp    *interp,
01114                   int           argc,
01115                   char          **argv)
01116 {
01117         fastf_t         hsv[3];
01118         unsigned char   rgb[3];
01119         struct bu_vls   result;
01120 
01121         if( argc != 4 )  {
01122                 Tcl_AppendResult( interp, "Usage: bu_hsv_to_rgb H S V\n",
01123                     (char *)NULL );
01124                 return TCL_ERROR;
01125         }
01126         bu_vls_init(&result);
01127         if (( Tcl_GetDouble( interp, argv[1], &hsv[0] ) != TCL_OK )
01128          || ( Tcl_GetDouble( interp, argv[2], &hsv[1] ) != TCL_OK )
01129          || ( Tcl_GetDouble( interp, argv[3], &hsv[2] ) != TCL_OK )
01130          || ( bu_hsv_to_rgb( hsv, rgb ) == 0) ) {
01131                 bu_vls_printf(&result, "bu_hsv_to_rgb: Bad HSV (%s, %s, %s)\n",
01132                     argv[1], argv[2], argv[3]);
01133                 Tcl_AppendResult(interp, bu_vls_addr(&result), (char *)NULL);
01134                 bu_vls_free(&result);
01135                 return TCL_ERROR;
01136         }
01137 
01138         bu_vls_printf(&result, "%d %d %d", V3ARGS(rgb));
01139         Tcl_AppendResult(interp, bu_vls_addr(&result), (char *)NULL);
01140         bu_vls_free(&result);
01141         return TCL_OK;
01142 
01143 }
01144 
01145 /**
01146  *
01147  * 
01148  *      bu_tcl_key_eq_to_key_val
01149  *
01150  * 
01151  *      Converts key=val to "key val" pairs.
01152  *
01153  * 
01154  *      @param clientData       - associated data/state
01155  *      @param interp           - tcl interpreter in which this command was registered.
01156  *      @param argc             - number of elements in argv
01157  *      @param argv             - command name and arguments
01158  * 
01159  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01160  */
01161 int
01162 bu_tcl_key_eq_to_key_val(ClientData     clientData,
01163                          Tcl_Interp     *interp,
01164                          int            argc,
01165                          char           **argv)
01166 {
01167         struct bu_vls vls;
01168         char *next;
01169         int i=0;
01170 
01171         bu_vls_init( &vls );
01172 
01173         while( ++i < argc )
01174         {
01175                 if( bu_key_eq_to_key_val( argv[i], &next, &vls ) )
01176                 {
01177                         bu_vls_free( &vls );
01178                         return TCL_ERROR;
01179                 }
01180 
01181                 if( i < argc - 1 )
01182                         Tcl_AppendResult(interp, bu_vls_addr( &vls ) , " ", NULL );
01183                 else
01184                         Tcl_AppendResult(interp, bu_vls_addr( &vls ), NULL );
01185 
01186                 bu_vls_trunc( &vls, 0 );
01187         }
01188 
01189         bu_vls_free( &vls );
01190         return TCL_OK;
01191 
01192 }
01193 
01194 /**
01195  *
01196  * 
01197  *      bu_tcl_shader_to_key_val
01198  *
01199  * 
01200  *      Converts a shader string to a tcl list.
01201  *
01202  * 
01203  *      @param clientData       - associated data/state
01204  *      @param interp           - tcl interpreter in which this command was registered.
01205  *      @param argc             - number of elements in argv
01206  *      @param argv             - command name and arguments
01207  *
01208  * 
01209  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01210  */
01211 int
01212 bu_tcl_shader_to_key_val(ClientData     clientData,
01213                          Tcl_Interp     *interp,
01214                          int            argc,
01215                          char           **argv)
01216 {
01217         struct bu_vls vls;
01218 
01219         bu_vls_init( &vls );
01220 
01221         if( bu_shader_to_tcl_list( argv[1], &vls ) )
01222         {
01223                 bu_vls_free( &vls );
01224                 return( TCL_ERROR );
01225         }
01226 
01227         Tcl_AppendResult(interp, bu_vls_addr( &vls ), NULL );
01228 
01229         bu_vls_free( &vls );
01230 
01231         return TCL_OK;
01232 
01233 }
01234 
01235 /**
01236  *
01237  * 
01238  *      bu_tcl_key_val_to_key_eq
01239  *
01240  * 
01241  *      Converts "key value" pairs to key=value.
01242  *
01243  * 
01244  *      @param clientData       - associated data/state
01245  *      @param interp           - tcl interpreter in which this command was registered.
01246  *      @param argc             - number of elements in argv
01247  *      @param argv             - command name and arguments
01248  *
01249  * 
01250  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01251  */
01252 int
01253 bu_tcl_key_val_to_key_eq(ClientData     clientData,
01254                          Tcl_Interp     *interp,
01255                          int            argc,
01256                          char           **argv)
01257 {
01258         int i=0;
01259 
01260         for( i=1 ; i<argc ; i += 2 )
01261         {
01262                 if( i+1 < argc-1 )
01263                         Tcl_AppendResult(interp, argv[i], "=", argv[i+1], " ", NULL );
01264                 else
01265                         Tcl_AppendResult(interp, argv[i], "=", argv[i+1], NULL );
01266 
01267         }
01268         return TCL_OK;
01269 
01270 }
01271 
01272 /**
01273  *
01274  * 
01275  *      bu_tcl_shader_to_key_eq
01276  *
01277  * 
01278  *      Converts a shader tcl list into a shader string.
01279  *
01280  * 
01281  *      @param clientData       - associated data/state
01282  *      @param interp           - tcl interpreter in which this command was registered.
01283  *      @param argc             - number of elements in argv
01284  *      @param argv             - command name and arguments
01285  *
01286  * 
01287  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01288  */
01289 int
01290 bu_tcl_shader_to_key_eq(ClientData      clientData,
01291                         Tcl_Interp      *interp,
01292                         int             argc,
01293                         char            **argv)
01294 {
01295         struct bu_vls vls;
01296 
01297 
01298         bu_vls_init( &vls );
01299 
01300         if( bu_shader_to_key_eq( argv[1], &vls ) )
01301         {
01302                 bu_vls_free( &vls );
01303                 return TCL_ERROR;
01304         }
01305 
01306         Tcl_AppendResult(interp, bu_vls_addr( &vls ), NULL );
01307 
01308         bu_vls_free( &vls );
01309 
01310         return TCL_OK;
01311 }
01312 
01313 
01314 /**
01315  *
01316  * 
01317  *      bu_tcl_brlcad_root
01318  *
01319  * 
01320  *      A tcl wrapper for bu_brlcad_root.
01321  *
01322  * 
01323  *      @param clientData       - associated data/state
01324  *      @param interp           - tcl interpreter in which this command was registered.
01325  *      @param argc             - number of elements in argv
01326  *      @param argv             - command name and arguments
01327  * 
01328  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01329  */
01330 int
01331 bu_tcl_brlcad_root(ClientData   clientData,
01332                    Tcl_Interp   *interp,
01333                    int           argc,
01334                    char         **argv)
01335 {
01336         if (argc != 2) {
01337                 Tcl_AppendResult(interp, "Usage: bu_brlcad_root subdir\n",
01338                                  (char *)NULL);
01339                 return TCL_ERROR;
01340         }
01341         Tcl_AppendResult(interp, bu_brlcad_root(argv[1], 0), NULL);
01342         return TCL_OK;
01343 }
01344 
01345 
01346 /**
01347  *
01348  * 
01349  *      bu_tcl_brlcad_data
01350  *
01351  * 
01352  *      A tcl wrapper for bu_brlcad_data.
01353  *
01354  * 
01355  *      @param clientData       - associated data/state
01356  *      @param interp           - tcl interpreter in which this command was registered.
01357  *      @param argc             - number of elements in argv
01358  *      @param argv             - command name and arguments
01359  * 
01360  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01361  */
01362 int
01363 bu_tcl_brlcad_data(ClientData   clientData,
01364                    Tcl_Interp   *interp,
01365                    int           argc,
01366                    char         **argv)
01367 {
01368         if (argc != 2) {
01369                 Tcl_AppendResult(interp, "Usage: bu_brlcad_data subdir\n",
01370                                  (char *)NULL);
01371                 return TCL_ERROR;
01372         }
01373         Tcl_AppendResult(interp, bu_brlcad_data(argv[1], 0), NULL);
01374         return TCL_OK;
01375 }
01376 
01377 
01378 /**
01379  *
01380  * 
01381  *      bu_tcl_brlcad_path
01382  *
01383  * 
01384  *      A tcl wrapper for bu_brlcad_path.
01385  *
01386  * 
01387  *      @param clientData       - associated data/state
01388  *      @param interp           - tcl interpreter in which this command was registered.
01389  *      @param argc             - number of elements in argv
01390  *      @param argv             - command name and arguments
01391  * 
01392  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01393  */
01394 int
01395 bu_tcl_brlcad_path(ClientData   clientData,
01396                    Tcl_Interp   *interp,
01397                    int           argc,
01398                    char         **argv)
01399 {
01400         if (argc != 2) {
01401                 Tcl_AppendResult(interp, "Usage: bu_brlcad_path subdir\n",
01402                                  (char *)NULL);
01403                 return TCL_ERROR;
01404         }
01405         Tcl_AppendResult(interp, bu_brlcad_path(argv[1], 0), NULL);
01406         return TCL_OK;
01407 }
01408 
01409 
01410 /**
01411  *
01412  * 
01413  *      bu_tcl_units_conversion
01414  *
01415  * 
01416  *      A tcl wrapper for bu_units_conversion.
01417  *
01418  * 
01419  *      @param clientData       - associated data/state
01420  *      @param interp           - tcl interpreter in which this command was registered.
01421  *      @param argc             - number of elements in argv
01422  *      @param argv             - command name and arguments
01423  * 
01424  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01425  */
01426 int
01427 bu_tcl_units_conversion(ClientData      clientData,
01428                         Tcl_Interp      *interp,
01429                         int             argc,
01430                         char            **argv)
01431 {
01432         double conv_factor;
01433         struct bu_vls result;
01434 
01435         if (argc != 2) {
01436                 Tcl_AppendResult(interp, "Usage: bu_units_conversion units_string\n",
01437                                  (char *)NULL);
01438                 return TCL_ERROR;
01439         }
01440 
01441         conv_factor = bu_units_conversion(argv[1]);
01442         if (conv_factor == 0.0) {
01443                 Tcl_AppendResult(interp, "ERROR: bu_units_conversion: Unrecognized units string: ",
01444                                  argv[1], "\n", (char *)NULL);
01445                 return TCL_ERROR;
01446         }
01447 
01448         bu_vls_init(&result);
01449         bu_vls_printf(&result, "%.12e", conv_factor);
01450         Tcl_AppendResult(interp, bu_vls_addr(&result), (char *)NULL);
01451         bu_vls_free(&result);
01452         return TCL_OK;
01453 }
01454 
01455 /**
01456  *
01457  * 
01458  *      bu_tcl_setup
01459  *
01460  * 
01461  *      Add all the supported Tcl interfaces to LIBBU routines to
01462  *      the list of commands known by the given interpreter.
01463  *
01464  * 
01465  *      @param interp           - tcl interpreter in which this command was registered.
01466  *
01467  * 
01468  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01469  */
01470 void
01471 bu_tcl_setup(Tcl_Interp *interp)
01472 {
01473         bu_register_cmds(interp, bu_cmds);
01474 
01475         Tcl_SetVar(interp, "bu_version", (char *)bu_version+5, TCL_GLOBAL_ONLY);        /* from vers.c */
01476         Tcl_SetVar(interp, "BU_DEBUG_FORMAT", BU_DEBUG_FORMAT, TCL_GLOBAL_ONLY);
01477         Tcl_LinkVar(interp, "bu_debug", (char *)&bu_debug, TCL_LINK_INT );
01478 
01479         /* initialize command history objects */
01480         Cho_Init(interp);
01481 }
01482 
01483 /**
01484  *
01485  * 
01486  *      Bu_Init
01487  *
01488  * 
01489  *      Allows LIBBU to be dynamically loaded to a vanilla tclsh/wish with
01490  *      "load /usr/brlcad/lib/libbu.so"
01491  *
01492  * 
01493  *      @param interp           - tcl interpreter in which this command was registered.
01494  *
01495  * 
01496  *      @return TCL_OK if successful, otherwise, TCL_ERROR.
01497  */
01498 int
01499 #ifdef BRLCAD_DEBUG
01500 Bu_d_Init(Tcl_Interp *interp)
01501 #else
01502 Bu_Init(Tcl_Interp *interp)
01503 #endif
01504 {
01505         bu_tcl_setup(interp);
01506 #if 0
01507         bu_hook_list_init(&bu_log_hook_list);
01508         bu_hook_list_init(&bu_bomb_hook_list);
01509 #endif
01510         return TCL_OK;
01511 }
01512 /*@}*/
01513 /*
01514  * Local Variables:
01515  * mode: C
01516  * tab-width: 8
01517  * c-basic-offset: 4
01518  * indent-tabs-mode: t
01519  * End:
01520  * ex: shiftwidth=4 tabstop=8
01521  */

Generated on Mon Sep 18 01:24:47 2006 for BRL-CAD by  doxygen 1.4.6