skylib_fluffos_v3/
skylib_fluffos_v3/bin/
skylib_fluffos_v3/bin/db/
skylib_fluffos_v3/fluffos-2.9-ds2.04/
skylib_fluffos_v3/fluffos-2.9-ds2.04/ChangeLog.old/
skylib_fluffos_v3/fluffos-2.9-ds2.04/Win32/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/simuls/
skylib_fluffos_v3/fluffos-2.9-ds2.04/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/clone/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/command/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/data/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/etc/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/master/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/log/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/compiler/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/efuns/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/operators/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/u/
skylib_fluffos_v3/fluffos-2.9-ds2.04/tmp/
skylib_fluffos_v3/fluffos-2.9-ds2.04/windows/
skylib_fluffos_v3/mudlib/
skylib_fluffos_v3/mudlib/cmds/
skylib_fluffos_v3/mudlib/cmds/admin/
skylib_fluffos_v3/mudlib/cmds/guild-race/
skylib_fluffos_v3/mudlib/cmds/living/broken/
skylib_fluffos_v3/mudlib/cmds/player/group_cmds/
skylib_fluffos_v3/mudlib/cmds/playtester/
skylib_fluffos_v3/mudlib/d/admin/
skylib_fluffos_v3/mudlib/d/admin/room/
skylib_fluffos_v3/mudlib/d/admin/room/we_care/
skylib_fluffos_v3/mudlib/d/admin/save/
skylib_fluffos_v3/mudlib/d/admin/text/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/buildings/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/map/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/roads/
skylib_fluffos_v3/mudlib/d/learning/chars/
skylib_fluffos_v3/mudlib/d/learning/functions/
skylib_fluffos_v3/mudlib/d/learning/handlers/
skylib_fluffos_v3/mudlib/d/learning/help_topics/
skylib_fluffos_v3/mudlib/d/learning/help_topics/npcs/
skylib_fluffos_v3/mudlib/d/learning/help_topics/objects/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/RCS/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/crowd/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/situations/
skylib_fluffos_v3/mudlib/d/learning/save/
skylib_fluffos_v3/mudlib/d/learning/school/
skylib_fluffos_v3/mudlib/d/learning/school/add_sc/
skylib_fluffos_v3/mudlib/d/learning/school/characters/
skylib_fluffos_v3/mudlib/d/learning/school/general/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/basic_commands/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/edtutor/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/unix_tutor/
skylib_fluffos_v3/mudlib/d/learning/school/items/
skylib_fluffos_v3/mudlib/d/learning/school/npc_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/room_basic/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/situations/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/terrain_tutor/
skylib_fluffos_v3/mudlib/d/learning/text/
skylib_fluffos_v3/mudlib/d/liaison/
skylib_fluffos_v3/mudlib/d/mudlib/
skylib_fluffos_v3/mudlib/d/mudlib/changes/
skylib_fluffos_v3/mudlib/d/playtesters/
skylib_fluffos_v3/mudlib/d/playtesters/effects/
skylib_fluffos_v3/mudlib/d/playtesters/handlers/
skylib_fluffos_v3/mudlib/d/playtesters/items/
skylib_fluffos_v3/mudlib/d/sage/
skylib_fluffos_v3/mudlib/doc/
skylib_fluffos_v3/mudlib/doc/creator/
skylib_fluffos_v3/mudlib/doc/driver/
skylib_fluffos_v3/mudlib/doc/driver/efuns/arrays/
skylib_fluffos_v3/mudlib/doc/driver/efuns/buffers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/calls/
skylib_fluffos_v3/mudlib/doc/driver/efuns/compile/
skylib_fluffos_v3/mudlib/doc/driver/efuns/filesystem/
skylib_fluffos_v3/mudlib/doc/driver/efuns/floats/
skylib_fluffos_v3/mudlib/doc/driver/efuns/functions/
skylib_fluffos_v3/mudlib/doc/driver/efuns/general/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mappings/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mixed/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mudlib/
skylib_fluffos_v3/mudlib/doc/driver/efuns/numbers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/parsing/
skylib_fluffos_v3/mudlib/doc/login/
skylib_fluffos_v3/mudlib/doc/lpc/basic_manual/
skylib_fluffos_v3/mudlib/doc/lpc/intermediate/
skylib_fluffos_v3/mudlib/doc/new/add_command/
skylib_fluffos_v3/mudlib/doc/new/events/
skylib_fluffos_v3/mudlib/doc/new/handlers/
skylib_fluffos_v3/mudlib/doc/new/living/race/
skylib_fluffos_v3/mudlib/doc/new/living/spells/
skylib_fluffos_v3/mudlib/doc/new/object/
skylib_fluffos_v3/mudlib/doc/new/player/
skylib_fluffos_v3/mudlib/doc/new/room/guild/
skylib_fluffos_v3/mudlib/doc/new/room/outside/
skylib_fluffos_v3/mudlib/doc/new/room/storeroom/
skylib_fluffos_v3/mudlib/doc/object/
skylib_fluffos_v3/mudlib/doc/playtesters/
skylib_fluffos_v3/mudlib/doc/policy/
skylib_fluffos_v3/mudlib/doc/weapons/
skylib_fluffos_v3/mudlib/global/
skylib_fluffos_v3/mudlib/global/creator/
skylib_fluffos_v3/mudlib/handlers/
skylib_fluffos_v3/mudlib/include/casino/
skylib_fluffos_v3/mudlib/include/cmds/
skylib_fluffos_v3/mudlib/include/effects/
skylib_fluffos_v3/mudlib/include/npc/
skylib_fluffos_v3/mudlib/include/room/
skylib_fluffos_v3/mudlib/include/shops/
skylib_fluffos_v3/mudlib/net/daemon/
skylib_fluffos_v3/mudlib/net/daemon/chars/
skylib_fluffos_v3/mudlib/net/inherit/
skylib_fluffos_v3/mudlib/net/obj/
skylib_fluffos_v3/mudlib/net/obj/BACKUPS/
skylib_fluffos_v3/mudlib/obj/amulets/
skylib_fluffos_v3/mudlib/obj/armours/plate/
skylib_fluffos_v3/mudlib/obj/b_day/
skylib_fluffos_v3/mudlib/obj/clothes/transport/horse/
skylib_fluffos_v3/mudlib/obj/faith/symbols/
skylib_fluffos_v3/mudlib/obj/fungi/
skylib_fluffos_v3/mudlib/obj/gatherables/
skylib_fluffos_v3/mudlib/obj/instruments/
skylib_fluffos_v3/mudlib/obj/media/
skylib_fluffos_v3/mudlib/obj/misc/player_shop/
skylib_fluffos_v3/mudlib/obj/monster/godmother/
skylib_fluffos_v3/mudlib/obj/monster/transport/
skylib_fluffos_v3/mudlib/obj/rings/
skylib_fluffos_v3/mudlib/obj/scabbards/
skylib_fluffos_v3/mudlib/obj/spells/
skylib_fluffos_v3/mudlib/obj/stationery/
skylib_fluffos_v3/mudlib/obj/stationery/envelopes/
skylib_fluffos_v3/mudlib/obj/toys/
skylib_fluffos_v3/mudlib/obj/vessels/
skylib_fluffos_v3/mudlib/obj/weapons/axes/
skylib_fluffos_v3/mudlib/obj/weapons/chains/
skylib_fluffos_v3/mudlib/obj/weapons/maces/BACKUPS/
skylib_fluffos_v3/mudlib/save/autodoc/
skylib_fluffos_v3/mudlib/save/book_handler/
skylib_fluffos_v3/mudlib/save/books/history/calarien/
skylib_fluffos_v3/mudlib/save/mail/
skylib_fluffos_v3/mudlib/save/new_soul/data/
skylib_fluffos_v3/mudlib/save/parcels/
skylib_fluffos_v3/mudlib/save/playerinfo/
skylib_fluffos_v3/mudlib/save/players/d/
skylib_fluffos_v3/mudlib/save/players/s/
skylib_fluffos_v3/mudlib/save/random_names/
skylib_fluffos_v3/mudlib/save/random_names/data/
skylib_fluffos_v3/mudlib/save/terrains/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_desert/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_grassy_field/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_mountain/
skylib_fluffos_v3/mudlib/save/todo_lists/
skylib_fluffos_v3/mudlib/secure/
skylib_fluffos_v3/mudlib/secure/cmds/admin/
skylib_fluffos_v3/mudlib/secure/cmds/lord/
skylib_fluffos_v3/mudlib/secure/config/
skylib_fluffos_v3/mudlib/secure/handlers/autodoc/
skylib_fluffos_v3/mudlib/secure/handlers/intermud/
skylib_fluffos_v3/mudlib/secure/include/global/
skylib_fluffos_v3/mudlib/secure/save/
skylib_fluffos_v3/mudlib/secure/save/handlers/
skylib_fluffos_v3/mudlib/secure/std/
skylib_fluffos_v3/mudlib/secure/std/classes/
skylib_fluffos_v3/mudlib/secure/std/modules/
skylib_fluffos_v3/mudlib/std/creator/
skylib_fluffos_v3/mudlib/std/dom/
skylib_fluffos_v3/mudlib/std/effects/
skylib_fluffos_v3/mudlib/std/effects/external/
skylib_fluffos_v3/mudlib/std/effects/fighting/
skylib_fluffos_v3/mudlib/std/effects/magic/
skylib_fluffos_v3/mudlib/std/effects/magic/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/other/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/priest/
skylib_fluffos_v3/mudlib/std/effects/room/
skylib_fluffos_v3/mudlib/std/environ/
skylib_fluffos_v3/mudlib/std/guilds/
skylib_fluffos_v3/mudlib/std/guilds/old/
skylib_fluffos_v3/mudlib/std/languages/
skylib_fluffos_v3/mudlib/std/liquids/
skylib_fluffos_v3/mudlib/std/npc/
skylib_fluffos_v3/mudlib/std/npc/goals/
skylib_fluffos_v3/mudlib/std/npc/goals/basic/
skylib_fluffos_v3/mudlib/std/npc/goals/misc/
skylib_fluffos_v3/mudlib/std/npc/plans/
skylib_fluffos_v3/mudlib/std/npc/plans/basic/
skylib_fluffos_v3/mudlib/std/npc/types/
skylib_fluffos_v3/mudlib/std/npc/types/helper/
skylib_fluffos_v3/mudlib/std/npcs/
skylib_fluffos_v3/mudlib/std/outsides/
skylib_fluffos_v3/mudlib/std/races/shadows/
skylib_fluffos_v3/mudlib/std/room/basic/BACKUPS/
skylib_fluffos_v3/mudlib/std/room/basic/topography/
skylib_fluffos_v3/mudlib/std/room/controller/
skylib_fluffos_v3/mudlib/std/room/inherit/topography/
skylib_fluffos_v3/mudlib/std/room/topography/area/
skylib_fluffos_v3/mudlib/std/room/topography/iroom/
skylib_fluffos_v3/mudlib/std/room/topography/milestone/
skylib_fluffos_v3/mudlib/std/shadows/curses/
skylib_fluffos_v3/mudlib/std/shadows/disease/
skylib_fluffos_v3/mudlib/std/shadows/fighting/
skylib_fluffos_v3/mudlib/std/shadows/healing/
skylib_fluffos_v3/mudlib/std/shadows/magic/
skylib_fluffos_v3/mudlib/std/shadows/poison/
skylib_fluffos_v3/mudlib/std/shadows/room/
skylib_fluffos_v3/mudlib/std/shops/controllers/
skylib_fluffos_v3/mudlib/std/shops/objs/
skylib_fluffos_v3/mudlib/std/shops/player_shop/
skylib_fluffos_v3/mudlib/std/socket/
skylib_fluffos_v3/mudlib/std/soul/d/
skylib_fluffos_v3/mudlib/std/soul/e/
skylib_fluffos_v3/mudlib/std/soul/i/
skylib_fluffos_v3/mudlib/std/soul/j/
skylib_fluffos_v3/mudlib/std/soul/k/
skylib_fluffos_v3/mudlib/std/soul/l/
skylib_fluffos_v3/mudlib/std/soul/n/
skylib_fluffos_v3/mudlib/std/soul/o/
skylib_fluffos_v3/mudlib/std/soul/q/
skylib_fluffos_v3/mudlib/std/soul/r/
skylib_fluffos_v3/mudlib/std/soul/u/
skylib_fluffos_v3/mudlib/std/soul/v/
skylib_fluffos_v3/mudlib/std/soul/y/
skylib_fluffos_v3/mudlib/std/soul/z/
skylib_fluffos_v3/mudlib/std/stationery/
skylib_fluffos_v3/mudlib/w/
skylib_fluffos_v3/mudlib/w/default/
skylib_fluffos_v3/mudlib/w/default/armour/
skylib_fluffos_v3/mudlib/w/default/clothes/
skylib_fluffos_v3/mudlib/w/default/item/
skylib_fluffos_v3/mudlib/w/default/npc/
skylib_fluffos_v3/mudlib/w/default/room/
skylib_fluffos_v3/mudlib/w/default/weapon/
skylib_fluffos_v3/mudlib/www/
skylib_fluffos_v3/mudlib/www/java/
skylib_fluffos_v3/mudlib/www/secure/
skylib_fluffos_v3/mudlib/www/secure/lpc/advanced/
skylib_fluffos_v3/mudlib/www/secure/lpc/intermediate/
skylib_fluffos_v3/win32/
/**
 * Universal data initialization handler.
 * The data initializer can be used to initialize databases for use in other
 * handlers.  The database is defined in a user-provided text file, with
 * a format similar to the virtual object compiler.  The input file is
 * converted to a temporary object, which allows fairly complicated
 * expressions to be used as data values.  The initializer can handle
 * arrays and mappings (nested to any level (theoretically)), with a base
 * element of any type, including mixed and classes.
 * <p>
 * To initialize a variable, assign it the value returned by
 * compile_data() in the initializer.  compile_data() takes an array of
 * filenames as its only argument.
 * <p>
 * <b>File format</b>
 * The data file uses the following keywords.  Each keyword is followed
 * by the required data.  The data can be spread over multiple lines,
 * following the same rules as for LPC code, but the keywords must be at
 * the beginning of the line (preceded by optional whitespace).
 * <dl>
 * <dt>::data:: < array | mapping > [ of ] ... < base >
 * <dd>
 * This keyword defines the structure of the data.  The word "of" is
 * optional.  "array" and "mapping" may be repeated as many times as
 * desired.  "base" is the base type of the data.  For classes, it would
 * be of the form "class <classname>".  For types other than classes,
 * the base isn't really
 * used at this time, but something needs to be there to keep the parser
 * in line.  Some examples:
 * <b>
 * <pre>::data:: array of mapping of array of int
 * ::data:: mapping of mapping of mixed
 * ::data:: mapping of array of class myclass</pre>
 * There should only be one ::data:: keyword in the list of files passed
 * to compile_data().  Also, note that classes need to be defined before
 * this statement.  This can be done either with ::quote:: or
 * ::#include::.
 * <dt>::item <index> [,] ... :: [ value ]
 * <dd>This keyword defines the value for one item of the data.  <index> is
 * repeated as often as necessary, given the structure declared in the
 * ::data:: statement.  For mappings, the index can be any valid mapping key.
 * For arrays, the index can be either a number, or the strings i, i++,
 * or ++i, for current index, current index (incrementing afterwards), or
 * next index.  The value can (and probably should) be omitted for
 * classes, with the field values specified with the "->" keyword below.
 * Examples (corresponding to the three ::data:: examples above):
 * <pre>
 * ::item 0, "item 1", 2:: 42
 * ::item "a", "b":: ({ 1, "fred", ({ 2, 3 }) })
 * ::item "x" i++::
 * </pre>
 * <dt> ::-><field>:: <value>
 * <dd>This allows the fields of items of type class to be assigned
 * individually.  In general, the preceding ::item:: keyword should not
 * have been given a value.  The class must have been defined previously,
 * either with an ::#include:: directive, or with the ::quote:: keyword.
 * Examples:
 * <pre>
 * ::Quote::
 * class item_data {
 *     string *season;
 *     mixed  quant;
 *     string ob;
 * }
 * 
 * ::Data:: mapping of class item_data

 * :item "white clover"::
 * ::->season:: ({ "spring" })
 * ::->quant:: ({ 3, 4 })
 * ::->ob:: "/std/plant"
 * </pre>
 * These statements set the season, quant, and ob fields of the mapping
 * <dt>::quote:: <LPC code>
 * <dd>This keyword allows specific LPC statements to be inserted in the
 * object that creates the database.  To use this effectively requires a
 * little understanding of the translation process.  First, all lines
 * associated with a given keyword are folded into one line.  This means
 * that using the "//" comment delimiter in a ::quote:: will cause the
 * remainder of the quoted statements to be ignored.  Second, the
 * prototype of the function that returns the data isn't written until
 * the ::data:: keyword is encountered.  Therefore, any "global"
 * statements (such as class definitions) should be included or quoted
 * before the ::data:: line.  The easiest way to see what's going on is
 * to try a few examples and look at the resulting .c file (which is the
 * first data file name with ".c" stuck on the end).
 * </dl>
 * @example
 * mixed data;
 * data = "/handlers/data"->compile_data(({ "/save/file1.dat",
 *      "/save/file2.dat" }));
 * // This will catenate the two files into one, translate it, and return
 * // the data.  Of course, someone has to create the data files also.
 * @author Jeremy
 */

#define DEBUG !
#define DC_DELIM 0
#define DC_ARRAY 1
#define DC_MAPPING 2
#define DC_OF 3
#define DC_CLASS 4
#define DC_STRING 5
#define DC_ITEM 6
#define DC_NUMBER 7
#define DC_GREY 8

// This is the number of characters it reads before starting a new
// function.  I set it to half of the biggest set of files that caused
// me problems.  It can be adjusted as needed.
#define MAX_SUBF_SIZE 16000

#define WHITESPACE(c) (c == 10 || c == 32 || c == '\n')

#ifdef DEBUG
#  define Error(s) write(s); log_file( "DATA_COMPILER", s);
#else
#  define Error(s) ;
#endif

string std_euid;

void create() {
    std_euid = "/secure/master"->creator_file(file_name(this_object()));
    seteuid(std_euid);
    //Error("Note: euid at creation is " + geteuid() + "\n");
}

int tmp_file_no;

private string strip_string( string str ) {
    int     i, j;
 
    if (!str || str == "") return "";
    j = strlen( str ) - 1;
    for( ; WHITESPACE( str[ i ] ) && i <= j; i++ ) ;
    for( ; WHITESPACE( str[ j ] ) && j > i; j-- ) ;
    return str[ i..j ];
} /* strip_space() */

private mixed cleanup_assoc( mixed parse ) {
    int j;

    // Clean out whitespace (seems like there should be an easier
    // way to do this...)
    for (j = 0; j < sizeof(parse[0]); j++) {
        if ((parse[1][j] == DC_DELIM) || (parse[1][j] == DC_OF)) {
            parse[0][j] = 0;
            parse[1][j] = 0;
        }
    }
    parse[0] -= ({ 0 });
    parse[1] -= ({ 0 });
    return parse;
} /* cleanup_assoc */

/**
 * Actualy compiles the files down.
 * See the header file for a more detailed explaination
 * @param path the files to parse
 */
mixed compile_data( string *path ) {
    string tmp_name, data = "", file_data = "", s1, tmp_val, base, keyword;
    string *segments, *ind, *val, cur_index;
    int i, j, t, debug_file, class_pending, stat, subfunc_cnt,
        subfunc_char_cnt, data_keyword_found;
    int *index_types;
    mixed parse, index_max;

    // Most of this is blatantly stolen from /global/virtual/compiler.c
    if (!sizeof(path))
      return 0;
    tmp_name = path[0] + "_dc.c";
    if( find_object( tmp_name ) )
        tmp_name->dest_me();
    if (file_size(tmp_name) > 0) {
        if ((stat = seteuid("Root")) == 0) {
            // This always happens.  But everything seems to work,
            // so I'll just take it out.
            // Error("Error: couldn't set euid to Root (" + stat + ", " +
            //       "secure/master"->valid_seteuid(this_object(), "Root") +
            //       ")\n");
        }
        stat = unguarded((: rm, tmp_name :));
        if (!stat) {
            Error("Error: couldn't remove old .c file (" +
                  geteuid(this_object()) + ", " +
                  "secure/master"->valid_seteuid(this_object(), "Root") +
                  ")\n");
            seteuid(std_euid);
            return 0;
        }
        //Error("Note: " + tmp_name + " removed (supposedly).\n");
    }
    seteuid(std_euid);
    for (i = 0; i < sizeof(path); i++) {
        if (file_size(path[i]) <= 0)
          continue;
        data += read_file( path[i] );
    }
    if (!data) {
        Error("Error: file(s) not found.\n");
        return 0;
    }
    /* Lines beginning with a # are a comment... */
    /* Break into segments at comments */
    segments = explode( "$\n" + data, "\n#" );
    if( !segments ) {
        Error( "prop_to_fun() : Nothing but comments?\n" );
        return 0;
    }
    /* Remove dummy $ (?) */
    segments[ 0 ] = segments[ 0 ][ 1..(sizeof(segments[ 0 ]) - 1) ];
    /* Remove comment lines */
    for( i = 1; i < sizeof( segments ); i++ ) {
        if( sscanf( segments[ i ], "%s\n%s", s1, segments[ i ] ) != 2 ) {
            segments[ i ] = "";
        }
    }
    /* Join segments together again */
    data = implode( segments, "\n" );
    
    /* See example file for explanation of syntax. */
 
    segments = explode( strip_string( data ), "::" );
    /* sizeof(segments) can be odd if the last line has no argument */
    if (sizeof( segments ) % 2) {
      segments += ({""});
    }
    ind = allocate( sizeof( segments ) / 2 );
    val = allocate( sizeof( segments ) / 2 );
 
    for( i = 0; i < sizeof( ind ); i++ ) {
        ind[ i ] = segments[ i * 2 ];
        //val[ i ] = replace( segments[ i * 2 + 1 ], "\n", " " );
        // This preserves the newlines; it makes it more readable and avoids
        // line length problems.
        val[ i ] = strip_string( segments[ i * 2 + 1 ] );
        /* look for virtual compiler meta char */
        if( ind[ i ][ 0..0 ] == "#" ) {
            ind[ i ] = lower_case( ind[ i ] );
            if( ind[ i ] == "#debug" ) {
                /* debug errent virtual programs, ie, don't rm */
                /* the .c file if debug_file is non-zero */
                sscanf( val[ i ], "%d", debug_file );
            } else if( ind[ i ] == "#include" ) {
                /* include the file in setup(), just before the */
                /* object is cloned.  */
                tmp_val = val[i];
                file_data += "#include " + replace( tmp_val, " ", "" ) + "\n";
            }
        }
    }
    for( i = 0; i < sizeof( ind ); i++ ) {
        keyword = lower_case( ind[ i ] );
        if( keyword[ 0..0 ] == "#" ) {
            /* it's a virtual keyword don't stick it in the .c file */
            continue;
        }
        // Keep track of how big the function is.  The easiest way
        // to judge the amount of code is by counting the characters.
        subfunc_char_cnt += sizeof(ind[i]) + sizeof(val[i]);
        if (keyword == "data") {
            if (data_keyword_found) {
                Error("Error: more than one data keyword found.\n");
                return 0;
            }
            data_keyword_found = 1;
            // This declares the structure of the database
            file_data += "void dest_me() { destruct( this_object() ); }\n\n";
            // Break up code into multiple functions; big files can
            // run into trouble compiling.
            parse = reg_assoc(val[i],
                              ({ "array", "mapping", "of", "class +[^\t ]+",
                                 "[^\t ]+" }),
                              ({ DC_ARRAY, DC_MAPPING, DC_OF, DC_CLASS,
                                 DC_GREY }),
                              DC_DELIM);
            parse = cleanup_assoc( parse );
            //printf("parse = %O\n", parse);
            for (j = 0; (j < sizeof(parse[0])) && !index_max; j++) {
                switch (parse[1][j]) {
                  case DC_ARRAY:
                    break;
                  case DC_MAPPING:
                    break;
                  case DC_CLASS:
                    base = implode(parse[0][j..], " ");
                    file_data += base + " item;\n";
                  case DC_GREY:
                    index_types = parse[1][0..j-1];
                    index_max = allocate(sizeof(index_types));
                    break;
                  default:
                    Error("Error: data parse error 1 (" + parse[0][j] + ")\n");
                    return 0;
                }
            }
            if (index_types[0] == DC_MAPPING)
              file_data += "mapping data = ([ ]);\n\n";
            else
              file_data += "mixed data;\n\n";
            for (j = 0; j < sizeof(index_types); j++) {
                switch (index_types[j]) {
                  case DC_ARRAY:
                    index_max[j] = -1;
                    break;
                  case DC_MAPPING:
                    //index_max[j] = ([ ]);
                    break;
                  default:
                    Error("Error: illegal index type found ("
                          + index_types[j] + ")\n");
                    return 0;
                }
            }
            file_data += "mixed data_return_" + subfunc_cnt + "() {\n";
            subfunc_cnt++;
            continue;
        }
        if (keyword[0..3] == "item") {
            // This is where the actual array values get assigned
            // First take care of pending class assignments
            if (class_pending) {
                file_data += "  data" + cur_index + " = item;\n";
                class_pending = 0;
            }
            // Check to see if we should break to a new function (this
            // is the safest place, since we can't break up an item
            // definition).
            if (subfunc_char_cnt > MAX_SUBF_SIZE) {
                // This could theoretically fail if we somehow got more than
                // MAX_SUBF_SIZE characters before the first "data" keyword.
                // So it goes...
                file_data += "}\n\n";
                file_data += "mixed data_return_" + subfunc_cnt + "() {\n";
                subfunc_cnt++;
                subfunc_char_cnt = 0;
            }
            parse = reg_assoc( ind[i], ({ "\"[^\"]*\"", "item", "[0-9]+",
                                      "[^,\t ]+"}),
                              ({ DC_STRING, DC_ITEM, DC_NUMBER, DC_GREY }));
            parse = cleanup_assoc( parse );
            //printf("parse = %O\nindex_max = %O\n", parse, index_max);
            cur_index = "";
            for (j = 0; j < sizeof(index_types); j++) {
                switch (index_types[j]) {
                  case DC_ARRAY:
                    // Index can be a number, "i", "i++", or "++i"
                    if (parse[1][j+1] != DC_NUMBER) {
                        if (parse[0][j+1] == "i") {
                            parse[0][j+1] = index_max[j] + "";
                        } else if (parse[0][j+1] == "i++") {
                            parse[0][j+1] = index_max[j] + "";
                            index_max[j]++;
                        } else if (parse[0][j+1] == "++i") {
                            index_max[j]++;
                            parse[0][j+1] = index_max[j] + "";
                        } else {
                          Error("Error: illegal index for array (" +
                                  parse[0][j+1] + ")\n");
                            return 0;
                        }
                    }
                    if ((t = to_int(parse[0][j+1])) > index_max[j]) {
                        file_data += "  data" + cur_index
                          + " = allocate(" + (t-index_max[j]) + ");\n";
                        index_max[j] = t;
                    }
                    break;
                  case DC_MAPPING:
                    if (j) {
                        file_data += "  if (!mappingp(data" + cur_index + "))"
                          + " data" + cur_index + " = ([]);\n";
                    }
                    break;
                  default:
                    Error("Error: illegal index type found (" + index_types[j]
                          + ")\n");
                    return 0;
                } /* switch */
                cur_index += "[" + parse[0][j+1] + "]";
            } /* for */
            if (strip_string(val[i]) != "") {
                //printf("val[i] = %O\n", val[i]);
                file_data += "  data" + cur_index + " = " + val[i] + ";\n";
            }
            continue;
        } /* if */
        if (keyword[0..1] == "->") {
            // This is for handling fields of classes
            if (!class_pending) {
                file_data += "  item = new( " + base + " );\n";
                class_pending = 1;
            }
            file_data += "  item->" + ind[i][2..] + " = " + val[i] + ";\n";
            continue;
        }
        if (keyword == "quote") {
            // A backdoor for putting in specific LPC lines
            file_data += val[i] + "\n";
            continue;
        }
    } /* for */
    if (class_pending) {
        file_data += "  data" + cur_index + " = item;\n";
    }
    file_data += "}\n\n";
    file_data += "mixed data_return() {\n";
    for (i = 0; i < subfunc_cnt; i++) {
        file_data += "  data_return_" + i + "();\n";
    }
    file_data += "  return data;\n}\n";
    seteuid("Root");
    unguarded((: write_file, tmp_name, file_data, 1 :));
    seteuid(std_euid);
    return tmp_name->data_return();
} /* compile_data() */