summaryrefslogtreecommitdiff
path: root/ipl/cfuncs/external.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-01-28 19:02:21 +0000
committerIgor Pashev <pashev.igor@gmail.com>2013-01-28 19:02:21 +0000
commitf627f77f23d1497c9e1f4269b5c8812d12b42f18 (patch)
tree708772d83a8355e25155cf233d5a9e38f8ad4d96 /ipl/cfuncs/external.c
parent6ab0c0f5bf14ed9c15370407b9ee7e0b4b089ae1 (diff)
downloadicon-f627f77f23d1497c9e1f4269b5c8812d12b42f18.tar.gz
Imported Upstream version 9.5.0upstream/9.5.0upstream
Diffstat (limited to 'ipl/cfuncs/external.c')
-rw-r--r--ipl/cfuncs/external.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/ipl/cfuncs/external.c b/ipl/cfuncs/external.c
new file mode 100644
index 0000000..afb96fa
--- /dev/null
+++ b/ipl/cfuncs/external.c
@@ -0,0 +1,154 @@
+/*
+############################################################################
+#
+# File: external.c
+#
+# Subject: Functions to demonstrate Icon external values
+#
+# Author: Gregg M. Townsend
+#
+# Date: October 29, 2009
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+#
+# These functions demonstrate the use of external values.
+#
+# extxmin() creates a minimal external type
+# extxstr(s) creates an external hold a string and trivial checksum
+# extxreal(r) creates a fully customized external type holding a real value
+#
+############################################################################
+#
+# Requires: Dynamic loading
+#
+############################################################################
+*/
+
+#include <string.h>
+#include "icall.h"
+
+/*
+ * minimal external type with no parameters
+ */
+int extxmin(int argc, descriptor argv[]) /*: create minimal external value */
+ {
+ RetExternal(alcexternal(0, 0, 0));
+ }
+
+/*
+ * custom external holding a string and a trivial checksum
+ */
+
+/* custom external data block extends the standard block */
+typedef struct sblock {
+ externalblock eb;
+ unsigned short cksum;
+ char string[];
+ } sblock;
+
+/* type name returns "xstr" */
+static int sname(int argc, descriptor argv[]) {
+ RetConstStringN("xstr", 4);
+ }
+
+/* image returns "xstr_N(cksum:string)" with no special string escapes */
+static int simage(int argc, descriptor argv[]) {
+ sblock *b = (sblock*)ExternalBlock(argv[1]);
+ char buffer[1000]; /* not robust against huge strings */
+ RetStringN(buffer,
+ sprintf(buffer, "xstr_%ld(%05d:%s)", b->eb.id, b->cksum, b->string));
+ }
+
+/* list of custom functions for constructor */
+static funclist sfuncs = {
+ NULL, /* cmp */
+ NULL, /* copy */
+ sname, /* name */
+ simage, /* image */
+ };
+
+/* finally, the exported constructor function, extxstr(s) */
+int extxstr(int argc, descriptor argv[]) /*: create string-valued external */
+ {
+ sblock *new;
+ char *p;
+ int slen;
+
+ ArgString(1);
+ slen = StringLen(argv[1]);
+ new = (sblock *)alcexternal(sizeof(sblock) + slen + 1, &sfuncs, 0);
+ memcpy(new->string, StringAddr(argv[1]), slen);
+ new->string[slen] = '\0';
+ int cksum = 0;
+ for (p = new->string; *p; p++)
+ cksum = 37 * cksum + (unsigned char) *p;
+ new->cksum = cksum;
+ RetExternal((externalblock*)new);
+ }
+
+
+/*
+ * custom real-valued external with lots of trimmings
+ */
+
+/* custom external data block extends the standard block */
+typedef struct rblock {
+ externalblock eb;
+ float value;
+ } rblock;
+
+/* comparison function for sorting */
+static int rcmp(int argc, descriptor argv[]) {
+ rblock *eb1 = (rblock*)ExternalBlock(argv[1]);
+ rblock *eb2 = (rblock*)ExternalBlock(argv[2]);
+ if (eb1->value < eb2->value) RetInteger(-1);
+ if (eb1->value > eb2->value) RetInteger(+1);
+ if (eb1->eb.id < eb2->eb.id) RetInteger(-1);
+ if (eb1->eb.id > eb2->eb.id) RetInteger(+1);
+ RetInteger(0);
+ }
+
+/* copy function duplicates block, getting new serial number */
+static int rcopy(int argc, descriptor argv[]) {
+ externalblock *b = ExternalBlock(argv[1]);
+ rblock *old = (rblock*)b;
+ rblock *new = (rblock *)alcexternal(sizeof(rblock), b->funcs, 0);
+ new->value = old->value;
+ RetExternal((externalblock*)new);
+ }
+
+/* type name returns "xreal" */
+static int rname(int argc, descriptor argv[]) {
+ RetConstStringN("xreal", 5);
+ }
+
+/* image returns "xreal_N(V)" */
+static int rimage(int argc, descriptor argv[]) {
+ rblock *b = (rblock*)ExternalBlock(argv[1]);
+ char buffer[100];
+ RetStringN(buffer,
+ sprintf(buffer, "xreal_%ld(%.1f)", b->eb.id, b->value));
+ }
+
+/* list of custom functions for constructor */
+static funclist rfuncs = {
+ rcmp, /* cmp */
+ rcopy, /* copy */
+ rname, /* name */
+ rimage, /* image */
+ };
+
+/* finally, the exported constructor function, extxreal(r) */
+int extxreal(int argc, descriptor argv[]) /*: create real-valued external */
+ {
+ rblock *new;
+
+ ArgReal(1);
+ float v = RealVal(argv[1]);
+ new = (rblock *)alcexternal(sizeof(rblock), &rfuncs, &v);
+ RetExternal((externalblock*)new);
+ }