System dependencies: -------------------- the code than handles random() and the time stuff in bltin.c assumes that integers and longs can be swapped. the solution is to add another data type - longs - but that is a pain because math operations would need to be overloaded. left as an excercise to the reader. ctime returns 26 chars in a string. (according to the man page) The assumption is made in the code (bltin.c) that it will be less than 32 chars. I've taken great pains to make sure the union of Opers is used wherever possible to prevent portability problems but such things are uncertain at best. Wherever possible syntactic techniques are used to avoid typing problems, rather than just casts. (I *KNOW* a long can be cast as a char * and vice-versa, but this sucker may be slow enough to demand being run on a CRAY :) The b+tree library used to store the static symbol table is fairly portable, but may break. If it does, good luck to you. There are no 'non-trivial' lint(1) complaints. 'trivial' is defined as: stupid shit like function types being declared differently because DEC and Sun can't decide if bcopy is an int or a void, or signal is a (*void)() or whatever. Pointer alignment warnings abound, of course. A word on memory management: ---------------------------- memory management is done through 3 completely separate mechanisms, depending on where the allocation is called from. all memory used in compilation (parse.y) is hacked around in static buffers. all memory used in temporaries during the interpeter run is malloc()ed with a function that keeps track of allocations and can free them all in a single call (tmpalloc() and friends). all memory used in the cache and freeze/thaw code (which can also wind up on the stack) is malloc()ed and is freed when the object leaves the cache or is modified. at any point in time all 3 of these types of memory objects can be found in the stack! be very careful, ye who hack, to ensure that you do not EVER make direct calls to free() unless you are very very sure you know where that memory came from! there are points in the caching code (in store.c and in sym.c) where things are falsely placed onto the temporary allocation list, to be freed later. be wary of this, as it leaves memory around only until the next call to tmpfree(). A word on the network interface: -------------------------------- the network interface is designed to allow easy replacement as new network paradigms (a good buzz word) are developed and ballyhooed. simply re-write functionally identical code to plug into tcpstuff.c and away you go. there is a bit of commenting about HOW the interface works at the head of tcpio.c. if you write bindings of this to other systems, let me know. it should be changed to feed the data to dispatch() a line-at-a-time! A word on adding new builtin functions: --------------------------------------- First, make sure it's necessary. Second, be REALLY careful if you have an existing universe database, since the builtin function numbers are compiled in to the objects, and if you change them, you have utterly smoked your db! that being said, how to do it: 1) make an entry in the keyword lookup table in parse.y the last value is the ordinal number of the builtin. 2) make an entry in blttab.c matching the ordinal number you specified in parse.y 3) write the builtin itself. look at the ones in bltin.c. read the comments in bltin.c that explain what happens if you assign to the result memory address before you are ready to return from the builtin! 4) make sure that your biltin is "sensible" and does not try to call any functions that would generate another interpreter run! the interpreter is re-entrant only with the most extreme care! 5) make an entry in the token table of the standalone syntax checker to match the new keyword, or you will confuse it terribly. A word on hacking the monitor: ------------------------------ There are parts of code in monitor.c that HAVE to make some assumptions about the universe rules - such as where to check for functions and whatnot. These are all in player_in(), and are marked with a big comment: /* HARDCODE */ near them. Before you randomly add 2 tonnes of searching to the monitor, remember that the monitor will get called a LOT, and the more searches it does, the more CPU and I/O bandwidth you need! A word on disgusting hacks in here to be aware of: -------------------------------------------------- There aren't TOO many such, I think, but the biggest, and by far the worst is the uid/perms tags stored in a function. This is a royal butt-pain, but is the most efficient way to implement setuid functions. What it means is that any place where you modify the perms/owner of an object you HAVE TO make sure if it's a function that you patch the mode bits back up again. There are awful potential problems with things that are being run or used in the current executing environment being modified while they are running (IE:assigning to a function WHILE it is being run, or a list while it is being iterated across). This is usually handled by either copying the object (as in a list iterator) or by putting it on the free chain for later freeing. A word on actually running the server: -------------------------------------- If you can't figure it out by reading the startserver and haltserver shell scripts, and looking at main.c, you should just give up - you don't know enough C. The only subtle things you need to do is figure out the format for the password file (in disp.c) and how to initialize your universe the first time (feed it init.u AFTER you've booted it with boot.u). A word on the password file: ---------------------------- The format is: user-connect name : password : user object number : flags for example: UberWiz:X:2:W The flags field presently can contain nothing (for none), or a '1' (for programmer permission granted), or a 'W' (for Wizard permission granted). Note that the user-connect-name can have nothing WHATSOEVER to do with the player's game name. Also, note that you can have more than one password entry with different sets of flags for the same object #. (so you can have a login for the Wiz that is not wiz-priv'd) You get to figure the rest out. mjr.