see5-installer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.rubocop.yml +11 -0
  4. data/CHANGELOG.md +5 -0
  5. data/Gemfile +10 -0
  6. data/README.md +29 -0
  7. data/Rakefile +12 -0
  8. data/ext/c5.0/Makefile +86 -0
  9. data/ext/c5.0/attwinnow.c +394 -0
  10. data/ext/c5.0/c50.c +330 -0
  11. data/ext/c5.0/classify.c +700 -0
  12. data/ext/c5.0/confmat.c +195 -0
  13. data/ext/c5.0/construct.c +853 -0
  14. data/ext/c5.0/contin.c +613 -0
  15. data/ext/c5.0/defns.i +788 -0
  16. data/ext/c5.0/discr.c +307 -0
  17. data/ext/c5.0/extern.i +170 -0
  18. data/ext/c5.0/formrules.c +720 -0
  19. data/ext/c5.0/formtree.c +1158 -0
  20. data/ext/c5.0/getdata.c +521 -0
  21. data/ext/c5.0/getnames.c +733 -0
  22. data/ext/c5.0/global.c +211 -0
  23. data/ext/c5.0/gpl.txt +674 -0
  24. data/ext/c5.0/implicitatt.c +1112 -0
  25. data/ext/c5.0/info.c +146 -0
  26. data/ext/c5.0/mcost.c +138 -0
  27. data/ext/c5.0/modelfiles.c +952 -0
  28. data/ext/c5.0/p-thresh.c +313 -0
  29. data/ext/c5.0/prune.c +1069 -0
  30. data/ext/c5.0/report.c +345 -0
  31. data/ext/c5.0/rules.c +579 -0
  32. data/ext/c5.0/ruletree.c +398 -0
  33. data/ext/c5.0/siftrules.c +1285 -0
  34. data/ext/c5.0/sort.c +156 -0
  35. data/ext/c5.0/subset.c +599 -0
  36. data/ext/c5.0/text.i +223 -0
  37. data/ext/c5.0/trees.c +740 -0
  38. data/ext/c5.0/update.c +129 -0
  39. data/ext/c5.0/utility.c +1146 -0
  40. data/ext/c5.0/xval +150 -0
  41. data/ext/c5.0/xval.c +402 -0
  42. data/ext/gritbot/Makefile +98 -0
  43. data/ext/gritbot/check.c +1110 -0
  44. data/ext/gritbot/cluster.c +342 -0
  45. data/ext/gritbot/common.c +1269 -0
  46. data/ext/gritbot/continatt.c +412 -0
  47. data/ext/gritbot/defns.i +623 -0
  48. data/ext/gritbot/discratt.c +459 -0
  49. data/ext/gritbot/extern.i +101 -0
  50. data/ext/gritbot/getdata.c +329 -0
  51. data/ext/gritbot/getnames.c +573 -0
  52. data/ext/gritbot/global.c +104 -0
  53. data/ext/gritbot/gpl.txt +674 -0
  54. data/ext/gritbot/gritbot.c +295 -0
  55. data/ext/gritbot/implicitatt.c +1108 -0
  56. data/ext/gritbot/inspect.c +794 -0
  57. data/ext/gritbot/modelfiles.c +687 -0
  58. data/ext/gritbot/outlier.c +415 -0
  59. data/ext/gritbot/sort.c +130 -0
  60. data/ext/gritbot/text.i +159 -0
  61. data/ext/gritbot/update.c +126 -0
  62. data/ext/gritbot/utility.c +1029 -0
  63. data/ext/see5-installer/extconf.rb +25 -0
  64. data/lib/see5/installer.rb +10 -0
  65. data/lib/see5/installer/version.rb +7 -0
  66. data/see5-installer.gemspec +30 -0
  67. metadata +115 -0
@@ -0,0 +1,733 @@
1
+ /*************************************************************************/
2
+ /* */
3
+ /* Copyright 2010 Rulequest Research Pty Ltd. */
4
+ /* */
5
+ /* This file is part of C5.0 GPL Edition, a single-threaded version */
6
+ /* of C5.0 release 2.07. */
7
+ /* */
8
+ /* C5.0 GPL Edition is free software: you can redistribute it and/or */
9
+ /* modify it under the terms of the GNU General Public License as */
10
+ /* published by the Free Software Foundation, either version 3 of the */
11
+ /* License, or (at your option) any later version. */
12
+ /* */
13
+ /* C5.0 GPL Edition 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 GNU */
16
+ /* General Public License for more details. */
17
+ /* */
18
+ /* You should have received a copy of the GNU General Public License */
19
+ /* (gpl.txt) along with C5.0 GPL Edition. If not, see */
20
+ /* */
21
+ /* <http://www.gnu.org/licenses/>. */
22
+ /* */
23
+ /*************************************************************************/
24
+
25
+
26
+
27
+ /*************************************************************************/
28
+ /* */
29
+ /* Get names of classes, attributes and attribute values */
30
+ /* ----------------------------------------------------- */
31
+ /* */
32
+ /*************************************************************************/
33
+
34
+
35
+ #include "defns.i"
36
+ #include "extern.i"
37
+
38
+ #include <sys/types.h>
39
+ #include <sys/stat.h>
40
+
41
+ #define MAXLINEBUFFER 10000
42
+ int Delimiter;
43
+ char LineBuffer[MAXLINEBUFFER], *LBp=LineBuffer;
44
+
45
+
46
+
47
+ /*************************************************************************/
48
+ /* */
49
+ /* Read a name from file f into string s, setting Delimiter. */
50
+ /* */
51
+ /* - Embedded periods are permitted, but periods followed by space */
52
+ /* characters act as delimiters. */
53
+ /* - Embedded spaces are permitted, but multiple spaces are */
54
+ /* replaced by a single space. */
55
+ /* - Any character can be escaped by '\'. */
56
+ /* - The remainder of a line following '|' is ignored. */
57
+ /* */
58
+ /* Colons are sometimes delimiters depending on ColonOpt */
59
+ /* */
60
+ /*************************************************************************/
61
+
62
+
63
+ Boolean ReadName(FILE *f, String s, int n, char ColonOpt)
64
+ /* -------- */
65
+ {
66
+ register char *Sp=s;
67
+ register int c;
68
+ char Msg[2];
69
+
70
+ /* Skip to first non-space character */
71
+
72
+ while ( (c = InChar(f)) == '|' || Space(c) )
73
+ {
74
+ if ( c == '|' ) SkipComment;
75
+ }
76
+
77
+ /* Return false if no names to read */
78
+
79
+ if ( c == EOF )
80
+ {
81
+ Delimiter = EOF;
82
+ return false;
83
+ }
84
+
85
+ /* Read in characters up to the next delimiter */
86
+
87
+ while ( c != ColonOpt && c != ',' && c != '\n' && c != '|' && c != EOF )
88
+ {
89
+ if ( --n <= 0 )
90
+ {
91
+ if ( Of ) Error(LONGNAME, "", "");
92
+ }
93
+
94
+ if ( c == '.' )
95
+ {
96
+ if ( (c = InChar(f)) == '|' || Space(c) || c == EOF ) break;
97
+ *Sp++ = '.';
98
+ continue;
99
+ }
100
+
101
+ if ( c == '\\' )
102
+ {
103
+ c = InChar(f);
104
+ }
105
+
106
+ if ( Space(c) )
107
+ {
108
+ *Sp++ = ' ';
109
+
110
+ while ( ( c = InChar(f) ) == ' ' || c == '\t' )
111
+ ;
112
+ }
113
+ else
114
+ {
115
+ *Sp++ = c;
116
+ c = InChar(f);
117
+ }
118
+ }
119
+
120
+ if ( c == '|' ) SkipComment;
121
+ Delimiter = c;
122
+
123
+ /* Special case for ':=' */
124
+
125
+ if ( Delimiter == ':' )
126
+ {
127
+ if ( *LBp == '=' )
128
+ {
129
+ Delimiter = '=';
130
+ LBp++;
131
+ }
132
+ }
133
+
134
+ /* Strip trailing spaces */
135
+
136
+ while ( Sp > s && Space(*(Sp-1)) ) Sp--;
137
+
138
+ if ( Sp == s )
139
+ {
140
+ Msg[0] = ( Space(c) ? '.' : c );
141
+ Msg[1] = '\00';
142
+ Error(MISSNAME, Fn, Msg);
143
+ }
144
+
145
+ *Sp++ = '\0';
146
+ return true;
147
+ }
148
+
149
+
150
+
151
+ /*************************************************************************/
152
+ /* */
153
+ /* Read names of classes, attributes and legal attribute values. */
154
+ /* On completion, names are stored in: */
155
+ /* ClassName - class names */
156
+ /* AttName - attribute names */
157
+ /* AttValName - attribute value names */
158
+ /* with: */
159
+ /* MaxAttVal - number of values for each attribute */
160
+ /* */
161
+ /* Other global variables set are: */
162
+ /* MaxAtt - maximum attribute number */
163
+ /* MaxClass - maximum class number */
164
+ /* MaxDiscrVal - maximum discrete values for an attribute */
165
+ /* */
166
+ /*************************************************************************/
167
+
168
+
169
+ void GetNames(FILE *Nf)
170
+ /* -------- */
171
+ {
172
+ char Buffer[1000]="", *EndBuff;
173
+ int AttCeiling=100, ClassCeiling=100;
174
+ Attribute Att;
175
+ ClassNo c;
176
+
177
+ ErrMsgs = AttExIn = 0;
178
+ LineNo = 0;
179
+ LBp = LineBuffer;
180
+ *LBp = 0;
181
+
182
+ MaxClass = ClassAtt = LabelAtt = CWtAtt = 0;
183
+
184
+ /* Get class names from names file. This entry can be:
185
+ - a list of discrete values separated by commas
186
+ - the name of the discrete attribute to use as the class
187
+ - the name of a continuous attribute followed by a colon and
188
+ a comma-separated list of thresholds used to segment it */
189
+
190
+ ClassName = AllocZero(ClassCeiling, String);
191
+ do
192
+ {
193
+ ReadName(Nf, Buffer, 1000, ':');
194
+
195
+ if ( ++MaxClass >= ClassCeiling)
196
+ {
197
+ ClassCeiling += 100;
198
+ Realloc(ClassName, ClassCeiling, String);
199
+ }
200
+ ClassName[MaxClass] = strdup(Buffer);
201
+ }
202
+ while ( Delimiter == ',' );
203
+
204
+ if ( Delimiter == ':' )
205
+ {
206
+ /* Thresholds for continuous class attribute */
207
+
208
+ ClassThresh = Alloc(ClassCeiling, ContValue);
209
+ MaxClass = 0;
210
+
211
+ do
212
+ {
213
+ ReadName(Nf, Buffer, 1000, ':');
214
+
215
+ if ( ++MaxClass >= ClassCeiling)
216
+ {
217
+ ClassCeiling += 100;
218
+ Realloc(ClassThresh, ClassCeiling, ContValue);
219
+ }
220
+
221
+ ClassThresh[MaxClass] = strtod(Buffer, &EndBuff);
222
+ if ( EndBuff == Buffer || *EndBuff != '\0' )
223
+ {
224
+ Error(BADCLASSTHRESH, Buffer, Nil);
225
+ }
226
+ else
227
+ if ( MaxClass > 1 &&
228
+ ClassThresh[MaxClass] <= ClassThresh[MaxClass-1] )
229
+ {
230
+ Error(LEQCLASSTHRESH, Buffer, Nil);
231
+ }
232
+ }
233
+ while ( Delimiter == ',' );
234
+ }
235
+
236
+ /* Get attribute and attribute value names from names file */
237
+
238
+ AttName = AllocZero(AttCeiling, String);
239
+ MaxAttVal = AllocZero(AttCeiling, DiscrValue);
240
+ AttValName = AllocZero(AttCeiling, String *);
241
+ SpecialStatus = AllocZero(AttCeiling, char);
242
+ AttDef = AllocZero(AttCeiling, Definition);
243
+ AttDefUses = AllocZero(AttCeiling, Attribute *);
244
+
245
+ MaxAtt = 0;
246
+ while ( ReadName(Nf, Buffer, 1000, ':') )
247
+ {
248
+ if ( Delimiter != ':' && Delimiter != '=' )
249
+ {
250
+ Error(BADATTNAME, Buffer, "");
251
+ }
252
+
253
+ /* Check for attributes included/excluded */
254
+
255
+ if ( ( *Buffer == 'a' || *Buffer == 'A' ) &&
256
+ ! memcmp(Buffer+1, "ttributes ", 10) &&
257
+ ! memcmp(Buffer+strlen(Buffer)-6, "cluded", 6) )
258
+ {
259
+ AttExIn = ( ! memcmp(Buffer+strlen(Buffer)-8, "in", 2) ? 1 : -1 );
260
+ if ( AttExIn == 1 )
261
+ {
262
+ ForEach(Att, 1, MaxAtt)
263
+ {
264
+ SpecialStatus[Att] |= SKIP;
265
+ }
266
+ }
267
+
268
+ while ( ReadName(Nf, Buffer, 1000, ':') )
269
+ {
270
+ Att = Which(Buffer, AttName, 1, MaxAtt);
271
+ if ( ! Att )
272
+ {
273
+ Error(UNKNOWNATT, Buffer, Nil);
274
+ }
275
+ else
276
+ if ( AttExIn == 1 )
277
+ {
278
+ SpecialStatus[Att] -= SKIP;
279
+ }
280
+ else
281
+ {
282
+ SpecialStatus[Att] |= SKIP;
283
+ }
284
+ }
285
+
286
+ break;
287
+ }
288
+
289
+ if ( Which(Buffer, AttName, 1, MaxAtt) > 0 )
290
+ {
291
+ Error(DUPATTNAME, Buffer, Nil);
292
+ }
293
+
294
+ if ( ++MaxAtt >= AttCeiling )
295
+ {
296
+ AttCeiling += 100;
297
+ Realloc(AttName, AttCeiling, String);
298
+ Realloc(MaxAttVal, AttCeiling, DiscrValue);
299
+ Realloc(AttValName, AttCeiling, String *);
300
+ Realloc(SpecialStatus, AttCeiling, char);
301
+ Realloc(AttDef, AttCeiling, Definition);
302
+ Realloc(AttDefUses, AttCeiling, Attribute *);
303
+ }
304
+
305
+ AttName[MaxAtt] = strdup(Buffer);
306
+ SpecialStatus[MaxAtt] = Nil;
307
+ AttDef[MaxAtt] = Nil;
308
+ MaxAttVal[MaxAtt] = 0;
309
+ AttDefUses[MaxAtt] = Nil;
310
+
311
+ if ( Delimiter == '=' )
312
+ {
313
+ if ( MaxClass == 1 && ! strcmp(ClassName[1], AttName[MaxAtt]) )
314
+ {
315
+ Error(BADDEF3, Nil, Nil);
316
+ }
317
+
318
+ ImplicitAtt(Nf);
319
+ ListAttsUsed();
320
+ }
321
+ else
322
+ {
323
+ ExplicitAtt(Nf);
324
+ }
325
+
326
+ /* Check for case weight attribute, which must be type continuous */
327
+
328
+ if ( ! strcmp(AttName[MaxAtt], "case weight") )
329
+ {
330
+ CWtAtt = MaxAtt;
331
+
332
+ if ( ! Continuous(CWtAtt) )
333
+ {
334
+ Error(CWTATTERR, "", "");
335
+ }
336
+ }
337
+ }
338
+
339
+ /* Check whether class is one of the attributes */
340
+
341
+ if ( MaxClass == 1 || ClassThresh )
342
+ {
343
+ /* Class attribute must be present and must be either
344
+ a discrete attribute or a thresholded continuous attribute */
345
+
346
+ ClassAtt = Which(ClassName[1], AttName, 1, MaxAtt);
347
+
348
+ if ( ClassAtt <= 0 || Exclude(ClassAtt) )
349
+ {
350
+ Error(NOTARGET, ClassName[1], "");
351
+ }
352
+ else
353
+ if ( ClassThresh &&
354
+ ( ! Continuous(ClassAtt) ||
355
+ StatBit(ClassAtt, DATEVAL|STIMEVAL|TSTMPVAL) ) )
356
+ {
357
+ Error(BADCTARGET, ClassName[1], "");
358
+ }
359
+ else
360
+ if ( ! ClassThresh &&
361
+ ( Continuous(ClassAtt) || StatBit(ClassAtt, DISCRETE) ) )
362
+ {
363
+ Error(BADDTARGET, ClassName[1], "");
364
+ }
365
+
366
+ Free(ClassName[1]);
367
+
368
+ if ( ! ClassThresh )
369
+ {
370
+ Free(ClassName);
371
+ MaxClass = MaxAttVal[ClassAtt];
372
+ ClassName = AttValName[ClassAtt];
373
+ }
374
+ else
375
+ {
376
+ /* Set up class names as segments of continuous target att */
377
+
378
+ MaxClass++;
379
+ Realloc(ClassName, MaxClass+1, String);
380
+
381
+ sprintf(Buffer, "%s <= %g", AttName[ClassAtt], ClassThresh[1]);
382
+ ClassName[1] = strdup(Buffer);
383
+
384
+ ForEach(c, 2, MaxClass-1)
385
+ {
386
+ sprintf(Buffer, "%g < %s <= %g",
387
+ ClassThresh[c-1], AttName[ClassAtt], ClassThresh[c]);
388
+ ClassName[c] = strdup(Buffer);
389
+ }
390
+
391
+ sprintf(Buffer, "%s > %g",
392
+ AttName[ClassAtt], ClassThresh[MaxClass-1]);
393
+ ClassName[MaxClass] = strdup(Buffer);
394
+ }
395
+ }
396
+
397
+ /* Ignore case weight attribute if it is excluded; otherwise,
398
+ it cannot be used in models */
399
+
400
+ if ( CWtAtt )
401
+ {
402
+ if ( Skip(CWtAtt) )
403
+ {
404
+ CWtAtt = 0;
405
+ }
406
+ else
407
+ {
408
+ SpecialStatus[CWtAtt] |= SKIP;
409
+ }
410
+ }
411
+
412
+ ClassName[0] = "?";
413
+
414
+ fclose(Nf);
415
+
416
+ if ( ErrMsgs > 0 ) Goodbye(1);
417
+ }
418
+
419
+
420
+
421
+ /*************************************************************************/
422
+ /* */
423
+ /* Continuous or discrete attribute */
424
+ /* */
425
+ /*************************************************************************/
426
+
427
+
428
+ void ExplicitAtt(FILE *Nf)
429
+ /* ----------- */
430
+ {
431
+ char Buffer[1000]="", *p;
432
+ DiscrValue v;
433
+ int ValCeiling=100, BaseYear;
434
+ time_t clock;
435
+
436
+ /* Read attribute type or first discrete value */
437
+
438
+ if ( ! ( ReadName(Nf, Buffer, 1000, ':') ) )
439
+ {
440
+ Error(EOFINATT, AttName[MaxAtt], "");
441
+ }
442
+
443
+ MaxAttVal[MaxAtt] = 0;
444
+
445
+ if ( Delimiter != ',' )
446
+ {
447
+ /* Typed attribute */
448
+
449
+ if ( ! strcmp(Buffer, "continuous") )
450
+ {
451
+ }
452
+ else
453
+ if ( ! strcmp(Buffer, "timestamp") )
454
+ {
455
+ SpecialStatus[MaxAtt] = TSTMPVAL;
456
+
457
+ /* Set the base date if not done already */
458
+
459
+ if ( ! TSBase )
460
+ {
461
+ clock = time(0);
462
+ BaseYear = gmtime(&clock)->tm_year + 1900;
463
+ SetTSBase(BaseYear);
464
+ }
465
+ }
466
+ else
467
+ if ( ! strcmp(Buffer, "date") )
468
+ {
469
+ SpecialStatus[MaxAtt] = DATEVAL;
470
+ }
471
+ else
472
+ if ( ! strcmp(Buffer, "time") )
473
+ {
474
+ SpecialStatus[MaxAtt] = STIMEVAL;
475
+ }
476
+ else
477
+ if ( ! memcmp(Buffer, "discrete", 8) )
478
+ {
479
+ SpecialStatus[MaxAtt] = DISCRETE;
480
+
481
+ /* Read max values and reserve space */
482
+
483
+ v = atoi(&Buffer[8]);
484
+ if ( v < 2 )
485
+ {
486
+ Error(BADDISCRETE, AttName[MaxAtt], "");
487
+ }
488
+
489
+ AttValName[MaxAtt] = Alloc(v+3, String);
490
+ AttValName[MaxAtt][0] = (char *) (long) v+1;
491
+ AttValName[MaxAtt][(MaxAttVal[MaxAtt]=1)] = strdup("N/A");
492
+ }
493
+ else
494
+ if ( ! strcmp(Buffer, "ignore") )
495
+ {
496
+ SpecialStatus[MaxAtt] = EXCLUDE;
497
+ }
498
+ else
499
+ if ( ! strcmp(Buffer, "label") )
500
+ {
501
+ LabelAtt = MaxAtt;
502
+ SpecialStatus[MaxAtt] = EXCLUDE;
503
+ }
504
+ else
505
+ {
506
+ /* Cannot have only one discrete value for an attribute */
507
+
508
+ Error(SINGLEATTVAL, AttName[MaxAtt], Buffer);
509
+ }
510
+ }
511
+ else
512
+ {
513
+ /* Discrete attribute with explicit values */
514
+
515
+ AttValName[MaxAtt] = AllocZero(ValCeiling, String);
516
+
517
+ /* Add "N/A" unless this attribute is the class */
518
+
519
+ if ( MaxClass > 1 || strcmp(ClassName[1], AttName[MaxAtt]) )
520
+ {
521
+ AttValName[MaxAtt][(MaxAttVal[MaxAtt]=1)] = strdup("N/A");
522
+ }
523
+ else
524
+ {
525
+ MaxAttVal[MaxAtt] = 0;
526
+ }
527
+
528
+ p = Buffer;
529
+
530
+ /* Special check for ordered attribute */
531
+
532
+ if ( ! memcmp(Buffer, "[ordered]", 9) )
533
+ {
534
+ SpecialStatus[MaxAtt] = ORDERED;
535
+
536
+ for ( p = Buffer+9 ; Space(*p) ; p++ )
537
+ ;
538
+ }
539
+
540
+ /* Record first real explicit value */
541
+
542
+ AttValName[MaxAtt][++MaxAttVal[MaxAtt]] = strdup(p);
543
+
544
+ /* Record remaining values */
545
+
546
+ do
547
+ {
548
+ if ( ! ( ReadName(Nf, Buffer, 1000, ':') ) )
549
+ {
550
+ Error(EOFINATT, AttName[MaxAtt], "");
551
+ }
552
+
553
+ if ( ++MaxAttVal[MaxAtt] >= ValCeiling )
554
+ {
555
+ ValCeiling += 100;
556
+ Realloc(AttValName[MaxAtt], ValCeiling, String);
557
+ }
558
+
559
+ AttValName[MaxAtt][MaxAttVal[MaxAtt]] = strdup(Buffer);
560
+ }
561
+ while ( Delimiter == ',' );
562
+
563
+ /* Cancel ordered status if <3 real values */
564
+
565
+ if ( Ordered(MaxAtt) && MaxAttVal[MaxAtt] <= 3 )
566
+ {
567
+ SpecialStatus[MaxAtt] = 0;
568
+ }
569
+ if ( MaxAttVal[MaxAtt] > MaxDiscrVal ) MaxDiscrVal = MaxAttVal[MaxAtt];
570
+ }
571
+ }
572
+
573
+
574
+
575
+ /*************************************************************************/
576
+ /* */
577
+ /* Locate value Val in List[First] to List[Last] */
578
+ /* */
579
+ /*************************************************************************/
580
+
581
+
582
+ int Which(String Val, String *List, int First, int Last)
583
+ /* ----- */
584
+ {
585
+ int n=First;
586
+
587
+ while ( n <= Last && strcmp(Val, List[n]) ) n++;
588
+
589
+ return ( n <= Last ? n : First-1 );
590
+ }
591
+
592
+
593
+
594
+ /*************************************************************************/
595
+ /* */
596
+ /* Build list of attributes used in current attribute definition */
597
+ /* AttDefUses[Att][0] = number of atts used */
598
+ /* AttDefUses[Att][1..] are the atts */
599
+ /* */
600
+ /*************************************************************************/
601
+
602
+
603
+ void ListAttsUsed()
604
+ /* ------------ */
605
+ {
606
+ Attribute Att;
607
+ Boolean *DefUses;
608
+ Definition D;
609
+ int e, NUsed=0;
610
+
611
+ DefUses = AllocZero(MaxAtt+1, Boolean);
612
+
613
+ D = AttDef[MaxAtt];
614
+
615
+ for ( e = 0 ; ; e++ )
616
+ {
617
+ if ( DefOp(D[e]) == OP_ATT )
618
+ {
619
+ Att = (Attribute) DefSVal(D[e]);
620
+ if ( ! DefUses[Att] )
621
+ {
622
+ DefUses[Att] = true;
623
+ NUsed++;
624
+ }
625
+ }
626
+ else
627
+ if ( DefOp(D[e]) == OP_END )
628
+ {
629
+ break;
630
+ }
631
+ }
632
+
633
+ if ( NUsed )
634
+ {
635
+ AttDefUses[MaxAtt] = Alloc(NUsed+1, Attribute);
636
+ AttDefUses[MaxAtt][0] = NUsed;
637
+
638
+ NUsed=0;
639
+ ForEach(Att, 1, MaxAtt-1)
640
+ {
641
+ if ( DefUses[Att] )
642
+ {
643
+ AttDefUses[MaxAtt][++NUsed] = Att;
644
+ }
645
+ }
646
+ }
647
+
648
+ Free(DefUses);
649
+ }
650
+
651
+
652
+
653
+ /*************************************************************************/
654
+ /* */
655
+ /* Free up all space allocated by GetNames() */
656
+ /* */
657
+ /*************************************************************************/
658
+
659
+
660
+ void FreeNames()
661
+ /* --------- */
662
+ {
663
+ Attribute a, t;
664
+
665
+ if ( ! AttName ) return;
666
+
667
+ ForEach(a, 1, MaxAtt)
668
+ {
669
+ if ( a != ClassAtt && Discrete(a) )
670
+ {
671
+ FreeVector((void **) AttValName[a], 1, MaxAttVal[a]);
672
+ }
673
+ }
674
+ FreeUnlessNil(AttValName); AttValName = Nil;
675
+ FreeUnlessNil(MaxAttVal); MaxAttVal = Nil;
676
+ FreeUnlessNil(ClassThresh); ClassThresh = Nil;
677
+ FreeVector((void **) AttName, 1, MaxAtt); AttName = Nil;
678
+ FreeVector((void **) ClassName, 1, MaxClass); ClassName = Nil;
679
+
680
+ FreeUnlessNil(SpecialStatus); SpecialStatus = Nil;
681
+
682
+ /* Definitions (if any) */
683
+
684
+ if ( AttDef )
685
+ {
686
+ ForEach(a, 1, MaxAtt)
687
+ {
688
+ if ( AttDef[a] )
689
+ {
690
+ for ( t = 0 ; DefOp(AttDef[a][t]) != OP_END ; t++ )
691
+ {
692
+ if ( DefOp(AttDef[a][t]) == OP_STR )
693
+ {
694
+ Free(DefSVal(AttDef[a][t]));
695
+ }
696
+ }
697
+
698
+ Free(AttDef[a]);
699
+ Free(AttDefUses[a]);
700
+ }
701
+ }
702
+ Free(AttDef); AttDef = Nil;
703
+ Free(AttDefUses); AttDefUses = Nil;
704
+ }
705
+ }
706
+
707
+
708
+
709
+ /*************************************************************************/
710
+ /* */
711
+ /* Read next char keeping track of line numbers */
712
+ /* */
713
+ /*************************************************************************/
714
+
715
+
716
+ int InChar(FILE *f)
717
+ /* ------ */
718
+ {
719
+ if ( ! *LBp )
720
+ {
721
+ LBp = LineBuffer;
722
+
723
+ if ( ! fgets(LineBuffer, MAXLINEBUFFER, f) )
724
+ {
725
+ LineBuffer[0] = '\00';
726
+ return EOF;
727
+ }
728
+
729
+ LineNo++;
730
+ }
731
+
732
+ return (int) *LBp++;
733
+ }