blob: 80eb370d7b621db1b96979ebfee53904d9a4bece [file] [log] [blame]
// MorgenGrauen MUDlib
//
// virtual/v_compiler.c -- a general virtual compiler object
//
// $Id: v_compiler.c 9142 2015-02-04 22:17:29Z Zesstra $
// principle:
// - inherit this object into your own 'virtual_compiler.c'
// - customize Validate() and CustomizeObject() for you own sake
//
// * Validate() checks if a room filename given as argument (without path)
// is valid and returns this filename with stripped '.c'!!
// * CustomizeObject() uses the previous_object()->Function() strategy to
// customize the standard object (for example to set a description)
//
// Properties: P_STD_OBJECT, P_COMPILER_PATH
#pragma strict_types
#pragma save_types
#pragma range_check
#pragma no_clone
#pragma pedantic
inherit "/std/thing/properties";
//#define NEED_PROTOTYPES
#include <thing/properties.h>
#include <defines.h>
#include <v_compiler.h>
#include <exploration.h>
#include <sys_debug.h>
#include <living/description.h> //fuer P_PARA
// Der VC braucht das 'alte' object_name()-basierte BLUE_NAME, da sonst das
// Konfigurieren der von einem VC-Objekt geclonten Clones via
// CustomizeObject() nicht funktioniert (load_name() ermittelt den Namen des
// VC-Standardobjektes)
#ifdef BLUE_NAME
#undef BLUE_NAME
#endif
#define BLUE_NAME(ob) (explode(object_name(ob),"#")[0])
private nosave string last_loaded_file;
private nosave mapping objects;
void create()
{
::create();
seteuid(getuid());
SetProp(P_STD_OBJECT, "/std/room");
SetProp(P_COMPILER_PATH, sprintf("/%s/",
implode(old_explode(object_name(this_object()), "/")[0..<2], "/")));
SetProp(P_PARA, ({}) ); // keine Para-VC-Objekte
objects = ([]);
}
// von den erbenen VCs zu ueberschreiben...
// TODO: aus Standardobjekt entfernen, weil durch P_PARA und QueryValidObject
// obsolet.
int NoParaObjects() { return 0; }
string Validate(string file)
{
if(!file) return 0;
if(file[<2..] == ".c") file = file[0..<3];
EPMASTER->PrepareVCQuery(file);
return file;
}
// Die Funktion bekommt einen Objektnamen uebergeben und muss entscheiden, ob
// dieser VC dafuer zustaendig ist, das Objekt zu generieren. Jeder Wert != 0
// zaehlt als 'zustaendig'. Es ist eine Art generalisiertem Validate(). Fuer
// maximale Nuetzlichkeit muss diese Funktion von den erbenden VCs
// ueberschrieben werden.
public int QueryValidObject(string oname) {
string fname, path, *pelem;
int para;
mixed ppara;
//erstmal Validate fragen
pelem=explode(oname,"/");
fname=pelem[<1];
if (!fname=Validate(fname))
return(0); //nicht zustaendig
// nicht im richtigen Pfad?
path=sprintf("%s/",implode(pelem[0..<2],"/"));
if (path!=QueryProp(P_COMPILER_PATH))
return(0);
// Para-Objekt?
if (sscanf(fname,"%s^%d",fname,para) > 1) {
if (NoParaObjects())
return(0); //direkt zurueck, keine Para-Objekte
// bestimmte Para-Dimensionen explizit erlaubt? (Wenn P_PARA nicht
// gesetzt ist, sind alle erlaubt!)
if (ppara=QueryProp(P_PARA)) {
if (pointerp(ppara) && member(ppara,para)!=-1)
return(1);
else if (intp(para) && ppara==para)
return(1);
// P_PARA gesetzt, aber gewuenschtes Para nicht enthalten...
else return(0);
}
}
return(1); //fall-through, offenbar zustaendig.
}
mixed CustomizeObject()
{
string file;
if(!clonep(previous_object()))
return Validate(explode(BLUE_NAME(previous_object()), "/")[<1]);
if(stringp(last_loaded_file)) file = last_loaded_file;
else file = Validate(explode(BLUE_NAME(previous_object()), "/")[<1]);
if(!file) return 0;
last_loaded_file = 0;
return file;
}
// add a new object to the object list if it compiles
private mixed AddObject(string file)
{
object ob;
string err;
// clean up the object list
objects = filter_indices(objects, function int (string f) {
return (objectp(objects[f])); } );
last_loaded_file = file;
// register new object
if(ob = clone_object(QueryProp(P_STD_OBJECT)))
objects[file] = ob;
return ob;
}
// try to create an object for the wanted file
mixed compile_object(string file)
{
// validate if the file name is a correct one
if(file = Validate(file))
return AddObject(file);
return 0;
}
// return all cloned virtual objects
mixed QueryObjects()
{
return m_values(objects)-({0});
}
// clean up rooms that have not been destructed yet
int remove() {
if(!mappingp(objects)) return 0;
//for(ob = QueryObjects(); sizeof(ob); ob = ob[1..])
foreach(object ob: QueryObjects()) {
ob->remove();
if(objectp(ob)) destruct(ob);
}
return 1;
}