static void end_log(struct log_stream *log, bool keep_buffer) { FILE *fp; if (!log->filename || !*log->filename || !log->fp) return; if ((fp = hashfind(strupper(log->filename), &htab_logfiles))) { int n; lock_file(fp); fputs("END OF LOG.\n", fp); fflush(fp); for (n = 0; n < NLOGS; n++) { if (logs[n].fp == fp) logs[n].fp = NULL; } fclose(fp); /* Implicit lock removal */ if (!keep_buffer) { free_bufferq(log->buffer); log->buffer = NULL; } hashdelete(strupper(log->filename), &htab_logfiles); } }
void luaH_free(Hash *frees) { while (frees) { Hash *next = (Hash *)frees->head.next; nblocks -= gcsize(frees->nhash); hashdelete(frees); frees = next; } }
void luaI_hashfree (Hash *frees) { while (frees) { Hash *next = frees->next; hashdelete(frees); frees = next; } }
static boolean tablemoveverb (hdltreenode hparam1, tyvaluerecord *v) { /* table.move (address, tableaddress): boolean; move the indicated table entry to the given table 9/30/91 dmb: use hashassign, not hashinsert, so existing item is overwritten 10/3/91 dmb: use new fllanghashassignprotect flag to override protection 5.0a15 dmb: on success, return address of moved value 5.1.4 dmb: generate errors if item doesn't exist */ hdlhashtable ht1, ht2; bigstring bs; tyvaluerecord val; boolean fl; hdlhashnode hnode; if (!getvarparam (hparam1, 1, &ht1, bs)) return (false); flnextparamislast = true; if (!gettablevalue (hparam1, 2, &ht2)) return (false); pushhashtable (ht1); fl = hashlookup (bs, &val, &hnode); if (fl) hashdelete (bs, false, false); /*don't toss the value*/ pophashtable (); if (!fl) { langparamerror (unknownidentifiererror, bs); return (false); } if (!hashtableassign (ht2, bs, val)) return (false); return (setaddressvalue (ht2, bs, v)); } /*tablemoveverb*/
boolean unlinksystemtablestructure (void) { /* try extracting system table from root before disposal. */ pushhashtable (systemtable); hashdelete (nameinternaltable, false, false); pophashtable (); return (true); } /*unlinksystemtablestructure*/
boolean claymovefile (const tybrowserspec *fs, const tybrowserspec *fsto) { tyvaluerecord val; hdlhashtable hdest; boolean fl; hdlhashnode hnode; if (!claygetdirid (fsto, &hdest)) { langerrormessage (BIGSTRING ("\x1b" "destination must be a table")); return (false); } opstartinternalchange (); pushhashtable ((*fs).parID); fl = hashlookup ((*fs).name, &val, &hnode); if (fl) { // if ((*fs).parID == agentstable) hashdelete ((*fs).name, false, false); /*don't toss the value*/ } pophashtable (); if (fl) { fl = hashtableassign (hdest, (*fs).name, val); /* if (fl && (hdest == agentstable) { hashtablelookupnode (hdest, (*fs).name, &hnode); scriptinstallagent (hnode); } */ } opendinternalchange (); return (true); } /*claymovefile*/
/** Remove a player from the player list htab. * \param player dbref of player to remove. * \param alias key to remove if given. */ void delete_player(dbref player, const char *alias) { if (!hft_initialized) { init_hft(); return; } if (alias) { /* This could be a compound alias, in which case we need to delete * them all, but we shouldn't delete the player's own name! */ char tbuf1[BUFFER_LEN], *s, *sp; mush_strncpy(tbuf1, alias, BUFFER_LEN); s = trim_space_sep(tbuf1, ALIAS_DELIMITER); while (s) { sp = split_token(&s, ALIAS_DELIMITER); while (sp && *sp && *sp == ' ') sp++; if (sp && *sp && strcasecmp(sp, Name(player))) hashdelete(strupper(sp), &htab_player_list); } } else hashdelete(strupper(Name(player)), &htab_player_list); }
static boolean tablemoveandrenameverb (hdltreenode hparam1, tyvaluerecord *v) { /* 5.0a15 dmb: on success, return address of moved value 5.1.4 dmb: generate errors if item doesn't exist */ hdlhashtable ht1, ht2; bigstring bs1, bs2; tyvaluerecord val; boolean fl; hdlhashnode hnode; if (!getvarparam (hparam1, 1, &ht1, bs1)) return (false); flnextparamislast = true; if (!getvarparam (hparam1, 2, &ht2, bs2)) return (false); pushhashtable (ht1); fl = hashlookup (bs1, &val, &hnode); if (fl) hashdelete (bs1, false, false); /*don't toss the value*/ pophashtable (); if (!fl) { langparamerror (unknownidentifiererror, bs1); return (false); } if (!hashtableassign (ht2, bs2, val)) return (false); return (setaddressvalue (ht2, bs2, v)); } /*tablemoveandrenameverb*/
void vattr_delete( char *name ) { VATTR *vp; int number; fixcase( name ); if( !ok_attr_name( name ) ) { return; } number = 0; vp = ( VATTR * ) hashfind( name, &mudstate.vattr_name_htab ); if( vp ) { number = vp->number; anum_set( number, NULL ); hashdelete( name, &mudstate.vattr_name_htab ); XFREE( vp, "vattr_delete" ); } return; }
/* ** Garbage collection to arrays ** Delete all unmarked arrays. */ Long lua_hashcollector (void) { Hash *curr_array = listhead, *prev = NULL; Long counter = 0; call_fallbacks(); while (curr_array != NULL) { Hash *next = curr_array->next; if (markarray(curr_array) != 1) { if (prev == NULL) listhead = next; else prev->next = next; hashdelete(curr_array); ++counter; } else { markarray(curr_array) = 0; prev = curr_array; } curr_array = next; } return counter; }
VATTR *vattr_rename( char *name, char *newname ) { VATTR *vp; fixcase( name ); if( !ok_attr_name( name ) ) { return ( NULL ); } /* * Be ruthless. */ if( strlen( newname ) >= VNAME_SIZE ) { newname[VNAME_SIZE - 1] = '\0'; } fixcase( newname ); if( !ok_attr_name( newname ) ) { return ( NULL ); } /* * We must explicitly delete and add the name to the hashtable, * * since we are changing the data. */ vp = ( VATTR * ) hashfind( name, &mudstate.vattr_name_htab ); if( vp ) { vp->name = store_string( newname ); hashdelete( name, &mudstate.vattr_name_htab ); hashadd( newname, ( int * ) vp, &mudstate.vattr_name_htab, 0 ); } return ( vp ); }
static boolean tablefunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) { /* bridges table.c with the language. the name of the verb is bs, its first parameter is hparam1, and we return a value in vreturned. we use a limited number of support routines from lang.c to get parameters and to return values. return false only if the error is serious enough to halt the running of the script that called us, otherwise error values are returned through the valuerecord, which is available to the script. if we return false, we try to provide a descriptive error message in the returned string bserror. 11/14/91 dmb: getcursorfunc returns address, not full path 10/3/92 dmb: commented out setcolwidthfunc. (this verb still isn't "offical") 4/2/93 dmb: added jettisonfunc 6/1/93 dmb: when vreturned is nil, return whether or not verb token must be run in the Frontier process 5.1.5b11 dmb: fixed gotofunc silent failure */ register tyvaluerecord *v = vreturned; register boolean fl = false; WindowPtr targetwindow; if (v == nil) { /*need Frontier process?*/ switch (token) { case sortbyfunc: case getcursorfunc: case getselectionfunc: case gotofunc: case gotonamefunc: case gofunc: case getdisplaysettings: case setdisplaysettings: return (true); default: return (false); } } setbooleanvalue (false, v); /*by default, table functions return false*/ switch (token) { /*these verbs don't require an open table window*/ /* case findfunc: if (!tablefindverb (hparam1, v)) goto error; return (true); */ case validatefunc: return (tablevalidateverb (hparam1, v)); case movefunc: return (tablemoveverb (hparam1, v)); case copyfunc: return (tablecopyverb (hparam1, v)); case renamefunc: return (tablerenameverb (hparam1, v)); case moveandrenamefunc: return (tablemoveandrenameverb (hparam1, v)); /* case lockfunc: case islockedfunc: */ case assignfunc: return (tableassignverb (hparam1, v)); #ifdef MACVERSION case packtablefunc: return (tablepacktableverb (hparam1, v)); #endif case emptytablefunc: return (tableemptytableverb (hparam1, v)); case jettisonfunc: { /*toss an object w/out forcing it into memory. for database recovery.*/ hdlhashtable htable; bigstring bs; if (!getvarparam (hparam1, 1, &htable, bs)) /*name of table*/ return (false); pushhashtable (htable); (*v).data.flvalue = hashdelete (bs, true, false); pophashtable (); return (true); } } /*switch*/ /*all other verbs require a table window in front*/ if (!langfindtargetwindow (idtableprocessor, &targetwindow)) { getstringlist (tableerrorlist, notableerror, bserror); return (false); } shellpushglobals (targetwindow); /*following verbs assume that an table is pushed*/ (*shellglobals.gettargetdataroutine) (idtableprocessor); /*set table globals*/ switch (token) { /* case setcolwidthfunc: { short colnum, colwidth; if (!getintvalue (hparam1, 1, &colnum)) break; flnextparamislast = true; if (!getintvalue (hparam1, 2, &colwidth)) break; (*v).data.flvalue = (*(**tableformatsdata).adjustcolwidthroutine) (colnum - 1, colwidth); tablesmashdisplay (); fl = true; break; } */ case sortbyfunc: { bigstring bssort, bstitle; short ixcol; flnextparamislast = true; if (!getstringvalue (hparam1, 1, bssort)) break; alllower (bssort); for (ixcol = namecolumn; ixcol <= kindcolumn; ++ixcol) { tablegettitlestring (ixcol, bstitle); alllower (bstitle); if (equalstrings (bssort, bstitle)) { hdlhashtable ht; bigstring bs; tablegetcursorinfo (&ht, bs, nil, nil); (*v).data.flvalue = tablesetsortorder (ht, ixcol); break; } } fl = true; break; } /* case centertablefunc: { boolean flcenter; flnextparamislast = true; if (!getbooleanvalue (hparam1, 1, &flcenter)) break; (*v).data.flvalue = tablesetcenter (flcenter); fl = true; break; } */ case getcursorfunc: { hdlhashtable htable; bigstring bs; tyvaluerecord val; hdlhashnode hhashnode; if (!langcheckparamcount (hparam1, 0)) /*too many parameters were passed*/ break; /* tablegetcursorpath (bspath); fl = setstringvalue (bspath, v); */ if (!tablegetcursorinfo (&htable, bs, &val, &hhashnode)) fl = setstringvalue (zerostring, v); else fl = setaddressvalue (htable, bs, v); break; } case getselectionfunc: fl = tablegetselectionverb (hparam1, v); break; case gotofunc: { short row; hdlheadrecord hsummit; flnextparamislast = true; if (!getintvalue (hparam1, 1, &row)) break; if (opnthsummit (row, &hsummit)) { opclearallmarks (); opmoveto (hsummit); (*v).data.flvalue = true; } fl = true; break; } case gotonamefunc: { hdlhashtable ht; bigstring bs; if (!tablegetcursorinfo (&ht, bs, nil, nil)) ht = nil; flnextparamislast = true; if (!getstringvalue (hparam1, 1, bs)) break; (*v).data.flvalue = tablemovetoname (ht, bs); fl = true; break; } case gofunc: { tydirection dir; short count; if (!getdirectionvalue (hparam1, 1, &dir)) break; flnextparamislast = true; if (!getintvalue (hparam1, 2, &count)) break; opsettextmode (false); if (dir == down) dir = flatdown; if (dir == up) dir = flatup; (*v).data.flvalue = opmotionkey (dir, count, false); fl = true; break; } case getdisplaysettings: fl = tablegetdisplaysettingsverb (hparam1, v); break; case setdisplaysettings: fl = tablesetdisplaysettingsverb (hparam1, v); break; case sortorderfunc: { hdlhashtable ht; bigstring bs; short ixcol; tablegetcursorinfo (&ht, bs, nil, nil); tablegetsortorder (ht, &ixcol); tablegettitlestring (ixcol, bs); fl = setstringvalue (bs, v); break; } } /*switch*/ shellupdatescrollbars (shellwindowinfo); shellpopglobals (); return (fl); } /*tablefunctionvalue*/
void do_dbclean( dbref player, dbref cause, int key ) { VATTR *vp, *vpx; dbref i, end; int ca, n_oldtotal, n_oldtop, n_deleted, n_renumbered, n_objt, n_atrt, got; char *as, *str; int *used_table; ATTR **new_table; UFUN *ufp; CMDENT *cmdp; ADDENT *addp; raw_broadcast( 0, "GAME: Cleaning database. Game may freeze for a few minutes." ); used_table = ( int * ) XCALLOC( mudstate.attr_next, sizeof( int ), "dbclean.used_table" ); n_oldtotal = mudstate.attr_next; n_oldtop = anum_alc_top; n_deleted = n_renumbered = n_objt = n_atrt = 0; /* * Non-user-defined attributes are always considered used. */ for( i = 0; i < A_USER_START; i++ ) { used_table[i] = i; } /* * Walk the database. Mark all the attribute numbers in use. */ atr_push(); DO_WHOLE_DB( i ) { for( ca = atr_head( i, &as ); ca; ca = atr_next( &as ) ) { used_table[ca] = ca; } } atr_pop(); /* * Walk the vattr table. If a number isn't in use, zorch it. */ vp = vattr_first(); while( vp ) { vpx = vp; vp = vattr_next( vp ); if( used_table[vpx->number] == 0 ) { anum_set( vpx->number, NULL ); hashdelete( vpx->name, &mudstate.vattr_name_htab ); XFREE( vpx, "dbclean.vpx" ); n_deleted++; } } /* * The user-defined function, added command, and hook structures embed * * attribute numbers. Clean out the ones we've deleted, resetting them * * to the *Invalid (A_TEMP) attr. */ for( ufp = ( UFUN * ) hash_firstentry( &mudstate.ufunc_htab ); ufp != NULL; ufp = ( UFUN * ) hash_nextentry( &mudstate.ufunc_htab ) ) { if( used_table[ufp->atr] == 0 ) { ufp->atr = A_TEMP; } } for( cmdp = ( CMDENT * ) hash_firstentry( &mudstate.command_htab ); cmdp != NULL; cmdp = ( CMDENT * ) hash_nextentry( &mudstate.command_htab ) ) { if( cmdp->pre_hook ) { if( used_table[cmdp->pre_hook->atr] == 0 ) { cmdp->pre_hook->atr = A_TEMP; } } if( cmdp->post_hook ) { if( used_table[cmdp->post_hook->atr] == 0 ) { cmdp->post_hook->atr = A_TEMP; } } if( cmdp->userperms ) { if( used_table[cmdp->userperms->atr] == 0 ) { cmdp->userperms->atr = A_TEMP; } } if( cmdp->callseq & CS_ADDED ) { for( addp = ( ADDENT * ) cmdp->info.added; addp != NULL; addp = addp->next ) { if( used_table[addp->atr] == 0 ) { addp->atr = A_TEMP; } } } } /* * Walk the table we've created of used statuses. When we find free * * slots, walk backwards to the first used slot at the end of the * * table. Write the number of the free slot into that used slot. */ for( i = A_USER_START, end = mudstate.attr_next - 1; ( i < mudstate.attr_next ) && ( i < end ); i++ ) { if( used_table[i] == 0 ) { while( ( end > i ) && ( used_table[end] == 0 ) ) { end--; } if( end > i ) { used_table[end] = used_table[i] = i; end--; } } } /* * Renumber the necessary attributes in the vattr tables. */ for( i = A_USER_START; i < mudstate.attr_next; i++ ) { if( used_table[i] != i ) { vp = ( VATTR * ) anum_get( i ); if( vp ) { vp->number = used_table[i]; vp->flags |= AF_DIRTY; anum_set( used_table[i], ( ATTR * ) vp ); anum_set( i, NULL ); n_renumbered++; } } } /* * Now we walk the database. For every object, if we have an attribute * * we're renumbering (the slot number is not equal to the array value * * at that slot), we delete the old attribute and add the new one. */ atr_push(); DO_WHOLE_DB( i ) { got = 0; for( ca = atr_head( i, &as ); ca; ca = atr_next( &as ) ) { if( used_table[ca] != ca ) { str = atr_get_raw( i, ca ); atr_add_raw( i, used_table[ca], str ); atr_clr( i, ca ); n_atrt++; got = 1; } } if( got ) { n_objt++; } } atr_pop(); /* * The new end of the attribute table is the first thing we've * * renumbered. */ for( end = A_USER_START; ( ( end == used_table[end] ) && ( end < mudstate.attr_next ) ); end++ ); mudstate.attr_next = end; /* * We might be able to shrink the size of the attribute table. * * If the current size of the table is less than the initial * * size, shrink it back down to the initial size. * * Otherwise, shrink it down so it's the current top plus the * * initial size, as if we'd just called anum_extend() for it. */ if( anum_alc_top > mudconf.init_size + A_USER_START ) { if( mudstate.attr_next < mudconf.init_size + A_USER_START ) { end = mudconf.init_size + A_USER_START; } else { end = mudstate.attr_next + mudconf.init_size; } if( end < anum_alc_top ) { new_table = ( ATTR ** ) XCALLOC( end + 1, sizeof( ATTR * ), "dbclean.new_table" ); for( i = 0; i < mudstate.attr_next; i++ ) { new_table[i] = anum_table[i]; } XFREE( anum_table, "dbclean.anum_table" ); anum_table = new_table; anum_alc_top = end; } } /* * Go through the function and added command tables again, and * * take care of the attributes that got renumbered. */ for( ufp = ( UFUN * ) hash_firstentry( &mudstate.ufunc_htab ); ufp != NULL; ufp = ( UFUN * ) hash_nextentry( &mudstate.ufunc_htab ) ) { if( used_table[ufp->atr] != ufp->atr ) { ufp->atr = used_table[ufp->atr]; } } for( cmdp = ( CMDENT * ) hash_firstentry( &mudstate.command_htab ); cmdp != NULL; cmdp = ( CMDENT * ) hash_nextentry( &mudstate.command_htab ) ) { if( cmdp->pre_hook ) { if( used_table[cmdp->pre_hook->atr] != cmdp->pre_hook->atr ) cmdp->pre_hook->atr = used_table[cmdp->pre_hook->atr]; } if( cmdp->post_hook ) { if( used_table[cmdp->post_hook->atr] != cmdp->post_hook->atr ) cmdp->post_hook->atr = used_table[cmdp->post_hook->atr]; } if( cmdp->userperms ) { if( used_table[cmdp->userperms->atr] != cmdp->userperms->atr ) cmdp->userperms->atr = used_table[cmdp->userperms->atr]; } if( cmdp->callseq & CS_ADDED ) { for( addp = ( ADDENT * ) cmdp->info.added; addp != NULL; addp = addp->next ) { if( used_table[addp->atr] != addp->atr ) { addp->atr = used_table[addp->atr]; } } } } /* * Clean up. */ XFREE( used_table, "dbclean.used_table" ); if( anum_alc_top != n_oldtop ) { notify_check( player, player, MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN, "Cleaned %d user attribute slots (reduced to %d): %d deleted, %d renumbered (%d objects and %d individual attrs touched). Table size reduced from %d to %d.", n_oldtotal - A_USER_START, mudstate.attr_next - A_USER_START, n_deleted, n_renumbered, n_objt, n_atrt, n_oldtop, anum_alc_top ); } else { notify_check( player, player, MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN, "Cleaned %d attributes (now %d): %d deleted, %d renumbered (%d objects and %d individual attrs touched).", n_oldtotal, mudstate.attr_next, n_deleted, n_renumbered, n_objt, n_atrt ); } raw_broadcast( 0, "GAME: Database cleaning complete." ); }