OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tix/] [generic/] [tixClass.c] - Blame information for rev 1781

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tixClass.c --
3
 *
4
 *      Implements the basic OOP class mechanism for the Tix Intrinsics.
5
 *
6
 * Copyright (c) 1996, Expert Interface Technologies
7
 *
8
 * See the file "license.terms" for information on usage and
9
 * redistribution of this file, and for a DISCLAIMER OF ALL
10
 * WARRANTIES.
11
 *
12
 */
13
 
14
/*
15
 *
16
 * Todo:
17
 *
18
 * (1)  Problems: now a class shares some configspecs with the parent class.
19
 *      If an option is declared as -static in the child class but not
20
 *      in the parent class, the parent class will still see this
21
 *      option as static.
22
 *
23
 */
24
 
25
 
26
#include <tk.h>
27
#include <tixPort.h>
28
#include <tixInt.h>
29
#include <tixItcl.h>
30
 
31
/*
32
 * Access control is not enabled yet.
33
 */
34
#define USE_ACCESS_CONTROL 0
35
 
36
 
37
static void             ClassTableDeleteProc _ANSI_ARGS_((
38
                            ClientData clientData, Tcl_Interp *interp));
39
static TixConfigSpec *  CopySpec _ANSI_ARGS_((TixConfigSpec *spec));
40
static TixClassRecord * CreateClassByName _ANSI_ARGS_((Tcl_Interp * interp,
41
                            char * classRec));
42
static TixClassRecord * CreateClassRecord _ANSI_ARGS_((Tcl_Interp *interp,
43
                            char * classRec, Tk_Window mainWindow,
44
                            int isWidget));
45
static void             FreeClassRecord _ANSI_ARGS_((
46
                            TixClassRecord *cPtr));
47
static void             FreeParseOptions _ANSI_ARGS_((
48
                            TixClassParseStruct * parsePtr));
49
static void             FreeSpec _ANSI_ARGS_((TixConfigSpec *spec));
50
static TixClassRecord * GetClassByName _ANSI_ARGS_((Tcl_Interp * interp,
51
                            char * classRec));
52
static TixConfigSpec *  InitAlias _ANSI_ARGS_((Tcl_Interp *interp,
53
                            TixClassRecord * cPtr, char *s));
54
static int              InitHashEntries _ANSI_ARGS_((
55
                            Tcl_Interp *interp,TixClassRecord * cPtr));
56
static int              InitClass _ANSI_ARGS_((Tcl_Interp * interp,
57
                            char * classRec, TixClassRecord * cPtr,
58
                            TixClassRecord * scPtr,
59
                            TixClassParseStruct * parsePtr));
60
static TixConfigSpec *  InitSpec _ANSI_ARGS_((Tcl_Interp * interp,
61
                            char * s, int isWidget));
62
static int              ParseClassOptions _ANSI_ARGS_((
63
                            Tcl_Interp * interp, char * opts,
64
                            TixClassParseStruct * rec));
65
static int              ParseInstanceOptions _ANSI_ARGS_((
66
                            Tcl_Interp * interp,TixClassRecord * cPtr,
67
                            char *widRec, int argc, char** argv));
68
static int              SetupAlias _ANSI_ARGS_((Tcl_Interp *interp,
69
                            TixClassRecord * cPtr, char *s));
70
static int              SetupAttribute _ANSI_ARGS_((Tcl_Interp *interp,
71
                            TixClassRecord * cPtr, char *s,
72
                            int which));
73
static int              SetupMethod _ANSI_ARGS_((Tcl_Interp *interp,
74
                            TixClassRecord * cPtr, char *s));
75
static int              SetupDefault _ANSI_ARGS_((Tcl_Interp *interp,
76
                            TixClassRecord * cPtr, char *s));
77
#if USE_ACCESS_CONTROL
78
static int              SetupSubWidget _ANSI_ARGS_((Tcl_Interp *interp,
79
                            TixClassRecord * cPtr, char *s));
80
#endif
81
static int              SetupSpec _ANSI_ARGS_((Tcl_Interp *interp,
82
                            TixClassRecord * cPtr, char *s,
83
                            int isWidget));
84
 
85
TIX_DECLARE_CMD(Tix_CreateWidgetCmd);
86
TIX_DECLARE_CMD(Tix_CreateInstanceCmd);
87
TIX_DECLARE_CMD(Tix_InstanceCmd);
88
TIX_DECLARE_CMD(Tix_UninitializedClassCmd);
89
 
90
/*
91
 * Hash tables used to store the classes and class specs.
92
 */
93
 
94
#define GetClassTable(interp) _TixGetHashTable(interp, "tixClassTab",  ClassTableDeleteProc)
95
#define GetSpecTable(interp)  _TixGetHashTable(interp, "tixSpecTab", NULL)
96
 
97
static char * TIX_EMPTY_STRING = "";
98
 
99
 
100
/*----------------------------------------------------------------------
101
 * GetClassByName --
102
 *
103
 *      Return a class struct if it has been created.
104
 *
105
 *----------------------------------------------------------------------
106
 */
107
 
108
static TixClassRecord *
109
GetClassByName(interp, classRec)
110
    Tcl_Interp * interp;
111
    char * classRec;
112
{
113
    Tcl_HashEntry *hashPtr;
114
 
115
    hashPtr = Tcl_FindHashEntry(GetClassTable(interp), classRec);
116
    if (hashPtr) {
117
        return (TixClassRecord *)Tcl_GetHashValue(hashPtr);
118
    } else {
119
        return NULL;
120
    }
121
}
122
 
123
static TixClassRecord *
124
CreateClassByName(interp, classRec)
125
    Tcl_Interp * interp;
126
    char * classRec;
127
{
128
    TixClassRecord * cPtr;
129
    TixInterpState state;
130
 
131
    TixSaveInterpState(interp, &state);
132
    cPtr = GetClassByName(interp, classRec);
133
    if (cPtr == NULL) {
134
        if (Tix_GlobalVarEval(interp, classRec, ":AutoLoad", (char*)NULL)
135
                == TCL_ERROR){
136
            cPtr = NULL;
137
        } else {
138
            cPtr = GetClassByName(interp, classRec);
139
        }
140
    }
141
    TixRestoreInterpState(interp, &state);
142
 
143
    return cPtr;
144
}
145
 
146
/*----------------------------------------------------------------------
147
 * CreateClassRecord --
148
 *
149
 *      Create a class record for the definiton of a new class, or return
150
 *      error if the class already exists.
151
 *
152
 *----------------------------------------------------------------------
153
 */
154
 
155
static TixClassRecord *
156
CreateClassRecord(interp, classRec, mainWindow, isWidget)
157
    Tcl_Interp * interp;
158
    char * classRec;
159
    Tk_Window mainWindow;
160
    int isWidget;
161
{
162
    Tcl_HashEntry *hashPtr;
163
    int isNew;
164
    TixClassRecord * cPtr;
165
 
166
    hashPtr = Tcl_CreateHashEntry(GetClassTable(interp), classRec, &isNew);
167
 
168
    if (isNew) {
169
        cPtr = (TixClassRecord *)ckalloc(sizeof(TixClassRecord));
170
#if USE_ACCESS_CONTROL
171
        cPtr->next       = NULL;
172
#endif
173
        cPtr->superClass = NULL;
174
        cPtr->isWidget   = isWidget;
175
        cPtr->className  = (char*)tixStrDup(classRec);
176
        cPtr->ClassName  = NULL;
177
        cPtr->nSpecs     = 0;
178
        cPtr->specs      = 0;
179
        cPtr->nMethods   = 0;
180
        cPtr->methods    = 0;
181
        cPtr->mainWindow = mainWindow;
182
        cPtr->parsePtr   = NULL;
183
        cPtr->initialized= 0;
184
        Tix_SimpleListInit(&cPtr->unInitSubCls);
185
        Tix_SimpleListInit(&cPtr->subWDefs);
186
 
187
#if USE_ACCESS_CONTROL
188
        Tix_SimpleListInit(&cPtr->subWidgets);
189
#endif
190
 
191
        Tcl_SetHashValue(hashPtr, (char*)cPtr);
192
        return cPtr;
193
    } else {
194
 
195
        /*
196
         * We don't allow redefinition of classes
197
         */
198
 
199
        Tcl_ResetResult(interp);
200
        Tcl_AppendResult(interp, "Class \"", classRec, "\" redefined", NULL);
201
        return NULL;
202
    }
203
}
204
 
205
/*----------------------------------------------------------------------
206
 * Tix_ClassCmd
207
 *
208
 *      Create a class record for a Tix class.
209
 *
210
 * argv[0] = "tixClass" or "tixWidgetClass"
211
 * argv[1] = class
212
 * argv[2] = arglist
213
 *----------------------------------------------------------------------
214
 */
215
 
216
TIX_DEFINE_CMD(Tix_ClassCmd)
217
{
218
    int isWidget, code = TCL_OK;
219
    TixClassParseStruct * parsePtr;
220
    TixClassRecord * cPtr, * scPtr;
221
    char * classRec = argv[1];
222
    Tk_Window mainWindow = (Tk_Window)clientData;
223
    DECLARE_ITCL_NAMESP(nameSp, interp);
224
 
225
    if (strcmp(argv[0], "tixClass")==0) {
226
        isWidget = 0;
227
    } else {
228
        isWidget = 1;
229
    }
230
 
231
    if (argc != 3) {
232
        return Tix_ArgcError(interp, argc, argv, 1, "className {...}");
233
    }
234
    if (!TixItclSetGlobalNameSp(&nameSp, interp)) {
235
        parsePtr = NULL;
236
        code = TCL_ERROR;
237
        goto done;
238
    }
239
 
240
    parsePtr = (TixClassParseStruct *)ckalloc(sizeof(TixClassParseStruct));
241
    if (ParseClassOptions(interp, argv[2], parsePtr) != TCL_OK) {
242
        ckfree((char*)parsePtr);
243
        parsePtr = NULL;
244
        code = TCL_ERROR;
245
        goto done;
246
    }
247
 
248
    cPtr = GetClassByName(interp, classRec);
249
    if (cPtr == NULL) {
250
        cPtr = CreateClassRecord(interp, classRec, mainWindow, isWidget);
251
        if (cPtr == NULL) {
252
            code = TCL_ERROR;
253
            goto done;
254
        }
255
    }
256
    if (cPtr->initialized) {
257
        Tcl_ResetResult(interp);
258
        Tcl_AppendResult(interp, "Class \"", classRec, "\" redefined", NULL);
259
        code = TCL_ERROR;
260
        goto done;
261
    }
262
 
263
    /*
264
     * (2) Set up the superclass
265
     */
266
 
267
    if (!parsePtr->superClass || strlen(parsePtr->superClass) == 0) {
268
        scPtr = NULL;
269
    }
270
    else {
271
        /*
272
         * Create the superclass's record if it does not exist yet.
273
         */
274
        scPtr = GetClassByName(interp, parsePtr->superClass);
275
        if (scPtr == NULL) {
276
            scPtr = CreateClassByName(interp, parsePtr->superClass);
277
            if (scPtr == NULL) {
278
                /*
279
                 * The superclass cannot be autoloaded. We create a
280
                 * empty class record. This record may later be filled
281
                 * by a tixClass call (which may be initiated by a
282
                 * "source" call by the the application, or by SAM).
283
                 */
284
                scPtr = CreateClassRecord(interp, parsePtr->superClass,
285
                        mainWindow, isWidget);
286
                if (scPtr == NULL) {
287
                    code = TCL_ERROR;
288
                    goto done;
289
                }
290
            }
291
        }
292
    }
293
    cPtr->superClass = scPtr;
294
 
295
    if (scPtr == NULL || scPtr->initialized == 1) {
296
        /*
297
         * It is safe to initialized the class now.
298
         */
299
        code = InitClass(interp, classRec, cPtr, scPtr, parsePtr);
300
        FreeParseOptions(parsePtr);
301
        cPtr->parsePtr = NULL;
302
    } else {
303
        /*
304
         * This class has an uninitialized superclass. We wait until the
305
         * superclass is initialized before we initialize this class.
306
         */
307
        Tix_SimpleListAppend(&scPtr->unInitSubCls, (char*)cPtr, 0);
308
        Tcl_CreateCommand(interp, cPtr->className,
309
                Tix_UninitializedClassCmd, (ClientData)cPtr, NULL);
310
        cPtr->parsePtr = parsePtr;
311
    }
312
 
313
done:
314
    TixItclRestoreGlobalNameSp(&nameSp, interp);
315
    if (code == TCL_ERROR) {
316
        if (parsePtr != NULL) {
317
            FreeParseOptions(parsePtr);
318
        }
319
    }
320
    return code;
321
}
322
 
323
static int
324
ParseClassOptions(interp, opts, parsePtr)
325
    Tcl_Interp * interp;
326
    char * opts;
327
    TixClassParseStruct * parsePtr;
328
{
329
    int    i;
330
    char * buff, *s, *p;
331
    int code = TCL_OK;
332
 
333
    parsePtr->alias             = TIX_EMPTY_STRING;
334
    parsePtr->configSpec        = TIX_EMPTY_STRING;
335
    parsePtr->ClassName         = TIX_EMPTY_STRING;
336
    parsePtr->def               = TIX_EMPTY_STRING;
337
    parsePtr->flag              = TIX_EMPTY_STRING;
338
    parsePtr->forceCall         = TIX_EMPTY_STRING;
339
    parsePtr->isStatic          = TIX_EMPTY_STRING;
340
    parsePtr->method            = TIX_EMPTY_STRING;
341
    parsePtr->readOnly          = TIX_EMPTY_STRING;
342
    parsePtr->subWidget         = TIX_EMPTY_STRING;
343
    parsePtr->superClass        = TIX_EMPTY_STRING;
344
    parsePtr->isVirtual         = TIX_EMPTY_STRING;
345
 
346
    parsePtr->optArgv           = NULL;
347
 
348
    /*
349
     * Get rid of the comments
350
     */
351
    buff = (char*)ckalloc((strlen(opts)+1) * sizeof(char));
352
    for (s=opts,p=buff; *s;) {
353
        /* Skip starting spaces */
354
        while (isspace(*s)) {
355
            s++;
356
        }
357
        if (*s == '#') {
358
            while (*s && *s != '\n') {
359
                s++;
360
            }
361
            if (*s) {
362
                s++;
363
            }
364
            continue;
365
        }
366
        while (*s && *s != '\n') {
367
            *p++ = *s++;
368
        }
369
        if (*s) {
370
            *p++ = *s++;
371
        }
372
    }
373
    *p = '\0';
374
 
375
    if (Tcl_SplitList(interp, buff, &parsePtr->optArgc, &parsePtr->optArgv)
376
            != TCL_OK) {
377
        code = TCL_ERROR;
378
        goto done;
379
    }
380
 
381
    if ((parsePtr->optArgc %2) == 1) {
382
        Tcl_AppendResult(interp, "value for \"",
383
                parsePtr->optArgv[parsePtr->optArgc-1],
384
                "\" missing", (char*)NULL);
385
        code = TCL_ERROR;
386
        goto done;
387
    }
388
    for (i=0; i<parsePtr->optArgc; i+=2) {
389
        if (strcmp(parsePtr->optArgv[i], "-alias") == 0) {
390
            parsePtr->alias = parsePtr->optArgv[i+1];
391
        }
392
        else if (strcmp(parsePtr->optArgv[i], "-configspec") == 0) {
393
            parsePtr->configSpec = parsePtr->optArgv[i+1];
394
        }
395
        else if (strcmp(parsePtr->optArgv[i], "-classname") == 0) {
396
            parsePtr->ClassName = parsePtr->optArgv[i+1];
397
        }
398
        else if (strcmp(parsePtr->optArgv[i], "-default") == 0) {
399
            parsePtr->def = parsePtr->optArgv[i+1];
400
        }
401
        else if (strcmp(parsePtr->optArgv[i], "-flag") == 0) {
402
            parsePtr->flag = parsePtr->optArgv[i+1];
403
        }
404
        else if (strcmp(parsePtr->optArgv[i], "-forcecall") == 0) {
405
            parsePtr->forceCall = parsePtr->optArgv[i+1];
406
        }
407
        else if (strcmp(parsePtr->optArgv[i], "-method") == 0) {
408
            parsePtr->method = parsePtr->optArgv[i+1];
409
        }
410
        else if (strcmp(parsePtr->optArgv[i], "-readonly") == 0) {
411
            parsePtr->readOnly = parsePtr->optArgv[i+1];
412
        }
413
        else if (strcmp(parsePtr->optArgv[i], "-static") == 0) {
414
            parsePtr->isStatic = parsePtr->optArgv[i+1];
415
        }
416
#if USE_ACCESS_CONTROL
417
        else if (strcmp(parsePtr->optArgv[i], "-subwidget") == 0) {
418
            parsePtr->subWidget = parsePtr->optArgv[i+1];
419
        }
420
#endif
421
        else if (strcmp(parsePtr->optArgv[i], "-superclass") == 0) {
422
            parsePtr->superClass = parsePtr->optArgv[i+1];
423
        }
424
        else if (strcmp(parsePtr->optArgv[i], "-virtual") == 0) {
425
            parsePtr->isVirtual = parsePtr->optArgv[i+1];
426
        }
427
        else {
428
            Tcl_AppendResult(interp, "unknown parsePtr->option \"",
429
                parsePtr->optArgv[i], "\"", (char*)NULL);
430
            code = TCL_ERROR;
431
            goto done;
432
        }
433
    }
434
 
435
  done:
436
    if (code != TCL_OK) {
437
        if (parsePtr->optArgv != NULL) {
438
            ckfree((char*)parsePtr->optArgv);
439
            parsePtr->optArgv = NULL;
440
        }
441
    }
442
    ckfree((char*)buff);
443
    return code;
444
}
445
 
446
static void
447
FreeParseOptions(parsePtr)
448
    TixClassParseStruct * parsePtr;
449
{
450
    if (parsePtr->optArgv) {
451
        ckfree((char*)parsePtr->optArgv);
452
    }
453
    ckfree((char*)parsePtr);
454
}
455
 
456
/*----------------------------------------------------------------------
457
 * InitClass --
458
 *
459
 *      Initialize the class record using the arguments supplied by the
460
 *      tixClass and tixWidgetClass commands.
461
 *
462
 * Results:
463
 *      Standard Tcl result.
464
 *
465
 * Side effects:
466
 *      The given class is initialized.
467
 *----------------------------------------------------------------------
468
 */
469
 
470
static int
471
InitClass(interp, classRec, cPtr, scPtr, parsePtr)
472
    Tcl_Interp * interp;
473
    char * classRec;
474
    TixClassRecord * cPtr;
475
    TixClassRecord * scPtr;
476
    TixClassParseStruct * parsePtr;
477
{
478
    int code = TCL_OK;
479
    int i, flag;
480
    int isWidget = cPtr->isWidget;
481
    Tix_ListIterator li;
482
    TixClassRecord * subPtr;
483
 
484
    cPtr->ClassName = (char*)tixStrDup(parsePtr->ClassName);
485
 
486
    /*
487
     * (3) Set up the methods.
488
     */
489
    if (SetupMethod(interp, cPtr, parsePtr->method) != TCL_OK) {
490
        code = TCL_ERROR;
491
        goto done;
492
    }
493
 
494
    /* (4) Set up the major configspecs */
495
    if (SetupSpec(interp, cPtr, parsePtr->configSpec, isWidget) != TCL_OK) {
496
        code = TCL_ERROR;
497
        goto done;
498
    }
499
 
500
    /*
501
     * (5) Set up the aliases
502
     */
503
 
504
    /* (5.1)Create the alias configSpec's */
505
    if (parsePtr->alias && *parsePtr->alias) {
506
        if (SetupAlias(interp, cPtr, parsePtr->alias) != TCL_OK) {
507
            code = TCL_ERROR;
508
            goto done;
509
        }
510
    }
511
 
512
    /*
513
     * We are done with the class record. Now let's put the flags into
514
     * a hash table so then they can be retrived quickly whenever we call
515
     * the "$widget config" method
516
     */
517
 
518
    if (InitHashEntries(interp, cPtr)!=TCL_OK) {
519
        code = TCL_ERROR;
520
        goto done;
521
    }
522
 
523
    /*
524
     * (5.2) Initialize the alias configSpec's
525
     */
526
    for (i=0; i<cPtr->nSpecs; i++) {
527
        if (cPtr->specs[i]->isAlias) {
528
            cPtr->specs[i]->realPtr =
529
              Tix_FindConfigSpecByName(interp, cPtr, cPtr->specs[i]->dbName);
530
        }
531
    }
532
 
533
    /*
534
     * (6) Set up the attributes of the specs
535
     */
536
    if (parsePtr->isStatic  && *parsePtr->isStatic) {
537
        if (SetupAttribute(interp, cPtr, parsePtr->isStatic, FLAG_STATIC)
538
                != TCL_OK) {
539
            code = TCL_ERROR;
540
            goto done;
541
        }
542
    }
543
    if (parsePtr->readOnly  && *parsePtr->readOnly) {
544
        if (SetupAttribute(interp,cPtr,parsePtr->readOnly, FLAG_READONLY)
545
                !=TCL_OK) {
546
            code = TCL_ERROR;
547
            goto done;
548
        }
549
    }
550
    if (parsePtr->forceCall  && *parsePtr->forceCall) {
551
        if (SetupAttribute(interp,cPtr,parsePtr->forceCall,FLAG_FORCECALL)
552
                !=TCL_OK) {
553
            code = TCL_ERROR;
554
            goto done;
555
        }
556
    }
557
 
558
    /* (7) Record the default options */
559
    if (SetupDefault(interp, cPtr, parsePtr->def) != TCL_OK) {
560
        code = TCL_ERROR;
561
        goto done;
562
    }
563
 
564
#if USE_ACCESS_CONTROL
565
    /* (8) Set up the SubWidget specs */
566
    if (isWidget) {
567
        if (SetupSubWidget(interp, cPtr, parsePtr->subWidget) != TCL_OK) {
568
            code = TCL_ERROR;
569
            goto done;
570
        }
571
    }
572
#endif
573
 
574
    /*
575
     * Set up the TCL array variable to store some information about the
576
     * class. This is compatible with the old Tix and it also speeds up
577
     * some operations because the look-up of these variables are done
578
     * by hash tables.
579
     */
580
    flag = TCL_GLOBAL_ONLY;
581
    if (parsePtr->superClass) {
582
        Tcl_SetVar2(interp, classRec, "superClass", parsePtr->superClass,flag);
583
    } else {
584
        Tcl_SetVar2(interp, classRec, "superClass", "", flag);
585
    }
586
 
587
    Tcl_SetVar2(interp, classRec, "className",     classRec,            flag);
588
    Tcl_SetVar2(interp, classRec, "ClassName",     parsePtr->ClassName, flag);
589
    Tcl_SetVar2(interp, classRec, "options",       parsePtr->flag,      flag);
590
    Tcl_SetVar2(interp, classRec, "forceCall",     parsePtr->forceCall, flag);
591
    Tcl_SetVar2(interp, classRec, "defaults",      parsePtr->def   ,    flag);
592
    Tcl_SetVar2(interp, classRec, "methods",       parsePtr->method,    flag);
593
    Tcl_SetVar2(interp, classRec, "staticOptions", parsePtr->isStatic,  flag);
594
 
595
    if (parsePtr->isVirtual) {
596
        Tcl_SetVar2(interp, classRec, "virtual",   "1",        flag);
597
    } else {
598
        Tcl_SetVar2(interp, classRec, "virtual",   "0",        flag);
599
    }
600
 
601
    if (isWidget) {
602
        Tcl_SetVar2(interp, classRec, "isWidget",  "1",        flag);
603
    } else {
604
        Tcl_SetVar2(interp, classRec, "isWidget",  "0",        flag);
605
    }
606
 
607
    /*
608
     * Now create the instantiation command.
609
     */
610
    if (isWidget) {
611
        Tcl_CreateCommand(interp, cPtr->className, Tix_CreateWidgetCmd,
612
                (ClientData)cPtr, NULL);
613
    } else {
614
        Tcl_CreateCommand(interp, cPtr->className, Tix_CreateInstanceCmd,
615
                (ClientData)cPtr, NULL);
616
    }
617
 
618
    /*
619
     * Create an "AutoLoad" command. This is needed so that class
620
     * definitions can be auto-loaded properly
621
     */
622
    if (Tix_GlobalVarEval(interp, "proc ", cPtr->className, ":AutoLoad {} {}",
623
            (char *) NULL) != TCL_OK) {
624
        code = TCL_ERROR;
625
        goto done;
626
    }
627
 
628
    cPtr->initialized = 1;
629
 
630
    /*
631
     * Complete the initialization of all the partially initialized
632
     * sub-classes.
633
     */
634
 
635
    Tix_SimpleListIteratorInit(&li);
636
    for (Tix_SimpleListStart(&cPtr->unInitSubCls, &li);
637
             !Tix_SimpleListDone(&li);
638
             Tix_SimpleListNext(&cPtr->unInitSubCls, &li)) {
639
 
640
        subPtr = (TixClassRecord*)li.curr;
641
        code = InitClass(interp, subPtr->className, subPtr, cPtr,
642
                subPtr->parsePtr);
643
 
644
        if (code == TCL_OK) {
645
            if (subPtr->parsePtr) {
646
                FreeParseOptions(subPtr->parsePtr);
647
            }
648
            subPtr->parsePtr = NULL;
649
            Tix_SimpleListDelete(&cPtr->unInitSubCls, &li);
650
        } else {
651
            /*
652
             * (ToDo) Tix is not in a stable state. Some variables
653
             * have not been freed.
654
             */
655
            goto done;
656
        }
657
    }
658
 
659
  done:
660
    return code;
661
}
662
 
663
/*
664
 *----------------------------------------------------------------------
665
 * FreeClassRecord --
666
 *
667
 *      Frees the data associated with a class.
668
 *
669
 * Results:
670
 *      None.
671
 *
672
 * Side effects:
673
 *      The Tix_InstanceCmd cannot be called afterwards.
674
 *----------------------------------------------------------------------
675
 */
676
 
677
static void
678
FreeClassRecord(cPtr)
679
    TixClassRecord *cPtr;
680
{
681
    int i;
682
    Tix_ListIterator li;
683
 
684
    if (cPtr->className) {
685
        ckfree(cPtr->className);
686
    }
687
    if (cPtr->ClassName) {
688
        ckfree(cPtr->ClassName);
689
    }
690
    for (i=0; i<cPtr->nSpecs; i++) {
691
        FreeSpec(cPtr->specs[i]);
692
    }
693
    if (cPtr->specs) {
694
        ckfree((char*)cPtr->specs);
695
    }
696
    for (i=0; i<cPtr->nMethods; i++) {
697
        ckfree(cPtr->methods[i]);
698
    }
699
    if (cPtr->methods) {
700
        ckfree((char*)cPtr->methods);
701
    }
702
 
703
    Tix_SimpleListIteratorInit(&li);
704
    for (Tix_SimpleListStart(&cPtr->unInitSubCls, &li);
705
             !Tix_SimpleListDone(&li);
706
             Tix_SimpleListNext(&cPtr->unInitSubCls, &li)) {
707
        Tix_SimpleListDelete(&cPtr->unInitSubCls, &li);
708
    }
709
    Tix_SimpleListIteratorInit(&li);
710
    for (Tix_SimpleListStart(&cPtr->subWDefs, &li);
711
             !Tix_SimpleListDone(&li);
712
             Tix_SimpleListNext(&cPtr->subWDefs, &li)) {
713
 
714
        Tix_SubwidgetDef * defPtr = (Tix_SubwidgetDef*)li.curr;
715
        Tix_SimpleListDelete(&cPtr->subWDefs, &li);
716
 
717
        ckfree((char*)defPtr->spec);
718
        ckfree((char*)defPtr->value);
719
        ckfree((char*)defPtr);
720
    }
721
 
722
    if (cPtr->parsePtr) {
723
        FreeParseOptions(cPtr->parsePtr);
724
    }
725
 
726
    ckfree((char*)cPtr);
727
}
728
 
729
TIX_DEFINE_CMD(Tix_UninitializedClassCmd)
730
{
731
    TixClassRecord * cPtr, *scPtr;
732
 
733
    cPtr = (TixClassRecord *)clientData;
734
    for (scPtr = cPtr->superClass; scPtr != NULL && scPtr->superClass != NULL;
735
            scPtr = scPtr->superClass) {
736
        ;
737
    }
738
    if (scPtr != NULL) {
739
        Tcl_AppendResult(interp, "Superclass \"", scPtr->className,
740
                "\" not defined", NULL);
741
    } else {
742
        Tcl_AppendResult(interp, "Unknown Tix internal error", NULL);
743
    }
744
 
745
    return TCL_ERROR;
746
}
747
 
748
 
749
/*----------------------------------------------------------------------
750
 * Tix_CreateInstanceCmd --
751
 *
752
 *      Create an instance object of a normal Tix class.
753
 *
754
 * argv[0]  = object name.
755
 * argv[1+] = args
756
 *----------------------------------------------------------------------
757
 */
758
 
759
TIX_DEFINE_CMD(Tix_CreateInstanceCmd)
760
{
761
    TixClassRecord * cPtr;
762
    char * widRec;
763
    int i, code = TCL_OK;
764
    TixConfigSpec * spec;
765
    char * value;
766
    DECLARE_ITCL_NAMESP(nameSp, interp);
767
 
768
    if (argc <= 1) {
769
        return Tix_ArgcError(interp, argc, argv, 1, "name ?arg? ...");
770
    }
771
 
772
    cPtr = (TixClassRecord *)clientData;
773
    widRec = argv[1];
774
 
775
    if (!TixItclSetGlobalNameSp(&nameSp, interp)) {
776
        code = TCL_ERROR;
777
        goto done;
778
    }
779
 
780
    Tcl_SetVar2(interp, widRec, "className", cPtr->className, TCL_GLOBAL_ONLY);
781
    Tcl_SetVar2(interp, widRec, "ClassName", cPtr->ClassName, TCL_GLOBAL_ONLY);
782
    Tcl_SetVar2(interp, widRec, "context",   cPtr->className, TCL_GLOBAL_ONLY);
783
 
784
    /* This is the command that access the widget */
785
    Tcl_CreateCommand(interp, widRec, Tix_InstanceCmd,
786
        (ClientData)cPtr, NULL);
787
 
788
    /* Set up the widget record according to defaults and arguments */
789
    ParseInstanceOptions(interp, cPtr, widRec, argc-2, argv+2);
790
 
791
    /* Call the constructor method */
792
    if (Tix_CallMethod(interp, cPtr->className, widRec, "Constructor",
793
                0, 0) != TCL_OK) {
794
        code = TCL_ERROR;
795
        goto done;
796
    }
797
 
798
    /*
799
     * %% warning. configuration methods for -forcecall options must
800
     * *not* assume that the value in the widget record has been
801
     * validated!
802
     *
803
     * todo: please explain the above in the programming guide.
804
     */
805
    for (i=0; i<cPtr->nSpecs; i++) {
806
        spec = cPtr->specs[i];
807
        if (spec->forceCall) {
808
          value = Tcl_GetVar2(interp, widRec, spec->argvName,
809
              TCL_GLOBAL_ONLY);
810
          if (Tix_CallConfigMethod(interp, cPtr, widRec, spec, value)!=TCL_OK){
811
              code = TCL_ERROR;
812
              goto done;
813
          }
814
        }
815
    }
816
 
817
    Tcl_SetResult(interp, widRec, TCL_VOLATILE);
818
 
819
  done:
820
    TixItclRestoreGlobalNameSp(&nameSp, interp);
821
    return code;
822
}
823
 
824
/*----------------------------------------------------------------------
825
 * Tix_InstanceCmd
826
 *
827
 *      Redirect the method calls to the class methods
828
 *
829
 * argv[0]  = widget name
830
 * argv[1]  = method name
831
 * argv[2+] = arglist
832
 */
833
TIX_DEFINE_CMD(Tix_InstanceCmd)
834
{
835
    TixClassRecord * cPtr;
836
    char * widRec = argv[0];
837
    char * method = argv[1];
838
    char * classRec;
839
    char * methodName;          /* full name of the method -- method may be
840
                                 * abbreviated */
841
    int len;
842
    int code;
843
    DECLARE_ITCL_NAMESP(nameSp, interp);
844
 
845
    cPtr = (TixClassRecord *)clientData;
846
    classRec = cPtr->className;
847
 
848
    if (argc <= 1) {
849
        return Tix_ArgcError(interp, argc, argv, 1, "option ...");
850
    }
851
 
852
    Tk_Preserve((ClientData) cPtr);
853
    if (!TixItclSetGlobalNameSp(&nameSp, interp)) {
854
        code = TCL_ERROR;
855
        goto done;
856
    }
857
 
858
    len = strlen(method);
859
 
860
    if ((methodName = Tix_FindPublicMethod(interp, cPtr, method)) == NULL) {
861
        code = Tix_UnknownPublicMethodError(interp, cPtr, widRec, method);
862
        goto done;
863
    }
864
 
865
    if (Tix_CallMethod(interp, classRec, widRec, methodName,
866
            argc-2, argv+2) == TCL_OK) {
867
        code = TCL_OK;
868
        goto done;
869
    }
870
    /*
871
     * We will have an "unknown error" return value here, now
872
     * try to execute the command as a "Intrinsics" command
873
     *          configure, cget, subwidget or subwidgets
874
     */
875
    else if (strncmp(method, "configure", len) == 0) {
876
        Tcl_ResetResult(interp);
877
 
878
        if (argc==2) {
879
            code = Tix_QueryAllOptions(interp, cPtr, widRec);
880
            goto done;
881
        }
882
        else if (argc == 3) {
883
            code = Tix_QueryOneOption(interp, cPtr, widRec, argv[2]);
884
            goto done;
885
        } else {
886
            code = Tix_ChangeOptions(interp, cPtr, widRec, argc-2, argv+2);
887
            goto done;
888
        }
889
    }
890
    else if (strncmp(method, "cget", len) == 0) {
891
        Tcl_ResetResult(interp);
892
 
893
        if (argc == 3) {
894
            code = Tix_GetVar(interp, cPtr, widRec, argv[2]);
895
            goto done;
896
        } else {
897
            code = Tix_ArgcError(interp, argc, argv, 2, "-flag");
898
            goto done;
899
        }
900
    }
901
    else if (cPtr->isWidget && strncmp(method, "subwidget", len) == 0) {
902
 
903
#if 0
904
        /* Subwidget protection is not yet implemented */
905
        Tix_SubWidgetSpec * ssPtr;
906
        ssPtr = GetSubWidgetSpec(cPtr, argv[2]);
907
#endif
908
        char * swName, buff[40];
909
 
910
        Tcl_ResetResult(interp);
911
        if (argc >= 3) {
912
            sprintf(buff, "w:%s", argv[2]);
913
            swName = Tcl_GetVar2(interp, widRec, buff, TCL_GLOBAL_ONLY);
914
 
915
            if (swName) {
916
                if (argc == 3) {
917
                    Tcl_SetResult(interp, swName, TCL_VOLATILE);
918
                    code = TCL_OK;
919
                    goto done;
920
                } else {
921
                    argv[2] = swName;
922
                    code = Tix_EvalArgv(interp, argc-2, argv+2);
923
                    goto done;
924
                }
925
            }
926
            Tcl_AppendResult(interp, "unknown subwidget \"", argv[2],
927
                "\"", NULL);
928
            code = TCL_ERROR;
929
            goto done;
930
        } else {
931
            code = Tix_ArgcError(interp, argc, argv, 2, "name ?args ...?");
932
            goto done;
933
        }
934
    }
935
    else if (cPtr->isWidget && strncmp(method, "subwidgets", len) == 0) {
936
        Tcl_ResetResult(interp);
937
 
938
        code = Tix_CallMethod(interp, classRec, widRec, "subwidgets",
939
            argc-2, argv+2);
940
        goto done;
941
    } else {
942
        /*
943
         * error message already append by Tix_CallMethod()
944
         */
945
        code = TCL_ERROR;
946
        goto done;
947
    }
948
 
949
  done:
950
    TixItclRestoreGlobalNameSp(&nameSp, interp);
951
    Tk_Release((ClientData) cPtr);
952
    return code;
953
}
954
 
955
/*----------------------------------------------------------------------
956
 * Subroutines for Class definition
957
 *
958
 *
959
 *----------------------------------------------------------------------
960
 */
961
static int SetupMethod(interp, cPtr, s)
962
    Tcl_Interp * interp;
963
    TixClassRecord * cPtr;
964
    char * s;
965
{
966
    TixClassRecord * scPtr = cPtr->superClass;
967
    char ** listArgv;
968
    int listArgc, i;
969
    int nMethods;
970
 
971
 
972
    if (s && *s) {
973
        if (Tcl_SplitList(interp, s, &listArgc, &listArgv) != TCL_OK) {
974
            return TCL_ERROR;
975
        }
976
    } else {
977
        listArgc = 0;
978
        listArgv = 0;
979
    }
980
 
981
    nMethods = listArgc;
982
 
983
    if (scPtr) {
984
        nMethods += scPtr->nMethods;
985
    }
986
    cPtr->nMethods = nMethods;
987
    cPtr->methods  = (char**)ckalloc(nMethods*sizeof(char*));
988
    /* Copy the methods of this class */
989
    for (i=0; i<listArgc; i++) {
990
        cPtr->methods[i] = (char*)tixStrDup(listArgv[i]);
991
    }
992
    /* Copy the methods of the super class */
993
    for (; i<nMethods; i++) {
994
        cPtr->methods[i] = (char*)tixStrDup(scPtr->methods[i-listArgc]);
995
    }
996
 
997
    if (listArgv) {
998
        ckfree((char*)listArgv);
999
    }
1000
 
1001
    return TCL_OK;
1002
}
1003
 
1004
static int
1005
SetupDefault(interp, cPtr, s)
1006
    Tcl_Interp * interp;
1007
    TixClassRecord * cPtr;
1008
    char * s;
1009
{
1010
    char ** listArgv;
1011
    int listArgc, i;
1012
    TixClassRecord * scPtr = cPtr->superClass;
1013
    Tix_ListIterator li;
1014
    Tix_SubwidgetDef *defPtr;
1015
 
1016
    if (s && *s) {
1017
        if (Tcl_SplitList(interp, s, &listArgc, &listArgv) != TCL_OK) {
1018
            return TCL_ERROR;
1019
        }
1020
    } else {
1021
        return TCL_OK;
1022
    }
1023
 
1024
    if (scPtr) {
1025
        /*
1026
         * Copy the subwidget default specs from the super-class
1027
         */
1028
        Tix_SimpleListIteratorInit(&li);
1029
        for (Tix_SimpleListStart(&scPtr->subWDefs, &li);
1030
             !Tix_SimpleListDone(&li);
1031
             Tix_SimpleListNext (&scPtr->subWDefs, &li)) {
1032
 
1033
            Tix_SubwidgetDef * p = (Tix_SubwidgetDef*)li.curr;
1034
 
1035
            defPtr = (Tix_SubwidgetDef*)ckalloc(sizeof(Tix_SubwidgetDef));
1036
            defPtr->spec  = (char*)tixStrDup(p->spec);
1037
            defPtr->value = (char*)tixStrDup(p->value);
1038
 
1039
            Tix_SimpleListAppend(&cPtr->subWDefs, (char*)defPtr, 0);
1040
        }
1041
    }
1042
 
1043
    /*
1044
     * Merge with the new default specs
1045
     */
1046
    for (i=0; i<listArgc; i++) {
1047
        char **list;
1048
        int n;
1049
 
1050
        if (Tcl_SplitList(interp, listArgv[i], &n, &list) != TCL_OK) {
1051
            goto error;
1052
        }
1053
        if (n != 2) {
1054
            Tcl_AppendResult(interp, "bad subwidget default format \"",
1055
                listArgv[i], "\"", NULL);
1056
            ckfree((char*)list);
1057
            goto error;
1058
        }
1059
 
1060
        Tix_SimpleListIteratorInit(&li);
1061
        for (Tix_SimpleListStart(&cPtr->subWDefs, &li);
1062
             !Tix_SimpleListDone(&li);
1063
             Tix_SimpleListNext (&cPtr->subWDefs, &li)) {
1064
 
1065
            Tix_SubwidgetDef * p = (Tix_SubwidgetDef*)li.curr;
1066
 
1067
            if (strcmp(list[0], p->spec) == 0) {
1068
                Tix_SimpleListDelete(&cPtr->subWDefs, &li);
1069
                ckfree((char*)p->value);
1070
                ckfree((char*)p->spec);
1071
                ckfree((char*)p);
1072
                break;
1073
            }
1074
        }
1075
        /* Append this spec to the end
1076
         */
1077
        defPtr = (Tix_SubwidgetDef*)ckalloc(sizeof(Tix_SubwidgetDef));
1078
        defPtr->spec  = (char*)tixStrDup(list[0]);
1079
        defPtr->value = (char*)tixStrDup(list[1]);
1080
 
1081
        Tix_SimpleListAppend(&cPtr->subWDefs, (char*)defPtr, 0);
1082
 
1083
        ckfree((char*)list);
1084
    }
1085
 
1086
    /*
1087
     * Add the defaults into the options database.
1088
     */
1089
    Tix_SimpleListIteratorInit(&li);
1090
    for (Tix_SimpleListStart(&cPtr->subWDefs, &li);
1091
         !Tix_SimpleListDone(&li);
1092
         Tix_SimpleListNext (&cPtr->subWDefs, &li)) {
1093
 
1094
        Tix_SubwidgetDef * p = (Tix_SubwidgetDef*)li.curr;
1095
 
1096
        if (Tix_GlobalVarEval(interp, "option add *", cPtr->ClassName,
1097
                p->spec, " [list ", p->value, "] widgetDefault",
1098
                NULL) != TCL_OK) {
1099
            goto error;
1100
        }
1101
    }
1102
 
1103
    if (listArgv) {
1104
        ckfree((char*)listArgv);
1105
    }
1106
    return TCL_OK;
1107
 
1108
  error:
1109
   if (listArgv) {
1110
        ckfree((char*)listArgv);
1111
    }
1112
    return TCL_ERROR;
1113
}
1114
 
1115
static int
1116
SetupSpec(interp, cPtr, s, isWidget)
1117
    Tcl_Interp * interp;
1118
    TixClassRecord * cPtr;
1119
    char * s;
1120
    int isWidget;
1121
{
1122
    TixClassRecord * scPtr = cPtr->superClass;
1123
    char ** listArgv;
1124
    int listArgc, i;
1125
    TixConfigSpec * dupSpec;
1126
    int nSpecs;
1127
    int j;
1128
    int nAlloc;
1129
    int code = TCL_OK;
1130
 
1131
    if (s && *s) {
1132
        if (Tcl_SplitList(interp, s, &listArgc, &listArgv) != TCL_OK) {
1133
            return TCL_ERROR;
1134
        }
1135
    } else {
1136
        listArgc = 0;
1137
        listArgv = 0;
1138
    }
1139
 
1140
    nSpecs = listArgc;
1141
 
1142
    if (scPtr != NULL) {
1143
        nAlloc = nSpecs+scPtr->nSpecs;
1144
    } else {
1145
        nAlloc = nSpecs;
1146
    }
1147
 
1148
    cPtr->nSpecs = nSpecs;
1149
    cPtr->specs  = (TixConfigSpec**)ckalloc(nAlloc*sizeof(TixConfigSpec*));
1150
 
1151
    /*
1152
     * Initialize the specs of this class
1153
     */
1154
    for (i=0; i<listArgc; i++) {
1155
        if ((cPtr->specs[i] = InitSpec(interp, listArgv[i], isWidget))==NULL){
1156
            code = TCL_ERROR;
1157
            goto done;
1158
        }
1159
    }
1160
    /*
1161
     * Copy the specs of the super class
1162
     */
1163
    if (scPtr != NULL) {
1164
        for (i=0; i<scPtr->nSpecs; i++) {
1165
            /* See if we have re-defined this configspec */
1166
            for (dupSpec = 0, j=0; j<listArgc; j++) {
1167
                char * pName = scPtr->specs[i]->argvName;
1168
                if (strcmp(cPtr->specs[j]->argvName, pName)==0) {
1169
                    dupSpec = cPtr->specs[j];
1170
                    break;
1171
                }
1172
            }
1173
 
1174
            if (dupSpec) {
1175
                /*
1176
                 * If we have not redefined the dbclass or dbname of
1177
                 * this duplicated configSpec, then simply
1178
                 * copy the parent's attributes to the new configSpec
1179
                 *
1180
                 * Otherwise we don't copy the parent's attributes (do nothing)
1181
                 */
1182
                if ((strcmp(dupSpec->dbClass, scPtr->specs[i]->dbClass) == 0)
1183
                    &&(strcmp(dupSpec->dbName, scPtr->specs[i]->dbName) == 0)){
1184
                    dupSpec->readOnly  = scPtr->specs[i]->readOnly;
1185
                    dupSpec->isStatic  = scPtr->specs[i]->isStatic;
1186
                    dupSpec->forceCall = scPtr->specs[i]->forceCall;
1187
                }
1188
            } else {
1189
                /*
1190
                 *Let's copy the parent's configSpec
1191
                 */
1192
                cPtr->specs[cPtr->nSpecs] = CopySpec(scPtr->specs[i]);
1193
                cPtr->nSpecs ++;
1194
            }
1195
        }
1196
    }
1197
 
1198
    if (cPtr->nSpecs != nAlloc) {
1199
        cPtr->specs = (TixConfigSpec**)
1200
          ckrealloc((char*)cPtr->specs, cPtr->nSpecs*sizeof(TixConfigSpec*));
1201
    }
1202
 
1203
  done:
1204
    if (listArgv) {
1205
        ckfree((char*)listArgv);
1206
    }
1207
    return code;
1208
}
1209
 
1210
static TixConfigSpec *
1211
InitSpec(interp, s, isWidget)
1212
    Tcl_Interp * interp;
1213
    char * s;
1214
    int isWidget;
1215
{
1216
    char ** listArgv = NULL;
1217
    int listArgc;
1218
    TixConfigSpec * sPtr = NULL;
1219
    char * specList = NULL;
1220
    char * cmdArgv[2];
1221
 
1222
    /* KLUDGE
1223
     *
1224
     * The following call will try to substitute the contents inside
1225
     * the string s. Since s was originally in curly brackets,
1226
     * setting s to {-bitmap bitmap Bitmap [tix getbitmap mybitmap]}
1227
     * will cause the defValue to be "[tix" because the nested
1228
     * expression is never evaluated.
1229
     *
1230
     */
1231
    cmdArgv[0] = "subst";
1232
    cmdArgv[1] = s;
1233
 
1234
    if (Tix_EvalArgv(interp, 2, cmdArgv)!= TCL_OK) {
1235
        goto done;
1236
    }
1237
 
1238
    specList = (char*)tixStrDup(interp->result);
1239
 
1240
    if (Tcl_SplitList(interp, specList, &listArgc, &listArgv)!= TCL_OK) {
1241
        goto done;
1242
    }
1243
    if (( isWidget && (listArgc < 4 || listArgc > 5)) ||
1244
        (!isWidget && (listArgc < 2 || listArgc > 3))) {
1245
        Tcl_ResetResult(interp);
1246
        Tcl_AppendResult(interp, "Wrong number of elements in ",
1247
            "config spec list \"", specList, "\"", NULL);
1248
        goto done;
1249
    }
1250
 
1251
    sPtr = (TixConfigSpec * )ckalloc(sizeof(TixConfigSpec));
1252
 
1253
    sPtr->isAlias   = 0;
1254
    sPtr->readOnly  = 0;
1255
    sPtr->isStatic  = 0;
1256
    sPtr->forceCall = 0;
1257
    sPtr->realPtr   = NULL;
1258
 
1259
    if (isWidget) {
1260
        sPtr->argvName = (char*)tixStrDup(listArgv[0]);
1261
        sPtr->dbName   = (char*)tixStrDup(listArgv[1]);
1262
        sPtr->dbClass  = (char*)tixStrDup(listArgv[2]);
1263
        sPtr->defValue = (char*)tixStrDup(listArgv[3]);
1264
    }
1265
    else {
1266
        sPtr->argvName = (char*)tixStrDup(listArgv[0]);
1267
        sPtr->dbClass  = TIX_EMPTY_STRING;
1268
        sPtr->dbName   = TIX_EMPTY_STRING;
1269
        sPtr->defValue = (char*)tixStrDup(listArgv[1]);
1270
    }
1271
 
1272
    /* Set up the verifyCmd */
1273
    if ((isWidget && listArgc == 5) || (!isWidget && listArgc == 3)) {
1274
        int n;
1275
 
1276
        if (isWidget) {
1277
            n = 4;
1278
        } else {
1279
            n = 2;
1280
        }
1281
 
1282
        sPtr->verifyCmd = (char*)tixStrDup(listArgv[n]);
1283
    } else {
1284
        sPtr->verifyCmd = NULL;
1285
    }
1286
 
1287
  done:
1288
    if (listArgv) {
1289
        ckfree((char *) listArgv);
1290
    }
1291
    if (specList) {
1292
        ckfree(specList);
1293
    }
1294
    return sPtr;
1295
}
1296
 
1297
static TixConfigSpec *
1298
CopySpec(sPtr)
1299
    TixConfigSpec *sPtr;        /* The spec record from the super class. */
1300
{
1301
    TixConfigSpec *nPtr = (TixConfigSpec *)ckalloc(sizeof(TixConfigSpec));
1302
 
1303
    nPtr->isAlias   = sPtr->isAlias;
1304
    nPtr->readOnly  = sPtr->readOnly;
1305
    nPtr->isStatic  = sPtr->isStatic;
1306
    nPtr->forceCall = sPtr->forceCall;
1307
 
1308
    if (sPtr->argvName != NULL &&  sPtr->argvName != TIX_EMPTY_STRING) {
1309
        nPtr->argvName = (char*)tixStrDup(sPtr->argvName);
1310
    } else {
1311
        nPtr->argvName = TIX_EMPTY_STRING;
1312
    }
1313
    if (sPtr->defValue != NULL &&  sPtr->defValue != TIX_EMPTY_STRING) {
1314
        nPtr->defValue = (char*)tixStrDup(sPtr->defValue);
1315
    } else {
1316
        nPtr->defValue = TIX_EMPTY_STRING;
1317
    }
1318
    if (sPtr->dbName != NULL &&  sPtr->dbName != TIX_EMPTY_STRING) {
1319
        nPtr->dbName = (char*)tixStrDup(sPtr->dbName);
1320
    } else {
1321
        nPtr->dbName = TIX_EMPTY_STRING;
1322
    }
1323
    if (sPtr->dbClass != NULL &&  sPtr->dbClass != TIX_EMPTY_STRING) {
1324
        nPtr->dbClass = (char*)tixStrDup(sPtr->dbClass);
1325
    } else {
1326
        nPtr->dbClass = TIX_EMPTY_STRING;
1327
    }
1328
    if (sPtr->verifyCmd != NULL) {
1329
        nPtr->verifyCmd = (char*)tixStrDup(sPtr->verifyCmd);
1330
    } else {
1331
        nPtr->verifyCmd = NULL;
1332
    }
1333
 
1334
    nPtr->realPtr = NULL;
1335
 
1336
    return nPtr;
1337
}
1338
 
1339
static void
1340
FreeSpec(sPtr)
1341
    TixConfigSpec *sPtr;        /* The spec record to free. */
1342
{
1343
    if (sPtr->argvName != NULL && sPtr->argvName != TIX_EMPTY_STRING) {
1344
        ckfree(sPtr->argvName);
1345
    }
1346
    if (sPtr->defValue != NULL && sPtr->defValue != TIX_EMPTY_STRING) {
1347
        ckfree(sPtr->defValue);
1348
    }
1349
    if (sPtr->dbName   != NULL && sPtr->dbName   != TIX_EMPTY_STRING) {
1350
        ckfree(sPtr->dbName);
1351
    }
1352
    if (sPtr->dbClass  != NULL && sPtr->dbClass  != TIX_EMPTY_STRING) {
1353
        ckfree(sPtr->dbClass);
1354
    }
1355
    if (sPtr->verifyCmd != NULL) {
1356
        ckfree(sPtr->verifyCmd);
1357
    }
1358
    ckfree((char*)sPtr);
1359
}
1360
 
1361
/*
1362
 *----------------------------------------------------------------------
1363
 * SetupAttribute --
1364
 *
1365
 *      Marks the spec's with the given attribute (-readonly, -forcecall,
1366
 *      and -static).
1367
 *
1368
 * Results:
1369
 *      Standard Tcl result.
1370
 *
1371
 * Side effects:
1372
 *      The attributes of the specs are updated.
1373
 *----------------------------------------------------------------------
1374
 */
1375
 
1376
static int
1377
SetupAttribute(interp, cPtr, s, which)
1378
    Tcl_Interp * interp;
1379
    TixClassRecord * cPtr;
1380
    char * s;
1381
    int which;
1382
{
1383
    char ** listArgv;
1384
    int listArgc, i;
1385
    TixConfigSpec  * spec;
1386
 
1387
    if (Tcl_SplitList(interp, s, &listArgc, &listArgv) != TCL_OK) {
1388
        return TCL_ERROR;
1389
    } else {
1390
        for (i=0; i<listArgc; i++) {
1391
            spec = Tix_FindConfigSpecByName(interp, cPtr, listArgv[i]);
1392
            if (spec == NULL) {
1393
                ckfree((char*)listArgv);
1394
                return TCL_ERROR;
1395
            }
1396
            switch(which) {
1397
              case FLAG_READONLY:
1398
                spec->readOnly = 1;
1399
                break;
1400
              case FLAG_STATIC:
1401
                spec->isStatic = 1;
1402
                break;
1403
              case FLAG_FORCECALL:
1404
                spec->forceCall = 1;
1405
                break;
1406
            }
1407
        }
1408
    }
1409
 
1410
    ckfree((char*)listArgv);
1411
    return TCL_OK;
1412
}
1413
 
1414
static int
1415
SetupAlias(interp, cPtr, s)
1416
    Tcl_Interp * interp;
1417
    TixClassRecord * cPtr;
1418
    char * s;
1419
{
1420
    char ** listArgv;
1421
    int listArgc, i;
1422
 
1423
    if (Tcl_SplitList(interp, s, &listArgc, &listArgv) != TCL_OK) {
1424
        return TCL_ERROR;
1425
    } else {
1426
        int nAliases = listArgc;
1427
        int nAlloc = cPtr->nSpecs + nAliases;
1428
 
1429
        cPtr->specs = (TixConfigSpec**)
1430
            ckrealloc((char*)cPtr->specs, nAlloc*sizeof(TixConfigSpec*));
1431
 
1432
        /* Initialize the aliases of this class */
1433
        for (i=cPtr->nSpecs; i<nAlloc; i++) {
1434
            cPtr->specs[i] = InitAlias(interp, cPtr, listArgv[i-cPtr->nSpecs]);
1435
            if (cPtr->specs[i] == NULL) {
1436
                ckfree((char*)listArgv);
1437
                return TCL_ERROR;
1438
            }
1439
        }
1440
 
1441
        cPtr->nSpecs = nAlloc;
1442
    }
1443
    ckfree((char*)listArgv);
1444
    return TCL_OK;
1445
}
1446
 
1447
static TixConfigSpec *
1448
InitAlias(interp, cPtr, s)
1449
    Tcl_Interp * interp;
1450
    TixClassRecord * cPtr;
1451
    char * s;
1452
{
1453
    char ** listArgv;
1454
    int listArgc;
1455
    TixConfigSpec  * sPtr;
1456
 
1457
    if (Tcl_SplitList(interp, s, &listArgc, &listArgv) != TCL_OK) {
1458
        return NULL;
1459
    } else {
1460
        sPtr = (TixConfigSpec*) ckalloc(sizeof(TixConfigSpec));
1461
        sPtr->isAlias    = 1;
1462
        sPtr->isStatic   = 0;
1463
        sPtr->forceCall  = 0;
1464
        sPtr->readOnly   = 0;
1465
        sPtr->argvName   = (char*)tixStrDup(listArgv[0]);
1466
        sPtr->dbName     = (char*)tixStrDup(listArgv[1]);
1467
        sPtr->dbClass    = TIX_EMPTY_STRING;
1468
        sPtr->defValue   = TIX_EMPTY_STRING;
1469
        sPtr->verifyCmd  = NULL;
1470
        sPtr->realPtr    = NULL;
1471
 
1472
        ckfree((char*)listArgv);
1473
        return sPtr;
1474
    }
1475
}
1476
 
1477
static int
1478
InitHashEntries(interp, cPtr)
1479
    Tcl_Interp * interp;
1480
    TixClassRecord *cPtr;
1481
{
1482
    Tcl_HashEntry * hashPtr;
1483
    int             isNew;
1484
    char          * key;
1485
    int             i;
1486
    TixConfigSpec * sPtr;
1487
 
1488
    for (i=0; i<cPtr->nSpecs; i++) {
1489
        sPtr = cPtr->specs[i];
1490
        key = Tix_GetConfigSpecFullName(cPtr->className, sPtr->argvName);
1491
 
1492
        hashPtr = Tcl_CreateHashEntry(GetSpecTable(interp), key, &isNew);
1493
        Tcl_SetHashValue(hashPtr, (char*)sPtr);
1494
 
1495
        ckfree(key);
1496
    }
1497
 
1498
    return TCL_OK;
1499
}
1500
/*----------------------------------------------------------------------
1501
 * Subroutines for object instantiation.
1502
 *
1503
 *
1504
 *----------------------------------------------------------------------
1505
 */
1506
static int
1507
ParseInstanceOptions(interp, cPtr, widRec, argc, argv)
1508
    Tcl_Interp * interp;
1509
    TixClassRecord * cPtr;
1510
    char *widRec;
1511
    int argc;
1512
    char** argv;
1513
{
1514
    int i;
1515
    TixConfigSpec *spec;
1516
 
1517
    if ((argc %2) != 0) {
1518
        Tcl_AppendResult(interp, "missing argument for \"", argv[argc-1],
1519
            "\"", NULL);
1520
        return TCL_ERROR;
1521
    }
1522
 
1523
    /* Set all specs by their default values */
1524
    for (i=0; i<cPtr->nSpecs; i++) {
1525
        spec = cPtr->specs[i];
1526
        if (!spec->isAlias) {
1527
            if (Tix_ChangeOneOption(interp, cPtr, widRec, spec,
1528
                spec->defValue, 1, 0)!=TCL_OK) {
1529
                return TCL_ERROR;
1530
            }
1531
        }
1532
    }
1533
 
1534
    /* Set specs according to argument line values */
1535
    for (i=0; i<argc; i+=2) {
1536
        spec = Tix_FindConfigSpecByName(interp, cPtr, argv[i]);
1537
 
1538
        if (spec == NULL) {     /* this is an invalid flag */
1539
            return TCL_ERROR;
1540
        }
1541
 
1542
        if (Tix_ChangeOneOption(interp, cPtr, widRec, spec,
1543
                argv[i+1], 0, 1)!=TCL_OK) {
1544
            return TCL_ERROR;
1545
        }
1546
    }
1547
 
1548
    return TCL_OK;
1549
}
1550
 
1551
/*
1552
 *----------------------------------------------------------------------
1553
 * ClassTableDeleteProc --
1554
 *
1555
 *      This procedure is called when the interp is about to be
1556
 *      deleted. It cleans up the hash entries and destroys the hash
1557
 *      table.
1558
 *
1559
 * Results:
1560
 *      None.
1561
 *
1562
 * Side effects:
1563
 *      All class definitions are deleted.
1564
 *----------------------------------------------------------------------
1565
 */
1566
 
1567
static void
1568
ClassTableDeleteProc(clientData, interp)
1569
    ClientData clientData;
1570
    Tcl_Interp *interp;
1571
{
1572
    Tcl_HashTable * classTablePtr = (Tcl_HashTable*)clientData;
1573
    Tcl_HashSearch hashSearch;
1574
    Tcl_HashEntry * hashPtr;
1575
    TixClassRecord * cPtr;
1576
 
1577
    for (hashPtr = Tcl_FirstHashEntry(classTablePtr, &hashSearch);
1578
            hashPtr;
1579
            hashPtr = Tcl_NextHashEntry(&hashSearch)) {
1580
        cPtr = (TixClassRecord*)Tcl_GetHashValue(hashPtr);
1581
        FreeClassRecord(cPtr);
1582
        Tcl_DeleteHashEntry(hashPtr);
1583
    }
1584
    Tcl_DeleteHashTable(classTablePtr);
1585
    ckfree((char*)classTablePtr);
1586
}
1587
 
1588
#if USE_ACCESS_CONTROL
1589
 
1590
/*
1591
 * Everything after this line are not used at this moment.
1592
 *
1593
 */
1594
 
1595
/*----------------------------------------------------------------------
1596
 *
1597
 *
1598
 *                      ACCESS CONTROL
1599
 *
1600
 *
1601
 *----------------------------------------------------------------------
1602
 */
1603
static void InitExportSpec(exPtr)
1604
    Tix_ExportSpec * exPtr;
1605
{
1606
    Tix_SimpleListInit(&exPtr->exportCmds);
1607
    Tix_SimpleListInit(&exPtr->restrictCmds);
1608
    Tix_SimpleListInit(&exPtr->exportOpts);
1609
    Tix_SimpleListInit(&exPtr->restrictOpts);
1610
}
1611
 
1612
static Tix_LinkList * CopyStringList(list, newList)
1613
    Tix_LinkList * list;
1614
    Tix_LinkList * newList;
1615
{
1616
    Tix_StringLink * ptr, * newLink;
1617
 
1618
    for (ptr=(Tix_StringLink*)list->head; ptr; ptr=ptr->next) {
1619
        newLink = (Tix_StringLink*)ckalloc(sizeof(Tix_StringLink));
1620
 
1621
        newLink->string = (char*)tixStrDup(ptr->string);
1622
        Tix_SimpleListAppend(newList, (char*)newLink, 0);
1623
    }
1624
}
1625
 
1626
static void
1627
CopyExportSpec(src, dst)
1628
    Tix_ExportSpec * src;
1629
    Tix_ExportSpec * dst;
1630
{
1631
    CopyStringList(&src->exportCmds,   &dst->exportCmds);
1632
    CopyStringList(&src->restrictCmds, &dst->restrictCmds);
1633
 
1634
    CopyStringList(&src->exportOpts,   &dst->exportOpts);
1635
    CopyStringList(&src->restrictOpts, &dst->restrictOpts);
1636
}
1637
 
1638
/*
1639
 * (1) All items that appear in list1 must not appear in list 2
1640
 * (2) If either list have the item "all" -- an item whose string pointer is
1641
 *     NULL -- the other list must be empty.
1642
 */
1643
static int CheckMutualExclusion(list1, list2)
1644
    Tix_LinkList * list1;
1645
    Tix_LinkList * list2;
1646
{
1647
    Tix_StringLink * ptr, *ptr2;
1648
 
1649
    if (list1->numItems == 0) {
1650
        return TCL_OK;
1651
    }
1652
    if (list2->numItems == 0) {
1653
        return TCL_OK;
1654
    }
1655
 
1656
    for (ptr=(Tix_StringLink *)(list1->head); ptr; ptr=ptr->next) {
1657
        if (ptr->string == NULL) {
1658
            goto error;
1659
        }
1660
 
1661
        for (ptr2=(Tix_StringLink *)(list2->head); ptr2; ptr2=ptr2->next) {
1662
            if (strcmp(ptr->string, ptr2->string) == 0) {
1663
 
1664
                /* Violates requirement (1) above :
1665
                 * Some items in list 1 also appear in list 2.
1666
                 */
1667
                goto error;
1668
            }
1669
        }
1670
    }
1671
 
1672
    return TCL_OK;
1673
 
1674
  error:
1675
 
1676
    return TCL_ERROR;
1677
}
1678
 
1679
static int AppendStrings(interp, list, string)
1680
    Tcl_Interp * interp;
1681
    Tix_LinkList * list;
1682
    char * string;
1683
{
1684
    char ** listArgv = NULL;
1685
    int listArgc, i;
1686
    Tix_StringLink * ptr;
1687
 
1688
    if (string && *string) {
1689
        if (Tcl_SplitList(interp, string, &listArgc, &listArgv) != TCL_OK) {
1690
            return TCL_ERROR;
1691
        }
1692
    } else {
1693
        /* Nothing to be done */
1694
        return TCL_OK;
1695
    }
1696
 
1697
    for (i=0; i<listArgc; i++) {
1698
        ptr = (Tix_StringLink *)ckalloc(sizeof(Tix_StringLink));
1699
 
1700
        if (strcmp(listArgv[i], "all")==0) {
1701
            ptr->string = NULL;
1702
        } else {
1703
            ptr->string=(char*)tixStrDup(listArgv[i]);
1704
        }
1705
        Tix_SimpleListAppend(list, (char*)ptr, 0);
1706
    }
1707
 
1708
    if (listArgv) {
1709
        ckfree((char*)listArgv);
1710
    }
1711
 
1712
    return TCL_OK;
1713
}
1714
 
1715
 
1716
static int ConflictingSpec(interp, which, eList, rList)
1717
    Tcl_Interp * interp;
1718
    char * which;
1719
    Tix_LinkList * eList;
1720
    Tix_LinkList * rList;
1721
{
1722
    Tix_LinkList *lists[2];
1723
    Tix_StringLink * ptr;
1724
    int i;
1725
    char * specs[2] = {"export :", "restrict :"};
1726
 
1727
    lists[0] = eList;
1728
    lists[1] = rList;
1729
 
1730
    Tcl_ResetResult(interp);
1731
    Tcl_AppendResult(interp, "conflicting export and restrictions ",
1732
        "for ", which, "\n", NULL);
1733
 
1734
    for (i=0; i<2; i++) {
1735
        Tcl_AppendResult(interp, specs[i], NULL);
1736
 
1737
        for (ptr=(Tix_StringLink *)(lists[i]->head); ptr; ptr=ptr->next) {
1738
            if (ptr->string == 0) {
1739
                Tcl_AppendResult(interp, "all ", NULL);
1740
            } else {
1741
                Tcl_AppendResult(interp, ptr->string, " ", NULL);
1742
            }
1743
        }
1744
        Tcl_AppendResult(interp, "\n", NULL);
1745
    }
1746
 
1747
    return TCL_ERROR;
1748
}
1749
 
1750
/*
1751
 * Define or redefine the export control
1752
 */
1753
static int DefineExport(interp, exPtr, name, spec)
1754
    Tcl_Interp * interp;
1755
    Tix_ExportSpec * exPtr;
1756
    char * name;
1757
    char * spec;
1758
{
1759
    char ** listArgv = NULL;
1760
    int listArgc, i;
1761
 
1762
    if (spec && *spec) {
1763
        if (Tcl_SplitList(interp, spec, &listArgc, &listArgv) != TCL_OK) {
1764
            return TCL_ERROR;
1765
        }
1766
    } else {
1767
        /* Nothing to be done */
1768
        return TCL_OK;
1769
    }
1770
 
1771
    if (listArgc %2 != 0) {
1772
        Tcl_ResetResult(interp);
1773
        Tcl_AppendResult(interp, "wrong # of argument in subwidget spec: \"",
1774
            spec, "\"", NULL);
1775
        goto error;
1776
    }
1777
 
1778
    for (i=0; i<listArgc; i+=2) {
1779
        if (strcmp(listArgv[i], "-exportcmd") == 0) {
1780
            if (AppendStrings(interp, &exPtr->exportCmds,
1781
                listArgv[i+1])==TCL_ERROR) {
1782
                goto error;
1783
            }
1784
        }
1785
        else if (strcmp(listArgv[i], "-restrictcmd") == 0) {
1786
            if (AppendStrings(interp, &exPtr->restrictCmds,
1787
                listArgv[i+1])==TCL_ERROR){
1788
                goto error;
1789
            }
1790
        }
1791
        else if (strcmp(listArgv[i], "-exportopt") == 0) {
1792
            if (AppendStrings(interp, &exPtr->exportOpts,
1793
                listArgv[i+1])==TCL_ERROR) {
1794
                goto error;
1795
            }
1796
        }
1797
        else if (strcmp(listArgv[i], "-restrictopt") == 0) {
1798
            if (AppendStrings(interp, &exPtr->restrictOpts,
1799
                listArgv[i+1])==TCL_ERROR){
1800
                goto error;
1801
            }
1802
        }
1803
    }
1804
 
1805
    if (CheckMutualExclusion(&exPtr->exportCmds, &exPtr->restrictCmds)
1806
        ==TCL_ERROR) {
1807
        ConflictingSpec(interp, "commands",
1808
            &exPtr->exportCmds, &exPtr->restrictCmds);
1809
        goto error;
1810
    }
1811
    if (CheckMutualExclusion(&exPtr->restrictCmds, &exPtr->exportCmds)
1812
        ==TCL_ERROR) {
1813
        ConflictingSpec(interp, "commands",
1814
             &exPtr->exportCmds, &exPtr->restrictCmds);
1815
        goto error;
1816
    }
1817
    if (CheckMutualExclusion(&exPtr->exportOpts, &exPtr->restrictOpts)
1818
        ==TCL_ERROR) {
1819
        ConflictingSpec(interp, "options",
1820
             &exPtr->exportOpts, &exPtr->restrictOpts);
1821
        goto error;
1822
    }
1823
    if (CheckMutualExclusion(&exPtr->restrictOpts, &exPtr->exportOpts)
1824
        ==TCL_ERROR) {
1825
        ConflictingSpec(interp, "options",
1826
             &exPtr->exportOpts, &exPtr->restrictOpts);
1827
        goto error;
1828
    }
1829
 
1830
  done:
1831
    if (listArgv) {
1832
        ckfree((char*)listArgv);
1833
    }
1834
    return TCL_OK;
1835
 
1836
  error:
1837
    if (listArgv) {
1838
        ckfree((char*)listArgv);
1839
    }
1840
    return TCL_ERROR;
1841
}
1842
/*----------------------------------------------------------------------
1843
 *
1844
 *
1845
 *                      SUBWIDGET SETUP
1846
 *
1847
 *
1848
 *----------------------------------------------------------------------
1849
 */
1850
static Tix_SubWidgetSpec *
1851
GetSubWidgetSpec(cPtr, name)
1852
    TixClassRecord * cPtr;
1853
    char * name;
1854
{
1855
    Tix_SubWidgetSpec *ptr;
1856
 
1857
    for (ptr=(Tix_SubWidgetSpec *)cPtr->subWidgets.head; ptr; ptr=ptr->next) {
1858
        if (strcmp(ptr->name, name) == 0) {
1859
            return ptr;
1860
        }
1861
    }
1862
 
1863
    return NULL;
1864
}
1865
 
1866
static Tix_SubWidgetSpec *
1867
AllocSubWidgetSpec()
1868
{
1869
    Tix_SubWidgetSpec * newPtr =
1870
      (Tix_SubWidgetSpec *)ckalloc(sizeof(Tix_SubWidgetSpec));
1871
 
1872
    newPtr->next        = NULL;
1873
    newPtr->name        = NULL;
1874
    InitExportSpec(&newPtr->exportSpec);
1875
    return newPtr;
1876
}
1877
 
1878
static void
1879
CopySubWidgetSpecs(scPtr, cPtr)
1880
    TixClassRecord * scPtr;
1881
    TixClassRecord * cPtr;
1882
{
1883
    Tix_SubWidgetSpec *ssPtr;
1884
 
1885
    for (ssPtr=(Tix_SubWidgetSpec *)scPtr->subWidgets.head;
1886
        ssPtr;
1887
        ssPtr=ssPtr->next) {
1888
 
1889
        Tix_SubWidgetSpec *newPtr;
1890
        newPtr = AllocSubWidgetSpec();
1891
 
1892
        newPtr->name = (char*)tixStrDup(ssPtr->name);
1893
        CopyExportSpec(&ssPtr->exportSpec, & newPtr->exportSpec);
1894
 
1895
        Tix_SimpleListAppend(&cPtr->subWidgets, (char*)newPtr, 0);
1896
    }
1897
}
1898
 
1899
static int
1900
SetupSubWidget(interp, cPtr, s)
1901
    Tcl_Interp * interp;
1902
    TixClassRecord * cPtr;
1903
    char * s;
1904
{
1905
    char ** listArgv;
1906
    TixClassRecord * scPtr = cPtr->superClass;
1907
    int listArgc, i;
1908
 
1909
    if (s && *s) {
1910
        if (Tcl_SplitList(interp, s, &listArgc, &listArgv) != TCL_OK) {
1911
            return TCL_ERROR;
1912
        }
1913
    } else {
1914
        return TCL_OK;
1915
    }
1916
 
1917
    if (listArgc %2 != 0) {
1918
        Tcl_ResetResult(interp);
1919
        Tcl_AppendResult(interp, "wrong # of argument in subwidget spec: \"",
1920
            s, "\"", NULL);
1921
        goto error;
1922
    }
1923
 
1924
    /* Copy all the subwidgets of the superclass to this class */
1925
    if (scPtr) {
1926
        CopySubWidgetSpecs(scPtr, cPtr);
1927
    }
1928
 
1929
    /* Iterate over all the newly defined or re-defined subwidgets */
1930
    for (i=0; i<listArgc; i+=2) {
1931
        char * name, *spec;
1932
        Tix_SubWidgetSpec * oldSpec;
1933
        Tix_SubWidgetSpec * newSpec;
1934
 
1935
        name = listArgv[i];
1936
        spec = listArgv[i+1];
1937
 
1938
        if (scPtr && ((oldSpec = GetSubWidgetSpec(cPtr, name)) != NULL)) {
1939
            if (DefineExport(interp, &oldSpec->exportSpec, name, spec)
1940
                    != TCL_OK) {
1941
                goto error;
1942
            }
1943
        }
1944
        else {
1945
            newSpec = AllocSubWidgetSpec();
1946
            newSpec->name = (char*)tixStrDup(name);
1947
 
1948
            Tix_SimpleListAppend(&cPtr->subWidgets, (char*)newSpec, 0);
1949
 
1950
            if (DefineExport(interp, &newSpec->exportSpec, name, spec)
1951
                    != TCL_OK) {
1952
                goto error;
1953
            }
1954
        }
1955
    }
1956
 
1957
    if (listArgv) {
1958
        ckfree((char*)listArgv);
1959
    }
1960
    return TCL_OK;
1961
 
1962
 
1963
  error:
1964
    if (listArgv) {
1965
        ckfree((char*)listArgv);
1966
    }
1967
    return TCL_ERROR;
1968
}
1969
 
1970
#endif
1971
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.