summaryrefslogtreecommitdiff
path: root/ipl/packs/loadfuncpp/doc
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/packs/loadfuncpp/doc
parent6ab0c0f5bf14ed9c15370407b9ee7e0b4b089ae1 (diff)
downloadicon-upstream.tar.gz
Imported Upstream version 9.5.0upstream/9.5.0upstream
Diffstat (limited to 'ipl/packs/loadfuncpp/doc')
-rw-r--r--ipl/packs/loadfuncpp/doc/Makefile51
-rw-r--r--ipl/packs/loadfuncpp/doc/Makefile.mak34
-rw-r--r--ipl/packs/loadfuncpp/doc/bang.cpp35
-rw-r--r--ipl/packs/loadfuncpp/doc/bang.icn10
-rw-r--r--ipl/packs/loadfuncpp/doc/compile.htm57
-rw-r--r--ipl/packs/loadfuncpp/doc/divide.cpp20
-rw-r--r--ipl/packs/loadfuncpp/doc/divide.icn10
-rw-r--r--ipl/packs/loadfuncpp/doc/divide2.cpp20
-rw-r--r--ipl/packs/loadfuncpp/doc/divide2.icn10
-rw-r--r--ipl/packs/loadfuncpp/doc/dull.cpp15
-rw-r--r--ipl/packs/loadfuncpp/doc/dull.icn9
-rw-r--r--ipl/packs/loadfuncpp/doc/examples.txt10
-rw-r--r--ipl/packs/loadfuncpp/doc/generator.cpp31
-rw-r--r--ipl/packs/loadfuncpp/doc/generator.icn9
-rw-r--r--ipl/packs/loadfuncpp/doc/hello.php10
-rw-r--r--ipl/packs/loadfuncpp/doc/icall.txt140
-rw-r--r--ipl/packs/loadfuncpp/doc/index.htm87
-rw-r--r--ipl/packs/loadfuncpp/doc/isexternal.cpp31
-rw-r--r--ipl/packs/loadfuncpp/doc/isexternal.icn14
-rw-r--r--ipl/packs/loadfuncpp/doc/iterate.cpp34
-rw-r--r--ipl/packs/loadfuncpp/doc/iterate.icn13
-rw-r--r--ipl/packs/loadfuncpp/doc/keyword.cpp16
-rw-r--r--ipl/packs/loadfuncpp/doc/keyword.icn10
-rw-r--r--ipl/packs/loadfuncpp/doc/loadfuncpp.css41
-rw-r--r--ipl/packs/loadfuncpp/doc/loadfuncpp.h470
-rw-r--r--ipl/packs/loadfuncpp/doc/loadfuncpp.htm42
-rw-r--r--ipl/packs/loadfuncpp/doc/makelist.cpp16
-rw-r--r--ipl/packs/loadfuncpp/doc/makelist.icn10
-rw-r--r--ipl/packs/loadfuncpp/doc/manual.htm1558
-rw-r--r--ipl/packs/loadfuncpp/doc/object.cpp15
-rw-r--r--ipl/packs/loadfuncpp/doc/object.icn23
31 files changed, 2851 insertions, 0 deletions
diff --git a/ipl/packs/loadfuncpp/doc/Makefile b/ipl/packs/loadfuncpp/doc/Makefile
new file mode 100644
index 0000000..586d7d6
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/Makefile
@@ -0,0 +1,51 @@
+
+#Automatically generated from Makefile.mak and examples.txt by ../savex.icn
+
+# icont -ucs file.icn -> u1, u2, goes in the /opt/icon/lib/.
+# g++ stuff -> .os, goes in the /opt/icon/bin/.
+
+
+ifndef TARGET
+
+ifneq ($(strip $(shell g++ -v 2>&1 | grep "darwin")),)
+TARGET=mac
+else
+ifneq ($(strip $(shell g++ -v 2>&1 | grep "cygwin")),)
+TARGET=cygwin
+else
+TARGET=other
+endif
+endif
+
+endif
+
+FLAGS_cygwin = /opt/icon/bin/iload.a -Wl,--enable-auto-import
+FLAGS_other =
+
+SHARED_mac = -bundle -undefined suppress
+SHARED_cygwin = -shared
+SHARED_other = -shared
+
+PIC_other = -fPIC
+PIC_mac = -flat_namespace
+
+EXAMPLES = bang.exe divide.exe divide2.exe dull.exe generator.exe isexternal.exe iterate.exe keyword.exe makelist.exe object.exe
+DYNAMICS = bang.so divide.so divide2.so dull.so generator.so isexternal.so iterate.so keyword.so makelist.so object.so
+
+%.so : %.cpp loadfuncpp.h
+ g++ $(SHARED_$(TARGET)) $(PIC_$(TARGET)) -o $@ $< $(FLAGS_$(TARGET))
+
+%.exe : %.icn %.so
+ icont -so $@ $*
+
+default: $(DYNAMICS) $(EXAMPLES)
+
+.PHONY : loadfuncpp.h
+
+loadfuncpp.h : ../loadfuncpp.h
+ cp ../loadfuncpp.h ./
+
+test : clean default
+
+clean :
+ rm -f *.exe *.so *.o *% *~ core .#*
diff --git a/ipl/packs/loadfuncpp/doc/Makefile.mak b/ipl/packs/loadfuncpp/doc/Makefile.mak
new file mode 100644
index 0000000..7a10f86
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/Makefile.mak
@@ -0,0 +1,34 @@
+
+ifndef TARGET
+ifneq ($(strip $(shell g++ -v 2>&1 | grep "cygwin")),)
+TARGET=cygwin
+else
+TARGET=other
+endif
+endif
+
+FLAGS_cygwin = /opt/icon/bin/iload.a -Wl,--enable-auto-import
+FLAGS_other =
+
+PIC_other = -fPIC
+
+EXAMPLES = #exe#
+DYNAMICS = #so#
+
+%.so : %.cpp loadfuncpp.h
+ g++ -shared $(PIC_$(TARGET)) -o $@ $< $(FLAGS_$(TARGET))
+
+%.exe : %.icn %.so
+ icont -so $@ $*
+
+default: $(DYNAMICS) $(EXAMPLES)
+
+.PHONY : loadfuncpp.h
+
+loadfuncpp.h : ../loadfuncpp.h
+ cp ../loadfuncpp.h ./
+
+test : clean default
+
+clean :
+ rm -f *.exe *.so *.o *% *~ core .#*
diff --git a/ipl/packs/loadfuncpp/doc/bang.cpp b/ipl/packs/loadfuncpp/doc/bang.cpp
new file mode 100644
index 0000000..c300169
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/bang.cpp
@@ -0,0 +1,35 @@
+
+/* Example of a C++ extension to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Type 'make iexample' to build.
+ * Carl Sturtivant, 2008/3/16
+ */
+
+#include "loadfuncpp.h"
+using namespace Icon;
+
+
+
+
+struct addup: public iterate {
+ safe total;
+ int count;
+
+ addup(): total(0L), count(0) {}
+
+ virtual void takeNext(const value& x) {
+ total = total + x;
+ }
+ virtual bool wantNext(const value& x) {
+ return ++count <= 10;
+ }
+};
+
+extern "C" int sumlist(value argv[]) {
+ addup sum;
+ sum.bang(argv[1]);
+ argv[0] = sum.total;
+ return SUCCEEDED;
+}
+
+
diff --git a/ipl/packs/loadfuncpp/doc/bang.icn b/ipl/packs/loadfuncpp/doc/bang.icn
new file mode 100644
index 0000000..bf0aba9
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/bang.icn
@@ -0,0 +1,10 @@
+
+link loadfuncpp
+
+
+procedure main()
+ sumlist := loadfuncpp("./bang.so", "sumlist", 1)
+ write( sumlist([1,2,3,4,5]) )
+end
+
+
diff --git a/ipl/packs/loadfuncpp/doc/compile.htm b/ipl/packs/loadfuncpp/doc/compile.htm
new file mode 100644
index 0000000..04a8514
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/compile.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+
+<HEAD>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
+ <TITLE>loadfuncpp</TITLE>
+ <LINK REL="stylesheet" TYPE="text/css" HREF="loadfuncpp.css">
+</HEAD>
+
+<BODY>
+
+<H3></H3>
+<CENTER>
+<P>
+<TABLE BORDER="0" WIDTH="700">
+ <TR>
+ <TD WIDTH="100%">
+ <H1 ALIGN="CENTER"><BR>
+ Loadfuncpp</H1>
+ <H2 ALIGN="CENTER">Compiler Options</H2>
+ <H3 ALIGN="CENTER">Carl Sturtivant, January 2009</H3>
+ <BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <P>When compiling a shared object (or dll) to dynamically load functions into Icon via loadfuncpp, try the following
+ compilation options, which have been successfully used to build libraries with version 0.91alpha on the systems
+ below. <BR>
+ <BR>
+ Everything is simplest if all shared objects are placed in the icon/bin directory and all linkable Icon (.u1/.u2
+ files) are placed in the icon/lib directory.
+ </BLOCKQUOTE>
+ <H2>Linux</H2>
+ <P><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">g++ -fPIC -shared -o </FONT><I><FONT SIZE="2" FACE="Courier New, Courier">file</FONT></I><FONT
+ SIZE="2" COLOR="black" FACE="Courier New, Courier">.so </FONT><I><FONT SIZE="2" FACE="Courier New, Courier">file</FONT></I><FONT
+ SIZE="2" COLOR="black" FACE="Courier New, Courier">.cpp</FONT></P>
+ <H2>Cygwin</H2>
+ <P><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">g++ -shared -o </FONT><I><FONT SIZE="2" FACE="Courier New, Courier">file</FONT></I><FONT
+ SIZE="2" COLOR="black" FACE="Courier New, Courier">.so </FONT><I><FONT SIZE="2" FACE="Courier New, Courier">file</FONT></I><FONT
+ SIZE="2" COLOR="black" FACE="Courier New, Courier">.cpp </FONT><I><FONT SIZE="2" FACE="Courier New, Courier">iload_so_directory</FONT></I><FONT
+ SIZE="2" COLOR="black" FACE="Courier New, Courier">/iload.a</FONT></P>
+ <H2>Macintosh</H2>
+ <P><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">g++ -flat_namespace -bundle -undefined suppress -o
+ </FONT><I><FONT SIZE="2" FACE="Courier New, Courier">file</FONT></I><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">.so
+ </FONT><I><FONT SIZE="2" FACE="Courier New, Courier">file</FONT></I><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">.cpp</FONT>
+ <H2>Solaris</H2>
+ <P><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">g++ -fPIC -shared -o </FONT><I><FONT SIZE="2" FACE="Courier New, Courier">file</FONT></I><FONT
+ SIZE="2" COLOR="black" FACE="Courier New, Courier">.so </FONT><I><FONT SIZE="2" FACE="Courier New, Courier">file</FONT></I><FONT
+ SIZE="2" COLOR="black" FACE="Courier New, Courier">.cpp</FONT>
+ </BLOCKQUOTE>
+ </TD>
+ </TR>
+</TABLE>
+
+</CENTER>
+
+</BODY>
+
+</HTML>
diff --git a/ipl/packs/loadfuncpp/doc/divide.cpp b/ipl/packs/loadfuncpp/doc/divide.cpp
new file mode 100644
index 0000000..a9f3d99
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/divide.cpp
@@ -0,0 +1,20 @@
+
+
+/* Example of a C++ extension to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Type 'make iexample' to build.
+ * Carl Sturtivant, 2008/3/16
+ */
+
+
+#include "loadfuncpp.h"
+using namespace Icon;
+
+extern "C" int div(value argv[]) {
+ safe x(argv[1]), y(argv[2]), z;
+ z = ( x/y, x%y );
+ argv[0] = z;
+ return SUCCEEDED;
+}
+
+
diff --git a/ipl/packs/loadfuncpp/doc/divide.icn b/ipl/packs/loadfuncpp/doc/divide.icn
new file mode 100644
index 0000000..9e5c0b8
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/divide.icn
@@ -0,0 +1,10 @@
+
+link loadfuncpp
+
+procedure main()
+ div := loadfuncpp("./divide.so", "div", 2)
+ ls := div(79, 10)
+ every write(!ls)
+end
+
+
diff --git a/ipl/packs/loadfuncpp/doc/divide2.cpp b/ipl/packs/loadfuncpp/doc/divide2.cpp
new file mode 100644
index 0000000..a9f3d99
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/divide2.cpp
@@ -0,0 +1,20 @@
+
+
+/* Example of a C++ extension to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Type 'make iexample' to build.
+ * Carl Sturtivant, 2008/3/16
+ */
+
+
+#include "loadfuncpp.h"
+using namespace Icon;
+
+extern "C" int div(value argv[]) {
+ safe x(argv[1]), y(argv[2]), z;
+ z = ( x/y, x%y );
+ argv[0] = z;
+ return SUCCEEDED;
+}
+
+
diff --git a/ipl/packs/loadfuncpp/doc/divide2.icn b/ipl/packs/loadfuncpp/doc/divide2.icn
new file mode 100644
index 0000000..48da848
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/divide2.icn
@@ -0,0 +1,10 @@
+
+link loadfuncpp
+
+procedure main()
+ div := loadfuncpp("./divide2.so", "div", 2)
+ ls := div(79, 10)
+ every write(!ls)
+end
+
+
diff --git a/ipl/packs/loadfuncpp/doc/dull.cpp b/ipl/packs/loadfuncpp/doc/dull.cpp
new file mode 100644
index 0000000..f1683ee
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/dull.cpp
@@ -0,0 +1,15 @@
+
+/* Example of a C++ extension to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Type 'make iexample' to build.
+ * Carl Sturtivant, 2008/3/16
+ */
+
+#include "loadfuncpp.h"
+using namespace Icon;
+
+extern "C" int dull(value argv[]) {
+ argv[0] = nullvalue;
+ return SUCCEEDED;
+}
+
diff --git a/ipl/packs/loadfuncpp/doc/dull.icn b/ipl/packs/loadfuncpp/doc/dull.icn
new file mode 100644
index 0000000..128f8a1
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/dull.icn
@@ -0,0 +1,9 @@
+
+link loadfuncpp
+
+
+procedure main()
+ dull := loadfuncpp("./dull.so", "dull", 1)
+ write(image( dull() ))
+end
+
diff --git a/ipl/packs/loadfuncpp/doc/examples.txt b/ipl/packs/loadfuncpp/doc/examples.txt
new file mode 100644
index 0000000..3b6a98e
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/examples.txt
@@ -0,0 +1,10 @@
+bang
+divide
+divide2
+dull
+generator
+isexternal
+iterate
+keyword
+makelist
+object
diff --git a/ipl/packs/loadfuncpp/doc/generator.cpp b/ipl/packs/loadfuncpp/doc/generator.cpp
new file mode 100644
index 0000000..5f99158
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/generator.cpp
@@ -0,0 +1,31 @@
+
+/* Example of a C++ extension to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Type 'make iexample' to build.
+ * Carl Sturtivant, 2008/3/16
+ */
+
+#include "loadfuncpp.h"
+using namespace Icon;
+
+class sequence: public generator {
+ safe current, inc;
+ public:
+ sequence(safe start, safe increment) {
+ current = start - increment;
+ inc = increment;
+ }
+ virtual bool hasNext() {
+ return true;
+ }
+ virtual value giveNext() {
+ return current = current + inc;
+ }
+};
+
+extern "C" int seq2(value argv[]){
+ sequence seq(argv[1], argv[2]);
+ return seq.generate(argv);
+}
+
+
diff --git a/ipl/packs/loadfuncpp/doc/generator.icn b/ipl/packs/loadfuncpp/doc/generator.icn
new file mode 100644
index 0000000..cf46dff
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/generator.icn
@@ -0,0 +1,9 @@
+
+link loadfuncpp
+
+
+procedure main()
+ seq2 := loadfuncpp("./generator.so", "seq2", 1)
+ every write( seq2(1001, 99) \ 30 )
+end
+
diff --git a/ipl/packs/loadfuncpp/doc/hello.php b/ipl/packs/loadfuncpp/doc/hello.php
new file mode 100644
index 0000000..d96e074
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/hello.php
@@ -0,0 +1,10 @@
+<HTML>
+ <HEAD>
+ <TITLE>Hello World</TITLE>
+ </HEAD>
+ <BODY>
+<?
+ print("Hello World");
+?>
+ </BODY>
+</HTML>
diff --git a/ipl/packs/loadfuncpp/doc/icall.txt b/ipl/packs/loadfuncpp/doc/icall.txt
new file mode 100644
index 0000000..700929f
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/icall.txt
@@ -0,0 +1,140 @@
+
+A Technique to Call Icon from C under Icon Version 9
+ Carl Sturtivant, 2008/2/20 Confidential Draft #1
+
+
+1. Summary.
+
+A new Icon function written in C with a special interface may be
+dynamically loaded from a shared object using the built-in function
+loadfunc [GT95]. We show how such a function may in turn call an Icon
+procedure using the technique described below, provided that the
+procedure call itself does not suspend, but only returns or fails. Note
+that this does not impose constraints of any kind upon other procedures
+executed as a consequence of calling the original procedure. In
+particular, the Icon procedure called from C may in turn lead to a call
+of another Icon function written in C calling Icon recursively. The
+technique described has been implemented and briefly tested with Icon
+9.51(?).
+
+
+2. Overview.
+
+If the body of an Icon function written in C is to call an Icon
+procedure that does not suspend and retrieve its return value, all
+without modifying iconx, then there are a number of hurdles to jump.
+The procedure descriptor, and those of its arguments must be pushed
+onto the Icon stack, and the interpreter induced to believe it needs to
+execute an icode instruction to invoke it, one that is not present in
+the icode it loaded. Once the procedure returns (or fails) the
+interpreter must be induced to return control to C just after the point
+where the attempt to call it occurred, rather than simply to go on to
+the next icode instruction. Then the result of the call needs to be
+popped off the Icon stack so that it is in the same state as before the
+call, since C does not normally modify the Icon stack. (Other details
+of the state of the interpreter will be restored by the mechanism
+whereby a procedure is called in Icon.) In all other respects, the main
+interpreter loop must continue to behave as before.
+
+These hurdles are insurmountable, so long as the code of the main
+interpreter loop is inviolate. The code of that loop as it is
+incorporated into iconx is inviolate, since a design goal is that the
+technique should work with the existing implementation. Therefore, we
+take a copy of that loop, and modify it to the ends above, and execute
+it only in order to call Icon. (The original interpreter continues to
+be used for all other purposes.) Dynamic linking allows the new
+interpreter loop to refer to all C globals and functions in iconx, and
+so nothing else need be copied, these things are merely referred to. In
+fact it takes very little modification of the copy to achieve these
+goals, and the result is a C function called icall to which the
+procedure and its arguments are passed to effect the call to Icoan. To
+simplify this interface, the arguments are passed as a single Icon
+list. The resulting function then has similar semantics as the binary
+"!" operator in Icon, (which we henceforth call 'apply' as it applies a
+procedure to its argument list) except that it may be called from C.
+
+
+3. Implementation.
+
+The main interpreter loop written in RTL resides in the file
+src/runtime/interp.r in the Icon distribution. This was translated into
+the corresponding C file xinterp.c by the RTL translator rtt with the
+command 'rtt -x interp.r'. Now this C file is edited into a file
+compiled into a single C function called icall, taking two descriptors
+(a procedure and a list of arguments) and returning an integer code.
+The effect of calling icall is to apply the procedure to its arguments,
+and restore the state of the interpreter, leaving the result of the
+call just beyond the stack pointer for retrieval.
+
+The contents of xinterp.c consist of some global variables and a
+function interp containing the interpreter loop. The global variable
+declarations are all modified by prefixing them with 'extern', so that
+they now simply refer to those used by the interpreter loop inside
+iconx. The function interp that returns an integer signal and has two
+parameters: an integer fsig used when the interpreter is called
+recursively to simulate suspension, and cargp, a pointer into the Icon
+stack. The function interp is renamed icall.
+
+Examination of src/runtime/init.r indicates that the signal 0 is passed
+to interp when it is initially called non-recursively to start up
+iconx. So fsig is removed from the parameter list and made a local
+variable initialized to 0. Similarly cargp is made a local variable,
+and icall is given two parameters theProc and arglist used to pass that
+necessary for the call to Icon. Immediately after the initial
+declarations inside icall, the Icon stack pointer sp is used to
+initialize cargp to refer to the first descriptor on the stack beyond
+sp, which is assigned the procedure desciptor parameter of icall. The
+desciptor beyond that is assigned the argument list descriptor
+parameter, and the stack pointer augmented to refer to its last word. A
+new local variable result_sp is initialized to location on the stack of
+the last word of the procedure descriptor. This is used by the
+mechanism to return to C described below. Now the details of pushing
+the procedure descriptor and the argument list descriptor onto the
+stack are complete.
+
+The body of interp consists of some straight-line code followed by the
+interpreter loop, which contains some code to get the next icode
+instruction followed by a switch to jump to the correct code to execute
+it, all inside and endless loop. Just before the loop starts, an
+unconditional goto is inserted, jumping to a newly inserted label
+called aptly 'apply' which is placed just after the switch label
+(called Op_Apply in interp.r) which precedes the code to implement the
+icode 'apply' instruction, that implements the apply operator (binary
+"!") in Icon. This instruction expects to find a procedure descriptor
+and a list descriptor on the stack, and then causes the icode
+instructions of the procedure to be accordingly invoked. Now the
+details of calling the procedure are complete. What is left to insert
+is the mechanism to return to C.
+
+When the procedure that we called returns or fails, it will execute a
+'pret' instruction or a 'pfail' instruction. However, these
+instructions may also be executed by Icon procedures called from the
+one we called. At the end of the code for 'pret' inside the switch in
+the interpreter is a 'break' to leave the switch and go round to get
+the next icode instruction. Just before that 'break' we can tell if our
+procedure call is the one returning by comparing the Icon stack pointer
+sp to the one we saved, result_sp, which our procedure call will have
+restored sp to when it overwrote the procedure descriptor with the
+result of the call. So if they are equal, we can clean up (decrement
+ilevel, move sp just before the former procedure descriptor) and
+return, finishing the call to icall. Now C can retrieve the result of
+the call just beyond the stack pointer. The 'pfail' code is similar,
+just before a jump to efail, which we do not execute since the context
+of our call is not an Icon expression. C can determine success or
+failure from the integer code returned. This completes the mechanism to
+return to C.
+
+
+4. Conclusions
+
+Overall this mechanism depends upon few things, mainly upon the fact
+that when a procedure is called, the Icon stack below the part used for
+the call is not modified during the call. Our copy of the interpreter
+loop is identical to the original with the exception of the code added
+for the C return mechanism, which is only exceptionally executed. And
+the Icon procedure call mechanism itself will save and restore the
+interpreter state apart from the stack pointer which we abuse at the
+start and restore at the end. The compiled result with gcc was about 10
+Kbyte. A simple test confirmed that call and return occur in the
+correct order, from Icon to C to Icon returning to C returning to Icon.
+
diff --git a/ipl/packs/loadfuncpp/doc/index.htm b/ipl/packs/loadfuncpp/doc/index.htm
new file mode 100644
index 0000000..dad9df8
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/index.htm
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+
+<HEAD>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
+ <TITLE>loadfuncpp</TITLE>
+ <LINK REL="stylesheet" TYPE="text/css" HREF="loadfuncpp.css">
+</HEAD>
+
+<BODY>
+
+<CENTER>
+<P>
+<TABLE BORDER="0" WIDTH="700">
+ <TR>
+ <TD WIDTH="100%">
+ <H1 ALIGN="CENTER"><BR>
+ Loadfuncpp</H1>
+ <H2 ALIGN="CENTER">A Dynamic Library used to aid Adding <BR>
+ External Functions written in C++ to<BR>
+ <A HREF="http://www.cs.arizona.edu/icon/lb3.htm" target="_blank">The Icon Programming Language</A></H2>
+ <H3 ALIGN="CENTER">Carl Sturtivant, February 2010, <FONT COLOR="#FF9900">version 0.91alpha</FONT></H3>
+ <BLOCKQUOTE>
+ <H5><FONT COLOR="#FF9900"></FONT></H5>
+ <H3><FONT COLOR="#CC0000">Features</FONT></H3>
+ </BLOCKQUOTE>
+ <UL>
+ <LI><FONT COLOR="#FF9900">Works with the existing Icon runtime system with no modification</FONT>
+ <LI><FONT COLOR="#FF9900">Call Icon with call syntax from C++ and vice-versa, recursively</FONT>
+ <LI><FONT COLOR="#FF9900">Has a simple way to create new Icon datatypes by inheritance</FONT>
+ <LI><FONT COLOR="#FF9900">Write new Icon functions in C++ that suspend a sequence of results</FONT>
+ <LI><FONT COLOR="#FF9900">Iterate in C++ through result sequences generated by Icon</FONT>
+ <LI><FONT COLOR="#FF9900">All Icon functions, keywords and operators made available in C++</FONT>
+ <LI><FONT COLOR="#FF9900">Takes care of garbage collection safety automatically</FONT>
+ <H5></H5>
+ </UL>
+ <BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <H4><A HREF="manual.htm">documentation</A><BR>
+ <A HREF="loadfuncpp.htm">experimental binaries</A><BR>
+ <A HREF="compile.htm">compilation options</A></H4>
+ </BLOCKQUOTE>
+ </BLOCKQUOTE>
+ </BLOCKQUOTE>
+ </BLOCKQUOTE>
+ <H3>News</H3>
+ <BLOCKQUOTE>
+ <P>2010/2/10 (I am releasing this now having moved on to a new implementation of the language entirely.) There
+ are no known bugs, but bugs almost certainly exist. This pack needs systematic in-depth testing for subtle issues
+ connected to garbage collection. Specifically, the mechanism to call Icon from C++ pushes onto the top of the Icon
+ stack a region used by a copy of the interpreter loop that's used to execute the Icon procedure called from C++.
+ I have not investigated how the Icon stack is garbage collected, and this region does not extend the stack the
+ way that Icon does. If this proves unsafe for garbage collection, the stack region for such a call may have to
+ have suitable frames containing pointers to the lower part of the stack (or vice-versa) placed in it to repair
+ this deficiency. Also, the way garbage collection safety of Icon values in C++ variables is ensured is to use the
+ constructor to implicitly link them onto the far end of the main co-expression's safe list, and unlink them from
+ there using the destructor. This is almost certainly safe from the usual call and return mechanism in iconx for
+ protecting local variables, but needs testing and verification.<BR>
+ <BR>
+ 2009/1/20 fixed a bug where a call of any C++ external function that in turn calls Icon and afterIcon returns calls
+ Icon::runerr would not correctly report the name and arguments of said function in the resulting traceback. Upped
+ the version number to 0.91alpha.<BR>
+ <BR>
+ 2009/1/20 loadfuncpp now searches for a shared object on the path defined by the environment variable FPATH with
+ the icon/bin directory appended if you specify no path. FPATH undefined leads loadfuncpp to search the current
+ directory followed by the icon/bin directory.<BR>
+ <BR>
+ 2009/1/12 <FONT COLOR="#FF9900">loadfuncpp has been completely overhauled</FONT>, and the old version is now obsolete.
+ Many small functions have been added to eliminate ambiguities in programs that use loadfuncpp, and the central
+ class has been renamed and a class eliminated. Small pieces of missing functionality have been added. The documentation
+ has been modified accordingly. It is now close to it's final form, and in need of some serious beta testing, and
+ I have someone who has agreed to do that. Once this is done, loadfuncpp will be made available as a pack with the
+ Icon 9.5 source distribution.
+ </BLOCKQUOTE>
+ </BLOCKQUOTE>
+ </TD>
+ </TR>
+</TABLE>
+
+</CENTER>
+
+</BODY>
+
+</HTML>
diff --git a/ipl/packs/loadfuncpp/doc/isexternal.cpp b/ipl/packs/loadfuncpp/doc/isexternal.cpp
new file mode 100644
index 0000000..ef5d219
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/isexternal.cpp
@@ -0,0 +1,31 @@
+
+
+/* Example of a C++ extension to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Type 'make iexample' to build.
+ * Carl Sturtivant, 2008/3/16
+ */
+
+
+#include "loadfuncpp.h"
+using namespace Icon;
+
+class myval: public external {
+ public:
+ virtual value name() { return "my external"; }
+};
+
+extern "C" int myext(value argv[]) {
+ argv[0] = new myval();
+ return SUCCEEDED;
+}
+
+extern "C" int ismine(value argv[]) {
+ if( argv[1].isExternal("my external") )
+ argv[0] = "Yes!";
+ else
+ argv[0] = "No!";
+ return SUCCEEDED;
+}
+
+
diff --git a/ipl/packs/loadfuncpp/doc/isexternal.icn b/ipl/packs/loadfuncpp/doc/isexternal.icn
new file mode 100644
index 0000000..bfa509a
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/isexternal.icn
@@ -0,0 +1,14 @@
+
+link loadfuncpp
+
+procedure main()
+ myext := loadfuncpp("./isexternal.so", "myext", 0)
+ ismine := loadfuncpp("./isexternal.so", "ismine", 1)
+ x := myext()
+ write(image(x))
+ write(image(type(x)))
+ write("is mine? ", ismine(x))
+ write("is also mine? ", ismine(3))
+end
+
+
diff --git a/ipl/packs/loadfuncpp/doc/iterate.cpp b/ipl/packs/loadfuncpp/doc/iterate.cpp
new file mode 100644
index 0000000..9a57e59
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/iterate.cpp
@@ -0,0 +1,34 @@
+
+/* Example of a C++ extension to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Type 'make iexample' to build.
+ * Carl Sturtivant, 2008/3/16
+ */
+
+#include "loadfuncpp.h"
+using namespace Icon;
+
+
+struct addup: public iterate {
+ safe total;
+ int count;
+
+ addup(): total(0L), count(0) {}
+
+ virtual void takeNext(const value& x) {
+ total = total + x;
+ }
+ virtual bool wantNext(const value& x) {
+ return ++count <= 10;
+ }
+};
+
+
+extern "C" int sum10(value argv[]){
+ addup sum;
+ sum.every(argv[1], argv[2]);
+ argv[0] = sum.total;
+ return SUCCEEDED;
+}
+
+
diff --git a/ipl/packs/loadfuncpp/doc/iterate.icn b/ipl/packs/loadfuncpp/doc/iterate.icn
new file mode 100644
index 0000000..1fd1cb7
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/iterate.icn
@@ -0,0 +1,13 @@
+
+link loadfuncpp
+
+
+procedure main()
+ sum10 := loadfuncpp("./iterate.so", "sum10", 2)
+ write( sum10(f,[]) )
+end
+
+procedure f()
+ suspend 1 to 15
+end
+
diff --git a/ipl/packs/loadfuncpp/doc/keyword.cpp b/ipl/packs/loadfuncpp/doc/keyword.cpp
new file mode 100644
index 0000000..3e3bde8
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/keyword.cpp
@@ -0,0 +1,16 @@
+
+/* Example of a C++ extension to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Type 'make iexample' to build.
+ * Carl Sturtivant, 2008/3/16
+ */
+
+#include "loadfuncpp.h"
+using namespace Icon;
+
+extern "C" int assignprog(value argv[]) {
+ safe newname(argv[1]);
+ &progname = newname;
+ return FAILED;
+}
+
diff --git a/ipl/packs/loadfuncpp/doc/keyword.icn b/ipl/packs/loadfuncpp/doc/keyword.icn
new file mode 100644
index 0000000..0340f9c
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/keyword.icn
@@ -0,0 +1,10 @@
+
+link loadfuncpp
+
+
+procedure main()
+ assignprog := loadfuncpp("./keyword.so", "assignprog", 1)
+ assignprog("Silly")
+ write(&progname)
+end
+
diff --git a/ipl/packs/loadfuncpp/doc/loadfuncpp.css b/ipl/packs/loadfuncpp/doc/loadfuncpp.css
new file mode 100644
index 0000000..975cbcb
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/loadfuncpp.css
@@ -0,0 +1,41 @@
+body { background-color: #FFFFFF;
+ color: #0066CC;
+ font-family: Georgia, "Times New Roman", serif;
+}
+h1 { background-color: #CCFFFF;
+ color: #0099FF;
+ line-height: 200%;
+ font-family: Georgia, "Times New Roman", serif;
+}
+h2 { background-color: #CCFFFF;
+ color: #0099FF;
+ font-family: Georgia, "Times New Roman", serif;
+ line-height: 100%
+}
+h3 { background-color: #CCFFFF;
+ font-family: Georgia, "Times New Roman", serif;
+ line-height: 90%
+}
+h4 { background-color: #FFFFFF;
+ color: #FF9900;
+ font-family: Georgia, "Times New Roman", serif;
+ line-height: 100%
+}
+a {color: #333300;
+}
+p {font-size: 120%;
+}
+ul {font-weight: bold;
+}
+#wrapper { width: 850px;
+ margin-left: auto;
+ margin-right: auto;
+}
+.nav { font-weight: bold;
+ font-size: 1.25em;
+}
+#footer {font-size: .75em;
+ font-style: italic;
+}
+
+
diff --git a/ipl/packs/loadfuncpp/doc/loadfuncpp.h b/ipl/packs/loadfuncpp/doc/loadfuncpp.h
new file mode 100644
index 0000000..934bca9
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/loadfuncpp.h
@@ -0,0 +1,470 @@
+
+/* C++ support for easy extensions to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Include this and link to iload.cpp which
+ * contains the necessary glue.
+ * See iexample.cpp for typical use.
+ * Carl Sturtivant, 2008/3/17
+ */
+
+#include<new>
+#include <cstdio>
+
+enum kind { Null, Integer, BigInteger, Real, Cset, File, Procedure, Record, List,
+ Set=10, Table=12, String, Constructor, Coexpression=18, External, Variable };
+
+enum special_value { NullString, StringLiteral, NewString, NullChar, Illegal };
+
+enum {
+ SUCCEEDED = 7, // Icon function call returned: A_Continue
+ FAILED = 1 // Icon function call failed: A_Resume
+};
+
+class value; //Icon value (descriptor)
+class safe; //for garbage-collection-safe Icon valued C++ variables and parameters of all kinds
+class keyword; //Icon keyword represented as an object with unary &
+class variadic; //for garbage-collection-safe variadic function argument lists
+class proc_block; //block specifying a procedure to iconx
+class external_block; //block specifying an external value to iconx
+class external_ftable; //function pointers specifying external value behavior to iconx
+class external; //C++ Object specifying an external value
+
+typedef int iconfunc(value argv[]); //type of icon built in functions or operators with a fixed number of arguments
+typedef int iconfvbl(int argc, value argv[]); //type of icon built in functions with a variable number of arguments
+
+extern const value nullvalue; //for default arguments
+extern const value nullstring;
+extern const value nullchar;
+extern const value illegal; //for unwanted trailing arguments
+extern void syserror(const char*); //fatal termination Icon-style with error message
+#define Fs_Read 0001 /* file open for reading */
+#define Fs_Write 0002 /* file open for writing */
+extern value IconFile(int fd, int status, char* fname); //make an Icon file descriptor
+
+namespace Icon {
+//all keywords excepting &fail, &cset (avoiding a name collision with function cset)
+extern keyword allocated;
+extern keyword ascii;
+extern keyword clock;
+extern keyword collections;
+extern keyword current;
+extern keyword date;
+extern keyword dateline;
+extern keyword digits;
+extern keyword dump;
+extern keyword e;
+extern keyword error;
+extern keyword errornumber;
+extern keyword errortext;
+extern keyword errorvalue;
+extern keyword errout;
+extern keyword features;
+extern keyword file;
+extern keyword host;
+extern keyword input;
+extern keyword lcase;
+extern keyword letters;
+extern keyword level;
+extern keyword line;
+extern keyword main;
+extern keyword null;
+extern keyword output;
+extern keyword phi;
+extern keyword pi;
+extern keyword pos;
+extern keyword progname;
+extern keyword random;
+extern keyword regions;
+extern keyword source;
+extern keyword storage;
+extern keyword subject;
+extern keyword time;
+extern keyword trace;
+extern keyword ucase;
+extern keyword version;
+}; //namespace Icon
+
+static void initialize_keywords();
+
+class keyword { //objects representing Icon keywords
+ friend void initialize_keywords();
+ iconfunc* f;
+ public:
+ safe operator&(); //get the keyword's value (could be an Icon 'variable')
+};
+
+
+class value { //a descriptor with class
+//data members modelled after 'typedef struct { word dword, vword; } descriptor;' from icall.h
+ private:
+ long dword;
+ long vword;
+ public:
+ friend class safe;
+ friend value IconFile(FILE* fd, int status, char* fname);
+ value(); //&null
+ value(special_value, const char* text = "");
+ value(int argc, value* argv); //makes a list of parameters passed in from Icon
+ value(int);
+ value(long);
+ value(float);
+ value(double);
+ value(char*);
+ value(const char*);
+ value(proc_block&);
+ value(proc_block*);
+ value(external*);
+ operator int();
+ operator long();
+ operator float();
+ operator double();
+ operator char*();
+ operator external*();
+ operator proc_block*() const;
+ bool operator==(const value&) const;
+ value& dereference();
+ value intify();
+ bool isNull();
+ bool notNull();
+ bool isExternal(const value&);
+ value size() const;
+ kind type();
+ bool toString(); //attempted conversion in place
+ bool toCset();
+ bool toInteger();
+ bool toReal();
+ bool toNumeric();
+ value subscript(const value&) const; //produces an Icon 'variable'
+ value& assign(const value&); //dereferences Icon style
+ value put(value x = nullvalue);
+ value push(value x = nullvalue);
+ void dump() const;
+ void printimage() const;
+ int compare(const value&) const; //comparator-style result: used for Icon sorting
+ value negative() const; // -x
+ value complement() const; // ~x
+ value refreshed() const; // ^x
+ value random() const; // ?x
+ value plus(const value&) const;
+ value minus(const value&) const;
+ value multiply(const value&) const;
+ value divide(const value&) const;
+ value remainder(const value&) const;
+ value power(const value&) const;
+ value union_(const value&) const; // x ++ y
+ value intersection(const value&) const; // x ** y
+ value difference(const value&) const; // x -- y
+ value concatenate(const value&) const; // x || y
+ value listconcatenate(const value&) const;// x ||| y
+ value slice(const value&, const value&) const; // x[y:z]
+ value& swap(value&); // x :=: y
+ value activate(const value& y = nullvalue) const; // y @ x ('*this' is activated)
+ value apply(const value&) const; // x!y (must return, not fail or suspend)
+}; //class value
+
+
+class generator {
+//class to inherit from for defining loadable functions that are generators
+ public:
+ int generate(value argv[]); //call to suspend everything produced by next()
+ protected: //override these, and write a constructor
+ virtual bool hasNext();
+ virtual value giveNext();
+}; //class generator
+
+
+class iterate {
+//class to inherit from for iterating over f!arg or !x
+ public:
+ void every(const value& g, const value& arg); //perform the iteration over g!arg
+ void bang(const value& x); //perform the iteration over !x
+ //override these, write a constructor and the means of recovering the answer
+ virtual bool wantNext(const value& x);
+ virtual void takeNext(const value& x);
+};
+
+
+
+class safe_variable {
+//data members modelled after 'struct tend_desc' from rstructs.h
+ friend class value;
+ friend inline int safecall_0(iconfunc*, value&);
+ friend inline int safecall_1(iconfunc*, value&, const value&);
+ friend inline int safecall_2(iconfunc*, value&, const value&, const value&);
+ friend inline int safecall_3(iconfunc*, value&, const value&, const value&, const value&);
+ friend inline int safecall_4(iconfunc*, value&, const value&, const value&, const value&, const value&);
+ friend inline int safecall_5(iconfunc*, value&, const value&, const value&, const value&, const value&, const value&);
+ friend inline int safecall_6(iconfunc*, value&, const value&, const value&, const value&, const value&, const value&, const value&);
+ friend inline int safecall_v0(iconfvbl*, value&);
+ friend inline int safecall_v1(iconfvbl*, value&, const value&);
+ friend inline int safecall_v2(iconfvbl*, value&, const value&, const value&);
+ friend inline int safecall_v3(iconfvbl*, value&, const value&, const value&, const value&);
+ friend inline int safecall_vbl(iconfvbl*,safe&, const variadic&);
+ protected:
+ safe_variable *previous;
+ int num;
+ value val;
+ safe_variable();
+ safe_variable(int);
+ safe_variable(long);
+ safe_variable(double);
+ safe_variable(value);
+ safe_variable(proc_block&);
+ safe_variable(proc_block*);
+ safe_variable(int, value*);
+ inline void push(safe_variable*& tendlist, int numvalues=1);
+ inline void pop(safe_variable*& tendlist);
+}; //class safe_variable
+
+
+class variadic: public safe_variable {
+ public:
+ variadic(int);
+ variadic(long);
+ variadic(float);
+ variadic(double);
+ variadic(char*);
+ variadic(value);
+ variadic(const safe&);
+ variadic(const safe&, const safe&);
+ variadic& operator,(const safe&);
+ operator value();
+ ~variadic();
+}; //class variadic
+
+
+class external_block {
+//modelled on 'struct b_external' in icon/src/h/rstructs.h
+ friend class external;
+ friend class value;
+ static long extra_bytes; //silent extra parameter to new
+ long title;
+ long blksize;
+ long id;
+ external_ftable* funcs;
+ external* val;
+ static void* operator new(size_t); //allocated by iconx
+ static void operator delete(void*); //do nothing
+ external_block();
+};
+
+class external {
+ friend class value;
+ static external_block* blockptr; //silent extra result of new
+ protected:
+ long id;
+ public:
+ static void* operator new(size_t); //allocated by new external_block()
+ static void operator delete(void*); //do nothing
+ external();
+ virtual ~external() {} //root class
+ virtual long compare(external*);
+ virtual value name();
+ virtual external* copy();
+ virtual value image();
+};
+
+
+class safe: public safe_variable {
+//use for a garbage collection safe icon valued safe C++ variable
+ friend class variadic;
+ friend class global;
+ public:
+ safe(); //&null
+ safe(const safe&);
+ safe(int);
+ safe(long);
+ safe(float);
+ safe(double);
+ safe(char*);
+ safe(const value&);
+ safe(const variadic&);
+ safe(proc_block&);
+ safe(proc_block*);
+ safe(int, value*); //from parameters sent in from Icon
+ ~safe();
+ safe& operator=(const safe&);
+ //augmenting assignments here
+ safe& operator+=(const safe&);
+ safe& operator-=(const safe&);
+ safe& operator*=(const safe&);
+ safe& operator/=(const safe&);
+ safe& operator%=(const safe&);
+ safe& operator^=(const safe&);
+ safe& operator&=(const safe&);
+ safe& operator|=(const safe&);
+ // ++ and -- here
+ safe& operator++();
+ safe& operator--();
+ safe operator++(int);
+ safe operator--(int);
+ //conversion to value
+ operator value() const;
+ //procedure call
+ safe operator()();
+ safe operator()(const safe&);
+ safe operator()(const safe& x1, const safe& x2,
+ const safe& x3 = illegal, const safe& x4 = illegal,
+ const safe& x5 = illegal, const safe& x6 = illegal,
+ const safe& x7 = illegal, const safe& x8 = illegal);
+ safe operator[](const safe&);
+
+ friend safe operator*(const safe&); //size
+ friend safe operator-(const safe&);
+ friend safe operator~(const safe&); //set complement
+ friend safe operator+(const safe&, const safe&);
+ friend safe operator-(const safe&, const safe&);
+ friend safe operator*(const safe&, const safe&);
+ friend safe operator/(const safe&, const safe&);
+ friend safe operator%(const safe&, const safe&);
+ friend safe operator^(const safe&, const safe&); //exponentiation
+ friend safe operator|(const safe&, const safe&); //union
+ friend safe operator&(const safe&, const safe&); //intersection
+ friend safe operator&&(const safe&, const safe&); //set or cset difference
+ friend safe operator||(const safe&, const safe&); //string concatenation
+ friend bool operator<(const safe&, const safe&);
+ friend bool operator>(const safe&, const safe&);
+ friend bool operator<=(const safe&, const safe&);
+ friend bool operator>=(const safe&, const safe&);
+ friend bool operator==(const safe&, const safe&);
+ friend bool operator!=(const safe&, const safe&);
+ friend variadic operator,(const safe&, const safe&); //variadic argument list construction
+
+ safe slice(const safe&, const safe&); // x[y:z]
+ safe apply(const safe&); // x ! y
+ safe listcat(const safe&); // x ||| y
+ safe& swap(safe&); // x :=: y
+ safe create(); // create !x
+ safe create(const safe&); // create x!y
+ safe activate(const safe& y = nullvalue); // y@x
+ safe refresh(); // ^x
+ safe random(); // ?x
+ safe dereference(); // .x
+ bool isIllegal() const; //is an illegal value used for trailing arguments
+}; //class safe
+
+
+//Icon built-in functions
+namespace Icon {
+ safe abs(const safe&);
+ safe acos(const safe&);
+ safe args(const safe&);
+ safe asin(const safe&);
+ safe atan(const safe&, const safe&);
+ safe center(const safe&, const safe&, const safe&);
+ safe char_(const safe&);
+ safe chdir(const safe&);
+ safe close(const safe&);
+ safe collect();
+ safe copy(const safe&);
+ safe cos(const safe&);
+ safe cset(const safe&);
+ safe delay(const safe&);
+ safe delete_(const safe&, const safe&);
+ safe detab(const variadic&);
+ safe detab( const safe& x1, const safe& x2,
+ const safe& x3=illegal, const safe& x4=illegal,
+ const safe& x5=illegal, const safe& x6=illegal,
+ const safe& x7=illegal, const safe& x8=illegal );
+ safe display(const safe&, const safe&);
+ safe dtor(const safe&);
+ safe entab(const variadic&);
+ safe entab( const safe& x1, const safe& x2,
+ const safe& x3=illegal, const safe& x4=illegal,
+ const safe& x5=illegal, const safe& x6=illegal,
+ const safe& x7=illegal, const safe& x8=illegal );
+ safe errorclear();
+ safe exit(const safe&);
+ safe exp(const safe&);
+ safe flush(const safe&);
+ safe function(); //generative: returns a list
+ safe get(const safe&);
+ safe getch();
+ safe getche();
+ safe getenv(const safe&);
+ safe iand(const safe&, const safe&);
+ safe icom(const safe&);
+ safe image(const safe&);
+ safe insert(const safe&, const safe&, const safe&);
+ safe integer(const safe&);
+ safe ior(const safe&, const safe&);
+ safe ishift(const safe&, const safe&);
+ safe ixor(const safe&, const safe&);
+ safe kbhit();
+ safe left(const safe&, const safe&, const safe&);
+ safe list(const safe&, const safe&);
+ safe loadfunc(const safe&, const safe&);
+ safe log(const safe&);
+ safe map(const safe&, const safe&, const safe&);
+ safe member(const safe&, const safe&);
+ safe name(const safe&);
+ safe numeric(const safe&);
+ safe open(const safe&, const safe&);
+ safe ord(const safe&);
+ safe pop(const safe&);
+ safe proc(const safe&, const safe&);
+ safe pull(const safe&);
+ safe push(const variadic&);
+ safe push( const safe& x1, const safe& x2,
+ const safe& x3=illegal, const safe& x4=illegal,
+ const safe& x5=illegal, const safe& x6=illegal,
+ const safe& x7=illegal, const safe& x8=illegal );
+ safe put(const variadic&);
+ safe put( const safe& x1, const safe& x2,
+ const safe& x3=illegal, const safe& x4=illegal,
+ const safe& x5=illegal, const safe& x6=illegal,
+ const safe& x7=illegal, const safe& x8=illegal );
+ safe read(const safe&);
+ safe reads(const safe&, const safe&);
+ safe real(const safe&);
+ safe remove(const safe&);
+ safe rename(const safe&, const safe&);
+ safe repl(const safe&, const safe&);
+ safe reverse(const safe&);
+ safe right(const safe&, const safe&, const safe&);
+ safe rtod(const safe&);
+ safe runerr(const safe&, const safe&);
+ safe runerr(const safe&);
+ safe seek(const safe&, const safe&);
+ safe serial(const safe&);
+ safe set(const safe&);
+ safe sin(const safe&);
+ safe sort(const safe&, const safe&);
+ safe sortf(const safe&, const safe&);
+ safe sqrt(const safe&);
+ safe stop();
+ safe stop(const variadic&);
+ safe stop( const safe& x1, const safe& x2,
+ const safe& x3=illegal, const safe& x4=illegal,
+ const safe& x5=illegal, const safe& x6=illegal,
+ const safe& x7=illegal, const safe& x8=illegal );
+ safe string(const safe&);
+ safe system(const safe&);
+ safe table(const safe&);
+ safe tan(const safe&);
+ safe trim(const safe&, const safe&);
+ safe type(const safe&);
+ safe variable(const safe&);
+ safe where(const safe&);
+ safe write();
+ safe write(const variadic&);
+ safe write( const safe& x1, const safe& x2,
+ const safe& x3=illegal, const safe& x4=illegal,
+ const safe& x5=illegal, const safe& x6=illegal,
+ const safe& x7=illegal, const safe& x8=illegal );
+ safe writes(const variadic&);
+ safe writes( const safe& x1, const safe& x2,
+ const safe& x3=illegal, const safe& x4=illegal,
+ const safe& x5=illegal, const safe& x6=illegal,
+ const safe& x7=illegal, const safe& x8=illegal );
+ //generative functions follow, crippled to return a single value
+ safe any(const safe&, const safe&, const safe&, const safe&);
+ safe many(const safe&, const safe&, const safe&, const safe&);
+ safe upto(const safe&, const safe&, const safe&, const safe&);
+ safe find(const safe&, const safe&, const safe&, const safe&);
+ safe match(const safe&, const safe&, const safe&, const safe&);
+ safe bal(const safe&, const safe&, const safe&, const safe&, const safe&, const safe&);
+ safe move(const safe&);
+ safe tab(const safe&);
+}; //namespace Icon
+
diff --git a/ipl/packs/loadfuncpp/doc/loadfuncpp.htm b/ipl/packs/loadfuncpp/doc/loadfuncpp.htm
new file mode 100644
index 0000000..50fc4b8
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/loadfuncpp.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+
+<HEAD>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
+ <TITLE>loadfuncpp</TITLE>
+ <LINK REL="stylesheet" TYPE="text/css" HREF="loadfuncpp.css">
+</HEAD>
+
+<BODY>
+
+<H3></H3>
+<CENTER>
+<P>
+<TABLE BORDER="0" WIDTH="700">
+ <TR>
+ <TD WIDTH="100%">
+ <H1 ALIGN="CENTER"><BR>
+ Loadfuncpp</H1>
+ <H2 ALIGN="CENTER">Experimental Binary Distribution</H2>
+ <H3 ALIGN="CENTER">Carl Sturtivant, February 2010</H3>
+ <BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <P>All versions are in the public domain as of now.<BR>
+ <BR>
+ <FONT COLOR="#FF9900">All versions are provisional, experimental and hacked off at speed</FONT>; sane behavior
+ is no more than probable so <B><FONT COLOR="#CC0000">use at your own risk</FONT></B><FONT COLOR="#CC0000">.</FONT></P>
+
+ <P>Read the <A HREF="manual.htm#Installation" target="_blank">documentation</A> for information on installation
+ and use. Everything is simplest if all shared objects are placed in the icon/bin directory and all linkable Icon
+ (.u1/.u2 files) are placed in the icon/lib directory.
+ </BLOCKQUOTE>
+ </BLOCKQUOTE>
+ </TD>
+ </TR>
+</TABLE>
+
+</CENTER>
+
+</BODY>
+
+</HTML>
diff --git a/ipl/packs/loadfuncpp/doc/makelist.cpp b/ipl/packs/loadfuncpp/doc/makelist.cpp
new file mode 100644
index 0000000..90b8c5d
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/makelist.cpp
@@ -0,0 +1,16 @@
+
+/* Example of a C++ extension to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Type 'make iexample' to build.
+ * Carl Sturtivant, 2008/3/16
+ */
+
+#include "loadfuncpp.h"
+using namespace Icon;
+
+extern "C" int makelist(int argc, value argv[]) {
+ safe arglist(argc, argv);
+ argv[0] = arglist;
+ return SUCCEEDED;
+}
+
diff --git a/ipl/packs/loadfuncpp/doc/makelist.icn b/ipl/packs/loadfuncpp/doc/makelist.icn
new file mode 100644
index 0000000..e5e4cd8
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/makelist.icn
@@ -0,0 +1,10 @@
+
+link loadfuncpp
+
+
+procedure main()
+ makelist := loadfuncpp("./makelist.so", "makelist")
+ write(image( ls := makelist(1,2,3) ))
+ every write(!ls)
+end
+
diff --git a/ipl/packs/loadfuncpp/doc/manual.htm b/ipl/packs/loadfuncpp/doc/manual.htm
new file mode 100644
index 0000000..38046e1
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/manual.htm
@@ -0,0 +1,1558 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+
+<HEAD>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
+ <TITLE>loadfuncpp</TITLE>
+ <LINK REL="stylesheet" TYPE="text/css" HREF="loadfuncpp.css">
+</HEAD>
+
+<BODY>
+
+<CENTER>
+<P>
+<TABLE BORDER="0" WIDTH="700">
+ <TR>
+ <TD WIDTH="100%">
+ <H1 ALIGN="CENTER"><BR>
+ Loadfuncpp</H1>
+ <H2 ALIGN="CENTER">How to Write External Functions and Libraries<BR>
+ for <A HREF="http://www.cs.arizona.edu/icon/lb3.htm" target="_blank">The Icon Programming Language</A> in C++</H2>
+ <H3 ALIGN="CENTER">Carl Sturtivant, February 2010, <FONT COLOR="#FF9900">version 0.91alpha</FONT></H3>
+ <BLOCKQUOTE>
+ <H2><A NAME="Contents"></A>Contents</H2>
+ <UL>
+ <LI><A HREF="#Contents">Contents</A>
+ <LI><A HREF="#Summary">Summary</A>
+ <LI><A HREF="#Installation">Installation</A>
+ <UL>
+ <LI><A HREF="#CorrectIconInstallation">Correct Icon Installation</A>
+ <LI><A HREF="#DefaultPlacement">Default Placement of Loadfuncpp Files</A>
+ <LI><A HREF="#AlternativePlacement">Alternative Placement of Loadfuncpp Files</A>
+ <LI><A HREF="#LoadfuncppInstallationTest">Loadfuncpp Installation Test</A>
+ </UL>
+ <LI><A HREF="#Manual">Manual</A>
+ <UL>
+ <LI><A HREF="#Writing">Writing, Loading and Calling an External Function</A>
+ <LI><A HREF="#Working">Working with Icon Values</A>
+ <UL>
+ <LI><A HREF="#Initialization">Assignment &amp; Initialization</A>
+ <LI><A HREF="#Operations">Icon Operations</A>
+ <LI><A HREF="#Functions">Icon Built-in Functions</A>
+ <LI><A HREF="#Keywords">Icon Keywords</A>
+ <LI><A HREF="#Types">Types, Conversions and Errors</A>
+ </UL>
+ <LI><A HREF="#Variadic">Variadic Functions and Dynamic List Construction</A>
+ <LI><A HREF="#Calling">Calling Icon from C++</A>
+ <LI><A HREF="#Generators">Working with Generators</A>
+ <UL>
+ <LI><A HREF="#Generate">Writing External Functions that are Generators</A>
+ <LI><A HREF="#Iterate">Calling Icon Procedures that are Generators in C++</A>
+ <LI><A HREF="#Bang">Iterating over Exploded Structures in C++</A>
+ <LI><A HREF="#Coexpressions">Working with Coexpressions in C++</A>
+ </UL>
+ <LI><A HREF="#Externals">Working with External Values</A>
+ <LI><A HREF="#Records">Using Icon Records as Objects</A>
+ </UL>
+ </UL>
+ <H2><A NAME="Summary"></A>Summary</H2>
+ <P>Since 1996 a new function for Version 9 of <A HREF="http://www.cs.arizona.edu/icon/" target="_blank">Icon</A>
+ could be written in C following a certain <A HREF="http://www.cs.arizona.edu/icon/current/cfuncs.htm" target="_blank">interface</A>,
+ and compiled into a shared library, where such is a <A HREF="http://www.ibm.com/developerworks/library/l-shobj/"
+ target="_blank">shared object</A> (.so) under Unix-like operating systems. More recently this has been implemented
+ using dynamically linked libraries (DLLs) under <A HREF="http://www.cs.arizona.edu/icon/v950/relnotes.htm"
+ target="_blank">cygwin</A>. The library could then be dynamically loaded by an Icon program calling the built-in
+ function <A HREF="http://www.cs.arizona.edu/icon/current/cfuncs.htm" target="_blank">loadfunc</A> which is passed
+ the location and name of the library and the name of the C function desired, and which returns an Icon function
+ that can subsequently be called. A suite of useful <A HREF="http://www.cs.arizona.edu/icon/library/fcfuncs.htm"
+ target="_blank">examples</A> of this technique is a part of the distribution of Icon.</P>
+ <P>Writing a significantly complex external function for use by <A HREF="http://www.cs.arizona.edu/icon/current/cfuncs.htm"
+ target="_blank">loadfunc</A> is potentially difficult for two reasons. First, an Icon structure (or other value,
+ string, list, set, table, et cetera) referred to solely by variables inside external code could be garbage collected
+ by Icon. Second, working directly with Icon data more complex than numbers, strings and files requires a thorough
+ understanding of the <A HREF="http://www.cs.arizona.edu/icon/ftp/doc/ib1up.pdf" target="_blank">implementation
+ of Icon</A>. The Icon runtime system is implemented in an <A HREF="http://www.cs.arizona.edu/icon/ftp/doc/ipd261.pdf"
+ target="_blank">extension of C</A> that is automatically translated into C. The design of the Icon virtual machine
+ is not object oriented, and contains a great deal of straight-line code. Icon structures are operated upon as combinations
+ of complex linked blocks. Writing code to work directly with such is lengthy, error prone and time consuming.</P>
+ <P>Loadfuncpp is a tool that makes writing external functions for Icon a relatively simple matter, requiring very
+ little understanding of the implementation of the Icon virtual machine. Loadfuncpp exploits the close compatibility
+ of C and C++ to provide a clean abstract interface to Icon. External functions for Icon are declared with C linkage,
+ and the Icon virtual machine requires no modification to use external functions written using loadfuncpp.</P>
+ <P>Beginning C++ programmers with programming experience in other languages should have little difficulty with
+ using loadfuncpp. It is not necessary to use templates, exceptions, or RTTI to use loadfuncpp. Little beyond some
+ C experience plus how to define a simple class with virtual and non-virtual member functions is needed to use loadfuncpp.
+ So C programmers with OOP experience but without C++ experience will also find loadfuncpp not difficult to use.</P>
+ <P>Loadfuncpp makes extensive use of operator overloading and other techniques to provide in C++ essentially the
+ same suite of operations, functions and capabilities that are available to the Icon programmer in Icon. The use
+ of these facilities in C++ is at most an order of magnitude more difficult than the corresponding Icon, and is
+ often much easier than that. These facilities include the ability to write external functions that suspend a sequence
+ of results, and the ability to call an Icon procedure that returns a value, which may in turn call a function that
+ calls Icon recursively in the same fashion.</P>
+ <P>These facilities also include the ability to create, activate and refresh coexpressions, the ability to write
+ external functions that are new string matching or string analysis functions, and the ability to work with all kinds
+ of Icon data as if they were built-in types. Loadfuncpp also provides garbage collection safety as a matter of
+ course, largely transparently to the C++ programmer. Loadfuncpp also provides a simple way to add new datatypes
+ to Icon using the new <A HREF="http://www.cs.arizona.edu/icon/v950/extlvals.htm" target="_blank">external values</A>
+ added to Icon version 9.5 in 2008. These are used extensively by loadfuncpp, and so loadfuncpp cannot be used with
+ versions of Icon prior to 9.5.</P>
+ <P>Loadfuncpp consists of three shared libraries (iload.so, loadnogpx.so and iloadgpx.so) normally placed in the
+ icon/bin directory (all are actually DLLs under cygwin despite the .so filename extension, and import library called
+ iload.a is used to link to them under cygwin) together with a small amount of Icon in loadfuncpp.icn, compiled
+ into loadfuncpp.u1 and loadfuncpp.u2 (using 'icont -c loadfuncpp.icn') which are normally placed in the icon/lib
+ directory. Loadfuncpp may then be used by an Icon program by adding the line 'link loadfuncpp' which makes the
+ function loadfuncpp available to Icon.</P>
+ <P>The function loadfuncpp is used in place of loadfunc to dynamically load external functions written to use the
+ loadfuncpp interface. The library containing loadfuncpp is itself loaded by an implicit call to loadfunc. The first
+ call to loadfuncpp loads iload.so (and also loads iloadgpx.so if the Icon installation supports graphics and iloadnogpx.so
+ if not) and replaces loadfuncpp by an external function in iload.so of the same name. This sequence of events makes
+ the C++ interface in iload.so available to all libraries subsequently loaded by Icon through calls of loadfuncpp.</P>
+ <H2><A NAME="Installation"></A>Installation</H2>
+ <P>Installation of Loadfuncpp is in three parts. First ensuring a correct Icon installation. Second placing the
+ loadfuncpp files appropriately. And third, ensuring that environment variables are set appropriately if the default
+ locations of loadfuncpp files are not used.</P>
+ <H3><A NAME="CorrectIconInstallation"></A>Correct Icon Installation</H3>
+ <P>You will need to install Icon version 9.5 Loadfuncpp to run. To verify you are running the correct version of
+ Icon, use `<A HREF="http://www.cs.arizona.edu/icon/refernce/icontx.htm#icont" target="_blank">icont</A> -V` and
+ `<A HREF="http://www.cs.arizona.edu/icon/refernce/icontx.htm#iconx" target="_blank">iconx</A> -V`.
+ <H3><A NAME="DefaultPlacement"></A>Default Placement of Loadfuncpp Files</H3>
+ <P>Loadfuncpp consists of the following files. Starting now (2010/2/8) loadfuncpp is available as an <A HREF="loadfuncpp.htm"
+ target="_blank">experimental source distribution.</A> I intend to do no further work on it. Use <I>make</I> and
+ examine the following files.
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="585">
+ <TR>
+ <TD WIDTH="26%">
+ <P>iload.so
+ </TD>
+ <TD WIDTH="74%">
+ <P>C++ part of the loadfuncpp interface to <A HREF="http://www.cs.arizona.edu/icon/refernce/icontx.htm#iconx" target="_blank">iconx</A>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="26%">
+ <P>loadfuncpp.icn
+ </TD>
+ <TD WIDTH="74%">
+ <P>Icon part of the loadfuncpp interface to <A HREF="http://www.cs.arizona.edu/icon/refernce/icontx.htm#iconx"
+ target="_blank">iconx</A>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="26%">
+ <P>iloadgpx.so
+ </TD>
+ <TD WIDTH="74%">
+ <P>C++ interface needed with the graphics build of Icon
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="26%">
+ <P>iloadnogpx.so
+ </TD>
+ <TD WIDTH="74%">
+ <P>C++ interface needed with the non-graphics build of Icon
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="26%">
+ <P>loadfuncpp.h
+ </TD>
+ <TD WIDTH="74%">
+ <P>C++ header for writing new external functions
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>The default installation of these files is as follows. (Here we assume that the directory containing your Icon
+ installation is called icon.) I recommend that you use these locations unless there is a compelling reason not
+ to.</P>
+ <P>
+ <TABLE BORDER="0" WIDTH="585">
+ <TR>
+ <TD WIDTH="26%">
+ <P>iload.so
+ </TD>
+ <TD WIDTH="74%">
+ <P>icon/bin
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="26%">
+ <P>iload.a
+ </TD>
+ <TD WIDTH="74%">
+ <P>icon/bin (cygwin only)
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="26%">
+ <P>loadfuncpp.u1
+ </TD>
+ <TD WIDTH="74%">
+ <P>icon/lib (from loadfuncpp.icn)
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="26%">
+ <P>loadfuncpp.u2
+ </TD>
+ <TD WIDTH="74%">
+ <P>icon/lib (from loadfuncpp.icn)
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="26%">
+ <P>iloadgpx.so
+ </TD>
+ <TD WIDTH="74%">
+ <P>icon/bin
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="26%">
+ <P>iloadnogpx.so
+ </TD>
+ <TD WIDTH="74%">
+ <P>icon/bin
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="26%">
+ <P>loadfuncpp.h
+ </TD>
+ <TD WIDTH="74%">
+ <P>wherever is convenient to #include in C++ source
+ </TD>
+ </TR>
+ </TABLE>
+<BR>
+ Under <I>cygwin only</I> there is one additional file used when <A HREF="compile.htm" target="_blank">linking</A>
+ a dynamic library that uses loadfuncpp. This is the windows import library iload.a, and is most naturally placed
+ in the same directory as iload.so, as it contains the information necessary to link against it.
+ <H3><A NAME="AlternativePlacement"></A>Alternative Placement of Loadfuncpp Files</H3>
+ <P>Alternatively, you can place iload.so and iloadgpx.so anywhere you please and set the environment variable FPATH
+ to include the directories containing iload.so and iloadgpx.so. FPATH should be a space or colon separated string
+ of locations. You can compile loadfuncpp.icn using `icont -c loadfuncpp.icn` and place the resulting files (loadfuncpp.u1
+ and loadfuncpp.u2) in any directory and set the environment variable IPATH to include that directory. IPATH should
+ also be a space or colon separated string of locations.
+ <H3><A NAME="LoadfuncppInstallationTest"></A>Loadfuncpp Installation Test</H3>
+ <P>Once loadfuncpp is installed, you may test your installation by creating a small new external function and load
+ and call it from Icon. Here's how.</P>
+ <P>
+ <UL>
+ <LI>Create a new directory, place a copy of loadfuncpp.h in it and work there
+ <LI>Edit a new file called (say) hello.cpp to contain the following code
+ <P>
+ <TABLE BORDER="0" WIDTH="312">
+ <TR>
+ <TD WIDTH="312">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">#include &quot;loadfuncpp.h&quot;
+
+extern &quot;C&quot; int hello(value argv[]) {
+ argv[0] = &quot;Hello World&quot;;
+ return SUCCEEDED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+
+ <LI>Compile hello.cpp into a shared object hello.so using one of these <A HREF="compile.htm" target="_blank">compiler
+ options</A>
+ <LI>Edit a new file called (say) hello.icn to contain the following code and ensure that hello.so is in the same
+ directory
+ <P>
+ <TABLE BORDER="0" WIDTH="392">
+ <TR>
+ <TD WIDTH="392">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">link loadfuncpp
+
+procedure main()
+ hello := loadfuncpp(&quot;./hello.so&quot;, &quot;hello&quot;, 0)
+ write( hello() )
+end</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+
+ <LI>Compile hello.icn by typing `icont hello.icn` and run it by typing `./hello` and you should get the output
+ <FONT COLOR="black">Hello World</FONT> appearing in the console.
+ </UL>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE ALIGN="CENTER">
+ <UL>
+ <P>
+ </UL>
+ <P>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <H2><A NAME="Manual"></A>Manual</H2>
+ <P>This manual assumes that you have a <A HREF="#Installation">working installation</A> of Loadfuncpp and Icon
+ as described above. An installation of Icon alone is not sufficient, nor can Loadfuncpp be used with any Icon version
+ prior to 9.5, as it relies upon the presence of <A HREF="http://www.cs.arizona.edu/icon/v950/extlvals.htm"
+ target="_blank">external values</A> which are first implemented as a part of that version.</P>
+ <H3><A NAME="Writing"></A>Writing, Loading and Calling a new External Function</H3>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE ALIGN="CENTER">
+ <P>A new Icon external function written in C++ takes one of the following forms.
+ </BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="432">
+ <TR>
+ <TD WIDTH="432">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">#include &quot;loadfuncpp.h&quot;
+
+extern &quot;C&quot; int fixed_arity(value argv[]) {
+ // ... has a fixed number of arguments
+ return SUCCEEDED; //or FAILED
+}
+
+extern &quot;C&quot; int variable_arity(int argc, value argv[]){
+ // ... has a variable number of arguments
+ return SUCCEEDED; //or FAILED
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>The C++ type 'value' is an Icon value (called a <A HREF="http://www.cs.arizona.edu/icon/current/cfuncs.htm" target="_blank">descriptor</A>),
+ representing null or an integer, real, string, cset, list, table, set, file, procedure, coexpression, record, <A
+ HREF="http://www.cs.arizona.edu/icon/v950/extlvals.htm" target="_blank">external value</A> or an Icon <A HREF="#Variable">variable</A>.
+ When such a function is called from Icon, its arguments are passed in the array argv starting from argv[1], and
+ argv[0] is taken to be the value returned to Icon by the function. In the function variable_arity the number of
+ arguments is also passed in argc. So the following is a one argument external function that returns its only argument.
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="432">
+ <TR>
+ <TD WIDTH="432">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">#include &quot;loadfuncpp.h&quot;
+
+extern &quot;C&quot; int ident(value argv[]) {
+ argv[0] = argv[1];
+ return SUCCEEDED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>The int returned to C++ is a signal to Icon indicating whether the call succeeded or failed. These are represented
+ by the constants SUCCEEDED and FAILED respectively, defined in loadfuncpp.h. However there is also a simple mechanism
+ in loadfuncpp to write <A HREF="#Generate">external functions that suspend a sequence of values</A> when called
+ in Icon.</P>
+ <P>Functions <A HREF="compile.htm" target="_blank">compiled into a shared object</A> are loaded into Icon by calls
+ of loadfuncpp. Such calls indicate to Icon whether the loaded function has a variable or a fixed number of arguments,
+ and if the latter, how many. For example the preceding functions might be loaded into Icon as follows if the body
+ of fixed_arity was written to use two arguments.
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="464">
+ <TR>
+ <TD WIDTH="464">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">link loadfuncpp
+
+procedure main()
+ fixed := loadfuncpp(&quot;./mylib.so&quot;, &quot;fixed_arity&quot;, 2)
+ variadic := loadfuncpp(&quot;./mylib.so&quot;, &quot;variable_arity&quot;)
+ #fixed and variadic now contain Icon functions
+ #and may be treated like any other such values
+end</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>If the number of arguments is not specified when loading a function of fixed <A HREF="http://en.wikipedia.org/wiki/Arity">arity</A>
+ then calling the result from Icon will lead to a memory violation. (Similar behavior will likely occur if a function
+ of variable arity is loaded with a specific arity specified, or if too small an arity is specified for a fixed
+ arity function.) Beware!<BR>
+ <BR>
+ A relative or absolute path to the shared object may be used as the first argument to loadfuncpp, in which case
+ loadfuncpp will look exactly where specified for it and nowhere else. <B>Alternatively, just the filename of the
+ shared object may be specified, in which case Icon will search FPATH for the file.</B> If FPATH is not set in the
+ environment Icon runs in, then iconx defines FPATH to consist of the current directory followed by the icon/bin
+ directory. If FPATH is set in the environment Icon is run in, then iconx appends the icon/bin directory. In either
+ case FPATH should be a space or colon separated series of directories, with no spaces in their paths. (This restriction
+ will be cleaned up &quot;soon&quot;.)</P>
+ <P>All of the C++ in this manual requires '#include &quot;loadfuncpp.h&quot;' and all of the Icon requires 'link
+ loadfuncpp'. Hereafter this will be assumed implicitly.</P>
+ <P>Here is an external function of no arguments that returns null, represented in C++ by the constant nullvalue.
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="432">
+ <TR>
+ <TD WIDTH="432">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">extern &quot;C&quot; int dull(value argv[]){
+ argv[0] = nullvalue;
+ return SUCCEEDED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>If this is compiled into the shared object 'dull.so' in the current directory then it might be called by Icon
+ as follows.
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="464">
+ <TR>
+ <TD WIDTH="464">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">dull := loadfuncpp(&quot;./dull.so&quot;, &quot;dull&quot;, 0)
+write(image( dull() ))</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>The value of argv[0] when an external function is called is of type procedure, and is the Icon value representing
+ the external function being called. So failure to assign to argv[0] means that Icon loads a function that returns
+ itself.</P>
+ <P>The C++ class <B>value</B> is intended to be used primarily in the interface to Icon. Icon structures in variables
+ of this class are not safe from garbage collection. Icon does guarantee that argv[] is garbage collection safe
+ however.</P>
+ <H3><A NAME="Working"></A>Working with Icon values</H3>
+ <P>Variables of the C++ class <B>safe</B> are intended to hold Icon values with guaranteed garbage collection safety.
+ The interface to Icon is largely available through the class safe. Most computation with Icon values in external
+ functions may be implemented through use of the <A HREF="#Operations">overloaded operators</A> in using this class,
+ along with its member functions that represent <A HREF="#Operations">additional Icon operators</A>. Loadfuncpp
+ also provides the <A HREF="#Keywords">Icon keywords</A> and in the namespace '<A HREF="#Builtin">Icon</A>' provides
+ a C++ variant of each of the <A HREF="#Functions">built-in functions in Icon</A>.</P>
+ <H4><A NAME="Initialization"></A>Assignment and Initialization among safe and value</H4>
+ <P>Assignment of a safe to a safe has the semantics of an Icon assignment. Specifically, if the left operand contains
+ an Icon value that is an <A NAME="Variable"></A>Icon <FONT COLOR="black">variable</FONT> (i.e. an Icon value used
+ to refer to the storage containing another Icon value so that the latter can be modified) then the assignment modifies
+ the value referred to by that Icon variable, not the C++ variable whose value is the Icon variable.</P>
+ <P>Assignment is possible among the classes safe and value, and has simple semantics: even values that are Icon
+ variables are copied. Initialization of variables of the class safe is possible from any of safe and value, with
+ the same simple semantics. In both cases the semantics is the same as Icon assignment, except in the case of an
+ Icon variable, which is merely copied, so that the variable assigned or initialized now contains the same Icon
+ variable. This lack of dereferencing is useful if an external function needs to return an Icon variable, in the
+ same way that an Icon procedure may.</P>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE ALIGN="CENTER">
+ <P>A variable of class safe may also be initialized from an array of values as follows.
+ </BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="432">
+ <TR>
+ <TD WIDTH="432">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">extern &quot;C&quot; int makelist(int argc, value argv[]){
+ safe arglist(argc, argv);
+ argv[0] = arglist;
+ return SUCCEEDED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>Such initialization creates an Icon list containing the values in the array starting from position 1. So the
+ above function called from Icon returns a list of its arguments.</P>
+ <P>A variable of class safe may be initialized by or assigned a C string, which causes an Icon string that is a
+ copy of the original to be created, so that the original can safely be modified or destroyed later. If such copying
+ is unwanted because the C string is a literal or constant, then the two argument value constructor may be used
+ as follows.
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="432">
+ <TR>
+ <TD WIDTH="432">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">extern &quot;C&quot; int f(value argv[]){
+ safe text = value(StringLiteral, &quot;Hello&quot;);
+ // ...
+ return SUCCEEDED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>A variable of class safe may also be initialized by or assigned a C++ long or int causing the creation of an
+ Icon integer. Similarly initialization or assignment of a double causes the creation of an Icon real.</P>
+ <H4><A NAME="Operations"></A>Icon operations on variables of class safe</H4>
+ <P>Here is a table of the overloaded operators and member functions implementing Icon operators for the class safe.
+ These are listed with their Icon equivalents, and with a note of any restrictions or extensions. The <A HREF="#Bang">unary
+ ! operator</A> in Icon is a generator and is supplied through loadfuncpp by <A HREF="#Bang">other means</A>.</P>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE ALIGN="CENTER">
+ <P>
+ <TABLE BORDER="0" WIDTH="585">
+ <TR>
+ <TH COLSPAN="2">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">functions of safe for Icon operators</FONT>
+ </TH>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TH WIDTH="130">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">unary</FONT>
+ </TH>
+ <TH WIDTH="164">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">Icon equivalent</FONT>
+ </TH>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">*x</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">*x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">~x</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">~x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">-x</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">-x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">++x</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x +:= 1</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">--x</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x -:= 1</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><B><FONT SIZE="2" FACE="Courier New, Courier">binary</FONT></B>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><B><FONT SIZE="2" FACE="Courier New, Courier">Icon equivalent</FONT></B>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">=</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">:=</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">+= -= *=</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">+:= -:= *:=</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">/= %= ^=</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">/:= %:= ^:=</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">+</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">+</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">-</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">-</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">*</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">*</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">/</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">/</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">%</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">%</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x^y</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x^y</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x | y</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x ++ y</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x &amp; y</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x ** y</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x &amp;&amp; y</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x -- y</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x || y</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x || y</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">|=</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">++:=</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">&amp;=</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">**:=</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">==</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">===</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">!=</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">~===</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">&lt; &gt; &lt;= &gt;=</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><B><FONT SIZE="2" FACE="Courier New, Courier">none</FONT></B>
+ </TD>
+ <TD WIDTH="271">
+ <P><A HREF="#Compare"><FONT SIZE="2" FACE="Courier New, Courier">The comparison used when sorting</FONT></A>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x[y]</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x[y]</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><B><FONT SIZE="2" FACE="Courier New, Courier">variadic</FONT></B>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><B><FONT SIZE="2" FACE="Courier New, Courier">Icon Equivalent</FONT></B>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x(...)</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x(...)</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><A HREF="#Call"><FONT SIZE="2" FACE="Courier New, Courier">Icon procedure call</FONT></A>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">(a,b ...)</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">[a,b ...]</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><A HREF="#Variadic"><FONT SIZE="2" FACE="Courier New, Courier">Variadic list construction</FONT></A>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><B><FONT SIZE="2" FACE="Courier New, Courier">member function</FONT></B>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><B><FONT SIZE="2" FACE="Courier New, Courier">Icon equivalent</FONT></B>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.slice(y,z)&nbsp;</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x[y:z]</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.apply(y)</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x ! y</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><A HREF="#Call"><FONT SIZE="2" FACE="Courier New, Courier">Apply Icon procedure to arguments</FONT></A>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.listcat(y)</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x ||| y</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.swap(y)</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x :=: y</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.create()</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">create !x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.create(y)</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">create x ! y</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.activate(y)</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">y@x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">y defaults to &amp;null</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.refresh()</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">^x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.random()</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">?x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.dereference()</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">.x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <H4><A NAME="Functions"></A>Icon Built-in Functions</H4>
+ <P>All of the functions built in to Icon are available in C++ in the namespace 'Icon'. The C++ counterpart of an
+ Icon built-in function returns &amp;null if the original function would have failed. Those functions that are generators
+ have been made to produce a single result. Those functions that are <A HREF="#Variadic">variadic</A> have been
+ made C++ compatible too; with a small number of arguments this can usually safely be ignored. The table below lists
+ each C++ variant of each Icon function that is a generator, along with a comment indicating how it has been modified
+ for C++ compatibility.</P>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE ALIGN="CENTER">
+ <P>
+ <TABLE BORDER="0" WIDTH="551">
+ <TR>
+ <TH WIDTH="96">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">Function</FONT>
+ </TH>
+ <TD WIDTH="441">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="96">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">bal</FONT>
+ </TD>
+ <TD WIDTH="441">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">returns the first result generated only</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="96">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">find</FONT>
+ </TD>
+ <TD WIDTH="441">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">returns the first result generated only</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="96">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">function</FONT>
+ </TD>
+ <TD WIDTH="441">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">returns a list of the results originally generated</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="96">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">key</FONT>
+ </TD>
+ <TD WIDTH="441">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">returns a list of the results originally generated</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="96">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">move</FONT>
+ </TD>
+ <TD WIDTH="441">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">cannot be resumed</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="96">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">tab</FONT>
+ </TD>
+ <TD WIDTH="441">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">cannot be resumed</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="96">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">upto</FONT>
+ </TD>
+ <TD WIDTH="441">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">returns the first result generated only</FONT>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <P>Here is an example of the use of such Icon built-in functions in a new external function. The following function
+ returns the set of its arguments.</P>
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="432">
+ <TR>
+ <TD WIDTH="432">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">extern &quot;C&quot; int makeset(int argc, value argv[]){
+ safe arglist(argc, argv);
+ argv[0] = Icon::set(arglist);
+ return SUCCEEDED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <H4><A NAME="Keywords"></A>Icon Keywords</H4>
+ <P>All of the Icon keywords have been made available apart from &amp;cset (to avoid a possible name collision),
+ and &amp;fail. The keywords are implemented through a keyword class with the unary '&amp;' operator overloaded
+ and are used thus in C++, as in the following example.</P>
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="432">
+ <TR>
+ <TD WIDTH="432">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">extern &quot;C&quot; int assignprog(value argv[]){
+ safe newname(argv[1]);
+ &amp;progname = newname; //Icon assignment semantics
+ return FAILED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>The preceding function assigns a new value to the keyword &amp;progname, just as in Icon. In all cases a keyword
+ is used with the unary '&amp;' operator, and therefore appears just as in an Icon program. The keywords that are
+ generators in Icon produce a list of values in C++.</P>
+ <H4><A NAME="Types"></A>Types, Conversions and Errors</H4>
+ <P>A well designed external function will probably do some type checking and conversions of its arguments, and
+ perhaps give a run-time error if they are problematic.</P>
+ <P>The member function <FONT COLOR="black">type()</FONT> in the value class returns one of the following constants
+ indicating its Icon type: <FONT COLOR="black">Null</FONT>, <FONT COLOR="black">Integer</FONT>, <A HREF="#BigInteger">BigInteger</A>,
+ <FONT COLOR="black">Real</FONT>, <FONT COLOR="black">Cset</FONT>, <FONT COLOR="black">File</FONT>, <FONT COLOR="black">Procedure</FONT>,
+ <FONT COLOR="black">Record</FONT>, <FONT COLOR="black">List</FONT>, <FONT COLOR="black">Set</FONT>, <FONT COLOR="black">Table</FONT>,
+ <FONT COLOR="black">String</FONT>, <FONT COLOR="black">Constructor</FONT>, <FONT COLOR="black">Coexpression</FONT>,
+ <FONT COLOR="black">External</FONT>, or <A HREF="#Variable">Variable</A>. Constructor means a record constructor,
+ and <A HREF="#BigInteger">BigInteger</A> is an integer with a binary representation larger than a machine word.</P>
+ <P>The member functions <FONT COLOR="black">isNull()</FONT> and <FONT COLOR="black">notNull()</FONT> in the value
+ class each return a boolean indicating whether or not the Icon type is null. The member functions <FONT COLOR="black">toInteger()</FONT>,
+ <FONT COLOR="black">toReal()</FONT>, <FONT COLOR="black">toNumeric()</FONT>, <FONT COLOR="black">toString()</FONT>
+ and <FONT COLOR="black">toCset()</FONT> in the value class each endeavors to perform a conversion in place to the
+ corresponding type following the same conventions as Icon. Each returns a boolean indicating whether the conversion
+ succeeded. If the conversion failed, then the Icon value remains unchanged. These functions are intended for use
+ with the arguments of an external function supplied to C++ before they are converted to the class safe and the
+ real computation begins. (The use of these functions on the entries in argv[] is garbage-collection safe because
+ Icon protects argv[].) For example to check that we have a string where we would need one as follows.
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="432">
+ <TR>
+ <TD WIDTH="432">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">extern &quot;C&quot; int assignprog(value argv[]){
+ if( !argv[1].toString() ) {
+ Icon::runerr(103, argv[1]);
+ return FAILED; //in case &amp;error is set
+ }
+ safe newname(argv[1]);
+ &amp;progname = newname; //Icon assignment semantics
+ return FAILED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>The function <FONT COLOR="black">syserror(const char*)</FONT> unconditionally and fatally terminates execution
+ with an Icon style error message referring to the point of execution in Icon together with the error message supplied
+ as a C string argument. This nicely complements <FONT COLOR="black">Icon::runerr</FONT>.<BR>
+ <BR>
+ To avoid problems with C++ conversion/overloading ambiguities, the class safe has been provided with a conversion
+ to the class value only, and no conversions to the types char*, int, long or double. On the other hand, the value
+ class has such conversions and so an explicit conversion to value can be used in many contexts to permit an implicit
+ conversion to a built-in type. See below for details.<BR>
+ <BR>
+ The overloaded operators for the class safe defining much of Icon's repertoire in C++ have been defined outside
+ the class safe, with the exception of those such as assignment, subscripting and call that C++ insists be non-static
+ member functions, and almost all such as well as all other member functions have parameters of type safe only.
+ This is so that the wide repertoire of conversions of other types to safe defined by loadfuncpp may be of maximum
+ utility.<BR>
+ <BR>
+ Conversions of char*, double, int and long to safe as well as value are defined, those from the built-in types
+ creating copies on the Icon heap. Specifically, the conversion from char* to safe or to value assumes a null terminated
+ C string, and produces a correspondingly copied Icon string.<BR>
+ <BR>
+ Conversions of value to long and double have been defined. These behave as expected for Icon integers and reals
+ respectively, but perform no conversions within Icon values (from integer to real or vice-versa). <BR>
+ <BR>
+ There is also a conversion from value to char* defined. This does <I>not</I> make a C string, but rather simply
+ produces a pointer to the start of an Icon string, which is not null terminated, and can move in the event of a
+ garbage collection. If null termination is desired, then concatenate the loadfuncpp constant value nullchar before
+ converting to char*, and if a copy outside of Icon is needed, then you will have to explicitly make one. Here is
+ an example.
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="432">
+ <TR>
+ <TD WIDTH="432">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">extern &quot;C&quot; int assignprog(value argv[]){
+ if( !argv[1].toString() ) {
+ Icon::runerr(103, argv[1]);
+ return FAILED; //in case &amp;error is set
+ }
+ safe newname(argv[1]);
+ char* s = value(newname || nullchar); //can move
+ char sbuf[100];
+ sprintf(sbuf, &quot;%s&quot;, s);
+ //use the local copy sbuf
+ //...
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+
+ </BLOCKQUOTE>
+ <P>The non-member functions <FONT COLOR="black">bytestointeger</FONT> and <FONT COLOR="black">integertobytes</FONT>
+ are useful to overtly convert to and from Icon integers of any size (i.e. type <FONT COLOR="black">Integer</FONT>
+ or <A HREF="#BigInteger">BigInteger</A> behind the scenes). Both functions take a value and return a value. In
+ this context Icon strings are considered to be representations of natural numbers. Each character is considered
+ a base 256 digit in the obvious way, and the digits are defined to be in order from most to least significant.
+ The empty string represents zero. <FONT COLOR="black">bytestointeger</FONT> takes such a string and produces the
+ corresponding Icon integer. <FONT COLOR="black">integertobytes</FONT> takes an Icon integer and produces an Icon
+ string representing its absolute value in the preceding sense. Neither function attempts type conversions, so for
+ meaningful results they must be passed respectively a string value and an integer value.<BR>
+ <BR>
+ The non-member functions <FONT COLOR="black">base64</FONT>, <FONT COLOR="black">base64tointeger</FONT> and <FONT
+ COLOR="black">base64tostring</FONT> are useful to overtly convert strings and integers of any size to and from
+ the commonly used <A HREF="http://www.faqs.org/rfcs/rfc3548.html">base64</A> encoding. Each function takes a value
+ and returns a value, and none attempts any type conversion of its arguments. <FONT COLOR="black">base64</FONT>
+ may be passed an Icon integer or string and produces a string containing the base64 encoding thereof. The sign
+ of an integer is ignored, so the base64 encoding of its absolute value is produced. <FONT COLOR="black">base64tointeger</FONT>
+ may be passed an Icon string that is a strict base64 encoding in which case it returns the corresponding Icon integer,
+ and similarly <FONT COLOR="black">base64tostring</FONT> may be passed an Icon string that is a strict base64 encoding
+ in which case it returns the corresponding Icon string. By strict base64 encoding is meant that the string's length
+ is a multiple of four, that the end of the string is a sequence of between zero and two &quot;=&quot; characters
+ (used to pad the file length to a multiple of four when encoding), and apart from that the remaining characters
+ in the string are either lower or upper case letters, or digits, or the characters &quot;/&quot; and &quot;+&quot;.
+ Failure to supply a string containing a strict base64 encoding to either function will cause null to be returned.</P>
+ <H3><A NAME="Variadic"></A><A HREF="http://en.wikipedia.org/wiki/Variadic_function">Variadic Functions</A> and
+ Dynamic List Construction</H3>
+ <P>Some built-in Icon functions take an arbitrary number of arguments. Unfortunately, C++ as of the present standard
+ has no convenient way to define a function with an arbitrary number of arguments of the same type. So variadic
+ functions included in the namespace 'Icon' such as <FONT COLOR="black">writes</FONT> are defined in two versions.
+ The first has at most eight arguments, with defaults and glue code to account for fewer being supplied. This takes
+ care of most uses of such functions.</P>
+ <P>The second uses a single argument of the class variadic, which is a wrapper for an Icon list of the arguments.
+ The operator ',' (comma) has been overloaded so as to combine two locals into a variadic, and to combine a variadic
+ and a safe so as to append the safe's value to the variadic's list. A variadic has a conversion to safe that in
+ effect removes the wrapper, and there are other sundry conversions and overloads of comma. These enable lists to
+ be constructed in place, providing a syntactic equivalent of things like <FONT COLOR="black">[x,y,z]</FONT> in
+ Icon, namely <FONT COLOR="black">(x,y,z)</FONT> in C++. The second implementation of writes may then be called
+ as <FONT COLOR="black">writes((x,y,z))</FONT>. The second pair of parentheses is necessary as comma is not regarded
+ as an operator by C++ when it is in a parameter list. Here is an example of the use of dynamic list construction.</P>
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="432">
+ <TR>
+ <TD WIDTH="432">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">extern &quot;C&quot; int divide(value argv[]){
+ safe x(argv[1]), y(argv[2]);
+ argv[0] = (x / y, x % y);
+ return SUCCEEDED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <H3><A NAME="Calling"></A>Calling Icon from C++</H3>
+ <P>The class safe has overloaded the function call operator '()' so that a safe may be called with function call
+ syntax. If the value of the safe is an Icon procedure (or function or record constructor) the effect is to call
+ Icon from C++. There are two kinds of restrictions on these calls.</P>
+ <P>The first restriction is because C++ requires a specific <A HREF="http://en.wikipedia.org/wiki/Arity" target="_blank">arity</A>
+ when overloading the function call operator, and has no convenient way to handle an arbitrary number of parameters
+ of the same type. This restriction is the same one affecting the calling of <A HREF="#Variadic">variadic functions</A>,
+ and is overcome in the same way with <A HREF="#Variadic">two implementations</A>. One with a single argument of
+ class variadic necessitating <A HREF="#Variadic">two pairs of parentheses</A> when the call is made, and the other
+ with up to eight arguments and useful for most procedure calls.</P>
+ <P>The second restriction is because there are three ways Icon can pass control back to a caller: by returning
+ a value, by failing and by suspending a value. However, there is only one way for C++ to receive control back from
+ a call it has made: by a value (possibly void) being returned. For this reason a call of an Icon procedure from
+ C++ will return &amp;null if the procedure fails, and will return rather than suspend if the procedure suspends
+ a value. In either case, the call always returns cleanly with a single value. It is possible to <A HREF="#Iterate">iterate
+ through the values suspended by an Icon procedure</A> in C++ through a different mechanism.</P>
+ <H3><A NAME="Generators"></A>Working with Generators from C++</H3>
+ <P>Generators and the flow of control in Icon have no counterpart in C++. Nevertheless, it is useful to be able
+ to both implement generators for Icon in C++, and iterate through generator sequences produced by Icon in C++,
+ as well as create coexpressions in C++. All these facilities are provided by loadfuncpp.</P>
+ <H4><A NAME="Generate"></A>Writing External Functions that are Generators</H4>
+ <P>Here is an example of a generator function written in C++. It is a C++ implementation of the built-in Icon function
+ <FONT COLOR="black">seq</FONT>, without the restriction to machine size integers.</P>
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="456">
+ <TR>
+ <TD WIDTH="456">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">class sequence: public generator {
+ safe current, inc;
+ public:
+ sequence(local start, local increment) {
+ current = start - increment;
+ inc = increment;
+ }
+ virtual bool hasNext() {
+ return true;
+ }
+ virtual value giveNext() {
+ return current += inc;
+ }
+};
+
+extern &quot;C&quot; int seq2(value argv[]){
+ sequence seq(argv[1], argv[2]);
+ return seq.generate(argv);
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>This exemplifies all the features of loadfuncpp that enable generator functions to be written. First a C++ version
+ of the generator is written as a class that inherits from the loadfuncpp class generator. Some data members are
+ added to maintain state as generation occurs, and a constructor is written to initialize those data members. Finally
+ the virtual functions <FONT COLOR="black">hasNext()</FONT> and <FONT COLOR="black">giveNext()</FONT> with exactly
+ the above prototypes are overloaded. The sequence generated by an object of this class is defined to be that produced
+ by repeatedly calling <FONT COLOR="black">hasNext()</FONT> to determine if there is a next member of the sequence,
+ and if there is, calling <FONT COLOR="black">giveNext()</FONT> to get it.</P>
+ <P>Now the external function itself simply creates a generator object of the above class, presumably using values
+ passed to it from Icon to initialize that object's state. Then the inherited member function <FONT COLOR="black">generate</FONT>
+ is called, passing the original argument array for technical reasons, and the signal it returns is passed back
+ to Icon. The effect of this call is to iterate through the calls of <FONT COLOR="black">giveNext()</FONT> while
+ <FONT COLOR="black">hasNext()</FONT> returns true, suspending the results produced by each call of <FONT COLOR="black">giveNext()</FONT>
+ to Icon. In a nutshell the call to <FONT COLOR="black">generate</FONT> suspends the sequence of results produced
+ by the object to Icon. The reason that <FONT COLOR="black">generate</FONT> needs to be passed argv is that it needs
+ to send its results to Icon by assigning to argv[0], in just as a single result is passed back.</P>
+ <H4><A NAME="Iterate"></A>Calling Icon Procedures that are Generators from C++</H4>
+ <P>Here is an example of how to iterate over the results of a call of an Icon procedure. In the example the procedure
+ to be called and its argument list are presumed to be the arguments passed to the external function, which then
+ computes the sum of the first ten results suspended by the call, or the sum of all the results if less than ten
+ results are computed.</P>
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="456">
+ <TR>
+ <TD WIDTH="456">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">class addup: public iterate {
+ public:
+ safe total;
+ int count;
+
+ addup(): total(0), count(0) {}
+
+ virtual void takeNext(const value&amp; x) {
+ total += x;
+ }
+ virtual bool wantNext(const value&amp; x) {
+ return ++count &lt;= 10;
+ }
+};
+
+extern &quot;C&quot; int sum10(value argv[]){
+ addup sum;
+ sum.every(argv[1], argv[2]);
+ argv[0] = sum.total;
+ return SUCCEEDED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>This exemplifies all the features of loadfuncpp that enable the results of a call to Icon to be iterated over
+ in C++. First a class representing the loop that will iterate over the generator sequence is written, inheriting
+ from the loadfuncpp class iterate. The data members of that class model the variables used in the loop, and the
+ constructor models the initialization of those loop variables. It is convenient that these be public along with
+ everything else; the class could be declared as a struct to achieve this. The two inherited virtual member functions
+ <FONT COLOR="black">wantNext()</FONT> and <FONT COLOR="black">takeNext()</FONT> with exactly the above prototypes
+ are then overridden. The function <FONT COLOR="black">wantNext()</FONT> models the loop condition: it returns true
+ if the loop will process the next result produced by the generator, and false if the loop should be terminated.
+ The function <FONT COLOR="black">takeNext()</FONT> models the loop body: it will be passed each result produced
+ by the generator, and may modify the loop variables accordingly.</P>
+ <P>Now the external function itself simply creates an object of this class, using the constructor to initialize
+ the loop variables, or simply assigning to them directly. This models setup code before the loop proper starts.
+ Then the inherited member function <FONT COLOR="black">every</FONT> is called with the generator function and its
+ argument list as arguments to the call. The call of <FONT COLOR="black">every</FONT> models executing the loop
+ body by calling the generator function applied to its argument list and repeatedly alternately calling <FONT COLOR="black">wantNext()</FONT>
+ to see if the loop should continue and <FONT COLOR="black">takeNext()</FONT> to pass the loop body the next result
+ produced by the call to Icon. The loop is terminated either by <FONT COLOR="black">wantNext()</FONT> returning
+ false or by the sequence of results generated by the call to Icon coming to an end, whichever occurs first.</P>
+ <H4><A NAME="Bang"></A>Iterating over Exploded Structures in C++</H4>
+ <P>This feature of loadfuncpp enables iteration over the results that would be generated in Icon by an expression
+ of the form <FONT COLOR="black">!x</FONT>, with one important difference: if <FONT COLOR="black">x</FONT> is a
+ table, then the results iterated over are those that would be produced by the Icon expression <FONT COLOR="black">key(x)</FONT>.
+ The technique use to perform such an iteration is almost identical to that used to <A HREF="#Iterate">iterate over
+ the results of a call to an Icon procedure</A>. The only difference is that a different inherited member function
+ (<FONT COLOR="black">bang</FONT>) is called to run the iteration. Here is an example that sums the first ten elements
+ of a list by quite unnecessarily using this technique.</P>
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="456">
+ <TR>
+ <TD WIDTH="456">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">class addup: public iterate {
+ public:
+ safe total;
+ int count;
+
+ addup(): total(0), count(0) {}
+
+ virtual void takeNext(const value&amp; x) {
+ total += x;
+ }
+ virtual bool wantNext(const value&amp; x) {
+ return ++count &lt;= 10;
+ }
+};
+
+extern &quot;C&quot; int sumlist(value argv[]) {
+ addup sum;
+ sum.bang(argv[1]);
+ argv[0] = sum.total;
+ return SUCCEEDED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <H4><A NAME="Coexpressions"></A>Working with Coexpressions in C++</H4>
+ <P>There are a handful of member functions in the class safe that provide an essentially complete set of operations
+ on coexpressions. These are straightforward to use and are summarized here.</P>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE ALIGN="CENTER">
+ <P>
+ <TABLE BORDER="0">
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><B><FONT SIZE="2" FACE="Courier New, Courier">safe function</FONT></B>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><B><FONT SIZE="2" FACE="Courier New, Courier">Icon equivalent</FONT></B>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.create()</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">create !x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">&nbsp;</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.create(y)</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">create x!y</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.activate(y)</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">y@x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P><FONT SIZE="2" FACE="Courier New, Courier">y defaults to &amp;null</FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH="130">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">x.refresh()</FONT>
+ </TD>
+ <TD WIDTH="164">
+ <P ALIGN="CENTER"><FONT SIZE="2" COLOR="black" FACE="Courier New, Courier">^x</FONT>
+ </TD>
+ <TD WIDTH="271">
+ <P>&nbsp;
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <BLOCKQUOTE>
+ <H3><A NAME="Externals"></A>Working with <A HREF="http://www.cs.arizona.edu/icon/v950/extlvals.htm" target="_blank">External
+ Values</A></H3>
+ <P>A new kind of external value is easily defined and used via inheritance from the loadfuncpp class external,
+ which permanently hides the low level machinery of the <A HREF="http://www.cs.arizona.edu/icon/v950/extlvals.htm"
+ target="_blank">C specification</A>. Here is an example of such that illustrates the use of the available features.</P>
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="456">
+ <TR>
+ <TD WIDTH="456">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">class Widget: public external {
+ long state;
+ public:
+ Widget(long x): state(x) {}
+
+ virtual value name() {
+ return &quot;Widget&quot;;
+ }
+ virtual external* copy() {
+ return new Widget(state);
+ }
+ virtual value image() {
+ char sbuf[100];
+ sprintf(sbuf, &quot;Widget_%ld(%ld)&quot;, id, state);
+ return value(NewString, sbuf);
+ }
+ virtual long compare(external* ep) {
+ //negative:less, zero:equal, positive:greater
+ Widget* wp = (Widget*)ep;
+ return this-&gt;state - wp-&gt;state;
+ }
+};
+
+extern &quot;C&quot; int widget(value argv[]) {
+ if( argv[1].type() != Integer ) {
+ Icon::runerr(101, argv[1]);
+ return FAILED;
+ }
+ argv[0] = new Widget(argv[1]);
+ return SUCCEEDED;
+}
+
+extern &quot;C&quot; int widgetint(value argv[]) {
+ if( argv[1].type() != External ) {
+ Icon::runerr(131, argv[1]);
+ return FAILED;
+ }
+ if( !argv[1].isExternal(&quot;Widget&quot;) ) {
+ Icon::runerr(132, argv[1]);
+ return FAILED;
+ }
+ external* ep = argv[1]; //implied conversion
+ Widget* wp = (Widget*)ep; //can move if GC occurs!
+ argv[0] = ep-&gt;state;
+ return SUCCEEDED;
+}</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+</P>
+ </BLOCKQUOTE>
+ <P>The example defines an external function <FONT COLOR="black">widget</FONT> that returns an external value to
+ Icon, and an external function <FONT COLOR="black">widgetint</FONT> that returns an integer extracted from a Widget
+ to Icon. Of course a real library would have in addition a number of external functions to work with Widgets; these
+ could call additional member functions in the Widget class to do the necessary work.</P>
+ <P>Overriding the inherited virtual functions <FONT COLOR="black">name()</FONT>, <FONT COLOR="black">copy()</FONT>,
+ <FONT COLOR="black">image()</FONT> and <FONT COLOR="black">compare()</FONT> automatically redefines the behavior
+ respectively of the built-in Icon functions type, copy and image and the Icon operators === and ~=== when applied
+ to Widgets, as well as the order for sorting Widgets among themselves in Icon. Such overriding is optional, and
+ the defaults defined in the <A HREF="http://www.cs.arizona.edu/icon/v950/extlvals.htm" target="_blank">C specification</A>
+ will apply otherwise. Specifically, the default copy is not to copy but to return the original.</P>
+ <P>There are automatic conversions to and from <FONT COLOR="black">external*</FONT> so that new widgets may be
+ assigned to values or safes, and vice versa when appropriate. The operator new has been overloaded so that an external
+ is allocated by Icon as a part of an Icon external block on the Icon heap. The class external has a protected data
+ member <FONT COLOR="black">id</FONT> that contains the serial number of the external value (assigned by Icon when
+ it allocates the external block). Using <FONT COLOR="black">id</FONT> may be convenient when overriding the <FONT
+ COLOR="black">image()</FONT> member function, as above.</P>
+ <P>External blocks are assumed by Icon not to contain any Icon <A HREF="http://www.cs.arizona.edu/icon/current/cfuncs.htm"
+ target="_blank">descriptors</A>, so do not declare any data members of the classes value or safe when inheriting
+ from external, unless you wish to invite disaster when a garbage collection occurs. Take into account that external
+ blocks may be relocated or garbage collected by Icon. It is not possible to arrange for a destructor or anything
+ else to be called when that occurs. If calling a destructor is essential, then place a pointer to the real object
+ in the external object, and allocate and manage the real object yourself.</P>
+ <H3><A NAME="Records"></A>Using Icon Records as Objects</H3>
+ <P>A new procedure that is a copy of another with an Icon record bound to it may be created by calling the procedure
+ <FONT COLOR="black">bindself</FONT>. The new procedure behaves exactly as the old one, except that a call of the
+ procedure <FONT COLOR="black">self</FONT> from within it returns the record attached to it by <FONT COLOR="black">bindself</FONT>.
+ This enables a record to contain a procedure that behaves like a method by virtue of being bound to it, as illustrated
+ by the following example.
+ <BLOCKQUOTE>
+ <P>
+ <TABLE BORDER="0" WIDTH="496">
+ <TR>
+ <TD WIDTH="496">
+ <PRE><FONT COLOR="black" FACE="Courier New, Courier">link loadfuncpp
+
+record object(val, print)
+
+procedure print()
+ obj := self() | fail
+ write( obj.val )
+end
+
+procedure newObject(x)
+ obj := object(x) #don't assign print method yet
+ #print will be a copy bound to the record it's embedded in
+ obj.print := bindself(print, obj)
+ return obj
+end
+
+procedure main()
+ obj := newObject(&quot;Hello&quot;)
+ obj.print()
+end</FONT></PRE>
+ </TD>
+ </TR>
+ </TABLE>
+
+ </BLOCKQUOTE>
+ <P>Note that <FONT COLOR="black">self</FONT> fails if called from a procedure that is not bound to a record i.e.
+ one that has not been returned by <FONT COLOR="black">bindself</FONT>. It is possible to use bindself to bind a
+ record to a procedure that already has a record bound to it. This simply replaces the bound record, which is useful
+ for copying records that are to be treated as objects in this way, e.g. when copying a prototype object when simulating
+ an object based inheritance scheme.
+ </BLOCKQUOTE>
+ </TD>
+ </TR>
+</TABLE>
+
+</CENTER>
+
+</BODY>
+
+</HTML>
diff --git a/ipl/packs/loadfuncpp/doc/object.cpp b/ipl/packs/loadfuncpp/doc/object.cpp
new file mode 100644
index 0000000..a8ac211
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/object.cpp
@@ -0,0 +1,15 @@
+
+/* Example of a C++ extension to icon via loadfunc,
+ * without garbage collection difficulties.
+ * Type 'make iexample' to build.
+ * Carl Sturtivant, 2008/3/16
+ */
+
+#include "loadfuncpp.h"
+using namespace Icon;
+
+extern "C" int dummy(value argv[]) {
+ return SUCCEEDED;
+}
+
+
diff --git a/ipl/packs/loadfuncpp/doc/object.icn b/ipl/packs/loadfuncpp/doc/object.icn
new file mode 100644
index 0000000..5fe2ba4
--- /dev/null
+++ b/ipl/packs/loadfuncpp/doc/object.icn
@@ -0,0 +1,23 @@
+
+link loadfuncpp
+
+record object(val, print)
+
+procedure print()
+ obj := self() | fail
+ write( obj.val )
+end
+
+procedure newObject(x)
+ obj := object(x) #don't assign print method yet
+ #print will be a copy bound to the record it's embedded in
+ obj.print := bindself(print, obj)
+ return obj
+end
+
+procedure main()
+ obj := newObject("Hello")
+ obj.print()
+end
+
+