mud/fluffos-2.23-ds03/make_func.y
2020-09-06 05:43:07 -07:00

418 lines
9.4 KiB
Plaintext

%{
#define EDIT_SOURCE
#define NO_OPCODES
#include "std.h"
#include "make_func.h"
#include "lex.h"
#include "preprocess.h"
#include "edit_source.h"
#include <stdlib.h>
#ifdef WIN32
#define MSDOS
#include <process.h>
#endif
void mf_fatal(const char *);
void yyerror(char const *);
int num_buff = 0;
int op_code, efun_code, efun1_code;
char *oper_codes[MAX_FUNC];
char *efun_codes[MAX_FUNC], *efun1_codes[MAX_FUNC];
char *efun_names[MAX_FUNC], *efun1_names[MAX_FUNC];
const char *key[MAX_FUNC], *buf[MAX_FUNC];
int min_arg = -1, limit_max = 0;
/*
* arg_types is the types of all arguments. A 0 is used as a delimiter,
* marking next argument. An argument can have several types.
*/
int arg_types[1000], last_current_type;
/*
* Store the types of the current efun. They will be copied into the
* arg_types list if they were not already there (to save memory).
*/
int curr_arg_types[40], curr_arg_type_size;
struct type {
const char *name;
int num;
} types[] = {
{ "void", VOID },
{ "int", INT },
{ "string", STRING },
{ "object", OBJECT },
{ "mapping", MAPPING },
{ "mixed", MIXED },
{ "unknown", UNKNOWN },
{ "float", FLOAT},
{ "function", FUNCTION},
{ "buffer", BUFFER}
};
#define NELEMS(arr) (sizeof arr / sizeof arr[0])
%}
%union {
int number;
const char *string;
}
%token ID NUM DEFAULT OPERATOR
%type <number> type arg_list basic typel arg_type typel2 NUM
%type <string> ID optional_ID optional_default
%%
specs: /* empty */ | specs spec ;
spec: operator | func;
operator: OPERATOR op_list ';' ;
op_list: op | op_list ',' op ;
op: ID
{
char f_name[500],c;
int i = 2;
sprintf(f_name, "F_%s", $1);
while ((c = f_name[i])) {
if (islower(c)) f_name[i++] = toupper(c);
else i++;
}
oper_codes[op_code] = (char *) malloc(i+1);
strcpy(oper_codes[op_code], f_name);
free((void *)$1);
op_code++;
} ;
optional_ID: ID | /* empty */ { $$ = ""; } ;
optional_default: /* empty */ { $$="DEFAULT_NONE"; }
| DEFAULT ':' NUM
{
static char buf[40];
sprintf(buf, "%i", $3);
$$ = buf;
}
| DEFAULT ':' ID
{
if (strcmp($3, "F__THIS_OBJECT"))
yyerror("Illegal default");
$$ = "DEFAULT_THIS_OBJECT";
} ;
func: type ID optional_ID '(' arg_list optional_default ')' ';'
{
char buff[500];
char f_name[500];
int i, len;
if (min_arg == -1)
min_arg = $5;
if (min_arg > 4) mf_fatal("min_arg > 4\n");
if ($3[0] == '\0') {
if (strlen($2) + 1 + 2 > sizeof f_name)
mf_fatal("A local buffer was too small!(1)\n");
sprintf(f_name, "F_%s", $2);
len = strlen(f_name);
for (i=0; i < len; i++) {
if (islower(f_name[i]))
f_name[i] = toupper(f_name[i]);
}
if (min_arg == 1 && !limit_max && $5 == 1) {
efun1_codes[efun1_code] = (char *) malloc(len + 1);
strcpy(efun1_codes[efun1_code], f_name);
efun1_names[efun1_code] = (char *) malloc(len - 1);
strcpy(efun1_names[efun1_code], $2);
efun1_code++;
} else {
efun_codes[efun_code] = (char *) malloc(len + 1);
strcpy(efun_codes[efun_code], f_name);
efun_names[efun_code] = (char *) malloc(len - 1);
strcpy(efun_names[efun_code], $2);
efun_code++;
}
} else {
if (strlen($3) + 1 + 17 > sizeof f_name)
mf_fatal("A local buffer was too small(2)!\n");
sprintf(f_name, "F_%s | F_ALIAS_FLAG", $3);
len = strlen(f_name);
for (i=0; i < len; i++) {
if (islower(f_name[i]))
f_name[i] = toupper(f_name[i]);
}
free((void *)$3);
}
for(i=0; i < last_current_type; i++) {
int j;
for (j = 0; j+i<last_current_type && j < curr_arg_type_size; j++)
{
if (curr_arg_types[j] != arg_types[i+j])
break;
}
if (j == curr_arg_type_size)
break;
}
if (i == last_current_type) {
int j;
for (j=0; j < curr_arg_type_size; j++) {
arg_types[last_current_type++] = curr_arg_types[j];
if (last_current_type == NELEMS(arg_types))
yyerror("Array 'arg_types' is too small");
}
}
if (!strcmp($2, "call_other") && !lookup_define("CAST_CALL_OTHERS")) {
$1 = MIXED;
}
sprintf(buff, "{\"%s\",%s,0,0,%d,%d,%s,%s,%s,%s,%s,%d,%s},\n",
$2, f_name, min_arg, limit_max ? -1 : $5,
$1 != VOID ? ctype($1) : "TYPE_NOVALUE",
etype(0), etype(1), etype(2), etype(3), i, $6);
if (strlen(buff) > sizeof buff)
mf_fatal("Local buffer overwritten !\n");
key[num_buff] = $2;
buf[num_buff] = (char *) malloc(strlen(buff) + 1);
strcpy((char *)buf[num_buff], buff);
num_buff++;
min_arg = -1;
limit_max = 0;
curr_arg_type_size = 0;
} ;
type: basic | basic '*' { $$ = $1 | 0x10000; };
basic: ID
{
int i = NELEMS(types);
$$ = 0;
while (i--){
if (strcmp($1, types[i].name) == 0) {
$$ = types[i].num;
break;
}
}
if (!$$) {
char buf[256];
sprintf(buf, "Invalid type: %s", $1);
yyerror(buf);
}
free((void *)$1);
};
arg_list: /* empty */ { $$ = 0; }
| typel2 { $$ = 1; if ($1) min_arg = 0; }
| arg_list ',' typel2 { $$ = $1 + 1; if ($3) min_arg = $$ - 1; } ;
typel2: typel
{
$$ = $1;
curr_arg_types[curr_arg_type_size++] = 0;
if (curr_arg_type_size == NELEMS(curr_arg_types))
yyerror("Too many arguments");
} ;
arg_type: type
{
if ($1 != VOID) {
curr_arg_types[curr_arg_type_size++] = $1;
if (curr_arg_type_size == NELEMS(curr_arg_types))
yyerror("Too many arguments");
}
$$ = $1;
} ;
typel: arg_type { $$ = ($1 == VOID && min_arg == -1); }
| typel '|' arg_type { $$ = (min_arg == -1 && ($1 || $3 == VOID));}
| '.' '.' '.' { $$ = min_arg == -1 ; limit_max = 1; } ;
%%
const char *ctype (int n)
{
static char buff[100]; /* 100 is such a comfortable size :-) */
const char *p = (char *)NULL;
if (n & 0x10000)
strcpy(buff, "TYPE_MOD_ARRAY|");
else
buff[0] = '\0';
n &= ~0x10000;
switch(n) {
case FLOAT: p = "TYPE_REAL"; break;
case FUNCTION: p = "TYPE_FUNCTION"; break;
case VOID: p = "TYPE_VOID"; break;
case STRING: p = "TYPE_STRING"; break;
case INT: p = "TYPE_NUMBER"; break;
case OBJECT: p = "TYPE_OBJECT"; break;
case MAPPING: p = "TYPE_MAPPING"; break;
case BUFFER: p = "TYPE_BUFFER"; break;
case MIXED: p = "TYPE_ANY"; break;
case UNKNOWN: p = "TYPE_UNKNOWN"; break;
default: yyerror("Bad type!");
}
strcat(buff, p);
if (strlen(buff) + 1 > sizeof buff)
mf_fatal("Local buffer overwritten in ctype()");
return buff;
}
const char *etype1 (int n)
{
if (n & 0x10000)
return "T_ARRAY";
switch(n) {
case FLOAT:
return "T_REAL";
case FUNCTION:
return "T_FUNCTION";
case INT:
return "T_NUMBER";
case OBJECT:
return "T_OBJECT";
case MAPPING:
return "T_MAPPING";
case STRING:
return "T_STRING";
case BUFFER:
return "T_BUFFER";
case MIXED:
return "T_ANY"; /* 0 means any type */
default:
yyerror("Illegal type for argument");
}
return "What?";
}
const char *etype (int n)
{
int i;
int local_size = 100;
char *buff = (char *)malloc(local_size);
for (i=0; i < curr_arg_type_size; i++) {
if (n == 0)
break;
if (curr_arg_types[i] == 0)
n--;
}
if (i == curr_arg_type_size)
return "T_ANY";
buff[0] = '\0';
for(; curr_arg_types[i] != 0; i++) {
const char *p;
if (curr_arg_types[i] == VOID)
continue;
if (buff[0] != '\0')
strcat(buff, "|");
p = etype1(curr_arg_types[i]);
/*
* The number 2 below is to include the zero-byte and the next
* '|' (which may not come).
*/
if (strlen(p) + strlen(buff) + 2 > local_size) {
fprintf(stderr, "Buffer overflow!\n");
exit(1);
}
strcat(buff, etype1(curr_arg_types[i]));
}
if (!strcmp(buff, ""))
strcpy(buff, "T_ANY");
return buff;
}
int ident (int);
int yylex() {
register int c;
for(;;) {
switch(c = getc(yyin)){
case ' ':
case '\t':
continue;
case '\n':
current_line++;
continue;
case '!':
{
char buff[2048];
fgets(buff, 2047, yyin);
fprintf(stderr, "Configuration problem: %s\n", buff);
exit(-1);
}
case '#':
{
int line;
char aBuf[2048], fname[2048];
fgets(aBuf, 2047, yyin);
if (sscanf(aBuf, "%d \"%[^\"]\"", &line, fname)) {
current_line = line;
if (current_file) free(current_file);
current_file = (char*)malloc(strlen(fname) + 1);
strcpy(current_file, fname);
} else
if (sscanf(aBuf, "%d", &line)) current_line = line;
current_line++;
continue;
}
case EOF:
fclose(yyin);
return -1;
default:
if ((c >= '0' && c <= '9') || c == '-') {
int v;
int neg = 0;
v = 0;
if (c == '-') {
neg = 1;
c = '0';
}
do {
v = v * 10 + (c - '0');
c = getc(yyin);
} while (c >= '0' && c <= '9');
ungetc(c, yyin);
yylval.number = (neg ? -v : v);
return NUM;
}
if (isalunum(c))
return ident(c);
return c;
}
}
}
int ident (int c)
{
char buff[100];
int len;
for (len = 0; isalunum(c); c = getc(yyin)) {
buff[len++] = c;
if (len == sizeof buff - 1) {
yyerror("Too long indentifier");
break;
}
}
(void)ungetc(c, yyin);
buff[len] = '\0';
if (!strcmp(buff, "default"))
return DEFAULT;
if (!strcmp(buff, "operator"))
return OPERATOR;
yylval.string = (char *)malloc(strlen(buff)+1);
strcpy((char *)yylval.string, buff);
return ID;
}