source: tol/toltcl/generic/tolaccess.cpp @ 41d0e3c

1941-docker-image-to-testdevel
Last change on this file since 41d0e3c was 41d0e3c, checked in by Jorge Pérez <josp.jorge@…>, 17 years ago

Fixed compilation bug:

..\generic\tolaccess.cpp(869) : error C2057: expected constant expression
..\generic\tolaccess.cpp(869) : error C2466: cannot allocate an array of constant size 0
..\generic\tolaccess.cpp(869) : error C2133: 'datav' : unknown size

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@1206 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 71.0 KB
Line 
1/* tolaccess.cpp: This file implements an interface between object in tol
2                  and "objects" in tclThis file define a set of utils
3                  functions.
4                  GNU/tolTcl Library
5
6   Copyright (C) 2001, 2002, 2003 - Bayes Decisión, SL
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2, or (at your option)
11   any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21   USA.
22 */
23
24#include <ctype.h>
25
26#if defined(_MSC_VER)
27#  include <win_tolinc.h>
28#endif
29
30#include <tol/tol_init.h>
31#include <tol/tol_version_def.h>
32#include <tol/tol_bcommon.h>
33#include <tol/tol_bstruct.h>
34#include <tol/tol_blanguag.h>
35#include <tol/tol_bmatgra.h>
36#include <tol/tol_bvmatgra.h>
37#include <tol/tol_bnameblock.h>
38#include <tol/tol_bspfun.h>
39#include <tol/tol_bcodgra.h>
40#include <tol/tol_bsetgra.h>
41#include <tol/tol_btsrgra.h>
42#include <tol/tol_btxtgra.h>
43#include <tol/tol_bmethodhook.h>
44
45#include <toltclInt.h>
46#include <tt_pool.h>
47
48
49/*
50 * if SyntaxObject has IsFile implemented, uncomment the following
51 * define:
52 */
53
54#define ISFILE_IMPLEMENTED
55
56typedef void (* getmethod)( const BSyntaxObject *, BText & );
57typedef int  (* checkmethod)( const BSyntaxObject * );
58
59static
60int QuickSort( Tcl_Interp * interp, Tcl_Obj * list );
61
62inline
63char * skipWhite(char * pch)
64{
65  while (*pch && isspace(*pch))
66    ++pch;
67  return pch;
68}
69
70static
71BText GetObjectName(const BSyntaxObject * so)
72{
73  return so->HasName() ? so->FullName() : so->LocalName();
74}
75
76static
77void GetName( const BSyntaxObject * so, BText & res )
78{
79  res = so->FullName();
80}
81
82static
83void GetIdentify( const BSyntaxObject * so, BText & res )
84{
85  res = so->Identify();
86}
87
88static
89void GetPath( const BSyntaxObject * so, BText & res )
90{
91  res = so->TolPath();
92}
93
94static
95int
96ExcludeAnything( const BSyntaxObject * so )
97{
98  return so != GraAnything();
99}
100
101static
102int HasNoSource( const BSyntaxObject * so )
103{
104  return !so->Source();
105}
106
107static
108int BList2TclList( Tcl_Interp * interp,
109                   BList * blist, Tcl_Obj * tcl_list,
110                   getmethod m, checkmethod accept = NULL)
111{
112  char * str;
113  Tcl_Obj * name;
114  Tcl_DString dstr;
115  BText tmp;
116
117  while(blist)
118  {
119    BSyntaxObject* so = (BSyntaxObject*)Car(blist);
120    if(!accept || (*accept)(so))
121    {
122      (*m)(so,tmp);
123      str = Tcl_ExternalToUtfDString(NULL,tmp,-1,&dstr);
124      name = Tcl_NewStringObj(str,-1);
125      Tcl_DStringFree(&dstr);
126      if ( Tcl_ListObjAppendElement(interp, tcl_list, name) != TCL_OK ) {
127        Tcl_DecrRefCount(name);
128        return TCL_ERROR;
129      }
130    }
131    blist = Cdr(blist);
132  }
133  return TCL_OK;
134}
135
136/*
137 * Fill in obj_result the result of avaluating in TOL the given
138 * string.
139 *
140 */
141
142/* cdr of console_stack point to first item */
143static BList console_stack;
144// Read only stack
145static BList console_stack_hidden;
146
147static
148void my_concat(BList* head, BList* tail)
149{
150  if (head->Cdr()) {
151    my_concat(head->Cdr(), tail);
152  } else {
153    head->PutCdr(tail);
154  }
155}
156
157int Tol_EvalExpr (Tcl_Obj * obj_expr, int hidden, Tcl_Obj * obj_result)
158{
159  BList * tol_result;
160  Tcl_DString dstr;
161  char * expr;
162 
163  Tcl_DStringInit(&dstr);
164  expr = Tcl_UtfToExternalDString(NULL,Tcl_GetString(obj_expr),-1,&dstr);
165  tol_result = MultyEvaluate(expr);
166  Tcl_DStringFree(&dstr);
167  if(tol_result) {
168    my_concat(hidden?&console_stack_hidden:&console_stack, tol_result);
169  }
170  /*  Tcl_AppendStringsToObj(obj_result,
171      "couldn't evaluate tol expresion \"",
172      Tcl_GetString(obj_expr), "\"", NULL);
173      return TCL_ERROR;*/
174  return TCL_OK;
175}
176
177int Tol_GetStructure( Tcl_Interp * interp, Tcl_Obj * name, Tcl_Obj * obj_result )
178{
179  Tcl_DString dstr;
180  BStruct * structure;
181  BStruct * substruct;
182
183  Tcl_DStringInit( &dstr );
184  Tcl_UtfToExternalDString( NULL, Tcl_GetString(name), -1, &dstr );
185  if ( Tcl_DStringLength( &dstr ) &&
186       (structure = FindStruct(Tcl_DStringValue(&dstr)))) {
187   
188    Tcl_Obj * tmp[2];
189    Tcl_Obj * info[2];
190    Tcl_Obj ** fields;
191    BText btxt;
192    int nfields;
193   
194    nfields = structure->Size();
195    fields = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*) * nfields );
196    for ( int i = 0; i < nfields; i++ ) {
197      BField & field = (*structure)[i];
198      btxt = field.Name();
199      Tcl_DStringFree(&dstr);
200      Tcl_ExternalToUtfDString( NULL, btxt, -1, &dstr );
201      info[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
202      Tcl_DStringFree( &dstr );
203      if ( (substruct = field.Struct()) ) {
204        btxt = substruct->Name();
205        Tcl_ExternalToUtfDString( NULL, btxt, -1, &dstr );
206        tmp[0] = Tcl_NewStringObj( "STRUCT", 6 );
207        tmp[1] = Tcl_NewStringObj( Tcl_DStringValue(&dstr), -1);
208        info[1] = Tcl_NewListObj( 2, tmp );
209      } else if ( field.Grammar() ) {
210        btxt = field.Grammar()->Name();
211        Tcl_ExternalToUtfDString( NULL, btxt, -1, &dstr );
212        info[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
213      }
214      fields[i] = Tcl_NewListObj(2,info);
215    }
216    Tcl_SetListObj( obj_result, nfields, fields );
217    Tcl_Free( (char*)fields );
218  }
219  return TCL_OK;
220}
221
222BSet* ContainerGetSet(const BSyntaxObject *container)
223{
224  if (container) {
225    if (container->Grammar()==GraSet())
226      return &(((BUserSet*)container)->Contens());
227    else if (container->Grammar()==GraNameBlock())
228      return &(((BUserNameBlock*)container)->Contens().Set());
229  }
230  return NULL;
231}
232 
233/*
234 * Return the path of a set if it is a file, trigger an error in other case
235 *
236 */
237
238int Tol_GetSetPath( Tcl_Interp * interp, Tcl_Obj * name, Tcl_Obj * obj_result )
239{
240  Tcl_DString uniBuffer;
241  const BSyntaxObject * syn;
242
243 /* if name contains spaces the we should try it first as a string */
244  Tcl_DStringInit(&uniBuffer);
245  Tcl_UtfToExternalDString(NULL,Tcl_GetString(name),-1,&uniBuffer);
246  BText fname(Tcl_DStringValue(&uniBuffer));
247  syn = (BSyntaxObject*)BSetFromFile::FindCompiled(fname);
248  Tcl_DStringFree(&uniBuffer);
249  if (!syn) {
250    syn = Tol_ResolveObject(interp, name, obj_result);
251  }
252  if ( !syn )
253    return TCL_ERROR;
254  BSet *ptrSet = ContainerGetSet(syn);
255  if ( ptrSet->SubType() >= BSet::MODFile && ptrSet->SubType() <= BSet::BMIFile ) {
256    Tcl_DString dstr;
257    BText path( syn->TolPath() );
258
259    Tcl_DStringInit( &dstr );
260    Tcl_ExternalToUtfDString(NULL,path,-1,&dstr);
261    Tcl_SetStringObj( obj_result, Tcl_DStringValue(&dstr), -1 );
262    return TCL_OK;
263  } else {
264    Tcl_AppendStringsToObj( obj_result, Tcl_GetString(name),
265                            " is not a valid file object", NULL );
266    return TCL_ERROR;
267  }
268}
269
270/*
271 * Fill in obj_result the content of the given tol object's names. The
272 * object are searched in the console's stack.
273 *
274 * Return:
275 *
276 *   {GRAMMAR NAME CONTENT PATH DESCRIPTION ISFILE [Has SubSet? SUBTYPE STRUCTURE]}
277 */
278
279int Tol_ListStack(Tcl_Interp * interp,int objc,Tcl_Obj *CONST objv[],
280                  Tcl_Obj * obj_result)
281{
282  BSyntaxObject * so;
283  BText btxt;
284  Tcl_DString dstr;
285  BList * tol_item;
286  Tcl_Obj * robjv[9];
287  int robjc;
288  Tcl_Obj * tcl_item;
289  int tcl_result;
290  BSet * ptrSet = 0;
291  int tmpCard;
292  int j;
293 
294  Tcl_DStringInit(&dstr);
295 
296  tol_item = console_stack.Cdr();
297  while (tol_item) {
298    so = (BSyntaxObject*)Car(tol_item);
299   
300    /* GRAMMAR NAME */
301    btxt = so->Grammar()->Name();
302    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
303    robjv[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
304    Tcl_DStringFree(&dstr);
305   
306    /* OBJECT NAME */
307//  btxt = so->Identify();
308    GetName( so, btxt );
309    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
310    robjv[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
311    Tcl_DStringFree(&dstr);
312   
313    /* OBJECT CONTENT */
314    btxt = so->Info();
315    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
316    robjv[2] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
317    Tcl_DStringFree(&dstr);
318   
319    /* OBJECT PATH */
320    btxt = so->SourcePath();
321    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
322    robjv[3] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
323    Tcl_DStringFree(&dstr);
324   
325    /* OBJECT DESCRIPTION */
326    btxt = so->Description();
327    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
328    robjv[4] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
329    Tcl_DStringFree(&dstr);
330   
331    /* IS THE OBJECT A FILE? */
332    robjv[5] = Tcl_NewIntObj(so->IsFile());
333////    if ( so->Grammar()==GraSet() ) {
334    if ( so->Grammar()==GraSet() || so->Grammar()==GraNameBlock()) {
335      /* HAS SUBSET */
336////      ptrSet = &(((BUserSet*)so)->Contens());
337      ptrSet = ContainerGetSet(so);
338      tmpCard = ptrSet->Card();
339      for (j=1; j<=tmpCard; ++j )
340        if ( (*ptrSet)[j]->Grammar()==GraSet() )
341          break;
342      robjv[6] = Tcl_NewIntObj(j<=tmpCard);
343       
344      /* SUBTYPE INFO */
345      robjv[7] = Tcl_NewIntObj( ptrSet->SubType() );
346       
347      /* STRUCT INFO */
348      if ( ptrSet->Struct() ) {
349        btxt = ptrSet->Struct()->Name();
350        Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
351        robjv[8] = Tcl_NewStringObj( Tcl_DStringValue(&dstr), -1 );
352        Tcl_DStringFree( &dstr );
353      } else
354        robjv[8] = Tcl_NewStringObj( NULL, 0 );
355      robjc = 9;
356    } else
357      robjc = 6;
358   
359    /* build the tcl item as a list */
360    tcl_item = Tcl_NewListObj(robjc,robjv);
361   
362    /* append to the end of the result */
363    tcl_result = Tcl_ListObjAppendElement(interp,obj_result,tcl_item);
364    if (tcl_result != TCL_OK) {
365      Tcl_SetStringObj(obj_result,"",-1);
366      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
367      return TCL_ERROR;
368    }
369    tol_item = Cdr(tol_item);
370  }
371  return TCL_OK;
372}
373
374struct tcl_info_t
375{
376  Tcl_Interp *interp;
377  int objc;
378  Tcl_Obj* CONST* objv;
379  Tcl_DString &dstr;
380};
381
382/*
383 * Tol_ReleaseStack --
384 *
385 * Recursive version in order to release stack in reverse order
386 *
387 * Preconditions:
388 *
389 *   P != NULL
390 */
391static
392int Tol_ReleaseStack(tcl_info_t &info, BList *P)
393{
394  int result;
395 
396  assert(P != NULL);
397
398  if (P->Cdr()) {
399    /* keep on looking for rest of items */
400    result = Tol_ReleaseStack(info, P->Cdr());
401    /* process this item */
402    BList *current = P->Cdr();
403    BSyntaxObject * so;
404    int i;
405    so = (BSyntaxObject*)(current->Car());
406    if (info.objc) {
407      const char* name = so->Name().String();
408      for (i = 0; i<info.objc; ++i) {
409        Tcl_UtfToExternalDString(NULL,Tcl_GetString(info.objv[i]),-1,
410                                 &info.dstr);
411        if (!strcmp(Tcl_DStringValue(&info.dstr), name)) {
412          Tcl_DStringFree(&info.dstr);
413          break;
414        }
415        Tcl_DStringFree(&info.dstr);
416      }
417    } else {
418      /* mark current as being found */
419      i = -1;
420    }
421    if (i<info.objc) {
422      BList *next = current->Cdr();
423      /* delete will DecNRefs to the Car */
424      delete current;
425      /* now try to release the BSyntaxObject */
426      DESTROY(so);
427      /* chain the list */
428      P->PutCdr(next);
429    }
430  } else {
431    /* EOR */
432    result = TCL_OK;
433  }
434  return result;
435}
436
437int Tol_ReleaseStack(Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[],
438                     Tcl_Obj * obj_result)
439{
440  Tcl_DString dstr;
441  tcl_info_t tcl_info = {interp, objc, objv, dstr};
442  Tcl_DStringInit(&dstr);
443
444  return Tol_ReleaseStack(tcl_info, &console_stack);
445}
446
447/*!
448 * Tol_GetConsoleObject --
449 *
450 *     Returns the object with given index in the console object list.
451 */
452BSyntaxObject * Tol_GetConsoleObject(int index )
453{
454  BList * current = console_stack.Cdr();
455  int i = 1;
456  while (current) {
457    if (i==index) break;
458    current = Cdr(current);
459    ++i;
460  }
461  return current ? (BSyntaxObject*)(current->Car()) : NULL;
462}
463
464
465/*
466 * return the container (File, Set or NameBlock) with name obj_name,
467 * in case of error return NULL and leave a description in
468 * obj_result.
469 *
470 */
471const BSyntaxObject * Tol_FindGlobalContainer(const char* Type,
472                                              const char* obj_name,
473                                              Tcl_Obj*    obj_result)
474{
475  BGrammar *gra;
476  BSyntaxObject* var;
477  Tcl_DString uniBuffer;
478
479  if (!strcmp(Type, "Set"))
480    gra = GraSet();
481  else if (!strcmp(Type, "NameBlock"))
482    gra = GraNameBlock();
483  else if (!strcmp(Type, "File"))
484    gra = NULL;
485  else {
486    Tcl_AppendStringsToObj(obj_result,"type '",
487                           Type,
488                           "' is not a container grammar", NULL );
489    return NULL;
490  }
491  Tcl_DStringInit(&uniBuffer);
492  Tcl_UtfToExternalDString(NULL,obj_name,-1,&uniBuffer);
493  if (!gra) {
494    /* should look in Files */
495    BText fname(Tcl_DStringValue(&uniBuffer));
496    if (!(var=(BSyntaxObject*)BSetFromFile::FindCompiled(fname))) {
497      Tcl_AppendStringsToObj(obj_result,"file \"",
498                             obj_name,
499                             "\" is not included", NULL );
500    }
501  } else if (!(var=gra->FINDVARIABLE(Tcl_DStringValue(&uniBuffer)))) {
502      Tcl_AppendStringsToObj(obj_result,"\"",
503                             obj_name,
504                             "\" isn't a ", Type, " variable", NULL );
505  }
506  Tcl_DStringFree(&uniBuffer);
507  return var;
508}
509
510/*
511 * given a tol set, returns its child corresponding to the set of
512 * indexes indexes of size n.  In case of error return NULL and leave
513 * a description in obj_result.
514 *
515 */
516
517const BSyntaxObject * Tol_FindChild(Tcl_Interp    *interp,
518                                    const BSyntaxObject *syn_obj,
519                                    Tcl_Obj       **indexes, int n,
520                                    Tcl_Obj       *obj_result)
521{
522  int tcl_code;
523  Tcl_DString dstr;
524  BSet *container;
525  int idx, card;
526  int i;
527
528  for (i=0; i<n; ++i) {
529    if (!(container = ContainerGetSet(syn_obj))) {
530      BText info(syn_obj->Info());
531      Tcl_DStringInit(&dstr);
532      Tcl_ExternalToUtfDString(NULL,info,-1,&dstr);
533      Tcl_AppendStringsToObj(obj_result,"object \"",
534                             Tcl_DStringValue(&dstr),
535                             "\" is not a container",
536                             NULL);
537      Tcl_DStringFree(&dstr);
538      break;
539    }
540    /* get the current object index */
541    tcl_code = Tcl_GetIntFromObj(interp,indexes[i],&idx);
542    if (tcl_code != TCL_OK) {
543      Tcl_AppendObjToObj( obj_result, Tcl_GetObjResult(interp));
544      break;
545    }
546    card = container->Card();
547    if (idx<1 || idx>card) {
548      Tcl_AppendStringsToObj(obj_result,
549                             "index '",
550                             Tcl_GetString(indexes[i]),
551                             "' out of range",
552                             NULL);
553      break;
554    }
555    /* take the next object in the list */
556    syn_obj = (*container)[idx];
557  }
558  return i == n ? syn_obj : NULL;
559}
560
561/*!
562 *  Tol_ResolveObject --
563 *
564 *     Resolve a SyntaxObject given a toltcl object reference. A
565 *     reference is {TYPE ?container? i1 i2 ... in} or a global
566 *     container's name of type File|Set|NameBlock|Console. When TYPE
567 *     is Console then container is not given. The grammar of the
568 *     object found is matched to the given argument grammar. If the
569 *     return value is NULL an error message is left in interp.
570 */
571
572const BSyntaxObject * Tol_ResolveObject(Tcl_Interp *interp,
573                                        Tcl_Obj    *obj_ref,
574                                        Tcl_Obj    *obj_result)
575{
576  Tcl_Obj ** items;
577  int n;
578  int tcl_code;
579  char * type;
580
581  /* look for subitem given in obj_ref */
582  tcl_code = Tcl_ListObjGetElements(interp, obj_ref, &n, &items);
583  if (tcl_code != TCL_OK) {
584    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
585    return NULL;
586  }
587
588  // this Tcl_Obj is to leave error messages
589  const BSyntaxObject * syn = NULL;
590
591  if (n >= 2) {
592    type = Tcl_GetString(items[0]);
593    if (!strcmp(type,"Console") || !strcmp(type,"File") ||
594        !strcmp(type,"Set") || !strcmp(type,"NameBlock") ) {
595      if (!strcmp(type,"Console")) {
596        // is a reference in the console, items[1] is the first index in
597        // the path, following indexes are indexes withing containers.
598        int i1;
599        if ((tcl_code = Tcl_GetIntFromObj(interp,items[1],&i1)!=TCL_OK)) {
600          Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
601          return NULL;
602        }
603        if (!(syn=Tol_GetConsoleObject(i1))) {
604          Tcl_AppendStringsToObj(obj_result, "index ",
605                                 Tcl_GetString(items[1]),
606                                 " not found in console", NULL);
607          return NULL;
608        }
609      } else {
610      /* should be File, Set or NameBlock, it is a hierarchical container */
611        if (!(syn=Tol_FindGlobalContainer(Tcl_GetString(items[0]),
612                                          Tcl_GetString(items[1]),
613                                          obj_result))) {
614          return NULL;
615        }
616      }
617      assert(syn);
618      if (n>2) {
619        // there are more indexes & syn should be a Container
620        if (!(syn=Tol_FindChild(interp,
621                                syn, items+2, n-2, obj_result))) {
622          return NULL;
623        }
624      }
625    } else {
626      if (n==2) {
627        // look global var in grammar
628        BGrammar * gra;
629        gra = BGrammar::FindByName(type);
630        if (!gra) {
631          Tcl_AppendStringsToObj(obj_result, "\"",
632                                                   type,
633                                                   "\" isn't a grammar", NULL);
634          return NULL;
635        }
636        Tcl_DString dstr;
637        Tcl_DStringInit(&dstr);
638        Tcl_UtfToExternalDString(NULL,Tcl_GetString(items[1]),-1,&dstr);
639        if (!(syn = gra->FINDVARIABLE(Tcl_DStringValue(&dstr))))
640          Tcl_AppendStringsToObj(obj_result, "variable '",
641                                 obj_ref, "' not found in grammar '",
642                                 gra->Name().String(), "'", NULL);
643        Tcl_DStringFree(&dstr);
644        /* found and matched */
645        return syn;
646      }
647    }
648  } else {
649      Tcl_AppendStringsToObj(obj_result,
650                             "incorrect object reference in ResolveObject",
651                             NULL);
652  }
653/*  if (grammar && syn && syn->Grammar()!=grammar) {
654    Tcl_AppendStringsToObj(obj_result, "grammar for object '",
655                           Tcl_GetString(obj_ref),
656                           "' does not match grammar '",
657                           grammar->Name().String(), "'", NULL);
658    syn = NULL;
659  }
660*/
661  return syn;
662}
663
664int Tol_FindSOInSet(BSet * ptrSet, const BSyntaxObject * syn,
665                    ToltclPool & indexes)
666{
667  int j;
668  const BSyntaxObject * so;
669 
670  for (j = 1; j <= ptrSet->Card(); j++) {
671    so = (*ptrSet)[j];
672    BSet *ptrSet;
673    if (so == syn || ((ptrSet=ContainerGetSet(so)) &&
674                      Tol_FindSOInSet(ptrSet,
675                                      syn, indexes))) {
676      /* found!!! */
677      indexes.AppendObject((void*)j);     
678      return 1;
679    }
680  }
681
682  return 0;
683}
684 
685/*
686 *  Puts in obj_result the global reference of the given
687 *  syntaxobject. The syntaxobject could be given as set member or as
688 *  global variable. In case of error leave in obj_result the message.
689 *  Returns TCL_OK if succesfull or TCL_ERROR in case of error.
690 */
691
692int Tol_GetReference(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[],
693                     Tcl_Obj * obj_result)
694{
695  Tcl_Obj ** items;
696  int n;
697  int tcl_code;
698  const BSyntaxObject * source, * syn;
699  BSet * ptrSet;
700  ToltclPool indexes;
701  Tcl_DString dstr;
702  int j;
703  char * graname, * objname;
704
705  assert(!Tcl_IsShared(obj_result));
706  tcl_code = Tcl_ListObjGetElements(interp,objv[0],&n,&items);
707  assert(tcl_code == TCL_OK);
708  if (n<2) {
709    Tcl_AppendStringsToObj(obj_result,
710                           "wrong # args: should be 'tol::info",
711                           " reference {grammar|container objname ?indexes?}'",
712                           NULL);
713    return TCL_ERROR;   
714  }
715  if (n==2 && strcmp(Tcl_GetString(items[0]),"Console")) {
716  // global access
717    BGrammar * gra;
718    graname = Tcl_GetString(items[0]);
719    gra = BGrammar::FindByName(graname);
720    if (!gra) {
721      Tcl_AppendStringsToObj( obj_result, "\"",
722                              graname,
723                              "\" isn't a grammar", NULL);
724      return TCL_ERROR;
725    }
726    objname = Tcl_GetString(items[1]);
727    Tcl_UtfToExternalDString(NULL,objname,-1,&dstr);
728    syn = gra->FINDVARIABLE(Tcl_DStringValue(&dstr));
729    Tcl_DStringFree(&dstr);
730    if (!syn) {
731      Tcl_AppendStringsToObj(obj_result, "\"",
732                             Tcl_GetString(items[1]),
733                             "\" isn't a variable in grammar ",
734                             graname, NULL);
735      return TCL_ERROR;
736    }
737    source = syn->Source();
738    if (!source) {
739      /* is a global variable not defined inside a file */
740      items = (Tcl_Obj**)Tcl_Alloc(sizeof(Tcl_Obj*) * 2);
741      Tcl_ExternalToUtfDString(NULL, graname, -1, &dstr);
742      items[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
743      Tcl_DStringFree(&dstr);
744      Tcl_ExternalToUtfDString(NULL, objname, -1, &dstr);
745      items[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
746      Tcl_DStringFree(&dstr);
747      Tcl_SetListObj(obj_result, 2, items);
748      Tcl_Free((char*)items);
749      return TCL_OK;
750    }
751  } else {
752    // member access
753    if (!(syn=Tol_ResolveObject(interp,objv[0],obj_result))) {
754      return TCL_ERROR;
755    }
756    /* here we have a valid reference */
757    tcl_code = Tcl_ListObjGetElements(interp,objv[0],&n,&items);
758    assert(tcl_code == TCL_OK);
759    if (!strcmp(Tcl_GetString(items[0]),"File") ||
760        !strcmp(Tcl_GetString(items[0]),"Console")) {
761      /* here we have in objv[0] the answer */
762      Tcl_SetListObj(obj_result, n, items);
763      return TCL_OK;     
764    }
765    source = syn->Source();
766    if (!source) {
767      /* here we have in objv[0] the answer too */
768      Tcl_SetListObj(obj_result, n, items);
769      return TCL_OK;
770    }
771  }
772  /* at this point variable has to be defined inside a file */
773  assert(source);
774  ptrSet = &(((BUserSet*)source)->Contens());
775  if (Tol_FindSOInSet(ptrSet, syn, indexes)) {
776    items = (Tcl_Obj**)Tcl_Alloc(sizeof(Tcl_Obj*) * (indexes.GetSize()+2));
777    Tcl_ExternalToUtfDString(NULL, "File", -1, &dstr);
778    items[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
779    Tcl_DStringFree(&dstr);
780    Tcl_ExternalToUtfDString(NULL, source->Name(), -1, &dstr);
781    items[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
782    Tcl_DStringFree(&dstr);
783    int last = indexes.GetLast();
784    for(j = last; j >= 0; j--)
785      items[last+2-j] = Tcl_NewIntObj(long(*indexes._GetObject(j)));
786    Tcl_SetListObj(obj_result, indexes.GetSize()+2, items);
787    Tcl_Free((char*)items);
788    return TCL_OK;
789  } else {
790    /* this should not happend because syn should be inside syn->source */
791    Tcl_AppendStringsToObj(obj_result,
792                             "internal error: syn not found in syn->Source()",
793                             NULL);
794    return TCL_ERROR;
795  }
796}
797
798inline void SAVE_SET_STRING( Tcl_Obj **obj, Tcl_DString* dstr )
799{
800  if (Tcl_IsShared( *obj ) ) {
801    Tcl_DecrRefCount( *obj );
802    *obj = Tcl_NewStringObj( Tcl_DStringValue( dstr ), -1 );
803    Tcl_IncrRefCount( *obj );
804  } else
805    Tcl_SetStringObj( *obj, Tcl_DStringValue( dstr ),-1 );
806}
807
808/*! Implement a foreach proc similar to the one provided in Tcl except
809 *  that instead of iterating over the list's items it iterates over
810 *  the Set's items. The set could be tolset if the indexes is empty
811 *  or tolset[i1][i2]...[ik] for the given indexes {i1,i2,...,ik}
812 */
813int Tol_ForEach (Tcl_Interp * interp,
814                 int objc,
815                 Tcl_Obj *CONST objv[],
816                 Tcl_Obj * obj_result)
817{
818  const BSyntaxObject* container;
819  Tcl_DString dstr;
820  Tcl_Obj * ArgIndexes;
821  int tcl_code = TCL_OK;
822  int i, card ;
823  int n, index_length;
824  Tcl_Obj ** items;
825
826  int length = 0;
827
828  if ( Tcl_GetCharLength( objv[ 0 ] ) == 0 ) {
829    Tcl_AppendStringsToObj( obj_result, "empty loop variable name", NULL );
830    return TCL_ERROR;
831  }
832 
833  if ( Tcl_ListObjLength( interp, objv[ 1 ], &length) != TCL_OK ) {
834    Tcl_AppendObjToObj( obj_result, Tcl_GetObjResult( interp ) );
835    return TCL_ERROR;
836  }
837  if ( length < 2 ) {
838    Tcl_AppendStringsToObj( obj_result,
839                            "invalid object reference '",
840                            Tcl_GetString(objv[0]),
841                            "must be {TYPE ?name? i1 i2 ... ik}",
842                            NULL );
843    return TCL_ERROR;
844  }
845
846  const int OBJ_GRAMMAR    = 0;
847  const int OBJ_GRAMMARV   = OBJ_GRAMMAR + 1;
848  const int OBJ_NAME       = OBJ_GRAMMARV + 1;
849  const int OBJ_NAMEV      = OBJ_NAME + 1;
850  const int OBJ_CONTENT    = OBJ_NAMEV + 1;
851  const int OBJ_CONTENTV   = OBJ_CONTENT + 1;
852  const int OBJ_PATH       = OBJ_CONTENTV + 1;
853  const int OBJ_PATHV      = OBJ_PATH + 1;
854  const int OBJ_DESC       = OBJ_PATHV + 1;
855  const int OBJ_DESCV      = OBJ_DESC + 1;
856  const int OBJ_INDEXES    =  OBJ_DESCV + 1;
857  const int OBJ_INDEXESV   =  OBJ_INDEXES + 1;
858  const int OBJ_ISFILE     = OBJ_INDEXESV + 1;
859  const int OBJ_ISFILEV    = OBJ_ISFILE + 1;
860  const int OBJ_HASSUBSET  = OBJ_ISFILEV + 1;
861  const int OBJ_HASSUBSETV = OBJ_HASSUBSET + 1;
862  const int OBJ_SUBTYPE    = OBJ_HASSUBSETV + 1;
863  const int OBJ_SUBTYPEV   = OBJ_SUBTYPE + 1;
864  const int OBJ_STRUCT     = OBJ_SUBTYPEV + 1;
865  const int OBJ_STRUCTV    = OBJ_STRUCT + 1;
866  const int NUM_OBJS      = OBJ_STRUCTV + 1;
867
868  int datac;
869  Tcl_Obj *datav[ NUM_OBJS ];
870
871 
872  if ( !( container = Tol_ResolveObject( interp, objv[ 1 ], obj_result ) ) ) {
873    return TCL_ERROR;
874  }
875  BSet *set = ContainerGetSet( container );
876  if (!set) {
877    Tcl_AppendStringsToObj(obj_result,
878                           "object '",
879                           Tcl_GetString(objv[0]),
880                           "' is not a valid container ",
881                           NULL);
882      return TCL_ERROR;
883  }
884 
885  card = set->Card();
886 
887  // is ok to ask for a list
888  Tcl_ListObjGetElements( interp, objv[ 0 ], &n, &items );
889
890  // initialize the list of indexes (the common part) for every item
891  // in the Set
892  if (strcmp(Tcl_GetString( items[ 0 ] ),"Console")) {
893    if (n>2)
894      ArgIndexes = Tcl_NewListObj( n - 2, items + 2 );
895    else
896      ArgIndexes = Tcl_NewListObj( 0, NULL );
897  } else {
898    if ( n > 1 )
899      ArgIndexes = Tcl_NewListObj( n - 1, items + 1 );
900    else
901      ArgIndexes = Tcl_NewListObj( 0, NULL );
902  }
903
904  datav[ OBJ_GRAMMAR ]  = Tcl_NewStringObj( "grammar", -1 );
905  datav[ OBJ_GRAMMARV ] = Tcl_NewObj( );
906  datav[ OBJ_NAME ]     = Tcl_NewStringObj( "name", -1 );
907  datav[ OBJ_NAMEV ]    = Tcl_NewObj( );
908  datav[ OBJ_CONTENT ]  = Tcl_NewStringObj( "content", -1 );
909  datav[ OBJ_CONTENTV ] = Tcl_NewObj( );
910  datav[ OBJ_PATH ]     = Tcl_NewStringObj( "path", -1 );
911  datav[ OBJ_PATHV ]    = Tcl_NewObj( );
912  datav[ OBJ_DESC ]     = Tcl_NewStringObj( "description", -1 );
913  datav[ OBJ_DESCV ]    = Tcl_NewObj( );
914  Tcl_Obj * last_index  = Tcl_NewIntObj( 0 );
915  Tcl_ListObjAppendElement( NULL, ArgIndexes, last_index );
916  datav[ OBJ_INDEXES ]  = Tcl_NewStringObj( "indexes", -1 );
917  datav[ OBJ_INDEXESV ] = ArgIndexes;
918  Tcl_ListObjLength( NULL, datav[ OBJ_INDEXES ], &index_length );
919  datav[ OBJ_ISFILE ]     = Tcl_NewStringObj( "isfile", -1 );
920  datav[ OBJ_ISFILEV ]    = Tcl_NewObj( );
921  datav[ OBJ_HASSUBSET ]  = Tcl_NewStringObj( "hassubset", -1 );
922  datav[ OBJ_HASSUBSETV ] = Tcl_NewObj( );
923  datav[ OBJ_SUBTYPE ]    = Tcl_NewStringObj( "subtype", -1 );
924  datav[ OBJ_SUBTYPEV ]   = Tcl_NewObj( );
925  datav[ OBJ_STRUCT ]     = Tcl_NewStringObj( "struct", -1 );
926  datav[ OBJ_STRUCTV ]    = Tcl_NewObj( );
927
928  // the just created objects have refcount = 0
929  for ( i = 0; i < NUM_OBJS; ++i ) {
930    Tcl_IncrRefCount( datav[ i ] );
931  }
932 
933  BSyntaxObject *syn_i;
934  BSet          *set_i; /* just in case syn_i be a container */
935
936  /* now iter over its children */
937 
938  Tcl_DStringInit( &dstr );
939  BText btxt;
940 
941  for ( i = 1; i <= card; ++i ) {
942    syn_i = ( *set )[ i ];
943   
944    /* read the grammar */
945    btxt = syn_i->Grammar( )->Name( );
946    Tcl_ExternalToUtfDString( NULL, btxt, -1, &dstr );
947    SAVE_SET_STRING( datav + OBJ_GRAMMARV, &dstr );
948    Tcl_DStringFree(&dstr);
949   
950    /* read the name */
951    //btxt = syn_i->Identify();
952    GetName( syn_i, btxt );
953    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
954    SAVE_SET_STRING( datav + OBJ_NAMEV, &dstr );
955    Tcl_DStringFree(&dstr);
956   
957    /* read the content */
958    btxt = syn_i->Info();
959    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
960    SAVE_SET_STRING( datav + OBJ_CONTENTV, &dstr );
961    Tcl_DStringFree(&dstr);
962   
963    /* read the path */
964    btxt = syn_i->SourcePath();
965    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
966    SAVE_SET_STRING( datav + OBJ_PATHV, &dstr );
967    Tcl_DStringFree(&dstr);
968   
969    /* read the description */   
970    btxt = syn_i->Description();
971    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
972    SAVE_SET_STRING( datav + OBJ_PATHV, &dstr );
973    Tcl_DStringFree(&dstr);
974
975    // Este if es para incluir en los items que son Set informacion
976    // que solo ellos llevan como: Subtype, IsFile, etc ...
977    if ( ( set_i = ContainerGetSet( syn_i ) ) ) {
978      /* update last index */
979      if ( Tcl_IsShared( last_index ) ) {
980        last_index = Tcl_NewIntObj( i );
981        Tcl_ListObjReplace( NULL, datav[ OBJ_INDEXESV ], index_length-1,
982                           1, 1, &last_index );
983      }
984      /* set the last value index */
985      Tcl_SetIntObj( last_index, i );
986      /* to refresh the string */
987      Tcl_InvalidateStringRep( datav[ OBJ_INDEXESV ] );
988      if ( Tcl_IsShared( datav[ OBJ_ISFILEV ] ) ) {
989        Tcl_DecrRefCount( datav[ OBJ_ISFILEV ] );
990#ifdef ISFILE_IMPLEMENTED
991        datav[ OBJ_ISFILEV ] = Tcl_NewIntObj( syn_i->IsFile( ) );
992#else
993        datav[OBJ_ISFILEV] = Tcl_NewIntObj( 0 );
994#endif
995        Tcl_IncrRefCount( datav[ OBJ_ISFILEV ] );
996      } else
997#ifdef ISFILE_IMPLEMENTED
998        Tcl_SetIntObj( datav[ OBJ_ISFILEV ], syn_i->IsFile( ) );
999#else
1000      Tcl_SetIntObj( datav[ OBJ_ISFILEV ], 0 );
1001#endif
1002      /* verify if has subset */
1003      int tmpCard = set_i->Card( );
1004      int j;
1005      for ( j = 1; j <= tmpCard; ++j )
1006        if ( ContainerGetSet( ( *set_i )[ j ] ) )
1007          break;
1008      if ( Tcl_IsShared( datav[ OBJ_HASSUBSETV ] ) ) {
1009        Tcl_DecrRefCount( datav[ OBJ_HASSUBSETV ] );
1010        datav[ OBJ_HASSUBSETV ] = Tcl_NewIntObj( j <= tmpCard );
1011        Tcl_IncrRefCount( datav[ OBJ_HASSUBSETV ] );
1012      } else
1013        Tcl_SetIntObj( datav[ OBJ_HASSUBSETV ], j <= tmpCard );
1014       
1015      /* subtype info */
1016      if ( Tcl_IsShared( datav[ OBJ_SUBTYPEV ] ) ) {
1017        Tcl_DecrRefCount( datav[ OBJ_SUBTYPEV ] );
1018        datav[ OBJ_SUBTYPEV ] = Tcl_NewIntObj( set_i->SubType( ) );
1019        Tcl_IncrRefCount( datav[ OBJ_SUBTYPEV ] );
1020      } else
1021        Tcl_SetIntObj( datav[ OBJ_SUBTYPEV ],set_i->SubType( ) );
1022       
1023      /* STRUCT INFO */
1024      // asume que dstr esta a longitud 0
1025      if ( set_i->Struct( ) ) {
1026        btxt = set_i->Struct( )->Name( );
1027        Tcl_ExternalToUtfDString( NULL, btxt, -1, &dstr );
1028      }
1029      SAVE_SET_STRING( datav + OBJ_PATHV, &dstr );
1030      Tcl_DStringFree( &dstr );
1031      datac = NUM_OBJS;
1032    } else
1033      datac = OBJ_INDEXESV + 1;
1034    // set the loop variable
1035    Tcl_Obj *varValuePtr = Tcl_ObjSetVar2( interp, objv[ 0 ], NULL,
1036                                           Tcl_NewListObj( datac, datav ),
1037                                           TCL_LEAVE_ERR_MSG );
1038    if (varValuePtr == NULL) {
1039      Tcl_AppendObjToObj( obj_result, Tcl_GetObjResult( interp ) );
1040      Tcl_AppendStringsToObj( obj_result,
1041                              "\n    (setting foreach loop variable \"",
1042                              Tcl_GetString( objv[ 0 ] ), "\")",
1043                              NULL );
1044      tcl_code = TCL_ERROR;
1045      break;
1046    }
1047    tcl_code = Tcl_EvalObjEx( interp, objv[ 2 ], 0 );
1048    if ( tcl_code != TCL_OK) {
1049      if ( tcl_code == TCL_CONTINUE) {
1050        tcl_code = TCL_OK;
1051      } else if ( tcl_code == TCL_BREAK) {
1052        tcl_code = TCL_OK;
1053        break;
1054      } else if ( tcl_code == TCL_ERROR) {
1055        Tcl_AppendObjToObj( obj_result, Tcl_GetObjResult( interp ) );
1056        break;
1057      } else {
1058        break;
1059      }
1060    }
1061  }
1062 
1063  /* liberar los objetos tcl */
1064  for ( i = 0; i < NUM_OBJS; ++i ) {
1065    Tcl_DecrRefCount( datav[ i ] );
1066  }
1067  return tcl_code;
1068}
1069
1070
1071/*
1072 * Iterate over a first level's children of a given set.  The set
1073 * could be a container Set, File or NameBlock if the index list is
1074 * empty or container[i1][i2]...[ik] for the given indexes
1075 * {i1,i2,...,ik}
1076 *
1077 * Used by tol::forallchil
1078 *
1079 */
1080
1081int Tol_IterChildren(Tcl_Interp * interp,
1082                     int objc,
1083                     Tcl_Obj *CONST objv[],
1084                     Tcl_Obj * obj_result)
1085{
1086  const BSyntaxObject* container;
1087  Tcl_DString dstr;
1088  Tcl_Obj * ArgIndexes;
1089  int tcl_code;
1090  int i, card ;
1091  int n, index_length;
1092  Tcl_Obj ** items;
1093  Tcl_Obj ** script_header;
1094
1095  int length = 0;
1096 
1097  if (Tcl_ListObjLength(interp,objv[0],&length)!=TCL_OK) {
1098    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1099    return TCL_ERROR;
1100  }
1101  if ( length < 2 ) {
1102    Tcl_AppendStringsToObj( obj_result,
1103                            "invalid object reference '",
1104                            Tcl_GetString(objv[0]),
1105                            "must be {TYPE ?name? i1 i2 ... ik}",
1106                            NULL );
1107    return TCL_ERROR;
1108  }
1109
1110  /* expand header of script */
1111  tcl_code = Tcl_ListObjGetElements( interp, objv[ 1 ],
1112                                     &length, &script_header );
1113  if ( tcl_code != TCL_OK ) {
1114    Tcl_AppendObjToObj( obj_result, Tcl_GetObjResult( interp ) );
1115    return TCL_ERROR;
1116  }
1117
1118  if ( !length ) {
1119    Tcl_AppendStringsToObj( obj_result,
1120                            "invalid script argument of length 0",
1121                            NULL );
1122    return TCL_ERROR;
1123  }
1124  int ARG_SCRIPT    = length - 1;
1125  int ARG_GRAMMAR   = ARG_SCRIPT + 1;
1126  int ARG_NAME      = ARG_GRAMMAR + 1;
1127  int ARG_CONTENT   = ARG_NAME + 1;
1128  int ARG_PATH      = ARG_CONTENT + 1;
1129  int ARG_DESC      = ARG_PATH + 1;
1130  int ARG_INDEXES   =  ARG_DESC + 1;
1131  int ARG_ISFILE    = ARG_INDEXES + 1;
1132  int ARG_HASSUBSET = ARG_ISFILE + 1;
1133  int ARG_SUBTYPE   = ARG_HASSUBSET + 1;
1134  int ARG_STRUCT    = ARG_SUBTYPE + 1;
1135  int NUM_ARGS      = ARG_STRUCT + 1;
1136 
1137  if ( !( container=Tol_ResolveObject( interp, objv[0], obj_result ) ) ) {
1138    return TCL_ERROR;
1139  }
1140  BSet *set = ContainerGetSet( container );
1141  if (!set) {
1142    Tcl_AppendStringsToObj(obj_result,
1143                           "object '",
1144                           Tcl_GetString(objv[0]),
1145                           "' is not a valid container ",
1146                           NULL);
1147      return TCL_ERROR;
1148  }
1149 
1150  card = set->Card();
1151 
1152  int datac;
1153  Tcl_Obj ** datav = new ( Tcl_Obj* [ NUM_ARGS ] );
1154
1155  // is ok to ask for a list
1156  Tcl_ListObjGetElements( interp, objv[ 0 ], &n, &items );
1157 
1158  if (strcmp(Tcl_GetString(items[0]),"Console")) {
1159    if (n>2)
1160      ArgIndexes = Tcl_NewListObj(n-2,items+2);
1161    else
1162      ArgIndexes = Tcl_NewListObj(0,NULL);
1163  } else {
1164    if (n>1)
1165      ArgIndexes = Tcl_NewListObj(n-1,items+1);
1166    else
1167      ArgIndexes = Tcl_NewListObj(0,NULL);
1168  }
1169
1170  for( i = 0; i < ARG_GRAMMAR; ++i ) {
1171    datav[ i ] = script_header[ i ];
1172  }
1173 
1174  datav[ARG_GRAMMAR] = Tcl_NewObj();
1175  datav[ARG_NAME]    = Tcl_NewObj();
1176  datav[ARG_CONTENT] = Tcl_NewObj();
1177  datav[ARG_PATH]    = Tcl_NewObj();
1178  datav[ARG_DESC]    = Tcl_NewObj();
1179  Tcl_Obj * last_index = Tcl_NewIntObj(0);
1180  Tcl_ListObjAppendElement(NULL,ArgIndexes,last_index);
1181  datav[ARG_INDEXES] = ArgIndexes;
1182  Tcl_ListObjLength(NULL,datav[ARG_INDEXES],&index_length);
1183  datav[ARG_ISFILE] = Tcl_NewObj();
1184  datav[ARG_HASSUBSET] = Tcl_NewObj();
1185  datav[ARG_SUBTYPE] = Tcl_NewObj();
1186  datav[ARG_STRUCT] = Tcl_NewObj();
1187  for ( i = 0; i < NUM_ARGS; ++i ) {
1188    Tcl_IncrRefCount( datav[i] );
1189  }
1190 
1191  BSyntaxObject *syn_i;
1192  BSet          *set_i; /* just in case syn_i be a container */
1193  /* now iter over its children */
1194 
1195  Tcl_DStringInit(&dstr);
1196  BText btxt;
1197 
1198  for ( i = 1; i <= card; ++i ) {
1199    syn_i = (*set)[i];
1200   
1201    /* read the grammar */
1202    btxt = syn_i->Grammar()->Name();
1203    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
1204    if (Tcl_IsShared(datav[ARG_GRAMMAR])) {
1205      Tcl_DecrRefCount(datav[ARG_GRAMMAR]);
1206      datav[ARG_GRAMMAR] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
1207      Tcl_IncrRefCount(datav[ARG_GRAMMAR]);
1208    } else
1209      Tcl_SetStringObj(datav[ARG_GRAMMAR], Tcl_DStringValue(&dstr),-1);
1210    Tcl_DStringFree(&dstr);
1211   
1212    /* read the name */
1213    //btxt = syn_i->Identify();
1214    GetName( syn_i, btxt );
1215    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
1216    if (Tcl_IsShared(datav[ARG_NAME])) {
1217      Tcl_DecrRefCount(datav[ARG_NAME]);
1218      datav[ARG_NAME] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
1219      Tcl_IncrRefCount(datav[ARG_NAME]);
1220    } else
1221      Tcl_SetStringObj(datav[ARG_NAME], Tcl_DStringValue(&dstr),-1);
1222    Tcl_DStringFree(&dstr);
1223   
1224    /* read the content */
1225    btxt = syn_i->Info();
1226    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
1227    if (Tcl_IsShared(datav[ARG_CONTENT])) {
1228      Tcl_DecrRefCount(datav[ARG_CONTENT]);
1229      datav[ARG_CONTENT] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
1230      Tcl_IncrRefCount(datav[ARG_CONTENT]);
1231    } else
1232      Tcl_SetStringObj(datav[ARG_CONTENT],Tcl_DStringValue(&dstr),-1);
1233    Tcl_DStringFree(&dstr);
1234   
1235    /* read the path */
1236    btxt = syn_i->SourcePath();
1237    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
1238    if (Tcl_IsShared(datav[ARG_PATH])) {
1239      Tcl_DecrRefCount(datav[ARG_PATH]);
1240      datav[ARG_PATH] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
1241      Tcl_IncrRefCount(datav[ARG_PATH]);
1242    } else
1243      Tcl_SetStringObj(datav[ARG_PATH],Tcl_DStringValue(&dstr),-1);
1244    Tcl_DStringFree(&dstr);
1245   
1246    /* read the description */   
1247    btxt = syn_i->Description();
1248    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
1249    if (Tcl_IsShared(datav[ARG_DESC])) {
1250      Tcl_DecrRefCount(datav[ARG_DESC]);
1251      datav[ARG_DESC] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
1252      Tcl_IncrRefCount(datav[ARG_DESC]);
1253    } else
1254      Tcl_SetStringObj(datav[ARG_DESC],Tcl_DStringValue(&dstr),-1);
1255    Tcl_DStringFree(&dstr);
1256   
1257    if ((set_i=ContainerGetSet(syn_i))) {
1258      /* update last index */
1259      if (Tcl_IsShared(last_index)) {
1260        last_index = Tcl_NewIntObj(i);
1261        Tcl_ListObjReplace(NULL, datav[ARG_INDEXES], index_length-1,
1262                           1, 1, &last_index);
1263      }
1264      /* set the last value index */
1265      Tcl_SetIntObj( last_index, i );
1266      /* to refresh the string */
1267      Tcl_InvalidateStringRep( datav[ ARG_INDEXES ] );
1268      if ( Tcl_IsShared( datav[ ARG_ISFILE ] ) ) {
1269        Tcl_DecrRefCount( datav[ ARG_ISFILE ] );
1270#ifdef ISFILE_IMPLEMENTED
1271        datav[ ARG_ISFILE ] = Tcl_NewIntObj( syn_i->IsFile( ) );
1272#else
1273        datav[ARG_ISFILE] = Tcl_NewIntObj( 0 );
1274#endif
1275        Tcl_IncrRefCount( datav[ ARG_ISFILE ] );
1276      } else
1277#ifdef ISFILE_IMPLEMENTED
1278        Tcl_SetIntObj( datav[ ARG_ISFILE ], syn_i->IsFile( ) );
1279#else
1280      Tcl_SetIntObj( datav[ ARG_ISFILE ], 0 );
1281#endif
1282      /* verify if has subset */
1283      int tmpCard = set_i->Card( );
1284      int j;
1285      for (j=1; j<=tmpCard; ++j )
1286        if ( ContainerGetSet( ( *set_i )[ j ] ) )
1287          break;
1288      if ( Tcl_IsShared( datav[ ARG_HASSUBSET ] ) ) {
1289        Tcl_DecrRefCount( datav[ ARG_HASSUBSET ] );
1290        datav[ ARG_HASSUBSET ] = Tcl_NewIntObj( j <= tmpCard );
1291        Tcl_IncrRefCount( datav[ ARG_HASSUBSET ] );
1292      } else
1293        Tcl_SetIntObj( datav[ ARG_HASSUBSET ], j <= tmpCard );
1294       
1295      /* subtype info */
1296      if ( Tcl_IsShared( datav[ ARG_SUBTYPE ] ) ) {
1297        Tcl_DecrRefCount( datav[ ARG_SUBTYPE ] );
1298        datav[ ARG_SUBTYPE ] = Tcl_NewIntObj( set_i->SubType( ) );
1299        Tcl_IncrRefCount( datav[ ARG_SUBTYPE ] );
1300      } else
1301        Tcl_SetIntObj( datav[ ARG_SUBTYPE ],set_i->SubType( ) );
1302       
1303      /* STRUCT INFO */
1304      if ( set_i->Struct( ) ) {
1305        btxt = set_i->Struct( )->Name( );
1306        Tcl_ExternalToUtfDString( NULL, btxt, -1, &dstr );
1307      }
1308      if ( Tcl_IsShared( datav[ ARG_STRUCT ] ) ) {
1309        Tcl_DecrRefCount( datav[ ARG_STRUCT ] );
1310        datav[ ARG_STRUCT ] = Tcl_NewStringObj( Tcl_DStringValue( &dstr ),-1 );
1311        Tcl_IncrRefCount( datav[ ARG_STRUCT ] );
1312      } else
1313        Tcl_SetStringObj( datav[ ARG_STRUCT ], Tcl_DStringValue( &dstr ),-1 );
1314      Tcl_DStringFree( &dstr );
1315      datac = NUM_ARGS;
1316    } else
1317      datac = ARG_INDEXES;
1318    tcl_code = Tcl_EvalObjv( interp, datac, datav, TCL_EVAL_GLOBAL );
1319    if ( tcl_code == TCL_BREAK ) {
1320      tcl_code = TCL_OK;
1321      break;
1322    }
1323    if ( tcl_code == TCL_ERROR ) {
1324      Tcl_AppendObjToObj( obj_result, Tcl_GetObjResult( interp ) );
1325      break;
1326    }
1327  }
1328 
1329  /* liberar los objetos tcl */
1330  /* OJO aqui tenia ARG_GRAMMAR en lugar de 0 */
1331  for ( i = 0; i < NUM_ARGS; ++i ) {
1332    Tcl_DecrRefCount( datav[ i ] );
1333  }
1334  delete []datav;
1335  return tcl_code;
1336}
1337
1338/*
1339 * Fill in obj_result the content of the matrix variable.
1340 *
1341 */
1342
1343int Tol_GetMatrixContent(Tcl_Interp * interp,
1344                         Tcl_Obj * obj_name,
1345                         Tcl_Obj * obj_result)
1346{
1347  //BGrammar * gra = NULL;
1348  const BSyntaxObject *tol_obj = NULL;
1349   
1350  if (!(tol_obj=Tol_ResolveObject(interp, obj_name, obj_result))) {
1351    return TCL_ERROR;
1352  }
1353
1354  BMatrix<double> vmat;
1355  BMatrix<double> &theMat = vmat;
1356
1357  if (tol_obj->Grammar()==GraVMatrix()) {
1358    BVMat &V = VMat((BSyntaxObject *)tol_obj);
1359    V.GetDMat(vmat);
1360  } else if (tol_obj->Grammar()==GraMatrix()) {
1361    theMat = ((DMat&)Mat((BSyntaxObject *)tol_obj));
1362  } else { 
1363    Tcl_AppendStringsToObj( obj_result, Tcl_GetString(obj_name),
1364                            " is not a valid Matrix|VMatrix object", NULL );   
1365    return TCL_ERROR;
1366  }
1367   
1368#define IT_NAME 0
1369#define IT_ROWS 1
1370#define IT_COLS 2
1371#define IT_DATA 3
1372#define IT_SIZE 4
1373     
1374  Tcl_Obj * items[4];
1375  Tcl_Obj ** subitems;
1376  int r, Rows, c, Cols;
1377  BDat & dat = BDat::Unknown();
1378 
1379  //BMatrix<BDat> & mat = (BMatrix<BDat>&)(((BUserMat*)tol_obj)->Contens());
1380 
1381  //items[IT_NAME] = Tcl_NewStringObj(tol_obj->Identify(),-1);
1382  BText tmp;
1383  GetName( tol_obj, tmp );
1384  items[IT_NAME] = Tcl_NewStringObj(tmp.Buffer(),-1);
1385  Rows = theMat.Rows();
1386  Cols = theMat.Columns();
1387  items[IT_ROWS] = Tcl_NewIntObj(Rows);
1388  items[IT_COLS] = Tcl_NewIntObj(Cols);
1389  subitems = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*Rows*Cols );
1390  for ( r = 0; r < Rows; ++r )
1391    for ( c = 0; c < Cols; ++c ) {
1392      dat = theMat(r,c);
1393      if (dat.IsKnown())
1394        subitems[r*Cols+c] = Tcl_NewDoubleObj(dat.Value());
1395      else
1396        subitems[r*Cols+c] = Tcl_NewStringObj("?",-1);
1397    }
1398  items[IT_DATA] = Tcl_NewListObj( Rows*Cols, subitems );
1399  Tcl_SetListObj( obj_result,IT_SIZE, items );
1400  Tcl_Free( (char*)subitems );
1401  return TCL_OK;
1402}
1403
1404/*
1405 * Fill in obj_result the content of the serie variable.
1406 *
1407 */
1408
1409int Tol_GetSerieContent(Tcl_Interp * interp,
1410                        int objc,
1411                        Tcl_Obj *CONST objv[],
1412                        Tcl_Obj * obj_result)
1413{
1414  const BSyntaxObject* var = Tol_ResolveObject(interp,
1415                                               objv[0],
1416                                               obj_result/*,
1417                                               GraSerie()*/);
1418  if (!var) {
1419    return TCL_ERROR;
1420  }
1421
1422  // parse dates arguments
1423 
1424  BDate I0, I1;
1425  int tcl_code;
1426
1427  BUserTimeSerie * serie = (BUserTimeSerie*)var;
1428  serie->ReadData();
1429
1430  if (objc == 1) {
1431    I0 = serie->FirstDate();
1432    I1 = serie->LastDate();
1433  } else {
1434    tcl_code = Tol_ParseDate(interp,Tcl_GetString(objv[1]),I0);
1435    if (tcl_code != TCL_OK) {
1436      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1437      return TCL_ERROR;
1438    }
1439    if (objc == 3) {
1440      tcl_code = Tol_ParseDate(interp,Tcl_GetString(objv[2]),I1);
1441      if (tcl_code != TCL_OK) {
1442        Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1443        return TCL_ERROR;
1444      }
1445    }
1446  }
1447 
1448  if ( !I0.HasValue() )
1449    I0 = BDate::DefaultFirst();
1450  if ( !I1.HasValue() )
1451    I1 = BDate::DefaultLast();
1452
1453  BUserTimeSet * tms;
1454  Tcl_Obj ** obj_array;
1455  int length;
1456
1457  char buffer[1024];
1458
1459  tms = serie->Dating();
1460
1461  if ( !tms ) {
1462    Tcl_AppendStringsToObj(obj_result,"Serie \"",
1463                           Tcl_GetString(objv[0]),
1464                           "\" does not have dating", NULL);
1465    return TCL_ERROR;
1466  }
1467
1468  // ajustamos el intervalo de fechas al fechado
1469
1470  I0 = tms->FirstNoLess(I0);
1471  I1 = tms->FirstNoGreat(I1);
1472  length = tms->Difference(I0,I1)+1;
1473  if ( length <= 0 ) {
1474    Tcl_SetStringObj(obj_result,
1475                     "last date must be greater or equal than first",-1);
1476    return TCL_ERROR;
1477  }
1478
1479  BDat  value;
1480  BText tmp;
1481  Tcl_Obj * subitems[2];
1482
1483  // ++ because we identify the TimeSet as the first element
1484
1485  ++length;
1486  obj_array = (Tcl_Obj**)ckalloc(length*sizeof(Tcl_Obj*));
1487
1488  //tmp = tms->Identify();
1489  GetName(tms, tmp);
1490  obj_array[0] = Tcl_NewStringObj(tmp,-1);
1491  for ( int i = 1; i < length; i++ ) {
1492    tmp = I0.GetText();
1493    subitems[0] = Tcl_NewStringObj(tmp,-1);
1494#if defined(_TOL_FROZEN_)
1495    value = (*serie)[I0];
1496#else
1497    value = (*serie)(I0);
1498#endif
1499    if ( value.IsKnown() )
1500      subitems[1] = Tcl_NewDoubleObj(value.Value());
1501    else
1502      subitems[1] = Tcl_NewStringObj("?",-1);
1503    obj_array[i] = Tcl_NewListObj(2,subitems);
1504    I0 += tms;
1505
1506    sprintf(buffer,"%d",i);
1507    Tcl_VarEval(interp, "puts ", buffer, NULL);
1508  }
1509  Tcl_SetListObj(obj_result,length,obj_array);
1510  Tcl_Free( (char*)obj_array );
1511  return TCL_OK;
1512}
1513
1514int Tol_ParseDate(Tcl_Interp * interp, char * what, BDate & date)
1515{
1516  int    year, month, day, hour, min;
1517  double sec;
1518 
1519  int tcl_code;
1520  Tcl_Obj * tcl_result;
1521  int objc;
1522  Tcl_Obj ** objv;
1523
1524  month = day = 1;
1525  hour  = min = 0;
1526  sec   = 0.0;
1527  char re_pat[] = "{^(?:y([0-9]+)(?:m([0-9]+))?(?:d([0-9]+))?)$}";
1528
1529  tcl_code = Tcl_VarEval(interp, "regexp -inline ", re_pat, " ",what, NULL);
1530  if ( tcl_code != TCL_OK )
1531    return TCL_ERROR;
1532  tcl_result = Tcl_DuplicateObj(Tcl_GetObjResult(interp));
1533  /* this should be a valid list, unless Tcl be corrupt */
1534  Tcl_ListObjGetElements(interp,tcl_result,&objc,&objv);
1535  if ( objc == 0 ) {
1536    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1537                           "invalid date: \"",what,"\"",NULL);
1538    Tcl_DecrRefCount(tcl_result);
1539    return TCL_ERROR;
1540  }
1541
1542  /* and objc must be 4 */
1543
1544  Tcl_GetIntFromObj(interp,objv[1],&year);
1545  Tcl_GetIntFromObj(interp,objv[2],&month);
1546  Tcl_GetIntFromObj(interp,objv[3],&day);
1547
1548  /* now is save to release tcl_result */
1549
1550  Tcl_DecrRefCount(tcl_result);
1551
1552  date.PutDate(year,month,day);
1553  if ( !date.HasValue() ) {
1554    Tcl_ResetResult(interp);
1555    char buffer[1024];
1556    sprintf(buffer,"y%dm%dd%d",year,month,day);
1557    tcl_result = Tcl_GetObjResult(interp);
1558    Tcl_AppendStringsToObj(tcl_result,
1559                           what," = ",buffer," is valid but unknown",NULL);
1560    return TCL_ERROR;
1561  }
1562  return TCL_OK;
1563}
1564
1565/*
1566 * Set the language to be used  by TOL. Fill in obj_result the previous
1567 * language.
1568 *
1569 */
1570
1571int Tol_SetLanguage(Tcl_Interp * interp, Tcl_Obj * lang, Tcl_Obj * obj_result)
1572{
1573  BBool curLang = BText::Language();
1574  BIdiomEnum nextLang;
1575 
1576  char * strLang = Tcl_GetString( lang );
1577  if ( !strcasecmp( strLang, "es" ) )
1578    nextLang = BSPANISH;
1579  else {
1580    /* anything else will be assumed as english */
1581    nextLang = BENGLISH;
1582  }
1583  /* set the previous language as result */
1584  if ( curLang == BSPANISH )
1585    Tcl_SetStringObj( obj_result, "es", -1 );
1586  else
1587    Tcl_SetStringObj( obj_result, "en", -1 );
1588  /* tell TOL what language to use from now on */
1589  BText::PutLanguage( nextLang );
1590  return TCL_OK;
1591}
1592
1593/*
1594 * Return the language used  by TOL. Fill in obj_result the current
1595 * language.
1596 *
1597 */
1598
1599int Tol_GetLanguage(Tcl_Interp * interp, Tcl_Obj * obj_result)
1600{
1601  BBool curLang = BText::Language();
1602 
1603  if ( curLang == BSPANISH )
1604    Tcl_SetStringObj( obj_result, "es", -1 );
1605  else
1606    Tcl_SetStringObj( obj_result, "en", -1 );
1607  return TCL_OK;
1608}
1609
1610/*
1611 * Fill in obj_result the version info corresponding to tol
1612 *
1613 *   {major MajorNum minor MinorNum release ReleaseNum coment Comment}
1614 *
1615 */
1616
1617int Tol_InfoVersion( Tcl_Interp * interp,  Tcl_Obj * obj_result )
1618{
1619#define VERSION_INFO_SIZE 4*2
1620 
1621  Tcl_Obj * items[VERSION_INFO_SIZE];
1622  char buffer[64];
1623
1624  /* Major Info */
1625  items[0] = Tcl_NewStringObj( "major", -1 );
1626  items[1] = Tcl_NewIntObj( VERSION_MAJOR );
1627  /* Minor Info */
1628  items[2] = Tcl_NewStringObj( "minor", -1 );
1629  items[3] = Tcl_NewIntObj( VERSION_MINOR );
1630  /* Release Info */
1631  items[4] = Tcl_NewStringObj( "release", -1 );
1632  sprintf(buffer,"%d", VERSION_RELEASE);
1633  items[5] = Tcl_NewStringObj(buffer, -1);
1634  /* Comment Info */
1635  items[6] = Tcl_NewStringObj( "comment", -1 );
1636  items[7] = Tcl_NewStringObj(TOLVersionBuild(), -1 );
1637  /* asign the items to the result list */
1638  Tcl_SetListObj( obj_result, VERSION_INFO_SIZE, items );
1639  return TCL_OK;
1640}
1641
1642/*
1643 * Fill in obj_result the list of files included in TOL
1644 *
1645 */
1646
1647
1648int Tol_InfoIncluded (Tcl_Interp * interp,Tcl_Obj * obj_result)
1649{
1650  BList* lst = BSetFromFile::Compiled();
1651
1652  BText txt(LstText(lst,"","",","));
1653  return BList2TclList(interp,lst,obj_result,&GetPath,&HasNoSource);
1654}
1655
1656/* OJO con la declaracion de tmpSet */
1657
1658int Tol_InfoFile(Tcl_Interp * interp, Tcl_Obj * file,
1659                 Tcl_Obj * obj_result)
1660{
1661  Tcl_DString dstr;
1662  const BSyntaxObject * so;
1663
1664  Tcl_DStringInit(&dstr);
1665  Tcl_UtfToExternalDString(NULL,Tcl_GetString(file),-1,&dstr);
1666 
1667  BText fname(Tcl_DStringValue(&dstr));
1668  so = (const BSyntaxObject*)BSetFromFile::FindCompiled(fname);
1669  Tcl_DStringFree(&dstr);
1670  if (!so) {
1671    Tcl_AppendStringsToObj(obj_result,"file \"",
1672                           Tcl_GetString(file),
1673                           "\" isn't included", NULL );
1674    return TCL_ERROR;
1675  }
1676  Tcl_Obj * info[6];
1677  /* adicionar la informacion del subtype y si tiene algun set
1678   * como descendiente
1679   */
1680  BText soInfo(so->Info());
1681  BText soPath(so->SourcePath());
1682  BText soDesc(so->Description());
1683
1684  char * pch = soInfo;
1685  if (pch) pch = skipWhite(pch);
1686  else pch = (char*)"";
1687
1688  Tcl_ExternalToUtfDString(NULL,pch,-1,&dstr);
1689  info[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1690  Tcl_DStringFree(&dstr);
1691
1692  Tcl_ExternalToUtfDString(NULL,soPath,-1,&dstr);
1693  info[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1694  Tcl_DStringFree(&dstr);
1695
1696  Tcl_ExternalToUtfDString(NULL,soDesc,-1,&dstr);
1697  info[2] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1698  Tcl_DStringFree(&dstr);
1699
1700  /* HAS SUBSET */
1701  BSet * ptrSet = &(((BUserSet*)so)->Contens());
1702  int tmpCard = ptrSet->Card();
1703  int j;
1704  for (j=1; j<=tmpCard; ++j )
1705    if (ContainerGetSet((*ptrSet)[j]))
1706      break;
1707  info[3] = Tcl_NewIntObj(j<=tmpCard);
1708   
1709  /* SUBTYPE INFO */
1710  info[4] = Tcl_NewIntObj( ptrSet->SubType() );
1711  /* STRUCTURE */
1712  info[5] = Tcl_NewStringObj( NULL, 0 );
1713  Tcl_SetListObj(obj_result, 6, info);
1714  return TCL_OK;
1715}
1716
1717/*
1718 * Fill in obj_result the result of evaluating including the file
1719 * given as argument: the absolute path.
1720 *
1721 */
1722
1723int Tol_IncludeFile(Tcl_Interp * interp,Tcl_Obj * obj_file,Tcl_Obj * obj_result)
1724{
1725  Tcl_DString dstr;
1726  BText fName;
1727
1728  Tcl_DStringInit(&dstr);
1729  fName = Tcl_UtfToExternalDString(NULL,Tcl_GetString(obj_file),-1,&dstr);
1730  BSetFromFile* uSet = (BSetFromFile*)BSetFromFile::FindCompiled(fName);
1731  Tcl_DStringFree(&dstr);
1732
1733  if(uSet) {
1734    DESTROY(uSet);
1735  }
1736  IncludeFile(fName);
1737  return TCL_OK;
1738}
1739
1740int Tol_DecompileFile( Tcl_Interp * interp,
1741                       Tcl_Obj * obj_file,
1742                       Tcl_Obj * obj_result )
1743{
1744  Tcl_DString dstr;
1745  BText fName;
1746
1747  Tcl_DStringInit(&dstr);
1748  fName = Tcl_UtfToExternalDString(NULL,Tcl_GetString(obj_file),-1,&dstr);
1749  BSetFromFile* uSet = (BSetFromFile*)BSetFromFile::FindCompiled(fName);
1750  Tcl_DStringFree(&dstr);
1751
1752  if(uSet) {
1753    DESTROY(uSet);
1754  } else {
1755    Tcl_AppendStringsToObj( obj_result, "file '",
1756                            Tcl_GetString(obj_file),
1757                            "' is not compiled", NULL );
1758    return TCL_ERROR;
1759  }
1760  if ( uSet ) {
1761    Tcl_AppendStringsToObj( obj_result, "could not decompile file '",
1762                            Tcl_GetString(obj_file), "'", NULL );
1763    return TCL_ERROR;
1764  }
1765  return TCL_OK;
1766}
1767/*
1768 *
1769 * Fill in obj_result the list of grammars defined in TOL
1770 *
1771 */
1772
1773int Tol_SetGrammarsObj(Tcl_Interp * interp, Tcl_Obj * obj_result )
1774{
1775
1776  BList* lstGra = BGrammar::Instances();
1777
1778  if (BList2TclList(interp,lstGra,obj_result,&GetName,&ExcludeAnything)==TCL_OK) {
1779    Tcl_Obj * name = Tcl_NewStringObj("Anything", -1);
1780    if (Tcl_ListObjAppendElement(interp,obj_result,name) != TCL_OK) {
1781      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1782      return TCL_ERROR;
1783    }
1784    if (QuickSort(interp,obj_result) != TCL_OK) {
1785      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1786      return TCL_ERROR;
1787    }
1788    return TCL_OK;
1789  }
1790  Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1791  return TCL_ERROR;
1792}
1793
1794/*
1795 *
1796 * Fill in obj_result the description of gra_name.
1797 *
1798 */
1799
1800int Tol_SetGrammarDescObj(Tcl_Interp * interp, Tcl_Obj * gra_name,
1801                          Tcl_Obj * obj_result )
1802{
1803  BGrammar * gra = BGrammar::FindByName(Tcl_GetString(gra_name));
1804
1805  if (gra) {
1806    BText desc(gra->Description());
1807    Tcl_SetStringObj(obj_result, desc, -1);
1808    return TCL_OK;
1809  }
1810  Tcl_AppendStringsToObj( obj_result, "\"",
1811                          Tcl_GetString(gra_name),
1812                          "\" isn't a grammar", NULL );
1813  return TCL_ERROR;
1814}
1815
1816/*
1817 *  Tol_FillFunctionInfo --
1818 *
1819 *    Used in Tol_SetFunctionsObj & Tol_SetFunctionInfoObj to return the info
1820 *    for the function requested.
1821 */
1822
1823static
1824int Tol_FillFunctionInfo(BOperator * opr, Tcl_Obj * obj_result)
1825{
1826  Tcl_Obj * info[3];
1827  Tcl_DString dstr_info;
1828  Tcl_DString dstr;
1829
1830  Tcl_DStringInit(&dstr_info);
1831  BText args(opr->Arguments());
1832 
1833  if(args.Last()!='}') // name doesn't comes within the arguments expression
1834  {   
1835      // grammar name
1836      Tcl_DStringAppend(&dstr_info, opr->Grammar()->Name(), -1);
1837      Tcl_DStringAppend(&dstr_info, " ", -1);
1838      // function name
1839      Tcl_DStringInit(&dstr);
1840      Tcl_ExternalToUtfDString(NULL, opr->FullName(), -1, &dstr);
1841      Tcl_DStringAppend(&dstr_info, Tcl_DStringValue(&dstr), -1);
1842      Tcl_DStringFree(&dstr);
1843  }
1844
1845  Tcl_ExternalToUtfDString(NULL,args.String(),-1,&dstr);
1846  Tcl_DStringAppend(&dstr_info, Tcl_DStringValue(&dstr), -1);
1847  Tcl_DStringFree(&dstr);
1848  info[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr_info), -1);
1849  Tcl_DStringFree(&dstr_info);
1850  Tcl_ExternalToUtfDString(NULL,opr->SourcePath(),-1,&dstr);
1851  info[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1852  Tcl_DStringFree(&dstr);
1853  Tcl_ExternalToUtfDString(NULL,opr->Description(),-1,&dstr);
1854  info[2] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1855  Tcl_DStringFree(&dstr);
1856  Tcl_SetListObj(obj_result, 3, info);
1857  return TCL_OK;
1858}
1859
1860/*
1861 *
1862 * Fill in obj_result the functions defined for grammar gra_name.  If gra_name
1863 * is a list it is considered as an object reference {type ?name? i1 ... ik}
1864 *
1865 */
1866
1867int Tol_SetFunctionsObj (Tcl_Interp * interp, Tcl_Obj * gra_name,
1868                         Tcl_Obj * obj_result)
1869{
1870  int length = 0;
1871 
1872  if (Tcl_ListObjLength(interp,gra_name,&length)!=TCL_OK) {
1873    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1874    return TCL_ERROR;
1875  }
1876  if (length>1) {
1877    const BSyntaxObject *syn;
1878    if (!(syn=Tol_ResolveObject(interp, gra_name, obj_result))) {
1879      return TCL_ERROR;
1880    }
1881   
1882    if (syn->Grammar() != GraCode()) {
1883      Tcl_AppendStringsToObj(obj_result, "'", Tcl_GetString(gra_name),
1884                             "' is not a function object", NULL);
1885      return TCL_ERROR;
1886    }
1887    BOperator * opr =  ((BGraContens<BCode>*)syn)->Contens().Operator();
1888    return Tol_FillFunctionInfo(opr, obj_result);
1889  }
1890  /* gra_name should be a grammar name */
1891  if (!strcmp(Tcl_GetString(gra_name), "Anything")) {
1892    const BSpFunHash& spf = BSpecialFunction::Instances();
1893    BSpFunHash::const_iterator iter;
1894    for(iter=spf.begin(); iter!=spf.end(); iter++)
1895    {
1896      Tcl_ListObjAppendElement(interp, obj_result,
1897                               Tcl_NewStringObj(iter->second->Name(), -1));
1898    }
1899    if (QuickSort(interp,obj_result) != TCL_OK) {
1900      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1901      return TCL_ERROR;
1902    }
1903    return TCL_OK;
1904  }
1905
1906  BGrammar * gra = BGrammar::FindByName(Tcl_GetString(gra_name));
1907 
1908  if (gra) {
1909    BList * lstOper = gra->GetOperators();
1910    if (BList2TclList(interp,lstOper,obj_result,&GetName) != TCL_OK) {
1911      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1912      DESTROY(lstOper);
1913      return TCL_ERROR;
1914    }
1915    DESTROY(lstOper);
1916    if (QuickSort(interp,obj_result) != TCL_OK) {
1917      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1918      return TCL_ERROR;
1919    }
1920    return TCL_OK;
1921  }
1922
1923  Tcl_AppendStringsToObj(obj_result, "'",
1924                         Tcl_GetString(gra_name),
1925                         "' isn't a grammar", NULL);
1926  return TCL_ERROR;
1927}
1928
1929static
1930BOperator* TT_FindOperator( const BGrammar *G, const char *expr )
1931{
1932  BOperator* opr = G->FindOperator( expr );
1933  if ( opr ) {
1934    return opr;
1935  }
1936  bool oldEnabled = BOut::Disable();
1937  bool stopFlag = BGrammar::StopFlag();
1938  BGrammar::Turn_StopFlag_Off();
1939  BSyntaxObject* obj = GraCode( )->BGrammar::LeftEvaluateExpr( expr );
1940  if ( stopFlag ) {
1941    BGrammar::Turn_StopFlag_On();
1942  } else {
1943    BGrammar::Turn_StopFlag_Off();
1944  }
1945  if( oldEnabled ) { BOut::Enable( ); }
1946  if(obj)
1947  {
1948    if( obj->Mode( ) == BUSERFUNMODE )
1949    {
1950      opr = dynamic_cast<BOperator*>( obj );
1951    }   
1952    if( obj->Mode( ) == BOBJECTMODE )
1953    {
1954      BUserCode *uc = dynamic_cast<BUserCode*>( obj );
1955      opr = uc ? uc->Contens().Operator( ) : NULL;
1956      if( opr && ( opr->Grammar( ) != G ) ) { opr = NULL; }
1957    }
1958  }
1959  return( opr );
1960}
1961
1962/*
1963 * Fill in obj_result the function's prototype and description
1964 * for a given function in a given grammar.
1965 *
1966 */
1967
1968int Tol_SetFunctionInfoObj (Tcl_Obj * gra_name,
1969                            Tcl_Obj * fun_name,
1970                            Tcl_Obj * obj_result)
1971{
1972  Tcl_DString dstr;
1973  Tcl_Obj * info[3];
1974
1975  if (!strcmp(Tcl_GetString(gra_name), "Anything")) {
1976    Tcl_DStringInit(&dstr);
1977    Tcl_UtfToExternalDString(NULL,Tcl_GetString(fun_name),-1,&dstr);
1978    const BSpecialFunction * spf = BSpecialFunction::Get(Tcl_DStringValue(&dstr));
1979    Tcl_DStringFree(&dstr);
1980    if (spf) {
1981      char * name, * args;
1982      size_t len;
1983     
1984      name = ((BText&)spf->Name()).Buffer();
1985      args = ((BText&)spf->Arguments()).Buffer();
1986      len = strlen(args);
1987      if(!len || args[len-1]!='}') {
1988        info[0] = Tcl_NewStringObj("Anything ", -1);
1989        Tcl_AppendStringsToObj(info[0],name,args,NULL);
1990      } else {
1991        info[0] = Tcl_NewStringObj("", -1);;
1992        Tcl_AppendStringsToObj(info[0],args,NULL);
1993      }
1994      info[1] = Tcl_NewStringObj("",-1);
1995      Tcl_ExternalToUtfDString(NULL,spf->Description(),-1,&dstr);
1996      info[2] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1997      Tcl_DStringFree(&dstr);
1998      Tcl_SetListObj(obj_result, 3, info);
1999      return TCL_OK;
2000    }
2001    Tcl_AppendStringsToObj( obj_result, "\"",
2002                            Tcl_GetString(fun_name),
2003                            "\" isn't a function in grammar Anything", NULL );
2004  } else {
2005    BGrammar * gra = BGrammar::FindByName(Tcl_GetString(gra_name));
2006 
2007    if (gra) {
2008      Tcl_DStringInit(&dstr);
2009      Tcl_UtfToExternalDString( NULL, Tcl_GetString( fun_name ), -1, &dstr );
2010      BOperator* opr = TT_FindOperator( gra, Tcl_DStringValue( &dstr ) );
2011      Tcl_DStringFree(&dstr);
2012      if (opr) {
2013        return Tol_FillFunctionInfo(opr, obj_result);
2014      }
2015      // release the previous use of dstr
2016      //Tcl_DStringFree(&dstr);
2017      Tcl_AppendStringsToObj( obj_result, "\"",
2018                              Tcl_GetString(fun_name),
2019                              "\" isn't a function in grammar ",
2020                              Tcl_GetString(gra_name), NULL );
2021    } else
2022      Tcl_AppendStringsToObj( obj_result, "\"",
2023                              Tcl_GetString(gra_name),
2024                              "\" isn't a grammar", NULL );
2025  }
2026  return TCL_ERROR;
2027}
2028
2029/* ojo info debe tener espacio para 7 Tcl_Obj como maximo */
2030/* retorna cuantos Tcl_Obj creo */
2031
2032int SynObj2TclObj( const BSyntaxObject * var, Tcl_Obj * info[] )
2033{
2034  Tcl_DString dstr;
2035  int infoc;
2036
2037  Tcl_DStringInit(&dstr);
2038
2039  /* GRAMMAR */
2040#ifdef ISFILE_IMPLEMENTED
2041  info[ 0 ] = Tcl_NewStringObj(var->IsFile( ) ? "File" :
2042                               var->Grammar( )->Name( ).String( ), -1 );
2043#else
2044  info[ 0 ] = Tcl_NewStringObj( var->Grammar( )->Name( ).String( ), -1 );
2045#endif
2046   
2047  /* NAME */
2048  BText synname;
2049 
2050  GetName(var, synname);
2051  Tcl_ExternalToUtfDString(NULL,synname,-1,&dstr);
2052  info[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
2053  Tcl_DStringFree(&dstr);
2054   
2055  /* REST OF FIELDS */
2056 
2057  BText varInfo(var->Info());
2058  BText varPath(var->SourcePath());
2059  BText varDesc(var->Description());
2060 
2061  /* OBJECT CONTENT */
2062  char * pch = varInfo;
2063 
2064  if (pch) pch = skipWhite(pch);
2065  else pch = (char*)"";
2066 
2067  Tcl_ExternalToUtfDString(NULL,pch,-1,&dstr);
2068  info[2] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
2069  Tcl_DStringFree(&dstr);
2070 
2071  /* OBJECT PATH */
2072  Tcl_ExternalToUtfDString(NULL,varPath,-1,&dstr);
2073  info[3] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
2074  Tcl_DStringFree(&dstr);
2075 
2076  /* OBJECT DESCRIPTION */
2077  Tcl_ExternalToUtfDString(NULL,varDesc,-1,&dstr);
2078  info[4] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
2079  Tcl_DStringFree(&dstr);
2080 
2081#ifdef ISFILE_IMPLEMENTED
2082  info[5] = Tcl_NewIntObj(var->IsFile());
2083#else
2084  info[5] = Tcl_NewIntObj(0);
2085#endif
2086  //info[6] = Tcl_NewIntObj(var->System());
2087  BSet *ptrSet;
2088  if ((ptrSet=ContainerGetSet(var))) {
2089    /* HAS SUBSET */
2090    int tmpCard = ptrSet->Card();
2091    int j;
2092    for (j=1; j<=tmpCard; ++j )
2093      if ( (*ptrSet)[j]->Grammar()==GraSet() )
2094        break;
2095    info[6] = Tcl_NewIntObj(j<=tmpCard);
2096     
2097    /* SUBTYPE */
2098    info[7] = Tcl_NewIntObj( ptrSet->SubType() );
2099     
2100    /* STRUCTURE */
2101    if ( ptrSet->Struct() ) {
2102      BText btxt( ptrSet->Struct()->Name() );
2103      Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
2104      info[8] = Tcl_NewStringObj( Tcl_DStringValue(&dstr), -1 );
2105      Tcl_DStringFree( &dstr );
2106    } else
2107      info[8] = Tcl_NewStringObj( NULL, 0 );
2108    infoc = 9;
2109  } else
2110    infoc = 6;
2111 
2112  return infoc;
2113}
2114
2115int Tol_SetVariableInfoObj (Tcl_Obj * gra_name,
2116                            Tcl_Obj * var_name,
2117                            Tcl_Obj * obj_result);
2118
2119/*!
2120 * Fill in obj_result the variables defined for grammar gra_name.
2121 * Or the element info if gra_name is a reference of an element
2122 * of a global container.
2123 */
2124int Tol_SetVariablesObj (Tcl_Interp *interp, Tcl_Obj *gra_name,
2125                         Tcl_Obj *obj_result)
2126{
2127  const BSyntaxObject *syn ;
2128 
2129  int length = 0;
2130  Tcl_Obj ** items;
2131  int tcl_code;
2132 
2133  if (Tcl_ListObjLength(interp,gra_name,&length)!=TCL_OK) {
2134    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
2135    return TCL_ERROR;
2136  }
2137  if (length!=1) {
2138    if (length == 2) {
2139      tcl_code = Tcl_ListObjGetElements(interp,gra_name,&length,&items);
2140      assert(tcl_code == TCL_OK);
2141      if (strcmp(Tcl_GetString(items[0]),"Console"))
2142        return Tol_SetVariableInfoObj(items[0], items[1], obj_result);
2143    }
2144    if (!(syn=Tol_ResolveObject(interp, gra_name, obj_result))) {
2145      return TCL_ERROR;
2146    }
2147//    Tcl_DString dstr;
2148    Tcl_Obj * info[9];
2149    int infoc;
2150   
2151    infoc = SynObj2TclObj(syn, info);
2152    Tcl_SetListObj(obj_result,infoc,info);
2153    return TCL_OK;
2154  }
2155  BGrammar *gra = BGrammar::FindByName(Tcl_GetString(gra_name));
2156  if (!gra) {
2157    Tcl_AppendStringsToObj( obj_result, "'",
2158                            Tcl_GetString(gra_name),
2159                            "' isn't a grammar", NULL );
2160    return TCL_ERROR;
2161  }
2162  BList * lstVar = gra->GetVariables();
2163  if (BList2TclList(interp,lstVar,obj_result,&GetIdentify) != TCL_OK) {
2164    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
2165    DESTROY(lstVar);
2166    return TCL_ERROR;
2167  }
2168  DESTROY(lstVar);
2169  if (QuickSort(interp,obj_result) != TCL_OK) {
2170    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
2171    return TCL_ERROR;
2172  }
2173  return TCL_OK;
2174}
2175
2176/*
2177 * Fill in obj_result the variables's description for a given variable
2178 * in a given grammar.
2179 *
2180 */
2181
2182int Tol_SetVariableInfoObj (Tcl_Obj * gra_name,
2183                            Tcl_Obj * var_name,
2184                            Tcl_Obj * obj_result)
2185{
2186  BGrammar * gra = BGrammar::FindByName(Tcl_GetString(gra_name));
2187  Tcl_DString dstr;
2188 
2189  Tcl_DStringInit(&dstr);
2190  if (gra) {
2191    Tcl_UtfToExternalDString(NULL,Tcl_GetString(var_name),-1,&dstr);
2192    const BSyntaxObject* var = gra->FINDVARIABLE(Tcl_DStringValue(&dstr));
2193    Tcl_DStringFree(&dstr);
2194
2195    if (var) {
2196      Tcl_Obj * info[9];
2197      int infoc;
2198      infoc = SynObj2TclObj( var, info );
2199      Tcl_SetListObj(obj_result,infoc,info);
2200//#define __INFO_PRINT_NREFS__
2201#ifdef __INFO_PRINT_NREFS__
2202      printf("NREF = %d\n", var->NRefs());
2203#endif
2204      return TCL_OK;
2205    }
2206    Tcl_AppendStringsToObj( obj_result, "\"",
2207                            Tcl_GetString(var_name),
2208                            "\" isn't a variable in grammar ",
2209                            Tcl_GetString(gra_name), NULL );
2210  } else
2211    Tcl_AppendStringsToObj( obj_result, "\"",
2212                            Tcl_GetString(gra_name),
2213                            "\" isn't a grammar", NULL );
2214  return TCL_ERROR;
2215}
2216
2217/*
2218 * Fill in obj_result the string representation of the
2219 * address of the object referenced in obj_ref.
2220 */
2221int Tol_GetAddressFromObject( Tcl_Interp * interp,
2222                             Tcl_Obj * obj_ref,
2223                             Tcl_Obj * obj_result)
2224{
2225  const BSyntaxObject *syn ;
2226
2227#ifndef _NDEBUG
2228#define _PRINT_ADDR_OBJREF_
2229#endif
2230
2231#ifdef _PRINT_ADDR_OBJREF_
2232  printf( "obj_ref = %s\n", Tcl_GetString( obj_ref ) );
2233#endif
2234
2235  if ( !( syn = Tol_ResolveObject( interp, obj_ref, obj_result ) ) ) {
2236    return TCL_ERROR;
2237  }
2238  BText addr = syn->GetAddressFromObject( );
2239  Tcl_AppendStringsToObj( obj_result, addr.Buffer( ), NULL );
2240  return TCL_OK;
2241}
2242                           
2243/*
2244 * We must be sure that the strings use 7 bit ASCII chararters.
2245 * Otherwise we must take care of the Utf representation.
2246 *
2247 */
2248
2249static
2250int StrObjCompare(const void * O1, const void * O2)
2251{
2252  char * str1 = (*(Tcl_Obj**)O1)->bytes;
2253  char * str2 = (*(Tcl_Obj**)O2)->bytes;
2254  int check1, check2;
2255
2256  check1 = isalpha(str1[0]);
2257  check2 = isalpha(str2[0]);
2258
2259  if ( check1 && !check2 )
2260    return 1;
2261  if ( check2 && !check1 )
2262    return -1;
2263  return strcmp(str1,str2);
2264}
2265
2266static
2267int QuickSort( Tcl_Interp * interp, Tcl_Obj * list )
2268{
2269  Tcl_Obj ** obj_array;
2270  int length;
2271
2272  if (Tcl_ListObjGetElements(interp, list, &length, &obj_array) != TCL_OK) {
2273    return TCL_ERROR;
2274  }
2275  qsort((void*)obj_array, length, sizeof(Tcl_Obj*), &StrObjCompare);
2276  return TCL_OK;
2277}
2278
2279static
2280void Tol_HciWriter( const BText & str )
2281{
2282  Tcl_CmdInfo cmd_info;
2283
2284  if (TT_interp && Tcl_GetCommandInfo(TT_interp,"Tol_HciWriter",&cmd_info) ) {
2285    Tcl_DString dstr;
2286    Tcl_Obj * objv[2];
2287   
2288    Tcl_DStringInit(&dstr);
2289    Tcl_IncrRefCount(objv[0]=Tcl_NewStringObj("Tol_HciWriter",-1));
2290    Tcl_ExternalToUtfDString(NULL, ((BText&)str).Buffer(), -1, &dstr);
2291    Tcl_IncrRefCount(objv[1]=Tcl_NewStringObj(Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr)));
2292    Tcl_DStringFree(&dstr);
2293 
2294    int status = Tcl_EvalObjv(TT_interp, 2, objv, TCL_EVAL_GLOBAL);
2295    if (status != TCL_OK) {
2296      printf("message: %s\n", ((BText&)str).Buffer());
2297      printf("objv[1] : %s\n", Tcl_GetString(objv[1]));
2298      printf("%s\n", TT_interp->result);
2299    }
2300    /* release the objects */
2301    Tcl_DecrRefCount(objv[0]);
2302    Tcl_DecrRefCount(objv[1]);
2303  }
2304}
2305
2306void Tol_InstallHciWriter()
2307{
2308  BOut::PutHciWriter(Tol_HciWriter);
2309  BOut::PutLogHciWriter(Tol_HciWriter);
2310}
2311
2312static
2313void Tol_SerieChart(BList * series, const BText& FileName )
2314{
2315#define CMD_SERIECHART "Tol_SerieChartMethod"
2316#define GRP_NAME "__grptmp_chart__%d"
2317
2318  Tcl_CmdInfo cmd_info;
2319  static int id = 0;
2320
2321  if (TT_interp && Tcl_GetCommandInfo(TT_interp,CMD_SERIECHART,&cmd_info) ) {
2322    Tcl_DString dstr;
2323    Tcl_Obj * objv[3];
2324    Tcl_Obj * obj_result=Tcl_NewObj();
2325    int tcl_result;
2326    char grpname[1024];
2327   
2328    Tcl_IncrRefCount(obj_result);
2329
2330    // first create the group of series
2331    sprintf(grpname, GRP_NAME, ++id);
2332    tcl_result = Tol_CreateSerieGrp(TT_interp, grpname, series, obj_result);
2333    if (tcl_result==TCL_ERROR) {
2334      printf("%s -- error in Tol_CreateSerieGrp: %s\n", CMD_SERIECHART,
2335             Tcl_GetString(obj_result));
2336      Tcl_DecrRefCount(obj_result);
2337      return;
2338    }
2339    // release the obj_result
2340    Tcl_DecrRefCount(obj_result);   
2341    // chart command
2342    Tcl_IncrRefCount(objv[0]=Tcl_NewStringObj(CMD_SERIECHART,-1));
2343    // serie group argument
2344    Tcl_IncrRefCount(objv[1]=Tcl_NewStringObj(grpname,-1));   
2345    // file name argument
2346    Tcl_DStringInit(&dstr);
2347    Tcl_ExternalToUtfDString(NULL, ((BText&)FileName).Buffer(), -1, &dstr);
2348    Tcl_IncrRefCount(objv[2]=Tcl_NewStringObj(Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr)));
2349    Tcl_DStringFree(&dstr);
2350    int status = Tcl_EvalObjv(TT_interp, 3, objv, TCL_EVAL_GLOBAL);
2351    if (status != TCL_OK) {
2352      printf("%s -- error in Tcl_EvalObjv:\n", CMD_SERIECHART);
2353      printf("%s\n", TT_interp->result);
2354      printf("objv[1] : %s\n", Tcl_GetString(objv[1]));
2355      printf("objv[2] : %s\n", Tcl_GetString(objv[2]));
2356    }
2357    /* release the objects */
2358    for (int i=0; i<3; i++)
2359      Tcl_DecrRefCount(objv[i]);
2360    /* the group of series should be destroyied in the Hook */
2361    /*Tcl_VarEval(TT_interp, "tol::seriegrp destroy ", grpname, NULL);*/
2362  }
2363}
2364
2365int Tol_Tcl_Eval(char * script, const char ** result)
2366{
2367  int status;
2368 
2369  status = Tcl_Eval(TT_interp, script);
2370  *result = Tcl_GetStringResult(TT_interp);
2371  return status==TCL_OK;
2372}
2373
2374Tcl_Obj *TolObj2TclObj( BSyntaxObject *tolObj )
2375{
2376  const char *grammar = tolObj->Grammar( )->Name( ).String( );
2377
2378  if ( !strcmp( grammar, "Text" ) ) {
2379    const BText &value = Text( tolObj );
2380    return Tcl_NewStringObj( value.String( ),-1 );
2381  } else if ( !strcmp( grammar, "Real" ) ) {
2382    const BDat &value = Dat( tolObj );
2383    return Tcl_NewDoubleObj( value.Value( ) );
2384  } else if ( !strcmp( grammar, "Set" ) ) {
2385    // a Tol Set maps to a Tcl list
2386    const BSet &setObj = ( ( BUserSet* )tolObj )->Contens( );
2387    int card = setObj.Card( );
2388    Tcl_Obj **objv = ( Tcl_Obj** )Tcl_Alloc( sizeof( Tcl_Obj* ) * card );
2389    for( int i = 1; i <= card; i++ ) {
2390      objv[ i - 1 ] = TolObj2TclObj( setObj[ i ] );
2391    }
2392    Tcl_Obj *listObj = Tcl_NewListObj( card, objv );
2393    Tcl_Free( ( char* )objv );
2394    return listObj;
2395  } else {
2396    // other types are not treated
2397    return Tcl_NewStringObj( tolObj->Dump( ).String( ),-1 );   
2398  }
2399}
2400
2401int Tol_Tcl_EvalEx( const BSet &Args, const char ** result )
2402{
2403  int status;
2404  Tcl_Obj **objv;
2405  int card = Args.Card( );
2406 
2407  if ( !Args.Card( ) ) {
2408    *result = "";
2409    status = TCL_OK;
2410  } else {
2411    objv = ( Tcl_Obj** )Tcl_Alloc( sizeof( Tcl_Obj* ) * card );
2412    for( int i=1; i<=card; i++ ) {
2413      objv[ i-1 ] = TolObj2TclObj( Args[i] );
2414      Tcl_IncrRefCount( objv[ i - 1 ] );
2415    }
2416    status = Tcl_EvalObjv( TT_interp, card, objv, TCL_EVAL_GLOBAL );
2417    *result = Tcl_GetStringResult( TT_interp );
2418    for( int i = 0; i < card; i++ ) {
2419      Tcl_DecrRefCount(objv[i]);
2420    }
2421  }
2422  return status==TCL_OK;
2423}
2424
2425int Tol_StopEvaluation()
2426{
2427  StopFlagOn();
2428  return TCL_OK;
2429}
2430
2431/*
2432 * Fill in obj_result the format .
2433 *
2434 */
2435
2436int Tol_LCFormat(Tcl_Interp*    interp,
2437                 Tcl_Obj *CONST obj_value,
2438                 Tcl_Obj *      obj_result)
2439{
2440  double value;
2441  char buffer[256];
2442 
2443  /* read the double value from tcl obj */
2444  if (Tcl_GetDoubleFromObj(TT_interp, obj_value, &value)==TCL_ERROR)
2445    {
2446      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
2447      return TCL_ERROR;
2448    }
2449  lc_format(value, buffer);
2450  Tcl_AppendStringsToObj(obj_result, buffer, NULL);
2451  return TCL_OK;
2452}
2453
2454void Tol_InstallMethodsHook()
2455{
2456  InstallSerieChartHook(&Tol_SerieChart);
2457  InstallTclEval(&Tol_Tcl_Eval);
2458  InstallTclEvalEx(&Tol_Tcl_EvalEx);
2459}
Note: See TracBrowser for help on using the repository browser.