From 44bc5a27d53124ba82becd4181fc381053c56fdb Mon Sep 17 00:00:00 2001 From: "Kjetil S. Matheussen" Date: Thu, 8 Jan 2004 14:55:24 +0000 Subject: First commit of k_vst~, k_guile and k_cext svn path=/trunk/externals/k_cext/; revision=1253 --- Makefile | 98 ++++++++++++ README | 248 +++++++++++++++++++++++++++++ help-do.pd | 30 ++++ help-fibonacci.pd | 12 ++ help-gcd.pd | 24 +++ help-k_cext.pd | 130 ++++++++++++++++ help-k_cext2.pd | 128 +++++++++++++++ help-k_cfunc.pd | 34 ++++ help-markov.pd | 66 ++++++++ help-rangeifelifelse.pd | 18 +++ help-send.pd | 28 ++++ help-sort.pd | 19 +++ k_cext.c | 335 ++++++++++++++++++++++++++++++++++++++++ k_cext.h | 185 ++++++++++++++++++++++ k_cext_funchandler.c | 157 +++++++++++++++++++ k_cext_generatecode.c | 402 ++++++++++++++++++++++++++++++++++++++++++++++++ k_cext_macosx.c | 87 +++++++++++ k_cext_unix.c | 77 ++++++++++ k_cext_win.c | 101 ++++++++++++ test.pd | 16 ++ 20 files changed, 2195 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100644 help-do.pd create mode 100644 help-fibonacci.pd create mode 100644 help-gcd.pd create mode 100644 help-k_cext.pd create mode 100644 help-k_cext2.pd create mode 100644 help-k_cfunc.pd create mode 100644 help-markov.pd create mode 100644 help-rangeifelifelse.pd create mode 100644 help-send.pd create mode 100644 help-sort.pd create mode 100644 k_cext.c create mode 100644 k_cext.h create mode 100644 k_cext_funchandler.c create mode 100644 k_cext_generatecode.c create mode 100644 k_cext_macosx.c create mode 100644 k_cext_unix.c create mode 100644 k_cext_win.c create mode 100644 test.pd 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 ". + + "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 [] 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 randoms_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;lokkenum_ins;lokke++){ + x->inlets[lokke-1] = floatinlet_new(&x->x_ob, &x->values[lokke]); + } + + for(lokke=0;lokkenum_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;ivalues[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 +#include +#include +#include +#include +#ifdef _MSC_VER +typedef int bool; +#define true 1 +#define false 0 +#else +#include +#endif + +#include + +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;ak_cext_process; + return; + } + } +} + +static void k_cext_addfloatfunc(char *name,t_k_cext *x){ + int lokke; + for(lokke=0;lokkek_cext_process; + return; + } + } +} + +static int k_cext_findintfromname(char *name){ + int lokke; + for(lokke=0;lokkeintfuncnames[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(;is_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;lokkenumargs;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(;ifile,"%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;lokkeindentation*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;lokke2file," "); + } + 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;lokkenumargs;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;lokkenumargs;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;lokkenumargs;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;lokkenum_intfuncs;lokke++){ + fprintf(k->file,"\"%s\"%s",k->intfuncnames+(lokke*50),lokkenum_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;lokkenum_floatfuncs;lokke++){ + fprintf(k->file,"\"%s\"%s",k->floatfuncnames+(lokke*50),lokkenum_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 + +#include + +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 +#include "k_cext.h" +#include + +#include +#include + + +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 +#include + +#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; -- cgit v1.2.1