[svn:mod_parrot] r560 - in mod_parrot/trunk: . include lib src/pmc

[email protected] Tue, 30 Dec 2008 14:13:25 -0800 (PST)
Newsgroups perl.cvs.mod_parrot
Message-ID <[email protected]>
Author: jhorwitz
Date: Tue Dec 30 14:13:25 2008
New Revision: 560

Added:
   mod_parrot/trunk/src/pmc/
   mod_parrot/trunk/src/pmc/modparrothandle.pmc
Modified:
   mod_parrot/trunk/CHANGES
   mod_parrot/trunk/Makefile.in
   mod_parrot/trunk/include/mod_parrot.h
   mod_parrot/trunk/lib/mod_parrot.pir

Log:
New ModParrotHandle PMC ties Parrot I/O ops to Apache I/O



Modified: mod_parrot/trunk/CHANGES
==============================================================================
--- mod_parrot/trunk/CHANGES	(original)
+++ mod_parrot/trunk/CHANGES	Tue Dec 30 14:13:25 2008
@@ -27,6 +27,7 @@
          * Various configuration fixes
          * Refactored lots of code to make it easier to maintain
          * Refactored PIR compilation rules in Makefile
+         * New ModParrotHandle PMC ties Parrot I/O ops to Apache I/O
  
        mod_perl6:
          * Replace PIR mod_perl6 with pure-perl mod_perl6

Modified: mod_parrot/trunk/Makefile.in
==============================================================================
--- mod_parrot/trunk/Makefile.in	(original)
+++ mod_parrot/trunk/Makefile.in	Tue Dec 30 14:13:25 2008
@@ -19,6 +19,10 @@
 PARROT_BLIB_DIR=@PARROT_BLIB_DIR@
 PARROT=@PARROT@
 APACHE_INCLUDE_DIR=@APACHE_INCLUDE_DIR@
+PARROT_DYNEXT=$(PARROT_SOURCE)/runtime/parrot/dynext
+BUILD_DYNPMC=$(PERL) $(PARROT_SOURCE)/tools/build/dynpmc.pl
+MODPARROT_GROUP=modparrot_group.so
+export DYNPMC_INCLUDE=$(APACHE_INCLUDE_DIR),../../include
 
 SRC_DIR = src
 TEST_SRC_DIR = t/src
@@ -56,7 +60,11 @@
 	lib/ModParrot/HLL/lolcode.pbc \
 	lib/ModParrot/HLL/nqp.pbc
 
-all: gen-src $(SRC_DIR)/mod_parrot.la libs
+PMCS= modparrothandle
+
+PMC_SOURCES= $(SRC_DIR)/pmc/modparrothandle.pmc
+
+all: gen-src $(SRC_DIR)/mod_parrot.la libs $(MODPARROT_GROUP)
 
 %.lo: %.c
 	$(LIBTOOL) --mode=compile $(CC) -o $@ $(EXTRA_CPPFLAGS) $(DEBUG) $(CFLAGS) -I$(APACHE_INCLUDE_DIR) -I$(APR_INCLUDE_DIR) -I$(APU_INCLUDE_DIR) $(DEFINES) -c $<
@@ -73,6 +81,11 @@
 
 libs: $(MPLIBS)
 
+$(MODPARROT_GROUP): $(PMC_SOURCES)
+	cd $(SRC_DIR)/pmc && $(BUILD_DYNPMC) generate $(PMCS)
+	cd $(SRC_DIR)/pmc && $(BUILD_DYNPMC) compile $(PMCS)
+	cd $(SRC_DIR)/pmc && $(BUILD_DYNPMC) linklibs $(PMCS)
+
 modperl6: languages/perl6/lib/mod_perl6.pir languages/perl6/lib/ModPerl6/Registry.pir
 
 %.pir: %.pm
@@ -94,17 +107,26 @@
 libs-clean: 
 	rm -f $(MPLIBS)
 
+pmcs-clean:
+	rm -f $(SRC_DIR)/pmc/$(MODPARROT_GROUP)
+	rm -f $(SRC_DIR)/pmc/*.c
+	rm -f $(SRC_DIR)/pmc/*.h
+	rm -f $(SRC_DIR)/pmc/*.o
+	rm -f $(SRC_DIR)/pmc/*.dump
+	rm -f $(SRC_DIR)/pmc/*.exp
+
 test-clean:
 	if [ -x t/TEST ]; then t/TEST -clean; fi
 	rm -f t/core.* t/lib/handlers.pbc t/TEST
 
-clean: files-clean libs-clean gen-src-clean modperl6-clean
+clean: files-clean libs-clean pmcs-clean gen-src-clean modperl6-clean
 
 distclean: clean test-clean
 	rm -f Makefile Makefile.old
 
-install: $(SRC_DIR)/mod_parrot.la
+install: $(SRC_DIR)/mod_parrot.la $(MODPARROT_GROUP)
 	$(APXS) -i -n parrot -a $(SRC_DIR)/mod_parrot.la
+	cd $(SRC_DIR)/pmc && $(BUILD_DYNPMC) copy "--destination=$(PARROT_DYNEXT)" $(PMCS)
 
 test: $(SRC_DIR)/mod_parrot.la libs
 	$(PARROT) -o t/lib/handlers.pbc t/lib/handlers.pir

Modified: mod_parrot/trunk/include/mod_parrot.h
==============================================================================
--- mod_parrot/trunk/include/mod_parrot.h	(original)
+++ mod_parrot/trunk/include/mod_parrot.h	Tue Dec 30 14:13:25 2008
@@ -99,5 +99,6 @@
     Parrot_PMC, Parrot_PMC);
 modparrot_context *modparrot_get_current_ctx(apr_pool_t *);
 void modparrot_set_current_ctx(apr_pool_t *, modparrot_context *);
+apr_size_t modparrot_request_read(request_rec *, char *, apr_size_t);
 
 #endif /* _MODPARROT_H */

Modified: mod_parrot/trunk/lib/mod_parrot.pir
==============================================================================
--- mod_parrot/trunk/lib/mod_parrot.pir	(original)
+++ mod_parrot/trunk/lib/mod_parrot.pir	Tue Dec 30 14:13:25 2008
@@ -18,6 +18,8 @@
 
 .include 'iglobals.pasm'
 
+.loadlib 'modparrot_group.so'
+
 # use when NCI can dlfunc from the current image
 .sub modparrot_init
     .local pmc func

Added: mod_parrot/trunk/src/pmc/modparrothandle.pmc
==============================================================================
--- (empty file)
+++ mod_parrot/trunk/src/pmc/modparrothandle.pmc	Tue Dec 30 14:13:25 2008
@@ -0,0 +1,547 @@
+/* $Id $ */
+
+/* Copyright (c) 2008 Jeff Horwitz
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+
+=head1 NAME
+
+src/pmc/modparrothandle.pmc - ModParrotHandle PMC
+
+=head1 DESCRIPTION
+
+=head2 Vtable Functions
+
+=over 4
+
+=cut
+
+*/
+
+#include "parrot/parrot.h"
+#include "../src/io/io_private.h"
+#include "mod_parrot.h"
+#include "httpd.h"
+#include "http_protocol.h"
+
+pmclass ModParrotHandle dynpmc need_ext group modparrot_group {
+    ATTR INTVAL  flags;               /* Filehandle flags             */
+    ATTR STRING *mode;                /* The mode string used in open */
+    ATTR STRING *encoding;            /* The encoding for read/write  */
+    ATTR STRING *filename;            /* A mock path and filename     */
+    ATTR INTVAL  read_offset;         /* Position, for reading bytes  */
+    ATTR PMC    *r;                   /* RequestRec object */
+
+/*
+
+=item C<void init()>
+
+Initializes a newly created ModParrotHandle object.
+
+=cut
+
+*/
+
+    VTABLE void init() {
+        Parrot_ModParrotHandle_attributes *data_struct =
+                mem_allocate_typed(Parrot_ModParrotHandle_attributes);
+
+        PMC_data(SELF)            = data_struct;
+        data_struct->flags        = 0;
+        data_struct->mode         = NULL;
+        data_struct->encoding     = NULL;
+        data_struct->filename     = NULL;
+        data_struct->r            = NULL;
+        data_struct->read_offset  = 0;
+
+        PObj_custom_mark_SET(SELF);
+        PObj_active_destroy_SET(SELF);
+    }
+
+/*
+
+=item C<PMC *clone()>
+
+Create a copy of the handle.
+
+=cut
+
+*/
+
+    VTABLE PMC *clone() {
+        Parrot_ModParrotHandle_attributes * const old_struct  = PARROT_MODPARROTHANDLE(SELF);
+        PMC * const copy = pmc_new(INTERP, SELF->vtable->base_type);
+        Parrot_ModParrotHandle_attributes * const data_struct = PARROT_MODPARROTHANDLE(copy);
+
+        data_struct->flags        = old_struct->flags;
+        data_struct->mode         = string_copy(INTERP, old_struct->mode);
+        data_struct->encoding     = string_copy(INTERP, old_struct->encoding);
+        data_struct->r            = old_struct->r;
+
+        return copy;
+    }
+
+/*
+
+=item C<void mark()>
+
+Mark active modparrothandle data as live.
+
+=cut
+
+*/
+
+    VTABLE void mark() {
+        Parrot_ModParrotHandle_attributes * const data_struct = PARROT_MODPARROTHANDLE(SELF);
+        if (data_struct->r)
+            pobject_lives(interp, (PObj *)data_struct->r);
+        if (data_struct->mode)
+            pobject_lives(interp, (PObj *)data_struct->mode);
+        if (data_struct->encoding)
+            pobject_lives(interp, (PObj *)data_struct->encoding);
+        if (data_struct->filename)
+            pobject_lives(interp, (PObj *)data_struct->filename);
+    }
+
+/*
+
+=item C<void destroy()>
+
+Free structures.
+
+=cut
+
+*/
+    VTABLE void destroy() {
+        if (PARROT_MODPARROTHANDLE(SELF)) {
+            mem_sys_free(PARROT_MODPARROTHANDLE(SELF));
+            PMC_data(SELF) = NULL;
+        }
+    }
+
+/*
+
+=item C<INTVAL get_bool()>
+
+XXX FIXME! -- always true for now
+Returns whether the handle has reached the end of the file.
+
+=cut
+
+*/
+
+    VTABLE INTVAL get_bool() {
+        return 0;
+    }
+
+
+/*
+
+=back
+
+=head2 Methods
+
+=over 4
+
+=item C<METHOD open(PMC *r, STRING *mode :optional)>
+
+Opens a mod_parrot handle using the supplied request_rec with the given mode.
+
+=cut
+
+*/
+
+    METHOD open(PMC *r, STRING *mode :optional, INTVAL got_mode :opt_flag) {
+        STRING *open_mode, *attrname;
+        INTVAL flags;
+        PMC *attrpmc;
+
+        if (PMC_IS_NULL(r)) {
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
+                "Missing RequestRec in ModParrotHandle open");
+        }
+        SET_ATTR_r(INTERP, SELF, r);
+
+        if (got_mode && !STRING_IS_NULL(mode))
+            SET_ATTR_mode(INTERP, SELF, string_copy(INTERP, mode));
+
+        /* Set a default mode of read-write. */
+        GET_ATTR_mode(INTERP, SELF, open_mode);
+        if (STRING_IS_NULL(open_mode)) {
+            open_mode = const_string(INTERP, "r");
+            SET_ATTR_mode(INTERP, SELF, open_mode);
+        }
+
+        flags = Parrot_io_parse_open_flags(interp, open_mode);
+        SET_ATTR_flags(INTERP, SELF, flags);
+
+        RETURN(PMC *SELF);
+    }
+
+/*
+
+=item C<METHOD is_tty()>
+
+ModParrotHandles are never tty's, returns false.
+
+=cut
+
+*/
+    METHOD is_tty() {
+        RETURN(INTVAL 0);
+    }
+
+/*
+
+=item C<METHOD close()>
+
+Resets the request_rec and other core data.
+
+=cut
+
+*/
+
+    METHOD close() {
+        SET_ATTR_r(INTERP, SELF, NULL);
+        SET_ATTR_read_offset(INTERP, SELF, 0);
+        RETURN(INTVAL 0);
+    }
+
+/*
+
+=item C<METHOD is_closed()>
+
+Check if the handle is open.
+
+=cut
+
+*/
+
+    METHOD is_closed() {
+        request_rec *rr = NULL;
+        STRING *attrname = const_string(INTERP, "r");
+        PMC *attrpmc;
+        PMC *r;
+
+        GET_ATTR_r(INTERP, SELF, r)
+        if (r) {
+            attrname = const_string(INTERP, "r");
+            attrpmc = VTABLE_get_attr_str(INTERP, r, attrname);
+            rr = (request_rec *)PMC_data(attrpmc);
+        }
+
+        if (rr)
+            RETURN(INTVAL 1);
+
+        RETURN(INTVAL 0);
+    }
+
+/*
+
+=item C<METHOD read(INTVAL length)>
+
+Read C<length> bytes from the handle.
+
+=cut
+
+*/
+
+    METHOD read(INTVAL length) {
+        INTVAL flags, bytes, offset;
+        STRING *attrname, *str;
+        PMC *attrpmc, *r;
+        request_rec *rr = NULL;
+        char *buf;
+
+        GET_ATTR_r(INTERP, SELF, r);
+        if (!r)
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
+                "Cannot read from a closed filehandle");
+
+        attrname = const_string(INTERP, "r");
+        attrpmc = VTABLE_get_attr_str(INTERP, r, attrname);
+        rr = (request_rec *)PMC_data(attrpmc);
+
+        GET_ATTR_flags(INTERP, SELF, flags);
+        if (!(flags & PIO_F_READ))
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
+                "Cannot read from a filehandle not opened for read");
+
+        buf = (char *)mem_sys_allocate(length);
+        bytes = modparrot_request_read(rr, buf, length);
+
+        if (bytes) {
+            GET_ATTR_read_offset(INTERP, SELF, offset);
+            SET_ATTR_read_offset(INTERP, SELF, offset + bytes);
+            str = string_from_cstring(INTERP, buf, bytes);
+        }
+        else {
+            /* XXX should be a null string */
+            str = string_from_literal(INTERP, "");
+        }
+
+        mem_sys_free(buf);
+
+        RETURN(STRING *str);
+    }
+
+/*
+
+=item C<METHOD readline()>
+
+TODO
+
+=cut
+
+*/
+
+/* readline code here */
+
+/*
+
+=item METHOD readall(STRING *name);
+
+TODO
+
+=cut
+
+*/
+
+/* readall code here */
+
+/*
+
+=item C<METHOD flush()>
+
+TODO
+
+=cut
+
+*/
+
+/* flush code here */
+
+/*
+
+=item C<METHOD print([INTVAL|FLOATVAL|STRING *|PMC*] value)>
+
+Print the passed in integer, number, string, or PMC to the handle.
+(Integers, numbers, and strings are auto-boxed as PMCs.)
+
+=cut
+
+*/
+
+    METHOD print(PMC *to_print) {
+        STRING *string_to_print = VTABLE_get_string(INTERP, to_print);
+        Parrot_io_putps(interp, SELF, string_to_print);
+    }
+
+/*
+
+=item C<METHOD puts(STRING *value)>
+
+Print the string to the handle.
+
+=cut
+
+*/
+
+    METHOD puts(STRING *to_print) {
+        INTVAL flags, status;
+        STRING *attrname;
+        PMC *attrpmc, *r;
+        request_rec *rr = NULL;
+        char *str;
+
+        GET_ATTR_r(INTERP, SELF, r);
+        if (!r)
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
+                "Cannot write to a closed filehandle");
+
+        attrname = const_string(INTERP, "r");
+        attrpmc = VTABLE_get_attr_str(INTERP, r, attrname);
+        rr = (request_rec *)PMC_data(attrpmc);
+
+        GET_ATTR_flags(INTERP, SELF, flags);
+        if (!(flags & PIO_F_WRITE))
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
+                "Cannot write to a filehandle not opened for write");
+
+        str = string_to_cstring(INTERP, to_print);
+        status = ap_rputs(str, rr);
+        string_cstring_free(str);
+
+        RETURN(INTVAL status);
+    }
+
+/*
+
+=item C<METHOD buffer_type(STRING *new_type :optional)>
+
+Set or retrieve the buffering attribute for the handle. This attribute is
+ignored, but stored for mocking.
+
+=cut
+
+*/
+
+    METHOD buffer_type(STRING *new_type :optional, INTVAL got_type :opt_flag) {
+        INTVAL flags;
+        STRING *nobuffer_string   = const_string(INTERP, "unbuffered");
+        STRING *linebuffer_string = const_string(INTERP, "line-buffered");
+        STRING *fullbuffer_string = const_string(INTERP, "full-buffered");
+
+        GET_ATTR_flags(INTERP, SELF, flags);
+
+        if (got_type) {
+            if (string_equal(INTERP, new_type, nobuffer_string) == 0) {
+                flags &= ~ PIO_F_LINEBUF;
+                flags &= ~ PIO_F_BLKBUF;
+            }
+            else if (string_equal(INTERP, new_type, linebuffer_string) == 0) {
+                flags |=   PIO_F_LINEBUF;
+                flags &= ~ PIO_F_BLKBUF;
+            }
+            else if (string_equal(INTERP, new_type, fullbuffer_string) == 0) {
+                flags &= ~ PIO_F_LINEBUF;
+                flags |=   PIO_F_BLKBUF;
+            }
+
+            SET_ATTR_flags(INTERP, SELF, flags);
+        }
+
+        if (flags & PIO_F_LINEBUF)
+            RETURN(STRING *linebuffer_string);
+        else if (flags & PIO_F_BLKBUF)
+            RETURN(STRING *fullbuffer_string);
+        RETURN(STRING *nobuffer_string);
+    }
+
+/*
+
+=item C<METHOD buffer_size(INTVAL new_size :optional)>
+
+Always returns 0 for ModParrotHandle.
+
+=cut
+
+*/
+
+    METHOD buffer_size(INTVAL new_size :optional, INTVAL got_size :opt_flag) {
+        RETURN(INTVAL 0);
+
+    }
+
+/*
+
+=item C<METHOD mode()>
+
+Retrieve the read mode string for the handle.
+
+=cut
+
+*/
+
+    METHOD mode() {
+        STRING *mode, *mode_copy;
+
+        GET_ATTR_mode(INTERP, SELF, mode);
+        mode_copy = string_copy(INTERP, mode);
+
+        RETURN(STRING *mode_copy);
+
+    }
+
+/*
+
+=item C<METHOD encoding(STRING *new_encoding)>
+
+Set or retrieve the encoding attribute (a string name of the selected encoding
+scheme) for the handle.
+
+=cut
+
+*/
+
+    METHOD encoding(STRING *new_encoding :optional, INTVAL got_encoding :opt_flag) {
+        STRING *encoding;
+        STRING *encoding_copy = NULL;
+
+        if (got_encoding) {
+            if (!STRING_IS_NULL(new_encoding))
+                encoding_copy = string_copy(INTERP, new_encoding);
+            SET_ATTR_encoding(INTERP, SELF, encoding_copy);
+            RETURN(STRING *new_encoding);
+        }
+
+        GET_ATTR_encoding(INTERP, SELF, encoding);
+        if (!STRING_IS_NULL(encoding))
+            encoding_copy = string_copy(INTERP, encoding);
+
+        RETURN(STRING *encoding_copy);
+
+    }
+
+/*
+
+=item C<METHOD eof()>
+
+XXX TODO
+Check if the handle is at end-of-file (if it has read to the end of
+the string data).
+
+=cut
+
+*/
+
+    METHOD eof() {
+        RETURN(INTVAL 0);
+    }
+
+
+/*
+
+=item C<METHOD get_fd()>
+
+ModParrotHandles do not use integer file descriptors, so always returns an
+error value.
+
+=cut
+
+*/
+
+    METHOD get_fd() {
+        RETURN(INTVAL -1);
+    }
+
+
+/*
+
+=back
+
+=cut
+
+*/
+
+} /* end pmclass */
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */