#define PARSER_C #include <stdio.h> #include <stdlib.h> #include <string.h> #include "gen.h" #include "mflagnames.h" #include "oflagnames.h" #include "pflagnames.h" #include "lflagnames.h" #include "sflagnames.h" #include "config.h" #include "events.h" /***************************************************************************** ** PROTOTYPE FUNCTIONS ****************************************************************************/ stmt_list_record *get_statements(token_record *the_token, FILE *the_file, mudcode_record *mudcode, hashTable *the_hash, int stop_at1, int stop_at2); stmt_record *get_identifier(token_record *the_token, FILE *the_file, mudcode_record *mudcode, Boolean Expect_Semicolon); /***************************************************************************** ** UTILITY FUNCTIONS ****************************************************************************/ char thezonenam[MAXNAMLEN]; /* holds current zonename for error report purposes */ char theitem[MAXNAMLEN+15]; char itemname[MAXNAMLEN+1]; int return_type = 0; /* holds the return type for passing up functions */ Boolean Valid = True; /* If no errors have been reported yet */ int error_counter = 0; /* How many errors we have had */ /*************************************************************************** ** ** to_neg - states an error, putting filename and line in the error ** ** Parameters: the_err - the string to display ** line - the line the error occured on in the zone file ** ** ** ***************************************************************************/ void to_neg(char *the_str) { char nextchar; char charhold; char *tmp_char; tmp_char = the_str; nextchar = *tmp_char; *tmp_char = '-'; tmp_char++; while (nextchar != '\0') { charhold = *tmp_char; *tmp_char = nextchar; nextchar = charhold; tmp_char++; } } /*************************************************************************** ** ** state_error - states an error, putting filename and line in the error ** ** Parameters: the_err - the string to display ** line - the line the error occured on in the zone file ** ** ** ***************************************************************************/ void state_error(char *the_err, int line) { if (line == 0) printf("%s%s - %s\n", error_counter == 0 ? "\n" : "",thezonenam, the_err); else printf("%s%s - %s - %s\n", error_counter == 0 ? "\n" : "", thezonenam, the_err, theitem); Valid = False; error_counter++; } /*************************************************************************** ** ** state_error - states an error, putting filename and line in the error ** ** Parameters: the_err - the string to display ** line - the line the error occured on in the zone file ** ** ** ***************************************************************************/ void state_warning(char *the_err) { printf("%s%s - WARNING: %s - %s\n", error_counter == 0 ? "\n" : "", thezonenam, the_err, theitem); } /***************************************************************************** ** ** table_lookup - looks in a table for a certain string, or flag ** ** Parameters: elem - the element to check ** table - the table to check ** ** ret - -1 if not in table, otherwise table number ** ** remarks - old code taken from the old generator, not all my work :) ** *****************************************************************************/ int table_lookup(char *elem, char *table[]) { int i; int r; /* Since this function is only used to check flags, i made it so it will * not stumble over a flag that has been abbreviated. For example: * CanFire is allowed as is CanFireBall */ for (i=0; table[i] != TABLE_END; i++) { if (table[i] == NULL) continue; if ((r = strncasecmp(elem,table[i],strlen(elem)) == 0)) return i; /*else if (r < 0) return -1;*/ } return -1; } /**************************************************************************** ** ** find_mudfunct - finds the mudfunction record that matches the token string ** ** Parameters: the_token - t ** mudcode - ** ** ret - returns a token, NULL if end of file, ** ****************************************************************************/ mudcode_record *find_mudfunct(token_record *the_token, mudcode_record *mudcode) { mudcode_record *tmp_ptr; tmp_ptr = mudcode; while (tmp_ptr != NULL) { if (!strcasecmp(tmp_ptr->code_name, the_token->the_string)) return tmp_ptr; tmp_ptr = tmp_ptr->next_mudcode; } return NULL; } /***************************************************************************** ** ** xget_token - much like get_token, but with error messages displayed and ** freeing of the last token ** ** Parameters: the_token - the last token gotten ** the_file - the file to get tokens from ** ** ret - returns a token, NULL if end of file, ** ****************************************************************************/ token_record *xget_token(FILE *the_file) { token_record *temp_token; /* holds the token record to pass back */ char error[80]; /* get the next token and check for errors */ temp_token = get_token(the_file, '\n', False); /* if we find the end of file */ if (temp_token->token_type == -1) { return NULL; } /* if we find an invalid token, go to next line and start from there */ else if (temp_token->token_type == -3) { sprintf(error, "Invalid token %s found", temp_token->the_string); state_error(error, temp_token->line); if (next_line(the_file) == -1) { return NULL; } return xget_token(the_file); } /* printf("token: %s, line: %d\n", temp_token->the_string, temp_token->line); */ return temp_token; } /********************************************************************************* ** LINE PARSING FUNCTIONS *********************************************************************************/ /******************************************************************************** ** ** get_str_list_assn - gets a string or list of strings ** ** Parameters: the_token - the token passed in, usually to clear it ** the_file - the file to get tokens from ** ** ret - returns a pointer to a list of string records, or ** returns NULL for an error ** ********************************************************************************/ string_record *get_str_list_assn(token_record *the_token, FILE *the_file, Boolean Expect_Eq) { char until_char; /* the character to get until */ token_record *temp_token; /* used to hold teh token strings */ token_record *next_token; /* used to move through token string */ string_record *temp_string; /* holds a temp string list to pass back */ string_record *next_string; /* used to move through string list */ char the_assn[MAXNAMLEN]; char error[80]; /* get next token, expect '=' */ if (Expect_Eq) { strcpy(the_assn, the_token->the_string); if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_EQUALS) { state_error("Missing '=' on assignment", the_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return NULL; } return NULL; } /* get next token, expect a '"' or '^' */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_APOST) { until_char = '\''; } else if (the_token->token_type == T_RIGHTAPOST) { until_char = '`'; } else if (the_token->token_type == T_QUOTE) { until_char = '\"'; } else if (the_token->token_type == T_CARROT) { until_char = '^'; } else { sprintf(error, "Missing '\"', '^', or ''' after '=' on %s assignment\n" " found1 %s", the_assn, the_token->the_string); state_error(error, the_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); } return NULL; } } else until_char = '\"'; /* get all strings and put into the string_record */ temp_token = get_token(the_file, until_char, False); if (temp_token->token_type == -1) state_error("End of file reached before closing string character", temp_token->line); else if (temp_token->token_type == -2) state_error("Too many lines in string (limit 100), " "possible missing closing char", temp_token->line); else if (temp_token->token_type == -4) { state_error("String too long!", temp_token->line); return NULL; } else { next_token = temp_token; temp_string = (string_record *) memAlloc(string_record,1,REC_STRING); temp_string->the_string = (char *) memAlloc(char,strlen(next_token->the_string) + 1,REC_CHAR); next_string = temp_string; /* move along token list, assigning strings to a string record list instead */ while (next_token != NULL) { next_string->the_string = (char *) memAlloc(char,strlen(next_token->the_string) + 1,REC_CHAR); strcpy(next_string->the_string, next_token->the_string); next_token = next_token->more; if (next_token != NULL) { next_string->nextstr = (string_record *) memAlloc(string_record,1,REC_STRING); next_string = next_string->nextstr; } } return temp_string; } return NULL; } /******************************************************************************* ** ** get_str_assn - gets a string from an assignment, checking for proper format ** ** Parameters: the_token - the token gotten, to free it ** the_file - the file to pull tokens from ** length - the max length of the strings ** ** ret - returns a zone record with all zone data stored in it or attached to ** it or return \0 for an error ** *******************************************************************************/ char *get_str_assn(token_record *the_token, FILE *the_file, int length) { char get_for[MAXNAMLEN]; /* holds what we are getting the string for */ char error[80]; /* holds an error message string */ char *ret_string; strcpy(get_for, the_token->the_string); /* printf("checking: %s\n", the_token->the_string); */ /* get next token, expect '=' */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_EQUALS) { sprintf(error, "Missing '=' on %s assignment", get_for); state_error(error, the_token->line); if (next_line(the_file) == -1); { state_error("Unexpected end of file reached", 0); return NULL; } return NULL; } /* get next token, expect an identifier */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_APOST) { the_token = get_token(the_file, '\'', False); } else if (the_token->token_type == T_QUOTE) { the_token = get_token(the_file, '\"', False); } if ((the_token->token_type != T_IDENTIFIER) && (the_token->token_type != T_STRING)) { sprintf(error, "Missing identifier after '=' on %s assignment, found %s.", get_for, the_token->the_string); state_error(error, the_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return NULL; } ret_string = (char *) memAlloc(char, length,REC_CHAR); strcpy(ret_string, the_token->the_string); return ret_string; } if (strlen(the_token->the_string) >= length) { state_error("String too long", the_token->line); return NULL; } else { ret_string = (char *) memAlloc(char, length,REC_CHAR); strcpy(ret_string, the_token->the_string); return ret_string; } } /********************************************************************************* ** ** get_loc_str_assn - gets a string from an assignment, checking for proper format ** ** Parameters: the_token - the token gotten, to free it ** the_file - the file to pull tokens from ** length - the max length of the strings ** ** ret - returns a zone record with all zone data stored in it or attached to it or ** return \0 for an error ** ********************************************************************************/ char *get_loc_str_assn(token_record *the_token, FILE *the_file, int length) { char get_for[MAXNAMLEN]; /* holds what we are getting the string for */ char error[80]; /* holds an error message string */ char *ret_string; /* printf("checking: %s\n", the_token->the_string); */ strcpy(get_for, the_token->the_string); /* get next token, expect '=' */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_EQUALS) { state_error("Missing '=' on assignment", the_token->line); if (next_line(the_file) == -1); { state_error("Unexpected end of file reached", 0); return NULL; } return NULL; } /* get next token, expect an identifier */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_APOST) { the_token = get_token(the_file, '\'', False); } else if (the_token->token_type == T_QUOTE) { the_token = get_token(the_file, '\"', False); } else if (the_token->token_type == T_POUND) { /* get next token, expect a number */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if ((the_token->token_type != T_NUMERICAL)) { state_error("Missing number after '#' on location assignment", the_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return NULL; } return NULL; } ret_string = (char *) memAlloc(char, (MAXNAMLEN*2)+5,REC_CHAR); strcpy(ret_string, "#"); strcat(ret_string, the_token->the_string); /*return the_token->the_string;*/ return ret_string; } else if ((the_token->token_type != T_IDENTIFIER) && (the_token->token_type != T_CARROT)) { sprintf(error, "Missing identifier after '=' on %s assignment, found %s.", get_for, the_token->the_string); state_error(error, the_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return NULL; } ret_string = (char *) memAlloc(char, (MAXNAMLEN*2)+5,REC_CHAR); strcpy(ret_string, the_token->the_string); return ret_string; } if (the_token->token_type == T_CARROT) { /* get next token, expect an identifier */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_APOST) { the_token = get_token(the_file, '\'', False); } else if (the_token->token_type == T_QUOTE) { the_token = get_token(the_file, '\"', False); } else if ((the_token->token_type != T_IDENTIFIER)) { state_error("Missing identifer after '^' on location assignment", the_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return NULL; } return NULL; } ret_string = (char *) memAlloc(char,(MAXNAMLEN*2)+5,REC_CHAR); sprintf(ret_string, "^%s", the_token->the_string); return ret_string; } if (strlen(the_token->the_string) >= length) { state_error("String too long", the_token->line); return NULL; } else { ret_string = (char *) memAlloc(char,(MAXNAMLEN*2)+5,REC_CHAR); strcpy(ret_string, the_token->the_string); return ret_string; } } /********************************************************************************* ** ** get_int_assn - gets an integer from an assignment, checking for proper format ** ** Parameters: the_token - the token passed in, for freeing it ** the_file - the file to pull tokens from ** ** ret - an integer, or -1 if an error is found ** ********************************************************************************/ int get_int_assn(token_record *the_token, FILE *the_file) { int returnint; /* holds the integer value for returning */ Boolean is_negative = False; /* get next token, expect '=' */ if ((the_token = xget_token(the_file)) == NULL) return -1; if (the_token->token_type != T_EQUALS) { state_error("Missing '=' on assignment", the_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return -1; } return -1; } /* get next token, expect a numeral */ if ((the_token = xget_token(the_file)) == NULL) return -1; if (the_token->token_type == T_MINUS) { if ((the_token = xget_token(the_file)) == NULL) return -1; is_negative = True; } if (the_token->token_type != T_NUMERICAL) { state_error("Missing number after '=' on assignment", the_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return -1; } return -1; } returnint = atoi(the_token->the_string); if (is_negative) returnint = -returnint; return returnint; } /********************************************************************************* ** ** xget_location - gets all locations, returning a pointer to a string list ** ** Parameters: the_token - the token passed in, it is freed first ** the_file - the file pointer ** ** ret - -1 if encountered an error, otherwise the location ** ********************************************************************************/ loc_str_record *xget_location(token_record *the_token, FILE *the_file, Boolean allow_type) { loc_str_record *temp_loc_str; char error[80]; temp_loc_str = (loc_str_record *) memAlloc(loc_str_record,1,REC_LOCSTR); if (allow_type) { if ((the_token->token_type == T_INROOM) || (the_token->token_type == T_INCONTAINER) || (the_token->token_type == T_WORNBY) || (the_token->token_type == T_WIELDEDBY) || (the_token->token_type == T_BOTHBY) || (the_token->token_type == T_CARRIEDBY)) { temp_loc_str->loc_type = the_token->token_type; /* get next token, expect ':' */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_COLON) { state_error("Missing required : after location type.", the_token->line); } /* get next token, expect identifer */ if ((the_token = xget_token(the_file)) == NULL) return NULL; } else temp_loc_str->loc_type = T_INROOM; } else temp_loc_str->loc_type = T_INROOM; if ((the_token->token_type != T_IDENTIFIER)) { sprintf(error, "Missing identifier on location, found %s,", the_token->the_string); state_error(error, the_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return NULL; } } if (strlen(the_token->the_string) >= ((MAXNAMLEN*2)+1)) { state_error("String too long", the_token->line); return NULL; } strcpy(temp_loc_str->the_loc, the_token->the_string); lowercase(temp_loc_str->the_loc); if (check_next_char(the_file) == ',') { if ((the_token = xget_token(the_file)) == NULL) return NULL; if ((the_token = xget_token(the_file)) == NULL) return NULL; temp_loc_str->nextloc = xget_location(the_token, the_file, allow_type); } return temp_loc_str; } /************************************************************************************* ** ** get_location - gets all locations, returning a pointer to a string list ** ** Parameters: elem - the element to check ** table - the ** ** ret - -1 if encountered an error, otherwise the location ** *************************************************************************************/ loc_str_record *get_location(token_record *the_token, FILE *the_file, Boolean allow_type) { /* get next token, expect '=' */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_EQUALS) { state_error("Missing '=' on assignment", the_token->line); if (next_line(the_file) == -1); { state_error("Unexpected end of file reached", 0); return NULL; } return NULL; } /* get next token, expect a location type or identifier */ if ((the_token = xget_token(the_file)) == NULL) return NULL; return xget_location(the_token, the_file, allow_type); } /************************************************************************************* ** ** xget_flags - gets all flags, returning an integer value ** ** Parameters: elem - the element to check ** table - the table to check ** ** ret - -1 if encountered an error, otherwise the number of flags gotten ** *************************************************************************************/ int xget_flags(token_record *the_token, DoubleLongInt *FLAGS, char *table[], FILE *the_file) { token_record *temp_token; int flagnum; char error[120]; int count = 0; if ((temp_token = xget_token(the_file)) == NULL) return -1; if ((flagnum = table_lookup(temp_token->the_string, table)) == -1) { sprintf(error, "Unknown flag %s", temp_token->the_string); state_error(error, temp_token->line); } else { if (flagnum < 32) XSETBIT(FLAGS->b3,flagnum); else if (flagnum >= 32 && flagnum < 64) XSETBIT(FLAGS->b2,flagnum); else if (flagnum >= 64 && flagnum < 96) XSETBIT(FLAGS->b1,flagnum); count++; } if (check_next_char(the_file) == ',') { if ((temp_token = xget_token(the_file)) == NULL) return -1; return (count + xget_flags(temp_token, FLAGS, table, the_file)); } return count; } /************************************************************************************* ** ** xget_mflags - gets all flags, returning an integer value ** ** Parameters: elem - the element to check ** table - the table to check ** ** ret - -1 if encountered an error, otherwise the number of flags gotten ** *************************************************************************************/ int xget_mflags(token_record *the_token, MFLAGS *FLAGS, FILE *the_file) { token_record *temp_token; int flagnum; char error[120]; int count = 0; if ((temp_token = xget_token(the_file)) == NULL) return -1; if ((flagnum = table_lookup(temp_token->the_string, Mflags)) == -1) { sprintf(error, "Unknown flag %s", temp_token->the_string); state_error(error, temp_token->line); } else { if (flagnum < 32) XSETBIT(FLAGS->l,flagnum); else if (flagnum >= 32) XSETBIT(FLAGS->h,flagnum); count++; } if (check_next_char(the_file) == ',') { if ((temp_token = xget_token(the_file)) == NULL) return -1; return (count + xget_mflags(temp_token, FLAGS, the_file)); } return count; } /************************************************************************************* ** ** get_mflags - gets all flags, returning an integer value ** ** Parameters: elem - the element to check ** table - the table to check ** ** ret - -1 if encountered an error, otherwise the number of flags gotten ** *************************************************************************************/ int get_mflags(token_record *the_token, MFLAGS *FLAGS, FILE *the_file) { token_record *temp_token; /* get next token, expect '=' */ if ((temp_token = xget_token(the_file)) == NULL) return -1; if (temp_token->token_type != T_EQUALS) { state_error("Missing '=' for flags", temp_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return -1; } return -1; } return xget_mflags(temp_token, FLAGS, the_file); } /************************************************************************************* ** ** get_flags - gets all flags, returning an integer value ** ** Parameters: elem - the element to check ** table - the table to check ** ** ret - -1 if encountered an error, otherwise the number of flags gotten ** *************************************************************************************/ int get_flags(token_record *the_token, DoubleLongInt *FLAGS, char *table[], FILE *the_file) { token_record *temp_token; /* get next token, expect '=' */ if ((temp_token = xget_token(the_file)) == NULL) return -1; if (temp_token->token_type != T_EQUALS) { state_error("Missing '=' for flags", temp_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return -1; } return -1; } return xget_flags(temp_token, FLAGS, table, the_file); } /***************************************************************************** ** MUDCODE PARSING FUNCTIONS ****************************************************************************/ /****************************************************************************** ** ** get_const - gets the code in a for loop ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *********************************************************************************/ stmt_record *get_const(token_record *the_token, FILE *the_file, mudcode_record *mudcode, hashTable *the_hash) { const_decl *const_ptr; stmt_record *ret_union; Boolean is_neg = False; char error[80]; char the_zone[MAXNAMLEN]; char holder[(MAXNAMLEN*3)+5]; hashRecord *next_hash; int i; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_CONST_DECL; /* printf("status - beginning check on constant declaration\n"); */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_IDENTIFIER) { state_error("Identifier expected in constant declaration.", the_token->line); return NULL; } const_ptr = (const_decl * ) memAlloc(const_decl,1,REC_CONSTDECL); strcpy(const_ptr->const_name, the_token->the_string); if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_EQUALS) { state_error("Missing '=' in constant declaration.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if ((the_token->token_type != T_APOST) && (the_token->token_type != T_QUOTE) && (the_token->token_type != T_NUMERICAL) && (the_token->token_type != T_TRUE) && (the_token->token_type != T_FALSE) && (the_token->token_type != T_MINUS)) { state_error("Missing value after '='.", the_token->line); return NULL; } if ((the_token->token_type == T_TRUE) || (the_token->token_type == T_FALSE)) { const_ptr->const_type = T_BOOLEAN; const_ptr->assign = (char * ) memAlloc(char,strlen(the_token->the_string) + 1, REC_CHAR); strcpy(const_ptr->assign, the_token->the_string); } else if (the_token->token_type == T_QUOTE) { const_ptr->const_type = T_STR; ungetc('"', the_file); ungetc('=', the_file); const_ptr->assign = get_str_assn(the_token, the_file, MAXNAMLEN); } else if (the_token->token_type == T_APOST) { const_ptr->const_type = T_STR; ungetc('\'', the_file); ungetc('=', the_file); const_ptr->assign = get_str_assn(the_token, the_file, MAXNAMLEN); } else if (the_token->token_type == T_MINUS) { is_neg = True; if ((the_token = xget_token(the_file)) == NULL) return NULL; } /* This cant be an else if you just set is_neg and want to use it here. else */ if (the_token->token_type == T_NUMERICAL) { const_ptr->const_type = T_NUMBER; const_ptr->assign = (char * ) memAlloc(char,strlen(the_token->the_string) + 1, REC_CHAR); strcpy(const_ptr->assign, the_token->the_string); if (is_neg) { to_neg(const_ptr->assign); } } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_SEMICOLON) { state_error("Missing ';' at end of constant declaration.", the_token->line); return NULL; } strcpy(the_zone, thezonenam); for (i=0; i< strlen(the_zone); i++) if (the_zone[i] == '.') the_zone[i] = '\0'; sprintf(holder, "dec@%s@%s@%s", the_zone, itemname, const_ptr->const_name); lowercase(holder); /* printf("storing const: %s\n", holder); */ next_hash = createHashRecord(holder, const_ptr->const_type); if (addHashRecord(next_hash, the_hash) == 0) { sprintf(error, "Redefinition of variable %s", the_token->the_string); state_error(error, the_token->line); } /* printf("status - finishing check on constant declaration\n"); */ ret_union->stmt.const_d = const_ptr; return ret_union; } /****************************************************************************** ** ** xget_decl - gets the code in a for loop ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *********************************************************************************/ var_decl *xget_decl(token_record *the_token, FILE *the_file, mudcode_record *mudcode, int the_type, hashTable *the_hash) { var_decl *var_ptr; char holder[(MAXNAMLEN*3)+5]; hashRecord *next_hash; char error[80]; char the_zone[MAXNAMLEN]; int i; if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_IDENTIFIER) { state_error("Identifier expected in type declaration.", the_token->line); return NULL; } strcpy(the_zone, thezonenam); for (i=0; i< strlen(the_zone); i++) if (the_zone[i] == '.') the_zone[i] = '\0'; sprintf(holder, "dec@%s@%s@%s", the_zone, itemname, the_token->the_string); lowercase(holder); /* printf("storing: %s\n", holder); */ next_hash = createHashRecord(holder, the_type); if (addHashRecord(next_hash, the_hash) == 0) { sprintf(error, "Redefinition of variable %s", the_token->the_string); state_error(error, the_token->line); } var_ptr = (var_decl * ) memAlloc(var_decl,1,REC_VARDECL); var_ptr->var_type = the_type; strcpy(var_ptr->var_name, the_token->the_string); if (the_type == T_STR) { if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_LPAREN) { state_error("Missing required length for string declaration.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_NUMERICAL) { state_error("Missing number after '(' in string length declaration.", the_token->line); return NULL; } var_ptr->str_len = atoi(the_token->the_string); if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_RPAREN) { state_error("Missing ')' after string length.", the_token->line); return NULL; } } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_COMMA) { var_ptr->more_var = xget_decl(the_token, the_file, mudcode, the_type, the_hash); } else if (the_token->token_type == T_SEMICOLON) { var_ptr->more_var = NULL; /* printf("status - finishing check on declaration\n"); */ } else { state_error("Missing ';' after variable declaration.", the_token->line); return NULL; } return var_ptr; } /****************************************************************************** ** ** get_decl - ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *********************************************************************************/ stmt_record *get_decl(token_record *the_token, FILE *the_file, mudcode_record *mudcode, hashTable *the_hash) { int var_type; stmt_record *ret_union; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_VAR_DECL; /* printf("status - beginning check on declaration\n"); */ var_type = the_token->token_type; ret_union->stmt.var_d = xget_decl(the_token, the_file, mudcode, var_type, the_hash); return ret_union; } /****************************************************************************** ** ** get_for - gets the code in a for loop ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *********************************************************************************/ stmt_record *get_for(token_record *the_token, FILE *the_file, mudcode_record *mudcode, hashTable *the_hash) { for_decl *for_ptr; stmt_record *ret_union; Boolean is_neg = False; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_FOR_LOOP; /* printf("status - beginning check on for statement\n"); */ for_ptr = (for_decl * ) memAlloc(for_decl,1,REC_FORDECL); if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_MINUS) { if ((the_token = xget_token(the_file)) == NULL) return NULL; is_neg = True; } if (the_token->token_type != T_NUMERICAL) { state_error("Missing initial number expected after 'for'.", the_token->line); return NULL; } for_ptr->from = atoi(the_token->the_string); if (is_neg) { for_ptr->from = -(for_ptr->from); is_neg = False; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_TO) { state_error("Missing 'to' in for statement.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_MINUS) { if ((the_token = xget_token(the_file)) == NULL) return NULL; is_neg = True; } if (the_token->token_type != T_NUMERICAL) { state_error("Missing to number after 'to' in for statement.", the_token->line); return NULL; } for_ptr->to = atoi(the_token->the_string); if (is_neg) { for_ptr->to = -(for_ptr->to); } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_LOOP) { state_error("Missing 'loop' in for statement.", the_token->line); return NULL; } for_ptr->for_statements = get_statements(the_token, the_file, mudcode, the_hash, T_END, 0); if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_LOOP) { state_error("Missing 'loop' after 'end' in while loop.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_SEMICOLON) { state_error("Missing ';' after 'end loop' in while loop.", the_token->line); return NULL; } /* printf("status - check finished on for statement\n"); */ ret_union->stmt.for_d = for_ptr; return ret_union; } /****************************************************************************** ** ** get_boolean - gets the code for a repeat type ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *********************************************************************************/ bool_stmt *get_boolean(token_record *the_token, FILE *the_file, mudcode_record *mudcode, int until) { bool_stmt *the_bool; the_bool = (bool_stmt *) memAlloc(bool_stmt, 1,REC_BOOLSTMT); while (the_token->token_type != until) { if (the_token->token_type == T_AND) { strcat(the_bool->bool_string, "&&"); } else if (the_token->token_type == T_OR) { strcat(the_bool->bool_string, "||"); } else if (the_token->token_type == T_IDENTIFIER) { if ((the_bool->the_stmt = get_identifier(the_token, the_file, mudcode, False)) == NULL) { state_error("Error in boolean expression.", 1); return False; } if ((the_token = xget_token(the_file)) == NULL) return NULL; the_bool->next_bool = get_boolean(the_token, the_file, mudcode, until); return the_bool; } else { strcat(the_bool->bool_string, the_token->the_string); } if ((the_token = xget_token(the_file)) == NULL) return NULL; } the_bool->the_stmt = NULL; the_bool->next_bool = NULL; return the_bool; } /****************************************************************************** ** ** get_while - gets the code for a repeat type ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *********************************************************************************/ stmt_record *get_while(token_record *the_token, FILE *the_file, mudcode_record *mudcode, hashTable *the_hash) { while_decl *while_ptr; stmt_record *ret_union; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_WHILE_LOOP; /* printf("status - beginning check on while statement\n"); */ while_ptr = (while_decl * ) memAlloc(while_decl,1,REC_WHILEDECL); if ((the_token = xget_token(the_file)) == NULL) return NULL; /* printf("status - beginning check on boolean statement\n"); */ while_ptr->bool_exp = get_boolean(the_token, the_file, mudcode, T_LOOP); while_ptr->while_statements = get_statements(the_token, the_file, mudcode, the_hash, T_END, 0); if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_LOOP) { state_error("Missing 'loop' after 'end' in while loop.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_SEMICOLON) { state_error("Missing ';' after 'end loop' in while loop.", the_token->line); return NULL; } /* printf("status - check finished on while statement\n"); */ ret_union->stmt.while_d = while_ptr; return ret_union; } /****************************************************************************** ** ** get_repeat - gets the code for a repeat type ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *********************************************************************************/ stmt_record *get_repeat(token_record *the_token, FILE *the_file, mudcode_record *mudcode, hashTable *the_hash) { while_decl *repeat_ptr; stmt_record *ret_union; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_REPEAT_UNTIL; /* printf("status - beginning check on repeat statement\n"); */ repeat_ptr = (while_decl * ) memAlloc(while_decl,1,REC_WHILEDECL); repeat_ptr->while_statements = get_statements(the_token, the_file, mudcode, the_hash, T_UNTIL, 0); if ((the_token = xget_token(the_file)) == NULL) return NULL; repeat_ptr->bool_exp = get_boolean(the_token, the_file, mudcode, T_SEMICOLON); /* printf("status - check finished on repeat statement\n"); */ ret_union->stmt.while_d = repeat_ptr; return ret_union; } /****************************************************************************** ** ** get_block - gets a block statement ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *********************************************************************************/ stmt_record *get_block(token_record *the_token, FILE *the_file, mudcode_record *mudcode, hashTable *the_hash) { block_decl *block_ptr; stmt_record *ret_union; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_BLOCK; /* printf("Status - beginning check on block statements\n"); */ block_ptr = (block_decl * ) memAlloc(block_decl,1,REC_BLOCKDECL); block_ptr->block_statements = get_statements(the_token, the_file, mudcode, the_hash, T_END, 0); if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_SEMICOLON) { state_error("Missing expected ';' after end for block statements.", the_token->line); return NULL; } /* printf("Status - finishing check on block statements\n"); */ ret_union->stmt.block_d = block_ptr; return ret_union; } /************************************************************************************* ** ** xget_arith_number - ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *************************************************************************************/ arith_number *xget_arith_number(token_record *the_token, FILE *the_file, mudcode_record *mudcode) { arith_number *tmp_arith; tmp_arith = (arith_number *) memAlloc(arith_number, 1,REC_ARITHNR); while (the_token->token_type != T_SEMICOLON) { if (the_token->token_type == T_IDENTIFIER) { if ((tmp_arith->numberfunct = get_identifier(the_token, the_file, mudcode, False)) == NULL) { state_error("Error in arithmetic expression.", 1); return False; } if ((the_token = xget_token(the_file)) == NULL) return NULL; tmp_arith->next_number = xget_arith_number(the_token, the_file, mudcode); return tmp_arith; } else { strcat(tmp_arith->arith_str, the_token->the_string); } if ((the_token = xget_token(the_file)) == NULL) return NULL; } tmp_arith->numberfunct = NULL; tmp_arith->next_number = NULL; return tmp_arith; } /************************************************************************************* ** ** get_arith_number - ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *************************************************************************************/ stmt_record *get_arith_number(token_record *the_token, FILE *the_file, mudcode_record *mudcode) { stmt_record *ret_union; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_ARITH_NUM; ret_union->stmt.arith_num_d = xget_arith_number(the_token, the_file, mudcode); return ret_union; } /************************************************************************************* ** ** get_arith_string - ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *************************************************************************************/ stmt_record *get_arith_string(token_record *the_token, FILE *the_file, mudcode_record *mudcode) { arith_string *str_ptr; char error[80]; stmt_record *ret_union; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_ARITH_STR; /* printf("Status - beginning check on an arithmetic string\n"); */ str_ptr = (arith_string * ) memAlloc(arith_string,1,REC_ARITHSTR); str_ptr->stringfunct1 = NULL; if ((the_token->token_type == T_QUOTE) || (the_token->token_type == T_APOST)) { str_ptr->string1 = get_str_list_assn(the_token, the_file, False); } else if (the_token->token_type == T_IDENTIFIER) { str_ptr->stringfunct1 = get_identifier(the_token, the_file, mudcode, False); } else { sprintf(error, "Unknown identifier %s for arithmetic string.", the_token->the_string); state_error(error, the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if ((the_token->token_type == T_QUOTE) || (the_token->token_type == T_APOST)) if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_SEMICOLON) { if (the_token->token_type == T_PLUS) { str_ptr->the_op = T_PLUS; } else { sprintf(error, "Unknown string operand %s.", the_token->the_string); state_error(error, the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; str_ptr->string2 = get_arith_string(the_token, the_file, mudcode); /* printf("Status - finishing check on an arithmetic string\n"); */ } ret_union->stmt.arith_str_d = str_ptr; return ret_union; } /********************************************************************************* ** ** get_identifier - get mudcode code ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** ********************************************************************************/ stmt_record *get_identifier(token_record *the_token, FILE *the_file, mudcode_record *mudcode, Boolean Expect_Semicolon) { mudfunct_decl *funct_ptr; /* the function call record created */ mudcode_record *templ_ptr; /* points to the correct stored mudfunction template */ param_record *param_ptr; /* used to move along parameters */ mudfunct_param *functp_ptr; /* used to store the user entered parameter values */ ident_decl *ident_ptr; /* if it is an identifier */ char error[80]; stmt_record *ret_union; string_record *temp_str; assignmt *assn_ptr; char *name_ptr; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_MUD_DEFINED; /* printf("Status - beginning check on an identifier %s (a function probably)\n", the_token->the_string); */ templ_ptr = NULL; if ((templ_ptr = find_mudfunct(the_token, mudcode)) == NULL) { if (check_next_char(the_file) == '(') { sprintf(error, "Unknown function %s.", the_token->the_string); state_error(error, the_token->line); return NULL; } else if (Expect_Semicolon) { name_ptr = the_token->the_string; if (check_next_char(the_file) == '=') { if ((the_token = xget_token(the_file)) == NULL) return NULL; if ((the_token = xget_token(the_file)) == NULL) return NULL; assn_ptr = (assignmt * ) memAlloc(assignmt,1,REC_ASSIGNMT); strcpy(assn_ptr->var_name, name_ptr); assn_ptr->the_stmt = get_arith_number(the_token, the_file, mudcode); ret_union->stmt_type = STMT_ASSIGNMT; ret_union->stmt.assignmt_d = assn_ptr; return ret_union; } else if (check_next_char(the_file) == ':') { if ((the_token = xget_token(the_file)) == NULL) return NULL; if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_EQUALS) { state_error("Missing expected '=' after ':' on " "string arithmetic assignment.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; assn_ptr = (assignmt * ) memAlloc(assignmt,1,REC_ASSIGNMT); strcpy(assn_ptr->var_name, name_ptr); assn_ptr->the_stmt = get_arith_string(the_token, the_file, mudcode); ret_union->stmt_type = STMT_ASSIGNMT; ret_union->stmt.assignmt_d = assn_ptr; return ret_union; } else { ident_ptr = (ident_decl * ) memAlloc(ident_decl,1,REC_IDENTDECL); strcpy(ident_ptr->the_ident, the_token->the_string); /* printf("Status - finishing check on an identifier, not a function\n"); */ ret_union->stmt_type = STMT_IDENT; ret_union->stmt.ident_d = ident_ptr; return ret_union; } } else { ident_ptr = (ident_decl * ) memAlloc(ident_decl,1,REC_IDENTDECL); strcpy(ident_ptr->the_ident, the_token->the_string); /* printf("Status - finishing check on an identifier, not a function\n"); */ ret_union->stmt_type = STMT_IDENT; ret_union->stmt.ident_d = ident_ptr; return ret_union; } } if (templ_ptr == NULL) printf("ARGH!! I escaped the unescapeable if statement!!!! error!!\n"); /* printf("found function %s\n", templ_ptr->code_name); */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_LPAREN) { sprintf(error, "Missing expected '(' after %s.", the_token->the_string); state_error(error, the_token->line); return NULL; } param_ptr = templ_ptr->parameters; funct_ptr = (mudfunct_decl * ) memAlloc(mudfunct_decl,1,REC_MFDECL); funct_ptr->parameters = (mudfunct_param * ) memAlloc(mudfunct_param,1,REC_MFPARAM); funct_ptr->parameters->has_quotes = False; funct_ptr->the_funct = templ_ptr; functp_ptr = funct_ptr->parameters; functp_ptr->funct_param = NULL; while (param_ptr != NULL) { switch(param_ptr->param_type) { case T_STR: if ((the_token = xget_token(the_file)) == NULL) return NULL; switch(the_token->token_type) { case T_APOST: case T_QUOTE: functp_ptr->has_quotes = True; functp_ptr->the_param = get_str_list_assn(the_token, the_file, False); /* allow "blah" "blah" to be seen as one string here */ while (check_next_char(the_file) == '\"' || check_next_char(the_file) == '\'') { temp_str = functp_ptr->the_param; while (temp_str->nextstr != NULL) temp_str = temp_str->nextstr; if ((the_token = xget_token(the_file)) == NULL) return NULL; temp_str->nextstr = get_str_list_assn(the_token, the_file, False); } break; case T_IDENTIFIER: if ((functp_ptr->funct_param = get_identifier(the_token, the_file, mudcode, False)) == NULL) { sprintf(error, "Unknown identifier %s.", the_token->the_string); state_error(error, the_token->line); return NULL; } break; default: state_error("Missing expected '\"' for defined string parameter", the_token->line); return NULL; break; } break; case T_NUMBER: if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_MINUS) { if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_NUMERICAL) { sprintf(error, "Expected number after '-', found %s.", the_token->the_string); state_error(error, the_token->line); return NULL; } functp_ptr->the_param = (string_record * ) memAlloc(string_record,1,REC_STRING); functp_ptr->the_param->the_string = (char *) memAlloc(char,strlen(the_token->the_string) + 1,REC_CHAR); strcpy(functp_ptr->the_param->the_string, the_token->the_string); to_neg(functp_ptr->the_param->the_string); } if (the_token->token_type == T_NUMERICAL) { functp_ptr->the_param = (string_record * ) memAlloc(string_record,1,REC_STRING); functp_ptr->the_param->the_string = (char *) memAlloc(char,strlen(the_token->the_string) + 1,REC_CHAR); strcpy(functp_ptr->the_param->the_string, the_token->the_string); } else if (the_token->token_type == T_IDENTIFIER) { if ((functp_ptr->funct_param = get_identifier(the_token, the_file, mudcode, False)) == NULL) { sprintf(error, "Unknown identifier %s.", the_token->the_string); state_error(error, the_token->line); return NULL; } /* printf("got ident: %s\n", functp_ptr->funct_param->stmt.ident_d->the_ident); */ } else { state_error("Missing expected number for defined numerical parameter", the_token->line); return NULL; } break; case T_BOOL: if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_BOOL) { functp_ptr->the_param = (string_record * ) memAlloc(string_record,1,REC_STRING); functp_ptr->the_param->the_string = (char *) memAlloc(char,strlen(the_token->the_string) + 1,REC_CHAR); strcpy(functp_ptr->the_param->the_string, the_token->the_string); } else if (the_token->token_type == T_IDENTIFIER) { if ((functp_ptr->funct_param = get_identifier(the_token, the_file, mudcode, False)) == NULL) { sprintf(error, "Unknown identifier %s.", the_token->the_string); state_error(error, the_token->line); return NULL; } } else { state_error("Missing expected boolean type for defined boolean parameter", the_token->line); return NULL; } functp_ptr->the_param = (string_record * ) memAlloc(string_record,1,REC_STRING); functp_ptr->the_param->the_string = (char *) memAlloc(char,strlen(the_token->the_string) + 1,REC_CHAR); strcpy(functp_ptr->the_param->the_string, the_token->the_string); break; case T_IDENT: if ((the_token = xget_token(the_file)) == NULL) return NULL; functp_ptr->the_param = (string_record * ) memAlloc(string_record,1,REC_STRING); functp_ptr->the_param->the_string = (char *) memAlloc(char,strlen(the_token->the_string) + 1,REC_CHAR); strcpy(functp_ptr->the_param->the_string, the_token->the_string); functp_ptr->funct_param = get_identifier(the_token, the_file, mudcode, False); break; default: printf("default return: type: %d\n", param_ptr->param_type ); return NULL; } if (param_ptr->next_param != NULL) { if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_COMMA) { sprintf(error, "Missing expected ',' after parameter in %s function.", templ_ptr->code_name); state_error(error, the_token->line); return NULL; } functp_ptr->more_param = (mudfunct_param * ) memAlloc(mudfunct_param,1,REC_MFPARAM); functp_ptr->more_param->has_quotes = False; functp_ptr = functp_ptr->more_param; functp_ptr->funct_param = NULL; } param_ptr = param_ptr->next_param; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_RPAREN) { sprintf(error, "Missing expected ')' at the end of %s function, found %s.", templ_ptr->code_name, the_token->the_string); state_error(error, the_token->line); return NULL; } if (Expect_Semicolon) { if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_SEMICOLON) { sprintf(error, "Missing expected ';' at the end of %s function.", templ_ptr->code_name); state_error(error, the_token->line); return NULL; } } /* printf("Status - finishing check on an identifier (a function probably)\n"); */ ret_union->stmt.mudfunct_d = funct_ptr; return ret_union; } /****************************************************************************** ** ** get_if - get if/then/else code ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *********************************************************************************/ stmt_record *get_if(token_record *the_token, FILE *the_file, mudcode_record *mudcode, hashTable *the_hash) { if_decl *if_ptr; stmt_record *ret_union; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_IF_THEN; /* printf("status - beginning check on if statement\n"); */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if_ptr = (if_decl * ) memAlloc(if_decl,1,REC_IFDECL); if_ptr->bool_exp = get_boolean(the_token, the_file, mudcode, T_THEN); if_ptr->if_statements = get_statements(the_token, the_file, mudcode, the_hash, T_ELSE, T_END); if (return_type == T_ELSE) { /* printf("status - beginning check on else statement\n"); */ if_ptr->else_statements = get_statements(the_token, the_file, mudcode, the_hash, T_END, 0); } else if (return_type == T_END) { if_ptr->else_statements = NULL; } else printf( "WARNING -- Wierd error encountered in get_if procedure, unexpected return_type!\n"); return_type = 0; if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_IF) { state_error("Missing if after end for if statement.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_SEMICOLON) { state_error("Missing ';' after end if.", the_token->line); return NULL; } /* printf("status - check finished on if statement\n"); */ ret_union->stmt.if_d = if_ptr; return ret_union; } /************************************************************************************* ** ** get_raw - get raw code in a linked list format ** ** Parameters: the_file - ** ** ret - returns the first token on the next line ** *************************************************************************************/ stmt_record *get_raw(FILE *the_file) { raw_decl *raw_ptr; stmt_record *ret_union; ret_union = (stmt_record *) memAlloc(stmt_record, 1,REC_STMT); ret_union->stmt_type = STMT_RAW_CODE; /* printf("status - beginning check on raw code\n");*/ raw_ptr = (raw_decl * ) memAlloc(raw_decl,1,REC_RAWDECL); raw_ptr->the_code = get_str_until(the_file, '@', '\0'); /* printf("status - check finished on raw code\n");*/ ret_union->stmt.raw_d = raw_ptr; return ret_union; } /************************************************************************************* ** ** get_statements - gets a list of statements ** ** Parameters: the_token - ** the_file - ** stop_at - ** ** ret - returns the first token on the next line ** *************************************************************************************/ stmt_list_record *get_statements(token_record *the_token, FILE *the_file, mudcode_record *mudcode, hashTable *the_hash, int stop_at1, int stop_at2) { stmt_list_record *temp_stmt; /* holds the main statement list record */ stmt_list_record *stmt_ptr; /* used to move along statement records */ stmt_list_record *last_stmt = NULL; /* holds the last record for removing a record */ char error[80]; if ((the_token = xget_token(the_file)) == NULL) return NULL; /* printf("Starting parse of a statement.\n"); */ temp_stmt = (stmt_list_record * ) memAlloc(stmt_list_record,1,REC_STMTLIST); stmt_ptr = temp_stmt; while ((the_token->token_type != stop_at1) && (the_token->token_type != stop_at2)) { if (error_counter >= MAX_ERRORS) return NULL; switch(the_token->token_type) { case T_CONSTANT: stmt_ptr->the_statement = get_const(the_token, the_file, mudcode, the_hash); break; case T_STR: case T_NUMBER: case T_BOOL: stmt_ptr->the_statement = get_decl(the_token, the_file, mudcode, the_hash); break; case T_FOR: stmt_ptr->the_statement = get_for(the_token, the_file, mudcode, the_hash); break; case T_WHILE: stmt_ptr->the_statement = get_while(the_token, the_file, mudcode, the_hash); break; case T_REPEAT: stmt_ptr->the_statement = get_repeat(the_token, the_file, mudcode, the_hash); break; case T_BEGIN: stmt_ptr->the_statement = get_block(the_token, the_file, mudcode, the_hash); break; case T_IDENTIFIER: stmt_ptr->the_statement = get_identifier(the_token, the_file, mudcode, True); break; case T_IF: stmt_ptr->the_statement = get_if(the_token, the_file, mudcode, the_hash); break; case T_AMPER: stmt_ptr->the_statement = get_raw(the_file); if ((the_token = xget_token(the_file)) == NULL) return NULL; break; default: sprintf(error, "Unknown token %s in statement lists.", the_token->the_string); state_error(error, the_token->line); if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return NULL; } break; } stmt_ptr->more_statements = (stmt_list_record * ) memAlloc(stmt_list_record,1,REC_STMTLIST); last_stmt = stmt_ptr; stmt_ptr = stmt_ptr->more_statements; if ((the_token = xget_token(the_file)) == NULL) return NULL; } return_type = the_token->token_type; /* remove the empty last one */ if (last_stmt != NULL) { xfree(last_stmt->more_statements,REC_STMTLIST); last_stmt->more_statements = NULL; return temp_stmt; } return NULL; } /********************************************************************************* ** ** xget_code - gets all locations, returning a pointer to a string list ** ** Parameters: the_token - the token passed in, it is freed first ** the_file - the file pointer ** ** ret - -1 if encountered an error, otherwise the location ** ********************************************************************************/ trap_desc *xget_code(token_record *the_token, FILE *the_file, hashTable *the_hash, char *zonename, Boolean allow_loc) { trap_desc *temp_trap_desc; char error[80]; hashRecord *next_hash; char hashnam[(MAXNAMLEN*2)+5]; temp_trap_desc = (trap_desc *) memAlloc(trap_desc,1,REC_TRAPDESC); temp_trap_desc->next_desc = NULL; if (!((the_token->token_type >= 0) && (the_token->token_type <= last_event()))) { /* printf("type: %d\n", the_token->token_type);*/ sprintf(error, "Expected trap action(s) after '=', found token %s.", the_token->the_string); state_error(error, the_token->line); return NULL; } temp_trap_desc->trap_verb = the_token->token_type; if (allow_loc) { if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_COLON) { state_error("Missing ':' after UseTrap statement action.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_IDENTIFIER) { state_error("Missing identifier after ':' for Trap location.", the_token->line); return NULL; } if (!strcasecmp(itemname, the_token->the_string)) { state_warning("Extern location name is same as this location; could result in a stack overflow"); } strcpy(temp_trap_desc->trap_location, the_token->the_string); } else temp_trap_desc->trap_location[0] = '\0'; if (check_next_char(the_file) == ',') { if (allow_loc) { state_error("Only one external event allowed after UseTrap statement.",the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) { state_error("Expected a trap after a ',', but found nothing.\n",the_token->line); return NULL; } the_token = get_token(the_file, '\n', True); temp_trap_desc->next_desc = xget_code(the_token, the_file, the_hash, zonename, allow_loc); } /* put this event into the hash table */ sprintf(hashnam, "trap@%s@%s", zonename, itemname); next_hash = createHashRecord(hashnam, 0); addHashRecord(next_hash, the_hash); return temp_trap_desc; } /******************************************************************************* ** ** get_extern - gets a string of code or data ** ** Parameters: the_file - ** stop_at - ** ** ret - returns the first token on the next line ** *******************************************************************************/ trap_record *get_extern(token_record *the_token, FILE *the_file, hashTable *the_hash, char *zonename, mudcode_record *mudcode) { trap_record *the_trap; /* Holds a trap record for passing back */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_EQUALS) { state_error("Expected '=' after UseTrap token.", the_token->line); return NULL; } the_trap = (trap_record * ) memAlloc(trap_record,1,REC_TRAP); the_token = get_token(the_file, '\n', True); the_trap->trap_verb = xget_code(the_token, the_file, the_hash, zonename, True); the_trap->the_statements = NULL; return the_trap; } /******************************************************************************* ** ** get_code - gets a string of code or data ** ** Parameters: the_file - ** stop_at - ** ** ret - returns the first token on the next line ** *******************************************************************************/ trap_record *get_code(token_record *the_token, FILE *the_file, mudcode_record *mudcode, hashTable *the_hash, char *zonename, int stop_at) { trap_record *the_trap; /* Holds a trap record for passing back */ trap_desc *temp_ptr; if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_EQUALS) { state_error("Expected '=' after trap token.", the_token->line); return NULL; } the_trap = (trap_record * ) memAlloc(trap_record,1,REC_TRAP); the_token = get_token(the_file, '\n', True); the_trap->trap_verb = xget_code(the_token, the_file, the_hash, zonename, False); temp_ptr = the_trap->trap_verb; the_trap->the_statements = get_statements(the_token, the_file, mudcode, the_hash, stop_at, 0); return the_trap; } /********************************************************************************* ** MUDCODE TEMPLATE LOADING FUNCTIONS ********************************************************************************/ /********************************************************************************* ** ** xload_mudcode - reads in mudcode from the file mudcode.lib and loads it all into a ** linked list ** ** ret - returns a linked list of mudcode records containing all mudcode information ** ********************************************************************************/ mudcode_record *xload_mudcode(token_record *the_token, FILE *the_file) { mudcode_record *temp_code; param_record *temp_param; thecode_record *temp_thecode; char error[80]; /* check for an identifier, name of mudcode function */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if ((the_token->token_type != T_IDENTIFIER) && (the_token->token_type != T_STRENGTH)) { sprintf(error, "Identifier for name of function expected, found %s.", the_token->the_string); state_error(error, the_token->line); return NULL; } /* create a place to store the template */ temp_code = (mudcode_record *) memAlloc(mudcode_record,1,REC_MUDCODE); /* copy name into template */ strcpy(temp_code->code_name, the_token->the_string); if ((the_token = xget_token(the_file)) == NULL) return NULL; /* start getting mudcode parameters */ if (the_token->token_type != T_LPAREN) { state_error("Missing required '('.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_RPAREN) { temp_code->parameters = (param_record *) memAlloc(param_record,1,REC_PARAM); temp_param = temp_code->parameters; } /* while we dont find a closing right parenthesis, get parameters */ while (the_token->token_type != T_RPAREN) { temp_param->next_param = NULL; if ((the_token->token_type != T_STR) && (the_token->token_type != T_NUMBER) && (the_token->token_type != T_BOOL) && (the_token->token_type != T_IDENT)) { sprintf(error, "Missing required variable type, found %s.", the_token->the_string); state_error(error, the_token->line); return NULL; } temp_param->param_type = the_token->token_type; if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_LPAREN) { state_error("Missing required '('.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_NUMERICAL) { state_error("Missing required number for variable.", the_token->line); return NULL; } temp_param->param_num = atoi(the_token->the_string); if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_RPAREN) { state_error("Missing required ')'.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_COMMA) { temp_param->next_param = (param_record * ) memAlloc(param_record,1,REC_PARAM); temp_param = temp_param->next_param; if ((the_token = xget_token(the_file)) == NULL) return NULL; } } /* done getting parameters, expect a semicolon to close it off */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_SEMICOLON) { state_error("Missing required ';' at end of function declaration.", the_token->line); return NULL; } /* go to the next char, which should be the start of the conversion code */ if (goto_next_char(the_file) < 0) return NULL; temp_code->the_code = (thecode_record * ) memAlloc(thecode_record,1,REC_THECODE); temp_thecode = temp_code->the_code; /* get until we hit a parameter or the end, and store it */ temp_thecode->code_str = get_str_until(the_file, '@', '{'); while (check_next_char(the_file) != '@') { /* get the squiggly */ if ((the_token = xget_token(the_file)) == NULL) return NULL; /* get the type and check it */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if ((the_token->token_type != T_STR) && (the_token->token_type != T_NUMBER) && (the_token->token_type != T_BOOL) && (the_token->token_type != T_IDENT)) { state_error("Missing variable type after '{'.", the_token->line); return NULL; } temp_thecode->param_type = the_token->token_type; /* expect a left paren */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_LPAREN) { state_error("Missing '(' after variable type.", the_token->line); return NULL; } /* get the number of the parameter */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_NUMERICAL) { state_error("Missing variable number after '('.", the_token->line); return NULL; } temp_thecode->param_num = atoi(the_token->the_string); /* get right paren and squiggly and finish off this param */ if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_RPAREN) { state_error("Missing ')' after variable number.", the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type != T_RSQUIG) { state_error("Missing '}' after ')'.", the_token->line); return NULL; } temp_thecode->next_code = (thecode_record * ) memAlloc(thecode_record,1,REC_THECODE); temp_thecode = temp_thecode->next_code; temp_thecode->code_str = get_str_until(the_file, '@', '{'); } temp_thecode->param_type = -1; temp_thecode->param_num = -1; if ((the_token = xget_token(the_file)) == NULL) return NULL; if ((the_token = xget_token(the_file)) == NULL) return NULL; while (the_token->token_type == T_POUND) { if (next_line(the_file) == -1) { state_error("Unexpected end of file reached", 0); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; } if (the_token->token_type != T_PERCENT) { sprintf(error, "Unknown token %s in mudcode.lib file", the_token->the_string); state_error(error, the_token->line); return NULL; } if ((the_token = xget_token(the_file)) == NULL) return NULL; if (the_token->token_type == T_START) { temp_code->next_mudcode = xload_mudcode(the_token, the_file); } else if (the_token->token_type != T_END) { state_error("Unknown token in mudcode.lib file", the_token->line); return NULL; } return temp_code; } /********************************************************************************* ** ** load_mudcode - reads in mudcode from the file mudcode.lib and loads it all into a ** linked list ** ** ret - returns a linked list of mudcode records containing all mudcode information ** ********************************************************************************/ mudcode_record *load_mudcode(void) { FILE *codefile; token_record *the_token; mudcode_record *the_code; char *mudcode_fn = request_char_value("MUDCODE_LIBRARY"); if (mudcode_fn == NULL) mudcode_fn = "mudcode.lib"; if ((codefile = xfopen(mudcode_fn)) == NULL) { state_error("Error opening mudcode file 'mudcode.lib'.", 0); return NULL; } printf(" [1] Loading Mud Code Library... "); strcpy(thezonenam, "mudcode"); if ((the_token = xget_token(codefile)) == NULL) return NULL; while (the_token->token_type != T_PERCENT) { /* printf("num: %d\n", the_token->line); */ if (the_token->token_type == T_POUND) { if (next_line(codefile) == -1) { state_error("Unexpected end of file reached", 0); return NULL; } } else { state_error("Unexpected token", the_token->line); } if ((the_token = xget_token(codefile)) == NULL) return NULL; } if ((the_token = xget_token(codefile)) == NULL) return NULL; if (the_token->token_type != T_START) { state_error("Token start expected.", the_token->line); return NULL; } the_code = xload_mudcode(the_token, codefile); if (the_code != NULL) printf(" Succesful.\n"); return the_code; } /********************************************************************************* ** MAIN PARSE FUNCTION ********************************************************************************/ /******************************************************************************** ** ** get_zone ** ** Parameters: filename - the filename string to open ** ** ret - returns a zone record with all zone data stored in it or attached to it ** ********************************************************************************/ zone_record *get_zone(char *zonename, hashTable *hasht, mudcode_record *mudcode) { FILE *zonefile; /* the zone file to parse */ char error[120]; /* stores an error message */ token_record *the_token; /* holds the pointer to a token */ zone_record *the_zone; /* points to the zone */ location_record *next_loc; /* points to the next location in the line */ object_record *next_obj; /* points to the next object in the line */ mobile_record *next_mob; /* points to the next mobile in the line */ hashRecord *next_hash; /* the next hash record to add */ trap_record *next_trap; /* pointer to go to the next trap record in the line */ char hashnam[(MAXNAMLEN*2)+5]; char filename[MAXNAMLEN]; char *tempstr; char *CPP_str; #ifdef USE_PIPE char pipe[256]; #endif Boolean is_loc_title; Boolean is_loc_desc; Boolean is_mob_loc; Boolean is_mob_str; Boolean is_mob_desc; Boolean is_obj_loc; sprintf(filename, "%s%s", zonename,fn_extension); /* try to open the file, passing it through the C preprocessor first */ #ifdef USE_PIPE CPP_str = request_char_value("CPP"); sprintf(pipe, CPP_str, filename); if ((zonefile = popen(pipe, "r")) == NULL) { sprintf(error, "Error opening zone file %s, it may not exist.", filename); state_error(error, 0); return NULL; } #else if ((zonefile = xfopen(filename)) == NULL) { sprintf(error, "Error opening zone file %s, it may not exist.", filename); state_error(error, 0); return NULL; } #endif strcpy(thezonenam, filename); the_zone = (zone_record *) memAlloc(zone_record,1,REC_ZONE); strcpy(the_zone->zonefile, zonename); the_zone->zonename = xlowercase(thezonenam, strlen(thezonenam) + 1); /*the_zone->zonename = (char *) memAlloc(char, strlen(thezonenam) + 1,REC_CHAR);*/ strcpy(the_zone->zonename, zonename); /* get all stuff at the head of the zone file, not sure what I should do with includes */ if ((the_token = xget_token(zonefile)) == NULL) { state_error("Unexpected error (end of file?). Terminating parse.", 0); return NULL; } while ((the_token->token_type != T_LOCATION) && (the_token->token_type != T_MOBILE) && (the_token->token_type != T_OBJECT) && (the_token->token_type != T_ZONE)) { if (next_line(zonefile) == -1) { state_error("End of file encountered before any locations, objects, or mobiles.\n", 0); return NULL; } if ((the_token = xget_token(zonefile)) == NULL) { state_error("Unexpected error (end of file?). Terminating parse.", 0); return NULL; } } /* get each item */ while (!(feof(zonefile))) { switch(the_token->token_type) { /* if we get a record for the zone */ case T_ZONE: /***************************getting zone name **********************/ xfree(the_zone->zonename,REC_CHAR); the_zone->zonename = lowercase(get_str_assn(the_token, zonefile, MAXNAMLEN)); if (the_zone->zonename == NULL) break; sprintf(theitem, "zone %s", the_zone->zonename); strcpy(itemname, the_zone->zonename); /***************************getting any other zone data ************/ if ((the_token = xget_token(zonefile)) == NULL) { state_error("Unexpected error (end of file?). Terminating parse.", 0); return NULL; } while (the_token->token_type != T_ENDZONE) { if (error_counter >= MAX_ERRORS) { state_error("Too many errors, terminating compile.", 1); return NULL; } switch(the_token->token_type) { case T_AUTHOR: the_zone->author = get_str_assn(the_token, zonefile, 30); break; case T_QUEST: the_zone->quest = get_str_assn(the_token, zonefile, MAXQUESTNAMLEN); break; case T_DATA: the_zone->code = get_statements(the_token, zonefile, mudcode, hasht, T_ENDDATA, 0); break; case T_LOCATION: case T_OBJECT: case T_MOBILE: state_error("Missing EndZone for the previous zone record.", the_token->line); return NULL; break; default: sprintf(error, "%s not a member of the zone data record", the_token->the_string); state_error(error, the_token->line); if (next_line(zonefile) == -1) { state_error("End of file encountered before required EndZone in zone record", 0); return the_zone; } break; } if ((the_token = xget_token(zonefile)) == NULL) { state_error("Unexpected error (end of file?). Terminating parse.", 0); return NULL; } } tempstr = get_str_assn(the_token, zonefile, MAXNAMLEN); if (strcasecmp(the_zone->zonename, tempstr)) { sprintf(error, "Endzone name %s does not match the zone record %s.", tempstr, the_zone->zonename); state_error(error, 0); } break; case T_LOCATION: if (the_zone->location_data == NULL) { the_zone->location_data = (location_record *) memAlloc(location_record,1,REC_LOCATION); next_loc = the_zone->location_data; } else { next_loc->next_loc = (location_record *) memAlloc(location_record,1,REC_LOCATION); next_loc = next_loc->next_loc; } /******************** initialize location data ********************/ is_loc_title = False; is_loc_desc = False; next_loc->north = NULL; next_loc->south = NULL; next_loc->east = NULL; next_loc->west = NULL; next_loc->up = NULL; next_loc->down = NULL; next_loc->northeast = NULL; next_loc->northwest = NULL; next_loc->southeast = NULL; next_loc->southwest = NULL; next_loc->hint = NULL; next_loc->lflags.b1 = next_loc->lflags.b2 = next_loc->lflags.b3 = 0; next_loc->loc_code = NULL; /***************************getting location name ********************/ next_loc->name = get_str_assn(the_token, zonefile, MAXNAMLEN); if (next_loc->name == NULL) break; /* load it into the globals */ tempstr = xlowercase(next_loc->name, MAXNAMLEN); sprintf(theitem, "location %s", next_loc->name); strcpy(itemname, next_loc->name); /* put this into the hash table */ sprintf(hashnam, "loc@%s@%s", zonename, tempstr); next_hash = createHashRecord(hashnam, cur_loc--); if (addHashRecord(next_hash, hasht) == 0) { sprintf(error, "Redefinition of location %s", tempstr); state_error(error, the_token->line); } xfree(tempstr,REC_CHAR); /***************************getting any other location data *************/ if ((the_token = xget_token(zonefile)) == NULL) { state_error("Unexpected error (end of file?). Terminating parse.", 0); return NULL; } while (the_token->token_type != T_ENDLOCATION) { if (error_counter >= MAX_ERRORS) { state_error("Too many errors, terminating compile.", 1); return NULL; } switch(the_token->token_type) { case T_NORTH: next_loc->north = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1)); break; case T_SOUTH: next_loc->south = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1)); break; case T_EAST: next_loc->east = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1)); break; case T_WEST: next_loc->west = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1)); break; case T_UP: next_loc->up = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1)); break; case T_DOWN: next_loc->down = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1)); break; case T_NORTHEAST: next_loc->northeast = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1)); break; case T_NORTHWEST: next_loc->northwest = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1)); break; case T_SOUTHEAST: next_loc->southeast = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1)); break; case T_SOUTHWEST: next_loc->southwest = lowercase(get_loc_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1)); break; case T_TITLE: next_loc->title = get_str_assn(the_token, zonefile, MAXTITLLEN); is_loc_title = True; break; case T_DESC: next_loc->desc = get_str_list_assn(the_token, zonefile, True); is_loc_desc = True; break; case T_HINT: next_loc->desc = get_str_list_assn(the_token, zonefile, True); break; case T_LFLAGS: get_flags(the_token, &next_loc->lflags, Lflags, zonefile); break; case T_TRAP: if (next_loc->loc_code == NULL) next_loc->loc_code = get_code(the_token, zonefile, mudcode, hasht, zonename, T_ENDTRAP); else { next_trap = next_loc->loc_code; while (next_trap->more_traps != NULL) next_trap = next_trap->more_traps; next_trap->more_traps = get_code(the_token, zonefile, mudcode, hasht, zonename, T_ENDTRAP); } break; case T_USETRAP: next_loc->loc_code = get_extern(the_token, zonefile, hasht, zonename, mudcode); break; case T_ZONE: case T_OBJECT: case T_MOBILE: state_error("Missing EndLocation for the previous location record.", the_token->line); return NULL; break; default: sprintf(error, "%s not a member of the location data record", the_token->the_string); state_error(error, the_token->line); if (next_line(zonefile) == -1) { state_error("End of file encountered before required EndLocation in location record", 0); return the_zone; } break; } if ((the_token = xget_token(zonefile)) == NULL) { state_error("Unexpected error (end of file?). Terminating parse.", 0); return NULL; } } tempstr = get_str_assn(the_token, zonefile, MAXNAMLEN); if (strcasecmp(next_loc->name, tempstr)) { sprintf(error, "EndLocation name %s does not match the location record %s.", tempstr, next_loc->name); state_error(error, 0); } /* make sure we have all location elements */ if (!is_loc_title) state_error("Missing required title element for location record", the_token->line); if (!is_loc_desc) state_error("Missing required description element for location record", the_token->line); break; case T_OBJECT: /*********************create a new object record ******************/ if (the_zone->object_data == NULL) { the_zone->object_data = (object_record *) memAlloc(object_record,1,REC_OBJECT); next_obj = the_zone->object_data; } else { next_obj->next_obj = (object_record *) memAlloc(object_record,1,REC_OBJECT); next_obj = next_obj->next_obj; } /******************** initialize object data ********************/ is_obj_loc = False; next_obj->name = NULL; next_obj->altname = NULL; next_obj->linked = NULL; next_obj->examine = NULL; next_obj->desc[0] = NULL; next_obj->desc[1] = NULL; next_obj->desc[2] = NULL; next_obj->desc[3] = NULL; next_obj->basevalue = DEF_OBJ_BVALUE; next_obj->state = DEF_OBJ_STATE; next_obj->maxstate = DEF_OBJ_STATE; next_obj->armor = DEF_OBJ_ARMOR; next_obj->damage = DEF_OBJ_DAMAGE; next_obj->size = DEF_OBJ_SIZE; next_obj->weight = DEF_OBJ_WEIGHT; next_obj->hint = NULL; next_obj->oflags.b1 = next_obj->oflags.b2 = next_obj->oflags.b3 = 0; next_obj->obj_code = NULL; /***************************getting object name *******************************/ next_obj->oname = get_str_assn(the_token, zonefile, MAXNAMLEN); if (next_obj->oname == NULL) break; /* store the object in the hash table */ tempstr = xlowercase(next_obj->oname, MAXNAMLEN); sprintf(hashnam, "obj@%s@%s", zonename, tempstr); /* load it into the globals */ sprintf(theitem, "object %s", next_obj->oname); strcpy(itemname, next_obj->oname); /* printf("parsing: %s\n", theitem); printf("storing: %s\n", hashnam);*/ next_hash = createHashRecord(hashnam, cur_obj++); if (addHashRecord(next_hash, hasht) == 0) { sprintf(error, "Redefinition of object %s", tempstr); state_error(error, the_token->line); } xfree(tempstr,REC_CHAR); /***************************getting any other object data *********************/ if ((the_token = xget_token(zonefile)) == NULL) { state_error("Unexpected error (end of file?). Terminating parse.", 0); return NULL; } while (the_token->token_type != T_ENDOBJECT) { if (error_counter >= MAX_ERRORS) { state_error("Too many errors, terminating compile.", 1); return NULL; } switch(the_token->token_type) { case T_NAME: next_obj->name = get_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1); break; case T_ALTNAME: next_obj->altname = get_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1); break; case T_LOCATION: next_obj->location = get_location(the_token, zonefile, True); is_obj_loc = True; break; case T_LINKED: next_obj->linked = get_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1); break; case T_BASEVALUE: next_obj->basevalue = get_int_assn(the_token, zonefile); break; case T_STATE: next_obj->state = get_int_assn(the_token, zonefile); break; case T_MAXSTATE: next_obj->maxstate = get_int_assn(the_token, zonefile); break; case T_ARMOR: next_obj->armor = get_int_assn(the_token, zonefile); break; case T_DAMAGE: next_obj->damage = get_int_assn(the_token, zonefile); break; case T_SIZE: next_obj->size = get_int_assn(the_token, zonefile); break; case T_WEIGHT: next_obj->weight = get_int_assn(the_token, zonefile); break; case T_VISIBILITY: next_obj->vis = get_int_assn(the_token, zonefile); break; case T_EXAMINE: next_obj->examine = get_str_list_assn(the_token, zonefile, True); break; case T_DESC1: next_obj->desc[0] = get_str_list_assn(the_token, zonefile, True); break; case T_DESC2: next_obj->desc[1] = get_str_list_assn(the_token, zonefile, True); break; case T_DESC3: next_obj->desc[2] = get_str_list_assn(the_token, zonefile, True); break; case T_DESC4: next_obj->desc[3] = get_str_list_assn(the_token, zonefile, True); break; case T_HINT: next_obj->hint = get_str_list_assn(the_token, zonefile, True); break; case T_OFLAGS: get_flags(the_token, &next_obj->oflags, Oflags, zonefile); break; case T_TRAP: if (next_obj->obj_code == NULL) next_obj->obj_code = get_code(the_token, zonefile, mudcode, hasht, zonename, T_ENDTRAP); else { next_trap = next_obj->obj_code; while (next_trap->more_traps != NULL) next_trap = next_trap->more_traps; next_trap->more_traps = get_code(the_token, zonefile, mudcode, hasht, zonename, T_ENDTRAP); } break; case T_USETRAP: next_obj->obj_code = get_extern(the_token, zonefile, hasht, zonename, mudcode); break; case T_ZONE: case T_MOBILE: state_error("Missing EndObject for the previous object record.", the_token->line); return NULL; break; default: sprintf(error, "%s not a member of the object data record", the_token->the_string); state_error(error, the_token->line); if (next_line(zonefile) == -1) { state_error("End of file encountered before required EndObject in object record", 0); return the_zone; } break; } if ((the_token = xget_token(zonefile)) == NULL) { state_error("Unexpected error (end of file?). Terminating parse.", 0); return NULL; } } tempstr = get_str_assn(the_token, zonefile, MAXNAMLEN); if (strcasecmp(next_obj->oname, tempstr)) { sprintf(error, "EndObject name %s does not match the object record %s.", tempstr, next_obj->oname); state_error(error, 0); } /* make sure we got the required object element */ if (!is_obj_loc) state_error("Missing required location element for object record", the_token->line); break; case T_MOBILE: /*********************create a new mobile record ******************/ if (the_zone->mobile_data == NULL) { the_zone->mobile_data = (mobile_record *) memAlloc(mobile_record,1,REC_MOBILE); next_mob = the_zone->mobile_data; } else { next_mob->next_mob = (mobile_record *) memAlloc(mobile_record,1,REC_MOBILE); next_mob = next_mob->next_mob; } /******************** initialize mobile data ********************/ is_mob_loc = False; is_mob_str = False; is_mob_desc = False; next_mob->name = NULL; next_mob->examine = NULL; next_mob->armor = DEF_MOB_ARMOR; next_mob->damage = DEF_MOB_DAMAGE; next_mob->aggr = DEF_MOB_AGGRESSION; next_mob->speed = DEF_MOB_SPEED; next_mob->wimpy = DEF_MOB_WIMPY; next_mob->hint = NULL; next_mob->mflags.h = next_mob->mflags.l = 0; next_mob->pflags.b1 = next_mob->pflags.b2 = next_mob->pflags.b3 = 0; next_mob->sflags.b1 = next_mob->sflags.b2 = next_mob->sflags.b3 = 0; next_mob->mob_code = NULL; /***************************getting mobile name *******************************/ next_mob->mname = get_str_assn(the_token, zonefile, MAXNAMLEN); if (next_mob->mname == NULL) break; /* load the mobile into the hash table */ tempstr = xlowercase(next_mob->mname, MAXNAMLEN); sprintf(hashnam, "mob@%s@%s", zonename, tempstr); /* load it into the globals */ sprintf(theitem, "mobile %s", next_mob->mname); strcpy(itemname, next_mob->mname); next_hash = createHashRecord(hashnam, cur_mob++); if (addHashRecord(next_hash, hasht) == 0) { sprintf(error, "Redefinition of mobile %s", tempstr); state_error(error, the_token->line); } xfree(tempstr,REC_CHAR); /***************************getting any other mobile data *********************/ if ((the_token = xget_token(zonefile)) == NULL) { state_error("Unexpected error (end of file?). Terminating parse.", 0); return NULL; } while (the_token->token_type != T_ENDMOBILE) { if (error_counter >= MAX_ERRORS) { state_error("Too many errors, terminating compile.", 1); return NULL; } switch(the_token->token_type) { case T_NAME: next_mob->name = get_str_assn(the_token, zonefile, (MAXNAMLEN*2)+1); break; case T_LOCATION: next_mob->location = get_location(the_token, zonefile, False); is_mob_loc = True; break; case T_STRENGTH: next_mob->strength = get_int_assn(the_token, zonefile); is_mob_str = True; break; case T_DAMAGE: next_mob->damage = get_int_assn(the_token, zonefile); break; case T_ARMOR: next_mob->armor = get_int_assn(the_token, zonefile); break; case T_SPEED: next_mob->speed = get_int_assn(the_token, zonefile); break; case T_AGGRESSION: next_mob->aggr = get_int_assn(the_token, zonefile); break; case T_WIMPY: next_mob->wimpy = get_int_assn(the_token, zonefile); break; case T_VISIBILITY: next_mob->vis = get_int_assn(the_token, zonefile); break; case T_DESC: next_mob->desc = get_str_list_assn(the_token, zonefile, True); is_mob_desc = True; break; case T_EXAMINE: next_mob->examine = get_str_list_assn(the_token, zonefile, True); break; case T_HINT: next_mob->hint = get_str_list_assn(the_token, zonefile, True); break; case T_MFLAGS: get_mflags(the_token, &next_mob->mflags, zonefile); break; case T_SFLAGS: get_flags(the_token, &next_mob->sflags, Sflags, zonefile); break; case T_PFLAGS: get_flags(the_token, &next_mob->pflags, Pflags, zonefile); break; case T_TRAP: if (next_mob->mob_code == NULL) next_mob->mob_code = get_code(the_token, zonefile, mudcode, hasht, zonename, T_ENDTRAP); else { next_trap = next_mob->mob_code; while (next_trap->more_traps != NULL) next_trap = next_trap->more_traps; next_trap->more_traps = get_code(the_token, zonefile, mudcode, hasht, zonename, T_ENDTRAP); } break; case T_USETRAP: next_mob->mob_code = get_extern(the_token, zonefile, hasht, zonename, mudcode); break; case T_ZONE: case T_OBJECT: state_error("Missing EndMobile for the previous mobile record.", the_token->line); return NULL; break; default: sprintf(error, "%s not a member of the mobile data record", the_token->the_string); state_error(error, the_token->line); if (next_line(zonefile) == -1) { state_error("End of file encountered before required EndMobile in mobile record", 0); return the_zone; } break; } if ((the_token = xget_token(zonefile)) == NULL) { state_error("Unexpected error (end of file?). Terminating parse.", 0); return NULL; } } tempstr = get_str_assn(the_token, zonefile, MAXNAMLEN); if (strcasecmp(next_mob->mname, tempstr)) { sprintf(error, "EndMobile name %s does not match the mobile record %s.", tempstr, next_mob->mname); state_error(error, 0); } /* make sure we got all required elements */ if (!is_mob_loc) state_error("Missing required location element for mobile record", the_token->line); if (!is_mob_str) state_error("Missing required strength element for mobile record", the_token->line); if (!is_mob_desc) state_error("Missing required description element for mobile record", the_token->line); break; default: sprintf(error, "Unrecognized element %s in zone file", the_token->the_string); state_error(error, the_token->line); if (next_line(zonefile) == -1) { return the_zone; } break; } strcpy(theitem, "<none>"); strcpy(itemname, "<none>"); if ((the_token = xget_token(zonefile)) == NULL) if (Valid == True) return the_zone; else { printf("Zone not valid\n"); return NULL; } } #ifndef USE_PIPE fclose(zonefile); #else pclose(zonefile); #endif if (Valid == True) return the_zone; else { printf("%d errors occured while reading this zone.\n",error_counter); return NULL; } }