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

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

refs #1323, make sure InitTolKernel is invoked only if TOL has not being initialized

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

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