/* next error will still return 1 by default */
%{
#include "y.tab.h"
#define FLEX_SCANNER
#include "lint.h"
#include "string.h"
#include "lnode.h"
#include "config.h"
int current_line;
int total_lines; /* Used to compute average compiled lines/s */
char *current_file;
extern char *argument_name;
int number(), lookup_table(), string(), atoi();
/*
* Flex doesn't handle negative characters, but this change will at least
* not crash the game.
*/
#ifdef YY_FATAL_ERROR
#undef YY_FATAL_ERROR
#define YY_FATAL_ERROR(msg) \
{ \
fputs( msg, stderr ); \
putc( '\n', stderr ); \
error(msg); \
}
#endif
#ifdef FLEX
#define yywrap() 1
#endif
/*
* using a lookup table cuts the size of the lexer down
*/
struct tl {
char *name;
int ret_val;
};
static struct tl table[] = {
{"remote_command" , F_REMOTE_COMMAND },
{"ls" , F_LS },
{"cat" , F_CAT },
{"grep" , F_GREP },
{"rm" , F_RM },
{"log_file" , F_LOG_FILE },
{"else" , F_ELSE },
{"reallocate" , F_REALLOCATE },
{"index" , F_INDEX },
{"searcha" , F_SEARCHA },
{"in_editor" , F_IN_EDITOR },
{"contents" , F_CONTENTS },
{"find_living" , F_FIND_LIVING },
{"find_player" , F_FIND_PLAYER },
{"previous_object" , F_PREVIOUS_OBJECT },
{"inherit" , F_INHERIT },
{"tell_object" , F_TELL_OBJECT },
{"query_host_name" , F_QUERY_HOST_NAME },
{"tail" , F_TAIL },
{"file_name" , F_FILE_NAME },
{"query_verb" , F_QUERY_VERB },
{"this_verb" , F_QUERY_VERB },
{"snoop" , F_SNOOP },
{"input_to" , F_INPUT_TO },
{"rmdir" , F_RMDIR },
{"mkdir" , F_MKDIR },
{"crypt" , F_CRYPT },
{"first_inventory" , F_FIRST_INVENTORY },
{"regcomp" , F_REGCOMP },
{"regexec" , F_REGEXEC },
{"transfer" , F_TRANSFER },
{"next_inventory" , F_NEXT_INVENTORY },
{"string" , F_STRING_DECL },
{"shout" , F_SHOUT },
{"sscanf" , F_SSCANF },
{"extract" , F_EXTRACT },
{"ed" , F_ED },
{"localcmd" , F_LOCALCMD },
{"swap" , F_SWAP },
{"explode" , F_EXPLODE },
{"break" , F_BREAK },
{"intp" , F_INTP },
{"pointerp" , F_POINTERP },
{"objectp" , F_OBJECTP },
{"stringp" , F_STRINGP },
{"users" , F_USERS },
{"ctime" , F_CTIME },
{"disable_commands" , F_DISABLE_COMMANDS },
{"allocate" , F_ALLOCATE },
{"combine_free_list" , F_COMBINE_FREE_LIST },
{"continue" , F_CONTINUE },
{"while" , F_WHILE },
{"capitalize" , F_CAPITALIZE },
{"living" , F_LIVING },
{"interactive" , F_INTERACTIVE },
{"lower_case" , F_LOWER_CASE },
{"set_heart_beat" , F_SET_HEART_BEAT },
{"strlen" , F_STRLEN },
{"say" , F_SAY },
{"tell_room" , F_TELL_ROOM },
{"find_object" , F_FIND_OBJECT },
{"add_worth" , F_ADD_WORTH },
{"time" , F_TIME },
{"create_wizard" , F_CREATE_WIZARD },
{"destruct" , F_DESTRUCT },
{"static" , F_STATIC },
{"environment" , F_ENVIRONMENT },
{"save_object" , F_SAVE_OBJECT },
{"enable_commands" , F_ENABLE_COMMANDS },
{"sizeof" , F_SIZEOF },
{"random" , F_RANDOM },
{"restore_object" , F_RESTORE_OBJECT },
{"this_object" , F_THIS_OBJECT },
{"clone_object" , F_CLONE_OBJECT },
{"this_player" , F_THIS_PLAYER },
{"if" , F_IF },
{"status" , F_STATUS },
{"object" , F_STATUS },
{"return" , F_RETURN },
{"write" , F_WRITE },
{"add_verb" , F_ADD_VERB },
{"add_xverb" , F_ADD_XVERB },
{"add_adj" , F_ADD_ADJ },
{"add_subst" , F_ADD_SUBST },
{"add_action" , F_ADD_ACTION },
{"move_object" , F_MOVE_OBJECT },
{"present" , F_PRESENT },
{"call_out" , F_CALL_OUT },
{"remove_call_out" , F_REMOVE_CALL_OUT },
{"find_call_out" , F_FIND_CALL_OUT },
{"creator" , F_CREATOR },
{"caller" , F_CALLER },
{"query_ip_number" , F_QUERY_IP_NUMBER },
{"command" , F_COMMAND },
{"set_light" , F_SET_LIGHT },
{"int" , F_INT },
{"call_other" , F_CALL_OTHER },
{"shutdown" , F_SHUTDOWN },
{"typeof" , F_TYPEOF },
{"cp" , F_CP },
{"rename" , F_RENAME },
{"read_file" , F_READ_FILE },
{"query_snoop" , F_QUERY_SNOOP },
{"write_file" , F_WRITE_FILE },
{"file_size" , F_FILE_SIZE },
{"parse_command" , F_PARSE_COMMAND },
{"implode" , F_IMPLODE },
{"query_idle" , F_QUERY_IDLE },
{"do" , F_DO },
{"for" , F_FOR },
{"filter_objects" , F_FILTER_OBJECTS },
{"query_load_average" , F_QUERY_LOAD_AVERAGE },
{"catch" , F_CATCH },
{"throw" , F_THROW },
{"set_bit" , F_SET_BIT },
{"clear_bit" , F_CLEAR_BIT },
{"test_bit" , F_TEST_BIT },
{"notify_fail" , F_NOTIFY_FAIL },
{"set_living_name" , F_SET_LIVING_NAME },
{ 0, 0}
};
extern char *local_names[];
extern int current_number_of_locals;
extern char *string_copy();
void pre_processor_info();
%}
#ifdef LEX
%e 1500
%p 5000
%n 1000
%k 1000
%a 2500
%o 3000
#endif
dec (0|[1-9][0-9]*)
oct (0[0-7]+)
hex (0[xX][0-9a-fA-F]+)
ident ([_a-zA-Z][_a-zA-Z0-9]*)
string (\"([^"\n]|\\\")*\")
%%
";" { return ';'; }
"(" { return '('; }
")" { return ')'; }
"," { return ','; }
"{" { return '{'; }
"}" { return '}'; }
"++" { return F_INC; }
"--" { return F_DEC; }
"?" { return '?'; }
":" { return ':'; }
"~" { return '~'; }
"&&" { return F_LAND; }
"&" { return '&'; }
"&=" { return F_AND_EQ; }
"||" { return F_LOR; }
"|" { return '|'; }
"|=" { return F_OR_EQ; }
"^" { return '^'; }
"^=" { return F_XOR_EQ; }
"<<" { return F_LSH; }
"<<=" { return F_LSH_EQ; }
">>" { return F_RSH; }
">>=" { return F_RSH_EQ; }
"!" { return F_NOT; }
"->" { return F_ARROW; }
"=" { return '='; }
"-" { return '-'; }
"-=" { return F_SUB_EQ; }
"+" { return '+'; }
"+=" { return F_ADD_EQ; }
"*" { return '*'; }
"*=" { return F_MULT_EQ; }
"%" { return '%'; }
"%=" { return F_MOD_EQ; }
"/" { return '/'; }
"/=" { return F_DIV_EQ; }
"<" { return '<'; }
">" { return '>'; }
">=" { return F_GE; }
"<=" { return F_LE; }
"==" { return F_EQ; }
"!=" { return F_NE; }
"::" { return F_COLON_COLON; }
^#.*$ { pre_processor_info(yytext); }
"[" { return '['; }
"]" { return ']'; }
{dec} { return dec(yytext); }
{hex} { return hex(yytext); }
{oct} { return oct(yytext); }
'.' { yylval.lnode = (struct lnode *)alloc_lnode_number(F_NUMBER,
yytext[1]);
return F_NUMBER; }
{ident} { return lookup_table(yytext); }
{string} { return string(yytext); }
[\t ] { break; }
"\n" { current_line++;
if (current_line & L_MASK) {
yyerror("Too many lines.\n");
current_line = 0;
}
total_lines++;
}
. { char buff[100]; sprintf(buff, "Illegal character '%c'", yytext[0]);
yyerror(buff); }
%%
extern YYSTYPE yylval;
#ifdef LEX
int yywrap() { return 1; }
#endif
int lookup_table(str)
char *str;
{
int i;
for (i=0; table[i].name; i++) {
if (*str != table[i].name[0]) continue;
if (strcmp(str, table[i].name) == 0) return(table[i].ret_val);
}
for (i=current_number_of_locals-1; i>=0; i--) {
if (strcmp(local_names[i], str) == 0) {
yylval.lnode = (struct lnode *)alloc_lnode_number(F_LOCAL_NAME, i);
return F_LOCAL_NAME;
}
}
if (argument_name && strcmp(str, argument_name) == 0)
return F_ARGUMENT;
yylval.string = string_copy(str);
return F_IDENTIFIER;
}
/*
* debugging, gives the name of a single.
*/
static char cbuf[100];
char * cmdname(c)
int c;
{
int i;
switch (c) {
case F_LOCAL_NAME: return "Local var def";
case F_ARGUMENT: return "First Argument";
}
for (i=0; table[i].name; i++) {
if (c == table[i].ret_val) return table[i].name;
}
sprintf(cbuf, "Identifier? (%d)", c);
return cbuf;
}
int string(str)
char *str;
{
char *p;
p = (char *)string_copy(str);
yylval.string = p;
for (str++; str[1] != '\0'; str++, p++) {
if (str[0] == '\\' && str[1] == 'n') {
*p = '\n';
str++;
} else if (str[0] == '\\' && str[1] == 't') {
*p = '\t';
str++;
} else if (str[0] == '\\' && str[1] == '"') { /* LA */
*p = '"'; /* LA */
str++; /* LA */
if (!str[1]) {
yyerror("Unterminated string");
break;
}
} else if (str[0] == '\\') {
*p = str[1];
str++;
} else
*p = *str;
}
*p = '\0';
return F_STRING;
}
int dec(str)
char *str;
{
int i;
i = atoi(str);
return number(i);
}
int hex(str)
char *str;
{
int i;
sscanf(str, "%x", &i);
return number(i);
}
int oct(str)
char *str;
{
int i;
sscanf(str, "%x", &i);
return number(i);
}
int number(i)
int i;
{
if (i == 0) {
yylval.lnode = (struct lnode *)alloc_lnode_single(F_CONST0);
return F_CONST0;
}
if (i == 1) {
yylval.lnode = (struct lnode *)alloc_lnode_single(F_CONST1);
return F_CONST1;
}
yylval.lnode =(struct lnode *)alloc_lnode_number(F_NUMBER, i);
return F_NUMBER;
}
void start_new_file(f)
FILE *f;
{
extern int yyprevious;
#ifdef FLEX
yy_init = 1;
#endif
#ifdef LEX
extern int yyprevious; /* KLUDGE! */
NLSTATE;
yysptr = yysbuf;
#endif
yyin = f;
}
void pre_processor_info(str)
char *str;
{
int line,i;
char file[100];
if (sscanf(str, "# %d \"%s\"", &line, file) != 2)
return;
i = strlen(file);
if (file[i-1] == '"')
file[i-1] = '\0';
free(current_file);
current_file = string_copy(file);
current_line = line - 1;
}
#ifdef 0
#ifdef LEX
void fix_vars()
{
extern int yyprevious;
current_line = 0;
yyprevious = 10;
yylineno = 1;
yysptr = yysbuf;
}
#endif
#endif