/* System module */ /* Various bits of information used by the interpreter are collected in module 'sys'. Data members: - stdin, stdout, stderr: standard file objects - ps1, ps2: primary and secondary prompts (strings) - path: module search path (list of strings) - modules: the table of modules (dictionary) Function members: - exit(sts): call exit() */ #include #include "PROTO.h" #include "object.h" #include "stringobject.h" #include "listobject.h" #include "dictobject.h" #include "fileobject.h" #include "moduleobject.h" #include "sysmodule.h" #include "node.h" /* For context.h */ #include "context.h" /* For import.h */ #include "import.h" #include "methodobject.h" #include "modsupport.h" #include "errors.h" static object *sysdict; object * sysget(name) char *name; { return dictlookup(sysdict, name); } FILE * sysgetfile(name, def) char *name; FILE *def; { FILE *fp = NULL; object *v = sysget(name); if (v != NULL) fp = getfilefile(v); if (fp == NULL) fp = def; return fp; } int sysset(name, v) char *name; object *v; { if (v == NULL) return dictremove(sysdict, name); else return dictinsert(sysdict, name, v); } static object * makeargv(argc, argv) int argc; char **argv; { int i; object *av, *v; if (argc < 0 || argv == NULL) argc = 0; av = newlistobject(argc); if (av != NULL) { for (i = 0; i < argc; i++) { v = newstringobject(argv[i]); if (v == NULL) { DECREF(av); av = NULL; break; } setlistitem(av, i, v); } } if (av == NULL) fatal("no mem for sys.argv"); return av; } /* sys.exit method */ static object * sys_exit(self, args) object *self; object *args; { int sts; if (!getintarg(args, &sts)) return NULL; goaway(sts); exit(sts); /* Just in case */ /* NOTREACHED */ } static object *sysin, *sysout, *syserr; void initsys(argc, argv) int argc; char **argv; { object *v; object *exit; if ((sysdict = newdictobject()) == NULL) fatal("can't create sys dict"); /* NB keep an extra ref to the std files to avoid closing them when the user deletes them */ sysin = newopenfileobject(stdin, "", "r"); sysout = newopenfileobject(stdout, "", "w"); syserr = newopenfileobject(stderr, "", "w"); v = makeargv(argc, argv); exit = newmethodobject("exit", sys_exit, (object *)NULL); if (err_occurred()) fatal("can't create sys.* objects"); dictinsert(sysdict, "stdin", sysin); dictinsert(sysdict, "stdout", sysout); dictinsert(sysdict, "stderr", syserr); dictinsert(sysdict, "argv", v); dictinsert(sysdict, "exit", exit); if (err_occurred()) fatal("can't insert sys.* objects in sys dict"); DECREF(exit); DECREF(v); /* The other symbols are added elsewhere */ /* Only now can we initialize the import stuff, after which we can turn ourselves into a module */ initimport(); if ((v = new_module("sys")) == NULL) fatal("can't create sys module"); if (setmoduledict(v, sysdict) != 0) fatal("can't assign sys dict to sys module"); DECREF(v); } static void cleardict(d) object *d; { int i; for (i = getdictsize(d); --i >= 0; ) { char *k; k = getdictkey(d, i); if (k != NULL) { (void) dictremove(d, k); } } } void closesys() { object *modules; modules = sysget("modules"); if (modules != NULL && is_dictobject(modules)) { int i; /* Explicitly erase all modules; this is the safest way to get rid of at least *some* circular dependencies */ INCREF(modules); for (i = getdictsize(modules); --i >= 0; ) { char *k; k = getdictkey(modules, i); if (k != NULL) { object *m; m = dictlookup(modules, k); if (m != NULL && is_moduleobject(m)) { object *d; d = getmoduledict(m); if (d != NULL && is_dictobject(d)) { cleardict(d); } } } } cleardict(modules); DECREF(modules); } DECREF(sysdict); }