source: tol/toltcl/generic/tolaccess.cpp @ 08e78b9

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

refs #1323, using TOLHasBeenInitialized which is already implemented inside TOL

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

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