// ---------------------------------------------------------------------------
// - Module.cpp -
// - afnix engine - module class implementation -
// ---------------------------------------------------------------------------
// - This program is free software; you can redistribute it and/or modify -
// - it provided that this copyright notice is kept intact. -
// - -
// - This program is distributed in the hope that it will be useful, but -
// - without any warranty; without even the implied warranty of -
// - merchantability or fitness for a particular purpose. In no event shall -
// - the copyright holder be liable for any direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software. -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2007 amaury darsch -
// ---------------------------------------------------------------------------
#include "Module.hpp"
#include "Reader.hpp"
#include "Extracter.hpp"
#include "Exception.hpp"
namespace afnix {
// -------------------------------------------------------------------------
// - private section -
// -------------------------------------------------------------------------
// the afnix magic number
const long AXC_MSIZE = 4;
const char AXC_MAGIC[] = {'\377', 'A', 'X', 'C'};
// this function write the module header to an output stream
static void write_module_magic (Output& os) {
for (long i = 0; i < AXC_MSIZE; i++) os.write (AXC_MAGIC[i]);
}
// this function check that the header matches the axc magic number
static Module::t_mtype get_module_type (Input* is) {
// check for nil and reset
if (is == nilp) return Module::REGULAR;
// read in the magic number
char mbuf[AXC_MSIZE];
for (long i = 0; i < AXC_MSIZE; i++) {
mbuf[i] = is->read ();
if (mbuf[i] != AXC_MAGIC[i]) {
is->pushback (mbuf, i+1);
return Module::REGULAR;
}
}
return Module::COMPILED;
}
// -------------------------------------------------------------------------
// - class section -
// -------------------------------------------------------------------------
// create a compiled module
Module::Module (void) {
d_type = COMPILED;
p_is = nilp;
}
// open a new module by name
Module::Module (const String& name) {
Module (new InputFile (name), name);
}
// open a module by stream
Module::Module (Input* is, const String& name) {
// try to open the file
Object::iref (p_is = is);
// find out the file type
d_type = get_module_type (p_is);
// create a new form reader
if (d_type == REGULAR) {
Reader* rd = new Reader (p_is);
p_former = rd;
rd->setfname (name);
} else {
p_former = new Extracter (p_is);
}
// save the module name
d_name = name;
}
// delete this module
Module::~Module (void) {
Object::dref (p_is);
delete p_former;
}
// return the class name
String Module::repr (void) const {
return "Module";
}
// get the next form available in this module
Form* Module::parse (void) {
rdlock ();
// check that we have a form reader
if (p_former == nilp) {
unlock ();
throw Exception ("module-error", "no former installed");
}
try {
Form* result = p_former->parse ();
unlock ();
return result;
} catch (...) {
unlock ();
throw;
}
}
// return the module type
Module::t_mtype Module::gettype (void) const {
rdlock ();
Module::t_mtype result = d_type;
unlock ();
return result;
}
// return the module name
String Module::getname (void) const {
rdlock ();
String result = d_name;
unlock ();
return result;
}
// return the reader line number
long Module::getlnum (void) const {
rdlock ();
// check that we have a form reader
if (p_former == nilp) {
unlock ();
throw Exception ("module-error", "no former installed");
}
try {
long result = p_former->getlnum ();
unlock ();
return result;
} catch (...) {
unlock ();
throw;
}
}
// write a module to an output stream
void Module::write (Output& os) {
rdlock ();
try {
// write the module header
write_module_magic (os);
// parse and serialize
while (true) {
Cons* cons = parse ();
if (cons == nilp) break;
cons->serialize (os);
Object::dref (cons);
}
unlock ();
} catch (...) {
unlock ();
throw;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1