source: tol/toltcl/generic/tolaccess.cpp @ eb21277

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

fixes #1449, the new reference has the form ADDRESS 90E6520:0:8CA6B90:0:8BB2450:0:2:4:3

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

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