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

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

refs #1812, refs #1818, compilación basada en CMake, eliminación de warnings, automatización de la regla install.

Configuración en Linux como:

cmake -DCMAKE_TOOLCHAIN_FILE=../linux-i686.toolchain.cmake -DTOL_PREFIX_PATH=/usr/local/tol32 -DCMAKE_BUILD_TYPE=Release -DTCL_LIBRARY=/usr/local/tcl8.5-i686/lib/libtcl8.5.so ..

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

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