/* 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