wdb_comb_std.c

Go to the documentation of this file.
00001 /*                  W D B _ C O M B _ S T D . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1997-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 wdb */
00023 /*@{*/
00024 /** @file wdb_comb_std.c
00025  *      Code to implement the database objects "c" command.
00026  *
00027  *  Author -
00028  *      John R. Anderson
00029  *
00030  *  Source -
00031  *      The U. S. Army Research Laboratory
00032  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00033  */
00034 
00035 #ifndef lint
00036 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/wdb_comb_std.c,v 14.12 2006/09/16 02:04:26 lbutler Exp $ (BRL)";
00037 #endif
00038 
00039 #include "common.h"
00040 
00041 #include <stdio.h>
00042 #ifdef HAVE_STRING_H
00043 #  include <string.h>
00044 #else
00045 #  include <strings.h>
00046 #endif
00047 
00048 #include "tcl.h"
00049 #include "machine.h"
00050 #include "bu.h"
00051 #include "vmath.h"
00052 #include "raytrace.h"
00053 #include "rtgeom.h"
00054 
00055 
00056 #define PRINT_USAGE Tcl_AppendResult(interp, "c: usage 'c [-cr] comb_name [bool_expr]'\n",\
00057                                      (char *)NULL)
00058 
00059 struct tokens {
00060         struct bu_list          l;
00061         short                   type;
00062         union tree              *tp;
00063 };
00064 
00065 /* token types */
00066 #define WDB_TOK_NULL    0
00067 #define WDB_TOK_LPAREN  1
00068 #define WDB_TOK_RPAREN  2
00069 #define WDB_TOK_UNION   3
00070 #define WDB_TOK_INTER   4
00071 #define WDB_TOK_SUBTR   5
00072 #define WDB_TOK_TREE    6
00073 
00074 HIDDEN void
00075 wdb_free_tokens(struct bu_list *hp)
00076 {
00077         struct tokens *tok;
00078 
00079         BU_CK_LIST_HEAD(hp);
00080 
00081         while (BU_LIST_WHILE(tok, tokens, hp)) {
00082                 BU_LIST_DEQUEUE(&tok->l);
00083                 if (tok->type == WDB_TOK_TREE) {
00084                         if (tok->tp)
00085                                 db_free_tree(tok->tp, &rt_uniresource);
00086                 }
00087         }
00088 }
00089 
00090 HIDDEN void
00091 wdb_append_union(struct bu_list *hp)
00092 {
00093         struct tokens *tok;
00094 
00095         BU_CK_LIST_HEAD( hp );
00096 
00097         tok = (struct tokens *)bu_malloc(sizeof(struct tokens), "tok");
00098         tok->type = WDB_TOK_UNION;
00099         tok->tp = (union tree *)NULL;
00100         BU_LIST_INSERT(hp, &tok->l);
00101 }
00102 
00103 HIDDEN void
00104 wdb_append_inter(struct bu_list *hp)
00105 {
00106         struct tokens *tok;
00107 
00108         BU_CK_LIST_HEAD(hp);
00109 
00110         tok = (struct tokens *)bu_malloc(sizeof(struct tokens), "tok");
00111         tok->type = WDB_TOK_INTER;
00112         tok->tp = (union tree *)NULL;
00113         BU_LIST_INSERT( hp, &tok->l );
00114 }
00115 
00116 HIDDEN void
00117 wdb_append_subtr(struct bu_list *hp)
00118 {
00119         struct tokens *tok;
00120 
00121         BU_CK_LIST_HEAD(hp);
00122 
00123         tok = (struct tokens *)bu_malloc(sizeof(struct tokens), "tok");
00124         tok->type = WDB_TOK_SUBTR;
00125         tok->tp = (union tree *)NULL;
00126         BU_LIST_INSERT( hp, &tok->l );
00127 }
00128 
00129 HIDDEN void
00130 wdb_append_lparen(struct bu_list *hp)
00131 {
00132         struct tokens *tok;
00133 
00134         BU_CK_LIST_HEAD(hp);
00135 
00136         tok = (struct tokens *)bu_malloc(sizeof(struct tokens), "tok");
00137         tok->type = WDB_TOK_LPAREN;
00138         tok->tp = (union tree *)NULL;
00139         BU_LIST_INSERT( hp, &tok->l );
00140 }
00141 
00142 HIDDEN void
00143 wdb_append_rparen(struct bu_list *hp)
00144 {
00145         struct tokens *tok;
00146 
00147         BU_CK_LIST_HEAD(hp);
00148 
00149         tok = (struct tokens *)bu_malloc(sizeof(struct tokens), "tok");
00150         tok->type = WDB_TOK_RPAREN;
00151         tok->tp = (union tree *)NULL;
00152         BU_LIST_INSERT(hp, &tok->l);
00153 }
00154 
00155 HIDDEN int
00156 wdb_add_operator(Tcl_Interp *interp, struct bu_list *hp, char ch, short int *last_tok)
00157 {
00158         char illegal[2];
00159 
00160         BU_CK_LIST_HEAD(hp);
00161 
00162         switch( ch )
00163         {
00164                 case 'u':
00165                         wdb_append_union(hp);
00166                         *last_tok = WDB_TOK_UNION;
00167                         break;
00168                 case '+':
00169                         wdb_append_inter(hp);
00170                         *last_tok = WDB_TOK_INTER;
00171                         break;
00172                 case '-':
00173                         wdb_append_subtr(hp);
00174                         *last_tok = WDB_TOK_SUBTR;
00175                         break;
00176                 default:
00177                         illegal[0] = ch;
00178                         illegal[1] = '\0';
00179                         Tcl_AppendResult(interp, "Illegal operator: ", illegal,
00180                                 ", aborting\n", (char *)NULL );
00181                         wdb_free_tokens(hp);
00182                         return TCL_ERROR;
00183         }
00184         return TCL_OK;
00185 }
00186 
00187 HIDDEN int
00188 wdb_add_operand(Tcl_Interp *interp, struct bu_list *hp, char *name)
00189 {
00190         char *ptr_lparen;
00191         char *ptr_rparen;
00192         int name_len;
00193         union tree *node;
00194         struct tokens *tok;
00195 
00196         BU_CK_LIST_HEAD(hp);
00197 
00198         ptr_lparen = strchr(name, '(');
00199         ptr_rparen = strchr(name, ')');
00200 
00201         RT_GET_TREE( node, &rt_uniresource );
00202         node->magic = RT_TREE_MAGIC;
00203         node->tr_op = OP_DB_LEAF;
00204         node->tr_l.tl_mat = (matp_t)NULL;
00205         if (ptr_lparen || ptr_rparen) {
00206                 int tmp1,tmp2;
00207 
00208                 if (ptr_rparen)
00209                         tmp1 = ptr_rparen - name;
00210                 else
00211                         tmp1 = (-1);
00212                 if (ptr_lparen)
00213                         tmp2 = ptr_lparen - name;
00214                 else
00215                         tmp2 = (-1);
00216 
00217                 if (tmp2 == (-1) && tmp1 > 0)
00218                         name_len = tmp1;
00219                 else if (tmp1 == (-1) && tmp2 > 0)
00220                         name_len = tmp2;
00221                 else if(tmp1 > 0 && tmp2 > 0) {
00222                         if (tmp1 < tmp2)
00223                                 name_len = tmp1;
00224                         else
00225                                 name_len = tmp2;
00226                 }
00227                 else {
00228                         Tcl_AppendResult(interp, "Cannot determine length of operand name: ",
00229                                 name, ", aborting\n", (char *)NULL);
00230                         return (0);
00231                 }
00232         } else
00233                 name_len = strlen( name );
00234 
00235         node->tr_l.tl_name = (char *)bu_malloc(name_len + 1, "node name");
00236         strncpy(node->tr_l.tl_name, name, name_len);
00237         node->tr_l.tl_name[name_len] = '\0';
00238         tok = (struct tokens *)bu_malloc(sizeof(struct tokens), "tok");
00239         tok->type = WDB_TOK_TREE;
00240         tok->tp = node;
00241         BU_LIST_INSERT(hp, &tok->l);
00242         return (name_len);
00243 }
00244 
00245 HIDDEN void
00246 wdb_do_inter(struct bu_list *hp)
00247 {
00248         struct tokens *tok;
00249 
00250         for (BU_LIST_FOR(tok, tokens, hp )) {
00251                 struct tokens *prev, *next;
00252                 union tree *tp;
00253 
00254                 if (tok->type != WDB_TOK_INTER)
00255                         continue;
00256 
00257                 prev = BU_LIST_PREV( tokens, &tok->l );
00258                 next = BU_LIST_NEXT( tokens, &tok->l );
00259 
00260                 if (prev->type !=WDB_TOK_TREE || next->type != WDB_TOK_TREE)
00261                         continue;
00262 
00263                 /* this is an eligible intersection operation */
00264                 tp = (union tree *)bu_malloc( sizeof( union tree ), "tp" );
00265                 tp->magic = RT_TREE_MAGIC;
00266                 tp->tr_b.tb_op = OP_INTERSECT;
00267                 tp->tr_b.tb_regionp = (struct region *)NULL;
00268                 tp->tr_b.tb_left = prev->tp;
00269                 tp->tr_b.tb_right = next->tp;
00270                 BU_LIST_DEQUEUE( &tok->l );
00271                 bu_free( (char *)tok, "tok" );
00272                 BU_LIST_DEQUEUE( &prev->l );
00273                 bu_free( (char *)prev, "prev" );
00274                 next->tp = tp;
00275                 tok = next;
00276         }
00277 }
00278 
00279 HIDDEN void
00280 wdb_do_union_subtr(struct bu_list *hp)
00281 {
00282         struct tokens *tok;
00283 
00284         for(BU_LIST_FOR(tok, tokens, hp)) {
00285                 struct tokens *prev, *next;
00286                 union tree *tp;
00287 
00288                 if (tok->type != WDB_TOK_UNION && tok->type != WDB_TOK_SUBTR)
00289                         continue;
00290 
00291                 prev = BU_LIST_PREV( tokens, &tok->l );
00292                 next = BU_LIST_NEXT( tokens, &tok->l );
00293 
00294                 if (prev->type !=WDB_TOK_TREE || next->type != WDB_TOK_TREE)
00295                         continue;
00296 
00297                 /* this is an eligible operation */
00298                 tp = (union tree *)bu_malloc( sizeof( union tree ), "tp" );
00299                 tp->magic = RT_TREE_MAGIC;
00300                 if (tok->type == WDB_TOK_UNION)
00301                         tp->tr_b.tb_op = OP_UNION;
00302                 else
00303                         tp->tr_b.tb_op = OP_SUBTRACT;
00304                 tp->tr_b.tb_regionp = (struct region *)NULL;
00305                 tp->tr_b.tb_left = prev->tp;
00306                 tp->tr_b.tb_right = next->tp;
00307                 BU_LIST_DEQUEUE(&tok->l);
00308                 bu_free((char *)tok, "tok");
00309                 BU_LIST_DEQUEUE(&prev->l);
00310                 bu_free((char *)prev, "prev");
00311                 next->tp = tp;
00312                 tok = next;
00313         }
00314 }
00315 
00316 HIDDEN int
00317 wdb_do_paren(struct bu_list *hp)
00318 {
00319         struct tokens *tok;
00320 
00321         for (BU_LIST_FOR(tok, tokens, hp)) {
00322                 struct tokens *prev, *next;
00323 
00324                 if (tok->type != WDB_TOK_TREE)
00325                         continue;
00326 
00327                 prev = BU_LIST_PREV( tokens, &tok->l );
00328                 next = BU_LIST_NEXT( tokens, &tok->l );
00329 
00330                 if (prev->type !=WDB_TOK_LPAREN || next->type != WDB_TOK_RPAREN)
00331                         continue;
00332 
00333                 /* this is an eligible operand surrounded by parens */
00334                 BU_LIST_DEQUEUE(&next->l);
00335                 bu_free((char *)next, "next");
00336                 BU_LIST_DEQUEUE(&prev->l);
00337                 bu_free((char *)prev, "prev");
00338         }
00339 
00340         if (hp->forw == hp->back && hp->forw != hp)
00341                 return 1;       /* done */
00342         else if (BU_LIST_IS_EMPTY(hp))
00343                 return -1;      /* empty tree!!!! */
00344         else
00345                 return 0;       /* more to do */
00346 
00347 }
00348 
00349 HIDDEN union tree *
00350 wdb_eval_bool(struct bu_list *hp)
00351 {
00352         int done=0;
00353         union tree *final_tree;
00354         struct tokens *tok;
00355 
00356         while (done != 1) {
00357                 wdb_do_inter(hp);
00358                 wdb_do_union_subtr(hp);
00359                 done = wdb_do_paren(hp);
00360         }
00361 
00362         if (done == 1) {
00363                 tok = BU_LIST_NEXT(tokens, hp);
00364                 final_tree = tok->tp;
00365                 BU_LIST_DEQUEUE(&tok->l);
00366                 bu_free((char *)tok, "tok");
00367                 return(final_tree);
00368         }
00369 
00370         return (union tree *)NULL;
00371 }
00372 
00373 HIDDEN int
00374 wdb_check_syntax(Tcl_Interp *interp, struct db_i *dbip, struct bu_list *hp, char *comb_name, struct directory *dp)
00375 {
00376         struct tokens *tok;
00377         int paren_count=0;
00378         int paren_error=0;
00379         int missing_exp=0;
00380         int missing_op=0;
00381         int op_count=0;
00382         int arg_count=0;
00383         int circular_ref=0;
00384         int errors=0;
00385         short last_tok=WDB_TOK_NULL;
00386 
00387         if(dbip == DBI_NULL)
00388           return 0;
00389 
00390         for( BU_LIST_FOR( tok, tokens, hp ) )
00391         {
00392                 switch( tok->type )
00393                 {
00394                         case WDB_TOK_LPAREN:
00395                                 paren_count++;
00396                                 if( last_tok == WDB_TOK_RPAREN )
00397                                         missing_op++;
00398                                 break;
00399                         case WDB_TOK_RPAREN:
00400                                 paren_count--;
00401                                 if( last_tok == WDB_TOK_LPAREN )
00402                                         missing_exp++;
00403                                 break;
00404                         case WDB_TOK_UNION:
00405                         case WDB_TOK_SUBTR:
00406                         case WDB_TOK_INTER:
00407                                 op_count++;
00408                                 break;
00409                         case WDB_TOK_TREE:
00410                                 arg_count++;
00411                                 if( !dp && !strcmp( comb_name, tok->tp->tr_l.tl_name ) )
00412                                         circular_ref++;
00413                                 else if( db_lookup( dbip, tok->tp->tr_l.tl_name, LOOKUP_QUIET ) == DIR_NULL )
00414                                         Tcl_AppendResult(interp, "WARNING: '",
00415                                                 tok->tp->tr_l.tl_name,
00416                                                 "' does not actually exist\n", (char *)NULL );
00417                                 break;
00418                 }
00419                 if( paren_count < 0 )
00420                         paren_error++;
00421                 last_tok = tok->type;
00422         }
00423 
00424         if( paren_count || paren_error )
00425         {
00426                 Tcl_AppendResult(interp, "ERROR: unbalanced parenthesis\n", (char *)NULL );
00427                 errors++;
00428         }
00429 
00430         if( missing_exp )
00431         {
00432                 Tcl_AppendResult(interp, "ERROR: empty parenthesis (missing expression)\n", (char *)NULL );
00433                 errors++;
00434         }
00435 
00436         if( missing_op )
00437         {
00438                 Tcl_AppendResult(interp, "ERROR: must have operator between ')('\n", (char *)NULL );
00439                 errors++;
00440         }
00441 
00442         if( op_count != arg_count-1 )
00443         {
00444                 Tcl_AppendResult(interp, "ERROR: mismatch of operators and operands\n", (char *)NULL );
00445                 errors++;
00446         }
00447 
00448         if( circular_ref )
00449         {
00450                 Tcl_AppendResult(interp, "ERROR: combination cannot reference itself during initial creation\n", (char *)NULL );
00451                 errors++;
00452         }
00453 
00454         if( errors )
00455         {
00456                 Tcl_AppendResult(interp, "\t---------aborting!\n", (char *)NULL );
00457                 return( 1 );
00458         }
00459 
00460         return( 0 );
00461 }
00462 
00463 int
00464 wdb_comb_std_cmd(struct rt_wdb  *wdbp,
00465                 Tcl_Interp      *interp,
00466                 int             argc,
00467                 char            **argv)
00468 {
00469         char                            *comb_name;
00470         int                             ch;
00471         int                             region_flag = -1;
00472         register struct directory       *dp;
00473         struct rt_db_internal           intern;
00474         struct rt_comb_internal         *comb = NULL;
00475         struct tokens                   tok_hd;
00476         struct tokens                   *tok;
00477         short                           last_tok;
00478         int                             i;
00479         union tree                      *final_tree;
00480 
00481         if (wdbp->dbip->dbi_read_only) {
00482                 Tcl_AppendResult(interp, "Database is read-only!\n", (char *)NULL);
00483                 return TCL_ERROR;
00484         }
00485 
00486         if (argc < 3 || RT_MAXARGS < argc) {
00487           struct bu_vls vls;
00488 
00489           bu_vls_init(&vls);
00490           bu_vls_printf(&vls, "helplib_alias wdb_comb_std %s", argv[0]);
00491           Tcl_Eval(interp, bu_vls_addr(&vls));
00492           bu_vls_free(&vls);
00493           return TCL_ERROR;
00494         }
00495 
00496         /* Parse options */
00497         bu_optind = 1;  /* re-init bu_getopt() */
00498         while ((ch = bu_getopt(argc, argv, "cgr?")) != EOF) {
00499                 switch (ch) {
00500                 case 'c':
00501                 case 'g':
00502                         region_flag = 0;
00503                         break;
00504                 case 'r':
00505                         region_flag = 1;
00506                         break;
00507                 /* XXX How about -p and -v for FASTGEN? */
00508                 case '?':
00509                 default:
00510                         PRINT_USAGE;
00511                         return TCL_OK;
00512                 }
00513         }
00514         argc -= (bu_optind + 1);
00515         argv += bu_optind;
00516 
00517         comb_name = *argv++;
00518         if (argc == -1) {
00519                 PRINT_USAGE;
00520                 return TCL_OK;
00521         }
00522 
00523         if ((region_flag != -1) && (argc == 0)) {
00524                 /*
00525                  *      Set/Reset the REGION flag of an existing combination
00526                  */
00527                 if ((dp = db_lookup(wdbp->dbip, comb_name, LOOKUP_NOISY)) == DIR_NULL)
00528                         return TCL_ERROR;
00529 
00530                 if (!(dp->d_flags & DIR_COMB)) {
00531                         Tcl_AppendResult(interp, comb_name, " is not a combination\n", (char *)0 );
00532                         return TCL_ERROR;
00533                 }
00534 
00535                 if (rt_db_get_internal(&intern, dp, wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) {
00536                         Tcl_AppendResult(interp, "Database read error, aborting\n", (char *)NULL);
00537                         return TCL_ERROR;
00538                 }
00539                 comb = (struct rt_comb_internal *)intern.idb_ptr;
00540                 RT_CK_COMB(comb);
00541 
00542                 if (region_flag) {
00543                         if( !comb->region_flag ) {
00544                                 /* assign values from the defaults */
00545                                 comb->region_id = wdbp->wdb_item_default++;
00546                                 comb->aircode = wdbp->wdb_air_default;
00547                                 comb->GIFTmater = wdbp->wdb_mat_default;
00548                                 comb->los = wdbp->wdb_los_default;
00549                         }
00550                         comb->region_flag = 1;
00551                 }
00552                 else
00553                         comb->region_flag = 0;
00554 
00555                 if (rt_db_put_internal(dp, wdbp->dbip, &intern, &rt_uniresource) < 0) {
00556                         rt_db_free_internal(&intern, &rt_uniresource);
00557                         Tcl_AppendResult(interp, "Database write error, aborting\n", (char *)NULL);
00558                         return TCL_ERROR;
00559                 }
00560 
00561                 return TCL_OK;
00562         }
00563         /*
00564          *      At this point, we know we have a Boolean expression.
00565          *      If the combination already existed and region_flag is -1,
00566          *      then leave its region_flag alone.
00567          *      If the combination didn't exist yet,
00568          *      then pretend region_flag was 0.
00569          *      Otherwise, make sure to set its c_flags according to region_flag.
00570          */
00571 
00572         dp = db_lookup( wdbp->dbip, comb_name, LOOKUP_QUIET );
00573         if (dp != DIR_NULL) {
00574                 Tcl_AppendResult(interp, "ERROR: ", comb_name, " already exists\n", (char *)0 );
00575                 return TCL_ERROR;
00576         }
00577 
00578         /* parse Boolean expression */
00579         BU_LIST_INIT(&tok_hd.l);
00580         tok_hd.type = WDB_TOK_NULL;
00581 
00582         last_tok = WDB_TOK_LPAREN;
00583         for (i=0 ; i<argc ; i++) {
00584                 char *ptr;
00585 
00586                 ptr = argv[i];
00587                 while (*ptr) {
00588                         while (*ptr == '(' || *ptr == ')') {
00589                                 switch (*ptr) {
00590                                 case '(':
00591                                         wdb_append_lparen( &tok_hd.l );
00592                                         last_tok = WDB_TOK_LPAREN;
00593                                         break;
00594                                 case ')':
00595                                         wdb_append_rparen( &tok_hd.l );
00596                                         last_tok = WDB_TOK_RPAREN;
00597                                         break;
00598                                 }
00599                                 ptr++;
00600                         }
00601 
00602                         if (*ptr == '\0')
00603                                 continue;
00604 
00605                         if (last_tok == WDB_TOK_RPAREN) {
00606                                 /* next token MUST be an operator */
00607                                 if (wdb_add_operator(interp, &tok_hd.l, *ptr, &last_tok) == TCL_ERROR) {
00608                                         wdb_free_tokens(&tok_hd.l);
00609                                         if (dp != DIR_NULL)
00610                                                 rt_db_free_internal(&intern, &rt_uniresource);
00611                                         return TCL_ERROR;
00612                                 }
00613                                 ptr++;
00614                         } else if (last_tok == WDB_TOK_LPAREN) {
00615                                 /* next token MUST be an operand */
00616                                 int name_len;
00617 
00618                                 name_len = wdb_add_operand(interp, &tok_hd.l, ptr );
00619                                 if (name_len < 1) {
00620                                         wdb_free_tokens(&tok_hd.l);
00621                                         if (dp != DIR_NULL)
00622                                                 rt_db_free_internal(&intern, &rt_uniresource);
00623                                         return TCL_ERROR;
00624                                 }
00625                                 last_tok = WDB_TOK_TREE;
00626                                 ptr += name_len;
00627                         } else if (last_tok == WDB_TOK_TREE) {
00628                                 /* must be an operator */
00629                                 if (wdb_add_operator(interp, &tok_hd.l, *ptr, &last_tok) == TCL_ERROR) {
00630                                         wdb_free_tokens(&tok_hd.l);
00631                                         if (dp != DIR_NULL)
00632                                                 rt_db_free_internal(&intern, &rt_uniresource);
00633                                         return TCL_ERROR;
00634                                 }
00635                                 ptr++;
00636                         } else if (last_tok == WDB_TOK_UNION ||
00637                                    last_tok == WDB_TOK_INTER ||
00638                                    last_tok == WDB_TOK_SUBTR) {
00639                                 /* must be an operand */
00640                                 int name_len;
00641 
00642                                 name_len = wdb_add_operand(interp, &tok_hd.l, ptr );
00643                                 if (name_len < 1) {
00644                                         wdb_free_tokens(&tok_hd.l);
00645                                         if (dp != DIR_NULL)
00646                                                 rt_db_free_internal(&intern, &rt_uniresource);
00647                                         return TCL_ERROR;
00648                                 }
00649                                 last_tok = WDB_TOK_TREE;
00650                                 ptr += name_len;
00651                         }
00652                 }
00653         }
00654 
00655         if (wdb_check_syntax(interp, wdbp->dbip, &tok_hd.l, comb_name, dp)) {
00656                 wdb_free_tokens(&tok_hd.l);
00657                 return TCL_ERROR;
00658         }
00659 
00660         /* replace any occurences of comb_name with existing tree */
00661         if (dp != DIR_NULL) {
00662                 for (BU_LIST_FOR(tok, tokens, &tok_hd.l)) {
00663                         struct rt_db_internal intern1;
00664                         struct rt_comb_internal *comb1;
00665 
00666                         switch (tok->type) {
00667                         case WDB_TOK_LPAREN:
00668                         case WDB_TOK_RPAREN:
00669                         case WDB_TOK_UNION:
00670                         case WDB_TOK_INTER:
00671                         case WDB_TOK_SUBTR:
00672                                 break;
00673                         case WDB_TOK_TREE:
00674                                 if (!strcmp(tok->tp->tr_l.tl_name, comb_name)) {
00675                                         db_free_tree( tok->tp, &rt_uniresource );
00676                                         if (rt_db_get_internal(&intern1, dp, wdbp->dbip, (fastf_t *)NULL, &rt_uniresource) < 0) {
00677                                                 Tcl_AppendResult(interp, "Cannot get records for ", comb_name, "\n" );
00678                                                 Tcl_AppendResult(interp, "Database read error, aborting\n", (char *)NULL);
00679                                                 return TCL_ERROR;
00680                                         }
00681                                         comb1 = (struct rt_comb_internal *)intern1.idb_ptr;
00682                                         RT_CK_COMB(comb1);
00683 
00684                                         tok->tp = comb1->tree;
00685                                         comb1->tree = (union tree *)NULL;
00686                                         rt_db_free_internal(&intern1, &rt_uniresource);
00687                                 }
00688                                 break;
00689                         default:
00690                                 Tcl_AppendResult(interp, "ERROR: Unrecognized token type\n", (char *)NULL);
00691                                 wdb_free_tokens(&tok_hd.l);
00692                                 return TCL_ERROR;
00693                         }
00694                 }
00695         }
00696 
00697         final_tree = wdb_eval_bool(&tok_hd.l);
00698 
00699         if (dp == DIR_NULL) {
00700                 int flags;
00701 
00702                 flags = DIR_COMB;
00703                 BU_GETSTRUCT(comb, rt_comb_internal);
00704                 comb->magic = RT_COMB_MAGIC;
00705                 comb->tree = final_tree;
00706                 bu_vls_init(&comb->shader);
00707                 bu_vls_init(&comb->material);
00708                 comb->region_id = -1;
00709                 if (region_flag == (-1))
00710                         comb->region_flag = 0;
00711                 else
00712                         comb->region_flag = region_flag;
00713 
00714                 if (comb->region_flag) {
00715                         struct bu_vls tmp_vls;
00716 
00717                         comb->region_flag = 1;
00718                         comb->region_id = wdbp->wdb_item_default++;;
00719                         comb->aircode = wdbp->wdb_air_default;
00720                         comb->los = wdbp->wdb_los_default;
00721                         comb->GIFTmater = wdbp->wdb_mat_default;
00722                         bu_vls_init(&tmp_vls);
00723                         bu_vls_printf(&tmp_vls,
00724                                 "Creating region id=%d, air=%d, los=%d, GIFTmaterial=%d\n",
00725                                 comb->region_id, comb->aircode, comb->los, comb->GIFTmater);
00726                         Tcl_AppendResult(interp, bu_vls_addr(&tmp_vls), (char *)NULL);
00727                         bu_vls_free(&tmp_vls);
00728 
00729                         flags |= DIR_REGION;
00730                 }
00731 
00732                 RT_INIT_DB_INTERNAL(&intern);
00733                 intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
00734                 intern.idb_type = ID_COMBINATION;
00735                 intern.idb_meth = &rt_functab[ID_COMBINATION];
00736                 intern.idb_ptr = (genptr_t)comb;
00737 
00738                 if ((dp=db_diradd(wdbp->dbip, comb_name, -1L, 0, flags, (genptr_t)&intern.idb_type)) == DIR_NULL) {
00739                         Tcl_AppendResult(interp, "Failed to add ", comb_name,
00740                                          " to directory, aborting\n" , (char *)NULL);
00741                         return TCL_ERROR;
00742                 }
00743 
00744                 if (rt_db_put_internal(dp, wdbp->dbip, &intern, &rt_uniresource) < 0) {
00745                         Tcl_AppendResult(interp, "Failed to write ", dp->d_namep, (char *)NULL );
00746                         return TCL_ERROR;
00747                 }
00748         } else {
00749                 db_delete(wdbp->dbip, dp);
00750 
00751                 dp->d_len = 0;
00752                 dp->d_un.file_offset = -1;
00753                 db_free_tree(comb->tree, &rt_uniresource);
00754                 comb->tree = final_tree;
00755 
00756                 if (rt_db_put_internal(dp, wdbp->dbip, &intern, &rt_uniresource) < 0) {
00757                         Tcl_AppendResult(interp, "Failed to write ", dp->d_namep, (char *)NULL );
00758                         return TCL_ERROR;
00759                 }
00760         }
00761 
00762         return TCL_OK;
00763 }
00764 
00765 /*
00766  * Input a combination in standard set-theoretic notation.
00767  *
00768  * Usage:
00769  *        procname c [-gr] comb_name boolean_expr
00770  *
00771  * NON-PARALLEL because of rt_uniresource
00772  */
00773 int
00774 wdb_comb_std_tcl(ClientData     clientData,
00775                  Tcl_Interp     *interp,
00776                  int            argc,
00777                  char           **argv)
00778 {
00779         struct rt_wdb *wdbp = (struct rt_wdb *)clientData;
00780 
00781         return wdb_comb_std_cmd(wdbp, interp, argc-1, argv+1);
00782 }
00783 /*@}*/
00784 
00785 /*
00786  * Local Variables:
00787  * mode: C
00788  * tab-width: 8
00789  * c-basic-offset: 4
00790  * indent-tabs-mode: t
00791  * End:
00792  * ex: shiftwidth=4 tabstop=8
00793  */

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