source: tol/toltcl/generic/tolaccess.cpp @ 9d2a70c

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

refs #994, #1404: implementing the command tol::checksyntax

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

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