Permalink
Browse files

Added in code to properly do native calls to library routines loaded via

dlopen or its loval equivalent.


git-svn-id: https://svn.parrot.org/parrot/trunk@2584 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information...
1 parent 58327f4 commit 2a2c19b1dcda1870e5f4e1799b157a0f8fd9654f Dan Sugalski committed Nov 21, 2002
Showing with 209 additions and 23 deletions.
  1. +62 −0 classes/nci.pmc
  2. +6 −5 core.ops
  3. +1 −0 include/parrot/method_util.h
  4. +1 −1 include/parrot/nci.h
  5. +1 −0 include/parrot/string_funcs.h
  6. +1 −1 interpreter.c
  7. +13 −2 languages/ruby/interactive.pl
  8. +12 −0 method_util.c
  9. +75 −8 nci.c
  10. +6 −5 ops/core.ops
  11. +1 −1 src/interpreter.c
  12. +12 −0 src/method_util.c
  13. +9 −0 src/string.c
  14. +9 −0 string.c
View
@@ -0,0 +1,62 @@
+/* NCI.pmc
+ * Copyright: 2002 Yet Another Society
+ * CVS Info
+ * $Id$
+ * Overview:
+ * The vtable functions for the native C call functions
+ * Data Structure and Algorithms:
+ * History:
+ * Initial revision by sean 2002/08/04
+ * Notes:
+ * References:
+ */
+
+#include "parrot/parrot.h"
+#include "parrot/method_util.h"
+
+pmclass NCI {
+
+ void init () {
+ }
+
+ INTVAL type () {
+ return enum_class_NCI;
+ }
+
+ STRING* name () {
+ return whoami;
+ }
+
+ PMC* clone () {
+ return Parrot_new_csub(INTERP, (Parrot_csub_t)D2FPTR(SELF->cache.struct_val));
+ }
+
+ PMC* get_pmc () {
+ return SELF;
+ }
+
+ INTVAL is_same (PMC* value) {
+ return SELF == value;
+ }
+
+ void set_same (PMC* value) {
+ SELF->cache.struct_val = value->cache.struct_val;
+ SELF->data = value->data;
+ }
+
+ INTVAL is_equal (PMC* value) {
+ return (SELF->vtable == value->vtable
+ && SELF->cache.struct_val == value->cache.struct_val
+ && SELF->data == value->data);
+ }
+
+ INTVAL defined () {
+ return SELF->data != NULL;
+ }
+
+ void* invoke (void * next) {
+ Parrot_csub_t func = (Parrot_csub_t)SELF->data;
+ func(INTERP, SELF);
+ return next;
+ }
+}
View
@@ -4275,10 +4275,11 @@ initialization routine for it.
Load a dynamic link library named $2 and store it in $1.
-=item B<dlfunc>(out PMC, in PMC, in STR)
+=item B<dlfunc>(out PMC, in PMC, in STR, in STR)
-Look up symbol $3 in library $2, and put the corresponding sub object
-in $1.
+Look up symbol $3 in library $2 with signature $3, and put the
+corresponding sub object in $1. Note that you need the signature so we
+can build or find an appropriate thunking function.
=item B<invoke>()
@@ -4321,7 +4322,7 @@ inline op loadlib(out PMC, in STR) {
goto NEXT();
}
-op dlfunc (out PMC, in PMC, in STR) {
+op dlfunc (out PMC, in PMC, in STR, in STR) {
const char * name = string_to_cstring(interpreter, ($3));
Parrot_csub_t p = (Parrot_csub_t)D2FPTR(Parrot_dlsym(($2)->data, name));
@@ -4333,7 +4334,7 @@ op dlfunc (out PMC, in PMC, in STR) {
PANIC("Failed to link native method");
}
- $1 = Parrot_new_csub(interpreter, p);
+ $1 = Parrot_new_nci(interpreter, p, $4);
goto NEXT();
}
@@ -27,6 +27,7 @@ void Parrot_push_proto(struct Parrot_Interp * interp,
typedef INTVAL (*Parrot_csub_t)(struct Parrot_Interp * , PMC * );
PMC * Parrot_new_csub(struct Parrot_Interp * interp, Parrot_csub_t func);
+PMC * Parrot_new_nci(struct Parrot_Interp * interp, Parrot_csub_t func, String *signature);
struct method_rec_t {
char * name;
@@ -15,6 +15,6 @@
#include "parrot/parrot.h"
-void *build_call_func(Parrot_Interp *, String *);
+void *build_call_func(struct Parrot_Interp *, String *);
#endif
@@ -20,6 +20,7 @@
INTVAL string_compute_strlen(STRING *);
STRING *string_concat(struct Parrot_Interp *, STRING *, STRING *, UINTVAL);
STRING *string_append(struct Parrot_Interp *, STRING *, STRING *, UINTVAL);
+STRING *string_from_c_string(struct Parrot_Interp *, const void *, UINTVAL);
STRING *string_repeat(struct Parrot_Interp *, const STRING *, UINTVAL,
STRING **);
STRING *string_chopn(STRING *, INTVAL);
View
@@ -22,7 +22,7 @@
# include "parrot/oplib/core_ops_cg.h"
#endif
-#define ATEXIT_DESTROY
+/* #define ATEXIT_DESTROY */
extern op_lib_t *PARROT_CORE_PREDEREF_OPLIB_INIT(void);
@@ -2,7 +2,7 @@
use strict;
use lib '.';
-use YAML;
+use Data::Dumper;
use Term::ReadLine;
use Parse::RecDescent;
use Ruby;
@@ -21,8 +21,19 @@
$::RD_TRACE = 0;
print "Trace off\n";
}
+ elsif($text =~ /^<(.*)/) {
+ my ($fh, $file_data);
+ open $fh, $text;
+ local $/;
+ $file_data = <$fh>;
+# $file_data =~ s/\cJ/ /g;
+# $file_data =~ s/\cM/ /g;
+ print $file_data, "\n";
+ my $return = Data::Dumper->Dump($grammar->program($file_data));
+ print $return;
+ }
else {
- my $return = Dump($grammar->program($text));
+ my $return = Data::Dumper->Dump($grammar->program($text));
print $return;
}
}
View
@@ -16,6 +16,18 @@
#include "parrot/method_util.h"
/*
+ * Create a new native sub. (new way)
+ */
+PMC *
+Parrot_new_nci(struct Parrot_Interp *interp, Parrot_csub_t func, String *signature)
+{
+ PMC *ret = pmc_new(interp, enum_class_NCI);
+ ret->cache.struct_val = (DPOINTER *)F2DPTR(func);
+ ret->data = build_call_func(interp, signature);
+ return ret;
+}
+
+/*
* Create a new native sub.
*/
PMC *
View
@@ -13,25 +13,92 @@
#include "parrot/parrot.h"
+#if !defined(CAN_BUILD_CALL_FRAMES)
+/* All our static functions that call in various ways. Yes, terribly
+ hackish, but that's just fine */
+
+/* Return void, take nothing */
+static void pcf_v_v(struct Parrot_Interp *interpreter, PMC *self) {
+ void (*pointer)();
+ pointer = self->cache.struct_val;
+ (void)(*pointer)();
+ interpreter->ctx.int_reg.registers[0] = 0;
+ interpreter->ctx.int_reg.registers[1] = 0;
+ interpreter->ctx.int_reg.registers[2] = 0;
+ interpreter->ctx.int_reg.registers[3] = 0;
+ interpreter->ctx.int_reg.registers[4] = 0;
+ return;
+}
+
+/* Return int, take nothing */
+static void pcf_i_v(struct Parrot_Interp *interpreter, PMC *self) {
+ int (*pointer)();
+ int return_data;
+ pointer = self->cache.struct_val;
+ return_data = (int)(*pointer)();
+ interpreter->ctx.int_reg.registers[5] = return_data;
+ interpreter->ctx.int_reg.registers[0] = 0;
+ interpreter->ctx.int_reg.registers[1] = 1;
+ interpreter->ctx.int_reg.registers[2] = 0;
+ interpreter->ctx.int_reg.registers[3] = 0;
+ interpreter->ctx.int_reg.registers[4] = 0;
+ return;
+}
+
+/* Return double, take nothing */
+static void pcf_d_v(struct Parrot_Interp *interpreter, PMC *self) {
+ double (*pointer)();
+ double return_data;
+ pointer = self->cache.struct_val;
+ return_data = (double)(*pointer)();
+ interpreter->ctx.int_reg.registers[0] = 0;
+ interpreter->ctx.int_reg.registers[1] = 0;
+ interpreter->ctx.int_reg.registers[2] = 0;
+ interpreter->ctx.int_reg.registers[3] = 0;
+ interpreter->ctx.int_reg.registers[4] = 1;
+ return;
+}
+
+/* Return double, take double */
+static void pcf_d_d(struct Parrot_Interp *interpreter, PMC *self) {
+ double (*pointer)();
+ double return_data;
+
+ pointer = self->cache.struct_val;
+ return_data = (double)(*pointer)(interpreter->ctx.num_reg.registers[5]);
+ interpreter->ctx.num_reg.registers[5] = return_data;
+ interpreter->ctx.int_reg.registers[0] = 0;
+ interpreter->ctx.int_reg.registers[1] = 0;
+ interpreter->ctx.int_reg.registers[2] = 0;
+ interpreter->ctx.int_reg.registers[3] = 0;
+ interpreter->ctx.int_reg.registers[4] = 1;
+ return;
+}
+
+#endif
+
+
+
/* This function serves a single purpose. It takes the function
signature for a C function we want to call and returns a pointer
to a function that can call it. */
-void *build_call_func(Parrot_Interp *interpreter, String *signature) {
+void *build_call_func(struct Parrot_Interp *interpreter, String *signature) {
#if defined(CAN_BUILD_CALL_FRAMES)
/* This would be a good place to put the code that builds the
frames. Undoubtedly painfully platform-dependent */
abort("Oh, no you can't!");
#else
/* And in here is the platform-independent way. Which is to say
"here there be hacks" */
+ if (0 == string_length(signature)) return pcf_v_v;
+ if (!string_compare(interpreter, signature, string_from_c_string(interpreter, "i", 1)))
+ return pcf_i_v;
+ if (!string_compare(interpreter, signature, string_from_c_string(interpreter, "d", 1)))
+ return pcf_d_v;
+ if (!string_compare(interpreter, signature, string_from_c_string(interpreter, "dd", 2)))
+ return pcf_d_d;
+
return NULL;
#endif
}
-#if !defined(CAN_BUILD_CALL_FRAMES)
-/* Return void, take nothing */
-static void pcf_v_v(Parrot_Interp *interpreter, void (*pointer)()) {
- (void)(*pointer)();
- return;
-}
-#endif
View
@@ -4275,10 +4275,11 @@ initialization routine for it.
Load a dynamic link library named $2 and store it in $1.
-=item B<dlfunc>(out PMC, in PMC, in STR)
+=item B<dlfunc>(out PMC, in PMC, in STR, in STR)
-Look up symbol $3 in library $2, and put the corresponding sub object
-in $1.
+Look up symbol $3 in library $2 with signature $3, and put the
+corresponding sub object in $1. Note that you need the signature so we
+can build or find an appropriate thunking function.
=item B<invoke>()
@@ -4321,7 +4322,7 @@ inline op loadlib(out PMC, in STR) {
goto NEXT();
}
-op dlfunc (out PMC, in PMC, in STR) {
+op dlfunc (out PMC, in PMC, in STR, in STR) {
const char * name = string_to_cstring(interpreter, ($3));
Parrot_csub_t p = (Parrot_csub_t)D2FPTR(Parrot_dlsym(($2)->data, name));
@@ -4333,7 +4334,7 @@ op dlfunc (out PMC, in PMC, in STR) {
PANIC("Failed to link native method");
}
- $1 = Parrot_new_csub(interpreter, p);
+ $1 = Parrot_new_nci(interpreter, p, $4);
goto NEXT();
}
View
@@ -22,7 +22,7 @@
# include "parrot/oplib/core_ops_cg.h"
#endif
-#define ATEXIT_DESTROY
+/* #define ATEXIT_DESTROY */
extern op_lib_t *PARROT_CORE_PREDEREF_OPLIB_INIT(void);
View
@@ -16,6 +16,18 @@
#include "parrot/method_util.h"
/*
+ * Create a new native sub. (new way)
+ */
+PMC *
+Parrot_new_nci(struct Parrot_Interp *interp, Parrot_csub_t func, String *signature)
+{
+ PMC *ret = pmc_new(interp, enum_class_NCI);
+ ret->cache.struct_val = (DPOINTER *)F2DPTR(func);
+ ret->data = build_call_func(interp, signature);
+ return ret;
+}
+
+/*
* Create a new native sub.
*/
PMC *
View
@@ -202,6 +202,15 @@ string_append(struct Parrot_Interp *interpreter, STRING *a,
return string_copy(interpreter, b);
}
+/*=for api string string_from_c_string
+ * Make a String from a passed in C string
+ */
+STRING *
+string_from_c_string(struct Parrot_Interp *interpreter, const void *buffer,
+ UINTVAL buflen) {
+ return string_make(interpreter, buffer, buflen ? buflen : strlen(buffer),
+ NULL, 0, NULL);
+}
/*=for api string string_make
* allocate memory for the string, copy information into it
View
@@ -202,6 +202,15 @@ string_append(struct Parrot_Interp *interpreter, STRING *a,
return string_copy(interpreter, b);
}
+/*=for api string string_from_c_string
+ * Make a String from a passed in C string
+ */
+STRING *
+string_from_c_string(struct Parrot_Interp *interpreter, const void *buffer,
+ UINTVAL buflen) {
+ return string_make(interpreter, buffer, buflen ? buflen : strlen(buffer),
+ NULL, 0, NULL);
+}
/*=for api string string_make
* allocate memory for the string, copy information into it

0 comments on commit 2a2c19b

Please sign in to comment.