/**************************************************************************/ // gio.cpp - see below /*************************************************************************** * The Dawn of Time v1.69r (c)1997-2004 Michael Garratt * * >> A number of people have contributed to the Dawn codebase, with the * * majority of code written by Michael Garratt - www.dawnoftime.org * * >> To use this source code, you must fully comply with the dawn license * * in licenses.txt... In particular, you may not remove this copyright * * notice. * **************************************************************************/ /*************************************************************************** * FILE: gio.cpp - generic input/output loading and saving function * * - supports tables, linked lists etc * * This never really got all parts finished, but it is very functional. * * 100% written by Kalahn :) * ***************************************************************************/ #include "include.h" bool gio_abort_fwrite_wordflag_with_undefined_flags=true; #define OFFSETDATA(offset) *)((void*)((char *)data + (offset))) #define GIODATA(dtype) (*(( dtype OFFSETDATA(gio_table[tableIndex].index))) #define GIOARRAY(dtype) (*(( dtype OFFSETDATA(gio_table[tableIndex].index + ( (arrayIndex) * sizeof(dtype))) )) #define GIOPARAMpvoid (gio_table[tableIndex].pvoid) #define GIOPARAMpflag_type (gio_table[tableIndex].pflag_type) #define GIOPARAMshort (gio_table[tableIndex].sval) #define GIOPARAMint (gio_table[tableIndex].ival) #define GIOPARAMlong (gio_table[tableIndex].lval) #define GIOflags (gio_table[tableIndex].flags) #define GIOHEADING (gio_table[tableIndex].heading) /**************************************************************************/ // doesn't use the reserved file at this stage FILE *openFileWrite(char *){ return NULL; }; /**************************************************************************/ // Read a number from a file. long fread_long( FILE *fp ) { long number; bool sign; char c; do{ c = getc( fp ); } while ( is_space(c) ); number = 0; sign = false; if ( c == '+' ) { c = getc( fp ); } else if ( c == '-' ) { sign = true; c = getc( fp ); } if ( !is_digit(c) ) { bug("Fread_long: bad format."); logf("non numeric character is '%c'",c); do_abort( ); } while ( is_digit(c) ) { number = number * 10 + c - '0'; c = getc( fp ); } if ( sign ) number = 0 - number; if ( c == '|' ) number += fread_long( fp ); else if ( c != ' ' ) ungetc( c, fp ); return number; } /**************************************************************************/ bool is_stat( const struct flag_type *flag_table ); FILE *saveRecord(gio_type *gio_table, void *data, FILE *fp, int *status){ int tableIndex, arrayIndex; // check if we actually want to skip this record tableIndex=0; if (gio_table[tableIndex].type==CUSTOM_DONT_SAVE_RECORD){ int result=((GIO_CUSTOM_RETURN_FUNCTION)GIOPARAMpvoid) (gio_table, tableIndex, data, fp); if(result){ // don't save entry if(status){ *status=0; // nothing saved } return NULL; } } if (!fp){ logf("saveRecord: fp not initialised"); fp=openFileWrite("myfile.txt"); } for (tableIndex=0; gio_table[tableIndex].type!=END; tableIndex++){ // skip fields which don't mean anything in this situation if ( gio_table[tableIndex].type==CUSTOM_READ || gio_table[tableIndex].type==CUSTOM_DONT_SAVE_RECORD) { continue; } switch (gio_table[tableIndex].type){ default: logf("saveRecord: unrecognised table type '%s'(%d)", GIOHEADING, gio_table[tableIndex].type); case END: break; case STR: if(!IS_NULLSTR(GIODATA(char *)) || IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)) { hide_tilde(GIODATA(char *)); fprintf(fp, "%s %s%s~\n", GIOHEADING, // put a leading . if string starts with a . or whitespace ((is_space(*GIODATA(char*))||*GIODATA(char*)=='.')?".":""), fix_string(GIODATA(char*)) ); show_tilde(GIODATA(char*)); } break; case _INT: if(GIODATA(int) || GIOPARAMint!=0 || IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ fprintf(fp, "%s %d\n", GIOHEADING, GIODATA(int)); } break; case _LONG: if(GIODATA(long) || GIOPARAMlong!=0 || IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ fprintf(fp, "%s %ld\n", GIOHEADING, GIODATA(long)); } break; case SHINT: if(GIODATA(short)!=0 || GIOPARAMshort!=0 || IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ fprintf(fp, "%s %d\n" , GIOHEADING, GIODATA(short) ); } break; case _CHAR: if(GIODATA(char) || IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ fprintf(fp, "%s %c\n", GIOHEADING, GIODATA(char)); } break; case _BOOL: fprintf(fp, "%s %s\n", GIOHEADING, GIODATA(bool)?"true":"false"); break; case WFLAG: // wordflag if( GIODATA(int)!=0 || is_stat( GIOPARAMpflag_type) || IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ fwrite_wordflag( GIOPARAMpflag_type, GIODATA(int), GIOHEADING, fp); } break; case SHWFLAG: // short wordflag if( GIODATA(short)!=0 || is_stat( GIOPARAMpflag_type) || IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ fwrite_wordflag( GIOPARAMpflag_type, GIODATA(short), GIOHEADING, fp); } break; case STR_ARRAY: // parameter is the max size of the array for (arrayIndex=0; arrayIndex<GIOPARAMint; arrayIndex++){ if ( IS_NULLSTR(GIOARRAY(char*)) || IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ continue; } fprintf(fp, "%s[%d] %s~\n", GIOHEADING, arrayIndex, GIOARRAY(char*)); } break; case STR_ARRAYLIST: // when you reach the first null in the list stop for (arrayIndex=0; arrayIndex<GIOPARAMint;arrayIndex++){ if (IS_NULLSTR(GIOARRAY(char*)) || IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ break; } fprintf(fp, "%s[%d] %s~\n", GIOHEADING, arrayIndex, GIOARRAY(char*)); } break; case INT_ARRAY: for (arrayIndex=0; arrayIndex<GIOPARAMint; arrayIndex++){ if(GIOARRAY(int)|| IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ fprintf(fp, "%s[%d] %d\n", GIOHEADING, arrayIndex, GIOARRAY(int)); } } break; case LONG_ARRAY: for (arrayIndex=0; arrayIndex<GIOPARAMint; arrayIndex++){ if(GIOARRAY(long)|| IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ fprintf(fp, "%s[%d] %ld\n", GIOHEADING, arrayIndex, GIOARRAY(long)); } } break; case SHINT_ARRAY: for (arrayIndex=0; arrayIndex<GIOPARAMint; arrayIndex++){ if(GIOARRAY(short)|| IS_SET(GIOflags,GIOFLAG_ALWAYS_WRITE)){ fprintf(fp, "%s[%d] %d\n", GIOHEADING, arrayIndex, GIOARRAY(short)); } } break; case BOOL_ARRAY: log_string("BOOL_ARRAY not supported yet"); break; case CUSTOM_WRITE: ((GIO_CUSTOM_FUNCTION *)GIOPARAMpvoid) (gio_table, tableIndex, data, fp); break; case READ_TO_EOL: // do nothing, since it is a read only code break; case READ_TO_END_OF_STRING: // do nothing, since it is a read only code break; } } fprintf( fp, END_RECORD"\n\n"); if(status){ *status=1; // save okay } return fp; }; /**************************************************************************/ // memory allocation is only done in here if the data value is NULL // - fp must be valid and at the point ready to read // - if data != NULL then we start by zeroing the whole structure int loadRecord(gio_type *gio_table, void *data, FILE *fp){ int tableIndex, arrayIndex, structSize; char *pStr; char inHeader[MIL], inBool[MIL], arrayHeader[MIL]; bool checkForArray; bool data_read=false; int result = 0; // 1= okay, 2=eof no data bool finished=false; bool clearing_with_strdup=false; if (!fp){ logf("loadRecord: fp not initialised"); do_abort(); } // get the total size of the structure we are working with for (tableIndex=0; gio_table[tableIndex].type!=END; tableIndex++){ //loop round till we get the to end of the list... the entry // that is of type end contains the total size of the structure // in its index value. } structSize=gio_table[tableIndex].index; // create our data node if required // doesn't use any form of magic numbers at this stage if (!data){ data=malloc(structSize); memset( data, 0, (size_t) structSize); }else{ if (strcmp(GIOHEADING, "gio-noclear") && strcmp(GIOHEADING, "strdup_empty")){ // memset the structure to all zeros before starting if required memset( data, 0, (size_t) structSize); // logf("loadRecord: structSize = %d",structSize); }else{ if(!strcmp(GIOHEADING, "strdup_empty")){ clearing_with_strdup=true; } // go thru manually clearing the values for (tableIndex=0; gio_table[tableIndex].type!=END; tableIndex++) { switch (gio_table[tableIndex].type) { default: break; case STR: if(clearing_with_strdup){ GIODATA(char*)=str_dup(""); }else{ GIODATA(char*)=NULL; } break; case _INT: GIODATA(int)= 0; break; case _LONG: GIODATA(long)=0; break; case SHINT: GIODATA(short)= 0; break; case _CHAR: GIODATA(char)= '\0'; break; case _BOOL: GIODATA(bool)=false; break; case WFLAG: // wordflag GIODATA(int)=0; break; case SHWFLAG: // short wordflag GIODATA(short)=0; break; /* // strdup note supported with these case STR_ARRAY: // parameter is the max size of the array case STR_ARRAYLIST: // parameter is the max size of the array case SHINT_ARRAY: case INT_ARRAY: break; */ } } } // go thru manually setting all the default integer values for (tableIndex=0; gio_table[tableIndex].type!=END; tableIndex++) { if(gio_table[tableIndex].type==_INT && GIOPARAMint!=0){ GIODATA(int)= GIOPARAMint; } if(gio_table[tableIndex].type==SHINT && GIOPARAMshort!=0){ GIODATA(short)= GIOPARAMshort; } } } // now read in the entry fscanf(fp, "%s ", inHeader); finished= false; while (str_cmp(inHeader,END_RECORD) && !finished){ if(!str_cmp("EOF~", inHeader)){ if(data_read){ return 3; }else{ return 2; } } if (feof(fp)){ bugf("LoadRecord: Unexpected end of file found! inHeader='%s'", inHeader); finished= true; return 4; } if(!str_cmp("end", inHeader)){ return 1; } // check on off chance their might be an array header if (inHeader[str_len(inHeader)-1]==']'){ strcpy(arrayHeader,inHeader); pStr=strstr( arrayHeader, "["); if (!pStr){ checkForArray=false; }else{ if (sscanf(pStr+1, "%d]", &arrayIndex)==0){ checkForArray=false; }else{ *pStr='\0'; checkForArray=true; } } }else{ checkForArray=false; } // find the match in the GIO table // - if you have duplicate entries, the second value will // not be read // - if exact search doesn't match, try prefix matching for (tableIndex=0; gio_table[tableIndex].type!=END; tableIndex++){ if (!str_cmp(inHeader, GIOHEADING) && gio_table[tableIndex].type!=CUSTOM_WRITE){ checkForArray=false; break; } if (checkForArray && !str_cmp(arrayHeader, GIOHEADING) &&( gio_table[tableIndex].type== STR_ARRAY || gio_table[tableIndex].type== STR_ARRAYLIST || gio_table[tableIndex].type== INT_ARRAY || gio_table[tableIndex].type== LONG_ARRAY || gio_table[tableIndex].type== SHINT_ARRAY || gio_table[tableIndex].type== BOOL_ARRAY )) { checkForArray=true; data_read=true; break; } } if(gio_table[tableIndex].type==END) { for (tableIndex=0; gio_table[tableIndex].type!=END; tableIndex++){ if (!str_prefix(inHeader, GIOHEADING) && gio_table[tableIndex].type!=CUSTOM_WRITE){ checkForArray=false; break; } if (checkForArray && !str_cmp(arrayHeader, GIOHEADING) &&( gio_table[tableIndex].type== STR_ARRAY || gio_table[tableIndex].type== STR_ARRAYLIST || gio_table[tableIndex].type== INT_ARRAY || gio_table[tableIndex].type== LONG_ARRAY || gio_table[tableIndex].type== SHINT_ARRAY || gio_table[tableIndex].type== BOOL_ARRAY )) { checkForArray=true; break; } } } switch (gio_table[tableIndex].type){ default: logf("loadRecord: unrecognised table type %d", gio_table[tableIndex].type); case END: logf("loadRecord: Unfound match for '%s' header, ignoring.", inHeader); // skip the value - most likely to be a single value fscanf(fp, "%s ", inHeader); break; case STR: { size_t skip; // skip the number of blank spaces in the heading if (str_len(inHeader)<str_len(GIOHEADING)){ skip=str_len(GIOHEADING)-str_len(inHeader); while(skip>0){ char c=getc(fp); if(is_space(c)){ skip--; }else{// make sure we dont take too much skip=0; ungetc(c, fp); } } } pStr= fread_string(fp); char *trim_dot; if(*pStr=='.'){ // remove a leading . in a entry if found... saving adds // one if the first char is whitespace or a . trim_dot=str_dup(pStr+1); free_string(pStr); pStr=trim_dot; } show_tilde(pStr); GIODATA(char*)= pStr; } break; case _INT: GIODATA(int)= fread_number(fp);; break; case _LONG: GIODATA(long)= fread_long(fp); break; case SHINT: GIODATA(short)= fread_number(fp); break; case _CHAR: GIODATA(char)= fread_letter(fp); break; case _BOOL: fscanf(fp, "%s ", inBool); // read the word if (!str_cmp(inBool, "true")){ GIODATA(bool)=true; }else if (!str_cmp(inBool, "false")){ GIODATA(bool)=false; }else{ // unmatched - default to false logf("loadRecord: BOOL type for '%s' header, unmatched logic '%s' setting to false.", inHeader, inBool); GIODATA(bool)=false; } break; case WFLAG: // wordflag GIODATA(int)=fread_wordflag( GIOPARAMpflag_type, fp); break; case SHWFLAG: // short wordflag GIODATA(short)= fread_wordflag( GIOPARAMpflag_type, fp); break; case STR_ARRAY: // parameter is the max size of the array case STR_ARRAYLIST: // same as STR_ARRAY for loading GIOARRAY(char*)= fread_string(fp); break; case SHINT_ARRAY: GIOARRAY(short)=fread_number(fp); break; case INT_ARRAY: GIOARRAY(int)= fread_number(fp); break; case LONG_ARRAY: GIOARRAY(long)= fread_long(fp); break; /* case INT_ARRAY: log_string("INT_ARRAY not supported yet"); break; case BOOL_ARRAY: log_string("BOOL_ARRAY not supported yet"); break; */ case READ_TO_EOL: fread_to_eol(fp); break; case READ_TO_END_OF_STRING: fread_string(fp); break; case CUSTOM_READ: ((GIO_CUSTOM_FUNCTION *)GIOPARAMpvoid) (gio_table, tableIndex, data, fp); // TO ADD break; } // read in the next header fscanf(fp, "%s ", inHeader); // logf("inheader='%s", inHeader); } return result; }; /**************************************************************************/ // just flag_lookup but ignores the settable bit int gioflag_lookup(const char *name, const struct flag_type *flag_table) { int flag; // first try an exact match, then do a substring match // exact for (flag = 0; flag_table[flag].name != NULL; flag++) { if ( !str_cmp( name, flag_table[flag].name )) return flag_table[flag].bit; } // substring for (flag = 0; flag_table[flag].name != NULL; flag++) { if ( !str_prefix( name, flag_table[flag].name )) return flag_table[flag].bit; } return NO_FLAG; } const char *get_flag_table_name( const struct flag_type *flag_table ); /**************************************************************************/ // written by Kalahn - July 98 int fread_wordflag( const struct flag_type *flag_table, FILE *fp) { char *wf_str, *ptr_str; char single_word[MIL]; int result, flag; // read in the string wf_str = fread_string (fp); fread_to_eol(fp); // break down and find words one at a time // convert all white spaces into ' ' for one arg first ptr_str=wf_str; do{ if (*ptr_str=='\t' || *ptr_str=='\n' || *ptr_str=='\r') *ptr_str=' '; }while (*++ptr_str); // support stat tables if ( is_stat( flag_table ) ) { ptr_str=wf_str; one_argument( ptr_str, single_word); if ( ( result= gioflag_lookup( single_word, flag_table ) ) != NO_FLAG ){ return result; }else{ logf("fread_wordflag(): Failed to match value for single word '%s', flag_table=%s.", single_word, get_flag_table_name(flag_table)); logf("Complete string ='%s'", ptr_str); return 0; } } // loop thru all the words and match up what we can find result=0; ptr_str=wf_str; while (!IS_NULLSTR(ptr_str)){ ptr_str = one_argument( ptr_str, single_word); for (flag = 0; flag_table[flag].name != NULL; flag++) { if ( single_word[0]==flag_table[flag].name[0] && !str_cmp( single_word, flag_table[flag].name)) { SET_BIT(result, flag_table[flag].bit); break; } } // if we didn't find the word in that table if (!flag_table[flag].name){ logf("fread_wordflag(): unfound word flag match '%s'", single_word); } } free_string (wf_str); return (result); } /**************************************************************************/ // written by Kalahn - July 98 // note: If the final character in the heading is a space, then it will // not be multiple lined char *fwrite_wordflag( const struct flag_type *flag_table, int bits, const char * heading, FILE *fp) { static int i; static char buf[5][512]; int flag; int bit_index; int bit_value; bool bit_found=false; bool singlelineformat=false; size_t heading_length=str_len(heading); // rotate buffers ++i= i%5; // initialise the buffer we are working on buf[i][0] = '\0'; if(heading_length>0 && heading[heading_length-1]==' '){ singlelineformat=true; } // 2 different modes... if their is a stat table to be written // a different mode is used from checking each bit is written if (is_stat( flag_table )){ for (flag = 0; flag_table[flag].name && !bit_found; flag++) { if ( flag_table[flag].bit == bits ){ strcat( buf[i], flag_table[flag].name ); bit_found=true; } } // report that we have a missing value in a table if(!bit_found) { logf("fwrite_wordflag(): VALUE MISSING!!! heading='%s'\n" " (value=%d, 1st table entry='%s')", heading, bits, flag_table[0].name); if(gio_abort_fwrite_wordflag_with_undefined_flags){ { // do autonote missing value char body[MSL]; sprintf(body, "The mud was aborted because for following reason:`1" "fwrite_wordflag(): VALUE MISSING!!! heading='%s'`1" " (value=%d, flag_table=%s, 1st table entry='%s')`1" "This is usually fixed by adding in a text word for the missing value " "(to the table which has a first entry as shown above.)", heading, bits, get_flag_table_name(flag_table), flag_table[0].name); autonote(NOTE_SNOTE, "fwrite_wordflag()", "mud aborted due to missing value!", "code", body, true); log_note(body); } do_abort(); } } }else{ // write bits the long way so we can record if a bit isn't written due // to no matching bit in the flag table. // Also write only one bit word for a single bit allowing multiple // words for a bit value in a table (colour vs color) and single words in // stored files. bool insert_space=false; for (bit_index=0; bit_index<32; bit_index++) { bit_found=false; bit_value = 1<<bit_index; if (!IS_SET(bit_value, bits)) continue; for (flag = 0; flag_table[flag].name && !bit_found; flag++) { if ( IS_SET(bit_value, flag_table[flag].bit) ) { if(singlelineformat){ if(insert_space){ strcat( buf[i], " "); } insert_space=true; }else{ strcat( buf[i], "\n\t"); } strcat( buf[i], flag_table[flag].name ); bit_found= true; } } // report that we have a missing bit in a table if(!bit_found) { logf("fwrite_wordflag(): BIT MISSING!!! '%c' heading='%s'\n" " (bit_index=%d, bit_value=%d, flag_table=%s, 1st table entry='%s')", (bit_index <= 'Z' - 'A'?'A' + bit_index : 'a' + bit_index - ( 'Z' - 'A' + 1 )), heading, bit_index, bit_value, get_flag_table_name(flag_table), flag_table[0].name); if(gio_abort_fwrite_wordflag_with_undefined_flags){ { // do autonote missing bit char body[MSL]; sprintf(body, "The mud was aborted because for following reason:`1" "fwrite_wordflag(): BIT MISSING!!! '%c' heading='%s'\n" " (bit_index=%d, bit_value=%d, 1st table entry='%s')" "This is usually fixed by adding the missing word for the bitflag." "(to the table which has a first entry as shown above.)", (bit_index <= 'Z' - 'A'?'A' + bit_index : 'a' + bit_index - ( 'Z' - 'A' + 1 )), heading, bit_index, bit_value, flag_table[0].name); autonote(NOTE_SNOTE, "fwrite_wordflag()", "mud aborted due to a missing bitflag!", "code", body, true); log_note(body); } do_abort(); } } } } // non stat table (multiple bit table) strcat( buf[i], "~\n" ); if(fp && str_len(buf[i])>2){ // only write something if we have something to write if(singlelineformat){ fprintf(fp, "%s%s", heading, buf[i]); }else{ fprintf(fp, "%s %s", heading, buf[i]); } } return (buf[i]); } /**************************************************************************/ // gio_generic_savelist returns true if no errors on save bool gio_generic_savelist( void *listpointer, gio_type *gio_table, char *filename, int nextoffset, bool backup) { FILE *fp; void *pdata; int count=0; int skipped=0; char write_filename[MSL]; sprintf(write_filename,"%s.write", filename); // find a free write filename - so if something stuffed up on // the write, we don't go over it. if(file_exists(write_filename)){ for(int i=0; i<20; i++){ sprintf(write_filename,"%s.write%d", filename, i); if(!file_exists(write_filename)){ break; } } } unlink(write_filename); logf("Starting gio_generic_savelist to %s.", write_filename); fclose( fpReserve ); if ( ( fp = fopen( write_filename, "w" ) ) == NULL ) { bugf("gio_generic_savelist(): fopen '%s' for write - error %d (%s)", write_filename, errno, strerror( errno)); bugf("An error occured! writing to '%s' which would become %s", write_filename, filename); fpReserve = fopen( NULL_FILE, "r" ); return false; } // Go thru linked list writing each node to disk for ( pdata=listpointer; pdata; pdata= *(void **)(((char*) pdata )+nextoffset)) { int status; saveRecord( gio_table, pdata, fp, &status); if(status){ count++; }else{ skipped++; } } int bytes_written=fprintf(fp, "EOF~\n"); fclose( fp ); if( bytes_written != str_len("EOF~\n") ){ bugf("gio_generic_savelist(): fprintf to '%s' incomplete - error %d (%s)", write_filename, errno, strerror( errno)); bugf("Incomplete generic io write of %s, write aborted - check diskspace!", write_filename); { char msgbody[MSL]; sprintf(msgbody,"Incomplete write of %s, write aborted - check diskspace!\r\n", write_filename); autonote(NOTE_SNOTE, "gio_generic_savelist()", "Problems saving a linked list using gio!", "code cc: imm", msgbody, true); } }else{ // handle backup option if(backup){ char buf[MIL]; sprintf(buf, "%s.giobak", filename); logf("GIOBACKUP: Renaming old %s to %s", filename, buf); unlink(buf); rename(filename, buf); } logf("Renaming new %s to %s", write_filename, filename); unlink(filename); rename(write_filename, filename); } fpReserve = fopen( NULL_FILE, "r" ); if(skipped){ logf("Finished gio_generic_savelist [%d], skipped writing %d.", count, skipped); }else{ logf("Finished gio_generic_savelist [%d].", count); } return true; } /**************************************************************************/ void * gio_generic_loadlist( int size, gio_type *gio_table, char *filename, int nextoffset) { FILE *fp; void *phead; void *pdata=NULL; void *plast=NULL; int count=0; if(!file_exists(filename)){ logf("File '%s' not found, cancelled gio list loading.", filename); return NULL; } logf("gio_generic_loadlist() reading in from %s... ", filename); fclose( fpReserve ); if ( ( fp = fopen( filename, "r" ) ) == NULL ) { bugf("gio_generic_loadlist(): fopen '%s' for read - error %d (%s)", filename, errno, strerror( errno)); bugf("An error occured! reading from %s", filename); fpReserve = fopen( NULL_FILE, "r" ); return NULL; } // Go thru linked list reading each node from disk plast=pdata; pdata=malloc(size); phead=pdata; memset( pdata, 0, (size_t) size); while (loadRecord(gio_table,pdata,fp)<2) { plast=pdata; pdata=malloc(size); *(void **)(((char*) plast )+nextoffset)=pdata; memset( pdata, 0, (size_t) size); count++; } if(plast) { *(void **)(((char*) plast )+nextoffset)=NULL; } fclose( fp ); fpReserve = fopen( NULL_FILE, "r" ); logf("Finished gio_generic_loadlist [%d].", count); return phead; } /**************************************************************************/ // convert a text into a value ignoring if the wordtext is settable. int wordflag_to_value( const struct flag_type *flag_table, const char *wordtext) { char *wf_str, *ptr_str; char single_word[MIL]; int result, flag; char buf[MIL]; strcpy(buf, wordtext); // read in the string wf_str = buf; // break down and find words one at a time // convert all white spaces into ' ' for one arg first ptr_str=wf_str; do{ if (*ptr_str=='\t' || *ptr_str=='\n' || *ptr_str=='\r') *ptr_str=' '; }while (*++ptr_str); // support stat tables if ( is_stat( flag_table ) ) { ptr_str=wf_str; one_argument( ptr_str, single_word); if ( ( result= gioflag_lookup( single_word, flag_table ) ) != NO_FLAG ){ return result; }else{ return 0; } } // loop thru all the words and match up what we can find result=0; ptr_str=wf_str; while (!IS_NULLSTR(ptr_str)){ ptr_str = one_argument( ptr_str, single_word); for (flag = 0; flag_table[flag].name != NULL; flag++) { if ( single_word[0]==flag_table[flag].name[0] && !str_cmp( single_word, flag_table[flag].name)) { SET_BIT(result, flag_table[flag].bit); break; } } // if we didn't find the word in that table if (!flag_table[flag].name){ logf("fread_wordflag(): unfound wordflag '%s'... table firstword='%s'", single_word, flag_table[0].name); } } return (result); } /**************************************************************************/ /**************************************************************************/