/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ABERED (AberMUD Dirt3 editor) * * * * This file handles the IO related to objects. It's main function is * * really to read and parse objects, done from read_dirt_obj(). It also * * writes dirt format objects out, write_dirt_obj() which is used for ostat * * command as well. * * * * Copyright (C) 1993 James Willie. All rights reseved. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <stdio.h> #include <ctype.h> #include "types.h" #include "macros.h" #include "extern.h" #include "prototyp.h" extern int line; char *obj_table[] = { "Name", "Pname", "Location", "Description", "End", "Altname", "Oflags", "Armor", "Damage", "MaxState", "State", "Bvalue", "Size", "Weight", "Examine", "Linked", "Counter", "Wflags", "Wlevel", TABLE_END }; char *olt_table[] = { "UNKNOWN", "IN_ROOM", "IN_CONTAINER", "CARRIED_BY", "WORN_BY", "WIELDED_BY", "BOTH_BY", TABLE_END }; /* ** The guts of the reading in of objects, read a word from line, switch ** to the appropriate entry, parse rest of line. Special cases are % ** which causes return NULL. Note that a line is discarded if the case ** does not use it all. */ POBJ read_dirt_obj(f) FILE *f; { OBJ *o; char s[128], n[128], r[128]; int c, d, k, i, j; char *t; o = NULL; for (;;) { do { c = getc(f); if (c == '\n') line++; } while (isspace(c)); for (t = s; isalnum(c) || c == '_';c = getc(f)) *t++ = c; *t = 0; if (t == s) { if (c == EOF) return NULL; if (c != '%') continue; ungetc(c,f); return NULL; } i = -1; if (c == '[') { c = getc(f); for (i = 0; isdigit(c); i = i * 10 + (c - '0'), c = getc(f)); if (c != ']') printf("Error on line %d: Not number in [..]\n", line); if (c == '\n') line++; c = getc(f); } while (c == ' ' || c == '\t' || c == '=') c = getc(f); ungetc(c,f); k = lookup(obj_table,s); #ifdef DEBUG fprintf(stderr,"%d:%s\n", k, s); #endif if (k != O_NAME && o == NULL) { printf("Error on line %d: Entry is out of sequence [%s]\n", line, s); exit(1); } switch (k) { case O_NAME: d = 0; for (t = n, c = getc(f); isalnum(c) || c == '_'; c = getc(f)) *t++ = c; *t = 0; ungetc(c,f); if ((o = NEW(OBJ)) == NULL) { printf("Can't create object, Out of memory error.\n"); exit(1); } init_obj(n,o); numobj++; objnum++; break; case O_PNAME: if (c == '"') { getc(f); /* Skip the " mark then get_text to next one. */ o->pname = get_text(f,'"'); line += text_lines; break; } get_word(s,f); free(o->pname); o->pname = COPY(s); break; case O_LOC: c = getc(f); for (t = n; isalnum(c) || c == '_'; c = getc(f)) *t++ = c; *t = 0; if (c != ':') { printf("Error on line %d: Object[%s] location is missing :\n", line, o->name); exit(1); } for (t = r, c = getc(f); isalnum(c) || c == '_'; c = getc(f)) *t++ = c; *t = 0; o->lname = COPY(r); o->ltype = lookup(olt_table,n); fix_obj(o); break; case O_DESC: if ((i < 0) || (i >= MAX_STATES)) { printf("Error on line %d: Illegal index to a desc[]\n", line); exit(1); } getc(f); /* Skip the " */ while(((c = getc(f)) != EOF) && (isspace(c)) && (c != '\n')) ; if (!isspace(c)) /* if we didn't skip a \n, put the char back */ ungetc(c,f); o->desc[i] = get_text(f,'"'); line += text_lines; break; case O_END: d = 0; c = getc(f); for (t = n; isalnum(c) || c == '_'; c = getc(f)) *t++ = c; *t = 0; ungetc(c,f); if (!EQ(n,o->name)) { printf("Error on line %d: Wrong name to end object.\n", line); printf(" Expected %s found %s\n", o->name, n); exit(1); } return o; break; case O_ANAME: if (c == '"') { getc(f); /* Skip the " mark then get_text to next one. */ o->altname = get_text(f, '"'); line += text_lines; break; } get_word(s,f); o->altname = COPY(s); break; case O_WFLAGS: #ifdef _NO_WFLAGS for (c = getc(f); c != '}'; c = getc(f)) { if (c == '\n') line++; } #else if (!wear_flags) { printf("Error in %s: Wflags aren't turned on. They won't save\n", o->name); } while (c != '{') { if (c == '\n') line++; if (c == EOF) { printf("Error on line %d: Object %s EOF found, expected Wflags\n", line, o->name); return NULL; } c = getc(f); } for (c = getc(f); c != '}'; c = getc(f)) { if (c == '\n') line++; if (!isalpha(c)) continue; for (t = r; isalpha(c); c = getc(f)) *t++ = (char)c; ungetc(c,f); *t = 0; j = lookup(w_flags, r); if ((j >= 0) && (j < NUM_WFLAGS)) o->wflags[j] = TRUE; else printf("Error on line %d: Unknown wflag %s in object %s\n", line, r, o->name); } #endif break; case O_OFLAGS: while (c != '{') { if (c == '\n') line++; if (c == EOF) { printf("Error on line %d: Object %s EOF found, expected Oflags\n", line, o->name); return NULL; } c = getc(f); } for (c = getc(f); c != '}'; c = getc(f)) { if (c == '\n') line++; if (!isalpha(c)) continue; for (t = r; isalpha(c); c = getc(f)) *t++ = (char)c; ungetc(c,f); *t = 0; j = lookup(o_flags, r); if ((j >= 0) && (j < NUM_OFLAGS)) o->oflags[j] = TRUE; else printf("Error on line %d: Unknown oflag %s in object %s\n", line, r, o->name); } break; case O_ARMOR: o->armor = get_int(f,&j); gint_error(j,obj_table[k],o->name); break; case O_COUNT: if (!o_counters) printf("Warning: a counter entry found, and o_counters not allowed\n"); o->counter = get_int(f, &j); gint_error(j,obj_table[k],o->name); break; case O_DAMAGE: o->damage = get_int(f,&j); gint_error(j,obj_table[k],o->name); break; case O_WLEVEL: #ifdef _NO_WFLAGS get_int(f, &i); #else o->wlevel = get_int(f,&j); gint_error(j,obj_table[k],o->name); #endif break; case O_MAXS: o->maxstate = get_int(f, &j); gint_error(j,obj_table[k],o->name); break; case O_STATE: o->state = get_int(f,&j); gint_error(j,obj_table[k],o->name); break; case O_VALUE: o->value = get_int(f,&j); gint_error(j,obj_table[k],o->name); break; case O_SIZE: o->size = get_int(f,&j); gint_error(j,obj_table[k],o->name); break; case O_WEIGHT: o->weight = get_int(f,&j); gint_error(j,obj_table[k],o->name); break; case O_LINK: get_word(r,f); o->link = COPY(r); break; case O_EXAM: getc(f); while(((c = getc(f)) != EOF) && isspace(c) && (c != '\n')) ; if (c == '\n') line++; else ungetc(c,f); o->examine = get_text(f,'"'); line += text_lines; break; default: printf("Error on line %d: unknown entry [%s]\n", line, s); exit(1); } while (c != '\n') { if (c == EOF) return NULL; c = getc(f); } line++; } printf("Eeeeeeek!!! Error of some sort\n"); return NULL; } /* ** read_dirt_objects, does exactly that, uses read_dort_obj to read ** sequence of 0 or more objects */ POBJ read_dirt_objects(f) FILE *f; { POBJ o1 = NULL, o2 = NULL; #ifdef DEBUG int x = line; #endif o1 = read_dirt_obj(f); o2 = o1; while(o1 != NULL) { #ifdef DEBUG printf("Object %s: Lines %d to %d\n", o1->name, x, line); x = line+1; #endif o1->next = read_dirt_obj(f); o1 = o1->next; } return o2; } /* ** Write out object o, to file f */ void write_dirt_obj(f,o) FILE *f; POBJ o; { int i; Bool test; if (o == NULL) { printf("NULL object\n"); return; } fprintf(f,"Name = %s\n",o->name); fprintf(f,"Pname = \"%s\"\n",o->pname); if (o->altname != NULL) fprintf(f,"AltName = \"%s\"\n",o->altname); fprintf(f,"Location = %s:%s\n",olt_table[(int)o->ltype],oloc_name(o)); fprintf(f, "Oflags { "); write_oflags(f,o); fprintf(f, "}\n"); #ifndef _NO_WFLAGS if (wear_flags == TRUE) { test = FALSE; for (i = 0; (i < NUM_WFLAGS) && (test == FALSE); i++) { if (o->wflags[i] == TRUE) test = TRUE; } if (test == TRUE) { fprintf(f, "Wflags { "); write_wflags(f,o); fprintf(f, "}\n"); if (o->wlevel >= 0) fprintf(f, "WLevel = %d\n", o->wlevel); } } #endif if (o->value != 0) fprintf(f,"BValue = %d\n",o->value); if (o->armor != 0) fprintf(f,"Armor = %d\n",o->armor); if (o->damage != 0) fprintf(f,"Damage = %d\n",o->damage); if ((o_counters) && (o->counter != 0)) fprintf(f,"Counter = %d\n", o->counter); if (o->size != 0) fprintf(f,"Size = %d\n",o->size); if (o->weight != 0) fprintf(f,"Weight = %d\n",o->weight); if (o->maxstate > 0) { fprintf(f,"MaxState = %d\n",o->maxstate); fprintf(f,"State = %d\n",o->state); } if (!EMPTY(o->link)) fprintf(f,"Linked = %s\n",o->link); for (i = 0; i < MAX_STATES; i++) /* Used to wrongly stop at o->maxstate */ { /* Thanks to Mary for bug report */ if (!EMPTY(o->desc[i])) { fprintf(f,"Desc[%1d] = \"",i); if (strlen(o->desc[i]) > 60) fputc('\n', f); fprintf(f,"%s\"\n",o->desc[i]); } } if (!EMPTY(o->examine)) { fprintf(f,"Examine = \"\n"); write_string(o->examine,f); fprintf(f, "\"\n"); } fprintf(f,"End = %s\n\n",o->name); return; } #ifndef _NO_WFLAGS void write_wflags(f,o) FILE *f; POBJ o; { int i; for (i = 0; i < NUM_WFLAGS; i++) { if (o->wflags[i] == TRUE) fprintf(f,"%s ", w_flags[i]); } return; } #endif void write_oflags(f,o) FILE *f; POBJ o; { int i; for (i = 0; i < NUM_OFLAGS; i++) { if (o->oflags[i] == TRUE) fprintf(f,"%s ", o_flags[i]); } return; } /* ** Initialize the new object */ void init_obj(n,o) char *n; POBJ o; { int j; if (o == NULL) return; o->name = COPY(n); o->number = objnum; o->pname = COPY(o->name); o->link = NULL; o->altname = NULL; o->location = NULL; o->lname = NULL; o->ltype = UNKNOWN; o->damage = 0; o->armor = 0; for(j = 0; j < NUM_OFLAGS; j++) o->oflags[j] = FALSE; #ifndef _NO_WFLAGS for(j = 0; j < NUM_WFLAGS; j++) o->wflags[j] = FALSE; o->wlevel = -1; #endif o->state = 0; o->maxstate = 0; o->value = 0; o->size = 0; o->weight = 0; o->counter = 0; for(j = 0; j < MAX_STATES; j++) o->desc[j] = NULL; o->examine = NULL; return; }