aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil S. Matheussen <ksvalast@users.sourceforge.net>2004-01-08 14:55:24 +0000
committerKjetil S. Matheussen <ksvalast@users.sourceforge.net>2004-01-08 14:55:24 +0000
commit44bc5a27d53124ba82becd4181fc381053c56fdb (patch)
tree4695439f8508017260cad061ad6505d5a7200d4c
First commit of k_vst~, k_guile and k_cextsvn2git-root
svn path=/trunk/externals/k_cext/; revision=1253
-rw-r--r--Makefile98
-rw-r--r--README248
-rw-r--r--help-do.pd30
-rw-r--r--help-fibonacci.pd12
-rw-r--r--help-gcd.pd24
-rw-r--r--help-k_cext.pd130
-rw-r--r--help-k_cext2.pd128
-rw-r--r--help-k_cfunc.pd34
-rw-r--r--help-markov.pd66
-rw-r--r--help-rangeifelifelse.pd18
-rw-r--r--help-send.pd28
-rw-r--r--help-sort.pd19
-rw-r--r--k_cext.c335
-rw-r--r--k_cext.h185
-rw-r--r--k_cext_funchandler.c157
-rw-r--r--k_cext_generatecode.c402
-rw-r--r--k_cext_macosx.c87
-rw-r--r--k_cext_unix.c77
-rw-r--r--k_cext_win.c101
-rw-r--r--test.pd16
20 files changed, 2195 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1bd0727
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,98 @@
+NAME=k_cext
+CSYM=k_cext
+
+DIR=k_cext
+
+current: pd_linux
+
+# ----------------------- NT -----------------------
+
+pd_nt: $(NAME).dll
+
+.SUFFIXES: .dll
+
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo /DINCLUDEPATH=\"c:\\programme\\audio\\pd\"
+
+PDNTINCLUDE = /I. /Ic:\programme\audio\pd\src
+PDNTLIB = libc.lib oldnames.lib kernel32.lib c:\programme\audio\pd\bin\pd.lib
+
+.c.dll:
+ cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c k_cext_win.c
+ cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
+ link /dll /export:$(CSYM)_setup $*.obj k_cext_win.obj $(PDNTLIB)
+
+# ----------------------- IRIX 5.x -----------------------
+
+pd_irix5: $(NAME).pd_irix5
+
+.SUFFIXES: .pd_irix5
+
+SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
+
+SGIINCLUDE = -I../../src
+
+.c.pd_irix5:
+ cc $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
+ rm $*.o
+
+# ----------------------- IRIX 6.x -----------------------
+
+pd_irix6: $(NAME).pd_irix6
+
+.SUFFIXES: .pd_irix6
+
+SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
+ -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
+ -Ofast=ip32
+
+.c.pd_irix6:
+ cc $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
+ ld -n32 -IPA -shared -rdata_shared -o $*.pd_irix6 $*.o
+ rm $*.o
+
+# ----------------------- LINUX i386 -----------------------
+
+pd_linux: $(NAME).pd_linux k_cext.c k_cext.h k_cext_generatecode.c
+
+.SUFFIXES: .pd_linux
+
+LINUXCFLAGS = -DPD -DUNIX -DICECAST -O2 -funroll-loops -fomit-frame-pointer \
+ -Wall -W -Wno-shadow -Wstrict-prototypes \
+ -Wno-unused -Wno-parentheses -Wno-switch #-Werror
+
+LINUXINCLUDEPATH=../../src
+LINUXINCLUDE = -I$(LINUXINCLUDEPATH)
+
+.c.pd_linux:
+ cc $(LINUXCFLAGS) $(LINUXINCLUDE) -DINCLUDEPATH=\""`pwd`"\" -DLINUXINCLUDE=\""$(LINUXINCLUDEPATH)"\" -o k_cext.o -c k_cext.c
+ cc $(LINUXCFLAGS) $(LINUXINCLUDE) -DINCLUDEPATH=\""`pwd`"\" -DLINUXINCLUDE=\""$(LINUXINCLUDEPATH)"\" -o k_cext_unix.o -c k_cext_unix.c
+ ld -export_dynamic -shared -o k_cext.pd_linux k_cext.o k_cext_unix.o -lc -lm
+ strip --strip-unneeded $*.pd_linux
+ rm -f $*.o ../$*.pd_linux
+ ln -s $(DIR)/$*.pd_linux ..
+ ln -sf $(DIR)/$*.pd_linux ../k_cfunc.pd_linux
+
+# ----------------------- Mac OSX -----------------------
+
+pd_darwin: $(NAME).pd_darwin k_cext.c k_cext.h k_cext_generatecode.c
+
+.SUFFIXES: .pd_darwin
+
+DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
+ -Wno-unused -Wno-parentheses -Wno-switch
+
+.c.pd_darwin:
+ cc $(DARWINCFLAGS) $(LINUXINCLUDE) -DINCLUDEPATH=\""`pwd`"\" -DLINUXINCLUDE=\""$(LINUXINCLUDEPATH)"\ -o $*.o -c k_cext.c
+ cc $(DARWINCFLAGS) $(LINUXINCLUDE) -DINCLUDEPATH=\""`pwd`"\" -DLINUXINCLUDE=\""$(LINUXINCLUDEPATH)"\ -o $*.o -c k_cext_macosx.c
+ cc -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $*.o
+ rm -f $*.o ../$*.pd_darwin
+ ln -s $*/$*.pd_darwin ..
+
+# ----------------------------------------------------------
+
+install:
+ cp help-*.pd ../../doc/5.reference
+
+clean:
+ rm -f *.o *.pd_* so_locations *~ core
diff --git a/README b/README
new file mode 100644
index 0000000..69c9cff
--- /dev/null
+++ b/README
@@ -0,0 +1,248 @@
+
+
+
+k_cext PD external
+
+
+
+INTRODUCTION
+
+ The k_cext PD external makes you able to program
+ the programming language "C" directly within
+ the PD objects.
+
+ +-------------------------------------------------------+
+ | Which means: You don't need an external text-editor. |
+ +-------------------------------------------------------+
+
+
+
+WHY USE K_CEXT
+
+ First, the reason for using "C", and not some other programming
+ or scripting language, was simply because it is
+ so easy to compile and link c code inside externals in pd.
+ Because C is probably not the best suited language for this
+ task, except when extreme cpu-efficiency is needed.
+
+ Still, I personally think making small k_cext objects
+ is a lot more comfortable than making large pd sub-patches
+ doing the same things. And thats probably the main reason
+ to use k_cext.
+
+
+
+
+A SMALL EXAMPLE IN K_CEXT
+
+ The following k_cext object have one inlet and one outlet.
+ What it does, when receiving a value on the inlet, is to
+ send the _previously_ received inlet value to the outlet.
+
+
+ [ k_cext 1 1;
+ static t_float prev=0;
+ O(0,prev);
+ prev=V(0); ]
+
+
+ The "k_cext 1 1" line is the k_cext header. The first "1"
+ means that it has one inlet, and the second "1" means that
+ it has one outlet.
+
+ The "static t_float prev=0;" line declares a variable for the
+ object called "prev". "t_float" means that the type of the variable is
+ a floating-point number. "static" means here that the value
+ for the variable is remembered the next time the object
+ is runned, which is necesarry if we want to send out the
+ previous value sent to the inlet.
+
+ "O(0,prev);" sends the value of "prev" to outlet number 0.
+ "O" is a function.
+
+ "prev=V(0);" stores the value of the current inlet to the
+ variable "prev" for the next time the object is run.
+
+
+
+
+THE SAME EXAMPLE AS A PD SUB-PATCH
+
+
+ The following PD-patch does the same:
+
+ [inlet]
+ |
+ [t f b]
+ \ /
+ \ /
+ X
+ / \
+ / \
+ [float]
+ |
+ [outlet]
+
+
+ I guess its a matter of personal taste, but I really don't
+ find the PD-way of sending out a previous value very intuitive.
+
+ And the advantage of using k_cext instead of making
+ PD sub-patches becomes more appearent the larger the tasks are.
+ Look at the help-file, and try to do the same things directly in PD.
+
+
+
+K_CEXT OBJECT
+
+ A k_cext object can be divided into three parts:
+
+ 1. Header.
+ 2. Variables
+ 3. Body.
+
+
+
+K_CEXT HEADER
+
+ The first line in a k_cext header is built up like this:
+
+ "k_cext <num_inlets> <num_outlets> <default inlet values>".
+
+ "k_cext 4 5 1 2 3 4" means that the object has 4 inlets,
+ 5 outlets, and the value of V(0) is by default 1, the
+ value of V(1) is by default 2, the value of V(2) is by
+ default 3, and the value of V(3) is by default 4.
+
+ Its optional whether you want to set "default inlet values"
+ or not. If not set, they get the value 0.
+
+
+
+K_CEXT VARIABLES
+
+ There are four types of variables that makes sense using
+ in a k_cext object. These are:
+
+ "int" - integer number.
+ "t_float" - floating point numbers.
+ "INTARRAY" - An array of integer numbers.
+ "FLOATARRAY" - An array of floating point numbers.
+
+ See the help patch for examples of use.
+
+
+
+MACROS / USING THE PD OBJECT AS A TEXT-EDITOR
+
+ Using the pd object as a text-editor is unfortunately
+ a bit limited. But by using some pre-defined macros
+ spesified in the "k_cext.h" file, its not that bad.
+
+ begin/end -
+ The most noticable limitation is probably that you are
+ not able to write { or }. This is solved by
+ using the BEGIN and END macros. Or better; the "DO"
+ symbol which makes k_cext automaticly insert BEGIN and
+ END for you. Look at the help-do.pd patch.
+
+ lineshift -
+ The pd object text editor doesn't understand lineshift
+ directly. Instead you have to use ";" at the end
+ of each line.
+
+ semicolon -
+ If you need to write ";", but dont want the line to end
+ right there, use the "SC" macro instead.
+
+ indentation -
+ The pd object text editor automaticly removes spaces and
+ tabs from the beginning of lines. You can work around this by
+ writing ". " instead. The k_cext external removes all
+ ". "'s at the beginning of lines before compiling the code.
+
+
+ More macros are defined in the k_cext.h header file.
+
+
+
+OS
+ k_cext runs fine in linux using gcc and in windows using visual C.
+ The macosx code was made by looking at code inside PD, and has never
+ been tested (at least not that I know if). It might work, but probably
+ not. Check out the k_cext_macosx.c file.
+
+
+FAQ
+ Q: I can not get k_cext to work in windows, and I dont have Visual C.
+ A: You need Visual C.
+
+ Q: Where can I get a windows .dll file?
+ A: Since you allready need to have some basic knowledge about C, in
+ addition to a C compiler, it should not be that hard for you to
+ compile the .dll file yourself, if you know how to use the k_cext
+ external. So you have to make it yourself.
+
+
+CHANGES
+ 0.3.0 -> 0.3.1:
+ -Works with VisualC. (0.3.0 didn't):
+ -Workaround for missing variable number of argument macros in VisualC, (which is not a gcc
+ extension, by the way, but a part of the iso99 c-standard).
+ -Workaround for missing stdbool.h file in VisualC. (also a part of the iso99 c-standard)
+ (code by Thomas Grill)
+ -Workaround for missing static <something> <something>[] in VisualC.
+ -Fixed a variable which was not defined at the beginning of the function. (Thomas Grill)
+
+ 0.2.5 -> 0.3.0:
+ -Added the k_cfunc object. k_cfunc is very similar to k_cext, but instead of being triggered
+ by getting a bang or value on the first inlet, the k_cfunc-code is run
+ when being called from another k_cfunc object or a k_cext object. In other words,
+ its a c function object available for k_cext.
+
+ 0.2.4 -> 0.2.5:
+ -Fixed the problem that integer numbers sometimes was converted to
+ floats before compiling.
+ -Fixed ENDSWITCH macro.
+ -Small internal changes.
+ -Changed the PD subpatch example in the README file to use the trigger
+ object. The information that was written earlier that you had to
+ make connections in a certain order, was misinformation. The behaviour
+ is unspesified according to the spesification. The trigger object fix
+ such situations. (But if you need to use the trigger-object, its a good
+ sign that you should rather use k_cext for the operation anyway. My
+ opinion.)
+ -Removed the windows .dll file. If you are not able to compile up k_cext
+ yourself, you most probably aren't able to use k_cext either.
+ -Added a "print" message, which prints out the generated c-code with
+ line-numbers to the terminal.
+ -Prints out the generated c-code with linenumbers if compilation fails.
+ Makes debugging a lot faster.
+ -Added a SEND macro that takes a symbol string and a number, and sends
+ a pd message.
+ -Added "DO", which can (and should) be used instead of the BEGIN macro.
+ DO is not a macro, but a special symbol used by the k_cext
+ preprocessor to know when to automaticly insert BEGIN and
+ END based on indentation. Just like Python. :)
+ -Changed the main example patch to use DO instead of BEGIN/END.
+ -Added some more example patches.
+ -Fixed nearly correct indentation for the generated C code.
+
+ 0.2.3 -> 0.2.4:
+ -Added a lot of new macros to k_cext.h.
+ -Fixed the help file a bit.
+ -Wrote the README file.
+ -Changed the license for k_cext.h from GPL to LGPL.
+ (Note, the k_cext external is still GPL)
+ -Some windows code was for some strange reason put
+ in the macosx file. Fixed.
+ -Added Mac OSX to the Makefile. (Not tested.)
+
+
+CREDITS
+ k_cext is made by Kjetil S. Matheussen 2002/2003.
+ k.s.matheussen@notam02.no
+
+ The windows-port is made by Olaf Matthes.
+ olaf.matthes@gmx.de
+
diff --git a/help-do.pd b/help-do.pd
new file mode 100644
index 0000000..1e7420c
--- /dev/null
+++ b/help-do.pd
@@ -0,0 +1,30 @@
+#N canvas 338 168 450 300 10;
+#X floatatom 8 272 5 0 0;
+#X floatatom 136 274 5 0 0;
+#X msg 129 103 1;
+#X floatatom 224 103 5 0 0;
+#X obj 12 158 k_cext 1 2 \; IF I(0)!=1 THEN DO \; . O0(I(0)) \; . O1(I(0)+1)
+\; ELSE \; . O0(-2) \; . O1(-3) \;;
+#X obj 269 141 k_cext 1 2 \; IF I(0)!=1 THEN BEGIN \; . O0(I(0)) \;
+. O1(I(0)+1) \; ELSE \; . O0(-2) \; . O1(-3) \; ENDIF;
+#X floatatom 274 269 5 0 0;
+#X floatatom 400 270 5 0 0;
+#X text 34 65 With DO:;
+#X text 288 65 Without DO:;
+#X text 10 5 DO is not a macro \, but a special symbol used by the
+k_cext preprocessor to know when to automaticly insert BEGIN and END
+based on indentation.;
+#X msg 293 109 print;
+#X msg 10 114 print;
+#X text 32 76 ---------;
+#X text 287 76 ---------;
+#X connect 2 0 4 0;
+#X connect 2 0 5 0;
+#X connect 3 0 4 0;
+#X connect 3 0 5 0;
+#X connect 4 0 0 0;
+#X connect 4 1 1 0;
+#X connect 5 0 6 0;
+#X connect 5 1 7 0;
+#X connect 11 0 5 0;
+#X connect 12 0 4 0;
diff --git a/help-fibonacci.pd b/help-fibonacci.pd
new file mode 100644
index 0000000..38cd194
--- /dev/null
+++ b/help-fibonacci.pd
@@ -0,0 +1,12 @@
+#N canvas 0 0 450 300 10;
+#X floatatom 51 143 5 0 0 0 - - -;
+#X floatatom 49 231 10 0 0 0 - - -;
+#X obj 50 174 k_cext 1 1 \; IF I(0)< 30 THEN DO \; . O(0 \, INT_fib(I(0)))
+\;;
+#X text 216 177 Set a limit on 30 \, because of;
+#X text 215 192 the computing time.;
+#X text 43 27 The simplest way to find the fibonacci numbers.;
+#X obj 49 62 k_cfunc INT_fib int n \; IF n<2 THEN DO \; . return n
+\; ELSE \; . return INT_fib(n-1)+INT_fib(n-2) \;;
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
diff --git a/help-gcd.pd b/help-gcd.pd
new file mode 100644
index 0000000..57ddcfd
--- /dev/null
+++ b/help-gcd.pd
@@ -0,0 +1,24 @@
+#N canvas 469 87 530 363 10;
+#X msg 14 79 print;
+#X floatatom 114 202 5 0 0 0 - - -;
+#X floatatom 73 201 5 0 0 0 - - -;
+#X msg 98 247 bang;
+#X floatatom 70 327 5 0 0 0 - - -;
+#X text 14 42 Find the greatest common divisor between two numbers.
+;
+#X msg 12 208 print;
+#X obj 73 271 k_cext 2 1 \; O(0 \, INT_gcd(I(0) \, I(1))) \;;
+#X obj 114 225 t b f;
+#X obj 285 174 k_cfunc INT_te \; return INT_te() \;;
+#X msg 283 132 print;
+#X obj 14 112 k_cfunc INT_gcd int a int b \; IF b==0 THEN DO \; . return
+a \; ELSE \; . return INT_gcd(b \, a%b) \;;
+#X connect 0 0 11 0;
+#X connect 1 0 8 0;
+#X connect 2 0 7 0;
+#X connect 3 0 7 0;
+#X connect 6 0 7 0;
+#X connect 7 0 4 0;
+#X connect 8 0 3 0;
+#X connect 8 1 7 1;
+#X connect 10 0 9 0;
diff --git a/help-k_cext.pd b/help-k_cext.pd
new file mode 100644
index 0000000..6456919
--- /dev/null
+++ b/help-k_cext.pd
@@ -0,0 +1,130 @@
+#N canvas 268 7 629 687 10;
+#X floatatom 19 52 5 0 0;
+#X floatatom 17 116 5 0 0;
+#X floatatom 238 54 5 0 0;
+#X floatatom 237 117 5 0 0;
+#X floatatom 419 50 5 0 0;
+#X floatatom 419 137 5 0 0;
+#X floatatom 30 216 5 0 0;
+#X floatatom 30 337 5 0 0;
+#X text 416 29 Sends out previous value.;
+#X text 235 33 Adds one.;
+#X floatatom 367 199 5 0 0;
+#X text 26 198 (Gliding average);
+#X floatatom 29 405 5 0 0;
+#X floatatom 29 502 20 0 0;
+#X text 32 356 Calculates the faculty.;
+#X text 139 707 Additional \, read the macros in k_cext.h;
+#X floatatom 373 394 5 0 0;
+#X floatatom 367 501 5 0 0;
+#X floatatom 515 397 5 0 0;
+#X floatatom 516 501 5 0 0;
+#X text 361 366 Divide two numbers.;
+#X text 361 379 Integer modulus in the second outlet.;
+#X floatatom 53 682 10 0 0;
+#X floatatom 176 587 5 0 0;
+#X msg 62 584 bang;
+#X text 16 31 Sends out the input.;
+#X text 10 149 ______________________________________________________
+;
+#X text 12 341 ______________________________________________________
+;
+#X text 226 516 ______________________________________________________
+;
+#X text 231 688 ______________________________________________________
+;
+#X text 20 -9 ______________________________________________________
+;
+#X text 102 -28 k_cext. The c external object for PD by K.Matheussen
+\;;
+#X text 230 -9 ______________________________________________________
+;
+#X text 221 149 ______________________________________________________
+;
+#X text 231 341 ______________________________________________________
+;
+#X text 11 516 ______________________________________________________
+;
+#X text 8 688 ______________________________________________________
+;
+#X obj 323 357 vsl 8 170 0 127 0 0 empty empty empty 0 -8 0 8 -1 -1
+-1 0 1;
+#X obj 334 165 vsl 8 185 0 127 0 0 empty empty empty 0 -8 0 8 -1 -1
+-1 0 1;
+#X obj 183 7 vsl 8 152 0 127 0 0 empty empty empty 0 -8 0 8 -1 -1 -1
+0 1;
+#X obj 381 8 vsl 8 152 0 127 0 0 empty empty empty 0 -8 0 8 -1 -1 -1
+0 1;
+#X text 201 9 2;
+#X text 398 10 3;
+#X text 16 9 1;
+#X text 12 166 4;
+#X text 352 165 5;
+#X text 13 356 6;
+#X text 338 357 7;
+#X text 22 535 8;
+#X obj 17 75 k_cext 1 1 \; O0(V(0)) \;;
+#X obj 237 76 k_cext 1 1 \; O0(V(0) + 1) \;;
+#X obj 422 72 k_cext 1 1 \; static t_float a=0 \; O0(a) \; a=V(0) \;
+;
+#X obj 30 240 k_cext 1 1 \; static FLOATARRAY(a \, 5) \; static int
+p=0 \; a[p%5]=V(0) \; p++ \; O0( (a[0]+a[1]+a[2]+a[3]+a[4])/5 ) \;
+;
+#X obj 133 681 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 0 256;
+#X obj 199 683 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 0 256;
+#X obj 275 683 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 0 256;
+#X floatatom 289 588 5 0 0;
+#X floatatom 359 338 5 0 0;
+#X floatatom 437 337 5 0 0;
+#X floatatom 530 337 5 0 0;
+#X text 371 174 Some modulo operations;
+#X obj 460 530 vsl 8 170 0 127 0 0 empty empty empty 0 -8 0 8 -1 -1
+-1 0 1;
+#X text 478 535 9 Start mozilla;
+#X msg 479 566 bang;
+#X text 43 534 Sends out four random numbers between the value of inlet
+1 and inlet 2 Default values for the inlets are set by argument 3 and
+4 (5 and 10).;
+#X text 28 183 Sends out the average of the 5 last values.;
+#X text 33 380 and the SC macro.;
+#X text 33 368 Also demonstrates the use of the FOR;
+#X obj 369 223 k_cext 1 3 \; int v=I(0) \; IF !(v%3) THEN DO \; . O0(v)
+\; ELIF !(v%2) THEN DO \; . O1(v) \; ELSE \; . O2(v) \;;
+#X obj 29 431 k_cext 1 1 \; int out=1 \, i \; FOR i=2 SC i<=I(0) SC
+i++ THEN DO \; . out*=i \; O0(out) \;;
+#X obj 62 608 k_cext 3 4 0 5 10 \; int i \; RANGE(i \, 0 \, 4) DO \;
+. O(i \, (int)BETWEEN(I(1) \, I(2))) \;;
+#X obj 479 602 k_cext 1 0 \; system("mozilla &") \;;
+#X obj 377 426 k_cext 2 2 \; IF I(1)!=0 THEN DO \; . O1(I(0) % I(1))
+\; O0(V(0) / V(1)) \;;
+#X msg 446 198 print;
+#X connect 0 0 49 0;
+#X connect 2 0 50 0;
+#X connect 4 0 51 0;
+#X connect 6 0 52 0;
+#X connect 10 0 68 0;
+#X connect 12 0 69 0;
+#X connect 16 0 72 0;
+#X connect 18 0 72 1;
+#X connect 23 0 70 1;
+#X connect 24 0 70 0;
+#X connect 49 0 1 0;
+#X connect 50 0 3 0;
+#X connect 51 0 5 0;
+#X connect 52 0 7 0;
+#X connect 56 0 70 2;
+#X connect 63 0 71 0;
+#X connect 68 0 57 0;
+#X connect 68 1 58 0;
+#X connect 68 2 59 0;
+#X connect 69 0 13 0;
+#X connect 70 0 22 0;
+#X connect 70 1 53 0;
+#X connect 70 2 54 0;
+#X connect 70 3 55 0;
+#X connect 72 0 17 0;
+#X connect 72 1 19 0;
+#X connect 73 0 68 0;
diff --git a/help-k_cext2.pd b/help-k_cext2.pd
new file mode 100644
index 0000000..19dcaea
--- /dev/null
+++ b/help-k_cext2.pd
@@ -0,0 +1,128 @@
+#N canvas 325 15 629 687 10;
+#X floatatom 19 52 5 0 0;
+#X floatatom 17 116 5 0 0;
+#X floatatom 238 54 5 0 0;
+#X floatatom 237 117 5 0 0;
+#X floatatom 419 50 5 0 0;
+#X floatatom 419 137 5 0 0;
+#X floatatom 30 216 5 0 0;
+#X floatatom 30 337 5 0 0;
+#X text 416 29 Sends out previous value.;
+#X text 235 33 Adds one.;
+#X floatatom 539 178 5 0 0;
+#X text 26 198 (Gliding average);
+#X floatatom 29 405 5 0 0;
+#X floatatom 29 502 20 0 0;
+#X text 32 356 Calculates the faculty.;
+#X text 139 707 Additional \, read the macros in k_cext.h;
+#X floatatom 373 394 5 0 0;
+#X floatatom 367 501 5 0 0;
+#X floatatom 515 397 5 0 0;
+#X floatatom 516 501 5 0 0;
+#X text 361 366 Divide two numbers.;
+#X text 361 379 Integer modulus in the second outlet.;
+#X floatatom 53 682 10 0 0;
+#X floatatom 176 587 5 0 0;
+#X msg 62 584 bang;
+#X text 16 31 Sends out the input.;
+#X text 10 149 ______________________________________________________
+;
+#X text 12 341 ______________________________________________________
+;
+#X text 226 516 ______________________________________________________
+;
+#X text 231 688 ______________________________________________________
+;
+#X text 20 -9 ______________________________________________________
+;
+#X text 102 -28 k_cext. The c external object for PD by K.Matheussen
+\;;
+#X text 230 -9 ______________________________________________________
+;
+#X text 221 149 ______________________________________________________
+;
+#X text 231 341 ______________________________________________________
+;
+#X text 11 516 ______________________________________________________
+;
+#X text 8 688 ______________________________________________________
+;
+#X obj 323 357 vsl 8 170 0 127 0 0 empty empty empty 0 -8 0 8 -1 -1
+-1 0 1;
+#X obj 334 165 vsl 8 185 0 127 0 0 empty empty empty 0 -8 0 8 -1 -1
+-1 0 1;
+#X obj 183 7 vsl 8 152 0 127 0 0 empty empty empty 0 -8 0 8 -1 -1 -1
+0 1;
+#X obj 381 8 vsl 8 152 0 127 0 0 empty empty empty 0 -8 0 8 -1 -1 -1
+0 1;
+#X text 201 9 2;
+#X text 398 10 3;
+#X text 16 9 1;
+#X text 12 166 4;
+#X text 352 165 5;
+#X text 13 356 6;
+#X text 338 357 7;
+#X text 22 535 8;
+#X obj 17 75 k_cext 1 1 \; O0(V(0)) \;;
+#X obj 237 76 k_cext 1 1 \; O0(V(0) + 1) \;;
+#X obj 422 72 k_cext 1 1 \; static t_float a=0 \; O0(a) \; a=V(0) \;
+;
+#X obj 30 240 k_cext 1 1 \; static FLOATARRAY(a \, 5) \; static int
+p=0 \; a[p%5]=V(0) \; p++ \; O0( (a[0]+a[1]+a[2]+a[3]+a[4])/5 ) \;
+;
+#X obj 133 681 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 22 256;
+#X obj 199 683 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 36 256;
+#X obj 275 683 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 58 256;
+#X floatatom 289 588 5 0 0;
+#X floatatom 359 338 5 0 0;
+#X floatatom 437 337 5 0 0;
+#X floatatom 530 337 5 0 0;
+#X text 371 174 Some modulo operations;
+#X obj 460 530 vsl 8 170 0 127 0 0 empty empty empty 0 -8 0 8 -1 -1
+-1 0 1;
+#X text 478 535 9 Start mozilla;
+#X msg 479 566 bang;
+#X text 43 534 Sends out four random numbers between the value of inlet
+1 and inlet 2 Default values for the inlets are set by argument 3 and
+4 (5 and 10).;
+#X text 28 183 Sends out the average of the 5 last values.;
+#X text 33 380 and the SC macro.;
+#X text 33 368 Also demonstrates the use of the FOR;
+#X obj 367 202 k_cext 1 3 \; int v=I(0) \; IF !(v%3) THEN DO \; . O0(v)
+\; ELIF !(v%2) THEN DO \; . O1(v) \; ELSE \; . O2(v) \;;
+#X obj 29 431 k_cext 1 1 \; int out=1 \, i \; FOR i=2 SC i<=I(0) SC
+i++ THEN DO \; . out*=i \; O0(out) \;;
+#X obj 62 608 k_cext 3 4 0 5 10 \; int i \; RANGE(i \, 0 \, 4) DO \;
+. O(i \, (int)BETWEEN(I(1) \, I(2))) \;;
+#X obj 479 602 k_cext 1 0 \; system("mozilla &") \;;
+#X obj 377 426 k_cext 2 2 \; IF I(1)!=0 THEN DO \; . O1(I(0) % I(1))
+\; O0(V(0) / V(1)) \;;
+#X connect 0 0 49 0;
+#X connect 2 0 50 0;
+#X connect 4 0 51 0;
+#X connect 6 0 52 0;
+#X connect 10 0 68 0;
+#X connect 12 0 69 0;
+#X connect 16 0 72 0;
+#X connect 18 0 72 1;
+#X connect 23 0 70 1;
+#X connect 24 0 70 0;
+#X connect 49 0 1 0;
+#X connect 50 0 3 0;
+#X connect 51 0 5 0;
+#X connect 52 0 7 0;
+#X connect 56 0 70 2;
+#X connect 63 0 71 0;
+#X connect 68 0 57 0;
+#X connect 68 1 58 0;
+#X connect 68 2 59 0;
+#X connect 69 0 13 0;
+#X connect 70 0 22 0;
+#X connect 70 1 53 0;
+#X connect 70 2 54 0;
+#X connect 70 3 55 0;
+#X connect 72 0 17 0;
+#X connect 72 1 19 0;
diff --git a/help-k_cfunc.pd b/help-k_cfunc.pd
new file mode 100644
index 0000000..390b46c
--- /dev/null
+++ b/help-k_cfunc.pd
@@ -0,0 +1,34 @@
+#N canvas 583 347 825 399 10;
+#X obj 31 310 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 30 256;
+#X obj 259 312 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 20 256;
+#X floatatom 33 110 5 0 0 0 - - -;
+#X floatatom 217 107 5 0 0 0 - - -;
+#X floatatom 30 182 5 0 0 0 - - -;
+#X obj 32 140 k_cext 2 1 \; O(0 \, INT_func(I(0) \, I(1))) \;;
+#X obj 31 234 k_cfunc 0 2 INT_func int a int b \; O(0 \, a) \; O(1
+\, b) \; return a+b \;;
+#X obj 404 315 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 32 256;
+#X obj 632 317 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 12 256;
+#X floatatom 406 115 5 0 0 0 - - -;
+#X floatatom 590 112 5 0 0 0 - - -;
+#X floatatom 403 187 5 0 0 0 - - -;
+#X obj 405 144 k_cext 2 1 \; O(0 \, FLOAT_func(V(0) \, V(1))) \;;
+#X obj 404 239 k_cfunc 0 2 FLOAT_func float a float b \; O(0 \, a)
+\; O(1 \, b) \; return a+b \;;
+#X text 148 25 Demonstrating the use of two functions to add integer
+numbers. The first one does an integer operation \, the second one
+does a floating point operation.;
+#X connect 2 0 5 0;
+#X connect 3 0 5 1;
+#X connect 5 0 4 0;
+#X connect 6 0 0 0;
+#X connect 6 1 1 0;
+#X connect 9 0 12 0;
+#X connect 10 0 12 1;
+#X connect 12 0 11 0;
+#X connect 13 0 7 0;
+#X connect 13 1 8 0;
diff --git a/help-markov.pd b/help-markov.pd
new file mode 100644
index 0000000..84290f3
--- /dev/null
+++ b/help-markov.pd
@@ -0,0 +1,66 @@
+#N canvas 0 107 907 643 10;
+#X obj 244 40 bng 20 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X obj 283 31 r state;
+#X obj 261 66 f 1;
+#X floatatom 312 55 3 0 0 0 - - -;
+#X text 227 19 STEP;
+#X msg 371 52 \; state 1;
+#X text 371 32 reset;
+#X obj 260 103 k_cext 1 0 \; \; int state=I(0) \; int s1[3]=BEGIN 30
+\, 10 \, 70 END \; int s2[3]=BEGIN 60 \, 60 \, 80 END \; int random=RANDOM(100)
+\; \; IF random < s1[state] THEN DO \; . SEND("state" \, 1) \; ELIF
+random < s2[state] THEN DO \; . SEND("state" \, 2) \; ELSE \; . SEND("state"
+\, 3) \;;
+#X obj 33 25 bng 20 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X obj 72 16 r state;
+#X obj 50 51 f 1;
+#X floatatom 101 40 3 0 0 0 - - -;
+#X text 16 4 STEP;
+#X obj 26 511 s state;
+#X text 244 391 documentation patches.;
+#X text 245 375 chain example in the PD;
+#X msg 155 65 print;
+#X msg 200 66 print;
+#X obj 26 100 k_cext 1 1 \; int state=I(0) \; int random=RANDOM(100)
+\; \; SWITCH state THEN DO \; . case 1: \; . . IF random<30 THEN DO
+\; . . . state=1 \; . . ELIF random<60 THEN DO \; . . . state=2 \;
+. . ELSE \; . . . state=3 \; . . break \; . case 2: \; . . IF random<10
+THEN DO \; . . . state=1 \; . . ELIF random<60 THEN DO \; . . . state=2
+\; . . ELSE \; . . . state=3 \; . . break \; . case 3: \; . . IF random<70
+THEN DO \; . . . state=1 \; . . ELIF random<80 THEN DO \; . . . state=2
+\; . . ELSE \; . . . state=3 \; O0(state) \;;
+#X obj 561 300 k_cfunc INT_markov int a int b \; int random=RANDOM(100)
+\; IF random<a THEN DO \; . return 1 \; ELIF random<b THEN DO \; .
+return 2 \; ELSE \; . return 3 \;;
+#X obj 557 115 k_cext 1 0 \; \; int s1[3]=BEGIN 30 \, 10 \, 70 END
+\; int s2[3]=BEGIN 60 \, 60 \, 80 END \; SEND("state" \, INT_markov(s1[I(0)]
+\, s2[I(0)])) \;;
+#X obj 574 46 bng 20 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X obj 613 37 r state;
+#X obj 591 72 f 1;
+#X floatatom 642 61 3 0 0 0 - - -;
+#X text 557 25 STEP;
+#X msg 530 72 print;
+#X text 237 29;
+#X text 244 360 Three ways to implement the markov;
+#X msg 561 259 print;
+#X connect 0 0 2 0;
+#X connect 1 0 2 1;
+#X connect 1 0 3 0;
+#X connect 2 0 7 0;
+#X connect 8 0 10 0;
+#X connect 9 0 10 1;
+#X connect 9 0 11 0;
+#X connect 10 0 18 0;
+#X connect 16 0 18 0;
+#X connect 17 0 7 0;
+#X connect 18 0 13 0;
+#X connect 21 0 23 0;
+#X connect 22 0 23 1;
+#X connect 22 0 24 0;
+#X connect 23 0 20 0;
+#X connect 26 0 20 0;
+#X connect 29 0 19 0;
diff --git a/help-rangeifelifelse.pd b/help-rangeifelifelse.pd
new file mode 100644
index 0000000..df694dd
--- /dev/null
+++ b/help-rangeifelifelse.pd
@@ -0,0 +1,18 @@
+#N canvas 321 226 450 300 10;
+#X floatatom 102 55 5 0 0;
+#X floatatom 112 275 5 0 0;
+#X floatatom 172 276 5 0 0;
+#X floatatom 218 278 5 0 0;
+#X floatatom 273 280 5 0 0;
+#X obj 160 39 k_cext 1 4 \; \; int lokke \; int a=5 \; \; RANGE(lokke
+\, 0 \, 4) DO \; . O(lokke \, I(0)) \; . IF I(0)==0 THEN DO \; . .
+O(1 \, 2) \; . ELIF I(0)==1 THEN DO \; . . O(2 \, 3) \; . ELSE \; .
+. O(3 \, 4) \; . . IF a==2 THEN DO \; . . . O(3 \, 23) \; . . . IF
+a==3 THEN DO \; . . . . O(2 \, 4) \;;
+#X msg 163 15 print;
+#X connect 0 0 5 0;
+#X connect 5 0 1 0;
+#X connect 5 1 2 0;
+#X connect 5 2 3 0;
+#X connect 5 3 4 0;
+#X connect 6 0 5 0;
diff --git a/help-send.pd b/help-send.pd
new file mode 100644
index 0000000..fa14d40
--- /dev/null
+++ b/help-send.pd
@@ -0,0 +1,28 @@
+#N canvas 488 163 708 409 10;
+#X floatatom 96 329 5 0 0;
+#X floatatom 39 199 5 0 0;
+#X floatatom 149 207 5 0 0;
+#X text 28 15 The SEND macro is just as efficient;
+#X text 30 29 as the send object \, and is defined like this:;
+#X obj 42 248 send a_sym;
+#X obj 141 235 k_cext 1 0 \; SEND("a_sym" \, I(0)) \;;
+#X obj 96 297 r a_sym;
+#X floatatom 161 331 5 0 0;
+#X obj 161 299 r a_sym2;
+#X floatatom 384 235 5 0 0;
+#X text 379 202 Warning \, the following code will not do;
+#X msg 321 182 print;
+#X text 379 215 as one might expect:;
+#X obj 382 261 k_cext 1 0 \; char *syms[2]=BEGIN "a_sym" \, "a_sym2"
+END \; static int s=0 \; IF s==0 THEN DO \; . s=1 \; ELSE \; . s=0
+\; SEND(syms[s] \, s+5) \;;
+#X text 32 59 #define SEND(symname \, val) do BEGIN static t_symbol
+*k_cext_internal_symbol=NULL SC if(k_cext_internal_symbol==NULL) k_cext_internal_symbol=gensym(symname)
+SC if(k_cext_internal_symbol->s_thing) pd_float(k_cext_internal_symbol->s_thing
+\, val) SC END while(0);
+#X connect 1 0 5 0;
+#X connect 2 0 6 0;
+#X connect 7 0 0 0;
+#X connect 9 0 8 0;
+#X connect 10 0 14 0;
+#X connect 12 0 14 0;
diff --git a/help-sort.pd b/help-sort.pd
new file mode 100644
index 0000000..018fbb3
--- /dev/null
+++ b/help-sort.pd
@@ -0,0 +1,19 @@
+#N canvas 149 460 622 320 10;
+#X floatatom 20 82 5 0 0 0 - - -;
+#X floatatom 20 267 5 0 0 0 - - -;
+#X text 14 24 Sends out the largest of;
+#X obj 20 111 k_cext 1 1 \; static FLOATARRAY(a \, 5) \; FLOATARRAY(a2
+\, 5) \; static int p=0 \; int i \; a[p%5]=V(0) \; p++ \; RANGE(i \,
+0 \, 5) a2[i]=a[i] \; FLOATSORT(a2 \, 5) \; O(0 \, a2[4]) \;;
+#X text 14 41 the five last float numbers.;
+#X floatatom 318 80 5 0 0 0 - - -;
+#X floatatom 318 265 5 0 0 0 - - -;
+#X text 312 22 Sends out the largest of;
+#X obj 318 109 k_cext 1 1 \; static INTARRAY(a \, 5) \; INTARRAY(a2
+\, 5) \; static int p=0 \; int i \; a[p%5]=I(0) \; p++ \; RANGE(i \,
+0 \, 5) a2[i]=a[i] \; INTSORT(a2 \, 5) \; O(0 \, a2[4]) \;;
+#X text 312 39 the five last integer numbers.;
+#X connect 0 0 3 0;
+#X connect 3 0 1 0;
+#X connect 5 0 8 0;
+#X connect 8 0 6 0;
diff --git a/k_cext.c b/k_cext.c
new file mode 100644
index 0000000..a414562
--- /dev/null
+++ b/k_cext.c
@@ -0,0 +1,335 @@
+/* --------------------------- k_cext ----------------------------------- */
+/* */
+/* Program c directly within a pd object. */
+/* */
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/* ---------------------------------------------------------------------------- */
+
+
+#include "m_pd.h"
+#include "k_cext.h"
+
+static char *version =
+"k_cext v0.3.0, written by Kjetil S. Matheussen, k.s.matheussen@notam02.no\n"
+"Windows-port by Olaf Matthes.";
+
+int instancenumber=0; // Can not be static because of the win-port.
+
+
+static t_class *k_cext_class;
+static t_class *k_cfunc_class;
+
+
+int k_cext_intcompare(const void *p1, const void *p2)
+{
+ int i = *((int *)p1);
+ int j = *((int *)p2);
+
+ if (i > j)
+ return (1);
+ if (i < j)
+ return (-1);
+ return (0);
+}
+
+int k_cext_floatcompare(const void *p1, const void *p2)
+{
+ float i = *((int *)p1);
+ float j = *((int *)p2);
+
+ if (i > j)
+ return (1);
+ if (i < j)
+ return (-1);
+ return (0);
+}
+
+
+static void k_cext_print(t_k_cext *x){
+ FILE *printfile;
+ char name[500];
+ int lokke;
+ char temp[500];
+
+ sprintf(name,"%s.c",x->filename);
+
+ printfile=fopen(name,"r");
+ post("------------------------------------------");
+ for(lokke=1;;lokke++){
+ char temp2[500];
+ int c;
+ if((c=fgetc(printfile))==EOF) break;
+ ungetc(c,printfile);
+ fgets(temp,400,printfile);
+ sprintf(temp2,"%3d %s",lokke,temp);
+ temp2[strlen(temp2)-1]=0;
+ post(temp2);
+ }
+ fclose(printfile);
+ post("------------------------------------------");
+
+}
+
+static void k_cext_bang(t_k_cext *x)
+{
+ /* Fixme, for some reason, k_cfunc's float method points to k_cext_float
+ instead of k_cfunc_float.
+ As a workaround, there is this x->iscext==true test below. */
+ if(x->k_cext_process!=NULL && x->iscext==true)
+ (*x->k_cext_process)(x);
+}
+
+
+static void k_cext_float(t_k_cext *x, t_floatarg f)
+{
+ x->values[0]=f;
+
+ k_cext_bang(x);
+}
+
+static void k_cfunc_float(t_k_cext *x, t_floatarg f)
+{
+ post("k_cfunc_float");
+ x->values[0]=f;
+}
+
+
+#include "k_cext_funchandler.c"
+
+
+struct k_cext_init{
+ int indentation;
+ int set_indentation[500]; // Very unlikely that anyone wants to indent more than 500 levels.
+ int thisisanelifline;
+ FILE *file;
+ char name[500];
+ char funcname[500];
+
+ int num_intfuncs;
+ int num_floatfuncs;
+
+ char intfuncnames[50000]; // Max functionname length=50, max number of functions=1000.
+ char floatfuncnames[50000];
+
+ int doinitpos1;
+ int doinitpos2;
+
+ /* The rest is used by k_cfunc objects. */
+ bool cfuncnamefound;
+ char cfuncname[200];
+ int cfuncrettype; //0=int, 1=float
+ int numargs;
+ char cfuncargtypes[50000];
+ char cfuncargnames[50000];
+};
+
+
+
+
+/******************************/
+/* Set up inlets and outlets. */
+/******************************/
+static void k_cext_makeinletsandoutlets(t_k_cext *x,t_int argc,t_atom* argv){
+ int lokke;
+
+ if(argc<2 || argv[1].a_type!=A_FLOAT){
+ x->num_outs=0;
+ }else{
+ x->num_outs=atom_getfloatarg(1,argc,argv);
+ x->outlets=calloc(sizeof(t_outlet*),x->num_outs);
+ }
+
+ if(argc<1 || argv[1].a_type!=A_FLOAT){
+ x->num_ins=1;
+ }else{
+ x->num_ins=atom_getfloatarg(0,argc,argv);
+ }
+
+ x->inlets=calloc(sizeof(t_inlet*),x->num_ins);
+ x->values=calloc(sizeof(t_float),x->num_ins);
+
+ for(lokke=1;lokke<x->num_ins;lokke++){
+ x->inlets[lokke-1] = floatinlet_new(&x->x_ob, &x->values[lokke]);
+ }
+
+ for(lokke=0;lokke<x->num_outs;lokke++){
+ x->outlets[lokke] = outlet_new(&x->x_ob, gensym("float"));
+ }
+
+}
+
+
+/******************************/
+/* Set default values for the inlets. */
+/******************************/
+static int k_cext_setdefaultvalues(t_k_cext *x,t_int argc, t_atom* argv){
+ int i;
+ for(i=2;i<argc;i++){
+ char string[500];
+ switch(argv[i].a_type){
+ case A_FLOAT:
+ x->values[i-2]=atom_getfloatarg(i,argc,argv);
+ break;
+ case A_SYMBOL:
+ return i;
+ }
+ }
+ return i;
+}
+
+
+
+#include "k_cext_generatecode.c"
+
+
+
+static void *k_cextandfunc_new(t_symbol *s, t_int argc, t_atom* argv,bool iscext)
+{
+ char temp[500];
+ int i;
+
+ struct k_cext_init k;
+
+ t_k_cext *x = (t_k_cext *)pd_new(k_cext_class);
+ x->iscext=iscext;
+
+ memset(&k,0,sizeof(struct k_cext_init));
+
+ k_cext_makeinletsandoutlets(x,argc,argv);
+
+ if(argv[2].a_type==A_FLOAT){
+ i=k_cext_setdefaultvalues(x,argc,argv);
+ }else{
+ if(argv[1].a_type==A_FLOAT){
+ i=2;
+ }else{
+ if(argv[0].a_type==A_FLOAT){
+ i=1;
+ }else{
+ i=0;
+ }
+ }
+ }
+
+ k_sys_mktempfilename(x->filename);
+ sprintf(k.name,"%s",x->filename);
+ k.name[strlen(k.name)+2]=0;
+ k.name[strlen(k.name)+1]='c';
+ k.name[strlen(k.name)]='.';
+
+ k.file=fopen(k.name,"w");
+ // post("name: %s\n",name)
+
+ k_sys_writeincludes(k.file);
+
+
+
+ k_cext_generatecode(x,argc,argv,i,&k);
+
+
+
+ /*************************************/
+ /* Compile and link */
+ /*************************************/
+
+ k_sys_makecompilestring(temp,k.name,k.funcname);
+ post("Compiling %s",k.name);
+ system(temp);
+
+ sprintf(k.name,"%s.o",k.name);
+
+ if(!k_sys_getprocessfunction(x,k.funcname,k.name)){
+ FILE *printfile;
+ post("Error in loader!");
+ x->k_cext_process=NULL;
+ k_cext_print(x);
+ return NULL;
+ }
+
+
+ if(x->iscext==false){
+ if(k.cfuncrettype==0){
+ k_cext_addintfunc(k.cfuncname,x);
+ }else{
+ k_cext_addfloatfunc(k.cfuncname,x);
+ }
+ }
+
+ return (void *)x;
+}
+
+static void *k_cext_new(t_symbol *s, t_int argc, t_atom* argv){
+ return k_cextandfunc_new(s,argc,argv,true);
+}
+
+static void *k_cfunc_new(t_symbol *s, t_int argc, t_atom* argv){
+ return k_cextandfunc_new(s,argc,argv,false);
+}
+
+
+
+static void k_cext_free(t_k_cext *x)
+{
+ char temp[500];
+
+ if(x->iscext==false){
+ k_cext_setdummy(x->k_cext_process);
+ }
+
+ if(x->handle!=NULL){
+ k_sys_freehandle(x);
+ }
+
+ sprintf(temp,"%s.c",x->filename);
+ k_sys_deletefile(temp);
+
+ free(x->inlets);
+ free(x->outlets);
+ free(x->values);
+}
+
+
+
+
+void k_cext_setup(void)
+{
+
+ k_sys_init();
+
+ /* k_cext */
+ k_cext_class = class_new(gensym("k_cext"), (t_newmethod)k_cext_new,
+ (t_method)k_cext_free, sizeof(t_k_cext), 0, A_GIMME, 0);
+ class_addfloat(k_cext_class, k_cext_float);
+ class_addbang(k_cext_class, (t_method)k_cext_bang);
+ class_addmethod(k_cext_class, (t_method)k_cext_print, gensym("print"), 0);
+ class_sethelpsymbol(k_cext_class, gensym("help-k_cext.pd"));
+
+ /* k_cfunc */
+ k_cfunc_class = class_new(gensym("k_cfunc"), (t_newmethod)k_cfunc_new,
+ (t_method)k_cext_free, sizeof(t_k_cext), 0, A_GIMME, 0);
+
+ // This does not work! Why? (Have to make workaround-code in k_cext_bang)
+ class_addfloat(k_cfunc_class, k_cfunc_float);
+ class_addmethod(k_cfunc_class, (t_method)k_cext_print, gensym("print"), 0);
+ class_sethelpsymbol(k_cfunc_class, gensym("help-k_cfunc.pd"));
+
+
+ post(version);
+}
+
+void k_cfunc_setup(void){
+ k_cext_setup();
+}
diff --git a/k_cext.h b/k_cext.h
new file mode 100644
index 0000000..1b1741a
--- /dev/null
+++ b/k_cext.h
@@ -0,0 +1,185 @@
+/*
+ * k_cext.h copyright 2002 Kjetil S. Matheussen.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <stdbool.h>
+#ifdef _MSC_VER
+typedef int bool;
+#define true 1
+#define false 0
+#else
+#include <stdbool.h>
+#endif
+
+#include <stdarg.h>
+
+typedef struct k_cext
+{
+ t_object x_ob;
+ t_float *values;
+
+ int num_ins;
+ int num_outs;
+
+ t_inlet **inlets;
+ t_outlet **outlets;
+
+ void (*k_cext_process)(struct k_cext *x);
+ void *handle;
+
+ char filename[40];
+
+ bool iscext;
+
+ void *userdata; // This attribute /can/ be used by a patch, but using "static" is much cleaner, so please don't.
+} t_k_cext;
+
+
+/* The following functions are used by intsort and floatsort */
+extern int k_cext_intcompare(const void *p1, const void *p2);
+extern int k_cext_floatcompare(const void *p1, const void *p2);
+
+
+/* The following functions are system dependant, and called internally from k_cext only.
+ All ports must implement these functions.
+ */
+
+extern int k_sys_getprocessfunction(t_k_cext *x,char *funcname,char *name);
+extern void k_sys_freehandle(t_k_cext *x);
+extern void k_sys_mktempfilename(char *to);
+extern void k_sys_writeincludes(FILE *file);
+extern void k_sys_makecompilestring(char *to,char *name,char *funcname);
+extern void k_sys_deletefile(char *name);
+extern void k_sys_init(void);
+
+
+
+#define V(a) (x->values[a])
+#define I(a) ((int)(x->values[a]))
+
+
+#define O(a,b) outlet_float(x->outlets[a],b)
+
+#define O0(b) O(0,b)
+#define O1(b) O(1,b)
+#define O2(b) O(2,b)
+#define O3(b) O(3,b)
+#define O4(b) O(4,b)
+#define O5(b) O(5,b)
+#define O6(b) O(6,b)
+
+#define BETWEEN(dasmin,dasmax) ((dasmin) + (((float)(dasmax-(dasmin)))*rand())/(RAND_MAX+1.0))
+#define RANDOM(dasmax) BETWEEN(0,dasmax)
+
+#define SEND(symname,val) \
+do{ \
+ static t_symbol *k_cext_internal_symbol=NULL; \
+ if(k_cext_internal_symbol==NULL) k_cext_internal_symbol=gensym(symname); \
+ if(k_cext_internal_symbol->s_thing) pd_float(k_cext_internal_symbol->s_thing, val); \
+}while(0)
+
+
+
+#define INTARRAY(name,len) int name[len]={0}
+#define FLOATARRAY(name,len) t_float name[len]={0.0f}
+
+#define INTSORT(a,b) qsort((void *)(a),b, sizeof (int), k_cext_intcompare);
+#define FLOATSORT(a,b) qsort((void *)(a),b, sizeof (float), k_cext_floatcompare);
+
+
+#define IF if(
+#define FOR for(
+#define RANGE(a,b,c) for(a=b;a<c;a++)
+#define WHILE while(
+#define SWITCH switch(
+
+#define THEN )
+#define BEGIN {
+
+#define LOOP for(;;){
+
+#define ELIF }else if(
+
+/* If you think "END ELSE BEGIN" is more natural, just write "END else BEGIN". */
+#define ELSE }else{
+
+#define END }
+#define ENDFOR END
+#define ENDRANGE END
+#define ENDIF END
+#define ENDWHILE END
+#define ENDLOOP END
+#define ENDSWITCH END
+
+#define SC ;
+
+#define NL "\n"
+
+#define SP " "
+
+
+typedef int (*k_cext_f_int_callback)(t_k_cext *x,...);
+typedef float (*k_cext_f_float_callback)(t_k_cext *x,...);
+
+#ifndef _MSC_VER
+static k_cext_f_int_callback *k_cext_int_funcs[];
+static k_cext_f_float_callback *k_cext_float_funcs[];
+static t_k_cext **k_cext_int_x[];
+static t_k_cext **k_cext_float_x[];
+#else
+k_cext_f_int_callback *k_cext_int_funcs[];
+k_cext_f_float_callback *k_cext_float_funcs[];
+t_k_cext **k_cext_int_x[];
+t_k_cext **k_cext_float_x[];
+#endif
+
+bool k_cext_get_int_funcs(k_cext_f_int_callback **funcs,t_k_cext **xs[],int length,...);
+bool k_cext_get_float_funcs(k_cext_f_float_callback **funcs,t_k_cext **xs[],int length,...);
+
+
+#define INT_(b,a) (*k_cext_int_funcs[a])
+#define I_(a) *k_cext_int_x[a]
+
+
+/*
+ The alternative suggested by Thomas Grill might be better:
+
+#define INT_0(b,a) (*k_cext_int_funcs[a])(*k_cext_int_x[a])
+#define INT_1(b,a,c) (*k_cext_int_funcs[a])(*k_cext_int_x[a],c)
+#define INT_2(b,a,c,d) (*k_cext_int_funcs[a])(*k_cext_int_x[a],c,d)
+#define INT_3(b,a,c,e) (*k_cext_int_funcs[a])(*k_cext_int_x[a],c,d,e)
+#define INT_4(b,a,c,e,f) (*k_cext_int_funcs[a])(*k_cext_int_x[a],c,d,e,f)
+...
+ */
+
+
+/* VC is reported not to be an iso99 c compiler, so the following very nice macro can't be used. #$¥5¥@{@{@$¥@ !!! */
+/* #define F_INT(a,...) (*k_cext_int_funcs[a])(*k_cext_int_x[a],__VA_ARGS__) */
+
+
+#define FLOAT_(b,a) (*k_cext_float_funcs[a])
+#define F_(a) *k_cext_float_x[a]
+
+/* Same here. */
+/* #define F_FLOAT(a,...) (*k_cext_float_funcs[a])(*k_cext_float_x[a],__VA_ARGS__) */
+
diff --git a/k_cext_funchandler.c b/k_cext_funchandler.c
new file mode 100644
index 0000000..2554fdd
--- /dev/null
+++ b/k_cext_funchandler.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2003 Kjetil S. Matheussen.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+#define MAX_FUNCS 1000
+#define MAX_FUNCLENGTH 50
+
+static char k_cext_intfuncnames[MAX_FUNCLENGTH*MAX_FUNCS]={0};
+static k_cext_f_int_callback k_cext_intfuncpointers[MAX_FUNCS]={0};
+static t_k_cext *k_cext_intxs[MAX_FUNCS];
+
+static char k_cext_floatfuncnames[MAX_FUNCLENGTH*MAX_FUNCS]={0};
+static k_cext_f_float_callback k_cext_floatfuncpointers[MAX_FUNCS]={0};
+static t_k_cext *k_cext_floatxs[MAX_FUNCS];
+
+
+
+static int k_cext_intdummy(t_k_cext *x,...){
+ post("Error. An integer k_func function has dissapeared. Returning 0 instead.\n");
+ return 0;
+}
+
+static float k_cext_floatdummy(t_k_cext *x,...){
+ post("Error. A float k_func function has dissapeared. Returning 0.0f instead.\n");
+ return 0.0f;
+}
+
+void k_cext_setdummy(void *func){
+ int lokke;
+ for(lokke=0;lokke<MAX_FUNCS;lokke++){
+ if(k_cext_intfuncpointers[lokke]==func){
+ k_cext_intfuncpointers[lokke]=k_cext_intdummy;
+ return;
+ }
+ }
+ for(lokke=0;lokke<MAX_FUNCS;lokke++){
+ if(k_cext_floatfuncpointers[lokke]==func){
+ k_cext_floatfuncpointers[lokke]=k_cext_floatdummy;
+ return;
+ }
+ }
+}
+
+
+static void k_cext_addintfunc(char *name,t_k_cext *x){
+ int lokke;
+
+ for(lokke=0;lokke<MAX_FUNCS;lokke++){
+ if(k_cext_intfuncpointers[lokke]==NULL || !strcmp(&k_cext_intfuncnames[lokke*MAX_FUNCLENGTH],name)){
+ post("---Adding ---%s--- at pos %d",name,lokke);
+ sprintf(&k_cext_intfuncnames[lokke*MAX_FUNCLENGTH],"%s",name);
+ k_cext_intxs[lokke]=x;
+ k_cext_intfuncpointers[lokke]=(k_cext_f_int_callback)x->k_cext_process;
+ return;
+ }
+ }
+}
+
+static void k_cext_addfloatfunc(char *name,t_k_cext *x){
+ int lokke;
+ for(lokke=0;lokke<MAX_FUNCS;lokke++){
+ if(k_cext_floatfuncpointers[lokke]==NULL || !strcmp(&k_cext_floatfuncnames[lokke*MAX_FUNCLENGTH],name)){
+ post("---Adding ---%s--- at pos %d",name,lokke);
+ sprintf(&k_cext_floatfuncnames[lokke*MAX_FUNCLENGTH],"%s",name);
+ k_cext_floatxs[lokke]=x;
+ k_cext_floatfuncpointers[lokke]=(k_cext_f_float_callback)x->k_cext_process;
+ return;
+ }
+ }
+}
+
+static int k_cext_findintfromname(char *name){
+ int lokke;
+ for(lokke=0;lokke<MAX_FUNCS;lokke++){
+ if(!strcmp(&k_cext_intfuncnames[lokke*MAX_FUNCLENGTH],name)){
+ return lokke;
+ }
+ }
+ return -1;
+}
+static int k_cext_findfloatfromname(char *name){
+ int lokke;
+ for(lokke=0;lokke<MAX_FUNCS;lokke++){
+ if(!strcmp(&k_cext_floatfuncnames[lokke*MAX_FUNCLENGTH],name)){
+ return lokke;
+ }
+ }
+ return -1;
+}
+
+
+
+bool k_cext_get_int_funcs(k_cext_f_int_callback **funcs,t_k_cext **xs[],int length,...){
+ int lokke;
+ bool ret=true;
+ va_list ap;
+ va_start(ap,length);
+
+ for(lokke=0;lokke<length;lokke++){
+ char *name=va_arg(ap,char *);
+ int num=k_cext_findintfromname(name);
+ if(num==-1){
+ post("Error, the k_func function with the name \"%s\" was not found.\n",name);
+ ret=false;
+ goto exit;
+ }
+ funcs[lokke]=&k_cext_intfuncpointers[num];
+ xs[lokke]=&k_cext_intxs[lokke];
+ }
+
+ exit:
+ va_end(ap);
+
+ return ret;
+}
+
+bool k_cext_get_float_funcs(k_cext_f_float_callback **funcs,t_k_cext **xs[],int length,...){
+ int lokke;
+ bool ret=true;
+ va_list ap;
+ va_start(ap,length);
+
+ for(lokke=0;lokke<length;lokke++){
+ char *name=va_arg(ap,char *);
+ int num=k_cext_findfloatfromname(name);
+ if(num==-1){
+ post("Error, the k_func function with the name \"%s\" was not found.\n",name);
+ ret=false;
+ goto exit;
+ }
+ funcs[lokke]=&k_cext_floatfuncpointers[num];
+ xs[lokke]=&k_cext_floatxs[num];
+ //post("xs[%d]=%x for %s",lokke,(unsigned int)xs[lokke],name);
+ }
+
+ exit:
+ va_end(ap);
+ return ret;
+}
+
+
diff --git a/k_cext_generatecode.c b/k_cext_generatecode.c
new file mode 100644
index 0000000..d2e493e
--- /dev/null
+++ b/k_cext_generatecode.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright 2003 Kjetil S. Matheussen.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+static bool has_intfunc(char *string){
+ if(strstr(string,"INT_(")) return false;
+ if(strstr(string,"INT_")) return true;
+ return false;
+}
+
+static bool has_floatfunc(char *string){
+ if(strstr(string,"FLOAT_(")) return false;
+ if(strstr(string,"FLOAT_")) return true;
+ return false;
+}
+
+static void k_cext_fixfuncs(struct k_cext_init *k,char *string){
+ char newstring[500];
+
+ sprintf(newstring,"%s",string);
+
+ if(has_intfunc(newstring)){
+ char name[500]={0};
+ char *f_intstart=strstr(newstring,"INT_");
+ char *f_namestart=f_intstart+4;
+ char *f_nameend=strstr(f_namestart+1,"(");
+ int lastarg=false;
+
+ //post("namestart: -%s-",f_namestart);
+ //post("nameend: -%s-",f_nameend);
+
+ if(f_nameend==NULL){
+ post("Error. k_cext needs this syntax: \"%s(\", not \"%s (\"",f_intstart,f_intstart);
+ return;
+ }
+
+ if(f_nameend[1]==')') lastarg=true;
+
+ memcpy(&k->intfuncnames[k->num_intfuncs*50],f_namestart,f_nameend-f_namestart);
+ memcpy(name,f_namestart,f_nameend-f_namestart);
+
+ f_intstart[0]=0;
+ sprintf(string,
+ "%s INT_(%s,%d)(I_(%d)%s %s",
+ newstring,
+ name,
+ k->num_intfuncs,
+ k->num_intfuncs,
+ lastarg==true?"":",",
+ f_nameend+1
+ );
+ k->num_intfuncs++;
+ }else{
+ if(has_floatfunc(newstring)){
+ char name[500]={0};
+ char *f_floatstart=strstr(newstring,"FLOAT_");
+ char *f_namestart=f_floatstart+6;
+ char *f_nameend=strstr(f_namestart+1,"(");
+ int lastarg=false;
+
+ //post("namestart: -%s-",f_namestart);
+ //post("nameend: -%s-",f_nameend);
+
+
+ if(f_nameend==NULL){
+ post("Error, k_cext needs this syntax: \"%s(\", not \"%s (\"",f_floatstart,f_floatstart);
+ return;
+ }
+
+ if(f_nameend[1]==')') lastarg=true;
+
+ memcpy(&k->floatfuncnames[k->num_floatfuncs*50],f_namestart,f_nameend-f_namestart);
+ memcpy(name,f_namestart,f_nameend-f_namestart);
+
+ f_floatstart[0]=0;
+ sprintf(string,
+ "%s FLOAT_(%s,%d)(F_(%d)%s %s",
+ newstring,
+ name,
+ k->num_floatfuncs,
+ k->num_floatfuncs,
+ lastarg==true?"":",",
+ f_nameend+1
+ );
+
+ k->num_floatfuncs++;
+ }else{
+ return;
+ }
+ }
+
+ if(has_intfunc(string) || has_floatfunc(string)){
+ k_cext_fixfuncs(k,string);
+ }
+}
+
+
+static void k_cext_gen_funcname(struct k_cext_init *k){
+ sprintf(k->funcname,"k_cext_process%d",instancenumber++);
+
+ k->doinitpos1=ftell(k->file);
+ fprintf(k->file," \n");
+ // static bool doinit(void);
+
+ fprintf(k->file,"void %s(t_k_cext *x){\n",k->funcname);
+ k->doinitpos2=ftell(k->file);
+ fprintf(k->file," \n");
+ // if(doinit()){
+
+}
+
+
+static int k_cext_gen_cfunc_funcname(t_k_cext *x,int argc, t_atom* argv,int i, struct k_cext_init *k){
+ char string[500];
+ int lokke;
+
+ k->doinitpos1=ftell(k->file);
+ fprintf(k->file," \n");
+
+ sprintf(string,"%s",atom_getsymbolarg(i,argc,argv)->s_name);
+ if(!strncmp(string,"INT_",4)){
+ k->cfuncrettype=0;
+ sprintf(k->cfuncname,"%s",string+4);
+ }else{
+ if(!strncmp(string,"FLOAT_",6)){
+ k->cfuncrettype=1;
+ sprintf(k->cfuncname,"%s",string+6);
+ }else{
+ post("k_cfunc: Error. Function name must begin with either INT_ or FLOAT_.");
+ return 1;
+ }
+ }
+ i++;
+
+ for(;i<argc;i+=2){
+ sprintf(string,"%s",atom_getsymbolarg(i,argc,argv)->s_name);
+ if(!strcmp(string,";")) goto end;
+ if(!strcmp(string,"float") || !strcmp(string,"t_float")){
+ sprintf(string,"double");
+ }
+ sprintf(&k->cfuncargtypes[k->numargs*50],"%s",string);
+ sprintf(&k->cfuncargnames[k->numargs*50],"%s",atom_getsymbolarg(i+1,argc,argv)->s_name);
+ k->numargs++;
+ }
+
+ end:
+
+ fprintf(k->file,"static %s %s(t_k_cext *x%s",k->cfuncrettype==0?"int":"float",k->cfuncname,k->numargs>0?",":"){\n");
+ for(lokke=0;lokke<k->numargs;lokke++){
+ fprintf(k->file,"%s %s%s",&k->cfuncargtypes[lokke*50],&k->cfuncargnames[lokke*50],lokke==k->numargs-1?"){\n":",");
+ }
+
+ k->doinitpos2=ftell(k->file);
+ fprintf(k->file," \n");
+
+ return i;
+}
+
+
+static void k_cext_gen_mainfunccode(t_k_cext *x,int argc, t_atom* argv,int i, struct k_cext_init *k){
+ int lokke;
+ int prevwasnewline=1;
+
+ for(;i<argc;i++){
+ char string[500];
+ switch(argv[i].a_type){
+ case A_FLOAT:
+ if((float)atom_getintarg(i,argc,argv)==atom_getfloatarg(i,argc,argv)){
+ fprintf(k->file,"%d ",(int)atom_getintarg(i,argc,argv));
+ }else{
+ fprintf(k->file,"%f ",atom_getfloatarg(i,argc,argv));
+ }
+ prevwasnewline=0;
+ break;
+ case A_SYMBOL:
+ sprintf(string,"%s",atom_getsymbolarg(i,argc,argv)->s_name);
+ if(!strcmp(".",string)){
+ sprintf(string," ");
+ k->indentation++;
+
+ }else{if(!strcmp("DO",string)){
+ k->set_indentation[k->indentation]=1;
+ sprintf(string,"BEGIN");
+
+ }else{if(!strcmp(";",string)){
+ if(prevwasnewline==1) break;
+ sprintf(string,";\n");
+ prevwasnewline=1;
+ k->indentation=0;
+ k->thisisanelifline=0;
+
+ }else{if(!strcmp("ELIF",string)){
+ k->thisisanelifline=1;
+
+ }else{
+
+ if(strstr(string,"INT_") || strstr(string,"FLOAT_")){
+ k_cext_fixfuncs(k,string);
+ }
+
+ prevwasnewline=0;
+ //post("%d: -%s-",k->indentation,string);
+
+ if(
+ strcmp("ELSE",string)
+ && k->thisisanelifline==0
+ )
+ {
+ int hasindented=0;
+ char orgind[500];
+ for(lokke=0;lokke<k->indentation*2;lokke++){
+ orgind[lokke]=' ';
+ }
+ orgind[lokke]=0;
+ for(lokke=499;lokke>=k->indentation;lokke--){
+ if(k->set_indentation[lokke]==1){
+ k->set_indentation[lokke]=0;
+ fprintf(k->file,"END\n");
+ hasindented++;
+ }
+ }
+ if(hasindented>0){
+ char temp2[500];
+ sprintf(temp2,"%s%s",orgind,string);
+ sprintf(string,temp2);
+ }
+ }
+ }
+ }
+ /*
+ if(!strcmp("\n",string)){
+ sprintf(string," ");
+ }
+ */
+ }
+ }
+ fprintf(k->file,"%s",string);
+ if(string[strlen(string)-1]!='\n') fprintf(k->file," ");
+ break;
+ default:
+ post("k_cext.c: Unknown argv type: %d",argv[i].a_type);
+ post("Please send this patch to k->s.matheussen@notam02.no .");
+ break;
+ }
+ }
+}
+
+static void k_cext_gen_endbrackets(struct k_cext_init *k){
+ int lokke;
+ for(lokke=499;lokke>=0;lokke--){
+ if(k->set_indentation[lokke]==1){
+ int lokke2;
+ for(lokke2=0;lokke2<lokke;lokke2++){
+ fprintf(k->file," ");
+ }
+ fprintf(k->file,"END\n");
+ }
+ }
+ fprintf(k->file,"}");
+}
+
+
+static void k_cext_gen_funcs_dasfunc(struct k_cext_init *k){
+ sprintf(k->funcname,"k_cext_process%d",instancenumber++);
+
+ fprintf(k->file,"\n%s %s(t_k_cext *x%s){\n",k->cfuncrettype==0?"int":"float",k->funcname,k->numargs>0?",...":"");
+
+ if(k->numargs>0){
+ int lokke;
+ fprintf(k->file," va_list k_cext_a;\n");
+ for(lokke=0;lokke<k->numargs;lokke++){
+ fprintf(k->file," %s %s;\n",&k->cfuncargtypes[lokke*50],&k->cfuncargnames[lokke*50]);
+ }
+ fprintf(k->file," va_start(k_cext_a,x);\n");
+ for(lokke=0;lokke<k->numargs;lokke++){
+ fprintf(k->file," %s=va_arg(k_cext_a,%s);\n",&k->cfuncargnames[lokke*50],&k->cfuncargtypes[lokke*50]);
+ }
+ fprintf(k->file," va_end(k_cext_a);\n");
+
+ fprintf(k->file," return %s(x,",k->cfuncname);
+ for(lokke=0;lokke<k->numargs;lokke++){
+ fprintf(k->file,"%s%s",&k->cfuncargnames[lokke*50],lokke==k->numargs-1?");\n}\n":",");
+ }
+
+ }else{
+ fprintf(k->file," return %s(x);\n}\n",k->cfuncname);
+ }
+}
+
+
+static void k_cext_gen_doinit(t_k_cext *x,struct k_cext_init *k){
+ int lokke;
+ if(k->num_intfuncs>0 || k->num_floatfuncs>0){
+ if(x->iscext==true){
+ fprintf(k->file,"}\n");
+ }
+
+ fprintf(k->file,
+ "static bool doinit(void){\n"
+ " static bool k_cext_inited=false;\n"
+ " if(k_cext_inited==false){\n"
+ );
+ if(k->num_intfuncs>0){
+ fprintf(k->file," if(k_cext_get_int_funcs(&k_cext_int_funcs[0],&k_cext_int_x[0],%d,",k->num_intfuncs);
+ for(lokke=0;lokke<k->num_intfuncs;lokke++){
+ fprintf(k->file,"\"%s\"%s",k->intfuncnames+(lokke*50),lokke<k->num_intfuncs-1?",":"");
+ }
+ fprintf(k->file,")==false) return false;\n");
+ }
+
+ if(k->num_floatfuncs>0){
+ fprintf(k->file," if(k_cext_get_float_funcs(&k_cext_float_funcs[0],&k_cext_float_x[0],%d,",k->num_floatfuncs);
+ for(lokke=0;lokke<k->num_floatfuncs;lokke++){
+ fprintf(k->file,"\"%s\"%s",k->floatfuncnames+(lokke*50),lokke<k->num_floatfuncs-1?",":"");
+ }
+ fprintf(k->file,")==false) return false;\n");
+ }
+
+ fprintf(k->file,
+ " k_cext_inited=true;\n"
+ " }\n"
+ " return true;\n"
+ "}\n"
+ );
+
+ if(k->num_intfuncs>0){
+ fprintf(k->file,
+#ifndef _MSC_VER
+ "static "
+#endif
+ "k_cext_f_int_callback *k_cext_int_funcs[%d]={0};\n"
+#ifndef _MSC_VER
+ "static "
+#endif
+ "t_k_cext **k_cext_int_x[%d]={0};\n",
+ k->num_intfuncs,k->num_intfuncs
+ );
+ }
+
+ if(k->num_floatfuncs>0){
+ fprintf(k->file,
+#ifndef _MSC_VER
+ "static "
+#endif
+ "k_cext_f_float_callback *k_cext_float_funcs[%d]={0};\n"
+#ifndef _MSC_VER
+ "static "
+#endif
+ "t_k_cext **k_cext_float_x[%d]={0};\n",
+ k->num_floatfuncs,k->num_floatfuncs
+ );
+ }
+
+ fseek(k->file,k->doinitpos1,SEEK_SET);
+ fprintf(k->file,"static bool doinit(void);");
+
+ fseek(k->file,k->doinitpos2,SEEK_SET);
+ fprintf(k->file,"if(doinit()){");
+ }else{
+ fprintf(k->file,"\n");
+ }
+
+}
+
+static void k_cext_generatecode(t_k_cext *x,int argc, t_atom* argv,int i, struct k_cext_init *k){
+
+ if(x->iscext==true){
+ k_cext_gen_funcname(k);
+ }else{
+ i=k_cext_gen_cfunc_funcname(x,argc,argv,i,k);
+ }
+
+ k_cext_gen_mainfunccode(x,argc,argv,i,k);
+ k_cext_gen_endbrackets(k);
+
+ if(x->iscext==false){
+ if(k->num_intfuncs>0 || k->num_floatfuncs>0){
+ fprintf(k->file,"return 0;}\n");
+ }
+ k_cext_gen_funcs_dasfunc(k);
+ }
+
+ k_cext_gen_doinit(x,k);
+
+ fclose(k->file);
+}
diff --git a/k_cext_macosx.c b/k_cext_macosx.c
new file mode 100644
index 0000000..1bfe97a
--- /dev/null
+++ b/k_cext_macosx.c
@@ -0,0 +1,87 @@
+/* k_cext_macosx.c. MacosX part of k_cext. Made by Kjetil Matheussen. Never tested. */
+//
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/* ---------------------------------------------------------------------------- */
+
+#include "m_pd.h"
+#include "k_cext.h"
+
+#include <unistd.h>
+
+#include <mach-o/dyld.h>
+
+int k_sys_getprocessfunction(t_k_cext *x,char *funcname,char *name){
+ NSObjectFileImage image;
+ void *ret;
+ NSSymbol s;
+
+ x->k_cext_process=NULL;
+ x->handle=NULL;
+
+ if ( NSCreateObjectFileImageFromFile( name, &image) != NSObjectFileImageSuccess ){
+ post("Error. \n");
+ return 0;
+ }
+ ret=NSLinkModule( image, name, NSLINKMODULE_OPTION_BINDNOW);
+ s = NSLookupSymbolInModule(ret,funcname);
+
+ if(s){
+ x->k_cext_process = (t_xxx)NSAddressOfSymbol( s);
+ }else{
+ return 0;
+ }
+
+ return 1;
+}
+
+void k_sys_freehandle(t_k_cext *x){
+ post("k_cext_macosx.c/k_sys_freehandle: FIX ME.\n");
+}
+
+
+void k_sys_mktempfilename(char *to){
+ sprintf(to,"/tmp/pd-k_cext-XXXXXX");
+ mktemp(to);
+}
+
+void k_sys_writeincludes(FILE *file){
+ fprintf(file,"#include \"" INCLUDEPATH "/" LINUXINCLUDE "/m_pd.h\"\n");
+ fprintf(file,"#include \"" INCLUDEPATH "/k_cext.h\"\n");
+}
+
+
+void k_sys_makecompilestring(char *to,char *name,char *funcname){
+ sprintf(to,"gcc -Wall -O2 %s -o %s.o -shared",name,name);
+}
+
+void k_sys_deletefile(char *name){
+ unlink(name);
+}
+
+static void k_sys_cleanup(void){
+ system("rm -fr /tmp/pd-k_cext-*");
+}
+
+static void finish(int sig){
+ k_sys_cleanup();
+ exit(0);
+}
+
+
+void k_sys_init(void){
+ atexit(k_sys_cleanup);
+ signal(SIGINT,finish);
+}
diff --git a/k_cext_unix.c b/k_cext_unix.c
new file mode 100644
index 0000000..ee9c252
--- /dev/null
+++ b/k_cext_unix.c
@@ -0,0 +1,77 @@
+/* k_cext_unix.c. unix part of k_cext. Made by Kjetil Matheussen. Never tested. */
+//
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/* ---------------------------------------------------------------------------- */
+
+#include <m_pd.h>
+#include "k_cext.h"
+#include <dlfcn.h>
+
+#include <unistd.h>
+#include <signal.h>
+
+
+int k_sys_getprocessfunction(t_k_cext *x,char *funcname,char *name){
+
+ x->handle=dlopen(name,RTLD_NOW|RTLD_GLOBAL);
+
+ if(x->handle!=NULL){
+ x->k_cext_process=(void (*)(struct k_cext *))dlsym(x->handle,funcname);
+ return 1;
+ }
+ return 0;
+}
+
+void k_sys_freehandle(t_k_cext *x){
+ char temp[500];
+ dlclose(x->handle);
+
+ sprintf(temp,"%s.c.o",x->filename);
+ unlink(temp);
+}
+
+void k_sys_mktempfilename(char *to){
+ sprintf(to,"/tmp/pd-k_cext-XXXXXX");
+ mktemp(to);
+}
+
+void k_sys_writeincludes(FILE *file){
+ fprintf(file,"#include \"" INCLUDEPATH "/" LINUXINCLUDE "/m_pd.h\"\n");
+ fprintf(file,"#include \"" INCLUDEPATH "/k_cext.h\"\n");
+}
+
+void k_sys_makecompilestring(char *to,char *name,char *funcname){
+ sprintf(to,"gcc -Wall -O2 %s -o %s.o -shared",name,name);
+}
+
+void k_sys_deletefile(char *name){
+ unlink(name);
+}
+
+static void k_sys_cleanup(void){
+ system("rm -fr /tmp/pd-k_cext-*");
+}
+
+static void finish(int sig){
+ k_sys_cleanup();
+ exit(0);
+}
+
+
+void k_sys_init(void){
+ atexit(k_sys_cleanup);
+ signal(SIGINT,finish);
+}
diff --git a/k_cext_win.c b/k_cext_win.c
new file mode 100644
index 0000000..7f2330d
--- /dev/null
+++ b/k_cext_win.c
@@ -0,0 +1,101 @@
+/* k_cext_win.c. Windows part of k_cext. Made by Kjetil Matheussen and Olaf Matthes. */
+//
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/* ---------------------------------------------------------------------------- */
+
+#include <io.h>
+#include <windows.h>
+
+#include "m_pd.h"
+#include "k_cext.h"
+
+#define MAX_INSTANCES 256
+
+char *nametemplate = "pd-XXXXXX";
+extern int instancenumber; /* number of instance of this object */
+char names[MAX_INSTANCES][9];
+
+
+int k_sys_getprocessfunction(t_k_cext *x, char *funcname, char *name){
+ char dllname[50];
+ strcpy(dllname, name);
+ sys_bashfilename(dllname, dllname);
+ dllname[strlen(dllname)-4]=0;
+ strcat(dllname, ".dll");
+ post("going to load %s...", dllname);
+ x->handle = LoadLibrary(dllname);
+
+ if (!x->handle){
+ x->handle=NULL;
+ post("Error (%d). \n", GetLastError());
+ return 0;
+ }
+ // x->k_cext_process = (t_xxx)GetProcAddress(x->handle, "k_cext_process");
+ x->k_cext_process=(void (*)(struct k_cext *))GetProcAddress(x->handle, funcname);
+ return 1;
+}
+
+void k_sys_freehandle(t_k_cext *x){
+ char temp[500];
+
+ FreeLibrary((HINSTANCE)x->handle);
+
+ sprintf(temp,"%s.dll",x->filename);
+ unlink(temp);
+ sprintf(temp,"%s.obj",x->filename);
+ unlink(temp);
+ sprintf(temp,"%s.exp",x->filename);
+ unlink(temp);
+ sprintf(temp,"%s.lib",x->filename);
+ unlink(temp);
+
+ unlink(x->filename);
+}
+
+void k_sys_mktempfilename(char *to){
+ char *temp;
+ FILE *file;
+ strcpy(names[instancenumber], nametemplate);
+ temp = _mktemp(names[instancenumber]);
+ if(temp == NULL)
+ {
+ error("could not create unique filename");
+ return;
+ }
+ sprintf(to,"%s",temp);
+ file=fopen(temp,"w"); /* we have to cheat ;-( */
+ fclose(file);
+}
+
+void k_sys_writeincludes(FILE *file){
+ fprintf(file,"#include \"" INCLUDEPATH "\\src\\m_pd.h\"\n");
+ fprintf(file,"#include \"" INCLUDEPATH "\\src\\k_cext.h\"\n"); /* needs to be in pd/src, sorry.. */
+}
+
+void k_sys_makecompilestring(char *to,char *name,char *funcname){
+ sprintf(to,"cl %s " INCLUDEPATH "\\bin\\pd.lib /LD /Gd /GD /Ox /DNT /link /export:%s",
+ name, funcname);
+}
+
+void k_sys_deletefile(char *name){
+ char delname[16];
+ post("del %s", name);
+ _unlink(name);
+
+}
+
+void k_sys_init(void){
+}
diff --git a/test.pd b/test.pd
new file mode 100644
index 0000000..f61becb
--- /dev/null
+++ b/test.pd
@@ -0,0 +1,16 @@
+#N canvas 321 226 450 300 10;
+#X floatatom 102 55 5 0 0;
+#X floatatom 112 275 5 0 0;
+#X floatatom 172 276 5 0 0;
+#X floatatom 218 278 5 0 0;
+#X floatatom 273 280 5 0 0;
+#X obj 160 39 k_cext 1 4 \; \; int lokke \; int a=5 \; \; RANGE(lokke
+\, 0 \, 4) DO \; . O(lokke \, I(0)) \; . IF I(0)==0 THEN DO \; . .
+O(1 \, 2) \; . ELIF I(0)==1 THEN DO \; . . O(2 \, 3) \; . ELSE \; .
+. O(3 \, 4) \; . . IF a==2 THEN DO \; . . . O(3 \, 23) \; . . . IF
+a==3 THEN DO \; . . . . O(2 \, 4) \;;
+#X connect 0 0 5 0;
+#X connect 5 0 1 0;
+#X connect 5 1 2 0;
+#X connect 5 2 3 0;
+#X connect 5 3 4 0;