source: tol/toltcl/generic/tolaccess.cpp @ 20663cb

1941-docker-image-to-testdevel
Last change on this file since 20663cb was 20663cb, checked in by Víctor de Buen <vdebuen@…>, 18 years ago

Handling with returned Code objects having mode BUSERFUNMODE

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

  • Property mode set to 100644
File size: 59.9 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_blanguag.h>
34#include <tol/tol_bmatgra.h>
35#include <tol/tol_bvmatgra.h>
36#include <tol/tol_bnameblock.h>
37#include <tol/tol_bspfun.h>
38#include <tol/tol_bcodgra.h>
39#include <tol/tol_bsetgra.h>
40#include <tol/tol_btsrgra.h>
41#include <tol/tol_btxtgra.h>
42#include <tol/tol_bmethodhook.h>
43
44#include <toltclInt.h>
45#include <tt_pool.h>
46
47
48/*
49 * if SyntaxObject has IsFile implemented, uncomment the following
50 * define:
51 */
52
53/* #define ISFILE_IMPLEMENTED */
54
55typedef void (* getmethod)( const BSyntaxObject *, BText & );
56typedef int  (* checkmethod)( const BSyntaxObject * );
57
58static
59int QuickSort( Tcl_Interp * interp, Tcl_Obj * list );
60
61inline
62char * skipWhite(char * pch)
63{
64  while (*pch && isspace(*pch))
65    ++pch;
66  return pch;
67}
68
69static
70BText GetObjectName(const BSyntaxObject * so)
71{
72  return so->HasName() ? so->FullName() : so->LocalName();
73}
74
75static
76void GetName( const BSyntaxObject * so, BText & res )
77{
78  res = so->FullName();
79}
80
81static
82void GetIdentify( const BSyntaxObject * so, BText & res )
83{
84  res = so->Identify();
85}
86
87static
88void GetPath( const BSyntaxObject * so, BText & res )
89{
90  res = so->TolPath();
91}
92
93static
94int
95ExcludeAnything( const BSyntaxObject * so )
96{
97  return so != GraAnything();
98}
99
100static
101int HasNoSource( const BSyntaxObject * so )
102{
103  return !so->Source();
104}
105
106static
107int BList2TclList( Tcl_Interp * interp,
108                   BList * blist, Tcl_Obj * tcl_list,
109                   getmethod m, checkmethod accept = NULL)
110{
111  char * str;
112  Tcl_Obj * name;
113  Tcl_DString dstr;
114  BText tmp;
115
116  while(blist)
117  {
118    BSyntaxObject* so = (BSyntaxObject*)Car(blist);
119    if(!accept || (*accept)(so))
120    {
121      (*m)(so,tmp);
122      str = Tcl_ExternalToUtfDString(NULL,tmp,-1,&dstr);
123      name = Tcl_NewStringObj(str,-1);
124      Tcl_DStringFree(&dstr);
125      if ( Tcl_ListObjAppendElement(interp, tcl_list, name) != TCL_OK ) {
126        Tcl_DecrRefCount(name);
127        return TCL_ERROR;
128      }
129    }
130    blist = Cdr(blist);
131  }
132  return TCL_OK;
133}
134
135/*
136 * Fill in obj_result the result of avaluating in TOL the given
137 * string.
138 *
139 */
140
141/* cdr of console_stack point to first item */
142static BList console_stack;
143// Read only stack
144static BList console_stack_hidden;
145
146static
147void my_concat(BList* head, BList* tail)
148{
149  if (head->Cdr()) {
150    my_concat(head->Cdr(), tail);
151  } else {
152    head->PutCdr(tail);
153  }
154}
155
156int Tol_EvalExpr (Tcl_Obj * obj_expr, int hidden, Tcl_Obj * obj_result)
157{
158  BList * tol_result;
159  Tcl_DString dstr;
160  char * expr;
161 
162  Tcl_DStringInit(&dstr);
163  expr = Tcl_UtfToExternalDString(NULL,Tcl_GetString(obj_expr),-1,&dstr);
164  tol_result = MultyEvaluate(expr);
165  Tcl_DStringFree(&dstr);
166  if(tol_result) {
167    my_concat(hidden?&console_stack_hidden:&console_stack, tol_result);
168  }
169  /*  Tcl_AppendStringsToObj(obj_result,
170      "couldn't evaluate tol expresion \"",
171      Tcl_GetString(obj_expr), "\"", NULL);
172      return TCL_ERROR;*/
173  return TCL_OK;
174}
175
176int Tol_GetStructure( Tcl_Interp * interp, Tcl_Obj * name, Tcl_Obj * obj_result )
177{
178  Tcl_DString dstr;
179  BStruct * structure;
180  BStruct * substruct;
181
182  Tcl_DStringInit( &dstr );
183  Tcl_UtfToExternalDString( NULL, Tcl_GetString(name), -1, &dstr );
184  if ( Tcl_DStringLength( &dstr ) &&
185       (structure = FindStruct(Tcl_DStringValue(&dstr)))) {
186   
187    Tcl_Obj * tmp[2];
188    Tcl_Obj * info[2];
189    Tcl_Obj ** fields;
190    BText btxt;
191    int nfields;
192   
193    nfields = structure->Size();
194    fields = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*) * nfields );
195    for ( int i = 0; i < nfields; i++ ) {
196      BField & field = (*structure)[i];
197      btxt = field.Name();
198      Tcl_DStringFree(&dstr);
199      Tcl_ExternalToUtfDString( NULL, btxt, -1, &dstr );
200      info[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
201      Tcl_DStringFree( &dstr );
202      if ( (substruct = field.Struct()) ) {
203        btxt = substruct->Name();
204        Tcl_ExternalToUtfDString( NULL, btxt, -1, &dstr );
205        tmp[0] = Tcl_NewStringObj( "STRUCT", 6 );
206        tmp[1] = Tcl_NewStringObj( Tcl_DStringValue(&dstr), -1);
207        info[1] = Tcl_NewListObj( 2, tmp );
208      } else if ( field.Grammar() ) {
209        btxt = field.Grammar()->Name();
210        Tcl_ExternalToUtfDString( NULL, btxt, -1, &dstr );
211        info[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
212      }
213      fields[i] = Tcl_NewListObj(2,info);
214    }
215    Tcl_SetListObj( obj_result, nfields, fields );
216    Tcl_Free( (char*)fields );
217  }
218  return TCL_OK;
219}
220
221BSet* ContainerGetSet(const BSyntaxObject *container)
222{
223  if (container) {
224    if (container->Grammar()==GraSet())
225      return &(((BUserSet*)container)->Contens());
226    else if (container->Grammar()==GraNameBlock())
227      return &(((BUserNameBlock*)container)->Contens().Set());
228  }
229  return NULL;
230}
231 
232/*
233 * Return the path of a set if it is a file, trigger an error in other case
234 *
235 */
236
237int Tol_GetSetPath( Tcl_Interp * interp, Tcl_Obj * name, Tcl_Obj * obj_result )
238{
239  Tcl_DString uniBuffer;
240  const BSyntaxObject * syn;
241
242 /* if name contains spaces the we should try it first as a string */
243  Tcl_DStringInit(&uniBuffer);
244  Tcl_UtfToExternalDString(NULL,Tcl_GetString(name),-1,&uniBuffer);
245  BText fname(Tcl_DStringValue(&uniBuffer));
246  syn = (BSyntaxObject*)BSetFromFile::FindCompiled(fname);
247  Tcl_DStringFree(&uniBuffer);
248  if (!syn) {
249    syn = Tol_ResolveObject(interp, name, obj_result);
250  }
251  if ( !syn )
252    return TCL_ERROR;
253  BSet *ptrSet = ContainerGetSet(syn);
254  if ( ptrSet->SubType() >= BSet::MODFile && ptrSet->SubType() <= BSet::BMIFile ) {
255    Tcl_DString dstr;
256    BText path( syn->TolPath() );
257
258    Tcl_DStringInit( &dstr );
259    Tcl_ExternalToUtfDString(NULL,path,-1,&dstr);
260    Tcl_SetStringObj( obj_result, Tcl_DStringValue(&dstr), -1 );
261    return TCL_OK;
262  } else {
263    Tcl_AppendStringsToObj( obj_result, Tcl_GetString(name),
264                            " is not a valid file object", NULL );
265    return TCL_ERROR;
266  }
267}
268
269/*
270 * Fill in obj_result the content of the given tol object's names. The
271 * object are searched in the console's stack.
272 *
273 * Return:
274 *
275 *   {GRAMMAR NAME CONTENT PATH DESCRIPTION ISFILE [Has SubSet? SUBTYPE STRUCTURE]}
276 */
277
278int Tol_ListStack(Tcl_Interp * interp,int objc,Tcl_Obj *CONST objv[],
279                  Tcl_Obj * obj_result)
280{
281  BSyntaxObject * so;
282  BText btxt;
283  Tcl_DString dstr;
284  BList * tol_item;
285  Tcl_Obj * robjv[9];
286  int robjc;
287  Tcl_Obj * tcl_item;
288  int tcl_result;
289  BSet * ptrSet = 0;
290  int tmpCard;
291  int j;
292 
293  Tcl_DStringInit(&dstr);
294 
295  tol_item = console_stack.Cdr();
296  while (tol_item) {
297    so = (BSyntaxObject*)Car(tol_item);
298   
299    /* GRAMMAR NAME */
300    btxt = so->Grammar()->Name();
301    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
302    robjv[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
303    Tcl_DStringFree(&dstr);
304   
305    /* OBJECT NAME */
306//  btxt = so->Identify();
307    GetName( so, btxt );
308    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
309    robjv[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
310    Tcl_DStringFree(&dstr);
311   
312    /* OBJECT CONTENT */
313    btxt = so->Info();
314    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
315    robjv[2] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
316    Tcl_DStringFree(&dstr);
317   
318    /* OBJECT PATH */
319    btxt = so->SourcePath();
320    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
321    robjv[3] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
322    Tcl_DStringFree(&dstr);
323   
324    /* OBJECT DESCRIPTION */
325    btxt = so->Description();
326    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
327    robjv[4] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
328    Tcl_DStringFree(&dstr);
329   
330    /* IS THE OBJECT A FILE? */
331    robjv[5] = Tcl_NewIntObj(so->IsFile());
332////    if ( so->Grammar()==GraSet() ) {
333    if ( so->Grammar()==GraSet() || so->Grammar()==GraNameBlock()) {
334      /* HAS SUBSET */
335////      ptrSet = &(((BUserSet*)so)->Contens());
336      ptrSet = ContainerGetSet(so);
337      tmpCard = ptrSet->Card();
338      for (j=1; j<=tmpCard; ++j )
339        if ( (*ptrSet)[j]->Grammar()==GraSet() )
340          break;
341      robjv[6] = Tcl_NewIntObj(j<=tmpCard);
342       
343      /* SUBTYPE INFO */
344      robjv[7] = Tcl_NewIntObj( ptrSet->SubType() );
345       
346      /* STRUCT INFO */
347      if ( ptrSet->Struct() ) {
348        btxt = ptrSet->Struct()->Name();
349        Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
350        robjv[8] = Tcl_NewStringObj( Tcl_DStringValue(&dstr), -1 );
351        Tcl_DStringFree( &dstr );
352      } else
353        robjv[8] = Tcl_NewStringObj( NULL, 0 );
354      robjc = 9;
355    } else
356      robjc = 6;
357   
358    /* build the tcl item as a list */
359    tcl_item = Tcl_NewListObj(robjc,robjv);
360   
361    /* append to the end of the result */
362    tcl_result = Tcl_ListObjAppendElement(interp,obj_result,tcl_item);
363    if (tcl_result != TCL_OK) {
364      Tcl_SetStringObj(obj_result,"",-1);
365      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
366      return TCL_ERROR;
367    }
368    tol_item = Cdr(tol_item);
369  }
370  return TCL_OK;
371}
372
373struct tcl_info_t
374{
375  Tcl_Interp *interp;
376  int objc;
377  Tcl_Obj* CONST* objv;
378  Tcl_DString &dstr;
379};
380
381/*
382 * Tol_ReleaseStack --
383 *
384 * Recursive version in order to release stack in reverse order
385 *
386 * Preconditions:
387 *
388 *   P != NULL
389 */
390static
391int Tol_ReleaseStack(tcl_info_t &info, BList *P)
392{
393  int result;
394 
395  assert(P != NULL);
396
397  if (P->Cdr()) {
398    /* keep on looking for rest of items */
399    result = Tol_ReleaseStack(info, P->Cdr());
400    /* process this item */
401    BList *current = P->Cdr();
402    BSyntaxObject * so;
403    int i;
404    so = (BSyntaxObject*)(current->Car());
405    if (info.objc) {
406      const char* name = so->Name().String();
407      for (i = 0; i<info.objc; ++i) {
408        Tcl_UtfToExternalDString(NULL,Tcl_GetString(info.objv[i]),-1,
409                                 &info.dstr);
410        if (!strcmp(Tcl_DStringValue(&info.dstr), name)) {
411          Tcl_DStringFree(&info.dstr);
412          break;
413        }
414        Tcl_DStringFree(&info.dstr);
415      }
416    } else {
417      /* mark current as being found */
418      i = -1;
419    }
420    if (i<info.objc) {
421      BList *next = current->Cdr();
422      /* delete will DecNRefs to the Car */
423      delete current;
424      /* now try to release the BSyntaxObject */
425      DESTROY(so);
426      /* chain the list */
427      P->PutCdr(next);
428    }
429  } else {
430    /* EOR */
431    result = TCL_OK;
432  }
433  return result;
434}
435
436int Tol_ReleaseStack(Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[],
437                     Tcl_Obj * obj_result)
438{
439  Tcl_DString dstr;
440  tcl_info_t tcl_info = {interp, objc, objv, dstr};
441  Tcl_DStringInit(&dstr);
442
443  return Tol_ReleaseStack(tcl_info, &console_stack);
444}
445
446/*!
447 * Tol_GetConsoleObject --
448 *
449 *     Returns the object with given index in the console object list.
450 */
451BSyntaxObject * Tol_GetConsoleObject(int index )
452{
453  BList * current = console_stack.Cdr();
454  int i = 1;
455  while (current) {
456    if (i==index) break;
457    current = Cdr(current);
458    ++i;
459  }
460  return current ? (BSyntaxObject*)(current->Car()) : NULL;
461}
462
463
464/*
465 * return the container (File, Set or NameBlock) with name obj_name,
466 * in case of error return NULL and leave a description in
467 * obj_result.
468 *
469 */
470const BSyntaxObject * Tol_FindGlobalContainer(const char* Type,
471                                              const char* obj_name,
472                                              Tcl_Obj*    obj_result)
473{
474  BGrammar *gra;
475  BSyntaxObject* var;
476  Tcl_DString uniBuffer;
477
478  if (!strcmp(Type, "Set"))
479    gra = GraSet();
480  else if (!strcmp(Type, "NameBlock"))
481    gra = GraNameBlock();
482  else if (!strcmp(Type, "File"))
483    gra = NULL;
484  else {
485    Tcl_AppendStringsToObj(obj_result,"type '",
486                           Type,
487                           "' is not a container grammar", NULL );
488    return NULL;
489  }
490  Tcl_DStringInit(&uniBuffer);
491  Tcl_UtfToExternalDString(NULL,obj_name,-1,&uniBuffer);
492  if (!gra) {
493    /* should look in Files */
494    BText fname(Tcl_DStringValue(&uniBuffer));
495    if (!(var=(BSyntaxObject*)BSetFromFile::FindCompiled(fname))) {
496      Tcl_AppendStringsToObj(obj_result,"file \"",
497                             obj_name,
498                             "\" is not included", NULL );
499    }
500  } else if (!(var=gra->FINDVARIABLE(Tcl_DStringValue(&uniBuffer)))) {
501      Tcl_AppendStringsToObj(obj_result,"\"",
502                             obj_name,
503                             "\" isn't a ", Type, " variable", NULL );
504  }
505  Tcl_DStringFree(&uniBuffer);
506  return var;
507}
508
509/*
510 * given a tol set, returns its child corresponding to the set of
511 * indexes indexes of size n.  In case of error return NULL and leave
512 * a description in obj_result.
513 *
514 */
515
516const BSyntaxObject * Tol_FindChild(Tcl_Interp    *interp,
517                                    const BSyntaxObject *syn_obj,
518                                    Tcl_Obj       **indexes, int n,
519                                    Tcl_Obj       *obj_result)
520{
521  int tcl_code;
522  Tcl_DString dstr;
523  BSet *container;
524  int idx, card;
525  int i;
526
527  for (i=0; i<n; ++i) {
528    if (!(container = ContainerGetSet(syn_obj))) {
529      BText info(syn_obj->Info());
530      Tcl_DStringInit(&dstr);
531      Tcl_ExternalToUtfDString(NULL,info,-1,&dstr);
532      Tcl_AppendStringsToObj(obj_result,"object \"",
533                             Tcl_DStringValue(&dstr),
534                             "\" is not a container",
535                             NULL);
536      Tcl_DStringFree(&dstr);
537      break;
538    }
539    /* get the current object index */
540    tcl_code = Tcl_GetIntFromObj(interp,indexes[i],&idx);
541    if (tcl_code != TCL_OK) {
542      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
543      break;
544    }
545    card = container->Card();
546    if (idx<1 || idx>card) {
547      Tcl_AppendStringsToObj(obj_result,
548                             "index '",
549                             Tcl_GetString(indexes[i]),
550                             "' out of range",
551                             NULL);
552      break;
553    }
554    /* take the next object in the list */
555    syn_obj = (*container)[idx];
556  }
557  return i == n ? syn_obj : NULL;
558}
559
560/*!
561 *  Tol_ResolveObject --
562 *
563 *     Resolve a SyntaxObject given a toltcl object reference. A
564 *     reference is {TYPE ?container? i1 i2 ... in} or a global
565 *     container's name of type File|Set|NameBlock|Console. When TYPE
566 *     is Console then container is not given. The grammar of the
567 *     object found is matched to the given argument grammar. If the
568 *     return value is NULL an error message is left in interp.
569 */
570
571const BSyntaxObject * Tol_ResolveObject(Tcl_Interp *interp,
572                                        Tcl_Obj    *obj_ref,
573                                        Tcl_Obj    *obj_result)
574{
575  Tcl_Obj ** items;
576  int n;
577  int tcl_code;
578  char * type;
579
580  /* look for subitem given in obj_ref */
581  tcl_code = Tcl_ListObjGetElements(interp, obj_ref, &n, &items);
582  if (tcl_code != TCL_OK) {
583    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
584    return NULL;
585  }
586
587  // this Tcl_Obj is to leave error messages
588  const BSyntaxObject * syn = NULL;
589
590  if (n >= 2) {
591    type = Tcl_GetString(items[0]);
592    if (!strcmp(type,"Console") || !strcmp(type,"File") ||
593        !strcmp(type,"Set") || !strcmp(type,"NameBlock") ) {
594      if (!strcmp(type,"Console")) {
595        // is a reference in the console, items[1] is the first index in
596        // the path, following indexes are indexes withing containers.
597        int i1;
598        if ((tcl_code = Tcl_GetIntFromObj(interp,items[1],&i1)!=TCL_OK)) {
599          Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
600          return NULL;
601        }
602        if (!(syn=Tol_GetConsoleObject(i1))) {
603          Tcl_AppendStringsToObj(obj_result, "index ",
604                                 Tcl_GetString(items[1]),
605                                 " not found in console", NULL);
606          return NULL;
607        }
608      } else {
609      /* should be File, Set or NameBlock, it is a hierarchical container */
610        if (!(syn=Tol_FindGlobalContainer(Tcl_GetString(items[0]),
611                                          Tcl_GetString(items[1]),
612                                          obj_result))) {
613          return NULL;
614        }
615      }
616      assert(syn);
617      if (n>2) {
618        // there are more indexes & syn should be a Container
619        if (!(syn=Tol_FindChild(interp,
620                                syn, items+2, n-2, obj_result))) {
621          return NULL;
622        }
623      }
624    } else {
625      if (n==2) {
626        // look global var in grammar
627        BGrammar * gra;
628        gra = BGrammar::FindByName(type);
629        if (!gra) {
630          Tcl_AppendStringsToObj(obj_result, "\"",
631                                                   type,
632                                                   "\" isn't a grammar", NULL);
633          return NULL;
634        }
635        Tcl_DString dstr;
636        Tcl_DStringInit(&dstr);
637        Tcl_UtfToExternalDString(NULL,Tcl_GetString(items[1]),-1,&dstr);
638        if (!(syn = gra->FINDVARIABLE(Tcl_DStringValue(&dstr))))
639          Tcl_AppendStringsToObj(obj_result, "variable '",
640                                 obj_ref, "' not found in grammar '",
641                                 gra->Name().String(), "'", NULL);
642        Tcl_DStringFree(&dstr);
643        /* found and matched */
644        return syn;
645      }
646    }
647  } else {
648      Tcl_AppendStringsToObj(obj_result,
649                             "incorrect object reference in ResolveObject",
650                             NULL);
651  }
652/*  if (grammar && syn && syn->Grammar()!=grammar) {
653    Tcl_AppendStringsToObj(obj_result, "grammar for object '",
654                           Tcl_GetString(obj_ref),
655                           "' does not match grammar '",
656                           grammar->Name().String(), "'", NULL);
657    syn = NULL;
658  }
659*/
660  return syn;
661}
662
663int Tol_FindSOInSet(BSet * ptrSet, const BSyntaxObject * syn,
664                    ToltclPool & indexes)
665{
666  int j;
667  const BSyntaxObject * so;
668 
669  for (j = 1; j <= ptrSet->Card(); j++) {
670    so = (*ptrSet)[j];
671    BSet *ptrSet;
672    if (so == syn || ((ptrSet=ContainerGetSet(so)) &&
673                      Tol_FindSOInSet(ptrSet,
674                                      syn, indexes))) {
675      /* found!!! */
676      indexes.AppendObject((void*)j);     
677      return 1;
678    }
679  }
680
681  return 0;
682}
683 
684/*
685 *  Puts in obj_result the global reference of the given
686 *  syntaxobject. The syntaxobject could be given as set member or as
687 *  global variable. In case of error leave in obj_result the message.
688 *  Returns TCL_OK if succesfull or TCL_ERROR in case of error.
689 */
690
691int Tol_GetReference(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[],
692                     Tcl_Obj * obj_result)
693{
694  Tcl_Obj ** items;
695  int n;
696  int tcl_code;
697  const BSyntaxObject * source, * syn;
698  BSet * ptrSet;
699  ToltclPool indexes;
700  Tcl_DString dstr;
701  int j;
702  char * graname, * objname;
703
704  assert(!Tcl_IsShared(obj_result));
705  tcl_code = Tcl_ListObjGetElements(interp,objv[0],&n,&items);
706  assert(tcl_code == TCL_OK);
707  if (n<2) {
708    Tcl_AppendStringsToObj(obj_result,
709                           "wrong # args: should be 'tol::info",
710                           " reference {grammar|container objname ?indexes?}'",
711                           NULL);
712    return TCL_ERROR;   
713  }
714  if (n==2 && strcmp(Tcl_GetString(items[0]),"Console")) {
715  // global access
716    BGrammar * gra;
717    graname = Tcl_GetString(items[0]);
718    gra = BGrammar::FindByName(graname);
719    if (!gra) {
720      Tcl_AppendStringsToObj( obj_result, "\"",
721                              graname,
722                              "\" isn't a grammar", NULL);
723      return TCL_ERROR;
724    }
725    objname = Tcl_GetString(items[1]);
726    Tcl_UtfToExternalDString(NULL,objname,-1,&dstr);
727    syn = gra->FINDVARIABLE(Tcl_DStringValue(&dstr));
728    Tcl_DStringFree(&dstr);
729    if (!syn) {
730      Tcl_AppendStringsToObj(obj_result, "\"",
731                             Tcl_GetString(items[1]),
732                             "\" isn't a variable in grammar ",
733                             graname, NULL);
734      return TCL_ERROR;
735    }
736    source = syn->Source();
737    if (!source) {
738      /* is a global variable not defined inside a file */
739      items = (Tcl_Obj**)Tcl_Alloc(sizeof(Tcl_Obj*) * 2);
740      Tcl_ExternalToUtfDString(NULL, graname, -1, &dstr);
741      items[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
742      Tcl_DStringFree(&dstr);
743      Tcl_ExternalToUtfDString(NULL, objname, -1, &dstr);
744      items[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
745      Tcl_DStringFree(&dstr);
746      Tcl_SetListObj(obj_result, 2, items);
747      Tcl_Free((char*)items);
748      return TCL_OK;
749    }
750  } else {
751    // member access
752    if (!(syn=Tol_ResolveObject(interp,objv[0],obj_result))) {
753      return TCL_ERROR;
754    }
755    /* here we have a valid reference */
756    tcl_code = Tcl_ListObjGetElements(interp,objv[0],&n,&items);
757    assert(tcl_code == TCL_OK);
758    if (!strcmp(Tcl_GetString(items[0]),"File") ||
759        !strcmp(Tcl_GetString(items[0]),"Console")) {
760      /* here we have in objv[0] the answer */
761      Tcl_SetListObj(obj_result, n, items);
762      return TCL_OK;     
763    }
764    source = syn->Source();
765    if (!source) {
766      /* here we have in objv[0] the answer too */
767      Tcl_SetListObj(obj_result, n, items);
768      return TCL_OK;
769    }
770  }
771  /* at this point variable has to be defined inside a file */
772  assert(source);
773  ptrSet = &(((BUserSet*)source)->Contens());
774  if (Tol_FindSOInSet(ptrSet, syn, indexes)) {
775    items = (Tcl_Obj**)Tcl_Alloc(sizeof(Tcl_Obj*) * (indexes.GetSize()+2));
776    Tcl_ExternalToUtfDString(NULL, "File", -1, &dstr);
777    items[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
778    Tcl_DStringFree(&dstr);
779    Tcl_ExternalToUtfDString(NULL, source->Name(), -1, &dstr);
780    items[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
781    Tcl_DStringFree(&dstr);
782    int last = indexes.GetLast();
783    for(j = last; j >= 0; j--)
784      items[last+2-j] = Tcl_NewIntObj(long(*indexes._GetObject(j)));
785    Tcl_SetListObj(obj_result, indexes.GetSize()+2, items);
786    Tcl_Free((char*)items);
787    return TCL_OK;
788  } else {
789    /* this should not happend because syn should be inside syn->source */
790    Tcl_AppendStringsToObj(obj_result,
791                             "internal error: syn not found in syn->Source()",
792                             NULL);
793    return TCL_ERROR;
794  }
795}
796
797
798/*
799 * Iterate over a first level's children of a given set.  The set
800 * could be a container Set, File or NameBlock if the index list is
801 * empty or container[i1][i2]...[ik] for the given indexes
802 * {i1,i2,...,ik}
803 *
804 */
805
806int Tol_IterChildren(Tcl_Interp * interp,
807                     int objc,
808                     Tcl_Obj *CONST objv[],
809                     Tcl_Obj * obj_result)
810{
811#define ARG_SCRIPT    0
812#define ARG_GRAMMAR   ARG_SCRIPT+1
813#define ARG_NAME      ARG_GRAMMAR+1
814#define ARG_CONTENT   ARG_NAME+1
815#define ARG_PATH      ARG_CONTENT+1
816#define ARG_DESC      ARG_PATH+1
817#define ARG_INDEXES   ARG_DESC+1
818#define ARG_ISFILE    ARG_INDEXES+1
819#define ARG_HASSUBSET ARG_ISFILE+1
820#define ARG_SUBTYPE   ARG_HASSUBSET+1
821#define ARG_STRUCT    ARG_SUBTYPE+1
822#define NUM_ARGS      ARG_STRUCT+1
823
824  const BSyntaxObject* container;
825  Tcl_DString dstr;
826  Tcl_Obj * ArgIndexes;
827  int tcl_code, cont_loop;
828  int i, card ;
829  int n, index_length;
830  Tcl_Obj ** items;
831
832  int length = 0;
833 
834  if (Tcl_ListObjLength(interp,objv[0],&length)!=TCL_OK) {
835    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
836    return TCL_ERROR;
837  }
838  if (length<2) {
839    Tcl_AppendStringsToObj(obj_result,
840                           "invalid object reference '",
841                           Tcl_GetString(objv[0]),
842                           "must be {TYPE ?name? i1 i2 ... ik}",
843                           NULL);
844    return TCL_ERROR;
845  }
846
847  if (!(container=Tol_ResolveObject(interp, objv[0], obj_result))) {
848    return TCL_ERROR;
849  }
850  BSet *set = ContainerGetSet(container);
851  if (!set) {
852    Tcl_AppendStringsToObj(obj_result,
853                           "object '",
854                           Tcl_GetString(objv[0]),
855                           "' is not a valid container ",
856                           NULL);
857      return TCL_ERROR;
858  }
859 
860  card = set->Card();
861 
862  int datac;
863  Tcl_Obj * datav[NUM_ARGS];
864  // is ok to ask for a list
865  Tcl_ListObjGetElements(interp,objv[0],&n,&items);
866 
867  if (strcmp(Tcl_GetString(items[0]),"Console")) {
868    if (n>2)
869      ArgIndexes = Tcl_NewListObj(n-2,items+2);
870    else
871      ArgIndexes = Tcl_NewListObj(0,NULL);
872  } else {
873    if (n>1)
874      ArgIndexes = Tcl_NewListObj(n-1,items+1);
875    else
876      ArgIndexes = Tcl_NewListObj(0,NULL);
877  }
878
879  datav[ARG_SCRIPT] = objv[1];
880 
881  datav[ARG_GRAMMAR] = Tcl_NewObj();
882  datav[ARG_NAME]    = Tcl_NewObj();
883  datav[ARG_CONTENT] = Tcl_NewObj();
884  datav[ARG_PATH]    = Tcl_NewObj();
885  datav[ARG_DESC]    = Tcl_NewObj();
886  Tcl_Obj * last_index = Tcl_NewIntObj(0);
887  Tcl_ListObjAppendElement(NULL,ArgIndexes,last_index);
888  datav[ARG_INDEXES] = ArgIndexes;
889  Tcl_ListObjLength(NULL,datav[ARG_INDEXES],&index_length);
890  datav[ARG_ISFILE] = Tcl_NewObj();
891  datav[ARG_HASSUBSET] = Tcl_NewObj();
892  datav[ARG_SUBTYPE] = Tcl_NewObj();
893  datav[ARG_STRUCT] = Tcl_NewObj();
894  for (i=ARG_GRAMMAR; i<NUM_ARGS; ++i)
895    Tcl_IncrRefCount(datav[i]);
896 
897  BSyntaxObject *syn_i;
898  BSet          *set_i; /* just in case syn_i be a container */
899  /* now iter over its children */
900 
901  Tcl_DStringInit(&dstr);
902  BText btxt;
903 
904 
905  for (i=1; i<=card; ++i) {
906    syn_i = (*set)[i];
907   
908    /* read the grammar */
909   
910    btxt = syn_i->Grammar()->Name();
911    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
912    if (Tcl_IsShared(datav[ARG_GRAMMAR])) {
913      Tcl_DecrRefCount(datav[ARG_GRAMMAR]);
914      datav[ARG_GRAMMAR] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
915      Tcl_IncrRefCount(datav[ARG_GRAMMAR]);
916    } else
917      Tcl_SetStringObj(datav[ARG_GRAMMAR], Tcl_DStringValue(&dstr),-1);
918    Tcl_DStringFree(&dstr);
919   
920    /* read the name */
921   
922    //btxt = syn_i->Identify();
923    GetName( syn_i, btxt );
924    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
925    if (Tcl_IsShared(datav[ARG_NAME])) {
926      Tcl_DecrRefCount(datav[ARG_NAME]);
927      datav[ARG_NAME] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
928      Tcl_IncrRefCount(datav[ARG_NAME]);
929    } else
930      Tcl_SetStringObj(datav[ARG_NAME], Tcl_DStringValue(&dstr),-1);
931    Tcl_DStringFree(&dstr);
932   
933    /* read the content */
934   
935    btxt = syn_i->Info();
936    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
937    if (Tcl_IsShared(datav[ARG_CONTENT])) {
938      Tcl_DecrRefCount(datav[ARG_CONTENT]);
939      datav[ARG_CONTENT] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
940      Tcl_IncrRefCount(datav[ARG_CONTENT]);
941    } else
942      Tcl_SetStringObj(datav[ARG_CONTENT],Tcl_DStringValue(&dstr),-1);
943    Tcl_DStringFree(&dstr);
944   
945    /* read the path */
946   
947    btxt = syn_i->SourcePath();
948    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
949    if (Tcl_IsShared(datav[ARG_PATH])) {
950      Tcl_DecrRefCount(datav[ARG_PATH]);
951      datav[ARG_PATH] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
952      Tcl_IncrRefCount(datav[ARG_PATH]);
953    } else
954      Tcl_SetStringObj(datav[ARG_PATH],Tcl_DStringValue(&dstr),-1);
955    Tcl_DStringFree(&dstr);
956   
957    /* read the description */
958   
959    btxt = syn_i->Description();
960    Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
961    if (Tcl_IsShared(datav[ARG_DESC])) {
962      Tcl_DecrRefCount(datav[ARG_DESC]);
963      datav[ARG_DESC] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
964      Tcl_IncrRefCount(datav[ARG_DESC]);
965    } else
966      Tcl_SetStringObj(datav[ARG_DESC],Tcl_DStringValue(&dstr),-1);
967    Tcl_DStringFree(&dstr);
968   
969    if ((set_i=ContainerGetSet(syn_i))) {
970      /* update last index */
971      if (Tcl_IsShared(last_index)) {
972        last_index = Tcl_NewIntObj(i);
973        Tcl_ListObjReplace(NULL, datav[ARG_INDEXES], index_length-1,
974                           1, 1, &last_index);
975      }
976      /*
977      if (Tcl_IsShared(datav[ARG_INDEXES])) {
978        Tcl_DecrRefCount(datav[ARG_INDEXES]);
979        datav[ARG_INDEXES] = Tcl_DuplicateObj(datav[ARG_INDEXES]);
980        Tcl_IncrRefCount(datav[ARG_INDEXES]);
981        Tcl_ListObjLength(NULL,datav[ARG_INDEXES],&n);
982        Tcl_ListObjIndex(NULL,datav[ARG_INDEXES],n-1,&last_index);
983      }
984      */
985      /* set the last value index */
986      Tcl_SetIntObj(last_index,i);
987      /* to refresh the string */
988      Tcl_InvalidateStringRep(datav[ARG_INDEXES]);
989      if (Tcl_IsShared(datav[ARG_ISFILE])) {
990        Tcl_DecrRefCount(datav[ARG_ISFILE]);
991#ifdef ISFILE_IMPLEMENTED
992        datav[ARG_ISFILE] = Tcl_NewIntObj(syn_i->IsFile());
993#else
994        datav[ARG_ISFILE] = Tcl_NewIntObj(0);
995#endif
996        Tcl_IncrRefCount(datav[ARG_ISFILE]);
997      } else
998#ifdef ISFILE_IMPLEMENTED
999        Tcl_SetIntObj(datav[ARG_ISFILE],syn_i->IsFile());
1000#else
1001      Tcl_SetIntObj(datav[ARG_ISFILE],0);
1002#endif
1003      /* verify if has subset */
1004      int tmpCard = set_i->Card();
1005      int j;
1006      for (j=1; j<=tmpCard; ++j )
1007        if (ContainerGetSet((*set_i)[j]))
1008          break;
1009      if (Tcl_IsShared(datav[ARG_HASSUBSET])) {
1010        Tcl_DecrRefCount(datav[ARG_HASSUBSET]);
1011        datav[ARG_HASSUBSET] = Tcl_NewIntObj(j<=tmpCard);
1012        Tcl_IncrRefCount(datav[ARG_HASSUBSET]);
1013      } else
1014        Tcl_SetIntObj(datav[ARG_HASSUBSET],j<=tmpCard);
1015       
1016      /* subtype info */
1017       
1018      if (Tcl_IsShared(datav[ARG_SUBTYPE])) {
1019        Tcl_DecrRefCount(datav[ARG_SUBTYPE]);
1020        datav[ARG_SUBTYPE] = Tcl_NewIntObj(set_i->SubType());
1021        Tcl_IncrRefCount(datav[ARG_SUBTYPE]);
1022      } else
1023        Tcl_SetIntObj(datav[ARG_SUBTYPE],set_i->SubType());
1024       
1025      /* STRUCT INFO */
1026      if ( set_i->Struct() ) {
1027        btxt = set_i->Struct()->Name();
1028        Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
1029      }
1030      if (Tcl_IsShared(datav[ARG_STRUCT])) {
1031        Tcl_DecrRefCount(datav[ARG_STRUCT]);
1032        datav[ARG_STRUCT] = Tcl_NewStringObj(Tcl_DStringValue(&dstr),-1);
1033        Tcl_IncrRefCount(datav[ARG_STRUCT]);
1034      } else
1035        Tcl_SetStringObj(datav[ARG_STRUCT],Tcl_DStringValue(&dstr),-1);
1036      Tcl_DStringFree(&dstr);
1037      datac = NUM_ARGS;
1038    } else
1039      datac = ARG_INDEXES;
1040    tcl_code = Tcl_EvalObjv(interp,datac,datav,TCL_EVAL_GLOBAL);
1041    if (tcl_code != TCL_OK) {
1042      /* liberar los objetos tcl */
1043      for (i=ARG_GRAMMAR; i<NUM_ARGS; ++i)
1044        Tcl_DecrRefCount(datav[i]);
1045      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1046      return tcl_code;
1047    }
1048    /* check if break loop */
1049    cont_loop = 1;
1050    tcl_code = Tcl_GetIntFromObj(interp,Tcl_GetObjResult(interp),&cont_loop);
1051    if (tcl_code == TCL_OK && !cont_loop)
1052      break;
1053  }
1054 
1055  /* liberar los objetos tcl */
1056  for (i=ARG_GRAMMAR; i<NUM_ARGS; ++i)
1057    Tcl_DecrRefCount(datav[i]);
1058  return TCL_OK;
1059}
1060
1061/*
1062 * Fill in obj_result the content of the matrix variable.
1063 *
1064 */
1065
1066int Tol_GetMatrixContent(Tcl_Interp * interp,
1067                         Tcl_Obj * obj_name,
1068                         Tcl_Obj * obj_result)
1069{
1070  //BGrammar * gra = NULL;
1071  const BSyntaxObject *tol_obj = NULL;
1072   
1073  if (!(tol_obj=Tol_ResolveObject(interp, obj_name, obj_result))) {
1074    return TCL_ERROR;
1075  }
1076
1077  BMatrix<double> vmat;
1078  BMatrix<double> &theMat = vmat;
1079
1080  if (tol_obj->Grammar()==GraVMatrix()) {
1081    BVMat &V = VMat((BSyntaxObject *)tol_obj);
1082    V.GetDMat(vmat);
1083  } else if (tol_obj->Grammar()==GraMatrix()) {
1084    theMat = ((DMat&)Mat((BSyntaxObject *)tol_obj));
1085  } else { 
1086    Tcl_AppendStringsToObj( obj_result, Tcl_GetString(obj_name),
1087                            " is not a valid Matrix|VMatrix object", NULL );   
1088    return TCL_ERROR;
1089  }
1090   
1091#define IT_NAME 0
1092#define IT_ROWS 1
1093#define IT_COLS 2
1094#define IT_DATA 3
1095#define IT_SIZE 4
1096     
1097  Tcl_Obj * items[4];
1098  Tcl_Obj ** subitems;
1099  int r, Rows, c, Cols;
1100  BDat & dat = BDat::Unknown();
1101 
1102  //BMatrix<BDat> & mat = (BMatrix<BDat>&)(((BUserMat*)tol_obj)->Contens());
1103 
1104  //items[IT_NAME] = Tcl_NewStringObj(tol_obj->Identify(),-1);
1105  BText tmp;
1106  GetName( tol_obj, tmp );
1107  items[IT_NAME] = Tcl_NewStringObj(tmp.Buffer(),-1);
1108  Rows = theMat.Rows();
1109  Cols = theMat.Columns();
1110  items[IT_ROWS] = Tcl_NewIntObj(Rows);
1111  items[IT_COLS] = Tcl_NewIntObj(Cols);
1112  subitems = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*Rows*Cols );
1113  for ( r = 0; r < Rows; ++r )
1114    for ( c = 0; c < Cols; ++c ) {
1115      dat = theMat(r,c);
1116      if (dat.IsKnown())
1117        subitems[r*Cols+c] = Tcl_NewDoubleObj(dat.Value());
1118      else
1119        subitems[r*Cols+c] = Tcl_NewStringObj("?",-1);
1120    }
1121  items[IT_DATA] = Tcl_NewListObj( Rows*Cols, subitems );
1122  Tcl_SetListObj( obj_result,IT_SIZE, items );
1123  Tcl_Free( (char*)subitems );
1124  return TCL_OK;
1125}
1126
1127/*
1128 * Fill in obj_result the content of the serie variable.
1129 *
1130 */
1131
1132int Tol_GetSerieContent(Tcl_Interp * interp,
1133                        int objc,
1134                        Tcl_Obj *CONST objv[],
1135                        Tcl_Obj * obj_result)
1136{
1137  const BSyntaxObject* var = Tol_ResolveObject(interp,
1138                                               objv[0],
1139                                               obj_result/*,
1140                                               GraSerie()*/);
1141  if (!var) {
1142    return TCL_ERROR;
1143  }
1144
1145  // parse dates arguments
1146 
1147  BDate I0, I1;
1148  int tcl_code;
1149
1150  BUserTimeSerie * serie = (BUserTimeSerie*)var;
1151  serie->ReadData();
1152
1153  if (objc == 1) {
1154    I0 = serie->FirstDate();
1155    I1 = serie->LastDate();
1156  } else {
1157    tcl_code = Tol_ParseDate(interp,Tcl_GetString(objv[1]),I0);
1158    if (tcl_code != TCL_OK) {
1159      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1160      return TCL_ERROR;
1161    }
1162    if (objc == 3) {
1163      tcl_code = Tol_ParseDate(interp,Tcl_GetString(objv[2]),I1);
1164      if (tcl_code != TCL_OK) {
1165        Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1166        return TCL_ERROR;
1167      }
1168    }
1169  }
1170 
1171  if ( !I0.HasValue() )
1172    I0 = BDate::DefaultFirst();
1173  if ( !I1.HasValue() )
1174    I1 = BDate::DefaultLast();
1175
1176  BUserTimeSet * tms;
1177  Tcl_Obj ** obj_array;
1178  int length;
1179
1180  char buffer[1024];
1181
1182  tms = serie->Dating();
1183
1184  if ( !tms ) {
1185    Tcl_AppendStringsToObj(obj_result,"Serie \"",
1186                           Tcl_GetString(objv[0]),
1187                           "\" does not have dating", NULL);
1188    return TCL_ERROR;
1189  }
1190
1191  // ajustamos el intervalo de fechas al fechado
1192
1193  I0 = tms->FirstNoLess(I0);
1194  I1 = tms->FirstNoGreat(I1);
1195  length = tms->Difference(I0,I1)+1;
1196  if ( length <= 0 ) {
1197    Tcl_SetStringObj(obj_result,
1198                     "last date must be greater or equal than first",-1);
1199    return TCL_ERROR;
1200  }
1201
1202  BDat  value;
1203  BText tmp;
1204  Tcl_Obj * subitems[2];
1205
1206  // ++ because we identify the TimeSet as the first element
1207
1208  ++length;
1209  obj_array = (Tcl_Obj**)ckalloc(length*sizeof(Tcl_Obj*));
1210
1211  //tmp = tms->Identify();
1212  GetName(tms, tmp);
1213  obj_array[0] = Tcl_NewStringObj(tmp,-1);
1214  for ( int i = 1; i < length; i++ ) {
1215    tmp = I0.GetText();
1216    subitems[0] = Tcl_NewStringObj(tmp,-1);
1217#if defined(_TOL_FROZEN_)
1218    value = (*serie)[I0];
1219#else
1220    value = (*serie)(I0);
1221#endif
1222    if ( value.IsKnown() )
1223      subitems[1] = Tcl_NewDoubleObj(value.Value());
1224    else
1225      subitems[1] = Tcl_NewStringObj("?",-1);
1226    obj_array[i] = Tcl_NewListObj(2,subitems);
1227    I0 += tms;
1228
1229    sprintf(buffer,"%d",i);
1230    Tcl_VarEval(interp, "puts ", buffer, NULL);
1231  }
1232  Tcl_SetListObj(obj_result,length,obj_array);
1233  Tcl_Free( (char*)obj_array );
1234  return TCL_OK;
1235}
1236
1237int Tol_ParseDate(Tcl_Interp * interp, char * what, BDate & date)
1238{
1239  int    year, month, day, hour, min;
1240  double sec;
1241 
1242  int tcl_code;
1243  Tcl_Obj * tcl_result;
1244  int objc;
1245  Tcl_Obj ** objv;
1246
1247  month = day = 1;
1248  hour  = min = 0;
1249  sec   = 0.0;
1250  char re_pat[] = "{^(?:y([0-9]+)(?:m([0-9]+))?(?:d([0-9]+))?)$}";
1251
1252  tcl_code = Tcl_VarEval(interp, "regexp -inline ", re_pat, " ",what, NULL);
1253  if ( tcl_code != TCL_OK )
1254    return TCL_ERROR;
1255  tcl_result = Tcl_DuplicateObj(Tcl_GetObjResult(interp));
1256  /* this should be a valid list, unless Tcl be corrupt */
1257  Tcl_ListObjGetElements(interp,tcl_result,&objc,&objv);
1258  if ( objc == 0 ) {
1259    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1260                           "invalid date: \"",what,"\"",NULL);
1261    Tcl_DecrRefCount(tcl_result);
1262    return TCL_ERROR;
1263  }
1264
1265  /* and objc must be 4 */
1266
1267  Tcl_GetIntFromObj(interp,objv[1],&year);
1268  Tcl_GetIntFromObj(interp,objv[2],&month);
1269  Tcl_GetIntFromObj(interp,objv[3],&day);
1270
1271  /* now is save to release tcl_result */
1272
1273  Tcl_DecrRefCount(tcl_result);
1274
1275  date.PutDate(year,month,day);
1276  if ( !date.HasValue() ) {
1277    Tcl_ResetResult(interp);
1278    char buffer[1024];
1279    sprintf(buffer,"y%dm%dd%d",year,month,day);
1280    tcl_result = Tcl_GetObjResult(interp);
1281    Tcl_AppendStringsToObj(tcl_result,
1282                           what," = ",buffer," is valid but unknown",NULL);
1283    return TCL_ERROR;
1284  }
1285  return TCL_OK;
1286}
1287
1288/*
1289 * Set the language to be used  by TOL. Fill in obj_result the previous
1290 * language.
1291 *
1292 */
1293
1294int Tol_SetLanguage(Tcl_Interp * interp, Tcl_Obj * lang, Tcl_Obj * obj_result)
1295{
1296  BBool curLang = BText::Language();
1297  BIdiomEnum nextLang;
1298 
1299  char * strLang = Tcl_GetString( lang );
1300  if ( !strcasecmp( strLang, "es" ) )
1301    nextLang = BSPANISH;
1302  else {
1303    /* anything else will be assumed as english */
1304    nextLang = BENGLISH;
1305  }
1306  /* set the previous language as result */
1307  if ( curLang == BSPANISH )
1308    Tcl_SetStringObj( obj_result, "es", -1 );
1309  else
1310    Tcl_SetStringObj( obj_result, "en", -1 );
1311  /* tell TOL what language to use from now on */
1312  BText::PutLanguage( nextLang );
1313  return TCL_OK;
1314}
1315
1316/*
1317 * Return the language used  by TOL. Fill in obj_result the current
1318 * language.
1319 *
1320 */
1321
1322int Tol_GetLanguage(Tcl_Interp * interp, Tcl_Obj * obj_result)
1323{
1324  BBool curLang = BText::Language();
1325 
1326  if ( curLang == BSPANISH )
1327    Tcl_SetStringObj( obj_result, "es", -1 );
1328  else
1329    Tcl_SetStringObj( obj_result, "en", -1 );
1330  return TCL_OK;
1331}
1332
1333/*
1334 * Fill in obj_result the version info corresponding to tol
1335 *
1336 *   {major MajorNum minor MinorNum release ReleaseNum coment Comment}
1337 *
1338 */
1339
1340int Tol_InfoVersion( Tcl_Interp * interp,  Tcl_Obj * obj_result )
1341{
1342#define VERSION_INFO_SIZE 4*2
1343 
1344  Tcl_Obj * items[VERSION_INFO_SIZE];
1345  char buffer[64];
1346
1347  /* Major Info */
1348  items[0] = Tcl_NewStringObj( "major", -1 );
1349  items[1] = Tcl_NewIntObj( VERSION_MAJOR );
1350  /* Minor Info */
1351  items[2] = Tcl_NewStringObj( "minor", -1 );
1352  items[3] = Tcl_NewIntObj( VERSION_MINOR );
1353  /* Release Info */
1354  items[4] = Tcl_NewStringObj( "release", -1 );
1355  sprintf(buffer,"%d", VERSION_RELEASE);
1356  items[5] = Tcl_NewStringObj(buffer, -1);
1357  /* Comment Info */
1358  items[6] = Tcl_NewStringObj( "comment", -1 );
1359  items[7] = Tcl_NewStringObj(TOLVersionBuild(), -1 );
1360  /* asign the items to the result list */
1361  Tcl_SetListObj( obj_result, VERSION_INFO_SIZE, items );
1362  return TCL_OK;
1363}
1364
1365/*
1366 * Fill in obj_result the list of files included in TOL
1367 *
1368 */
1369
1370
1371int Tol_InfoIncluded (Tcl_Interp * interp,Tcl_Obj * obj_result)
1372{
1373  BList* lst = BSetFromFile::Compiled();
1374
1375  BText txt(LstText(lst,"","",","));
1376  return BList2TclList(interp,lst,obj_result,&GetPath,&HasNoSource);
1377}
1378
1379/* OJO con la declaracion de tmpSet */
1380
1381int Tol_InfoFile(Tcl_Interp * interp, Tcl_Obj * file,
1382                 Tcl_Obj * obj_result)
1383{
1384  Tcl_DString dstr;
1385  const BSyntaxObject * so;
1386
1387  Tcl_DStringInit(&dstr);
1388  Tcl_UtfToExternalDString(NULL,Tcl_GetString(file),-1,&dstr);
1389 
1390  BText fname(Tcl_DStringValue(&dstr));
1391  so = (const BSyntaxObject*)BSetFromFile::FindCompiled(fname);
1392  Tcl_DStringFree(&dstr);
1393  if (!so) {
1394    Tcl_AppendStringsToObj(obj_result,"file \"",
1395                           Tcl_GetString(file),
1396                           "\" isn't included", NULL );
1397    return TCL_ERROR;
1398  }
1399  Tcl_Obj * info[6];
1400  /* adicionar la informacion del subtype y si tiene algun set
1401   * como descendiente
1402   */
1403  BText soInfo(so->Info());
1404  BText soPath(so->SourcePath());
1405  BText soDesc(so->Description());
1406
1407  char * pch = soInfo;
1408  if (pch) pch = skipWhite(pch);
1409  else pch = "";
1410
1411  Tcl_ExternalToUtfDString(NULL,pch,-1,&dstr);
1412  info[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1413  Tcl_DStringFree(&dstr);
1414
1415  Tcl_ExternalToUtfDString(NULL,soPath,-1,&dstr);
1416  info[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1417  Tcl_DStringFree(&dstr);
1418
1419  Tcl_ExternalToUtfDString(NULL,soDesc,-1,&dstr);
1420  info[2] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1421  Tcl_DStringFree(&dstr);
1422
1423  /* HAS SUBSET */
1424  BSet * ptrSet = &(((BUserSet*)so)->Contens());
1425  int tmpCard = ptrSet->Card();
1426  int j;
1427  for (j=1; j<=tmpCard; ++j )
1428    if (ContainerGetSet((*ptrSet)[j]))
1429      break;
1430  info[3] = Tcl_NewIntObj(j<=tmpCard);
1431   
1432  /* SUBTYPE INFO */
1433  info[4] = Tcl_NewIntObj( ptrSet->SubType() );
1434  /* STRUCTURE */
1435  info[5] = Tcl_NewStringObj( NULL, 0 );
1436  Tcl_SetListObj(obj_result, 6, info);
1437  return TCL_OK;
1438}
1439
1440/*
1441 * Fill in obj_result the result of evaluating including the file
1442 * given as argument: the absolute path.
1443 *
1444 */
1445
1446int Tol_IncludeFile(Tcl_Interp * interp,Tcl_Obj * obj_file,Tcl_Obj * obj_result)
1447{
1448  Tcl_DString dstr;
1449  BText fName;
1450
1451  Tcl_DStringInit(&dstr);
1452  fName = Tcl_UtfToExternalDString(NULL,Tcl_GetString(obj_file),-1,&dstr);
1453  BSetFromFile* uSet = (BSetFromFile*)BSetFromFile::FindCompiled(fName);
1454  Tcl_DStringFree(&dstr);
1455
1456  if(uSet) {
1457    DESTROY(uSet);
1458  }
1459  IncludeFile(fName);
1460  return TCL_OK;
1461}
1462
1463int Tol_DecompileFile( Tcl_Interp * interp,
1464                       Tcl_Obj * obj_file,
1465                       Tcl_Obj * obj_result )
1466{
1467  Tcl_DString dstr;
1468  BText fName;
1469
1470  Tcl_DStringInit(&dstr);
1471  fName = Tcl_UtfToExternalDString(NULL,Tcl_GetString(obj_file),-1,&dstr);
1472  BSetFromFile* uSet = (BSetFromFile*)BSetFromFile::FindCompiled(fName);
1473  Tcl_DStringFree(&dstr);
1474
1475  if(uSet) {
1476    DESTROY(uSet);
1477  } else {
1478    Tcl_AppendStringsToObj( obj_result, "file '",
1479                            Tcl_GetString(obj_file),
1480                            "' is not compiled", NULL );
1481    return TCL_ERROR;
1482  }
1483  if ( uSet ) {
1484    Tcl_AppendStringsToObj( obj_result, "could not decompile file '",
1485                            Tcl_GetString(obj_file), "'", NULL );
1486    return TCL_ERROR;
1487  }
1488  return TCL_OK;
1489}
1490/*
1491 *
1492 * Fill in obj_result the list of grammars defined in TOL
1493 *
1494 */
1495
1496int Tol_SetGrammarsObj(Tcl_Interp * interp, Tcl_Obj * obj_result )
1497{
1498
1499  BList* lstGra = BGrammar::Instances();
1500
1501  if (BList2TclList(interp,lstGra,obj_result,&GetName,&ExcludeAnything)==TCL_OK) {
1502    Tcl_Obj * name = Tcl_NewStringObj("Anything", -1);
1503    if (Tcl_ListObjAppendElement(interp,obj_result,name) != TCL_OK) {
1504      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1505      return TCL_ERROR;
1506    }
1507    if (QuickSort(interp,obj_result) != TCL_OK) {
1508      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1509      return TCL_ERROR;
1510    }
1511    return TCL_OK;
1512  }
1513  Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1514  return TCL_ERROR;
1515}
1516
1517/*
1518 *
1519 * Fill in obj_result the description of gra_name.
1520 *
1521 */
1522
1523int Tol_SetGrammarDescObj(Tcl_Interp * interp, Tcl_Obj * gra_name,
1524                          Tcl_Obj * obj_result )
1525{
1526  BGrammar * gra = BGrammar::FindByName(Tcl_GetString(gra_name));
1527
1528  if (gra) {
1529    BText desc(gra->Description());
1530    Tcl_SetStringObj(obj_result, desc, -1);
1531    return TCL_OK;
1532  }
1533  Tcl_AppendStringsToObj( obj_result, "\"",
1534                          Tcl_GetString(gra_name),
1535                          "\" isn't a grammar", NULL );
1536  return TCL_ERROR;
1537}
1538
1539/*
1540 *  Tol_FillFunctionInfo --
1541 *
1542 *    Used in Tol_SetFunctionsObj & Tol_SetFunctionInfoObj to return the info
1543 *    for the function requested.
1544 */
1545
1546static
1547int Tol_FillFunctionInfo(BOperator * opr, Tcl_Obj * obj_result)
1548{
1549  Tcl_Obj * info[3];
1550  Tcl_DString dstr_info;
1551  Tcl_DString dstr;
1552
1553  Tcl_DStringInit(&dstr_info);
1554  BText args(opr->Arguments());
1555 
1556  if(args.Last()!='}') // name doesn't comes within the arguments expression
1557  {   
1558      // grammar name
1559      Tcl_DStringAppend(&dstr_info, opr->Grammar()->Name(), -1);
1560      Tcl_DStringAppend(&dstr_info, " ", -1);
1561      // function name
1562      Tcl_DStringInit(&dstr);
1563      Tcl_ExternalToUtfDString(NULL, opr->FullName(), -1, &dstr);
1564      Tcl_DStringAppend(&dstr_info, Tcl_DStringValue(&dstr), -1);
1565      Tcl_DStringFree(&dstr);
1566  }
1567
1568  Tcl_ExternalToUtfDString(NULL,args.String(),-1,&dstr);
1569  Tcl_DStringAppend(&dstr_info, Tcl_DStringValue(&dstr), -1);
1570  Tcl_DStringFree(&dstr);
1571  info[0] = Tcl_NewStringObj(Tcl_DStringValue(&dstr_info), -1);
1572  Tcl_DStringFree(&dstr_info);
1573  Tcl_ExternalToUtfDString(NULL,opr->SourcePath(),-1,&dstr);
1574  info[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1575  Tcl_DStringFree(&dstr);
1576  Tcl_ExternalToUtfDString(NULL,opr->Description(),-1,&dstr);
1577  info[2] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1578  Tcl_DStringFree(&dstr);
1579  Tcl_SetListObj(obj_result, 3, info);
1580  return TCL_OK;
1581}
1582
1583/*
1584 *
1585 * Fill in obj_result the functions defined for grammar gra_name.  If gra_name
1586 * is a list it is considered as an object reference {type ?name? i1 ... ik}
1587 *
1588 */
1589
1590int Tol_SetFunctionsObj (Tcl_Interp * interp, Tcl_Obj * gra_name,
1591                         Tcl_Obj * obj_result)
1592{
1593  int length = 0;
1594 
1595  if (Tcl_ListObjLength(interp,gra_name,&length)!=TCL_OK) {
1596    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1597    return TCL_ERROR;
1598  }
1599  if (length>1) {
1600    const BSyntaxObject *syn;
1601    if (!(syn=Tol_ResolveObject(interp, gra_name, obj_result))) {
1602      return TCL_ERROR;
1603    }
1604   
1605    if (syn->Grammar() != GraCode()) {
1606      Tcl_AppendStringsToObj(obj_result, "'", Tcl_GetString(gra_name),
1607                             "' is not a function object", NULL);
1608      return TCL_ERROR;
1609    }
1610    BOperator * opr =  ((BGraContens<BCode>*)syn)->Contens().Operator();
1611    return Tol_FillFunctionInfo(opr, obj_result);
1612  }
1613  /* gra_name should be a grammar name */
1614  if (!strcmp(Tcl_GetString(gra_name), "Anything")) {
1615    const BSpFunHash& spf = BSpecialFunction::Instances();
1616    BSpFunHash::const_iterator iter;
1617    for(iter=spf.begin(); iter!=spf.end(); iter++)
1618    {
1619      Tcl_ListObjAppendElement(interp, obj_result,
1620                               Tcl_NewStringObj(iter->second->Name(), -1));
1621    }
1622    if (QuickSort(interp,obj_result) != TCL_OK) {
1623      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1624      return TCL_ERROR;
1625    }
1626    return TCL_OK;
1627  }
1628
1629  BGrammar * gra = BGrammar::FindByName(Tcl_GetString(gra_name));
1630 
1631  if (gra) {
1632    BList * lstOper = gra->GetOperators();
1633    if (BList2TclList(interp,lstOper,obj_result,&GetName) != TCL_OK) {
1634      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1635      DESTROY(lstOper);
1636      return TCL_ERROR;
1637    }
1638    DESTROY(lstOper);
1639    if (QuickSort(interp,obj_result) != TCL_OK) {
1640      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1641      return TCL_ERROR;
1642    }
1643    return TCL_OK;
1644  }
1645
1646  Tcl_AppendStringsToObj(obj_result, "'",
1647                         Tcl_GetString(gra_name),
1648                         "' isn't a grammar", NULL);
1649  return TCL_ERROR;
1650}
1651
1652static
1653BOperator* TT_FindOperator( const BGrammar *G, const char *expr )
1654{
1655  BOperator* opr = G->FindOperator( expr );
1656  if ( opr ) {
1657    return opr;
1658  }
1659  bool oldEnabled = BOut::Disable();
1660  BSyntaxObject* obj = GraCode( )->BGrammar::LeftEvaluateExpr( expr );
1661  if( oldEnabled ) { BOut::Enable( ); }
1662  if(obj)
1663  {
1664    if(obj->Mode()==BUSERFUNMODE)
1665    {
1666      opr = dynamic_cast<BOperator*>(obj);
1667    }   
1668    if(obj->Mode()==BOBJECTMODE)
1669    {
1670      BUserCode *uc = dynamic_cast<BUserCode*>( obj );
1671      opr = uc->Contens().Operator( );
1672      if(opr && (opr->Grammar( ) != G)) { opr = NULL; }
1673    }
1674  }
1675  return(opr);
1676}
1677
1678/*
1679 * Fill in obj_result the function's prototype and description
1680 * for a given function in a given grammar.
1681 *
1682 */
1683
1684int Tol_SetFunctionInfoObj (Tcl_Obj * gra_name,
1685                            Tcl_Obj * fun_name,
1686                            Tcl_Obj * obj_result)
1687{
1688  Tcl_DString dstr;
1689  Tcl_Obj * info[3];
1690
1691  if (!strcmp(Tcl_GetString(gra_name), "Anything")) {
1692    Tcl_DStringInit(&dstr);
1693    Tcl_UtfToExternalDString(NULL,Tcl_GetString(fun_name),-1,&dstr);
1694    const BSpecialFunction * spf = BSpecialFunction::Get(Tcl_DStringValue(&dstr));
1695    Tcl_DStringFree(&dstr);
1696    if (spf) {
1697      char * name, * args;
1698      size_t len;
1699     
1700      name = ((BText&)spf->Name()).Buffer();
1701      args = ((BText&)spf->Arguments()).Buffer();
1702      len = strlen(args);
1703      if(!len || args[len-1]!='}') {
1704        info[0] = Tcl_NewStringObj("Anything ", -1);
1705        Tcl_AppendStringsToObj(info[0],name,args,NULL);
1706      } else {
1707        info[0] = Tcl_NewStringObj("", -1);;
1708        Tcl_AppendStringsToObj(info[0],args,NULL);
1709      }
1710      info[1] = Tcl_NewStringObj("",-1);
1711      Tcl_ExternalToUtfDString(NULL,spf->Description(),-1,&dstr);
1712      info[2] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1713      Tcl_DStringFree(&dstr);
1714      Tcl_SetListObj(obj_result, 3, info);
1715      return TCL_OK;
1716    }
1717    Tcl_AppendStringsToObj( obj_result, "\"",
1718                            Tcl_GetString(fun_name),
1719                            "\" isn't a function in grammar Anything", NULL );
1720  } else {
1721    BGrammar * gra = BGrammar::FindByName(Tcl_GetString(gra_name));
1722 
1723    if (gra) {
1724      Tcl_DStringInit(&dstr);
1725      Tcl_UtfToExternalDString( NULL, Tcl_GetString( fun_name ), -1, &dstr );
1726      BOperator* opr = TT_FindOperator( gra, Tcl_DStringValue( &dstr ) );
1727      Tcl_DStringFree(&dstr);
1728      if (opr) {
1729        return Tol_FillFunctionInfo(opr, obj_result);
1730      }
1731      // release the previous use of dstr
1732      //Tcl_DStringFree(&dstr);
1733      Tcl_AppendStringsToObj( obj_result, "\"",
1734                              Tcl_GetString(fun_name),
1735                              "\" isn't a function in grammar ",
1736                              Tcl_GetString(gra_name), NULL );
1737    } else
1738      Tcl_AppendStringsToObj( obj_result, "\"",
1739                              Tcl_GetString(gra_name),
1740                              "\" isn't a grammar", NULL );
1741  }
1742  return TCL_ERROR;
1743}
1744
1745/* ojo info debe tener espacio para 7 Tcl_Obj como maximo */
1746/* retorna cuantos Tcl_Obj creo */
1747
1748int SynObj2TclObj( const BSyntaxObject * var, Tcl_Obj * info[] )
1749{
1750  Tcl_DString dstr;
1751  int infoc;
1752
1753  Tcl_DStringInit(&dstr);
1754
1755  /* GRAMMAR */
1756  info[0] = Tcl_NewStringObj(var->Grammar()->Name().String(), -1);
1757   
1758  /* NAME */
1759  BText synname;
1760 
1761  GetName(var, synname);
1762  Tcl_ExternalToUtfDString(NULL,synname,-1,&dstr);
1763  info[1] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1764  Tcl_DStringFree(&dstr);
1765   
1766  /* REST OF FIELDS */
1767 
1768  BText varInfo(var->Info());
1769  BText varPath(var->SourcePath());
1770  BText varDesc(var->Description());
1771 
1772  /* OBJECT CONTENT */
1773  char * pch = varInfo;
1774  if (pch) pch = skipWhite(pch);
1775  else pch = "";
1776 
1777  Tcl_ExternalToUtfDString(NULL,pch,-1,&dstr);
1778  info[2] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1779  Tcl_DStringFree(&dstr);
1780 
1781  /* OBJECT PATH */
1782  Tcl_ExternalToUtfDString(NULL,varPath,-1,&dstr);
1783  info[3] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1784  Tcl_DStringFree(&dstr);
1785 
1786  /* OBJECT DESCRIPTION */
1787  Tcl_ExternalToUtfDString(NULL,varDesc,-1,&dstr);
1788  info[4] = Tcl_NewStringObj(Tcl_DStringValue(&dstr), -1);
1789  Tcl_DStringFree(&dstr);
1790 
1791#ifdef ISFILE_IMPLEMENTED
1792  info[5] = Tcl_NewIntObj(var->IsFile());
1793#else
1794  info[5] = Tcl_NewIntObj(0);
1795#endif
1796  //info[6] = Tcl_NewIntObj(var->System());
1797  BSet *ptrSet;
1798  if ((ptrSet=ContainerGetSet(var))) {
1799    /* HAS SUBSET */
1800    int tmpCard = ptrSet->Card();
1801    int j;
1802    for (j=1; j<=tmpCard; ++j )
1803      if ( (*ptrSet)[j]->Grammar()==GraSet() )
1804        break;
1805    info[6] = Tcl_NewIntObj(j<=tmpCard);
1806     
1807    /* SUBTYPE */
1808    info[7] = Tcl_NewIntObj( ptrSet->SubType() );
1809     
1810    /* STRUCTURE */
1811    if ( ptrSet->Struct() ) {
1812      BText btxt( ptrSet->Struct()->Name() );
1813      Tcl_ExternalToUtfDString(NULL,btxt,-1,&dstr);
1814      info[8] = Tcl_NewStringObj( Tcl_DStringValue(&dstr), -1 );
1815      Tcl_DStringFree( &dstr );
1816    } else
1817      info[8] = Tcl_NewStringObj( NULL, 0 );
1818    infoc = 9;
1819  } else
1820    infoc = 6;
1821 
1822  return infoc;
1823}
1824
1825int Tol_SetVariableInfoObj (Tcl_Obj * gra_name,
1826                            Tcl_Obj * var_name,
1827                            Tcl_Obj * obj_result);
1828
1829/*!
1830 * Fill in obj_result the variables defined for grammar gra_name.
1831 * Or the element info if gra_name is a reference of an element
1832 * of a global container.
1833 */
1834int Tol_SetVariablesObj (Tcl_Interp *interp, Tcl_Obj *gra_name,
1835                         Tcl_Obj *obj_result)
1836{
1837  const BSyntaxObject *syn ;
1838 
1839  int length = 0;
1840  Tcl_Obj ** items;
1841  int tcl_code;
1842 
1843  if (Tcl_ListObjLength(interp,gra_name,&length)!=TCL_OK) {
1844    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1845    return TCL_ERROR;
1846  }
1847  if (length!=1) {
1848    if (length == 2) {
1849      tcl_code = Tcl_ListObjGetElements(interp,gra_name,&length,&items);
1850      assert(tcl_code == TCL_OK);
1851      if (strcmp(Tcl_GetString(items[0]),"Console"))
1852        return Tol_SetVariableInfoObj(items[0], items[1], obj_result);
1853    }
1854    if (!(syn=Tol_ResolveObject(interp, gra_name, obj_result))) {
1855      return TCL_ERROR;
1856    }
1857//    Tcl_DString dstr;
1858    Tcl_Obj * info[9];
1859    int infoc;
1860   
1861    infoc = SynObj2TclObj(syn, info);
1862    Tcl_SetListObj(obj_result,infoc,info);
1863    return TCL_OK;
1864  }
1865  BGrammar *gra = BGrammar::FindByName(Tcl_GetString(gra_name));
1866  if (!gra) {
1867    Tcl_AppendStringsToObj( obj_result, "'",
1868                            Tcl_GetString(gra_name),
1869                            "' isn't a grammar", NULL );
1870    return TCL_ERROR;
1871  }
1872  BList * lstVar = gra->GetVariables();
1873  if (BList2TclList(interp,lstVar,obj_result,&GetIdentify) != TCL_OK) {
1874    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1875    DESTROY(lstVar);
1876    return TCL_ERROR;
1877  }
1878  DESTROY(lstVar);
1879  if (QuickSort(interp,obj_result) != TCL_OK) {
1880    Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
1881    return TCL_ERROR;
1882  }
1883  return TCL_OK;
1884}
1885
1886/*
1887 * Fill in obj_result the variables's description for a given variable
1888 * in a given grammar.
1889 *
1890 */
1891
1892int Tol_SetVariableInfoObj (Tcl_Obj * gra_name,
1893                            Tcl_Obj * var_name,
1894                            Tcl_Obj * obj_result)
1895{
1896  BGrammar * gra = BGrammar::FindByName(Tcl_GetString(gra_name));
1897  Tcl_DString dstr;
1898 
1899  Tcl_DStringInit(&dstr);
1900  if (gra) {
1901    Tcl_UtfToExternalDString(NULL,Tcl_GetString(var_name),-1,&dstr);
1902    const BSyntaxObject* var = gra->FINDVARIABLE(Tcl_DStringValue(&dstr));
1903    Tcl_DStringFree(&dstr);
1904
1905    if (var) {
1906      Tcl_Obj * info[9];
1907      int infoc;
1908      infoc = SynObj2TclObj( var, info );
1909      Tcl_SetListObj(obj_result,infoc,info);
1910//#define __INFO_PRINT_NREFS__
1911#ifdef __INFO_PRINT_NREFS__
1912      printf("NREF = %d\n", var->NRefs());
1913#endif
1914      return TCL_OK;
1915    }
1916    Tcl_AppendStringsToObj( obj_result, "\"",
1917                            Tcl_GetString(var_name),
1918                            "\" isn't a variable in grammar ",
1919                            Tcl_GetString(gra_name), NULL );
1920  } else
1921    Tcl_AppendStringsToObj( obj_result, "\"",
1922                            Tcl_GetString(gra_name),
1923                            "\" isn't a grammar", NULL );
1924  return TCL_ERROR;
1925}
1926
1927/*
1928 * We must be sure that the strings use 7 bit ASCII chararters.
1929 * Otherwise we must take care of the Utf representation.
1930 *
1931 */
1932
1933static
1934int StrObjCompare(const void * O1, const void * O2)
1935{
1936  char * str1 = (*(Tcl_Obj**)O1)->bytes;
1937  char * str2 = (*(Tcl_Obj**)O2)->bytes;
1938  int check1, check2;
1939
1940  check1 = isalpha(str1[0]);
1941  check2 = isalpha(str2[0]);
1942
1943  if ( check1 && !check2 )
1944    return 1;
1945  if ( check2 && !check1 )
1946    return -1;
1947  return strcmp(str1,str2);
1948}
1949
1950static
1951int QuickSort( Tcl_Interp * interp, Tcl_Obj * list )
1952{
1953  Tcl_Obj ** obj_array;
1954  int length;
1955
1956  if (Tcl_ListObjGetElements(interp, list, &length, &obj_array) != TCL_OK) {
1957    return TCL_ERROR;
1958  }
1959  qsort((void*)obj_array, length, sizeof(Tcl_Obj*), &StrObjCompare);
1960  return TCL_OK;
1961}
1962
1963static
1964void Tol_HciWriter( const BText & str )
1965{
1966  Tcl_CmdInfo cmd_info;
1967
1968  if (TT_interp && Tcl_GetCommandInfo(TT_interp,"Tol_HciWriter",&cmd_info) ) {
1969    Tcl_DString dstr;
1970    Tcl_Obj * objv[2];
1971   
1972    Tcl_DStringInit(&dstr);
1973    Tcl_IncrRefCount(objv[0]=Tcl_NewStringObj("Tol_HciWriter",-1));
1974    Tcl_ExternalToUtfDString(NULL, ((BText&)str).Buffer(), -1, &dstr);
1975    Tcl_IncrRefCount(objv[1]=Tcl_NewStringObj(Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr)));
1976    Tcl_DStringFree(&dstr);
1977 
1978    int status = Tcl_EvalObjv(TT_interp, 2, objv, TCL_EVAL_GLOBAL);
1979    if (status != TCL_OK) {
1980      printf("message: %s\n", ((BText&)str).Buffer());
1981      printf("objv[1] : %s\n", Tcl_GetString(objv[1]));
1982      printf("%s\n", TT_interp->result);
1983    }
1984    /* release the objects */
1985    Tcl_DecrRefCount(objv[0]);
1986    Tcl_DecrRefCount(objv[1]);
1987  }
1988}
1989
1990void Tol_InstallHciWriter()
1991{
1992  BOut::PutHciWriter(Tol_HciWriter);
1993  BOut::PutLogHciWriter(Tol_HciWriter);
1994}
1995
1996static
1997void Tol_SerieChart(BList * series, const BText& FileName )
1998{
1999#define CMD_SERIECHART "Tol_SerieChartMethod"
2000#define GRP_NAME "__grptmp_chart__%d"
2001
2002  Tcl_CmdInfo cmd_info;
2003  static int id = 0;
2004
2005  if (TT_interp && Tcl_GetCommandInfo(TT_interp,CMD_SERIECHART,&cmd_info) ) {
2006    Tcl_DString dstr;
2007    Tcl_Obj * objv[3];
2008    Tcl_Obj * obj_result=Tcl_NewObj();
2009    int tcl_result;
2010    char grpname[1024];
2011   
2012    Tcl_IncrRefCount(obj_result);
2013
2014    // first create the group of series
2015    sprintf(grpname, GRP_NAME, ++id);
2016    tcl_result = Tol_CreateSerieGrp(TT_interp, grpname, series, obj_result);
2017    if (tcl_result==TCL_ERROR) {
2018      printf("%s -- error in Tol_CreateSerieGrp: %s\n", CMD_SERIECHART,
2019             Tcl_GetString(obj_result));
2020      Tcl_DecrRefCount(obj_result);
2021      return;
2022    }
2023    // release the obj_result
2024    Tcl_DecrRefCount(obj_result);   
2025    // chart command
2026    Tcl_IncrRefCount(objv[0]=Tcl_NewStringObj(CMD_SERIECHART,-1));
2027    // serie group argument
2028    Tcl_IncrRefCount(objv[1]=Tcl_NewStringObj(grpname,-1));   
2029    // file name argument
2030    Tcl_DStringInit(&dstr);
2031    Tcl_ExternalToUtfDString(NULL, ((BText&)FileName).Buffer(), -1, &dstr);
2032    Tcl_IncrRefCount(objv[2]=Tcl_NewStringObj(Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr)));
2033    Tcl_DStringFree(&dstr);
2034    int status = Tcl_EvalObjv(TT_interp, 3, objv, TCL_EVAL_GLOBAL);
2035    if (status != TCL_OK) {
2036      printf("%s -- error in Tcl_EvalObjv:\n", CMD_SERIECHART);
2037      printf("%s\n", TT_interp->result);
2038      printf("objv[1] : %s\n", Tcl_GetString(objv[1]));
2039      printf("objv[2] : %s\n", Tcl_GetString(objv[2]));
2040    }
2041    /* release the objects */
2042    for (int i=0; i<3; i++)
2043      Tcl_DecrRefCount(objv[i]);
2044    /* the group of series should be destroyied in the Hook */
2045    /*Tcl_VarEval(TT_interp, "tol::seriegrp destroy ", grpname, NULL);*/
2046  }
2047}
2048
2049int Tol_Tcl_Eval(char * script, const char ** result)
2050{
2051  int status;
2052 
2053  status = Tcl_Eval(TT_interp, script);
2054  *result = Tcl_GetStringResult(TT_interp);
2055  return status==TCL_OK;
2056}
2057
2058Tcl_Obj *TolObj2TclObj(BSyntaxObject *tolObj)
2059{
2060  const char *grammar = tolObj->Grammar()->Name().String();
2061
2062  if (!strcmp(grammar, "Text")) {
2063    const BText &value = Text(tolObj);
2064    return Tcl_NewStringObj(value.String(),-1);
2065  } else if (!strcmp(grammar, "Real")) {
2066    const BDat &value = Dat(tolObj);
2067    return Tcl_NewDoubleObj(value.Value());
2068  } else {
2069    return Tcl_NewStringObj(tolObj->Dump().String(),-1);   
2070  }
2071}
2072
2073int Tol_Tcl_EvalEx(const BSet &Args, const char ** result)
2074{
2075  int status;
2076  Tcl_Obj **objv;
2077  int card = Args.Card();
2078 
2079  if (!Args.Card()) {
2080    *result = "";
2081    status = TCL_OK;
2082  } else {
2083    objv = (Tcl_Obj**)Tcl_Alloc(sizeof(Tcl_Obj*)*card);
2084    for(int i=1; i<=card; i++) {
2085      objv[i-1] = TolObj2TclObj(Args[i]);
2086      Tcl_IncrRefCount(objv[i-1]);
2087    }
2088    status = Tcl_EvalObjv(TT_interp, card, objv, TCL_EVAL_GLOBAL);
2089    *result = Tcl_GetStringResult(TT_interp);
2090    for(int i=0; i<card; i++) {
2091      Tcl_DecrRefCount(objv[i]);
2092    }
2093  }
2094  return status==TCL_OK;
2095}
2096
2097int Tol_StopEvaluation()
2098{
2099  StopFlagOn();
2100  return TCL_OK;
2101}
2102
2103/*
2104 * Fill in obj_result the format .
2105 *
2106 */
2107
2108int Tol_LCFormat(Tcl_Interp*    interp,
2109                 Tcl_Obj *CONST obj_value,
2110                 Tcl_Obj *      obj_result)
2111{
2112  double value;
2113  char buffer[256];
2114 
2115  /* read the double value from tcl obj */
2116  if (Tcl_GetDoubleFromObj(TT_interp, obj_value, &value)==TCL_ERROR)
2117    {
2118      Tcl_AppendObjToObj(obj_result,Tcl_GetObjResult(interp));
2119      return TCL_ERROR;
2120    }
2121  lc_format(value, buffer);
2122  Tcl_AppendStringsToObj(obj_result, buffer, NULL);
2123  return TCL_OK;
2124}
2125
2126void Tol_InstallMethodsHook()
2127{
2128  InstallSerieChartHook(&Tol_SerieChart);
2129  InstallTclEval(&Tol_Tcl_Eval);
2130  InstallTclEvalEx(&Tol_Tcl_EvalEx);
2131}
Note: See TracBrowser for help on using the repository browser.