include <hush/source.h>
include <hush/handler.h>
include <hush/dictionary.h>
include <hush/string.h>
ifndef CIAO
include <hush/vm.h>
endif
include <hush/sys/io.h>
include <hush/kit.h>
include <hush/event.h>
include <hush/sys/types.h>
include <hush/session.h>
include <hush/assert.h>
include <hush/sys/cell.h>
include <hush/sys/port.h>
include <string.h>
include <stdio.h>
include "hush/sys/garbage.i"
include "hush/sys/light.h"
define TYPE handler
include "hush/sys/table.i"
static void checkflush(ostream& os, const char* s) {
//if (s[0]=='\n') os.flush();
}
include <hush/api/io.h>
static void printerr(const char* s) { cerr << s; checkflush(cerr,s); }
static void printout(const char* s) { cout << s; checkflush(cerr,s); }
int handler::initialized = 0;
int handler::initialize() {
IO::initialize();
obscure::initialize();
if (!handler::initialized) {
handler::_err = 0; // &cerr;
handler::_out = 0; // &cout;
handler::_in = 0; // &cin;
}
IO* x = handler::_err = new IO;
x->_print = printerr;
session::_default->_register(x);
x = handler::_out = new IO;
x->_print = printout;
session::_default->_register(x);
return handler::initialized = 1;
}
IO* handler::_out = 0;
IO* handler::_err = 0;
IO* handler::_in = 0;
struct handler_state {
handler_state(handler* x = 0) {
refs = 1;
_etc = 0; _mode = 0; _garb = 0;
_bdy = 0; _ctx = x; _slf = 0; // _bdy is global!
i_options = 0; resources = 0;
s_options = 0;
}
~handler_state() {
if (_garb) delete _garb;
if (_etc) delete _etc;
}
int refs;
int _mode;
cell* _etc;
hush_garbage* _garb;
handler* _bdy; // for a unified body
handler* _ctx; // the context
handler* _slf; // for inner components
dictionary<dvstring>* s_options;
dictionary<int>* i_options;
dictionary<void>* resources;
};
define STATE ((handler_state*)_state)
define THIS(X) ((handler_state*)((handler*) this)->_state)->X
define NAME (_name)
define MODE (STATE->_mode)
define GARB (STATE->_garb)
define LGARB ((light_garbage*)((handler*)this)->_garb)
define ETC (STATE->_etc)
define REGISTER(X) \
if (!_state) ((handler*)this)->_state = (void*) new handler_state; \
if (!GARB) GARB = new hush_garbage; \
GARB->_register(X)
ifndef CIAO
define LREGISTER(X) \
if (!LGARB) LGARB = new light_garbage; \
LGARB->_register(X)
else
define LREGISTER(X)
endif
define VAL ((handler*) ETC ->el )
int handler::_no = 0;
IO& handler::out(const char* opts) const {
opts = opts;
if (!_out) _out = IO::_default;
return *_out;
}
IO& handler::err(const char* opts) const {
opts = opts;
if (!_err) _err = IO::_default;
if (!_err) _err = IO::_default = new IO;
return *_err;
}
IO& handler::in(const char* opts) const {
opts = opts;
if (!_in) _in = IO::_default;
return *_in;
}
void handler::_declare(const handler* h) const { REGISTER(h); }
void handler::_register(const obscure* h) const { LREGISTER(h); }
void handler::_register(const handler* h) const { LREGISTER(h); }
void handler::_register(const term* p) const { LREGISTER(p); }
void handler::_register(const char* p) const { LREGISTER(p); }
void handler::_register(const dvstring* p) const { LREGISTER(p); }
ifndef NOLIST
void handler::_register(const dvlist_type* p) const { REGISTER(p); }
endif
void handler::_register(const iter_type* p) const { REGISTER(p); }
void handler::_register(const dictionary_type* p) const { REGISTER(p); }
void handler::_register(const garbage_type* p) const { REGISTER(p); }
void handler::_register(const dvbinding* p) const { REGISTER(p); }
void handler::_register(const srv_type* p) const { REGISTER(p); }
void handler::_register(const clt_type* p) const { REGISTER(p); }
void handler::_register(const vm_type* p) const { REGISTER(p); }
/ CORE(AE):
//If the member initializations are taken out core follows
handler::handler() {
handler::created++;
_vmp = 0;
_name = 0;
_state = 0; // new handler_state;
_event = 0; tk = 0;
_garb = 0; // ...
tk = kit::_default;
}
handler::~handler() {
handler::_cleanup();
//if (LGARB) { delete (light_garbage*) LGARB; LGARB = 0; }
if (_state && (--STATE->refs == 0)) delete STATE;
handler::deleted++;
}
void handler::_cleanup(const char* opts) const {
opts = opts; // AE for future refinement
if (LGARB) { delete (light_garbage*) LGARB; /*LGARB = 0;*/ }
if (_state && GARB) { delete (hush_garbage*) GARB; GARB = 0; }
}
handler_option& handler::operator[](const char* key) {
handler_option* x = new handler_option(this,key);
_register(x);
return *x;
}
void handler::rename(const char* s) {
if (_context()) _context()->rename(s);
else if (s && _exists()) _this()->rename(s);
else if (s) {
if (NAME) delete[] NAME;
NAME = new char[strlen(s)+1];
strcpy(NAME,s);
}
}
char* handler::name() const {
//if (_context()) return _context()->name(); else
return NAME;
}
char* handler::description() const { return "handler"; }
char* handler::mimetype() const { return "application/x-hush:.sh:"; }
int handler::mode() const { return _state?MODE:0; }
int handler::mode( int i ) {
if (_exists()) return _this()->mode();
else {
if (!_state) _state = new handler_state;
int tmp = MODE;
MODE = i;
return tmp;
}
}
/*
int handler::mode( const char* s ) {
if (_exists()) return _this()->mode(s);
else {
if (!_state) _state = new handler_state;
int tmp = MODE;
if (!strcmp(s,"explicit")) MODE = handler::explic;
else if (!strcmp(s,"implicit")) MODE = handler::implicit;
else _error("mode");
return tmp;
}
}*/
char* handler::category() const { return "hush"; }
char* handler::info() const { return "handler"; } // obsolete
kit* handler::thekit() const {
if (_exists()) return _this()->thekit();
else
return tk?tk: kit::_default;
}
event* handler::dispatch(event* e) {
_event = e;
if (_vmp) {
return ((vm<handler>*)_vmp)->dispatch(e);
} else {
if (e->thekit()) tk = e->thekit(); // AE
int result = this->operator()();
if (result != OK) return 0; // jrvosse
else return _event;
}
}
int handler::operator()() {
require( tk );
if (!_event) return 0; check for event
event* e = _event;
if (tk->tracelevel() > 5) {
err() << "EVENT: " << e->eventclass() << " " <<
e->info() << "(" << event::created << ","
<< event::deleted << ")" << "\n";
}
if (tk->tracelevel() > 3) {
err() << "EVENT " << e->type() << " " << e->name() << "\n";
}
if ( e->type() == ButtonPress ) press(*e);
else if ( e->type() == ButtonRelease ) release(*e);
else if ( e->type() == KeyPress ) keypress(*e);
else if ( e->type() == KeyRelease ) keyrelease(*e);
else if ( e->type() == MotionNotify ) motion(*e);
else if ( e->type() == EnterNotify ) enter(*e);
else if ( e->type() == LeaveNotify ) leave(*e);
else other(*e);
return 0;
}
void handler::other(event&) { }
int handler::verify() const {
if (_exists()) return _this()->verify();
else return 1;
}
void handler::obsolete(const char* s) const {
_obsolete(s);
}
void handler::dependent(handler* h) {
if (_exists()) _this()->dependent(h);
else {
if (!_state) _state = new handler_state;
if (h->contains(this)) {
err() << "ERROR: circular dependency by linking ";
err() << h->name() << " to " << this->name() << "\n";
}
else if (!ETC) {
ETC = new cell(h);
}
else ETC->insert(h);
}
}
void handler::remove(handler* e) {
if (_exists()) _this()->remove(e);
else {
cell* p = (_state && ETC)? ETC : 0;
while (p) {
handler* h = (handler*) p->el;
if (h == e) p->el = 0;
p = p->next;
}
}
}
void handler::process(event* e) {
if (_exists()) _this()->process(e);
else {
event* x = e;
cell* p = (_state && ETC) ? ETC: 0;
handler* h = p ? (handler*) p->el : 0;
while (h && p) {
x = h->dispatch(x);
p = p->next;
h = p ? (handler*) p->el : 0;
}
}
}
int handler::contains(handler* h) {
if (_exists()) return _this()->contains(h);
else
return (STATE && ETC)?ETC->contains(h):0;
}
void handler::option(const char* k, const char* v) {
if (_exists()) _this()->option(k,v);
else {
int x = 0; // option(k);
if (!x && v) {
if (!_state) _state = new handler_state();
if (!STATE->s_options) {
STATE->s_options = new dictionary<dvstring>;
_register( STATE->s_options);
}
dvstring* p = new dvstring(v);
STATE->s_options->_register(p);
(*STATE->s_options)[k] = p;
}
}
}
char* handler::option(const char* k) {
if (_exists()) return _this()->option(k);
else if (k) {
dvstring* result = 0;
if (STATE && !STATE->s_options) result = 0;
else result = (*STATE->s_options)[k];
if (result) return *result;
else return 0;
}
else return 0;
}
void handler::_option(const char* s, int n) {
if (_exists()) _this()->_option(s,n);
else {
int x = _option(s);
if (!x && n) {
if (!_state) _state = new handler_state();
if (!STATE->i_options) {
STATE->i_options = new dictionary<int>;
_register( STATE->i_options);
}
int* p = new int(n);
STATE->i_options->_register(p);
(*STATE->i_options)[s] = p;
}
}
}
int handler::_option(const char* s) {
if (_exists()) return _this()->_option(s);
else {
int* pn = 0;
int result = 0;
if (STATE && !STATE->i_options) result = 0;
else pn = (*STATE->i_options)[s];
if (pn) return *pn; else result = 0;
return result;
}
}
void handler::_resource(const char* s, handler* p) {
if (_exists()) _this()->_resource(s,p);
else {
if (p) {
if (!_state) _state = new handler_state();
if (!STATE->resources) {
STATE->resources = new dictionary<void>;
_register( STATE->resources );
}
(*STATE->resources)[s] = (void*) p;
}
}
}
handler* handler::_resource(const char* s) {
if (_exists()) return _this()->_resource(s);
else {
void* pn = 0;
if (STATE && STATE->resources)
pn = (*STATE->resources)[s];
return (handler*) pn;
}
}
/ Utilities
char* handler::flatten(int argc, char* argv[]) const {
char* buf = new char [BUFSIZ]; LEAK!
char temp[BUFSIZ];
buf[0]='\0';
if (argc > 0) { strcpy(buf,*argv++); argc--; }
while (--argc >= 0) {
temp[0] = '\0';
sprintf(temp,"%s %s",buf,*argv++);
strcpy(buf,temp);
}
return buf;
}
static int check(const char* s) {
int b = 0; const char* p = s;
while (!b && *p) if (*p++ == ' ') b = 1;
return b;
}
char* handler::quote(int argc, char* argv[]) const {
char* buf = new char [BUFSIZ]; LEAK!
char temp[BUFSIZ];
buf[0]='\0';
if (argc > 0) { strcpy(buf,*argv++); argc--; }
while (--argc >= 0) {
temp[0] = '\0';
if (check(*argv))
sprintf(temp,"%s {%s}",buf,*argv++);
else
sprintf(temp,"%s %s",buf,*argv++);
strcpy(buf,temp);
}
return buf;
}
char* handler::gensym(const char* s) const {
char* buf = new char [BUFSIZ]; LEAK!
if (!s)
sprintf(buf,"handler%d",++handler::_no);
else
sprintf(buf,"%s%d",s,++handler::_no);
return buf;
}
/ The handler 'dispatch logic' for inner and outer contexts
int handler::invariant() const { // private _body(), _context() is virt
return ((_body() != this) && (_context() != this) &&
(_self() != this) && !(_body() && _context()) );
}
/ Meta handlers
handler* handler::_redirect(handler* x) { // to inner component
//AE require( invariant() );
require( x && x != this );
if (!_state) _state = new handler_state();
STATE->_slf = x;
//promise( invariant() );
return this;
}
void handler::_reparent(handler* x) { // to outer component
require( x && x != this && invariant() );
if (!_state) _state = new handler_state();
handler* h = x->_context();
if (h) {
require( h != this );
STATE->_ctx = h;
}
else
STATE->_ctx = x;
_debug("_reparent");
promise( handler::invariant() );
}
void handler::_alias(handler* x) { // Any idea?
require( x && x != this && invariant() );
if (!_state) _state = new handler_state();
handler* h = x->_body();
if (h) {
require( h != this );
STATE->_bdy = h;
}
else
STATE->_bdy = x;
_debug("_alias");
promise( handler::invariant() );
}
/ To check whether there is an inner or outer context
handler* handler::_body() const { return 0; } // private - override!!
int handler::_exists() const {
return _this() != this;
} // private
handler* handler::_this() const { // private -- as an example
return (handler*) this;
}
/ Public access functions -- non virtual
handler* handler::_context() const {
//require( invariant() );
return STATE?STATE->_ctx:0;
}
handler* handler::_self() const {
//require( invariant() );
return STATE?STATE->_slf:0;
}
// Notification
void handler::_write(const char* s, const char* msg ) const {
//err()
cerr << "(" << category() << ") "
<< info() << "::" << s << " "
<< msg << " (" << name() << ")"
<< " <" << (void*)this << ", " << _body() << ". " << _context() << ">" << "\n";
}
void* handler::_error(const char* s, const char* msg ) const {
err() << "ERROR: "; _write(s,msg);
return 0;
}
void handler::_warning(const char* s, const char* msg ) const {
err() << "WARNING: "; _write(s,msg);
}
void handler::_debug(const char* s, const char* msg ) const {
if (session::_trace > 3 ) {
cerr << "DEBUG: "; _write(s,msg);
//err() << "DEBUG: "; _write(s,msg);
}
}
void handler::_obsolete(const char* s, const char* msg ) const {
err() << "OBSOLETE: "; _write(s,msg);
}
// unquote
char* handler::unquote(const char* s) const {
static char buf[1024*10];
if (!s) return 0;
char* p = (char*) s; int i=0;
while ( p && *p != 0 ) {
if ( *p != '\'' && *p != '\\' ) buf[i++] = *p++;
else p++;
}
buf[i]='\0';
strcpy((char*)s,buf);
return (char*) s;
}
long handler::eval(const char* cmd) { return tk?tk->eval(cmd):0; }
char* handler::evaluate(const char* cmd) { return tk?tk->evaluate(cmd):0; }
char* handler::result(long id) { return tk?tk->result(id):0; }
void handler::result(const char* s) {
if (_event) _event->result(s);
}
#undef cerr
#undef cout
#undef ostream
include <fstream.h>
void handler::fileout(const char* f, const char* s) {
if (f && s) {
ofstream out(f);
if (out.fail()) {
cerr << "handler::fileout fail " << f << endl;
} else {
out << s << endl;
}
}
}
include <hush/agent.h>
static char file_result[1024];
char* handler::filein(const char* f) {
if (!agent::_default) {
agent::_default = new agent();
_register(agent::_default);
}
char* x = agent::_default->source(f);
ifstream in;
in.open(x);
if (in.fail()) {
cerr << "handler::filein fail " << f << endl;
} else {
in >> (char*) file_result;
return (char*) file_result;
}
return 0;
}
|
Hush Online Technology
hush@cs.vu.nl
11/03/98 |
|
|