mux/src/db_rw.cpp

Go to the documentation of this file.
00001 // db_rw.cpp
00002 //
00003 // $Id: db_rw.cpp,v 1.24 2007/02/03 04:32:52 sdennis Exp $
00004 //
00005 
00006 #include "copyright.h"
00007 #include "autoconf.h"
00008 #include "config.h"
00009 #include "externs.h"
00010 
00011 #include "attrs.h"
00012 #include "vattr.h"
00013 
00014 static int g_version;
00015 static int g_format;
00016 static int g_flags;
00017 
00018 /* ---------------------------------------------------------------------------
00019  * getboolexp1: Get boolean subexpression from file.
00020  */
00021 
00022 static BOOLEXP *getboolexp1(FILE *f)
00023 {
00024     BOOLEXP *b;
00025     char *buff, *s;
00026     int d, anum;
00027 
00028     int c = getc(f);
00029     switch (c)
00030     {
00031     case '\n':
00032         ungetc(c, f);
00033         return TRUE_BOOLEXP;
00034 
00035     case EOF:
00036 
00037         // Unexpected EOF in boolexp.
00038         //
00039         mux_assert(0);
00040         break;
00041 
00042     case '(':
00043         b = alloc_bool("getboolexp1.openparen");
00044         switch (c = getc(f))
00045         {
00046         case NOT_TOKEN:
00047             b->type = BOOLEXP_NOT;
00048             b->sub1 = getboolexp1(f);
00049             if ((d = getc(f)) == '\n')
00050             {
00051                 d = getc(f);
00052             }
00053             if (d != ')')
00054             {
00055                 goto error;
00056             }
00057             return b;
00058 
00059         case INDIR_TOKEN:
00060             b->type = BOOLEXP_INDIR;
00061             b->sub1 = getboolexp1(f);
00062             if ((d = getc(f)) == '\n')
00063             {
00064                 d = getc(f);
00065             }
00066             if (d != ')')
00067             {
00068                 goto error;
00069             }
00070             return b;
00071 
00072         case IS_TOKEN:
00073             b->type = BOOLEXP_IS;
00074             b->sub1 = getboolexp1(f);
00075             if ((d = getc(f)) == '\n')
00076             {
00077                 d = getc(f);
00078             }
00079             if (d != ')')
00080             {
00081                 goto error;
00082             }
00083             return b;
00084 
00085         case CARRY_TOKEN:
00086             b->type = BOOLEXP_CARRY;
00087             b->sub1 = getboolexp1(f);
00088             if ((d = getc(f)) == '\n')
00089             {
00090                 d = getc(f);
00091             }
00092             if (d != ')')
00093             {
00094                 goto error;
00095             }
00096             return b;
00097 
00098         case OWNER_TOKEN:
00099             b->type = BOOLEXP_OWNER;
00100             b->sub1 = getboolexp1(f);
00101             if ((d = getc(f)) == '\n')
00102             {
00103                 d = getc(f);
00104             }
00105             if (d != ')')
00106             {
00107                 goto error;
00108             }
00109             return b;
00110 
00111         default:
00112             ungetc(c, f);
00113             b->sub1 = getboolexp1(f);
00114             if ((c = getc(f)) == '\n')
00115             {
00116                 c = getc(f);
00117             }
00118             switch (c)
00119             {
00120             case AND_TOKEN:
00121                 b->type = BOOLEXP_AND;
00122                 break;
00123 
00124             case OR_TOKEN:
00125                 b->type = BOOLEXP_OR;
00126                 break;
00127 
00128             default:
00129                 goto error;
00130             }
00131             b->sub2 = getboolexp1(f);
00132             if ((d = getc(f)) == '\n')
00133             {
00134                 d = getc(f);
00135             }
00136             if (d != ')')
00137             {
00138                 goto error;
00139             }
00140             return b;
00141         }
00142 
00143     case '-':
00144 
00145         // obsolete NOTHING key, eat it.
00146         //
00147         while ((c = getc(f)) != '\n')
00148         {
00149             mux_assert(c != EOF);
00150         }
00151         ungetc(c, f);
00152         return TRUE_BOOLEXP;
00153 
00154     case '"':
00155         ungetc(c, f);
00156         buff = alloc_lbuf("getboolexp_quoted");
00157         strcpy(buff, getstring_noalloc(f, 1));
00158         c = fgetc(f);
00159         if (c == EOF)
00160         {
00161             free_lbuf(buff);
00162             return TRUE_BOOLEXP;
00163         }
00164 
00165         b = alloc_bool("getboolexp1_quoted");
00166         anum = mkattr(GOD, buff);
00167         if (anum <= 0)
00168         {
00169             free_bool(b);
00170             free_lbuf(buff);
00171             goto error;
00172         }
00173         free_lbuf(buff);
00174         b->thing = anum;
00175 
00176         // If last character is : then this is an attribute lock. A
00177         // last character of / means an eval lock.
00178         //
00179         if (  c == ':'
00180            || c == '/')
00181         {
00182             if (c == '/')
00183             {
00184                 b->type = BOOLEXP_EVAL;
00185             }
00186             else
00187             {
00188                 b->type = BOOLEXP_ATR;
00189             }
00190             buff = alloc_lbuf("getboolexp1.attr_lock");
00191             strcpy(buff, getstring_noalloc(f, 1));
00192             b->sub1 = (BOOLEXP *)StringClone(buff);
00193             free_lbuf(buff);
00194         }
00195         return b;
00196 
00197     default: // dbref or attribute.
00198 
00199         ungetc(c, f);
00200         b = alloc_bool("getboolexp1.default");
00201         b->type = BOOLEXP_CONST;
00202         b->thing = 0;
00203 
00204         // This is either an attribute, eval, or constant lock. Constant locks
00205         // are of the form <num>, while attribute and eval locks are of the
00206         // form <anam-or-anum>:<string> or <aname-or-anum>/<string>
00207         // respectively. The characters <nl>, |, and & terminate the string.
00208         //
00209         if (mux_isdigit(c))
00210         {
00211             while (mux_isdigit(c = getc(f)))
00212             {
00213                 b->thing = b->thing * 10 + c - '0';
00214             }
00215         }
00216         else if (mux_AttrNameInitialSet(c))
00217         {
00218             buff = alloc_lbuf("getboolexp1.atr_name");
00219 
00220             for (  s = buff;
00221 
00222                    (c = getc(f)) != EOF
00223                 && c != '\n'
00224                 && c != ':'
00225                 && c != '/'
00226                 && s < buff + LBUF_SIZE;
00227 
00228                    *s++ = (char)c)
00229             {
00230                 ; // Nothing.
00231             }
00232 
00233             if (c == EOF)
00234             {
00235                 free_lbuf(buff);
00236                 free_bool(b);
00237                 goto error;
00238             }
00239             *s = '\0';
00240 
00241             // Look the name up as an attribute. If not found, create a new
00242             // attribute.
00243             //
00244             anum = mkattr(GOD, buff);
00245             if (anum <= 0)
00246             {
00247                 free_bool(b);
00248                 free_lbuf(buff);
00249                 goto error;
00250             }
00251             free_lbuf(buff);
00252             b->thing = anum;
00253         }
00254         else
00255         {
00256             free_bool(b);
00257             goto error;
00258         }
00259 
00260         // If last character is : then this is an attribute lock. A last
00261         // character of / means an eval lock.
00262         //
00263         if (  c == ':'
00264            || c == '/')
00265         {
00266             if (c == '/')
00267             {
00268                 b->type = BOOLEXP_EVAL;
00269             }
00270             else
00271             {
00272                 b->type = BOOLEXP_ATR;
00273             }
00274             buff = alloc_lbuf("getboolexp1.attr_lock");
00275             for (  s = buff;
00276 
00277                    (c = getc(f)) != EOF
00278                 && c != '\n'
00279                 && c != ')'
00280                 && c != OR_TOKEN
00281                 && c != AND_TOKEN
00282                 && s < buff + LBUF_SIZE;
00283 
00284                    *s++ = (char)c)
00285             {
00286                 ; // Nothing
00287             }
00288             if (c == EOF)
00289             {
00290                 goto error;
00291             }
00292             *s++ = 0;
00293             b->sub1 = (BOOLEXP *)StringClone(buff);
00294             free_lbuf(buff);
00295         }
00296         ungetc(c, f);
00297         return b;
00298     }
00299 
00300 error:
00301 
00302     // Bomb Out.
00303     //
00304     mux_assert(0);
00305     return TRUE_BOOLEXP;
00306 }
00307 
00308 /* ---------------------------------------------------------------------------
00309  * getboolexp: Read a boolean expression from the flat file.
00310  */
00311 
00312 static BOOLEXP *getboolexp(FILE *f)
00313 {
00314     BOOLEXP *b = getboolexp1(f);
00315     int c = getc(f);
00316     mux_assert(c == '\n');
00317 
00318     if (g_format == F_MUX)
00319     {
00320         if ((c = getc(f)) != '\n')
00321         {
00322             ungetc(c, f);
00323         }
00324     }
00325     return b;
00326 }
00327 
00328 /* ---------------------------------------------------------------------------
00329  * get_list: Read attribute list from flat file.
00330  */
00331 
00332 static bool get_list(FILE *f, dbref i)
00333 {
00334     char *buff = alloc_lbuf("get_list");
00335     for (;;)
00336     {
00337         dbref atr;
00338         int c;
00339         switch (c = getc(f))
00340         {
00341         case '>':   // read # then string
00342             atr = getref(f);
00343             if (atr > 0)
00344             {
00345                 // Store the attr
00346                 //
00347                 atr_add_raw(i, atr, getstring_noalloc(f, true));
00348             }
00349             else
00350             {
00351                 // Silently discard
00352                 //
00353                 getstring_noalloc(f, true);
00354             }
00355             break;
00356 
00357         case '\n':  // ignore newlines. They're due to v(r).
00358 
00359             break;
00360 
00361         case '<':   // end of list
00362 
00363             free_lbuf(buff);
00364             c = getc(f);
00365             if (c != '\n')
00366             {
00367                 ungetc(c, f);
00368                 Log.tinyprintf("No line feed on object %d" ENDLINE, i);
00369                 return true;
00370             }
00371             return true;
00372 
00373         default:
00374             Log.tinyprintf("Bad character '%c' when getting attributes on object %d" ENDLINE, c, i);
00375 
00376             // We've found a bad spot.  I hope things aren't too bad.
00377             //
00378             getstring_noalloc(f, true);
00379         }
00380     }
00381 }
00382 
00383 /* ---------------------------------------------------------------------------
00384  * putbool_subexp: Write a boolean sub-expression to the flat file.
00385  */
00386 static void putbool_subexp(FILE *f, BOOLEXP *b)
00387 {
00388     ATTR *va;
00389 
00390     switch (b->type)
00391     {
00392     case BOOLEXP_IS:
00393 
00394         putc('(', f);
00395         putc(IS_TOKEN, f);
00396         putbool_subexp(f, b->sub1);
00397         putc(')', f);
00398         break;
00399 
00400     case BOOLEXP_CARRY:
00401 
00402         putc('(', f);
00403         putc(CARRY_TOKEN, f);
00404         putbool_subexp(f, b->sub1);
00405         putc(')', f);
00406         break;
00407 
00408     case BOOLEXP_INDIR:
00409 
00410         putc('(', f);
00411         putc(INDIR_TOKEN, f);
00412         putbool_subexp(f, b->sub1);
00413         putc(')', f);
00414         break;
00415 
00416     case BOOLEXP_OWNER:
00417 
00418         putc('(', f);
00419         putc(OWNER_TOKEN, f);
00420         putbool_subexp(f, b->sub1);
00421         putc(')', f);
00422         break;
00423 
00424     case BOOLEXP_AND:
00425 
00426         putc('(', f);
00427         putbool_subexp(f, b->sub1);
00428         putc(AND_TOKEN, f);
00429         putbool_subexp(f, b->sub2);
00430         putc(')', f);
00431         break;
00432 
00433     case BOOLEXP_OR:
00434 
00435         putc('(', f);
00436         putbool_subexp(f, b->sub1);
00437         putc(OR_TOKEN, f);
00438         putbool_subexp(f, b->sub2);
00439         putc(')', f);
00440         break;
00441 
00442     case BOOLEXP_NOT:
00443 
00444         putc('(', f);
00445         putc(NOT_TOKEN, f);
00446         putbool_subexp(f, b->sub1);
00447         putc(')', f);
00448         break;
00449 
00450     case BOOLEXP_CONST:
00451 
00452         putref(f, b->thing);
00453         break;
00454 
00455     case BOOLEXP_ATR:
00456 
00457         va = atr_num(b->thing);
00458         if (va)
00459         {
00460             fprintf(f, "%s:%s", va->name, (char *)b->sub1);
00461         }
00462         else
00463         {
00464             fprintf(f, "%d:%s\n", b->thing, (char *)b->sub1);
00465         }
00466         break;
00467 
00468     case BOOLEXP_EVAL:
00469 
00470         va = atr_num(b->thing);
00471         if (va)
00472         {
00473             fprintf(f, "%s/%s\n", va->name, (char *)b->sub1);
00474         }
00475         else
00476         {
00477             fprintf(f, "%d/%s\n", b->thing, (char *)b->sub1);
00478         }
00479         break;
00480 
00481     default:
00482 
00483         Log.tinyprintf("Unknown boolean type in putbool_subexp: %d" ENDLINE, b->type);
00484         break;
00485     }
00486 }
00487 
00488 /* ---------------------------------------------------------------------------
00489  * putboolexp: Write boolean expression to the flat file.
00490  */
00491 
00492 static void putboolexp(FILE *f, BOOLEXP *b)
00493 {
00494     if (b != TRUE_BOOLEXP)
00495     {
00496         putbool_subexp(f, b);
00497     }
00498     putc('\n', f);
00499 }
00500 
00501 dbref db_read(FILE *f, int *db_format, int *db_version, int *db_flags)
00502 {
00503     dbref i, anum;
00504     int ch;
00505     const char *tstr;
00506     int aflags;
00507     BOOLEXP *tempbool;
00508     char *buff;
00509     int nVisualWidth;
00510 
00511     g_format = F_UNKNOWN;
00512     g_version = 0;
00513     g_flags = 0;
00514 
00515     bool header_gotten = false;
00516     bool size_gotten = false;
00517     bool nextattr_gotten = false;
00518 
00519     bool read_attribs = true;
00520     bool read_name = true;
00521     bool read_key = true;
00522     bool read_money = true;
00523 
00524     int nName;
00525     bool bValid;
00526     char *pName;
00527 
00528     int iDotCounter = 0;
00529     if (mudstate.bStandAlone)
00530     {
00531         Log.WriteString("Reading ");
00532         Log.Flush();
00533     }
00534     db_free();
00535     for (i = 0;; i++)
00536     {
00537         if (mudstate.bStandAlone)
00538         {
00539             if (!iDotCounter)
00540             {
00541                 iDotCounter = 100;
00542                 fputc('.', stderr);
00543                 fflush(stderr);
00544             }
00545             iDotCounter--;
00546         }
00547 
00548         ch = getc(f);
00549         switch (ch)
00550         {
00551         case '-':   // Misc tag
00552             ch = getc(f);
00553             if (ch == 'R')
00554             {
00555                 // Record number of players
00556                 //
00557                 mudstate.record_players = getref(f);
00558                 if (mudconf.reset_players)
00559                 {
00560                     mudstate.record_players = 0;
00561                 }
00562             }
00563             break;
00564 
00565         case '+':
00566 
00567             // MUX header
00568             //
00569             ch = getc(f);
00570             if (ch == 'A')
00571             {
00572                 // USER-NAMED ATTRIBUTE
00573                 //
00574                 anum = getref(f);
00575                 tstr = getstring_noalloc(f, true);
00576                 if (mux_isdigit(*tstr))
00577                 {
00578                     aflags = 0;
00579                     while (mux_isdigit(*tstr))
00580                     {
00581                         aflags = (aflags * 10) + (*tstr++ - '0');
00582                     }
00583                     tstr++; // skip ':'
00584                 }
00585                 else
00586                 {
00587                     aflags = mudconf.vattr_flags;
00588                 }
00589                 pName = MakeCanonicalAttributeName(tstr, &nName, &bValid);
00590                 if (bValid)
00591                 {
00592                     vattr_define_LEN(pName, nName, anum, aflags);
00593                 }
00594             }
00595             else if (ch == 'X')
00596             {
00597                 // MUX VERSION
00598                 //
00599                 if (header_gotten)
00600                 {
00601                     Log.tinyprintf(ENDLINE "Duplicate MUX version header entry at object %d, ignored." ENDLINE, i);
00602                     tstr = getstring_noalloc(f, 0);
00603                 }
00604                 else
00605                 {
00606                     header_gotten = true;
00607                     g_format = F_MUX;
00608                     g_version = getref(f);
00609                     mux_assert((g_version & MANDFLAGS) == MANDFLAGS);
00610 
00611                     // Otherwise extract feature flags
00612                     //
00613                     if (g_version & V_DATABASE)
00614                     {
00615                         read_attribs = false;
00616                         read_name = !(g_version & V_ATRNAME);
00617                     }
00618                     read_key = !(g_version & V_ATRKEY);
00619                     read_money = !(g_version & V_ATRMONEY);
00620                     g_flags = g_version & ~V_MASK;
00621 
00622                     g_version &= V_MASK;
00623                     if (  g_version < MIN_SUPPORTED_VERSION
00624                        || MAX_SUPPORTED_VERSION < g_version)
00625                     {
00626                         Log.tinyprintf(ENDLINE "Unsupported flatfile version: %d." ENDLINE, g_version);
00627                         return -1;
00628                     }
00629                 }
00630             }
00631             else if (ch == 'S')
00632             {
00633                 // SIZE
00634                 //
00635                 if (size_gotten)
00636                 {
00637                     Log.tinyprintf(ENDLINE "Duplicate size entry at object %d, ignored." ENDLINE, i);
00638                     tstr = getstring_noalloc(f, 0);
00639                 }
00640                 else
00641                 {
00642                     mudstate.min_size = getref(f);
00643                     size_gotten = true;
00644                 }
00645             }
00646             else if (ch == 'N')
00647             {
00648                 // NEXT ATTR TO ALLOC WHEN NO FREELIST
00649                 //
00650                 if (nextattr_gotten)
00651                 {
00652                     Log.tinyprintf(ENDLINE "Duplicate next free vattr entry at object %d, ignored." ENDLINE, i);
00653                     tstr = getstring_noalloc(f, 0);
00654                 }
00655                 else
00656                 {
00657                     mudstate.attr_next = getref(f);
00658                     nextattr_gotten = true;
00659                 }
00660             }
00661             else
00662             {
00663                 Log.tinyprintf(ENDLINE "Unexpected character '%c' in MUX header near object #%d, ignored." ENDLINE, ch, i);
00664                 tstr = getstring_noalloc(f, 0);
00665             }
00666             break;
00667 
00668         case '!':   // MUX entry
00669             i = getref(f);
00670             db_grow(i + 1);
00671 
00672             if (read_name)
00673             {
00674                 tstr = getstring_noalloc(f, true);
00675                 buff = alloc_lbuf("dbread.s_Name");
00676                 (void)ANSI_TruncateToField(tstr, MBUF_SIZE, buff, MBUF_SIZE,
00677                     &nVisualWidth, ANSI_ENDGOAL_NORMAL);
00678                 s_Name(i, buff);
00679                 free_lbuf(buff);
00680 
00681                 s_Location(i, getref(f));
00682             }
00683             else
00684             {
00685                 s_Location(i, getref(f));
00686             }
00687 
00688             // ZONE
00689             //
00690             int zone;
00691             zone = getref(f);
00692             if (zone < NOTHING)
00693             {
00694                 zone = NOTHING;
00695             }
00696             s_Zone(i, zone);
00697 
00698             // CONTENTS and EXITS
00699             //
00700             s_Contents(i, getref(f));
00701             s_Exits(i, getref(f));
00702 
00703             // LINK
00704             //
00705             s_Link(i, getref(f));
00706 
00707             // NEXT
00708             //
00709             s_Next(i, getref(f));
00710 
00711             // LOCK
00712             //
00713             if (read_key)
00714             {
00715                 tempbool = getboolexp(f);
00716                 atr_add_raw(i, A_LOCK,
00717                 unparse_boolexp_quiet(1, tempbool));
00718                 free_boolexp(tempbool);
00719             }
00720 
00721             // OWNER
00722             //
00723             s_Owner(i, getref(f));
00724 
00725             // PARENT
00726             //
00727             s_Parent(i, getref(f));
00728 
00729             // PENNIES
00730             //
00731             if (read_money)
00732             {
00733                 s_PenniesDirect(i, getref(f));
00734             }
00735 
00736             // FLAGS
00737             //
00738             s_Flags(i, FLAG_WORD1, getref(f));
00739             s_Flags(i, FLAG_WORD2, getref(f));
00740             s_Flags(i, FLAG_WORD3, getref(f));
00741 
00742             // POWERS
00743             //
00744             s_Powers(i, getref(f));
00745             s_Powers2(i, getref(f));
00746 
00747             // ATTRIBUTES
00748             //
00749             if (read_attribs)
00750             {
00751                 if (!get_list(f, i))
00752                 {
00753                     Log.tinyprintf(ENDLINE "Error reading attrs for object #%d" ENDLINE, i);
00754                     return -1;
00755                 }
00756             }
00757 
00758             // check to see if it's a player
00759             //
00760             if (isPlayer(i))
00761             {
00762                 c_Connected(i);
00763             }
00764             break;
00765 
00766         case '*':   // EOF marker
00767             tstr = getstring_noalloc(f, 0);
00768             if (strncmp(tstr, "**END OF DUMP***", 16))
00769             {
00770                 Log.tinyprintf(ENDLINE "Bad EOF marker at object #%d" ENDLINE, i);
00771                 return -1;
00772             }
00773             else
00774             {
00775                 *db_version = g_version;
00776                 *db_format = g_format;
00777                 *db_flags = g_flags;
00778                 if (mudstate.bStandAlone)
00779                 {
00780                     Log.WriteString(ENDLINE);
00781                     Log.Flush();
00782                 }
00783                 else
00784                 {
00785                     load_player_names();
00786                 }
00787                 return mudstate.db_top;
00788             }
00789 
00790         case EOF:
00791             Log.tinyprintf(ENDLINE "Unexpected end of file near object #%d" ENDLINE, i);
00792             return -1;
00793 
00794         default:
00795             if (mux_isprint(ch))
00796             {
00797                 Log.tinyprintf(ENDLINE "Illegal character '%c' near object #%d" ENDLINE, ch, i);
00798             }
00799             else
00800             {
00801                 Log.tinyprintf(ENDLINE "Illegal character 0x%02x near object #%d" ENDLINE, ch, i);
00802             }
00803             return -1;
00804         }
00805     }
00806 }
00807 
00808 static bool db_write_object(FILE *f, dbref i, int db_format, int flags)
00809 {
00810     UNUSED_PARAMETER(db_format);
00811 
00812     ATTR *a;
00813     char *got, *as;
00814     dbref aowner;
00815     int ca, aflags, j;
00816     BOOLEXP *tempbool;
00817 
00818     if (!(flags & V_ATRNAME))
00819     {
00820         putstring(f, Name(i));
00821     }
00822     putref(f, Location(i));
00823     putref(f, Zone(i));
00824     putref(f, Contents(i));
00825     putref(f, Exits(i));
00826     putref(f, Link(i));
00827     putref(f, Next(i));
00828     if (!(flags & V_ATRKEY))
00829     {
00830         got = atr_get(i, A_LOCK, &aowner, &aflags);
00831         tempbool = parse_boolexp(GOD, got, true);
00832         free_lbuf(got);
00833         putboolexp(f, tempbool);
00834         if (tempbool)
00835         {
00836             free_boolexp(tempbool);
00837         }
00838     }
00839     putref(f, Owner(i));
00840     putref(f, Parent(i));
00841     if (!(flags & V_ATRMONEY))
00842     {
00843         putref(f, Pennies(i));
00844     }
00845     putref(f, Flags(i));
00846     putref(f, Flags2(i));
00847     putref(f, Flags3(i));
00848     putref(f, Powers(i));
00849     putref(f, Powers2(i));
00850 
00851     // Write the attribute list.
00852     //
00853     if (!(flags & V_DATABASE))
00854     {
00855         char buf[SBUF_SIZE];
00856         buf[0] = '>';
00857         for (ca = atr_head(i, &as); ca; ca = atr_next(&as))
00858         {
00859             if (mudstate.bStandAlone)
00860             {
00861                 j = ca;
00862             }
00863             else
00864             {
00865                 a = atr_num(ca);
00866                 if (!a)
00867                 {
00868                     continue;
00869                 }
00870                 j = a->number;
00871             }
00872 
00873             if (j < A_USER_START)
00874             {
00875                 switch (j)
00876                 {
00877                 case A_NAME:
00878                     if (!(flags & V_ATRNAME))
00879                     {
00880                         continue;
00881                     }
00882                     break;
00883 
00884                 case A_LOCK:
00885                     if (!(flags & V_ATRKEY))
00886                     {
00887                         continue;
00888                     }
00889                     break;
00890 
00891                 case A_LIST:
00892                 case A_MONEY:
00893                     continue;
00894                 }
00895             }
00896 
00897             // Format is: ">%d\n", j
00898             //
00899             const char *p = atr_get_raw(i, j);
00900             int n = mux_ltoa(j, buf+1) + 1;
00901             buf[n++] = '\n';
00902             fwrite(buf, sizeof(char), n, f);
00903             putstring(f, p);
00904         }
00905         fwrite("<\n", sizeof(char), 2, f);
00906     }
00907     return false;
00908 }
00909 
00910 dbref db_write(FILE *f, int format, int version)
00911 {
00912     dbref i;
00913     int flags;
00914     ATTR *vp;
00915 
00916     switch (format)
00917     {
00918     case F_MUX:
00919         flags = version;
00920         break;
00921 
00922     default:
00923         Log.WriteString("Can only write MUX format." ENDLINE);
00924         return -1;
00925     }
00926     if (mudstate.bStandAlone)
00927     {
00928         Log.WriteString("Writing ");
00929         Log.Flush();
00930     }
00931     i = mudstate.attr_next;
00932     fprintf(f, "+X%d\n+S%d\n+N%d\n", flags, mudstate.db_top, i);
00933     fprintf(f, "-R%d\n", mudstate.record_players);
00934 
00935     // Dump user-named attribute info.
00936     //
00937     char Buffer[LBUF_SIZE];
00938     Buffer[0] = '+';
00939     Buffer[1] = 'A';
00940     int iAttr;
00941     for (iAttr = A_USER_START; iAttr <= anum_alc_top; iAttr++)
00942     {
00943         vp = (ATTR *) anum_get(iAttr);
00944         if (  vp != NULL
00945            && !(vp->flags & AF_DELETED))
00946         {
00947             // Format is: "+A%d\n\"%d:%s\"\n", vp->number, vp->flags, vp->name
00948             //
00949             char *pBuffer = Buffer+2;
00950             pBuffer += mux_ltoa(vp->number, pBuffer);
00951             *pBuffer++ = '\n';
00952             *pBuffer++ = '"';
00953             pBuffer += mux_ltoa(vp->flags, pBuffer);
00954             *pBuffer++ = ':';
00955             int nNameLength = strlen(vp->name);
00956             memcpy(pBuffer, vp->name, nNameLength);
00957             pBuffer += nNameLength;
00958             *pBuffer++ = '"';
00959             *pBuffer++ = '\n';
00960             fwrite(Buffer, sizeof(char), pBuffer-Buffer, f);
00961         }
00962     }
00963 
00964     int iDotCounter = 0;
00965     char buf[SBUF_SIZE];
00966     buf[0] = '!';
00967     DO_WHOLE_DB(i)
00968     {
00969         if (mudstate.bStandAlone)
00970         {
00971             if (!iDotCounter)
00972             {
00973                 iDotCounter = 100;
00974                 fputc('.', stderr);
00975                 fflush(stderr);
00976             }
00977             iDotCounter--;
00978         }
00979 
00980         if (!isGarbage(i))
00981         {
00982             // Format is: "!%d\n", i
00983             //
00984             int n = mux_ltoa(i, buf+1) + 1;
00985             buf[n++] = '\n';
00986             fwrite(buf, sizeof(char), n, f);
00987             db_write_object(f, i, format, flags);
00988         }
00989     }
00990     fputs("***END OF DUMP***\n", f);
00991     if (mudstate.bStandAlone)
00992     {
00993         Log.WriteString(ENDLINE);
00994         Log.Flush();
00995     }
00996     return mudstate.db_top;
00997 }

Generated on Mon May 28 04:40:09 2007 for MUX by  doxygen 1.4.7