[PD-cvs] externals/k_cext Makefile,NONE,1.1 README,NONE,1.1 help-do.pd,NONE,1.1 help-fibonacci.pd,NONE,1.1 help-gcd.pd,NONE,1.1 help-k_cext.pd,NONE,1.1 help-k_cext2.pd,NONE,1.1 help-k_cfunc.pd,NONE,1.1 help-markov.pd,NONE,1.1 help-rangeifelifelse.pd,NONE,1.1 help-send.pd,NONE,1.1 help-sort.pd,NONE,1.1 k_cext.c,NONE,1.1 k_cext.h,NONE,1.1 k_cext_funchandler.c,NONE,1.1 k_cext_generatecode.c,NONE,1.1 k_cext_macosx.c,NONE,1.1 k_cext_unix.c,NONE,1.1 k_cext_win.c,NONE,1.1 test.pd,NONE,1.1

ksvalast at users.sourceforge.net ksvalast at users.sourceforge.net
Thu Jan 8 15:55:26 CET 2004


Update of /cvsroot/pure-data/externals/k_cext
In directory sc8-pr-cvs1:/tmp/cvs-serv12055/k_cext

Added Files:
	Makefile README help-do.pd help-fibonacci.pd help-gcd.pd 
	help-k_cext.pd help-k_cext2.pd help-k_cfunc.pd help-markov.pd 
	help-rangeifelifelse.pd help-send.pd help-sort.pd k_cext.c 
	k_cext.h k_cext_funchandler.c k_cext_generatecode.c 
	k_cext_macosx.c k_cext_unix.c k_cext_win.c test.pd 
Log Message:
First commit of k_vst~, k_guile and k_cext

--- NEW FILE: Makefile ---
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

--- NEW FILE: README ---



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 at notam02.no

	The windows-port is made by Olaf Matthes.
	olaf.matthes at gmx.de


--- NEW FILE: help-do.pd ---
#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;

--- NEW FILE: help-fibonacci.pd ---
#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;

--- NEW FILE: help-gcd.pd ---
#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;

--- NEW FILE: help-k_cext.pd ---
#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;

--- NEW FILE: help-k_cext2.pd ---
#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;

--- NEW FILE: help-k_cfunc.pd ---
#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;

--- NEW FILE: help-markov.pd ---
#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;

--- NEW FILE: help-rangeifelifelse.pd ---
#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;

--- NEW FILE: help-send.pd ---
#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;

--- NEW FILE: help-sort.pd ---
#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;

--- NEW FILE: k_cext.c ---
/* --------------------------- 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 at 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();
}

--- NEW FILE: k_cext.h ---
/*
 *   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__) */


--- NEW FILE: k_cext_funchandler.c ---
/*
 *   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;
}



--- NEW FILE: k_cext_generatecode.c ---
/*
 *   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 at 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);
}

--- NEW FILE: k_cext_macosx.c ---
/* 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);
}

--- NEW FILE: k_cext_unix.c ---
/* 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);
}

--- NEW FILE: k_cext_win.c ---
/* 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){
}

--- NEW FILE: test.pd ---
#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;






More information about the Pd-cvs mailing list