1 %{
2 #define EDIT_SOURCE
3 #define NO_OPCODES
4 #include "std.h"
5 #include "make_func.h"
6 #include "lex.h"
7 #include "preprocess.h"
8 #include "edit_source.h"
9
10 #ifdef WIN32
11 #define MSDOS
12 #include <process.h>
13 #endif
14
15 void mf_fatal(char *);
16
17 int num_buff = 0;
18 int op_code, efun_code, efun1_code;
19 char *oper_codes[MAX_FUNC];
20 char *efun_codes[MAX_FUNC], *efun1_codes[MAX_FUNC];
21 char *efun_names[MAX_FUNC], *efun1_names[MAX_FUNC];
22 char *key[MAX_FUNC], *buf[MAX_FUNC];
23
24 int min_arg = -1, limit_max = 0;
25
26 /*
27 * arg_types is the types of all arguments. A 0 is used as a delimiter,
28 * marking next argument. An argument can have several types.
29 */
30 int arg_types[400], last_current_type;
31
32 /*
33 * Store the types of the current efun. They will be copied into the
34 * arg_types list if they were not already there (to save memory).
35 */
36 int curr_arg_types[40], curr_arg_type_size;
37
38 struct type {
39 char *name;
40 int num;
41 } types[] = {
42 { "void", VOID },
43 { "int", INT },
44 { "string", STRING },
45 { "object", OBJECT },
46 { "mapping", MAPPING },
47 { "mixed", MIXED },
48 { "unknown", UNKNOWN },
49 { "float", FLOAT},
50 { "function", FUNCTION},
51 { "buffer", BUFFER}
52 };
53
54 #define NELEMS(arr) (sizeof arr / sizeof arr[0])
55 %}
56
57 %union {
58 int number;
59 char *string;
60 }
61
62 %token ID NUM DEFAULT OPERATOR
63
64 %type <number> type arg_list basic typel arg_type typel2 NUM
65
66 %type <string> ID optional_ID optional_default
67
68 %%
69
70 specs: /* empty */ | specs spec ;
71
72 spec: operator | func;
73
74 operator: OPERATOR op_list ';' ;
75
76 op_list: op | op_list ',' op ;
77
78 op: ID
79 {
80 char f_name[500],c;
81 int i = 2;
82 sprintf(f_name, "F_%s", $1);
83 while ((c = f_name[i])) {
84 if (islower(c)) f_name[i++] = toupper(c);
85 else i++;
86 }
87 oper_codes[op_code] = (char *) malloc(i+1);
88 strcpy(oper_codes[op_code], f_name);
89 free($1);
90
91 op_code++;
92 } ;
93
94 optional_ID: ID | /* empty */ { $$ = ""; } ;
95
96 optional_default: /* empty */ { $$="DEFAULT_NONE"; }
97 | DEFAULT ':' NUM
98 {
99 static char buf[40];
100 sprintf(buf, "%i", $3);
101 $$ = buf;
102 }
103 | DEFAULT ':' ID
104 {
105 if (strcmp($3, "F__THIS_OBJECT"))
106 yyerror("Illegal default");
107 $$ = "DEFAULT_THIS_OBJECT";
108 } ;
109
110 func: type ID optional_ID '(' arg_list optional_default ')' ';'
111 {
112 char buff[500];
113 char f_name[500];
114 int i, len;
115 if (min_arg == -1)
116 min_arg = $5;
117 if (min_arg > 4) mf_fatal("min_arg > 4/n");
118 if ($3[0] == '/0') {
119 if (strlen($2) + 1 + 2 > sizeof f_name)
120 mf_fatal("A local buffer was too small!(1)/n");
121 sprintf(f_name, "F_%s", $2);
122 len = strlen(f_name);
123 for (i=0; i < len; i++) {
124 if (islower(f_name[i]))
125 f_name[i] = toupper(f_name[i]);
126 }
127 if (min_arg == 1 && !limit_max && $5 == 1) {
128 efun1_codes[efun1_code] = (char *) malloc(len + 1);
129 strcpy(efun1_codes[efun1_code], f_name);
130 efun1_names[efun1_code] = (char *) malloc(len - 1);
131 strcpy(efun1_names[efun1_code], $2);
132 efun1_code++;
133 } else {
134 efun_codes[efun_code] = (char *) malloc(len + 1);
135 strcpy(efun_codes[efun_code], f_name);
136 efun_names[efun_code] = (char *) malloc(len - 1);
137 strcpy(efun_names[efun_code], $2);
138 efun_code++;
139 }
140 } else {
141 if (strlen($3) + 1 + 17 > sizeof f_name)
142 mf_fatal("A local buffer was too small(2)!/n");
143 sprintf(f_name, "F_%s | F_ALIAS_FLAG", $3);
144 len = strlen(f_name);
145 for (i=0; i < len; i++) {
146 if (islower(f_name[i]))
147 f_name[i] = toupper(f_name[i]);
148 }
149 free($3);
150 }
151 for(i=0; i < last_current_type; i++) {
152 int j;
153 for (j = 0; j+i<last_current_type && j < curr_arg_type_size; j++)
154 {
155 if (curr_arg_types[j] != arg_types[i+j])
156 break;
157 }
158 if (j == curr_arg_type_size)
159 break;
160 }
161 if (i == last_current_type) {
162 int j;
163 for (j=0; j < curr_arg_type_size; j++) {
164 arg_types[last_current_type++] = curr_arg_types[j];
165 if (last_current_type == NELEMS(arg_types))
166 yyerror("Array 'arg_types' is too small");
167 }
168 }
169 if (!strcmp($2, "call_other") && !lookup_define("CAST_CALL_OTHERS")) {
170 $1 = MIXED;
171 }
172 sprintf(buff, "{/"%s/",%s,0,0,%d,%d,%s,%s,%s,%s,%s,%d,%s},/n",
173 $2, f_name, min_arg, limit_max ? -1 : $5,
174 $1 != VOID ? ctype($1) : "TYPE_NOVALUE",
175 etype(0), etype(1), etype(2), etype(3), i, $6);
176 if (strlen(buff) > sizeof buff)
177 mf_fatal("Local buffer overwritten !/n");
178
179 key[num_buff] = $2;
180 buf[num_buff] = (char *) malloc(strlen(buff) + 1);
181 strcpy(buf[num_buff], buff);
182 num_buff++;
183 min_arg = -1;
184 limit_max = 0;
185 curr_arg_type_size = 0;
186 } ;
187
188 type: basic | basic '*' { $$ = $1 | 0x10000; };
189
190 basic: ID
191 {
192 int i = NELEMS(types);
193 $$ = 0;
194 while (i--){
195 if (strcmp($1, types[i].name) == 0) {
196 $$ = types[i].num;
197 break;
198 }
199 }
200 if (!$$) {
201 char buf[256];
202 sprintf(buf, "Invalid type: %s", $1);
203 yyerror(buf);
204 }
205 free($1);
206 };
207
208 arg_list: /* empty */ { $$ = 0; }
209 | typel2 { $$ = 1; if ($1) min_arg = 0; }
210 | arg_list ',' typel2 { $$ = $1 + 1; if ($3) min_arg = $$ - 1; } ;
211
212 typel2: typel
213 {
214 $$ = $1;
215 curr_arg_types[curr_arg_type_size++] = 0;
216 if (curr_arg_type_size == NELEMS(curr_arg_types))
217 yyerror("Too many arguments");
218 } ;
219
220 arg_type: type
221 {
222 if ($1 != VOID) {
223 curr_arg_types[curr_arg_type_size++] = $1;
224 if (curr_arg_type_size == NELEMS(curr_arg_types))
225 yyerror("Too many arguments");
226 }
227 $$ = $1;
228 } ;
229
230 typel: arg_type { $$ = ($1 == VOID && min_arg == -1); }
231 | typel '|' arg_type { $$ = (min_arg == -1 && ($1 || $3 == VOID));}
232 | '.' '.' '.' { $$ = min_arg == -1 ; limit_max = 1; } ;
233
234 %%
235
236 char *ctype P1(int, n)
237 {
238 static char buff[100]; /* 100 is such a comfortable size :-) */
239 char *p = (char *)NULL;
240
241 if (n & 0x10000)
242 strcpy(buff, "TYPE_MOD_ARRAY|");
243 else
244 buff[0] = '/0';
245 n &= ~0x10000;
246 switch(n) {
247 case FLOAT: p = "TYPE_REAL"; break;
248 case FUNCTION: p = "TYPE_FUNCTION"; break;
249 case VOID: p = "TYPE_VOID"; break;
250 case STRING: p = "TYPE_STRING"; break;
251 case INT: p = "TYPE_NUMBER"; break;
252 case OBJECT: p = "TYPE_OBJECT"; break;
253 case MAPPING: p = "TYPE_MAPPING"; break;
254 case BUFFER: p = "TYPE_BUFFER"; break;
255 case MIXED: p = "TYPE_ANY"; break;
256 case UNKNOWN: p = "TYPE_UNKNOWN"; break;
257 default: yyerror("Bad type!");
258 }
259 strcat(buff, p);
260 if (strlen(buff) + 1 > sizeof buff)
261 mf_fatal("Local buffer overwritten in ctype()");
262 return buff;
263 }
264
265 char *etype1 P1(int, n)
266 {
267 if (n & 0x10000)
268 return "T_ARRAY";
269 switch(n) {
270 case FLOAT:
271 return "T_REAL";
272 case FUNCTION:
273 return "T_FUNCTION";
274 case INT:
275 return "T_NUMBER";
276 case OBJECT:
277 return "T_OBJECT";
278 case MAPPING:
279 return "T_MAPPING";
280 case STRING:
281 return "T_STRING";
282 case BUFFER:
283 return "T_BUFFER";
284 case MIXED:
285 return "T_ANY"; /* 0 means any type */
286 default:
287 yyerror("Illegal type for argument");
288 }
289 return "What?";
290 }
291
292 char *etype P1(int, n)
293 {
294 int i;
295 int local_size = 100;
296 char *buff = (char *)malloc(local_size);
297
298 for (i=0; i < curr_arg_type_size; i++) {
299 if (n == 0)
300 break;
301 if (curr_arg_types[i] == 0)
302 n--;
303 }
304 if (i == curr_arg_type_size)
305 return "T_ANY";
306 buff[0] = '/0';
307 for(; curr_arg_types[i] != 0; i++) {
308 char *p;
309 if (curr_arg_types[i] == VOID)
310 continue;
311 if (buff[0] != '/0')
312 strcat(buff, "|");
313 p = etype1(curr_arg_types[i]);
314 /*
315 * The number 2 below is to include the zero-byte and the next
316 * '|' (which may not come).
317 */
318 if (strlen(p) + strlen(buff) + 2 > local_size) {
319 fprintf(stderr, "Buffer overflow!/n");
320 exit(1);
321 }
322 strcat(buff, etype1(curr_arg_types[i]));
323 }
324 if (!strcmp(buff, ""))
325 strcpy(buff, "T_ANY");
326 return buff;
327 }
328
329 int ident PROT((int));
330
331 int yylex() {
332 register int c;
333
334 for(;;) {
335 switch(c = getc(yyin)){
336 case ' ':
337 case '/t':
338 continue;
339 case '/n':
340 current_line++;
341 continue;
342 case '!':
343 {
344 char buff[2048];
345 fgets(buff, 2047, yyin);
346 fprintf(stderr, "Configuration problem: %s/n", buff);
347 exit(-1);
348 }
349 case '#':
350 {
351 int line;
352
353 char aBuf[2048], fname[2048];
354 fgets(aBuf, 2047, yyin);
355 if (sscanf(aBuf, "%d /"%[^/"]/"", &line, fname)) {
356 current_line = line;
357 if (current_file) free(current_file);
358 current_file = (char*)malloc(strlen(fname) + 1);
359 strcpy(current_file, fname);
360 } else
361 if (sscanf(aBuf, "%d", &line)) current_line = line;
362 current_line++;
363 continue;
364 }
365 case EOF:
366 fclose(yyin);
367 return -1;
368 default:
369 if ((c >= '0' && c <= '9') || c == '-') {
370 int v;
371 int neg = 0;
372 v = 0;
373 if (c == '-') {
374 neg = 1;
375 c = '0';
376 }
377 do {
378 v = v * 10 + (c - '0');
379 c = getc(yyin);
380 } while (c >= '0' && c <= '9');
381 ungetc(c, yyin);
382 yylval.number = (neg ? -v : v);
383 return NUM;
384 }
385 if (isalunum(c))
386 return ident(c);
387 return c;
388 }
389 }
390 }
391
392 int ident P1(int, c)
393 {
394 char buff[100];
395 int len;
396
397 for (len = 0; isalunum(c); c = getc(yyin)) {
398 buff[len++] = c;
399 if (len == sizeof buff - 1) {
400 yyerror("Too long indentifier");
401 break;
402 }
403 }
404 (void)ungetc(c, yyin);
405 buff[len] = '/0';
406 if (!strcmp(buff, "default"))
407 return DEFAULT;
408 if (!strcmp(buff, "operator"))
409 return OPERATOR;
410
411 yylval.string = (char *)malloc(strlen(buff)+1);
412 strcpy(yylval.string, buff);
413 return ID;
414 }