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,1112 @@
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
+ /* Routines to handle implicitly-defined attributes */
30
+ /* ------------------------------------------------ */
31
+ /* */
32
+ /*************************************************************************/
33
+
34
+
35
+ #include "defns.i"
36
+ #include "extern.i"
37
+ #include <ctype.h>
38
+
39
+
40
+ char *Buff; /* buffer for input characters */
41
+ int BuffSize, BN; /* size and index of next character */
42
+
43
+ EltRec *TStack; /* expression stack model */
44
+ int TStackSize, TSN; /* size of stack and index of next entry */
45
+
46
+ int DefSize, DN; /* size of definition and next element */
47
+
48
+ Boolean PreviousError; /* to avoid parasitic errors */
49
+
50
+ AttValue _UNK, /* quasi-constant for unknown value */
51
+ _NA; /* ditto for not applicable */
52
+
53
+
54
+ #define FailSyn(Msg) {DefSyntaxError(Msg); return false;}
55
+ #define FailSem(Msg) {DefSemanticsError(Fi, Msg, OpCode); return false;}
56
+
57
+ typedef union _xstack_elt
58
+ {
59
+ DiscrValue _discr_val;
60
+ ContValue _cont_val;
61
+ String _string_val;
62
+ }
63
+ XStackElt;
64
+
65
+ #define cval _cont_val
66
+ #define sval _string_val
67
+ #define dval _discr_val
68
+
69
+
70
+
71
+ /*************************************************************************/
72
+ /* */
73
+ /* A definition is handled in two stages: */
74
+ /* - The definition is read (up to a line ending with a period) */
75
+ /* replacing multiple whitespace characters with one space */
76
+ /* - The definition is then read (using a recursive descent */
77
+ /* parser), building up a reverse polish expression */
78
+ /* Syntax and semantics errors are flagged */
79
+ /* */
80
+ /*************************************************************************/
81
+
82
+
83
+ void ImplicitAtt(FILE *Nf)
84
+ /* ----------- */
85
+ {
86
+ #ifdef CUBIST
87
+ _UNK.cval = UNKNOWN;
88
+ #else
89
+ _UNK.dval = UNKNOWN;
90
+ #endif
91
+ _NA.dval = NA;
92
+
93
+ /* Get definition as a string in Buff */
94
+
95
+ ReadDefinition(Nf);
96
+
97
+ PreviousError = false;
98
+ BN = 0;
99
+
100
+ /* Allocate initial stack and attribute definition */
101
+
102
+ TStack = Alloc(TStackSize=50, EltRec);
103
+ TSN = 0;
104
+
105
+ AttDef[MaxAtt] = Alloc(DefSize = 100, DefElt);
106
+ DN = 0;
107
+
108
+ /* Parse Buff as an expression terminated by a period */
109
+
110
+ Expression();
111
+ if ( ! Find(".") ) DefSyntaxError("'.' ending definition");
112
+
113
+ /* Final check -- defined attribute must not be of type String */
114
+
115
+ if ( ! PreviousError )
116
+ {
117
+ if ( DN == 1 && DefOp(AttDef[MaxAtt][0]) == OP_ATT &&
118
+ strcmp(AttName[MaxAtt], "case weight") )
119
+ {
120
+ Error(SAMEATT, AttName[ (long) DefSVal(AttDef[MaxAtt][0]) ], Nil);
121
+ }
122
+
123
+ if ( TStack[0].Type == 'B' )
124
+ {
125
+ /* Defined attributes should never have a value N/A */
126
+
127
+ MaxAttVal[MaxAtt] = 3;
128
+ AttValName[MaxAtt] = AllocZero(4, String);
129
+ AttValName[MaxAtt][1] = strdup("??");
130
+ AttValName[MaxAtt][2] = strdup("t");
131
+ AttValName[MaxAtt][3] = strdup("f");
132
+ }
133
+ else
134
+ {
135
+ MaxAttVal[MaxAtt] = 0;
136
+ }
137
+ }
138
+
139
+ if ( PreviousError )
140
+ {
141
+ DN = 0;
142
+ SpecialStatus[MaxAtt] = EXCLUDE;
143
+ }
144
+
145
+ /* Write a terminating marker */
146
+
147
+ DefOp(AttDef[MaxAtt][DN]) = OP_END;
148
+
149
+ Free(Buff);
150
+ Free(TStack);
151
+ }
152
+
153
+
154
+
155
+ /*************************************************************************/
156
+ /* */
157
+ /* Read the text of a definition. Skip comments, collapse */
158
+ /* multiple whitespace characters. */
159
+ /* */
160
+ /*************************************************************************/
161
+
162
+
163
+ void ReadDefinition(FILE *f)
164
+ /* -------------- */
165
+ {
166
+ Boolean LastWasPeriod=false;
167
+ char c;
168
+
169
+ Buff = Alloc(BuffSize=50, char);
170
+ BN = 0;
171
+
172
+ while ( true )
173
+ {
174
+ c = InChar(f);
175
+
176
+ if ( c == '|' ) SkipComment;
177
+
178
+ if ( c == EOF || c == '\n' && LastWasPeriod )
179
+ {
180
+ /* The definition is complete. Add a period if it's
181
+ not there already and terminate the string */
182
+
183
+ if ( ! LastWasPeriod ) Append('.');
184
+ Append(0);
185
+
186
+ return;
187
+ }
188
+
189
+ if ( Space(c) )
190
+ {
191
+ Append(' ');
192
+ }
193
+ else
194
+ if ( c == '\\' )
195
+ {
196
+ /* Escaped character -- bypass any special meaning */
197
+
198
+ Append(InChar(f));
199
+ }
200
+ else
201
+ {
202
+ LastWasPeriod = ( c == '.' );
203
+ Append(c);
204
+ }
205
+ }
206
+ }
207
+
208
+
209
+
210
+ /*************************************************************************/
211
+ /* */
212
+ /* Append a character to Buff, resizing it if necessary */
213
+ /* */
214
+ /*************************************************************************/
215
+
216
+
217
+ void Append(char c)
218
+ /* ------ */
219
+ {
220
+ if ( c == ' ' && (! BN || Buff[BN-1] == ' ' ) ) return;
221
+
222
+ if ( BN >= BuffSize )
223
+ {
224
+ Realloc(Buff, BuffSize += 50, char);
225
+ }
226
+
227
+ Buff[BN++] = c;
228
+ }
229
+
230
+
231
+
232
+ /*************************************************************************/
233
+ /* */
234
+ /* Recursive descent parser with syntax error checking. */
235
+ /* The reverse polish is built up by calls to Dump() and DumpOp(), */
236
+ /* which also check for semantic validity. */
237
+ /* */
238
+ /* For possible error messages, each routine also keeps track of */
239
+ /* the beginning of the construct that it recognises (in Fi). */
240
+ /* */
241
+ /*************************************************************************/
242
+
243
+
244
+ Boolean Expression()
245
+ /* ---------- */
246
+ {
247
+ int Fi=BN;
248
+
249
+ if ( Buff[BN] == ' ' ) BN++;
250
+
251
+ if ( ! Conjunct() ) FailSyn("expression");
252
+
253
+ while ( Find("or") )
254
+ {
255
+ BN += 2;
256
+
257
+ if ( ! Conjunct() ) FailSyn("expression");
258
+
259
+ DumpOp(OP_OR, Fi);
260
+ }
261
+
262
+ return true;
263
+ }
264
+
265
+
266
+
267
+ Boolean Conjunct()
268
+ /* -------- */
269
+ {
270
+ int Fi=BN;
271
+
272
+ if ( ! SExpression() ) FailSyn("expression");
273
+
274
+ while ( Find("and") )
275
+ {
276
+ BN += 3;
277
+
278
+ if ( ! SExpression() ) FailSyn("expression");
279
+
280
+ DumpOp(OP_AND, Fi);
281
+ }
282
+
283
+ return true;
284
+ }
285
+
286
+
287
+
288
+ String RelOps[] = {">=", "<=", "!=", "<>", ">", "<", "=", (String) 0};
289
+
290
+ Boolean SExpression()
291
+ /* ----------- */
292
+ {
293
+ int o, Fi=BN;
294
+
295
+ if ( ! AExpression() ) FailSyn("expression");
296
+
297
+ if ( (o = FindOne(RelOps)) >= 0 )
298
+ {
299
+ BN += strlen(RelOps[o]);
300
+
301
+ if ( ! AExpression() ) FailSyn("expression");
302
+
303
+ DumpOp(( o == 0 ? OP_GE :
304
+ o == 1 ? OP_LE :
305
+ o == 4 ? OP_GT :
306
+ o == 5 ? OP_LT :
307
+ o == 2 || o == 3 ?
308
+ ( TStack[TSN-1].Type == 'S' ? OP_SNE : OP_NE ) :
309
+ ( TStack[TSN-1].Type == 'S' ? OP_SEQ : OP_EQ ) ), Fi);
310
+ }
311
+
312
+ return true;
313
+ }
314
+
315
+
316
+
317
+ String AddOps[] = {"+", "-", (String) 0};
318
+
319
+ Boolean AExpression()
320
+ /* ----------- */
321
+ {
322
+ int o, Fi=BN;
323
+
324
+ if ( Buff[BN] == ' ' ) BN++;
325
+
326
+ if ( (o = FindOne(AddOps)) >= 0 )
327
+ {
328
+ BN += 1;
329
+ }
330
+
331
+ if ( ! Term() ) FailSyn("expression");
332
+
333
+ if ( o == 1 ) DumpOp(OP_UMINUS, Fi);
334
+
335
+ while ( (o = FindOne(AddOps)) >= 0 )
336
+ {
337
+ BN += 1;
338
+
339
+ if ( ! Term() ) FailSyn("arithmetic expression");
340
+
341
+ DumpOp((char)(OP_PLUS + o), Fi);
342
+ }
343
+
344
+ return true;
345
+ }
346
+
347
+
348
+
349
+ String MultOps[] = {"*", "/", "%", (String) 0};
350
+
351
+ Boolean Term()
352
+ /* ---- */
353
+ {
354
+ int o, Fi=BN;
355
+
356
+ if ( ! Factor() ) FailSyn("expression");
357
+
358
+ while ( (o = FindOne(MultOps)) >= 0 )
359
+ {
360
+ BN += 1;
361
+
362
+ if ( ! Factor() ) FailSyn("arithmetic expression");
363
+
364
+ DumpOp((char)(OP_MULT + o), Fi);
365
+ }
366
+
367
+ return true;
368
+ }
369
+
370
+
371
+
372
+ Boolean Factor()
373
+ /* ---- */
374
+ {
375
+ int Fi=BN;
376
+
377
+ if ( ! Primary() ) FailSyn("value");
378
+
379
+ while ( Find("^") )
380
+ {
381
+ BN += 1;
382
+
383
+ if ( ! Primary() ) FailSyn("exponent");
384
+
385
+ DumpOp(OP_POW, Fi);
386
+ }
387
+
388
+ return true;
389
+ }
390
+
391
+
392
+
393
+ Boolean Primary()
394
+ /* ------- */
395
+ {
396
+ if ( Atom() )
397
+ {
398
+ return true;
399
+ }
400
+ else
401
+ if ( Find("(") )
402
+ {
403
+ BN++;
404
+ if ( ! Expression() ) FailSyn("expression in parentheses");
405
+ if ( ! Find(")") ) FailSyn("')'");
406
+ BN++;
407
+ return true;
408
+ }
409
+ else
410
+ {
411
+ FailSyn("attribute, value, or '('");
412
+ }
413
+ }
414
+
415
+
416
+
417
+ String Funcs[] = {"sin", "cos", "tan", "log", "exp", "int", (String) 0};
418
+
419
+ Boolean Atom()
420
+ /* ---- */
421
+ {
422
+ char *EndPtr, *Str, Date[11], Time[9];
423
+ int o, FirstBN, Fi=BN;
424
+ ContValue F;
425
+ Attribute Att;
426
+
427
+ if ( Buff[BN] == ' ' ) BN++;
428
+
429
+ if ( Buff[BN] == '"' )
430
+ {
431
+ FirstBN = ++BN;
432
+ while ( Buff[BN] != '"' )
433
+ {
434
+ if ( ! Buff[BN] ) FailSyn("closing '\"'");
435
+ BN++;
436
+ }
437
+
438
+ /* Make a copy of the string without double quotes */
439
+
440
+ Buff[BN] = '\00';
441
+ Str = strdup(Buff + FirstBN);
442
+
443
+ Buff[BN++] = '"';
444
+ Dump(OP_STR, 0, Str, Fi);
445
+ }
446
+ else
447
+ if ( (Att = FindAttName()) )
448
+ {
449
+ BN += strlen(AttName[Att]);
450
+
451
+ Dump(OP_ATT, 0, (String) (long) Att, Fi);
452
+ }
453
+ else
454
+ if ( isdigit(Buff[BN]) )
455
+ {
456
+ /* Check for date or time first */
457
+
458
+ if ( ( Buff[BN+4] == '/' && Buff[BN+7] == '/' ||
459
+ Buff[BN+4] == '-' && Buff[BN+7] == '-' )&&
460
+ isdigit(Buff[BN+1]) && isdigit(Buff[BN+2]) &&
461
+ isdigit(Buff[BN+3]) &&
462
+ isdigit(Buff[BN+5]) && isdigit(Buff[BN+6]) &&
463
+ isdigit(Buff[BN+8]) && isdigit(Buff[BN+9]) )
464
+ {
465
+ memcpy(Date, Buff+BN, 10);
466
+ Date[10] = '\00';
467
+ if ( (F = DateToDay(Date)) == 0 )
468
+ {
469
+ Error(BADDEF1, Date, "date");
470
+ }
471
+
472
+ BN += 10;
473
+ }
474
+ else
475
+ if ( Buff[BN+2] == ':' && Buff[BN+5] == ':' &&
476
+ isdigit(Buff[BN+1]) &&
477
+ isdigit(Buff[BN+3]) && isdigit(Buff[BN+4]) &&
478
+ isdigit(Buff[BN+6]) && isdigit(Buff[BN+7]) )
479
+ {
480
+ memcpy(Time, Buff+BN, 8);
481
+ Time[8] = '\00';
482
+ if ( (F = TimeToSecs(Time)) == 0 )
483
+ {
484
+ Error(BADDEF1, Time, "time");
485
+ }
486
+
487
+ BN += 8;
488
+ }
489
+ else
490
+ {
491
+ F = strtod(Buff+BN, &EndPtr);
492
+
493
+ /* Check for period after integer */
494
+
495
+ if ( EndPtr > Buff+BN+1 && *(EndPtr-1) == '.' )
496
+ {
497
+ EndPtr--;
498
+ }
499
+
500
+ BN = EndPtr - Buff;
501
+ }
502
+
503
+ Dump(OP_NUM, F, Nil, Fi);
504
+ }
505
+ else
506
+ if ( (o = FindOne(Funcs)) >= 0 )
507
+ {
508
+ BN += 3;
509
+
510
+ if ( ! Find("(") ) FailSyn("'(' after function name");
511
+ BN++;
512
+
513
+ if ( ! Expression() ) FailSyn("expression");
514
+
515
+ if ( ! Find(")") ) FailSyn("')' after function argument");
516
+ BN++;
517
+
518
+ DumpOp((char)(OP_SIN + o), Fi);
519
+ }
520
+ else
521
+ if ( Buff[BN] == '?' )
522
+ {
523
+ BN++;
524
+ if ( TStack[TSN-1].Type == 'N' )
525
+ {
526
+ Dump(OP_NUM, _UNK.cval, Nil, Fi);
527
+ }
528
+ else
529
+ {
530
+ Dump(OP_STR, 0, Nil, Fi);
531
+ }
532
+ }
533
+ else
534
+ if ( ! memcmp(Buff+BN, "N/A", 3) )
535
+ {
536
+ BN += 3;
537
+ if ( TStack[TSN-1].Type == 'N' )
538
+ {
539
+ Dump(OP_NUM, _NA.cval, Nil, Fi);
540
+ }
541
+ else
542
+ {
543
+ Dump(OP_STR, 0, strdup("N/A"), Fi);
544
+ }
545
+ }
546
+ else
547
+ {
548
+ return false;
549
+ }
550
+
551
+ return true;
552
+ }
553
+
554
+
555
+
556
+ /*************************************************************************/
557
+ /* */
558
+ /* Skip spaces and check for specific string */
559
+ /* */
560
+ /*************************************************************************/
561
+
562
+
563
+ Boolean Find(String S)
564
+ /* ---- */
565
+ {
566
+ if ( Buff[BN] == ' ' ) BN++;
567
+
568
+ return ( ! Buff[BN] ? false : ! memcmp(Buff+BN, S, strlen(S)) );
569
+ }
570
+
571
+
572
+
573
+ /*************************************************************************/
574
+ /* */
575
+ /* Find one of a zero-terminated list of alternatives */
576
+ /* */
577
+ /*************************************************************************/
578
+
579
+
580
+ int FindOne(String *Alt)
581
+ /* ------- */
582
+ {
583
+ int a;
584
+
585
+ for ( a = 0 ; Alt[a] ; a++ )
586
+ {
587
+ if ( Find(Alt[a]) ) return a;
588
+ }
589
+
590
+ return -1;
591
+ }
592
+
593
+
594
+
595
+ /*************************************************************************/
596
+ /* */
597
+ /* Find an attribute name */
598
+ /* */
599
+ /*************************************************************************/
600
+
601
+
602
+ Attribute FindAttName()
603
+ /* ----------- */
604
+ {
605
+ Attribute Att, LongestAtt=0;
606
+
607
+ ForEach(Att, 1, MaxAtt-1)
608
+ {
609
+ if ( ! Exclude(Att) && Find(AttName[Att]) )
610
+ {
611
+ if ( ! LongestAtt ||
612
+ strlen(AttName[Att]) > strlen(AttName[LongestAtt]) )
613
+ {
614
+ LongestAtt = Att;
615
+ }
616
+ }
617
+ }
618
+
619
+ if ( LongestAtt && ( MaxClass == 1 || ClassThresh ) &&
620
+ ! strcmp(ClassName[1], AttName[LongestAtt]) )
621
+ {
622
+ Error(BADDEF4, Nil, Nil);
623
+ }
624
+
625
+ return LongestAtt;
626
+ }
627
+
628
+
629
+
630
+ /*************************************************************************/
631
+ /* */
632
+ /* Error message routines. Syntax errors come from the */
633
+ /* recursive descent parser, semantics errors from the routines */
634
+ /* that build up the equivalent polish */
635
+ /* */
636
+ /*************************************************************************/
637
+
638
+
639
+ void DefSyntaxError(String Msg)
640
+ /* -------------- */
641
+ {
642
+ String RestOfText;
643
+ int i=10;
644
+
645
+ if ( ! PreviousError )
646
+ {
647
+ RestOfText = Buff + BN;
648
+
649
+ /* Abbreviate text if longer than 12 characters */
650
+
651
+ if ( CharWidth(RestOfText) > 12 )
652
+ {
653
+ #ifdef UTF8
654
+ /* Find beginning of UTF-8 character */
655
+
656
+ for ( ; (RestOfText[i] & 0x80) ; i++)
657
+ ;
658
+ #endif
659
+ RestOfText[i] = RestOfText[i+1] = '.';
660
+ }
661
+
662
+ Error(BADDEF1, RestOfText, Msg);
663
+ PreviousError = true;
664
+ }
665
+ }
666
+
667
+
668
+
669
+ void DefSemanticsError(int Fi, String Msg, int OpCode)
670
+ /* ----------------- */
671
+ {
672
+ char Exp[1000], XMsg[1000], Op[1000];
673
+
674
+ if ( ! PreviousError )
675
+ {
676
+ /* Abbreviate the input if necessary */
677
+
678
+ if ( BN - Fi > 23 )
679
+ {
680
+ sprintf(Exp, "%.10s...%.10s", Buff+Fi, Buff+BN-10);
681
+ }
682
+ else
683
+ {
684
+ sprintf(Exp, "%.*s", BN - Fi, Buff+Fi);
685
+ }
686
+
687
+ switch ( OpCode )
688
+ {
689
+ case OP_AND: sprintf(Op, "%s", "and"); break;
690
+ case OP_OR: sprintf(Op, "%s", "or"); break;
691
+ case OP_SEQ:
692
+ case OP_EQ: sprintf(Op, "%s", "="); break;
693
+ case OP_SNE:
694
+ case OP_NE: sprintf(Op, "%s", "<>"); break;
695
+ case OP_GT: sprintf(Op, "%s", ">"); break;
696
+ case OP_GE: sprintf(Op, "%s", ">="); break;
697
+ case OP_LT: sprintf(Op, "%s", "<"); break;
698
+ case OP_LE: sprintf(Op, "%s", "<="); break;
699
+ case OP_PLUS: sprintf(Op, "%s", "+"); break;
700
+ case OP_MINUS: sprintf(Op, "%s", "-"); break;
701
+ case OP_UMINUS: sprintf(Op, "%s", "unary -"); break;
702
+ case OP_MULT: sprintf(Op, "%s", "*"); break;
703
+ case OP_DIV: sprintf(Op, "%s", "/"); break;
704
+ case OP_MOD: sprintf(Op, "%s", "%"); break;
705
+ case OP_POW: sprintf(Op, "%s", "^"); break;
706
+ case OP_SIN: sprintf(Op, "%s", "sin"); break;
707
+ case OP_COS: sprintf(Op, "%s", "cos"); break;
708
+ case OP_TAN: sprintf(Op, "%s", "tan"); break;
709
+ case OP_LOG: sprintf(Op, "%s", "log"); break;
710
+ case OP_EXP: sprintf(Op, "%s", "exp"); break;
711
+ case OP_INT: sprintf(Op, "%s", "int");
712
+ }
713
+
714
+ sprintf(XMsg, "%s with '%s'", Msg, Op);
715
+ Error(BADDEF2, Exp, XMsg);
716
+ PreviousError = true;
717
+ }
718
+ }
719
+
720
+
721
+
722
+ /*************************************************************************/
723
+ /* */
724
+ /* Reverse polish routines. These use a model of the stack */
725
+ /* during expression evaluation to detect type conflicts etc */
726
+ /* */
727
+ /*************************************************************************/
728
+
729
+
730
+
731
+ void Dump(char OpCode, ContValue F, String S, int Fi)
732
+ /* ---- */
733
+ {
734
+ if ( Buff[Fi] == ' ' ) Fi++;
735
+
736
+ if ( ! UpdateTStack(OpCode, F, S, Fi) ) return;
737
+
738
+ /* Make sure enough room for this element */
739
+
740
+ if ( DN >= DefSize-1 )
741
+ {
742
+ Realloc(AttDef[MaxAtt], DefSize += 100, DefElt);
743
+ }
744
+
745
+ DefOp(AttDef[MaxAtt][DN]) = OpCode;
746
+ if ( OpCode == OP_ATT || OpCode == OP_STR )
747
+ {
748
+ DefSVal(AttDef[MaxAtt][DN]) = S;
749
+ }
750
+ else
751
+ {
752
+ DefNVal(AttDef[MaxAtt][DN]) = F;
753
+ }
754
+
755
+ DN++;
756
+ }
757
+
758
+
759
+
760
+ void DumpOp(char OpCode, int Fi)
761
+ /* ------ */
762
+ {
763
+ Dump(OpCode, 0, Nil, Fi);
764
+ }
765
+
766
+
767
+
768
+ Boolean UpdateTStack(char OpCode, ContValue F, String S, int Fi)
769
+ /* ------------ */
770
+ {
771
+ if ( TSN >= TStackSize )
772
+ {
773
+ Realloc(TStack, TStackSize += 50, EltRec);
774
+ }
775
+
776
+ switch ( OpCode )
777
+ {
778
+ case OP_ATT:
779
+ TStack[TSN].Type = ( Continuous((long) S) ? 'N' : 'S' );
780
+ break;
781
+
782
+ case OP_NUM:
783
+ TStack[TSN].Type = 'N';
784
+ break;
785
+
786
+ case OP_STR:
787
+ TStack[TSN].Type = 'S';
788
+ break;
789
+
790
+ case OP_AND:
791
+ case OP_OR:
792
+ if ( TStack[TSN-2].Type != 'B' || TStack[TSN-1].Type != 'B' )
793
+ {
794
+ FailSem("non-logical value");
795
+ }
796
+ TSN -= 2;
797
+ break;
798
+
799
+ case OP_EQ:
800
+ case OP_NE:
801
+ if ( TStack[TSN-2].Type != TStack[TSN-1].Type )
802
+ {
803
+ FailSem("incompatible values");
804
+ }
805
+ TSN -= 2;
806
+ TStack[TSN].Type = 'B';
807
+ break;
808
+
809
+ case OP_GT:
810
+ case OP_GE:
811
+ case OP_LT:
812
+ case OP_LE:
813
+ if ( TStack[TSN-2].Type != 'N' || TStack[TSN-1].Type != 'N' )
814
+ {
815
+ FailSem("non-arithmetic value");
816
+ }
817
+ TSN -= 2;
818
+ TStack[TSN].Type = 'B';
819
+ break;
820
+
821
+ case OP_SEQ:
822
+ case OP_SNE:
823
+ if ( TStack[TSN-2].Type != 'S' || TStack[TSN-1].Type != 'S' )
824
+ {
825
+ FailSem("incompatible values");
826
+ }
827
+ TSN -= 2;
828
+ TStack[TSN].Type = 'B';
829
+ break;
830
+
831
+ case OP_PLUS:
832
+ case OP_MINUS:
833
+ case OP_MULT:
834
+ case OP_DIV:
835
+ case OP_MOD:
836
+ case OP_POW:
837
+ if ( TStack[TSN-2].Type != 'N' || TStack[TSN-1].Type != 'N' )
838
+ {
839
+ FailSem("non-arithmetic value");
840
+ }
841
+ TSN -= 2;
842
+ break;
843
+
844
+ case OP_UMINUS:
845
+ if ( TStack[TSN-1].Type != 'N' )
846
+ {
847
+ FailSem("non-arithmetic value");
848
+ }
849
+ TSN--;
850
+ break;
851
+
852
+ case OP_SIN:
853
+ case OP_COS:
854
+ case OP_TAN:
855
+ case OP_LOG:
856
+ case OP_EXP:
857
+ case OP_INT:
858
+ if ( TStack[TSN-1].Type != 'N' )
859
+ {
860
+ FailSem("non-arithmetic argument");
861
+ }
862
+ TSN--;
863
+ }
864
+
865
+ TStack[TSN].Fi = Fi;
866
+ TStack[TSN].Li = BN-1;
867
+ TSN++;
868
+
869
+ return true;
870
+ }
871
+
872
+
873
+
874
+ /*************************************************************************/
875
+ /* */
876
+ /* Evaluate an implicit attribute for a case */
877
+ /* */
878
+ /*************************************************************************/
879
+
880
+ #define CUnknownVal(AV) (AV.cval==_UNK.cval)
881
+ #define DUnknownVal(AV) (AV.dval==_UNK.dval)
882
+ #define DUNA(a) (DUnknownVal(XStack[a]) || NotApplicVal(XStack[a]))
883
+ #define CUNA(a) (CUnknownVal(XStack[a]) || NotApplicVal(XStack[a]))
884
+ #define C1(x) (CUNA(XSN-1) ? _UNK.cval : (x))
885
+ #define C2(x) (CUNA(XSN-1) || CUNA(XSN-2) ? _UNK.cval : (x))
886
+ #define CD2(x) (CUNA(XSN-1) || CUNA(XSN-2) ? _UNK.dval : (x))
887
+ #define D2(x) (DUNA(XSN-1) || DUNA(XSN-2) ? _UNK.dval : (x))
888
+
889
+
890
+ AttValue EvaluateDef(Definition D, DataRec Case)
891
+ /* ----------- */
892
+ {
893
+ XStackElt XStack[100]; /* allows 100-level nesting */
894
+ int XSN=0, DN, bv1, bv2, Mult;
895
+ double cv1, cv2;
896
+ String sv1, sv2;
897
+ Attribute Att;
898
+ DefElt DElt;
899
+ AttValue ReturnVal;
900
+
901
+ for ( DN = 0 ; ; DN++)
902
+ {
903
+ switch ( DefOp((DElt = D[DN])) )
904
+ {
905
+ case OP_ATT:
906
+ Att = (long) DefSVal(DElt);
907
+
908
+ if ( Continuous(Att) )
909
+ {
910
+ XStack[XSN++].cval = CVal(Case, Att);
911
+ }
912
+ else
913
+ {
914
+ XStack[XSN++].sval =
915
+ ( Unknown(Case, Att) && ! NotApplic(Case, Att) ? 0 :
916
+ AttValName[Att][XDVal(Case, Att)] );
917
+ }
918
+ break;
919
+
920
+ case OP_NUM:
921
+ XStack[XSN++].cval = DefNVal(DElt);
922
+ break;
923
+
924
+ case OP_STR:
925
+ XStack[XSN++].sval = DefSVal(DElt);
926
+ break;
927
+
928
+ case OP_AND:
929
+ bv1 = XStack[XSN-2].dval;
930
+ bv2 = XStack[XSN-1].dval;
931
+ XStack[XSN-2].dval = ( bv1 == 3 || bv2 == 3 ? 3 :
932
+ D2(bv1 == 2 && bv2 == 2 ? 2 : 3) );
933
+ XSN--;
934
+ break;
935
+
936
+ case OP_OR:
937
+ bv1 = XStack[XSN-2].dval;
938
+ bv2 = XStack[XSN-1].dval;
939
+ XStack[XSN-2].dval = ( bv1 == 2 || bv2 == 2 ? 2 :
940
+ D2(bv1 == 2 || bv2 == 2 ? 2 : 3) );
941
+ XSN--;
942
+ break;
943
+
944
+ case OP_EQ:
945
+ cv1 = XStack[XSN-2].cval;
946
+ cv2 = XStack[XSN-1].cval;
947
+ XStack[XSN-2].dval = ( cv1 == cv2 ? 2 : 3 );
948
+ XSN--;
949
+ break;
950
+
951
+ case OP_NE:
952
+ cv1 = XStack[XSN-2].cval;
953
+ cv2 = XStack[XSN-1].cval;
954
+ XStack[XSN-2].dval = ( cv1 != cv2 ? 2 : 3 );
955
+ XSN--;
956
+ break;
957
+
958
+ case OP_GT:
959
+ cv1 = XStack[XSN-2].cval;
960
+ cv2 = XStack[XSN-1].cval;
961
+ XStack[XSN-2].dval = CD2(cv1 > cv2 ? 2 : 3);
962
+ XSN--;
963
+ break;
964
+
965
+ case OP_GE:
966
+ cv1 = XStack[XSN-2].cval;
967
+ cv2 = XStack[XSN-1].cval;
968
+ XStack[XSN-2].dval = CD2(cv1 >= cv2 ? 2 : 3);
969
+ XSN--;
970
+ break;
971
+
972
+ case OP_LT:
973
+ cv1 = XStack[XSN-2].cval;
974
+ cv2 = XStack[XSN-1].cval;
975
+ XStack[XSN-2].dval = CD2(cv1 < cv2 ? 2 : 3);
976
+ XSN--;
977
+ break;
978
+
979
+ case OP_LE:
980
+ cv1 = XStack[XSN-2].cval;
981
+ cv2 = XStack[XSN-1].cval;
982
+ XStack[XSN-2].dval = CD2(cv1 <= cv2 ? 2 : 3);
983
+ XSN--;
984
+ break;
985
+
986
+ case OP_SEQ:
987
+ sv1 = XStack[XSN-2].sval;
988
+ sv2 = XStack[XSN-1].sval;
989
+ XStack[XSN-2].dval =
990
+ ( ! sv1 && ! sv2 ? 2 :
991
+ ! sv1 || ! sv2 ? 3 :
992
+ ! strcmp(sv1, sv2) ? 2 : 3 );
993
+ XSN--;
994
+ break;
995
+
996
+ case OP_SNE:
997
+ sv1 = XStack[XSN-2].sval;
998
+ sv2 = XStack[XSN-1].sval;
999
+ XStack[XSN-2].dval =
1000
+ ( ! sv1 && ! sv2 ? 3 :
1001
+ ! sv1 || ! sv2 ? 2 :
1002
+ strcmp(sv1, sv2) ? 2 : 3 );
1003
+ XSN--;
1004
+ break;
1005
+
1006
+ case OP_PLUS:
1007
+ cv1 = XStack[XSN-2].cval;
1008
+ cv2 = XStack[XSN-1].cval;
1009
+ XStack[XSN-2].cval = C2(cv1 + cv2);
1010
+ XSN--;
1011
+ break;
1012
+
1013
+ case OP_MINUS:
1014
+ cv1 = XStack[XSN-2].cval;
1015
+ cv2 = XStack[XSN-1].cval;
1016
+ XStack[XSN-2].cval = C2(cv1 - cv2);
1017
+ XSN--;
1018
+ break;
1019
+
1020
+ case OP_MULT:
1021
+ cv1 = XStack[XSN-2].cval;
1022
+ cv2 = XStack[XSN-1].cval;
1023
+ XStack[XSN-2].cval = C2(cv1 * cv2);
1024
+ XSN--;
1025
+ break;
1026
+
1027
+ case OP_DIV:
1028
+ /* Note: have to set precision of result */
1029
+
1030
+ cv1 = XStack[XSN-2].cval;
1031
+ cv2 = XStack[XSN-1].cval;
1032
+ if ( ! cv2 ||
1033
+ CUnknownVal(XStack[XSN-2]) ||
1034
+ CUnknownVal(XStack[XSN-1]) ||
1035
+ NotApplicVal(XStack[XSN-2]) ||
1036
+ NotApplicVal(XStack[XSN-1]) )
1037
+ {
1038
+ XStack[XSN-2].cval = _UNK.cval;
1039
+ }
1040
+ else
1041
+ {
1042
+ Mult = Denominator(cv1);
1043
+ cv1 = cv1 / cv2;
1044
+ while ( fabs(cv2) > 1 )
1045
+ {
1046
+ Mult *= 10;
1047
+ cv2 /= 10;
1048
+ }
1049
+ XStack[XSN-2].cval = rint(cv1 * Mult) / Mult;
1050
+ }
1051
+ XSN--;
1052
+ break;
1053
+
1054
+ case OP_MOD:
1055
+ cv1 = XStack[XSN-2].cval;
1056
+ cv2 = XStack[XSN-1].cval;
1057
+ XStack[XSN-2].cval = C2(fmod(cv1, cv2));
1058
+ XSN--;
1059
+ break;
1060
+
1061
+ case OP_POW:
1062
+ cv1 = XStack[XSN-2].cval;
1063
+ cv2 = XStack[XSN-1].cval;
1064
+ XStack[XSN-2].cval =
1065
+ ( CUNA(XSN-1) || CUNA(XSN-2) ||
1066
+ ( cv1 < 0 && ceil(cv2) != cv2 ) ? _UNK.cval :
1067
+ pow(cv1, cv2) );
1068
+ XSN--;
1069
+ break;
1070
+
1071
+ case OP_UMINUS:
1072
+ cv1 = XStack[XSN-1].cval;
1073
+ XStack[XSN-1].cval = C1(-cv1);
1074
+ break;
1075
+
1076
+ case OP_SIN:
1077
+ cv1 = XStack[XSN-1].cval;
1078
+ XStack[XSN-1].cval = C1(sin(cv1));
1079
+ break;
1080
+
1081
+ case OP_COS:
1082
+ cv1 = XStack[XSN-1].cval;
1083
+ XStack[XSN-1].cval = C1(cos(cv1));
1084
+ break;
1085
+
1086
+ case OP_TAN:
1087
+ cv1 = XStack[XSN-1].cval;
1088
+ XStack[XSN-1].cval = C1(tan(cv1));
1089
+ break;
1090
+
1091
+ case OP_LOG:
1092
+ cv1 = XStack[XSN-1].cval;
1093
+ XStack[XSN-1].cval =
1094
+ ( CUNA(XSN-1) || cv1 <= 0 ? _UNK.cval : log(cv1) );
1095
+ break;
1096
+
1097
+ case OP_EXP:
1098
+ cv1 = XStack[XSN-1].cval;
1099
+ XStack[XSN-1].cval = C1(exp(cv1));
1100
+ break;
1101
+
1102
+ case OP_INT:
1103
+ cv1 = XStack[XSN-1].cval;
1104
+ XStack[XSN-1].cval = C1(rint(cv1));
1105
+ break;
1106
+
1107
+ case OP_END:
1108
+ ReturnVal.cval = XStack[0].cval; /* cval >= dval bytes */
1109
+ return ReturnVal;
1110
+ }
1111
+ }
1112
+ }