void signal_handler(int sig) { /* Since our 'shutdown_wgrace' is not reentrant, and may (likely) access * non-volatile global variables, be damn sure it's not called twice. */ if ( fatal_error_in_process ) raise(sig); switch(sig) { case SIGBUS: case SIGTERM: case SIGABRT: case SIGSEGV: case SIGFPE: case SIGILL: fatal_error_in_process = 1; /* Yes, this IS a fatal error */ bugf("BUG: Signal handler in %s.", /* Log signal to bug log file */ (sig == SIGBUS) ? "SIGBUS" : (sig == SIGTERM) ? "SIGTERM" : (sig == SIGABRT) ? "SIGABRT" : (sig == SIGSEGV) ? "SIGSEGV" : (sig == SIGFPE) ? "SIGFPE" : "SIGILL"); bugf("Bugged function :%s.", last_command ? last_command : "unknown"); shutdown_wgrace(); /* Attempt a graceful shutdown */ raise(sig); /* set return status of process */ break; } }
/* * Load in all the class files. */ void load_classes( void ) { FILE *fpList; const char *filename; char fname [ MAX_STRING_LENGTH ]; char classlist [ MAX_STRING_LENGTH ]; int stat; log_string( "Loading classes" ); sprintf( classlist, "%s%s", CLASS_DIR, CLASS_LIST ); if ( !( fpList = fopen( classlist, "r" ) ) ) { perror( classlist ); exit( 1 ); } for ( ; ; ) { GET_TOKEN( fpList, filename, "$" ); strcpy( fname, filename ); if ( fname[0] == '$' ) break; if ( fread_class( fname ) ) fputc( '.', stderr ); else bugf( "Cannot load class file: %s", fname ); } fclose( fpList ); fputc( '\n', stderr ); return; }
/***************************************************************************** Name: show_olc_cmds Purpose: Format up the commands from given table. Called by: show_commands(olc_act.c). ****************************************************************************/ void show_olc_cmds( CHAR_DATA *ch ) { char buf[MAX_STRING_LENGTH]; char buf1[MAX_STRING_LENGTH]; const struct olc_comm_type * tabla; int cmd; int col; buf1[0] = '\0'; col = 0; tabla = get_olc_tabla(ch->desc->editor); if (tabla == NULL) { bugf( "slow_olc_cmds : tabla NULL, editor %d", ch->desc->editor ); return; } for (cmd = 0; tabla[cmd].number != NULL; cmd++) { sprintf (buf, "%-15.15s", tabla[cmd].number); strcat (buf1, buf); if (++col % 5 == 0) strcat (buf1, "\n\r"); } if (col % 5 != 0) strcat (buf1, "\n\r"); send_to_char (buf1, ch); return; }
/* * If string is in shared space, decrement usage, if usage then is 0, * free the chunk and attempt to merge with next node. Other * strings are freed with standard free. * Never call free/delete externally on a shared string. */ void _free_string(char *str, const char *caller) { BufEntry *ptr; if (!str || str == &str_empty[0]) return; if (str > string_space && str < top_string) { ptr = (BufEntry *) (str - HEADER_SIZE); if (--ptr->usage > 0) return; else if (ptr->usage < 0) { bugf("SSM: free_string: multiple free/invalid from %s: %20.20s", caller, (char *)&ptr->buf[0]); return; } numFree++; sAllocString -= (ptr->size + HEADER_SIZE); nAllocString--; if (!ssm_buf_free || ssm_buf_free > ptr) ssm_buf_free = ptr; if (fBootDb) { TempHash *ptr; TempHash *walk; int ihash = get_string_hash( str, strlen( str ) ); for (ptr = temp_string_hash[ihash]; ptr; ptr = ptr->next) { if (ptr->str != str) continue; else if (ptr == temp_string_hash[ihash]) temp_string_hash[ihash] = ptr->next; else for (walk = temp_string_hash[ihash]; walk; walk = walk->next) { if (walk->next == ptr) { walk->next = ptr->next; break; } } free(ptr); break; } } return; } sOverFlowString -= strlen(str) + 1; nOverFlowString--; free(str); }
/* * Command to allow the player to show the terrain type of the room they * are in. */ void do_terrain(CHAR_DATA *ch, char *argument) { if (ch == NULL || ch->in_room == NULL) { return; } switch (ch->in_room->sector_type) { case(SECT_INSIDE): send_to_char("You are indoors.\r\n", ch); break; case(SECT_CITY): send_to_char("You see the city about you... not a lot of terrain.\r\n", ch); break; case(SECT_FIELD): send_to_char("The terrain is that of fields.\r\n", ch); break; case(SECT_FOREST): send_to_char("The terrain is that of the forest.\r\n", ch); break; case(SECT_HILLS): send_to_char("The terrain is that of the hills.\r\n", ch); break; case(SECT_MOUNTAIN): send_to_char("The terrain is that of the mountains.\r\n", ch); break; case(SECT_AIR): send_to_char("There is no terrain, your in the air!\r\n", ch); break; case(SECT_DESERT): send_to_char("The terrain is that of the desert.\r\n", ch); break; case(SECT_BEACH): send_to_char("The terrain is that of the beach.\r\n", ch); break; case(SECT_OCEAN): send_to_char("You are in the ocean!\r\n", ch); break; case(SECT_UNDERWATER): send_to_char("You are underwater!\r\n", ch); break; case(SECT_WATER_SWIM): case(SECT_WATER_NOSWIM): send_to_char("You are in the water.\r\n", ch); break; case(SECT_UNDERGROUND): send_to_char("The terrain is that of the underground.\r\n", ch); break; default: send_to_char("The terrain type is undetermined.\r\n", ch); bugf("Unhandled terrain type in do_terrain for vnum %d", ch->in_room->vnum); break; } act("$n takes a look around $mself and examines the terrain.", ch, NULL, NULL, TO_ROOM); return; }
/* * Read and allocate space for a string from a file. * This replaces db.c fread_string * This is modified version of Furey's fread_string from Merc */ char *_fread_string(FILE * fp, const char *caller) { char buf[MAX_STRING_LENGTH * 4]; char *ptr = buf; char c; do { c = getc(fp); } while (isspace(c)); if ((*ptr++ = c) == '~') return &str_empty[0]; for (;;) { switch (*ptr = getc(fp)) { default: ptr++; break; case EOF: bugf("Fread_string: EOF"); raise(SIGSEGV); break; case '\n': ptr++; *ptr++ = '\r'; break; case '\r': break; case '~': *ptr = '\0'; if (fBootDb) { int len = ptr - buf; ptr = temp_hash_find(buf, len); if (ptr) return _str_dup(ptr, caller); ptr = _str_dup(buf, caller); temp_hash_add(ptr, len); return ptr; } ptr=_str_dup(buf, caller); tail_chain(); return ptr; } } }
void hedit( CHAR_DATA *ch, char *argument) { HELP_DATA * pHelp; HELP_AREA *had; char arg[MAX_INPUT_LENGTH]; char command[MAX_INPUT_LENGTH]; int cmd; smash_tilde(argument); strcpy(arg, argument); argument = one_argument( argument, command); EDIT_HELP(ch, pHelp); had = get_help_area(pHelp); if (had == NULL) { bugf( "hedit : had para help %s NULL", pHelp->keyword ); edit_done(ch); return; } if (ch->pcdata->security < 9) { send_to_char("HEdit: Insuficiente seguridad para editar help.\n\r",ch); edit_done(ch); return; } if (command[0] == '\0') { hedit_show(ch, argument); return; } if (!str_cmp(command, "done") ) { edit_done(ch); return; } for (cmd = 0; hedit_table[cmd].name != NULL; cmd++) { if (!str_prefix(command, hedit_table[cmd].name) ) { if ((*hedit_table[cmd].olc_fun) (ch, argument)) had->changed = TRUE; return; } } interpret(ch, arg); return; }
/* * New code for writing a clan to a file. */ void save_clan( CLAN_DATA *clan ) { FILE *fp; char buf [ MAX_STRING_LENGTH ]; if ( !clan->filename ) return; sprintf( buf, "%s%s", CLAN_DIR, clan->filename ); fclose( fpReserve ); if ( !( fp = fopen( buf, "w" ) ) ) { bugf( "Cannot open: %s for writing", clan->filename ); } else { fprintf( fp, "#CLAN\n" ); fprintf( fp, "WhoName %s~\n", clan->who_name ); fprintf( fp, "Name %s~\n", clan->name ); fprintf( fp, "Motto %s~\n", clan->motto ); fprintf( fp, "Desc %s~\n", fix_string( clan->description ) ); fprintf( fp, "Overlord %s~\n", clan->overlord ); fprintf( fp, "Chieftain %s~\n", clan->chieftain ); fprintf( fp, "PKills %d\n", clan->pkills ); fprintf( fp, "PDeaths %d\n", clan->pdeaths ); fprintf( fp, "MKills %d\n", clan->mkills ); fprintf( fp, "MDeaths %d\n", clan->mdeaths ); fprintf( fp, "IllegalPK %d\n", clan->illegal_pk ); fprintf( fp, "Score %d\n", clan->score ); fprintf( fp, "ClanType %d\n", clan->clan_type ); fprintf( fp, "Clanheros %d\n", clan->clanheros ); fprintf( fp, "Subchiefs %d\n", clan->subchiefs ); fprintf( fp, "Members %d\n", clan->members ); fprintf( fp, "ClanObjOne %d\n", clan->clanobj1 ); fprintf( fp, "ClanObjTwo %d\n", clan->clanobj2 ); fprintf( fp, "ClanObjThree %d\n", clan->clanobj3 ); fprintf( fp, "Recall %d\n", clan->recall ); fprintf( fp, "Donation %d\n", clan->donation ); if ( clan->cclass ) fprintf( fp, "Class %s~\n", clan->cclass->name ); fprintf( fp, "End\n" ); fprintf( fp, "#END\n" ); fclose( fp ); } fpReserve = fopen( NULL_FILE, "r" ); return; }
/* * Read string into user supplied buffer. * Modified version of Furey's fread_string */ void temp_fread_string(FILE * fp, char *buf) { char *ptr = buf; char c; do { c = getc(fp); } while (isspace(c)); if ((*ptr++ = c) == '~') { *buf = '\0'; return; } for (;;) { switch (*ptr = getc(fp)) { default: ptr++; break; case EOF: bugf("Fread_string: EOF"); raise(SIGSEGV); break; case '\n': ptr++; *ptr++ = '\r'; break; case '\r': break; case '~': *ptr = '\0'; return; } } }
//ta fukcja szuka arta do wywalenia i od razu go wywala z listy OBJ_DATA * przeszukanie( OBJ_DATA *list, sh_int vnum, OBJ_DATA *container ) { OBJ_DATA * found = NULL; OBJ_DATA *obj, *prev_obj = NULL; for ( obj = list; obj; obj = obj->next_content ) { if ( obj->contains ) found = przeszukanie( obj->contains, vnum, obj ); if ( found ) return found; if ( obj->pIndexData->vnum == vnum ) { if ( container == NULL && prev_obj == NULL ) { bugf("Small probability bug encountered. See comments on how to deal with it."); /* Mieli¶my pecha i trafi³a nam siê sytuacja taka, ¿e usuwany artefakt jest pierwszym elementem w ekwipunku gracza. W tym momencie prev_obj jest równy NULL i container tak¿e. Mo¿na sprawiæ, by ten kod nigdy siê nie wychrznia³: wystarczy ¿e container nie bêdzie wska¼nikiem na pojemnik, ale bardziej ogólnie, wska¼nikiem na zmienn± w pojemniku przechowuj±c± zawarto¶æ. To znaczy, jedno z dwóch: ch->carrying # dla postaci cointainer->contains # dla pojemników Taka zmiana jest jednak czasoch³onna i podatna na dalsze b³êdy. Zamiast tego zwracamy NULL. */ return NULL; } if ( container != NULL && prev_obj == NULL ) { container->contains = obj->next_content; } else prev_obj->next_content = obj->next_content; return obj; } prev_obj = obj; } return NULL; }
void init_string_space() { BufEntry *walk; int i; string_space = (char *) malloc(MAX_STRING); if (!string_space) { bugf("SSM: Can't allocate %ld bytes shared string space.", MAX_STRING); raise(SIGSEGV); } top_string = string_space + MAX_STRING - 1; ssm_buf_head = (BufEntry *) string_space; HEADER_SIZE = (int) ((char *) &ssm_buf_head->buf[0] - (char *) ssm_buf_head); walk = ssm_buf_head; for (i = 0;; i++) { walk->usage = 0; walk->size = CHUNK_SIZE - HEADER_SIZE; if (i < MAX_CHUNKS - 1) { walk->next = (BufEntry *) ((char *) walk + CHUNK_SIZE); walk = walk->next; continue; } walk->next = 0; break; } ssm_buf_free = ssm_buf_head; temp_string_hash = (TempHash **) calloc(sizeof(TempHash *), MAX_KEY_HASH); }
void write_interpret( CHAR_DATA * ch, char *argument ) { BUF_DATA_STRUCT *buf_data; char *buf; int curlen; for ( buf_data = first_buf; buf_data != NULL; buf_data = buf_data->next ) { if ( buf_data->ch == ch ) break; } if ( buf_data == NULL ) { bugf( "Call to write_interpret when not writing (char=%s)\r\n", ch->name.c_str() ); ch->position = POS_STANDING; return; } buf = buf_data->buf; /* * Check to see if text was a command or simply addition */ if ( argument[0] != '.' ) { curlen = strlen( buf ); if ( curlen > MAX_STRING_LENGTH - 240 ) { send_to_char( "String to long, cannot add new line.\r\n", ch ); return; } for ( buf = buf + curlen; *argument != '\0'; ) *( buf++ ) = *( argument++ ); *( buf++ ) = '\n'; *( buf++ ) = '\r'; *buf = '\0'; return; } /* * We have a command. */ /* * Commands are .help .save .preview .- .clear .lines */ argument++; if ( argument[0] == '\0' || !str_prefix(argument, "save") || !str_prefix(argument, "quit") ) { bool save; char **dest; if ( !str_prefix(argument, "quit") ) save = false; else save = true; dest = buf_data->dest; ch = buf_data->ch; /* * Save routine. */ if ( save ) { /* * Check that dest still points to buf (to check for corruption) */ if ( *dest != buf ) { bug( "write_interpret: Original destination has been overwritten.", 0 ); send_to_char( "Cannot save, string pointer been modified.\r\n", ch ); } else { FILE *fp = NULL; if ( ch->pcdata->header != &str_empty[0] ) /* File passed from helpedit */ { if ( (fp = file_open(ch->pcdata->header, "w")) == NULL ) { send_to_char("Something is broken in write_interpret saving to file.\r\n", ch); file_close(fp); return; } } *dest = str_dup( buf ); if ( ( buf_data->returnfunc ) != NULL ) ( *buf_data->returnfunc ) ( buf_data->returnparm, dest, ch, TRUE ); if ( ch->pcdata->header != &str_empty[0] ) /* File passed from helpedit */ { fprintf(fp, "%s", buf); file_close(fp); } } } else { *dest = &str_empty[0]; if ( ( buf_data->returnfunc ) != NULL ) ( *buf_data->returnfunc ) ( buf_data->returnparm, dest, ch, FALSE ); } /* * Re-use memory. */ dispose( buf_data->buf, MAX_STRING_LENGTH ); UNLINK( buf_data, first_buf, last_buf, next, prev ); /* * Re-set char */ ch->position = buf_data->old_char_pos; delete buf_data; return; } if ( !str_prefix(argument, "help") ) { /* * Help */ ch = buf_data->ch; send_to_char( "Normal type will be appended to the string, line by line.\r\n", ch ); send_to_char( ".help or .h : displays this help.\r\n", ch ); send_to_char( ".save or . : saves and exits the editor.\r\n", ch ); send_to_char( ".preview or .p : display a preview of the text.\r\n", ch ); send_to_char( ".-[num] or .- : deletes [num] lines from the end, or just one line\r\n", ch ); send_to_char( ".clear : deletes whole text.\r\n", ch ); send_to_char( ".quit or .q : quits without saving.\r\n", ch ); send_to_char( ".format or .f : formats text for 80 chars.\r\n", ch ); send_to_char( ".replace or .r : replaces word with string.\r\n", ch ); send_to_char( " (usage) : .r <word> <string>. If no string, arg1 deleted.\r\n", ch ); return; } if ( !str_prefix(argument, "replace") ) { /* * Mag: I bet you take one look at this, and change it :) -S- */ char arg1[MAX_STRING_LENGTH]; char arg2[MAX_STRING_LENGTH]; char word[MAX_STRING_LENGTH]; char new_buf[MAX_STRING_LENGTH]; char pBuf; int pos; int npos; int wpos; int buf_length; int foo; int i; char *src; argument = one_argument( argument + 1, arg1 ); /* Skip the R */ strcpy( arg2, argument ); if ( arg1[0] == '\0' ) { send_to_char( "No arg1 supplied for replace command.\r\n", ch ); return; } new_buf[0] = '\0'; buf_length = strlen( buf ); pos = 0; npos = 0; wpos = 0; word[0] = '\0'; for ( ;; ) { pBuf = buf[pos]; if ( pBuf == '\0' || pos > buf_length ) break; if ( pBuf == ' ' ) { new_buf[npos] = ' '; pos++; npos++; continue; } if ( !isgraph( pBuf ) ) { new_buf[npos] = pBuf; pos++; npos++; continue; } wpos = 0; for ( ;; ) { if ( !isgraph( pBuf ) ) break; word[wpos] = pBuf; pos++; wpos++; pBuf = buf[pos]; } word[wpos] = '\0'; if ( !str_cmp( word, arg1 ) ) { if ( arg2[0] != '\0' ) for ( foo = 0; arg2[foo] != '\0'; foo++ ) { new_buf[npos] = arg2[foo]; npos++; } else { /* * Do nothing (much). */ if ( npos > 0 ) npos--; send_to_char( "Arg1 deleted.\r\n", ch ); } } else { for ( foo = 0; word[foo] != '\0'; foo++ ) { new_buf[npos] = word[foo]; npos++; } } } /* * -gulp- Copy new_buf into message structure... */ src = buf; for ( i = 0; i < npos; i++ ) *( src++ ) = new_buf[i]; *( src ) = '\0'; return; } if ( !str_prefix(argument, "preview") ) { send_to_char( buf, ch ); return; } if ( argument[0] == '-' ) { int num; int a; argument++; if ( argument[0] == '\0' ) num = 2; else num = atoi( argument ) + 1; if ( num <= 0 ) return; for ( a = strlen( buf ); a >= 0; a-- ) { if ( buf[a] == '\n' ) { num--; if ( num == 0 ) break; } } if ( a == 0 ) { send_to_char( "Tried to delete too many lines.\r\n", buf_data->ch ); return; } a++; if ( buf[a] == '\r' ) a++; send_to_char( "Deleted:\r\n", buf_data->ch ); send_to_char( buf + a, buf_data->ch ); buf[a] = '\0'; return; } if ( !str_prefix(argument, "format") ) { char *src; char dest[MAX_STRING_LENGTH]; int col; char *srcspc; int destspc; char c; int n, i; int lastcol; /* * Format text */ /* * Go through line by line, doing word wrapping */ lastcol = 79; col = 0; n = 0; srcspc = NULL; destspc = 0; for ( src = buf; *src != '\0'; ) { c = *( src++ ); switch ( c ) { case '\n': /* Convert /n/r into one space */ if ( ( *src == '\r' ) && ( *( src + 1 ) == '\n' ) && ( *( src + 2 ) == '\r' ) ) { /* * Do not convert paragraph endings. */ dest[n++] = c; /* \n */ dest[n++] = *( src++ ); /* \r */ dest[n++] = *( src++ ); /* \n */ dest[n++] = *( src++ ); /* \r */ col = 0; srcspc = NULL; destspc = 0; break; } /* * Also if there is a space on the next line, don't merge. */ if ( ( *src == '\r' ) && ( *( src + 1 ) == ' ' ) ) { dest[n++] = c; /* \n */ dest[n++] = *( src++ ); /* \r */ col = 0; srcspc = NULL; destspc = 0; break; } /* * Otherwise convert to a space */ /* * Get rid of spaces at end of a line. */ if ( n > 0 ) { while ( dest[--n] == ' ' ); n++; } dest[n++] = ' '; col++; srcspc = src - 1; destspc = n - 1; break; case '\r': break; case '\t': /* Tab */ col += 7; case '.': /* Punctuation */ case ' ': case ',': case ';': case '?': case '!': case ')': srcspc = src - 1; destspc = n - 1; case '-': if ( srcspc == NULL ) { srcspc = src - 1; /* Only use a dash if necessary */ destspc = n - 1; } case '@': /* Color */ dest[n++] = c; break; default: if ( dest[n - 1] == '@' ) /* We're a color code */ { dest[n++] = c; break; } dest[n++] = c; col++; break; } if ( col >= lastcol ) { /* * Need to do a line break */ if ( srcspc == NULL ) { /* * there were no breakable characters on the line. */ dest[n++] = '\n'; dest[n++] = '\r'; } else { n = destspc; /* n now points to a breakable char. */ src = srcspc; while ( dest[n] == ' ' || dest[n] == '\n' ) { n--; } src++; n++; if ( *src == '\r' ) src++; while ( *src == ' ' ) src++; /* * src now points to the new line to be put in dest. */ dest[n++] = '\n'; dest[n++] = '\r'; col = 0; srcspc = NULL; destspc = 0; } } } /* * Get rid of spaces at end, and add a newline. */ while ( dest[--n] == ' ' ); n++; dest[n++] = '\n'; dest[n++] = '\r'; /* * Copy from dest back into buffer */ src = buf; for ( i = 0; i < n; i++ ) *( src++ ) = dest[i]; *( src ) = '\0'; return; } if ( !str_cmp( argument, "clear" ) ) { buf[0] = '\0'; send_to_char( "Done.\r\n", buf_data->ch ); return; } send_to_char( "Command not known, type .help for help.\r\n", buf_data->ch ); return; }
/* * Function finds out if a seed will grow into something else. */ void seed_grow_check(OBJ_DATA *obj) { OBJ_DATA *obj_temp; int chance = 0; int count = 0; // Initial checks to ditch out, object must exist, room must exist // and the seed must be buried. Also no growing in certain sectors // should an item somehow get buried there. if (obj == NULL || obj->in_room == NULL || obj->item_type != ITEM_SEED || !IS_OBJ_STAT(obj, ITEM_BURIED)) { return; } // Places it should never be buried. if (obj->in_room->sector_type == SECT_INSIDE || obj->in_room->sector_type == SECT_WATER_SWIM || obj->in_room->sector_type == SECT_WATER_NOSWIM || obj->in_room->sector_type == SECT_UNDERWATER || obj->in_room->sector_type == SECT_AIR) { bugf("Item buried in a sector_type (%d) it shouldn't be at room %d", obj->in_room->sector_type, obj->in_room->vnum); return; } // If the object doesn't have a vnum set to grow, report it, extract it. if (obj->value[0] == 0) { bugf("Seed vnum %d does not have a vnum set for the item to grow, extracting object.", obj->pIndexData->vnum); separate_obj(obj); extract_obj(obj); return; } // Setup the base chance based off of sector type of the room it's planted in. switch (obj->in_room->sector_type) { case SECT_DESERT: chance -= 75; break; case SECT_BEACH: chance -= 50; break; case SECT_FIELD: chance += 35; break; case SECT_MOUNTAIN: chance -= 15; break; case SECT_HILLS: case SECT_FOREST: chance += 25; break; default: chance = 0; break; } if (IS_OBJ_STAT(obj, ITEM_BLESS)) { chance += 5; } if (IS_OBJ_STAT(obj, ITEM_GLOW)) { chance += 5; } if (IS_OBJ_STAT(obj, ITEM_EVIL)) { chance -= 5; } // Add the immortal initial set chance plus randomness. chance += obj->value[1]; chance += number_range(1, 20); // Count any other seeds that might be buried in the room. for (obj_temp = obj->in_room->contents; obj_temp; obj_temp = obj_temp->next_content) { if (obj_temp->item_type == ITEM_SEED && IS_OBJ_STAT(obj_temp, ITEM_BURIED)) { count++; } } // The more seeds that are planted the less chance any will grow. if (count > 3) { chance -= (3 * count); } // Seeds have a greaater chance of growing during the day. if (IS_DAY()) { chance += 15; } else { chance -= 15; } // Always at least 1 percent chance, always a chance for failure chance = URANGE(1, chance, 95); // The moment of truth. if (!CHANCE(chance)) { return; } // Remove the buried bit, it's going to get extracted but we want people to be able // to see it's short description in the act message and they won't unless it's not buried. separate_obj(obj); REMOVE_BIT(obj->extra_flags, ITEM_BURIED); // Show the room that something has sprouted. if (obj->in_room != NULL && obj->in_room->people != NULL) { act("$p sprouts and grows from the ground!", obj->in_room->people, obj, NULL, TO_ALL); } // Create the new object that has been grown, set it's intiial values and // put it in the room. obj_temp = create_object(get_obj_index(obj->value[0])); obj_to_room(obj_temp, obj->in_room); obj_temp->cost = ((obj->cost * 3) / 2); obj_temp->timer = number_range(75, 200); // Life span of the grown item // Extract the seed (it's already been separated, it's job in this world is complete. extract_obj(obj); return; }
/* * New code for loading classes from file. */ bool fread_class( char *filename ) { FILE *fp; char *word; struct class_type *class; char buf [ MAX_STRING_LENGTH ]; bool fMatch; int stat; int number = -1; sprintf( buf, "Loading class: %s", filename ); log_string( buf ); sprintf( buf, "%s%s%s", data_directory, CLASS_DIR, filename ); if ( !( fp = fopen( buf, "r" ) ) ) { perror( buf ); return FALSE; } class = alloc_mem ( sizeof( CLASS_TYPE ) ); for ( ; ; ) { word = feof( fp ) ? "End" : fread_word( fp, &stat ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'A': KEY( "AtrPrm", class->attr_prime, fread_number( fp, &stat ) ); break; case 'C': KEY( "Cla", number, fread_number( fp, &stat ) ); if ( number < 0 || number >= MAX_CLASS ) { sprintf( buf, "Fread_class: bad class '%s'.", filename ); bug ( buf, 0 ); return FALSE; } break; case 'E': if ( !str_cmp( word, "End" ) ) { fclose( fp ); class_table[number] = class; return TRUE; } break; case 'H': KEY( "Hpmin", class->hp_min, fread_number( fp, &stat ) ); KEY( "Hpmax", class->hp_max, fread_number( fp, &stat ) ); break; case 'M': KEY( "Mana", class->fMana, fread_number( fp, &stat ) ); break; case 'N': SKEY( "Nm", class->name ); break; case 'S': KEY( "SkllAdpt", class->skill_adept, fread_number( fp, &stat ) ); if ( !str_cmp( word, "Skll" ) ) { int sn; int value; char *word; value = fread_number( fp, &stat ); sn = skill_lookup( (word = fread_word( fp, &stat )) ); if ( sn < 0 ) { sprintf( buf, "Fread_class - unknown skill: %s", word ); bug( buf, 0 ); } else skills_table[sn].skill_level[number] = value; fMatch = TRUE; } else if ( !str_cmp( word, "Spll" ) ) { int sn; int value; char *word; value = fread_number( fp, &stat ); sn = spell_lookup( (word = fread_word( fp, &stat )) ); if ( sn < 0 ) { sprintf( buf, "Fread_class - unknown spell: %s", word ); bug( buf, 0 ); } else { if( value <= MAX_CIRCLE && value > 0 ) { spells_table[sn].spell_circle[number] = value; } else { bug( "Spell in class file has level greater than MAX_CIRCLE", 0 ); spells_table[sn].spell_circle[number] = MAX_CIRCLE+2; } } fMatch = TRUE; } else if ( !str_cmp( word, "Song" ) ) { int sn; int value; char *word; value = fread_number( fp, &stat ); sn = song_lookup( (word = fread_word( fp, &stat )) ); if ( sn < 0 ) { sprintf( buf, "Fread_class - unknown song: %s", word ); bug( buf, 0 ); } else { if( value < MAX_LEVEL ) { songs_table[sn].spell_circle[number] = value; } else { bug( "Song in class file has level greater than MAX_LEVEL", 0 ); songs_table[sn].spell_circle[number] = MAX_LEVEL; } } fMatch = TRUE; } break; case 'T': KEY( "Thac0", class->thac0_00, fread_number( fp, &stat ) ); KEY( "Thac47", class->thac0_47, fread_number( fp, &stat ) ); break; case 'W': SKEY( "WhoNm", class->who_name ); KEY( "Wpn", class->weapon, fread_number( fp, &stat ) ); break; } if ( !fMatch ) { bugf( "load_class_file: no match: %s", word ); } }
/* * New code for loading classes from file. */ bool fread_class( char *filename ) { FILE *fp; static CLASS_TYPE class_zero; CLASS_TYPE *cclass; const char *word; char buf [ MAX_STRING_LENGTH ]; bool fMatch; int stat; int level; int i; sprintf( buf, "%s%s", CLASS_DIR, filename ); if ( !( fp = fopen( buf, "r" ) ) ) { perror( buf ); return FALSE; } strcpy( strArea, filename ); fpArea = fp; cclass = (CLASS_TYPE *) alloc_mem ( sizeof( CLASS_TYPE ) ); *cclass = class_zero; cclass->skill_level = (int *) alloc_mem( sizeof( int ) * MAX_SKILL ); cclass->skill_adept = (int *) alloc_mem( sizeof( int ) * MAX_SKILL ); cclass->skill_rating = (int *) alloc_mem( sizeof( int ) * MAX_SKILL ); /* Initialize MAX_SPELL marker so noone can use it. */ cclass->skill_level[MAX_SPELL] = MAX_LEVEL+1; for ( i = 0; i < MAX_SKILL; i++ ) { cclass->skill_level[i] = L_APP; cclass->skill_adept[i] = 0; } for ( i = 0; i <= MAX_LEVEL; i++ ) { cclass->title[i][0] = str_dup( "" ); cclass->title[i][1] = str_dup( "" ); } for ( i = 0; i < MAX_POSE; i++ ) { cclass->pose[i][0] = str_dup( "" ); cclass->pose[i][1] = str_dup( "" ); } for ( ; ; ) { GET_TOKEN( fp, word, "End" ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'A': KEY( "AtrPrm", cclass->attr_prime, fread_number( fp, &stat ) ); break; case 'C': break; case 'E': if ( !str_cmp( word, "End" ) ) { fclose( fp ); if ( !class_first ) class_first = cclass; if ( class_last ) class_last->next = cclass; class_last = cclass; fpArea = NULL; return TRUE; } break; case 'G': KEY( "Guild", cclass->guild, fread_number( fp, &stat ) ); break; case 'H': KEY( "Hpmin", cclass->hp_min, fread_number( fp, &stat ) ); KEY( "Hpmax", cclass->hp_max, fread_number( fp, &stat ) ); break; case 'M': KEY( "Mana", cclass->fMana, fread_number( fp, &stat ) ); break; case 'N': SKEY( "Nm", cclass->name ); break; case 'P': if ( !str_cmp( word, "Pose" ) ) { level = fread_number( fp, &stat ); i = fread_number( fp, &stat ); if ( level < MAX_POSE ) { free_string( cclass->pose[level][i] ); cclass->pose[level][i] = fread_string( fp, &stat ); } else bugf( "Fread_class: invalid pose." ); fMatch = TRUE; } break; case 'S': KEY( "SkllAdpt", cclass->max_adept, fread_number( fp, &stat ) ); if ( !str_cmp( word, "Skll" ) ) { int sn; int value1; int value2; int value3; value1 = fread_number( fp, &stat ); value2 = fread_number( fp, &stat ); value3 = fread_number( fp, &stat ); word = fread_word( fp, &stat ); sn = skill_lookup( word ); if ( sn == -1 ) { bugf( "Fread_class: unknown skill: %s.", word ); } else { cclass->skill_level [sn] = value1; cclass->skill_rating[sn] = value2; cclass->skill_adept [sn] = value3; } fMatch = TRUE; } break; case 'T': KEY( "Thac0", cclass->thac0_00, fread_number( fp, &stat ) ); KEY( "Thac47", cclass->thac0_47, fread_number( fp, &stat ) ); if ( !str_cmp( word, "Ttle" ) ) { i = fread_number( fp, &stat ); if ( i <= MAX_LEVEL ) { free_string( cclass->title[i][0] ); free_string( cclass->title[i][1] ); cclass->title[i][0] = fread_string( fp, &stat ); cclass->title[i][1] = fread_string( fp, &stat ); } else bugf( "Fread_class: too many titles." ); fMatch = TRUE; } break; case 'W': SKEY( "WhoNm", cclass->who_name ); KEY( "Wpn", cclass->weapon, fread_number( fp, &stat ) ); break; } if ( !fMatch ) { bugf( "load_class_file: no match: %s", word ); } } return FALSE; }
bool load_clan_file( char *filename ) { CLAN_DATA *clan; FILE *fp; int stat; char buf [ MAX_STRING_LENGTH ]; sprintf( buf, "%s%s", CLAN_DIR, filename ); if ( !( fp = fopen( buf, "r" ) ) ) { perror( buf ); return FALSE; } clan = (CLAN_DATA *) alloc_mem ( sizeof( CLAN_DATA ) ); clan->filename = str_dup( filename ); for ( ; ; ) { char *word; int letter; letter = fread_letter( fp ); if ( letter == '*' ) { fread_to_eol( fp ); continue; } if ( letter != '#' ) { bug( "Load_clan_file: # not found.", 0 ); free_mem( clan, sizeof( CLAN_DATA ) ); break; } word = fread_word( fp, &stat ); if ( !str_cmp( word, "CLAN" ) ) { fread_clan( clan, fp ); if ( !clan_first ) clan_first = clan; else clan_last->next = clan; clan->next = NULL; clan_last = clan; break; } else if ( !str_cmp( word, "END" ) ) break; else { bugf( "Load_clan_file: bad section: %s.", word ); free_mem( clan, sizeof( CLAN_DATA ) ); break; } } fclose( fp ); return TRUE; }
/* * New code for loading clans from file. */ bool fread_clan( CLAN_DATA *clan, FILE *fp ) { const char *word; bool fMatch; int stat; for ( ; ; ) { GET_TOKEN( fp, word, "End" ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'C': SKEY( "Chieftain", clan->chieftain ); if ( !str_cmp( word, "Class" ) ) { clan->cclass = class_lookup( temp_fread_string( fp, &stat ) ); fMatch = TRUE; break; } KEY( "ClanHeros", clan->clanheros, fread_number( fp, &stat ) ); KEY( "ClanType", clan->clan_type, fread_number( fp, &stat ) ); KEY( "ClanObjOne", clan->clanobj1, fread_number( fp, &stat ) ); KEY( "ClanObjTwo", clan->clanobj2, fread_number( fp, &stat ) ); KEY( "ClanObjThree", clan->clanobj3, fread_number( fp, &stat ) ); break; case 'D': SKEY( "Desc", clan->description ); KEY( "Donation", clan->donation, fread_number( fp, &stat ) ); break; case 'E': if ( !str_cmp( word, "End" ) ) return TRUE; break; case 'I': KEY( "IllegalPK", clan->illegal_pk, fread_number( fp, &stat ) ); break; case 'M': KEY( "Members", clan->members, fread_number( fp, &stat ) ); KEY( "MKills", clan->mkills, fread_number( fp, &stat ) ); KEY( "MDeaths", clan->mdeaths, fread_number( fp, &stat ) ); SKEY( "Motto", clan->motto ); break; case 'N': SKEY( "Name", clan->name ); break; case 'O': SKEY( "Overlord", clan->overlord ); break; case 'P': KEY( "PKills", clan->pkills, fread_number( fp, &stat ) ); KEY( "PDeaths", clan->pdeaths, fread_number( fp, &stat ) ); break; case 'R': KEY( "Recall", clan->recall, fread_number( fp, &stat ) ); break; case 'S': KEY( "Score", clan->score, fread_number( fp, &stat ) ); KEY( "Subchiefs", clan->subchiefs, fread_number( fp, &stat ) ); break; case 'W': SKEY( "WhoName", clan->who_name ); break; } if ( !fMatch ) { bugf( "Load_clan_file: no match: %s", word ); } } return FALSE; }
void fread_social( FILE *fp ) { const char *word; SOC_INDEX_DATA *social; bool fMatch; int stat; social = new_social( ); for ( ; ; ) { GET_TOKEN( fp, word, "End" ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'C': SKEY( "CharNoArg", social->char_no_arg ); SKEY( "CharFound", social->char_found ); SKEY( "CharAuto", social->char_auto ); break; case 'E': if ( !str_cmp( word, "End" ) ) { if ( !social->name ) { bugf( "Fread_social: Name not found" ); free_social( social ); return; } if ( !social->char_no_arg ) { bugf( "Fread_social: CharNoArg not found" ); free_social( social ); return; } add_social( social ); return; } break; case 'N': SKEY( "Name", social->name ); break; case 'O': SKEY( "OthersNoArg", social->others_no_arg ); SKEY( "OthersFound", social->others_found ); SKEY( "OthersAuto", social->others_auto ); break; case 'V': SKEY( "VictFound", social->vict_found ); break; } if ( !fMatch ) { bugf( "Fread_social: no match: %s. Skipping to next line.", word ); fread_to_eol( fp ); } } return; }
void save_class( const CLASS_TYPE *cclass ) { FILE *fp; char buf [ MAX_STRING_LENGTH ]; char filename [ MAX_INPUT_LENGTH ]; int level; int pose; int sn; sprintf( filename, "%s.cls", cclass->who_name ); filename[0] = LOWER( filename[0] ); sprintf( buf, "%s%s", CLASS_DIR, filename ); fclose( fpReserve ); if ( !( fp = fopen( buf, "w" ) ) ) { bugf( "Cannot open: %s for writing", filename ); } else { fprintf( fp, "Nm %s~\n", cclass->name ); fprintf( fp, "WhoNm %s~\n", cclass->who_name ); fprintf( fp, "AtrPrm %d\n", cclass->attr_prime ); fprintf( fp, "Wpn %d\n", cclass->weapon ); fprintf( fp, "Guild %d\n", cclass->guild ); fprintf( fp, "Sklladpt %d\n", cclass->max_adept ); fprintf( fp, "Thac0 %d\n", cclass->thac0_00 ); fprintf( fp, "Thac47 %d\n", cclass->thac0_47 ); fprintf( fp, "Hpmin %d\n", cclass->hp_min ); fprintf( fp, "Hpmax %d\n", cclass->hp_max ); fprintf( fp, "Mana %d\n", cclass->fMana ); for ( sn = 0; sn < MAX_SKILL; sn++ ) { if ( !skill_table[sn].name ) break; if ( ( level = cclass->skill_level[sn] ) < LEVEL_IMMORTAL ) fprintf( fp, "Skll %3d %3d %3d '%s'\n", level, cclass->skill_rating[sn], cclass->skill_adept [sn], skill_table[sn].name ); } for ( level = 0; level <= MAX_LEVEL; level++ ) fprintf( fp, "Ttle %2d %s~ %s~\n", level, cclass->title [level] [0], cclass->title [level] [1] ); for ( pose = 0; pose < MAX_POSE; pose++ ) { fprintf( fp, "Pose %2d %1d %s~\n", pose, 0, cclass->pose[pose][0] ); fprintf( fp, "Pose %2d %1d %s~\n", pose, 1, cclass->pose[pose][1] ); } fprintf( fp, "End\n" ); fclose( fp ); } fpReserve = fopen( NULL_FILE, "r" ); return; }
void remove_artefact_remote( char *name, unsigned int vnum ) { CHAR_DATA * ch; OBJ_DATA *obj; char buf[ MAX_STRING_LENGTH ]; char buf1[ MAX_STRING_LENGTH ]; sprintf( buf1, "imie: %s vnum: %d", name, vnum ); log_string( buf1 ); //sprawdzalismy juz czy istnieje plik wiec: ch = load_char_remote( name ); if ( ch == NULL ) { bugf( "load_char_remote: no match '%s'.", name ); remove_name_from_artefact_list( ch->name ); return; } if ( !ch->carrying ) { free_char( ch ); return; } //dobra to szuka i od razu wywala z listy if ( ch->carrying->pIndexData->vnum == vnum ) { obj = ch->carrying; ch->carrying = ch->carrying->next_content; } else if ( ( obj = przeszukanie( ch->carrying, vnum, NULL ) ) == NULL ) { remove_name_from_artefact_list( ch->name ); restore_char_on_artefact_list( ch ); return ; } sprintf( buf, "ZABRANO PRZETRZYMYWANY ARTEFAKT: Posiadacz:%s Avnum:%s,%d", ch->name, obj->name, obj->pIndexData->vnum ); log_string( buf ); append_file_format_daily(NULL, ARTEFACT_LOG_FILE, "%s -> PRZETRZYMANY :%s vnum:%d (DEL)",ch->name, obj->short_descr, obj->pIndexData->vnum); get_money_from_rent( ch, obj ); //sprawdzic czy kase zapisuje na nowo //daty nie zmieniac przypadkiem !!! //logowac to //tu koncowe rzeczy obj->carried_by = NULL; obj->next_content = NULL; //to sprawdzic czy w workach tez liczone ch->carry_number -= get_obj_number( obj ); ch->carry_weight -= get_obj_weight( obj ); save_char_obj( ch, FALSE, TRUE ); //z TRUE nei zapisuje nowej daty //to cos zle dziala, dodaje zamiast odejmowac ;) remove_name_from_artefact_list( ch->name ); restore_char_on_artefact_list( ch ); free_char( ch ); return ; }
//leci po liscie artow i sprawdza wszystkie pliki graczy z llisty void scan_players_for_artefacts() { struct dirent * pDirent = NULL; DIR *pDir = NULL; ARTEFACT_DATA *atmp = NULL; ARTEFACT_OWNER *otmp = NULL; ARTEFACT_STORER *storer = NULL, *temp_storer = NULL, *first_storer = NULL; int czas; pDir = opendir( "../player/" ); if ( !pDir ) { bugf( "Cannot open players directory. Skipping check." ); return; // can't continue. } //jedziemy po plikach while ( TRUE ) { pDirent = readdir( pDir ); if ( !pDirent ) { break; } for ( atmp = artefact_system; atmp; atmp = atmp->next ) { for ( otmp = atmp->first_owner;otmp;otmp = otmp->next ) { { CHAR_DATA * ch; ch = load_char_remote( otmp->owner ); if ( !ch ) { remove_name_from_artefact_list( otmp->owner ); continue; } otmp->last_logoff = ch->pcdata->last_logoff; free_char( ch ); } remove_artefact_art_destroy( otmp->owner ); //i tu tera sprawdzanie przetrzymywania czas = ( current_time - ( otmp->last_logoff ) ) / ( 24 * 60 * 60 ); if ( atmp->max_day < czas ) //przetrzymane, zabieramy kolesiowi { storer = new_storer_data(); storer->name = otmp->owner; storer->vnum = atmp->avnum; storer->next = NULL; if ( first_storer == NULL ) { first_storer = storer; } else { temp_storer->next = storer; } temp_storer = storer; } } /*alast=atmp;*/ } //fory break; } closedir( pDir ); //dobra to teraz wywalanie,modlmy sie zeby dzialalo for ( temp_storer = first_storer;temp_storer;temp_storer = temp_storer->next ) { remove_artefact_remote( temp_storer->name, temp_storer->vnum ); } return ; }
char * translate_error_code( siginfo_t *info ) { char * signal = NULL, *signal_code_info = NULL; void * addr = NULL; signal = strsignal(info->si_signo); switch( info->si_signo ) { case SIGTERM: switch( info->si_code ) { case SI_USER: signal_code_info = "kill, sigsend or raise";break; case SI_KERNEL: signal_code_info = "kernel";break; case SI_QUEUE: signal_code_info = "sigqueue";break; case SI_TIMER: signal_code_info = "timer expire"; case SI_MESGQ: signal_code_info = "mesg state changed";break; case SI_ASYNCIO: signal_code_info = "AIO completed";break; case SI_SIGIO: signal_code_info = "queued SIGIO";break; } break; case SIGABRT: switch( info->si_code ) { case SI_USER: signal_code_info = "kill, sigsend or raise";break; case SI_KERNEL: signal_code_info = "kernel";break; case SI_QUEUE: signal_code_info = "sigqueue";break; case SI_TIMER: signal_code_info = "timer expire"; case SI_MESGQ: signal_code_info = "mesg state changed";break; case SI_ASYNCIO: signal_code_info = "AIO completed";break; case SI_SIGIO: signal_code_info = "queued SIGIO";break; } break; case SIGILL: addr = info->si_addr; switch( info->si_code ) { case ILL_ILLOPC: signal_code_info = "illegal opcode";break; case ILL_ILLOPN: signal_code_info = "illegal operand";break; case ILL_ILLADR: signal_code_info = "illegal addresing mode";break; case ILL_ILLTRP: signal_code_info = "illegal trap";break; case ILL_PRVOPC: signal_code_info = "privileged opcode";break; case ILL_PRVREG: signal_code_info = "privileged operand";break; case ILL_COPROC: signal_code_info = "coprocessor error";break; case ILL_BADSTK: signal_code_info = "internal stack error";break; } break; case SIGBUS: addr = info->si_addr; switch( info->si_code ) { case BUS_ADRALN: signal_code_info = "invalid address alignment";break; case BUS_ADRERR: signal_code_info = "non-existant physical address";break; case BUS_OBJERR: signal_code_info = "object specific hardware error";break; } break; case SIGFPE: addr = info->si_addr; switch( info->si_code ) { case FPE_INTDIV: signal_code_info = "integer divide by zero";break; case FPE_INTOVF: signal_code_info = "integer overflow";break; case FPE_FLTDIV: signal_code_info = "floating point divide by zero";break; case FPE_FLTOVF: signal_code_info = "floating divide by zero";break; case FPE_FLTUND: signal_code_info = "floating point underflow";break; case FPE_FLTRES: signal_code_info = "floating point inexact result";break; case FPE_FLTINV: signal_code_info = "floating point invalid operation";break; case FPE_FLTSUB: signal_code_info = "subscript out of range";break; } break; case SIGSEGV: addr = info->si_addr; switch( info->si_errno ) { case SEGV_MAPERR: signal_code_info = "address not mapped to object";break; case SEGV_ACCERR: signal_code_info = "invalid permission for mapped object";break; } break; case SIGPOLL: switch( info->si_code ) { case POLL_IN: signal_code_info = "data input available";break; case POLL_OUT: signal_code_info = "output buffers available";break; case POLL_MSG: signal_code_info = "input message available";break; case POLL_ERR: signal_code_info = "i/o error";break; case POLL_PRI: signal_code_info = "high priority input available";break; case POLL_HUP: signal_code_info = "device disconnect";break; } break; } bugf("Signal: %s", signal ? signal : "UNKNOWN?"); if( signal_code_info ) bugf( "Info: %s", signal_code_info ); if( addr != NULL ) bugf("Addres of fault: %x", addr ); if( last_command ) bugf("Bugged function :%s, previous: %s.", last_command, previous_command?previous_command:"BRAK_POPRZEDNIEJ"); return signal_code_info; }
char *_str_dup(const char *str, const char *caller) { BufEntry *ptr; int len; int rlen; char *str_new; ssm_dup_count++; ssm_recent_loops=0; if (!str || !*str) return &str_empty[0]; if (str > string_space && str < top_string) { ptr = (BufEntry *) (str - HEADER_SIZE); if (ptr->usage <= 0) { bugf("str_dup: invalid string from %s: %20.20s", caller, str); ptr->usage=0; /* make it valid again */ } ptr->usage++; return (char *) str; } rlen = len = (int) strlen(str) + 1; /* * Round up to machine dependant address size. * Don't remove this, because when the BufEntry struct is overlaid * the struct must be aligned correctly. */ if ((len + HEADER_SIZE) & addrSizeMask) len += addrTypeSize - ((len + HEADER_SIZE) & addrSizeMask); RETRY: for (ptr = ssm_buf_free; ptr; ptr = ptr->next) { ssm_recent_loops++; ssm_loops++; if (ptr->usage == 0 && ptr->size >= len) break; } if (ptr) ptr->usage = 1; if (!ptr) { if (numFree > 1) numFree++; if (numFree >= MAX_FREE) { int merges; log_f("SSM: Attempting to optimize shared string heap."); merges = defrag_heap(); /* goto is fine because defrag will return 0 next time */ if (merges) goto RETRY; } /* A one time toggle just for bugging purposes */ if (!Full) { bugf("SSM: The shared string heap is full!"); Full = 1; } str_new = (char *) malloc(rlen); strcpy(str_new, str); sOverFlowString += rlen; nOverFlowString++; if (sOverFlowString > hwOverFlow) hwOverFlow=sOverFlowString; return str_new; } /* If there is at least header size excess break it up */ else if (ptr->size - len >= (HEADER_SIZE+8)) { BufEntry *temp; /* WARNING! - DONT REMOVE THE CASTS BELOW! - Fusion */ temp = (BufEntry *) ((char *) ptr + HEADER_SIZE + len); temp->size = ptr->size - (len + HEADER_SIZE); temp->next = ptr->next; temp->usage = 0; ptr->size = len; ptr->next = temp; ssm_buf_free = temp; } else { if (ptr != ssm_buf_free) ssm_buf_free->usage--; /* buf_free was skipped */ /* spec: don't start from the start of the heap again! */ for ( ; ssm_buf_free; ssm_buf_free = ssm_buf_free->next) { ssm_loops++; ssm_recent_loops++; if (ssm_buf_free->usage == 0) break; } } str_new = (char *) &ptr->buf[0]; strcpy(str_new, str); ptr->caller=caller; nAllocString++; sAllocString += ptr->size + HEADER_SIZE; return str_new; }