rev 737 - in trunk: . include/prothon modules/OS src
SVN User <[email protected]> Thu, 15 Jul 2004 01:46:53 -0400
| Newsgroups | gmane.comp.lang.prothon.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: mark
Date: 2004-07-15 01:46:48 -0400 (Thu, 15 Jul 2004)
New Revision: 737
Modified:
trunk/STATUS.txt
trunk/include/prothon/prothon.h
trunk/include/prothon/prothon_dll.h
trunk/modules/OS/OS.c
trunk/src/builtins-file.c
trunk/src/object.c
Log:
added process object with methods, untested
Modified: trunk/STATUS.txt
===================================================================
--- trunk/STATUS.txt 2004-07-14 22:26:33 UTC (rev 736)
+++ trunk/STATUS.txt 2004-07-15 05:46:48 UTC (rev 737)
@@ -1,15 +1,16 @@
----------------------- TO-DO (highest priority first) ------------------------
---- add pOpen, pOpen2, pOpen3, & pOpen4 to os module
+--- add Process object to os module
--- write regression app in Prothon
+--- check all PEPs
+--- revisit all methods to change list returns into generators
+
--- bug in simple instantiation in the console in 710
---- revisit all methods to change list returns into generators
+--- getAttr, delAttr, getAttrNoProp, setAttrNoProp, & delAttrNoProp
---- check all PEPs
-
--- check into tcl and twisted about async io
--- -o optimize cmd-line option to remove asserts
Modified: trunk/include/prothon/prothon.h
===================================================================
--- trunk/include/prothon/prothon.h 2004-07-14 22:26:33 UTC (rev 736)
+++ trunk/include/prothon/prothon.h 2004-07-15 05:46:48 UTC (rev 737)
@@ -340,6 +340,8 @@
MUTEX_PROTO, // Mutex
PARMPTR_PROTO, //
PROP_PROTO, //
+ FILE_PROTO, //
+ TEXTFILE_PROTO, //
// Exceptions
EXCEPTION, // Exception
@@ -558,6 +560,10 @@
// Clobbers binary data in dest object (copy)
void copy_object_data(isp ist, obj_p copy, obj_p obj);
+// SET_FILE_OBJ_DATA: low-level routine to create a file object
+void set_file_obj_data(isp ist, obj_p file_obj, obj_p filename, obj_p mode,
+ apr_file_t *fp, int bufsize, apr_int32_t flags);
+
// SET_TYPE_IF_EXC: Set data type and owner, throw exception if already set
#define SET_TYPE_IF_EXC(owner, obj, type) \
if ((obj)->data_type != DATA_TYPE_NONE) \
@@ -1096,13 +1102,16 @@
#define SEQ_OR_PARAM(index, var) /* obj_p var; */ \
- if ( has_proto(ist, ITEM, OBJ(STRING_PROTO)) || \
- !has_proto(ist, ITEM, OBJ(SEQ_PROTO))) { \
+do { obj_p list, item = index > 0 ? parms[((index)-1)*2+1] : \
+ list_item(ist, parms[1], -index); \
+ if ( has_proto(ist, item, OBJ(STRING_PROTO)) || \
+ !has_proto(ist, item, OBJ(SEQ_PROTO))) { \
list = NEW_LIST(1); \
- list_append(ist, list, ITEM); \
+ list_append(ist, list, item); \
(var) = list; \
} else \
- (var) = ITEM
+ (var) = item; \
+} while (FALSE)
// FORM_RPARAM: convenience macro for single formal right parameter
// Defines a formal label/default-value list that matches func(rparam).
Modified: trunk/include/prothon/prothon_dll.h
===================================================================
--- trunk/include/prothon/prothon_dll.h 2004-07-14 22:26:33 UTC (rev 736)
+++ trunk/include/prothon/prothon_dll.h 2004-07-15 05:46:48 UTC (rev 737)
@@ -135,7 +135,10 @@
i32_t (*int2i32t)(isp ist, obj_p self);
i64_t (*int2i64t)(isp ist, obj_p self);
char* (*pr2c_strptr)(isp ist, obj_p str_obj);
+ void (*set_file_obj_data)(isp ist, obj_p file_obj, obj_p filename, obj_p mode,
+ apr_file_t *fp, int bufsize, apr_int32_t flags);
+
void* (*pr_malloc)(size_t nbytes);
void* (*pr_realloc)(void *p, size_t nbytes);
void (*pr_free)(void *p);
@@ -372,6 +375,7 @@
#define int2i64t (*services->int2i64t)
#define int2i32t (*services->int2i32t)
#define pr2c_strptr (*services->pr2c_strptr)
+#define set_file_obj_data (*services->set_file_obj_data)
#endif // OBJECT_H
Modified: trunk/modules/OS/OS.c
===================================================================
--- trunk/modules/OS/OS.c 2004-07-14 22:26:33 UTC (rev 736)
+++ trunk/modules/OS/OS.c 2004-07-15 05:46:48 UTC (rev 737)
@@ -58,15 +58,48 @@
// note: to build this in windows, define NO_APR
MODULE_DECLARE(os);
+MODULE_DECLARE(Process);
+#define PROC_STDIN 1
+#define PROC_STDOUT 2
+#define PROC_STDERR 4
+#define PROC_WAIT 8
+#define PROC_SHELLCMD 16
+#define PROC_COPYENV 32
+#define PROC_COPYENVPATH 64
+#define PROC_DAEMON 128
+
+MODULE_CONSTANT_DECLARE(os, STDIN );
+MODULE_CONSTANT_DECLARE(os, STDOUT );
+MODULE_CONSTANT_DECLARE(os, STDERR );
+MODULE_CONSTANT_DECLARE(os, WAIT );
+MODULE_CONSTANT_DECLARE(os, SHELLCMD );
+MODULE_CONSTANT_DECLARE(os, COPYENV );
+MODULE_CONSTANT_DECLARE(os, COPYENVPATH );
+MODULE_CONSTANT_DECLARE(os, DAEMON );
+
MODULE_START(os)
{
os_OBJ = NEW_OBJ(NULL);
MODULE_SET_DOC(os, "Operating System specific routines");
set_obj_id(os_OBJ, *, os);
MODULE_ADD_TO_BASE(os);
+
+ Process_OBJ = NEW_OBJ(NULL);
+ MODULE_SET_DOC(Process, "Operating System Process Object Prototype");
+ MODULE_ADD_TO_BASE(Process);
+
+ MODULE_CONSTANT_INT(os, STDIN , PROC_STDIN );
+ MODULE_CONSTANT_INT(os, STDOUT , PROC_STDOUT );
+ MODULE_CONSTANT_INT(os, STDERR , PROC_STDERR );
+ MODULE_CONSTANT_INT(os, WAIT , PROC_WAIT );
+ MODULE_CONSTANT_INT(os, SHELLCMD , PROC_SHELLCMD );
+ MODULE_CONSTANT_INT(os, COPYENV , PROC_COPYENV );
+ MODULE_CONSTANT_INT(os, COPYENVPATH , PROC_COPYENVPATH );
+ MODULE_CONSTANT_INT(os, DAEMON , PROC_DAEMON );
}
+//**************************** os *******************************************
DEF(os, system, FPARM1(cmd, NULL)) {
if (!has_proto(ist, parms[1], OBJ(STRING_PROTO))) {
ist->exception_obj = NEW_OBJ(OBJ(TYPE_EXC));
@@ -77,10 +110,213 @@
return NEW_INT(system(pr2c_strptr(ist, parms[1])));
}
+//**************************** Process ***************************************
+typedef struct {
+ data_size_t size;
+ apr_pool_t* pool;
+ apr_proc_t proc;
+} proc_t;
+
+typedef proc_t* proc_p;
+
+#define MAX_ARGV_ARGS 128
+#define MAX_ENV_VARS 512
+
+#define SIGKILL 11 // stolen from APR private.h, is this right???
+
+DEF(Process, init_, FPARM4(argV, OBJ(NODEF), flags, NEW_INT(0), dir, OBJ(NONE), env, OBJ(NONE))) {
+ apr_status_t aprerr;
+ apr_procattr_t* attr;
+ apr_pool_t* pool;
+ obj_p argv_list, env_list=NULL, dir;
+ int i, arg_len, env_len, flags;
+ int stdin_flg=APR_NO_PIPE, stdout_flg=APR_NO_PIPE, stderr_flg=APR_NO_PIPE;
+ apr_cmdtype_e cmd_type = 0;
+ proc_p procp;
+ char *argv_arr[MAX_ARGV_ARGS], *env_arr[MAX_ENV_VARS];
+
+ BIN_EMPTY_CHK();
+ SEQ_OR_PARAM(1, argv_list);
+ arg_len = (int) list_len(ist, argv_list);
+ if (arg_len >= MAX_ARGV_ARGS) {
+ raise_exception(ist, OBJ(VALUE_EXC), "%d args is more than the max of %d", arg_len, MAX_ARGV_ARGS-1);
+ return NULL;
+ }
+ for (i=0; i < arg_len; i++) {
+ obj_p str_obj = list_item(ist, argv_list, i);
+ CHECK_TYPE_EXC(str_obj, OBJ(STRING_PROTO), String);
+ argv_arr[i] = pr2c_strptr(ist, str_obj);
+ }
+ argv_arr[i] = NULL;
+ INT_32_PARAM(2, flags);
+ if ((flags & (PROC_STDIN|PROC_STDOUT|PROC_STDERR)) && (flags & PROC_WAIT)) {
+ raise_exception(ist, OBJ(VALUE_EXC), "flags argument cannot specify pipes and WAIT");
+ return NULL;
+ }
+ i = 0;
+ if (flags & PROC_SHELLCMD ) { cmd_type = APR_SHELLCMD; i++; }
+ if (flags & PROC_COPYENV ) { cmd_type = APR_PROGRAM_ENV; i++; }
+ if (flags & PROC_COPYENVPATH) { cmd_type = APR_PROGRAM_PATH; i++; }
+ if (i > 1) {
+ raise_exception(ist, OBJ(VALUE_EXC), "flags can only have one of SHELLCMD, COPYENV, & COPYENVPATH");
+ return NULL;
+ }
+ dir = parms[5];
+ if (dir == OBJ(NONE)) dir = NULL;
+ if (parms[7] != OBJ(NONE)) {
+ SEQ_OR_PARAM(4, env_list);
+ env_len = (int) list_len(ist, env_list);
+ if (env_len >= MAX_ENV_VARS) {
+ raise_exception(ist, OBJ(VALUE_EXC), "%d env vars is more than the max of %d", env_len, MAX_ENV_VARS-1);
+ return NULL;
+ }
+ for (i=0; i < env_len; i++) {
+ obj_p str_obj = list_item(ist, argv_list, i);
+ CHECK_TYPE_EXC(str_obj, OBJ(STRING_PROTO), String);
+ env_arr[i] = pr2c_strptr(ist, str_obj);
+ }
+ env_arr[i] = NULL;
+ }
+ aprerr = apr_pool_create(&pool, get_pr_head_pool());
+ IF_APR_ERR("out of memory in Process init_") return NULL;
+
+ aprerr = apr_procattr_create(&attr, pool);
+ IF_APR_ERR("error in apr_procattr_create") return NULL;
+
+ if (flags & PROC_STDIN) stdin_flg = APR_FULL_BLOCK;
+ if (flags & PROC_STDOUT) stdout_flg = APR_FULL_BLOCK;
+ if (flags & PROC_STDERR) stderr_flg = APR_FULL_BLOCK;
+ aprerr = apr_procattr_io_set(attr, stdin_flg, stdout_flg, stderr_flg);
+ IF_APR_ERR("error in apr_procattr_io_set") return NULL;
+
+ if (dir) {
+ char* path = pr2c_strptr(ist, get_attr(ist, dir, sym(ist, "path")));
+ aprerr = apr_procattr_dir_set(attr, path);
+ IF_APR_ERR("error in apr_procattr_dir_set") return NULL;
+ }
+ if (cmd_type) {
+ aprerr = apr_procattr_cmdtype_set(attr, cmd_type);
+ IF_APR_ERR("error in apr_procattr_cmdtype_set") return NULL;
+ }
+ if (flags & PROC_DAEMON) {
+ aprerr = apr_procattr_detach_set(attr, APR_PROC_DETACH_DAEMONIZE);
+ IF_APR_ERR("error in apr_procattr_detach_set") return NULL;
+ }
+ procp = self->data.ptr = pr_malloc(sizeof(proc_t));
+ DATA_SIZE(self) = (data_size_t) sizeof(proc_t);
+ procp->pool = pool;
+
+ aprerr = apr_proc_create(&procp->proc, argv_arr[0], argv_arr, env_arr, attr, pool);
+ IF_APR_ERR("error in apr_proc_create") return NULL;
+
+ set_attr(ist, self, SYM(NAME_), NEW_STRING(argv_arr[0]));
+ set_attr(ist, self, sym(ist, "pid"), NEW_INT(procp->proc.pid));
+
+ if (flags & PROC_STDIN) {
+ obj_p file_obj = NEW_OBJ(OBJ(TEXTFILE_PROTO));
+ SET_TYPE_IF_EXC(OBJ(TEXTFILE_PROTO), file_obj, DATA_TYPE_DATAPTR) return NULL;
+ set_file_obj_data( ist, file_obj, NEW_STRING("stdInPipe"), NEW_STRING("w"),
+ procp->proc.in, 0, APR_WRITE );
+ set_attr(ist, file_obj, sym(ist, "encoding"), NEW_STRING("ASCII"));
+ file_obj->unclonable = TRUE;
+ set_attr(ist, self, sym(ist, "stdInPipe"), file_obj);
+ }
+ if (flags & PROC_STDOUT) {
+ obj_p file_obj = NEW_OBJ(OBJ(TEXTFILE_PROTO));
+ SET_TYPE_IF_EXC(OBJ(TEXTFILE_PROTO), file_obj, DATA_TYPE_DATAPTR) return NULL;
+ set_file_obj_data( ist, file_obj, NEW_STRING("stdOutPipe"), NEW_STRING("r"),
+ procp->proc.out, 0, APR_READ );
+ set_attr(ist, file_obj, sym(ist, "encoding"), NEW_STRING("ASCII"));
+ file_obj->unclonable = TRUE;
+ set_attr(ist, self, sym(ist, "stdOutPipe"), file_obj);
+ }
+ if (flags & PROC_STDERR) {
+ obj_p file_obj = NEW_OBJ(OBJ(TEXTFILE_PROTO));
+ SET_TYPE_IF_EXC(OBJ(TEXTFILE_PROTO), file_obj, DATA_TYPE_DATAPTR) return NULL;
+ set_file_obj_data( ist, file_obj, NEW_STRING("stdErrPipe"), NEW_STRING("r"),
+ procp->proc.err, 0, APR_READ );
+ set_attr(ist, file_obj, sym(ist, "encoding"), NEW_STRING("ASCII"));
+ file_obj->unclonable = TRUE;
+ set_attr(ist, self, sym(ist, "stdErrPipe"), file_obj);
+ }
+}
+
+DEF(Process, str_, NULL) {
+ char *name, buf[300];
+ if (self == Process_OBJ) return NEW_STRING("<Process:prototype>");
+ BIN_STR_CHK(Process);
+ name = pr2c_strptr(ist, get_attr(ist, self, SYM(NAME_)));
+ apr_snprintf(buf, sizeof(buf), "<Process:%s>", name);
+ return NEW_STRING(buf);
+}
+
+DEF(Process, running_QUES, FPARM1(retCodes, OBJ(PR_FALSE))) {
+ apr_status_t aprerr;
+ proc_p procp;
+ int exitcode;
+ obj_p res = NULL;
+ apr_exit_why_e exit_why;
+ BIN_CONTENT_CHK(Process);
+ procp = self->data.ptr;
+ aprerr = apr_proc_wait(&procp->proc, &exitcode, &exit_why, APR_NOWAIT);
+ IF_APR_ERR("error in apr_proc_wait") return NULL;
+ if (aprerr & APR_CHILD_DONE) res = OBJ(PR_FALSE);
+ if (aprerr & APR_CHILD_NOTDONE) res = OBJ(PR_TRUE);
+ if (res && parms[1] == OBJ(PR_TRUE)) {
+ obj_p tuple = NEW_TUPLE(3);
+ list_append(ist, tuple, res);
+ list_append(ist, tuple, NEW_INT(exitcode));
+ list_append(ist, tuple, NEW_INT(exit_why));
+ return tuple;
+ } else if (res)
+ return res;
+ raise_exception(ist, OBJ(INTERNAL_EXC), "invalid return status from apr_proc_wait: %d", aprerr);
+ return NULL;
+}
+
+DEF(Process, wait, FPARM1(retCodes, OBJ(PR_FALSE))) {
+ apr_status_t aprerr;
+ proc_p procp;
+ int exitcode;
+ apr_exit_why_e exit_why;
+
+ BIN_CONTENT_CHK(Process);
+ procp = self->data.ptr;
+ aprerr = apr_proc_wait(&procp->proc, &exitcode, &exit_why, APR_WAIT);
+ IF_APR_ERR("error in apr_proc_wait") return NULL;
+ if (parms[1] == OBJ(PR_TRUE)) {
+ obj_p tuple = NEW_TUPLE(2);
+ list_append(ist, tuple, NEW_INT(exitcode));
+ list_append(ist, tuple, NEW_INT(exit_why));
+ return tuple;
+ } else
+ NEW_INT(exitcode);
+}
+
+DEF(Process, kill, FPARM1(sig, NEW_INT(SIGKILL))) {
+ apr_status_t aprerr;
+ proc_p procp;
+ int sig;
+
+ BIN_CONTENT_CHK(Process);
+ INT_32_PARAM(1, sig);
+ procp = self->data.ptr;
+ aprerr = apr_proc_kill(&procp->proc, sig);
+ IF_APR_ERR("error in apr_proc_kill") return NULL;
+ return self;
+}
+
+//**************************** MODULE INIT **********************************
MAIN_MODULE_INIT(os)
{
MODULE_SUB_INIT(os);
MODULE_ADD_SYM(os, system);
+ MODULE_ADD_SYM(Process, init_);
+ MODULE_ADD_SYM(Process, str_);
+ MODULE_ADD_SYM(Process, running_QUES);
+ MODULE_ADD_SYM(Process, wait);
+ MODULE_ADD_SYM(Process, kill);
+
check_exceptions(ist);
}
Modified: trunk/src/builtins-file.c
===================================================================
--- trunk/src/builtins-file.c 2004-07-14 22:26:33 UTC (rev 736)
+++ trunk/src/builtins-file.c 2004-07-15 05:46:48 UTC (rev 737)
@@ -65,6 +65,7 @@
#define MIN_BUFSIZE 65536
typedef struct {
+ data_size_t size;
apr_file_t *stream; /* APR file reference */
int bufsize; /* Size of our buffer */
apr_pool_t *pool; /* Pool associated with this file */
@@ -91,7 +92,7 @@
MODULE_DECLARE(StdErr);
//*************************** set_file_obj_data *******************************
-static void set_file_obj_data( isp ist, obj_p file_obj, obj_p filename, obj_p mode,
+void set_file_obj_data( isp ist, obj_p file_obj, obj_p filename, obj_p mode,
apr_file_t *fp, int bufsize, apr_int32_t flags) {
apr_status_t aprerr;
apr_pool_t *subpool = NULL;
@@ -136,11 +137,11 @@
if (bufsize < MIN_BUFSIZE)
bufsize = MIN_BUFSIZE;
-
- filep->bufsize = bufsize;
- filep->stream = fp;
- filep->pool = subpool;
- filep->flags = flags;
+ filep->size = sizeof(file_t);
+ filep->bufsize = bufsize;
+ filep->stream = fp;
+ filep->pool = subpool;
+ filep->flags = flags;
file_obj->data.ptr = filep;
file_obj->rd_access = ACC_USER1;
file_obj->wr_access = ACC_USER1;
@@ -624,7 +625,7 @@
MODULE_START(File)
{
- File_OBJ = NEW_OBJ(NULL);
+ File_OBJ = OBJ(FILE_PROTO);
set_obj_doc(File_OBJ, "File object prototype");
MODULE_ADD_TO_BASE(File);
@@ -1250,7 +1251,7 @@
MODULE_START(TextFile)
{
- TextFile_OBJ = NEW_OBJ(File_OBJ);
+ TextFile_OBJ = OBJ(TEXTFILE_PROTO);
set_obj_doc(TextFile_OBJ, "TextFile object prototype");
MODULE_ADD_TO_BASE(TextFile);
Modified: trunk/src/object.c
===================================================================
--- trunk/src/object.c 2004-07-14 22:26:33 UTC (rev 736)
+++ trunk/src/object.c 2004-07-15 05:46:48 UTC (rev 737)
@@ -210,6 +210,7 @@
dll_services.pr2c_strptr = pr2c_strptr;
dll_services.proto_owns_binary = proto_owns_binary;
dll_services.obj_set_data_owner = obj_set_data_owner;
+ dll_services.set_file_obj_data = set_file_obj_data;
/* Setup the core objects. Order counts here */
OBJ(OBJECT) = NEW_OBJ(NULL);
@@ -231,11 +232,13 @@
OBJ(SLICE_PROTO) = NEW_OBJ(NULL);
OBJ(LOCAL_PROTO) = NEW_OBJ(NULL);
OBJ(OUTER_PROTO) = NEW_OBJ(NULL);
- OBJ(SUPER_PROTO) = NEW_OBJ(NULL);
+ OBJ(SUPER_PROTO) = NEW_OBJ(NULL);
OBJ(THREAD_PROTO) = NEW_OBJ(NULL);
OBJ(MUTEX_PROTO) = NEW_OBJ(NULL);
OBJ(PARMPTR_PROTO) = NEW_OBJ(NULL);
OBJ(PROP_PROTO) = NEW_OBJ(NULL);
+ OBJ(FILE_PROTO) = NEW_OBJ(NULL);
+ OBJ(TEXTFILE_PROTO) = NEW_OBJ(NULL);
OBJ(ROOT_GLOBALS) = NEW_OBJ(NULL);
OBJ(MODULES) = NEW_OBJ(NULL);
OBJ(SYS) = NEW_OBJ(NULL);