summaryrefslogtreecommitdiff
path: root/src/iconc/dbase.c
blob: fdd3e5078960b755d2b4e5e51e5941d20cad62a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*
 * dbase.c - routines to access data base of implementation information
 *  produced by rtt.
 */
#include "../h/gsupport.h"
#include "../h/lexdef.h"
#include "ctrans.h"
#include "csym.h"
#include "ctree.h"
#include "ccode.h"
#include "cproto.h"
#include "cglobals.h"

/*
 * Prototypes.
 */
static int chck_spec (struct implement *ip);
static int acpt_op   (struct implement *ip);


static struct optab *optr; /* pointer into operator table */

/*
 * readdb - read data base produced by rtt.
 */
void readdb(db_name)
char *db_name;
   {
   char *op, *s;
   int i;
   struct implement *ip;
   char buf[MaxPath];			/* file name construction buffer */
   struct fileparts *fp;
   unsigned hashval;

   fp = fparse(db_name);
   if (*fp->ext == '\0')
      db_name = salloc(makename(buf, NULL, db_name, DBSuffix));
   else if (!smatch(fp->ext, DBSuffix))
      quitf("bad data base name: %s", db_name);

   if (!db_open(db_name, &s))
        db_err1(1, "cannot open data base");

   if (largeints && (*s == 'N')) {
       twarn("Warning, run-time system does not support large integers", NULL);
       largeints = 0;
       }

   /*
    * Read information about functions.
    */
   db_tbl("functions", bhash);

   /*
    * Read information about operators.
    */
   optr = optab;

   /*
    * read past operators header.
    */
   db_chstr("operators", "operators");

   while ((op = db_string()) != NULL) {
      if ((ip = db_impl('O')) == NULL)
         db_err2(1, "no implementation information for operator", op);
      ip->op = op;
      if (acpt_op(ip)) {
         db_code(ip);
         hashval = IHasher(op);
         ip->blink = ohash[hashval];
         ohash[hashval] = ip;
         db_chstr("end", "end");
         }
      else
         db_dscrd(ip);
      }
   db_chstr("endsect", "endsect");

   /*
    * Read information about keywords.
    */
   db_tbl("keywords", khash);

   db_close();

   /*
    * If error conversion is supported, make sure it is reflected in
    *   the minimum result sequence of operations.
    */
   if (err_conv) {
      for (i = 0; i < IHSize; ++i)
         for (ip = bhash[i]; ip != NULL; ip = ip->blink)
            if (ip->ret_flag & DoesEFail)
               ip->min_result = 0;
      for (i = 0; i < IHSize; ++i)
         for (ip = ohash[i]; ip != NULL; ip = ip->blink)
            if (ip->ret_flag & DoesEFail)
               ip->min_result = 0;
      for (i = 0; i < IHSize; ++i)
         for (ip = khash[i]; ip != NULL; ip = ip->blink)
            if (ip->ret_flag & DoesEFail)
               ip->min_result = 0;
      }
   }

/*
 * acpt_opt - given a data base entry for an operator determine if it
 *  is in iconc's operator table.
 */
static int acpt_op(ip)
struct implement *ip;
   {
   register char *op;
   register int opcmp;

   /*
    * Calls to this function are in lexical order by operator symbol continue
    *  searching operator table  from where we left off.
    */
   op = ip->op;
   for (;;) {
      /*
       * optab has augmented assignments out of lexical order. Skip anything
       *  which does not expect an implementation. This gets augmented
       *  assignments out of the way.
       */
      while (optr->expected == 0 && optr->tok.t_word != NULL)
         ++optr;
      if (optr->tok.t_word == NULL)
         return chck_spec(ip);
      opcmp = strcmp(op, optr->tok.t_word);
      if (opcmp > 0)
         ++optr;
      else if (opcmp < 0)
         return chck_spec(ip);
      else {
         if (ip->nargs == 1 && (optr->expected & Unary)) {
            if (optr->unary == NULL) {
               optr->unary = ip;
               return 1;
               }
            else
               return 0;
            }
         else if (ip->nargs == 2 && (optr->expected & Binary)) {
            if (optr->binary == NULL) {
               optr->binary = ip;
               return 1;
               }
            else
               return 0;
            }
         else
            return chck_spec(ip);
         }
      }
   }

/*
 * chck_spec - check whether the operator is one that does not use standard
 *    unary or binary syntax.
 */
static int chck_spec(ip)
struct implement *ip;
   {
   register char *op;
   int indx;

   indx = -1;
   op = ip->op;
   if (strcmp(op, "...") == 0) {
      if (ip->nargs == 2)
         indx = ToOp;
      else
         indx = ToByOp;
      }
   else if (strcmp(op, "[:]") == 0)
      indx = SectOp;
   else if (strcmp(op, "[]") == 0)
      indx = SubscOp;
   else if (strcmp(op, "[...]") == 0)
      indx = ListOp;

   if (indx == -1) {
      db_err2(0, "unexpected operator (or arity),", op);
      return 0;
      }
   if (spec_op[indx] == NULL) {
      spec_op[indx] = ip;
      return 1;
      }
   else
      return 0;
   }