rev 625 - in trunk: . include/prothon pr/test src
SVN User <[email protected]> Tue, 15 Jun 2004 03:11:29 -0400
| Newsgroups | gmane.comp.lang.prothon.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: mark
Date: 2004-06-15 03:11:26 -0400 (Tue, 15 Jun 2004)
New Revision: 625
Modified:
trunk/STATUS.txt
trunk/include/prothon/prothon.h
trunk/pr/test/test.pr
trunk/src/builtins-file.c
Log:
most file methods are implemented, TextFile is started
Modified: trunk/STATUS.txt
===================================================================
--- trunk/STATUS.txt 2004-06-14 22:47:58 UTC (rev 624)
+++ trunk/STATUS.txt 2004-06-15 07:11:26 UTC (rev 625)
@@ -2,12 +2,17 @@
----------------------- TO-DO (highest priority first) ------------------------
--- Complete File/Dir objects
+ set times, get times, perms, attrs
+ use 'b' in all files
http://www.prothon.org/pipermail/prothon-user/2004-April/000955.html
--- TextFile object
http://www.prothon.org/pipermail/prothon-user/2004-June/001863.html
--- support any object that supports file methods in stdxxx (duck std)
http://www.prothon.org/pipermail/prothon-user/2004-June/001769.html
+--- Python regrets from Paul and print proposal
+ http://www.prothon.org/pipermail/prothon-user/2004-June/001970.html
+
--- implement 1xc3fe ?
--- check immutable bit for default param values or make new default object each use
Modified: trunk/include/prothon/prothon.h
===================================================================
--- trunk/include/prothon/prothon.h 2004-06-14 22:47:58 UTC (rev 624)
+++ trunk/include/prothon/prothon.h 2004-06-15 07:11:26 UTC (rev 625)
@@ -981,17 +981,25 @@
(var) = int2i64t(ist, index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)); }
i64_t int2i64t(isp ist, obj_p self);
-#define STRING_PARAM(index, var) \
+#define BYTES__PARAM(index, var) /* obj_p var; */ \
+{ obj_p __pobj = ( index > 0 ? parms[((index)-1)*2+1] : \
+ list_item(ist, parms[1], -index)); \
+ if (!has_proto(ist, __pobj, OBJ(BYTES_PROTO))) { \
+ raise_exception( ist, OBJ(TYPE_EXC), \
+ "expected bytes in parameter " #index ); \
+ return NULL; \
+ } var = __pobj; }
+
+#define STRING_PARAM(index, var) /* char* var; */ \
{ if (!has_proto(ist, (index > 0 ? parms[((index)-1)*2+1] : \
list_item(ist, parms[1], -index)), OBJ(STRING_PROTO))) { \
raise_exception(ist, OBJ(TYPE_EXC), \
"expected a string in parameter " #index); \
return NULL; \
} (var) = pr2c_strptr(ist, (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index))); }
-
#define FUNC___PARAM(index, var) /* obj_p var; */ \
-{ if (!has_proto(ist, (index > 0 ? parms[((index)-1)*2+1] : \
+{ if (!has_proto(ist, (index > 0 ? parms[((index)-1)*2+1] : \
list_item(ist, parms[1], -index)) , \
OBJ(FUNC_PROTO))) { \
raise_exception(ist, OBJ(TYPE_EXC), \
Modified: trunk/pr/test/test.pr
===================================================================
--- trunk/pr/test/test.pr 2004-06-14 22:47:58 UTC (rev 624)
+++ trunk/pr/test/test.pr 2004-06-15 07:11:26 UTC (rev 625)
@@ -1,5 +1,4 @@
#!/usr/bin/env prothon
-
/*
d = Dir()
print 'dir:',d, ' len:', len(d), d.path, d.name
@@ -7,12 +6,27 @@
print '--- dirs ---'
dirs = d.dirs()
for i in d.numDirs():
- print "{0:-40.40} {1:-30.30}".fmt(dirs[i].path, dirs[i].name)
+ print "{0:-60.60} {1:17.17}".fmt(dirs[i].path, dirs[i].name)
print
print '--- files ---'
files = d.files()
for i in d.numFiles():
- print "{0:-40.40} {1:-30.30}".fmt(files[i].path, files[i].name)
+ print "{0:-60.60} {1:17.17}".fmt(files[i].path, files[i].name)
print
+
+files[2].open('r')
+print files[2].read()
+files[2].close()
*/
-print TempDir()
\ No newline at end of file
+
+File("abc/test").delete()
+f = File("abc/test.txt")
+print f, f.exists?(), f.closed?()
+f.open('w')
+print f, f.exists?(), f.closed?()
+f.write(x"303132")
+print f, f.exists?(), f.closed?()
+f.close()
+print f, f.exists?(), f.closed?()
+
+
Modified: trunk/src/builtins-file.c
===================================================================
--- trunk/src/builtins-file.c 2004-06-14 22:47:58 UTC (rev 624)
+++ trunk/src/builtins-file.c 2004-06-15 07:11:26 UTC (rev 625)
@@ -69,27 +69,28 @@
int bufsize; /* Size of our buffer */
apr_pool_t *pool; /* Pool associated with this file */
apr_int32_t flags; /* APR flags */
-} pr_file_t;
+} file_t;
-typedef pr_file_t* pr_file_p;
+typedef file_t* file_p;
-#define STREAM(obj) (((pr_file_p)((obj)->data.ptr))->stream)
-#define BUFSIZE(obj) (((pr_file_p)((obj)->data.ptr))->bufsize)
-#define POOL(obj) (((pr_file_p)((obj)->data.ptr))->pool)
-#define FLAGS(obj) (((pr_file_p)((obj)->data.ptr))->flags)
+#define STREAM(obj) (((file_p)((obj)->data.ptr))->stream)
+#define BUFSIZE(obj) (((file_p)((obj)->data.ptr))->bufsize)
+#define POOL(obj) (((file_p)((obj)->data.ptr))->pool)
+#define FLAGS(obj) (((file_p)((obj)->data.ptr))->flags)
#define OPEN(obj) (((obj) != File_OBJ) && STREAM(obj))
MODULE_DECLARE(Dir);
MODULE_DECLARE(TempDir);
MODULE_DECLARE(File);
+MODULE_DECLARE(TextFile);
//*************************** set_file_obj_data *******************************
static 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;
- pr_file_p filep;
- char* temp, *p2, *p1, *p0, *p, *dirpath;
+ file_p filep;
+ char* temp, *p2, *p1, *p0, *p, *fullpath;
obj_p new_obj;
if (fp)
@@ -99,29 +100,29 @@
IF_APR_ERR("out of memory in set_file_obj_data()") return;
}
temp = pr2c_strptr(ist, filename);
- p0 = temp;
- p2 = p0 + strlen(p0);
- if (*(p2-1) == '/') {
- aprerr = apr_filepath_merge( &dirpath, NULL, temp,
- APR_FILEPATH_TRUENAME, subpool );
+ if (strcmp(temp, "<stdin>") && strcmp(temp, "<stdout>") && strcmp(temp, "<stderr>")) {
+ aprerr = apr_filepath_merge( &fullpath, NULL, temp,
+ APR_FILEPATH_TRUENAME, subpool );
IF_APR_ERR("error in filepath_merge") return;
+ } else
+ fullpath = temp;
#ifdef WIN32
- for(p=dirpath; *p; p++) *p = tolower(*p);
+ for(p=fullpath; *p; p++) *p = tolower(*p);
#endif
- set_attr(ist, file_obj, sym(ist, "path"), NEW_STRING(dirpath));
- p0 = dirpath;
- p2 = p0 + strlen(p0) - 1;
- } else
- set_attr(ist, file_obj, sym(ist, "path"), filename);
+ set_attr(ist, file_obj, sym(ist, "path"), NEW_STRING(fullpath));
+
+ p0 = fullpath;
+ p2 = p0 + strlen(p0);
+ if (*(p2-1) == '/') p2--;
for (p1=p2-1; p1 >= p0 && *p1 != '/'; p1--);
if (*p1 != '/') new_obj = NEW_STRING("");
- else new_obj = NEW_STRINGN(p1+1, p2-p1-1);
+ else new_obj = NEW_STRINGN(p1+1, p2-p1-1);
set_attr(ist, file_obj, sym(ist, "name"), new_obj);
if (mode)
set_attr(ist, file_obj, sym(ist, "mode"), mode);
- filep = pr_malloc(sizeof(pr_file_t));
+ filep = pr_malloc(sizeof(file_t));
if (bufsize < MIN_BUFSIZE)
bufsize = MIN_BUFSIZE;
@@ -171,7 +172,7 @@
apr_status_t aprerr;
const char *dirpath, *destpath = NULL;
char *filepath, *filepath2;
- pr_file_p filep;
+ file_p filep;
obj_p uperms_obj = NULL, res = OBJ(NONE);
i64_t count = 0;
filep = self->data.ptr;
@@ -290,7 +291,7 @@
DEF(Dir, exists_QUES, NULL) {
apr_finfo_t finfo;
char* path;
- pr_file_p filep;
+ file_p filep;
BIN_CONTENT_CHK(Dir);
filep = self->data.ptr;
path = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
@@ -303,7 +304,7 @@
apr_status_t aprerr;
char* path;
i32_t uperms;
- pr_file_p filep;
+ file_p filep;
BIN_CONTENT_CHK(Dir);
INT_32_PARAM(1, uperms);
filep = self->data.ptr;
@@ -317,7 +318,7 @@
apr_status_t aprerr;
const char *rootpath, *filepath;
char *temp, *tempp, *respath;
- pr_file_p filep;
+ file_p filep;
BIN_CONTENT_CHK(Dir);
filep = self->data.ptr;
filepath = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
@@ -338,7 +339,7 @@
DEF(Dir, isRoot_QUES, NULL) {
apr_status_t aprerr;
const char *rootpath, *filepath;
- pr_file_p filep;
+ file_p filep;
BIN_CONTENT_CHK(Dir);
filep = self->data.ptr;
filepath = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
@@ -381,7 +382,7 @@
DEF(Dir, rename, FPARM1(name, NULL)) {
apr_status_t aprerr;
char *name, *dirpath, *p;
- pr_file_p filep;
+ file_p filep;
BIN_CONTENT_CHK(Dir);
STRING_PARAM(1, name);
filep = self->data.ptr;
@@ -399,7 +400,7 @@
DEF(Dir, move, FPARM1(dir, NULL)) {
apr_status_t aprerr;
char *dirpath1, *dirpath2;
- pr_file_p filep;
+ file_p filep;
BIN_CONTENT_CHK(Dir);
CHECK_TYPE_EXC(parms[1], Dir_OBJ, Directory);
filep = self->data.ptr;
@@ -414,7 +415,7 @@
apr_status_t aprerr;
i32_t uperms;
char* path;
- pr_file_p filep;
+ file_p filep;
BIN_CONTENT_CHK(Dir);
CHECK_TYPE_EXC(parms[1], Dir_OBJ, Directory);
INT_32_PARAM(2, uperms);
@@ -429,7 +430,7 @@
DEF(Dir, delete, NULL) {
apr_status_t aprerr;
char* path;
- pr_file_p filep;
+ file_p filep;
BIN_CONTENT_CHK(Dir);
filep = self->data.ptr;
dir_list(ist, self, -1, DLIST_DELETE, NULL, NULL, 0);
@@ -460,11 +461,11 @@
return self;
}
-DEF(Dir, setFileAttrs, FPARM3(readOnly, OBJ(NONE), executable, OBJ(NONE), hidden, OBJ(NONE))) {
+DEF(Dir, setAttrs, FPARM3(readOnly, OBJ(NONE), executable, OBJ(NONE), hidden, OBJ(NONE))) {
apr_status_t aprerr;
char* path;
int attrs = 0, attrs_mask = 0;
- pr_file_p filep;
+ file_p filep;
BIN_CONTENT_CHK(Dir);
filep = self->data.ptr;
if (parms[1] == OBJ(PR_TRUE)) {
@@ -514,7 +515,7 @@
apr_temp_dir_get(&temp_dir_path, subpool);
set_file_obj_data( ist, TempDir_OBJ, NEW_STRING(temp_dir_path),
NULL, NULL, 0, APR_READ );
- SET_TYPE_IF_EXC(TempDir_OBJ, TempDir_OBJ, DATA_TYPE_DATAPTR) return;
+ SET_TYPE_IF_EXC(Dir_OBJ, TempDir_OBJ, DATA_TYPE_DATAPTR) return;
MODULE_ADD_TO_BASE(TempDir);
set_unclonable(TempDir_OBJ);
}
@@ -554,8 +555,8 @@
raise_exception(ist, OBJ(TYPE_EXC), "setUPerms() not allowed on TempDir");
return NULL;
}
-DEF(TempDir, setFileAttrs, FPARM3(readOnly, OBJ(NONE), executable, OBJ(NONE), hidden, OBJ(NONE))) {
- raise_exception(ist, OBJ(TYPE_EXC), "setFileAttrs() not allowed on TempDir");
+DEF(TempDir, setAttrs, FPARM3(readOnly, OBJ(NONE), executable, OBJ(NONE), hidden, OBJ(NONE))) {
+ raise_exception(ist, OBJ(TYPE_EXC), "setAttrs() not allowed on TempDir");
return NULL;
}
@@ -571,7 +572,7 @@
}
DEF(File, init_, FPARM3( path, NULL,
- mode, NEW_STRING("r"),
+ mode, NEW_STRING(""),
bufsize, NEW_INT(-1) ) ) {
apr_file_t *f;
apr_status_t aprerr;
@@ -586,6 +587,15 @@
STRING_PARAM(2, mode);
INT_32_PARAM(3, bufsize);
+ if (strlen(mode) == 0) {
+ read_unlock(ist, self);
+ SET_TYPE_IF_EXC(File_OBJ, self, DATA_TYPE_DATAPTR) return NULL;
+ set_file_obj_data(ist, self, parms[1], NULL, NULL, 0, 0);
+ read_lock(ist, self);
+ self->unclonable = TRUE;
+ return OBJ(NONE);
+ }
+
if ((mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') ||
(mode[1] != '+' && mode[1] != '\0')) {
raise_exception(ist, OBJ(TYPE_EXC), "File mode `%s' is not valid", mode);
@@ -619,9 +629,6 @@
apr_pool_destroy(subpool);
return NULL;
}
-
- /* set_file_obj_data(ist, ) modified the object, and thus calls write_lock.
- * We need to unlock in order to avoid a deadlock */
read_unlock(ist, self);
SET_TYPE_IF_EXC(File_OBJ, self, DATA_TYPE_DATAPTR) return NULL;
set_file_obj_data(ist, self, parms[1], parms[3], f, bufsize, flags);
@@ -639,6 +646,206 @@
return NEW_STRING(buf);
}
+DEF(File, exists_QUES, NULL) {
+ apr_finfo_t finfo;
+ char *path;
+ file_p filep;
+ BIN_CONTENT_CHK(File);
+ filep = self->data.ptr;
+ if (OPEN(self)) return OBJ(PR_TRUE);
+ path = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
+ apr_stat(&finfo, path, APR_FINFO_MIN, filep->pool);
+ if (finfo.filetype == APR_REG) return OBJ(PR_TRUE);
+ else return OBJ(PR_FALSE);
+ return OBJ(NONE);
+}
+
+DEF(File, rename, FPARM1(name, NULL)) {
+ apr_status_t aprerr;
+ char *name, *path, *p;
+ file_p filep;
+ BIN_CONTENT_CHK(File);
+ STRING_PARAM(1, name);
+ if (OPEN(self)) {
+ raise_exception( ist, OBJ(IO_EXC), "attempt to rename an open file");
+ return NULL;
+ }
+ for (p=name; *p; p++)
+ if (*p == '/' || *p == '\\') {
+ raise_exception( ist, OBJ(VALUE_EXC), "slash chars not allowed in file name: \"%s\"", name);
+ return NULL;
+ }
+ path = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
+ filep = self->data.ptr;
+ aprerr = apr_file_rename(path, name, filep->pool);
+ IF_APR_ERR("renaming a file") return NULL;
+ return new_file_obj(ist, name);
+}
+
+DEF(File, move, FPARM1(dir, NULL)) {
+ apr_status_t aprerr;
+ obj_p res;
+ char *srcfilepath, *filename, *dstpath, *dstfilepath;
+ file_p filep;
+ BIN_CONTENT_CHK(File);
+ CHECK_TYPE_EXC(parms[1], Dir_OBJ, Directory);
+ if (OPEN(self)) {
+ raise_exception( ist, OBJ(IO_EXC), "attempt to move an open file");
+ return NULL;
+ }
+ filep = self->data.ptr;
+ srcfilepath = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
+ filename = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "name")));
+ dstpath = pr2c_strptr(ist, get_attr(ist, parms[1], sym(ist, "path")));
+ dstfilepath = pr_malloc(strlen(dstpath) + strlen(filename) + 1);
+ strcpy(dstfilepath, dstpath); strcat(dstfilepath, filename);
+ aprerr = apr_file_rename(srcfilepath, dstfilepath, filep->pool);
+ IF_APR_ERR("moving a file") return NULL;
+ res = new_file_obj(ist, dstfilepath, NULL, NULL, 0, 0);
+ pr_free(dstfilepath);
+ return res;
+}
+
+DEF(File, copy, FPARM2(file, NULL, uperms, NEW_INT(APR_UREAD|APR_UWRITE|APR_UEXECUTE))) {
+ apr_status_t aprerr;
+ i32_t uperms;
+ char* path1, path2;
+ file_p filep;
+ BIN_CONTENT_CHK(File);
+ CHECK_TYPE_EXC(parms[1], File_OBJ, File);
+ INT_32_PARAM(2, uperms);
+ filep = self->data.ptr;
+ path1 = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
+ path2 = pr2c_strptr(ist, get_attr(ist, parms[1], sym(ist, "path")));
+ aprerr = apr_file_copy(path1, path2, uperms, filep->pool);
+ IF_APR_ERR("copying file") return NULL;
+ return parms[1];
+}
+
+DEF(File, delete, NULL) {
+ apr_status_t aprerr;
+ char* path;
+ file_p filep;
+ BIN_CONTENT_CHK(File);
+ if (OPEN(self)) {
+ raise_exception( ist, OBJ(IO_EXC), "attempt to delete an open file");
+ return NULL;
+ }
+ filep = self->data.ptr;
+ path = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
+ aprerr = apr_file_remove(path, filep->pool );
+ IF_APR_ERR("deleting file") return NULL;
+ return self;
+}
+
+DEF(File, eq__QUES, FORM_RPARAM) {
+ obj_p self_path, other_path;
+ BIN_CONTENT_CHK(File);
+ CHECK_TYPE_EXC(parms[1], File_OBJ, Directory);
+ self_path = get_attr(ist, self, sym(ist, "path"));
+ other_path = get_attr(ist, parms[1], sym(ist, "path"));
+ return call_func1(ist, self_path, SYM(EQ__QUES), other_path);
+}
+
+DEF(File, setUPerms, FPARM1(uperms, NEW_INT(APR_UREAD|APR_UWRITE|APR_UEXECUTE))) {
+ apr_status_t aprerr;
+ char* path;
+ int uperms;
+ BIN_CONTENT_CHK(File);
+ INT_32_PARAM(1, uperms);
+ path = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
+ aprerr = apr_file_perms_set(path, uperms);
+ IF_APR_ERR("setting unix permissions") return NULL;
+ return self;
+}
+
+DEF(File, setAttrs, FPARM3(readOnly, OBJ(NONE), executable, OBJ(NONE), hidden, OBJ(NONE))) {
+ apr_status_t aprerr;
+ char* path;
+ int attrs = 0, attrs_mask = 0;
+ file_p filep;
+ BIN_CONTENT_CHK(File);
+ filep = self->data.ptr;
+ if (parms[1] == OBJ(PR_TRUE)) {
+ attrs |= APR_FILE_ATTR_READONLY; attrs_mask |= APR_FILE_ATTR_READONLY; }
+ if (parms[3] == OBJ(PR_TRUE)) {
+ attrs |= APR_FILE_ATTR_EXECUTABLE; attrs_mask |= APR_FILE_ATTR_EXECUTABLE; }
+ if (parms[5] == OBJ(PR_TRUE)) {
+ attrs |= APR_FILE_ATTR_HIDDEN; attrs_mask |= APR_FILE_ATTR_HIDDEN; }
+ if (parms[1] == OBJ(PR_FALSE)) attrs_mask |= APR_FILE_ATTR_READONLY;
+ if (parms[3] == OBJ(PR_FALSE)) attrs_mask |= APR_FILE_ATTR_EXECUTABLE;
+ if (parms[5] == OBJ(PR_FALSE)) attrs_mask |= APR_FILE_ATTR_HIDDEN;
+ path = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
+ aprerr = apr_file_attrs_set(path, attrs, attrs_mask, filep->pool );
+ IF_APR_ERR("setting file attributes") return NULL;
+ return self;
+}
+
+DEF(File, open, FPARM2( mode, NEW_STRING(""),
+ bufsize, NEW_INT(-1) ) ) {
+ apr_file_t *f;
+ apr_status_t aprerr;
+ apr_int32_t flags = 0;
+ char err_buf[1024];
+ char *path, *mode;
+ int bufsize;
+ file_p filep;
+
+ BIN_CONTENT_CHK(File);
+ STRING_PARAM(1, mode);
+ INT_32_PARAM(2, bufsize);
+ if (OPEN(self)) {
+ raise_exception(ist, OBJ(TYPE_EXC), "file is already open");
+ return NULL;
+ }
+ filep = self->data.ptr;
+ path = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
+
+ if (strlen(mode) == 0) {
+ read_unlock(ist, self);
+ SET_TYPE_IF_EXC(File_OBJ, self, DATA_TYPE_DATAPTR) return NULL;
+ set_file_obj_data(ist, self, parms[1], NULL, NULL, 0, 0);
+ read_lock(ist, self);
+ self->unclonable = TRUE;
+ return OBJ(NONE);
+ }
+
+ if ((mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') ||
+ (mode[1] != '+' && mode[1] != '\0')) {
+ raise_exception(ist, OBJ(TYPE_EXC), "File mode `%s' is not valid", mode);
+ return NULL;
+ }
+
+ if (mode[0] == 'r') {
+ flags = APR_READ;
+ if (mode[1] == '+')
+ flags |= APR_WRITE;
+ } else if (mode[0] == 'w') {
+ flags = APR_WRITE | APR_CREATE | APR_TRUNCATE;
+ if (mode[1] == '+')
+ flags |= APR_READ;
+ } else if (mode[0] == 'a') {
+ flags = APR_WRITE | APR_CREATE | APR_APPEND;
+ if (mode[1] == '+')
+ flags |= APR_READ;
+ }
+
+ aprerr = apr_file_open(&f, path, flags, APR_OS_DEFAULT, filep->pool);
+ if (aprerr != APR_SUCCESS) {
+ raise_exception(ist, OBJ(IO_EXC), "Unable to open path %s: %s",
+ path, apr_strerror(aprerr, err_buf, sizeof(err_buf)));
+ return NULL;
+ }
+
+ if (bufsize < MIN_BUFSIZE)
+ bufsize = MIN_BUFSIZE;
+
+ filep->bufsize = bufsize;
+ filep->stream = f;
+ filep->flags = flags;
+ return OBJ(NONE);
+}
+
DEF(File, close, NULL) {
BIN_CONTENT_CHK(File);
if (OPEN(self)) {
@@ -675,31 +882,336 @@
}
return OBJ(NONE);
}
-#if 0
-DEF(File, fileNo, NULL) {
+DEF(File, read, FPARM1(size, NEW_INT(-1))) {
+ int readall = FALSE;
+ size_t size, total_read=0, num_read;
+ obj_p byt_obj;
+ byt_p obj_str;
+ u8_t* buf;
+ apr_status_t aprerr;
+ char err_buf[1024];
+ i64_t size_in;
+
BIN_CONTENT_CHK(File);
+ INT_64_PARAM(1, size_in);
+
if (!has_proto(ist, self, File_OBJ)) {
- raise_exception(ist, OBJ(TYPE_EXC), "fileNo can only be called on a File object");
+ raise_exception(ist, OBJ(TYPE_EXC), "read can only be called on a File object");
return NULL;
}
if (!OPEN(self)) {
- raise_exception(ist, OBJ(IO_EXC), "fileNo called on closed file");
+ raise_exception(ist, OBJ(IO_EXC), "read called on closed file");
return NULL;
}
- return NEW_INT(_fileno(STREAM(self)));
+ if (!(FLAGS(self) & APR_READ)) {
+ raise_exception(ist, OBJ(IO_EXC), "read called on file opened without read perms");
+ return NULL;
+ }
+ if (!size_in) return NEW_BYTES(NULL, 0);
+ if (size_in < 0) {
+ readall = TRUE;
+ size = BUFSIZE(self);
+ } else
+ size = (size_t) size_in;
+ byt_obj = NEW_OBJ(OBJ(BYTES_PROTO));
+ if (size < IMM_DATA_LEN) {
+ SET_TYPE_IF_EXC(OBJ(BYTES_PROTO), byt_obj, DATA_TYPE_IMMDATA) return NULL;
+ buf = byt_obj->data.bytes;
+ } else {
+ obj_str = obj_malloc(ist, OBJ(BYTES_PROTO), byt_obj, sizeof(str_t)+size+1);
+ buf = obj_str->byt;
+ }
+ num_read = size;
+ aprerr = apr_file_read(STREAM(self), buf, &num_read);
+ if (aprerr != APR_SUCCESS && aprerr != APR_EOF) {
+ raise_exception(ist, OBJ(IO_EXC), "%s",
+ apr_strerror(aprerr, err_buf, sizeof(err_buf)));
+ return NULL;
+ }
+ total_read += num_read;
+ while(aprerr != APR_EOF && (readall || total_read < size)) {
+ size_t next_read = (readall ? size : size - total_read);
+ size_t new_len = total_read + next_read;
+ if (byt_obj->data_type == DATA_TYPE_IMMDATA && new_len >= IMM_DATA_LEN) {
+ obj_str = obj_malloc(ist, OBJ(BYTES_PROTO), byt_obj, sizeof(str_t)+new_len+1);
+ buf = obj_str->byt;
+ } else {
+ obj_str = obj_realloc(ist, byt_obj, sizeof(str_t)+new_len+1);
+ buf = obj_str->byt;
+ }
+ num_read = next_read;
+ aprerr = apr_file_read(STREAM(self), buf + total_read, &num_read);
+ if (aprerr != APR_SUCCESS && aprerr != APR_EOF) {
+ raise_exception(ist, OBJ(IO_EXC), "%s",
+ apr_strerror(aprerr, err_buf, sizeof(err_buf)));
+ return NULL;
+ }
+ total_read += num_read;
+ }
+ if (byt_obj->data_type == DATA_TYPE_IMMDATA)
+ byt_obj->imm_data_len = (int) total_read;
+ else {
+ obj_str = obj_realloc(ist, byt_obj, sizeof(str_t)+total_read+1);
+ obj_str->len = (data_size_t) total_read;
+ buf = obj_str->byt;
+ }
+ buf[total_read] = 0;
+ byt_obj->immutable = TRUE;
+ return byt_obj;
}
-DEF(File, isATty_QUES, NULL) {
+DEF(File, seek, FPARM2( pos, NULL,
+ how, NEW_INT(0) ) ) {
+ apr_off_t pos;
+ apr_seek_where_t origin;
+ apr_status_t aprerr;
+ char err_buf[1024];
+ i64_t pos_in, how;
+
BIN_CONTENT_CHK(File);
+ INT_64_PARAM(1, pos_in);
+ INT_64_PARAM(2, how);
+
+ if (!has_proto(ist, self, File_OBJ)) {
+ raise_exception(ist, OBJ(TYPE_EXC), "seek can only be called on a File object");
+ return NULL;
+ }
if (!OPEN(self)) {
- raise_exception(ist, OBJ(IO_EXC), "isatty called on closed stream");
+ raise_exception(ist, OBJ(IO_EXC), "seek called on closed file");
return NULL;
}
- if (_isatty(_fileno(STREAM(self)))) return OBJ(PR_TRUE);
- else return OBJ(PR_FALSE);
+ pos = (apr_off_t)pos_in;
+ switch(how) {
+ case 0: origin = APR_SET; break;
+ case 1: origin = APR_CUR; break;
+ case 2: origin = APR_END; break;
+ default :
+ raise_exception(ist, OBJ(TYPE_EXC), "file seek how parameter must be 0, 1, or 2");
+ return NULL;
+ }
+
+ aprerr = apr_file_seek(STREAM(self), origin, &pos);
+ if (aprerr != APR_SUCCESS) {
+ raise_exception(ist, OBJ(IO_EXC), "%s",
+ apr_strerror(aprerr, err_buf, sizeof(err_buf)));
+ return NULL;
+ }
+ return OBJ(NONE);
}
-#endif
-DEF(File, read, FPARM1(size, NEW_INT(-1))) {
+
+DEF(File, truncate, FPARM1(size, NULL)) {
+ apr_status_t aprerr;
+ char err_buf[1024];
+ apr_off_t size;
+ i64_t size_in;
+
+ BIN_CONTENT_CHK(File);
+ INT_64_PARAM(1, size_in);
+
+ if (!has_proto(ist, self, File_OBJ)) {
+ raise_exception(ist, OBJ(TYPE_EXC), "truncate can only be called on a File object");
+ return NULL;
+ }
+ if (!OPEN(self)) {
+ raise_exception(ist, OBJ(IO_EXC), "truncate called on closed file");
+ return NULL;
+ }
+
+ /* XXX Need a way to check for upper bounds portably. This can be
+ * different on 64-bit systems, or systems which support LFS */
+ if (size_in < 0) {
+ raise_exception(ist, OBJ(TYPE_EXC), "file truncate size value out of range");
+ return NULL;
+ }
+ size = (apr_off_t)(size_in);
+
+ aprerr = apr_file_trunc(STREAM(self), size);
+ if(aprerr != APR_SUCCESS) {
+ raise_exception(ist, OBJ(IO_EXC), "%s",
+ apr_strerror(aprerr, err_buf, sizeof(err_buf)));
+ return NULL;
+ }
+ return OBJ(NONE);
+}
+
+DEF(File, write, FPARM1(bytes, NULL)) {
+ apr_size_t size;
+ apr_status_t aprerr;
+ char err_buf[1024];
+ obj_p bytes;
+ u8_t* byts;
+
+ BIN_CONTENT_CHK(File);
+ BYTES__PARAM(1, bytes);
+ byts = bytes_ptr(bytes);
+ size = bytes_len(bytes);
+
+ if (!has_proto(ist, self, File_OBJ)) {
+ raise_exception(ist, OBJ(TYPE_EXC), "write can only be called from a File object");
+ return NULL;
+ }
+ if (!OPEN(self)) {
+ raise_exception(ist, OBJ(IO_EXC), "write called on closed file");
+ return NULL;
+ }
+ if (!(FLAGS(self) & APR_WRITE)) {
+ raise_exception(ist, OBJ(IO_EXC), "write called on file opened without write perms");
+ return NULL;
+ }
+ aprerr = apr_file_write(STREAM(self), byts, &size);
+ if (aprerr != APR_SUCCESS) {
+ raise_exception(ist, OBJ(IO_EXC), "%s",
+ apr_strerror(aprerr, err_buf, sizeof(err_buf)));
+ return NULL;
+ }
+ return parms[1];
+}
+
+DEF(File, setStdOut, FORM_RPARAM) {
+ int i;
+ if (!has_proto(ist, parms[1], File_OBJ)) {
+ raise_exception(ist, OBJ(TYPE_EXC), "stdout can only be assigned to a file object");
+ return NULL;
+ }
+ su(i); read_unlock(ist, self);
+ set_attr(ist, self, sym(ist, "stdout"), parms[1]);
+ un_su(i); read_lock(ist, self);
+ return parms[1];
+}
+
+#define __STDIN 0
+#define __STDOUT 1
+#define __STDERR 2
+
+static obj_p __open_std_file(int type, apr_pool_t *subpool)
+{
+ obj_p mode, file;
+ apr_file_t *fp;
+ apr_status_t aprerr;
+ apr_int32_t flags;
+
+ switch (type) {
+ case __STDIN:
+ aprerr = apr_file_open_stdin(&fp, subpool);
+ mode = NEW_STRING("r");
+ file = NEW_STRING("<stdin>");
+ flags = APR_READ;
+ break;
+
+ case __STDOUT:
+ aprerr = apr_file_open_stdout(&fp, subpool);
+ file = NEW_STRING("<stdout>");
+ mode = NEW_STRING("w");
+ flags = APR_WRITE;
+ break;
+
+ case __STDERR:
+ aprerr = apr_file_open_stderr(&fp, subpool);
+ file = NEW_STRING("<stderr>");
+ mode = NEW_STRING("w");
+ flags = APR_WRITE;
+ break;
+
+ default:
+ return NULL; /* XXX something stupid, do an error */
+ }
+
+ if (aprerr != APR_SUCCESS)
+ return NULL;
+
+ return new_file_obj(ist, file, mode, fp, MIN_BUFSIZE, flags);
+}
+
+DEF(File, objList_, FORM_RPARAM) {
+ return parms[1];
+}
+
+//*************************** MODULE TextFile *************************************
+
+MODULE_START(TextFile)
+{
+ TextFile_OBJ = NEW_OBJ(File_OBJ);
+ set_obj_doc(TextFile_OBJ, "TextFile object prototype");
+
+ MODULE_ADD_TO_BASE(TextFile);
+ TextFile_OBJ->unclonable = TRUE;
+}
+
+DEF(TextFile, init_, FPARM3( path, NULL,
+ mode, NEW_STRING(""),
+ bufsize, NEW_INT(-1) ) ) {
+ apr_file_t *f;
+ apr_status_t aprerr;
+ apr_pool_t *subpool;
+ apr_int32_t flags = 0;
+ char err_buf[1024];
+ char *path, *mode;
+ int bufsize;
+
+ BIN_EMPTY_CHK();
+ STRING_PARAM(1, path);
+ STRING_PARAM(2, mode);
+ INT_32_PARAM(3, bufsize);
+
+ if (strlen(mode) == 0) {
+ read_unlock(ist, self);
+ SET_TYPE_IF_EXC(TextFile_OBJ, self, DATA_TYPE_DATAPTR) return NULL;
+ set_file_obj_data(ist, self, parms[1], NULL, NULL, 0, 0);
+ read_lock(ist, self);
+ self->unclonable = TRUE;
+ return OBJ(NONE);
+ }
+
+ if ((mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') ||
+ (mode[1] != '+' && mode[1] != '\0')) {
+ raise_exception(ist, OBJ(TYPE_EXC), "TextFile mode `%s' is not valid", mode);
+ return NULL;
+ }
+
+ if (mode[0] == 'r') {
+ flags = APR_READ;
+ if (mode[1] == '+')
+ flags |= APR_WRITE;
+ } else if (mode[0] == 'w') {
+ flags = APR_WRITE | APR_CREATE | APR_TRUNCATE;
+ if (mode[1] == '+')
+ flags |= APR_READ;
+ } else if (mode[0] == 'a') {
+ flags = APR_WRITE | APR_CREATE | APR_APPEND;
+ if (mode[1] == '+')
+ flags |= APR_READ;
+ }
+
+ aprerr = apr_pool_create(&subpool, get_pr_head_pool());
+ if (aprerr != APR_SUCCESS) {
+ raise_exception(ist, OBJ(OUTOFMEMORY_EXC), "Out of memory opening files");
+ return NULL;
+ }
+
+ aprerr = apr_file_open(&f, path, flags, APR_OS_DEFAULT, subpool);
+ if (aprerr != APR_SUCCESS) {
+ raise_exception(ist, OBJ(IO_EXC), "Unable to open path %s: %s",
+ path, apr_strerror(aprerr, err_buf, sizeof(err_buf)));
+ apr_pool_destroy(subpool);
+ return NULL;
+ }
+ read_unlock(ist, self);
+ SET_TYPE_IF_EXC(TextFile_OBJ, self, DATA_TYPE_DATAPTR) return NULL;
+ set_file_obj_data(ist, self, parms[1], parms[3], f, bufsize, flags);
+ read_lock(ist, self);
+ self->unclonable = TRUE;
+ return OBJ(NONE);
+}
+
+DEF(TextFile, str_, NULL) {
+ char buf[300], *path;
+ BIN_STR_CHK(TextFile);
+ path = pr2c_strptr(ist, get_attr(ist, self, sym(ist, "path")));
+ apr_snprintf(buf, sizeof(buf), "<TextFile:'%s'>", path);
+ pr_free(path);
+ return NEW_STRING(buf);
+}
+DEF(TextFile, read, FPARM1(size, NEW_INT(-1))) {
int readall = FALSE;
size_t size, total_read=0, num_read;
obj_p byt_obj;
@@ -776,8 +1288,7 @@
byt_obj->immutable = TRUE;
return byt_obj;
}
-
-DEF(File, readLine, FPARM1(size, NEW_INT(-1))) {
+DEF(TextFile, readLine, FPARM1(size, NEW_INT(-1))) {
int readall = FALSE;
size_t size, total_read;
obj_p byt_obj;
@@ -853,7 +1364,7 @@
return byt_obj;
}
-DEF(File, readLines, FPARM1(size, NEW_INT(-1))) {
+DEF(TextFile, readLines, FPARM1(size, NEW_INT(-1))) {
int readall = FALSE;
size_t size, total_read=0, num_read;
obj_p byt_obj, list_obj;
@@ -937,90 +1448,7 @@
return list_obj;
}
-DEF(File, seek, FPARM2( pos, NULL,
- how, NEW_INT(0) ) ) {
- apr_off_t pos;
- apr_seek_where_t origin;
- apr_status_t aprerr;
- char err_buf[1024];
- i64_t pos_in, how;
-
- BIN_CONTENT_CHK(File);
- INT_64_PARAM(1, pos_in);
- INT_64_PARAM(2, how);
-
- if (!has_proto(ist, self, File_OBJ)) {
- raise_exception(ist, OBJ(TYPE_EXC), "seek can only be called on a File object");
- return NULL;
- }
- if (!OPEN(self)) {
- raise_exception(ist, OBJ(IO_EXC), "seek called on closed file");
- return NULL;
- }
- pos = (apr_off_t)pos_in;
- switch(how) {
- case 0: origin = APR_SET; break;
- case 1: origin = APR_CUR; break;
- case 2: origin = APR_END; break;
- default :
- raise_exception(ist, OBJ(TYPE_EXC), "file seek how parameter must be 0, 1, or 2");
- return NULL;
- }
-
- aprerr = apr_file_seek(STREAM(self), origin, &pos);
- if (aprerr != APR_SUCCESS) {
- raise_exception(ist, OBJ(IO_EXC), "%s",
- apr_strerror(aprerr, err_buf, sizeof(err_buf)));
- return NULL;
- }
- return OBJ(NONE);
-}
-#if 0
-DEF(File, tell, NULL) {
- BIN_CONTENT_CHK(File);
- if (!OPEN(self)) {
- raise_exception(ist, OBJ(IO_EXC), "tell called on closed file");
- return NULL;
- }
- return NEW_INT(ftell(STREAM(self)));
-}
-#endif
-DEF(File, truncate, FPARM1(size, NULL)) {
- apr_status_t aprerr;
- char err_buf[1024];
- apr_off_t size;
- i64_t size_in;
-
- BIN_CONTENT_CHK(File);
- INT_64_PARAM(1, size_in);
-
- if (!has_proto(ist, self, File_OBJ)) {
- raise_exception(ist, OBJ(TYPE_EXC), "truncate can only be called on a File object");
- return NULL;
- }
- if (!OPEN(self)) {
- raise_exception(ist, OBJ(IO_EXC), "truncate called on closed file");
- return NULL;
- }
-
- /* XXX Need a way to check for upper bounds portably. This can be
- * different on 64-bit systems, or systems which support LFS */
- if (size_in < 0) {
- raise_exception(ist, OBJ(TYPE_EXC), "file truncate size value out of range");
- return NULL;
- }
- size = (apr_off_t)(size_in);
-
- aprerr = apr_file_trunc(STREAM(self), size);
- if(aprerr != APR_SUCCESS) {
- raise_exception(ist, OBJ(IO_EXC), "%s",
- apr_strerror(aprerr, err_buf, sizeof(err_buf)));
- return NULL;
- }
- return OBJ(NONE);
-}
-
-DEF(File, write, FPARM1(str, NULL)) {
+DEF(TextFile, write, FPARM1(str, NULL)) {
apr_size_t size;
apr_status_t aprerr;
char err_buf[1024];
@@ -1052,7 +1480,7 @@
return parms[1];
}
-DEF(File, writeLines, FPARM1(lst, NULL)) {
+DEF(TextFile, writeLines, FPARM1(lst, NULL)) {
char* str;
apr_size_t size;
apr_status_t aprerr;
@@ -1104,65 +1532,7 @@
return parms[1];
}
-DEF(File, setStdOut, FORM_RPARAM) {
- int i;
- if (!has_proto(ist, parms[1], File_OBJ)) {
- raise_exception(ist, OBJ(TYPE_EXC), "stdout can only be assigned to a file object");
- return NULL;
- }
- su(i); read_unlock(ist, self);
- set_attr(ist, self, sym(ist, "stdout"), parms[1]);
- un_su(i); read_lock(ist, self);
- return parms[1];
-}
-#define __STDIN 0
-#define __STDOUT 1
-#define __STDERR 2
-
-static obj_p __open_std_file(int type, apr_pool_t *subpool)
-{
- obj_p mode, file;
- apr_file_t *fp;
- apr_status_t aprerr;
- apr_int32_t flags;
-
- switch (type) {
- case __STDIN:
- aprerr = apr_file_open_stdin(&fp, subpool);
- mode = NEW_STRING("r");
- file = NEW_STRING("<stdin>");
- flags = APR_READ;
- break;
-
- case __STDOUT:
- aprerr = apr_file_open_stdout(&fp, subpool);
- file = NEW_STRING("<stdout>");
- mode = NEW_STRING("w");
- flags = APR_WRITE;
- break;
-
- case __STDERR:
- aprerr = apr_file_open_stderr(&fp, subpool);
- file = NEW_STRING("<stderr>");
- mode = NEW_STRING("w");
- flags = APR_WRITE;
- break;
-
- default:
- return NULL; /* XXX something stupid, do an error */
- }
-
- if (aprerr != APR_SUCCESS)
- return NULL;
-
- return new_file_obj(ist, file, mode, fp, MIN_BUFSIZE, flags);
-}
-
-DEF(File, objList_, FORM_RPARAM) {
- return parms[1];
-}
-
MAIN_MODULE_INIT(File) {
apr_pool_t *std_pool;
apr_status_t aprerr;
@@ -1187,7 +1557,7 @@
MODULE_ADD_SYM(Dir, delete);
MODULE_ADD_SYM(Dir, eq__QUES);
MODULE_ADD_SYM(Dir, setUPerms);
- MODULE_ADD_SYM(Dir, setFileAttrs);
+ MODULE_ADD_SYM(Dir, setAttrs);
MODULE_ADD_SYM(Dir, objList_);
MODULE_SUB_INIT(TempDir);
@@ -1198,24 +1568,39 @@
MODULE_ADD_SYM(TempDir, move);
MODULE_ADD_SYM(TempDir, delete);
MODULE_ADD_SYM(TempDir, setUPerms);
- MODULE_ADD_SYM(TempDir, setFileAttrs);
+ MODULE_ADD_SYM(TempDir, setAttrs);
MODULE_SUB_INIT(File);
MODULE_ADD_SYM(File, init_);
MODULE_ADD_SYM(File, str_);
+ MODULE_ADD_SYM(File, exists_QUES);
+ MODULE_ADD_SYM(File, rename);
+ MODULE_ADD_SYM(File, move);
+ MODULE_ADD_SYM(File, copy);
+ MODULE_ADD_SYM(File, delete);
+ MODULE_ADD_SYM(File, eq__QUES);
+ MODULE_ADD_SYM(File, setUPerms);
+ MODULE_ADD_SYM(File, setAttrs);
MODULE_ADD_SYM(File, read);
- MODULE_ADD_SYM(File, readLine);
- MODULE_ADD_SYM(File, readLines);
MODULE_ADD_SYM(File, write);
- MODULE_ADD_SYM(File, writeLines);
MODULE_ADD_SYM(File, flush);
MODULE_ADD_SYM(File, seek);
MODULE_ADD_SYM(File, truncate);
+ MODULE_ADD_SYM(File, open);
MODULE_ADD_SYM(File, close);
MODULE_ADD_SYM(File, closed_QUES);
MODULE_ADD_SYM(File, setStdOut);
MODULE_ADD_SYM(File, objList_);
+ MODULE_SUB_INIT(TextFile);
+ MODULE_ADD_SYM(TextFile, init_);
+ MODULE_ADD_SYM(TextFile, str_);
+ MODULE_ADD_SYM(TextFile, read);
+ MODULE_ADD_SYM(TextFile, readLine);
+ MODULE_ADD_SYM(TextFile, readLines);
+ MODULE_ADD_SYM(TextFile, write);
+ MODULE_ADD_SYM(TextFile, writeLines);
+
/* Create base file objects for std{in,out,err} */
aprerr = apr_pool_create(&std_pool, get_pr_head_pool());
/* Need some kind of error return! */