kaya-0.4.4/0000755000175100017510000000000011170340772010552 5ustar cimcimkaya-0.4.4/LGPL30000644000175100017510000001672711170340770011331 0ustar cimcim GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. kaya-0.4.4/tests/0000755000175100017510000000000011170340770011712 5ustar cimcimkaya-0.4.4/tests/runtest.pl0000644000175100017510000000277211170340770013763 0ustar cimcim#!/usr/bin/perl my $exitstatus = 0; sub runtest { my ($test, $update) = @_; chdir($test); print "Running $test..."; $got = `sh ./run`; $exp = `cat expected`; open(OUT,">output"); print OUT $got; close(OUT); # $ok = system("diff output expected &> /dev/null"); # Mangle newlines in $got and $exp $got =~ s/\r\n/\n/g; $exp =~ s/\r\n/\n/g; if ($got eq $exp) { print "success\n"; } else { if ($update == 0) { $exitstatus = 1; print "FAILURE\n"; } else { system("cp output expected"); print "UPDATED\n"; } } chdir(".."); } if ($#ARGV>=0) { $test=shift(@ARGV); if ($test eq "all") { opendir(DIR, "."); @list = readdir(DIR); foreach $file (@list) { if ($file =~ /^test/) { push(@tests,$file); } } @tests = sort @tests; } else { push(@tests, $test); } @opts = @ARGV; } else { print "Give a test name, or 'all' to run all.\n"; exit; } $update=0; $diff=0; $show=0; while ($opt=shift(@opts)) { if ($opt eq "-u") { $update = 1; } if ($opt eq "-d") { $diff = 1; } if ($opt eq "-s") { $show = 1; } } foreach $test (@tests) { if ($diff == 0 && $show == 0) { runtest($test,$update); } else { chdir($test); if ($show == 1) { system("cat output"); } if ($diff == 1) { print "Differences in $test:\n"; $ok = system("diff output expected"); if ($ok == 0) { print "No differences found.\n"; } } chdir(".."); } } exit $exitstatus; kaya-0.4.4/tests/test035/0000755000175100017510000000000011170340767013127 5ustar cimcimkaya-0.4.4/tests/test035/test035.k0000644000175100017510000000044011170340767014510 0ustar cimcimprogram test035; Void runScary(String function) { Int(Int,Int) realfn = unmarshal(function,888); putStrLn("Result is "+realfn(5,32)); } Void main() { z = 5; plus = \(Int x,Int y) -> x+y+z; plusm = marshal(plus,888); // putStrLn(plusm); runScary(plusm); } kaya-0.4.4/tests/test035/expected0000644000175100017510000000004711170340767014654 0ustar cimcimCompiling program test035 Result is 42 kaya-0.4.4/tests/test035/run0000644000175100017510000000023011170340767013651 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test035.k -L ../../rts -L ../../stdlib ./test035 rm -f test035 test035.exe kaya-0.4.4/tests/test002/0000755000175100017510000000000011170340770013113 5ustar cimcimkaya-0.4.4/tests/test002/test002.k0000644000175100017510000000131511170340770014470 0ustar cimcim// -*-C-*- program test002; import Array; import Strings; Int add(var Int x, var Int y) { return x+y; } [Int] testarr() { arr = []; for x in [1..10] { for y in [5,3..-9] { push(arr,x*y); } } return arr; } Void main() { for y in range(10,20) { for z in range(1,5) { putStr( String(y)+"-"+String(z)+","); } putStr("\n"); } // print "Enter a number:"; // val = stringToInt(get(stdin())); val = 100; x = fold(add, range(1,val),0); putStr( "The sum of numbers from 1 to " + String(val) + " is " + String(x) + "\n"); for n in testarr { putStr(n+","); } putStr("\n"); for m in testarr() { putStr(m+","); } putStr("\n"); } kaya-0.4.4/tests/test002/expected0000644000175100017510000000155711170340770014647 0ustar cimcimCompiling program test002 10-1,10-2,10-3,10-4,10-5, 11-1,11-2,11-3,11-4,11-5, 12-1,12-2,12-3,12-4,12-5, 13-1,13-2,13-3,13-4,13-5, 14-1,14-2,14-3,14-4,14-5, 15-1,15-2,15-3,15-4,15-5, 16-1,16-2,16-3,16-4,16-5, 17-1,17-2,17-3,17-4,17-5, 18-1,18-2,18-3,18-4,18-5, 19-1,19-2,19-3,19-4,19-5, 20-1,20-2,20-3,20-4,20-5, The sum of numbers from 1 to 100 is 5050 5,3,1,-1,-3,-5,-7,-9,10,6,2,-2,-6,-10,-14,-18,15,9,3,-3,-9,-15,-21,-27,20,12,4,-4,-12,-20,-28,-36,25,15,5,-5,-15,-25,-35,-45,30,18,6,-6,-18,-30,-42,-54,35,21,7,-7,-21,-35,-49,-63,40,24,8,-8,-24,-40,-56,-72,45,27,9,-9,-27,-45,-63,-81,50,30,10,-10,-30,-50,-70,-90, 5,3,1,-1,-3,-5,-7,-9,10,6,2,-2,-6,-10,-14,-18,15,9,3,-3,-9,-15,-21,-27,20,12,4,-4,-12,-20,-28,-36,25,15,5,-5,-15,-25,-35,-45,30,18,6,-6,-18,-30,-42,-54,35,21,7,-7,-21,-35,-49,-63,40,24,8,-8,-24,-40,-56,-72,45,27,9,-9,-27,-45,-63,-81,50,30,10,-10,-30,-50,-70,-90, kaya-0.4.4/tests/test002/run0000644000175100017510000000024111170340767013645 0ustar cimcim#!/bin/bash export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test002.k -L ../../rts -L ../../stdlib ./test002 rm -f test002 test002.exe kaya-0.4.4/tests/test055/0000755000175100017510000000000011170340770013123 5ustar cimcimkaya-0.4.4/tests/test055/test055.k0000644000175100017510000000043711170340770014514 0ustar cimcimprogram test055; Int getNum(Int a) { z = 1; if (a % 2 == 0) { return 10; } else { return 208; } } Int constA = 44; Int constB = 17; (Int,Int) mkVal() { return (10+getNum(constA-4),215+getNum(constB-4)); } Void main() { m = mkVal(); putStrLn(m.fst+","+m.snd); } kaya-0.4.4/tests/test055/expected0000644000175100017510000000004111170340770014642 0ustar cimcimCompiling program test055 20,423 kaya-0.4.4/tests/test055/run0000644000175100017510000000023011170340770013645 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test055.k -L ../../rts -L ../../stdlib ./test055 rm -f test055 test055.exe kaya-0.4.4/tests/test009/0000755000175100017510000000000011170340767013130 5ustar cimcimkaya-0.4.4/tests/test009/test009.k0000644000175100017510000000037411170340766014517 0ustar cimcim// -*-C-*-ish program array; Void main() { for(y=0;y<30;y=y+1) { for(x=0;x<30;x=x+1) { i[x][y] = x*y; } } for(y=0;y<30;y=y+1) { for(x=0;x<30;x=x+1) { putStr( String(x)+"*"+String(y)+" = " + String(i[x][y])+"\n"); } } } kaya-0.4.4/tests/test009/expected0000644000175100017510000002310611170340767014656 0ustar cimcimCompiling program array 0*0 = 0 1*0 = 0 2*0 = 0 3*0 = 0 4*0 = 0 5*0 = 0 6*0 = 0 7*0 = 0 8*0 = 0 9*0 = 0 10*0 = 0 11*0 = 0 12*0 = 0 13*0 = 0 14*0 = 0 15*0 = 0 16*0 = 0 17*0 = 0 18*0 = 0 19*0 = 0 20*0 = 0 21*0 = 0 22*0 = 0 23*0 = 0 24*0 = 0 25*0 = 0 26*0 = 0 27*0 = 0 28*0 = 0 29*0 = 0 0*1 = 0 1*1 = 1 2*1 = 2 3*1 = 3 4*1 = 4 5*1 = 5 6*1 = 6 7*1 = 7 8*1 = 8 9*1 = 9 10*1 = 10 11*1 = 11 12*1 = 12 13*1 = 13 14*1 = 14 15*1 = 15 16*1 = 16 17*1 = 17 18*1 = 18 19*1 = 19 20*1 = 20 21*1 = 21 22*1 = 22 23*1 = 23 24*1 = 24 25*1 = 25 26*1 = 26 27*1 = 27 28*1 = 28 29*1 = 29 0*2 = 0 1*2 = 2 2*2 = 4 3*2 = 6 4*2 = 8 5*2 = 10 6*2 = 12 7*2 = 14 8*2 = 16 9*2 = 18 10*2 = 20 11*2 = 22 12*2 = 24 13*2 = 26 14*2 = 28 15*2 = 30 16*2 = 32 17*2 = 34 18*2 = 36 19*2 = 38 20*2 = 40 21*2 = 42 22*2 = 44 23*2 = 46 24*2 = 48 25*2 = 50 26*2 = 52 27*2 = 54 28*2 = 56 29*2 = 58 0*3 = 0 1*3 = 3 2*3 = 6 3*3 = 9 4*3 = 12 5*3 = 15 6*3 = 18 7*3 = 21 8*3 = 24 9*3 = 27 10*3 = 30 11*3 = 33 12*3 = 36 13*3 = 39 14*3 = 42 15*3 = 45 16*3 = 48 17*3 = 51 18*3 = 54 19*3 = 57 20*3 = 60 21*3 = 63 22*3 = 66 23*3 = 69 24*3 = 72 25*3 = 75 26*3 = 78 27*3 = 81 28*3 = 84 29*3 = 87 0*4 = 0 1*4 = 4 2*4 = 8 3*4 = 12 4*4 = 16 5*4 = 20 6*4 = 24 7*4 = 28 8*4 = 32 9*4 = 36 10*4 = 40 11*4 = 44 12*4 = 48 13*4 = 52 14*4 = 56 15*4 = 60 16*4 = 64 17*4 = 68 18*4 = 72 19*4 = 76 20*4 = 80 21*4 = 84 22*4 = 88 23*4 = 92 24*4 = 96 25*4 = 100 26*4 = 104 27*4 = 108 28*4 = 112 29*4 = 116 0*5 = 0 1*5 = 5 2*5 = 10 3*5 = 15 4*5 = 20 5*5 = 25 6*5 = 30 7*5 = 35 8*5 = 40 9*5 = 45 10*5 = 50 11*5 = 55 12*5 = 60 13*5 = 65 14*5 = 70 15*5 = 75 16*5 = 80 17*5 = 85 18*5 = 90 19*5 = 95 20*5 = 100 21*5 = 105 22*5 = 110 23*5 = 115 24*5 = 120 25*5 = 125 26*5 = 130 27*5 = 135 28*5 = 140 29*5 = 145 0*6 = 0 1*6 = 6 2*6 = 12 3*6 = 18 4*6 = 24 5*6 = 30 6*6 = 36 7*6 = 42 8*6 = 48 9*6 = 54 10*6 = 60 11*6 = 66 12*6 = 72 13*6 = 78 14*6 = 84 15*6 = 90 16*6 = 96 17*6 = 102 18*6 = 108 19*6 = 114 20*6 = 120 21*6 = 126 22*6 = 132 23*6 = 138 24*6 = 144 25*6 = 150 26*6 = 156 27*6 = 162 28*6 = 168 29*6 = 174 0*7 = 0 1*7 = 7 2*7 = 14 3*7 = 21 4*7 = 28 5*7 = 35 6*7 = 42 7*7 = 49 8*7 = 56 9*7 = 63 10*7 = 70 11*7 = 77 12*7 = 84 13*7 = 91 14*7 = 98 15*7 = 105 16*7 = 112 17*7 = 119 18*7 = 126 19*7 = 133 20*7 = 140 21*7 = 147 22*7 = 154 23*7 = 161 24*7 = 168 25*7 = 175 26*7 = 182 27*7 = 189 28*7 = 196 29*7 = 203 0*8 = 0 1*8 = 8 2*8 = 16 3*8 = 24 4*8 = 32 5*8 = 40 6*8 = 48 7*8 = 56 8*8 = 64 9*8 = 72 10*8 = 80 11*8 = 88 12*8 = 96 13*8 = 104 14*8 = 112 15*8 = 120 16*8 = 128 17*8 = 136 18*8 = 144 19*8 = 152 20*8 = 160 21*8 = 168 22*8 = 176 23*8 = 184 24*8 = 192 25*8 = 200 26*8 = 208 27*8 = 216 28*8 = 224 29*8 = 232 0*9 = 0 1*9 = 9 2*9 = 18 3*9 = 27 4*9 = 36 5*9 = 45 6*9 = 54 7*9 = 63 8*9 = 72 9*9 = 81 10*9 = 90 11*9 = 99 12*9 = 108 13*9 = 117 14*9 = 126 15*9 = 135 16*9 = 144 17*9 = 153 18*9 = 162 19*9 = 171 20*9 = 180 21*9 = 189 22*9 = 198 23*9 = 207 24*9 = 216 25*9 = 225 26*9 = 234 27*9 = 243 28*9 = 252 29*9 = 261 0*10 = 0 1*10 = 10 2*10 = 20 3*10 = 30 4*10 = 40 5*10 = 50 6*10 = 60 7*10 = 70 8*10 = 80 9*10 = 90 10*10 = 100 11*10 = 110 12*10 = 120 13*10 = 130 14*10 = 140 15*10 = 150 16*10 = 160 17*10 = 170 18*10 = 180 19*10 = 190 20*10 = 200 21*10 = 210 22*10 = 220 23*10 = 230 24*10 = 240 25*10 = 250 26*10 = 260 27*10 = 270 28*10 = 280 29*10 = 290 0*11 = 0 1*11 = 11 2*11 = 22 3*11 = 33 4*11 = 44 5*11 = 55 6*11 = 66 7*11 = 77 8*11 = 88 9*11 = 99 10*11 = 110 11*11 = 121 12*11 = 132 13*11 = 143 14*11 = 154 15*11 = 165 16*11 = 176 17*11 = 187 18*11 = 198 19*11 = 209 20*11 = 220 21*11 = 231 22*11 = 242 23*11 = 253 24*11 = 264 25*11 = 275 26*11 = 286 27*11 = 297 28*11 = 308 29*11 = 319 0*12 = 0 1*12 = 12 2*12 = 24 3*12 = 36 4*12 = 48 5*12 = 60 6*12 = 72 7*12 = 84 8*12 = 96 9*12 = 108 10*12 = 120 11*12 = 132 12*12 = 144 13*12 = 156 14*12 = 168 15*12 = 180 16*12 = 192 17*12 = 204 18*12 = 216 19*12 = 228 20*12 = 240 21*12 = 252 22*12 = 264 23*12 = 276 24*12 = 288 25*12 = 300 26*12 = 312 27*12 = 324 28*12 = 336 29*12 = 348 0*13 = 0 1*13 = 13 2*13 = 26 3*13 = 39 4*13 = 52 5*13 = 65 6*13 = 78 7*13 = 91 8*13 = 104 9*13 = 117 10*13 = 130 11*13 = 143 12*13 = 156 13*13 = 169 14*13 = 182 15*13 = 195 16*13 = 208 17*13 = 221 18*13 = 234 19*13 = 247 20*13 = 260 21*13 = 273 22*13 = 286 23*13 = 299 24*13 = 312 25*13 = 325 26*13 = 338 27*13 = 351 28*13 = 364 29*13 = 377 0*14 = 0 1*14 = 14 2*14 = 28 3*14 = 42 4*14 = 56 5*14 = 70 6*14 = 84 7*14 = 98 8*14 = 112 9*14 = 126 10*14 = 140 11*14 = 154 12*14 = 168 13*14 = 182 14*14 = 196 15*14 = 210 16*14 = 224 17*14 = 238 18*14 = 252 19*14 = 266 20*14 = 280 21*14 = 294 22*14 = 308 23*14 = 322 24*14 = 336 25*14 = 350 26*14 = 364 27*14 = 378 28*14 = 392 29*14 = 406 0*15 = 0 1*15 = 15 2*15 = 30 3*15 = 45 4*15 = 60 5*15 = 75 6*15 = 90 7*15 = 105 8*15 = 120 9*15 = 135 10*15 = 150 11*15 = 165 12*15 = 180 13*15 = 195 14*15 = 210 15*15 = 225 16*15 = 240 17*15 = 255 18*15 = 270 19*15 = 285 20*15 = 300 21*15 = 315 22*15 = 330 23*15 = 345 24*15 = 360 25*15 = 375 26*15 = 390 27*15 = 405 28*15 = 420 29*15 = 435 0*16 = 0 1*16 = 16 2*16 = 32 3*16 = 48 4*16 = 64 5*16 = 80 6*16 = 96 7*16 = 112 8*16 = 128 9*16 = 144 10*16 = 160 11*16 = 176 12*16 = 192 13*16 = 208 14*16 = 224 15*16 = 240 16*16 = 256 17*16 = 272 18*16 = 288 19*16 = 304 20*16 = 320 21*16 = 336 22*16 = 352 23*16 = 368 24*16 = 384 25*16 = 400 26*16 = 416 27*16 = 432 28*16 = 448 29*16 = 464 0*17 = 0 1*17 = 17 2*17 = 34 3*17 = 51 4*17 = 68 5*17 = 85 6*17 = 102 7*17 = 119 8*17 = 136 9*17 = 153 10*17 = 170 11*17 = 187 12*17 = 204 13*17 = 221 14*17 = 238 15*17 = 255 16*17 = 272 17*17 = 289 18*17 = 306 19*17 = 323 20*17 = 340 21*17 = 357 22*17 = 374 23*17 = 391 24*17 = 408 25*17 = 425 26*17 = 442 27*17 = 459 28*17 = 476 29*17 = 493 0*18 = 0 1*18 = 18 2*18 = 36 3*18 = 54 4*18 = 72 5*18 = 90 6*18 = 108 7*18 = 126 8*18 = 144 9*18 = 162 10*18 = 180 11*18 = 198 12*18 = 216 13*18 = 234 14*18 = 252 15*18 = 270 16*18 = 288 17*18 = 306 18*18 = 324 19*18 = 342 20*18 = 360 21*18 = 378 22*18 = 396 23*18 = 414 24*18 = 432 25*18 = 450 26*18 = 468 27*18 = 486 28*18 = 504 29*18 = 522 0*19 = 0 1*19 = 19 2*19 = 38 3*19 = 57 4*19 = 76 5*19 = 95 6*19 = 114 7*19 = 133 8*19 = 152 9*19 = 171 10*19 = 190 11*19 = 209 12*19 = 228 13*19 = 247 14*19 = 266 15*19 = 285 16*19 = 304 17*19 = 323 18*19 = 342 19*19 = 361 20*19 = 380 21*19 = 399 22*19 = 418 23*19 = 437 24*19 = 456 25*19 = 475 26*19 = 494 27*19 = 513 28*19 = 532 29*19 = 551 0*20 = 0 1*20 = 20 2*20 = 40 3*20 = 60 4*20 = 80 5*20 = 100 6*20 = 120 7*20 = 140 8*20 = 160 9*20 = 180 10*20 = 200 11*20 = 220 12*20 = 240 13*20 = 260 14*20 = 280 15*20 = 300 16*20 = 320 17*20 = 340 18*20 = 360 19*20 = 380 20*20 = 400 21*20 = 420 22*20 = 440 23*20 = 460 24*20 = 480 25*20 = 500 26*20 = 520 27*20 = 540 28*20 = 560 29*20 = 580 0*21 = 0 1*21 = 21 2*21 = 42 3*21 = 63 4*21 = 84 5*21 = 105 6*21 = 126 7*21 = 147 8*21 = 168 9*21 = 189 10*21 = 210 11*21 = 231 12*21 = 252 13*21 = 273 14*21 = 294 15*21 = 315 16*21 = 336 17*21 = 357 18*21 = 378 19*21 = 399 20*21 = 420 21*21 = 441 22*21 = 462 23*21 = 483 24*21 = 504 25*21 = 525 26*21 = 546 27*21 = 567 28*21 = 588 29*21 = 609 0*22 = 0 1*22 = 22 2*22 = 44 3*22 = 66 4*22 = 88 5*22 = 110 6*22 = 132 7*22 = 154 8*22 = 176 9*22 = 198 10*22 = 220 11*22 = 242 12*22 = 264 13*22 = 286 14*22 = 308 15*22 = 330 16*22 = 352 17*22 = 374 18*22 = 396 19*22 = 418 20*22 = 440 21*22 = 462 22*22 = 484 23*22 = 506 24*22 = 528 25*22 = 550 26*22 = 572 27*22 = 594 28*22 = 616 29*22 = 638 0*23 = 0 1*23 = 23 2*23 = 46 3*23 = 69 4*23 = 92 5*23 = 115 6*23 = 138 7*23 = 161 8*23 = 184 9*23 = 207 10*23 = 230 11*23 = 253 12*23 = 276 13*23 = 299 14*23 = 322 15*23 = 345 16*23 = 368 17*23 = 391 18*23 = 414 19*23 = 437 20*23 = 460 21*23 = 483 22*23 = 506 23*23 = 529 24*23 = 552 25*23 = 575 26*23 = 598 27*23 = 621 28*23 = 644 29*23 = 667 0*24 = 0 1*24 = 24 2*24 = 48 3*24 = 72 4*24 = 96 5*24 = 120 6*24 = 144 7*24 = 168 8*24 = 192 9*24 = 216 10*24 = 240 11*24 = 264 12*24 = 288 13*24 = 312 14*24 = 336 15*24 = 360 16*24 = 384 17*24 = 408 18*24 = 432 19*24 = 456 20*24 = 480 21*24 = 504 22*24 = 528 23*24 = 552 24*24 = 576 25*24 = 600 26*24 = 624 27*24 = 648 28*24 = 672 29*24 = 696 0*25 = 0 1*25 = 25 2*25 = 50 3*25 = 75 4*25 = 100 5*25 = 125 6*25 = 150 7*25 = 175 8*25 = 200 9*25 = 225 10*25 = 250 11*25 = 275 12*25 = 300 13*25 = 325 14*25 = 350 15*25 = 375 16*25 = 400 17*25 = 425 18*25 = 450 19*25 = 475 20*25 = 500 21*25 = 525 22*25 = 550 23*25 = 575 24*25 = 600 25*25 = 625 26*25 = 650 27*25 = 675 28*25 = 700 29*25 = 725 0*26 = 0 1*26 = 26 2*26 = 52 3*26 = 78 4*26 = 104 5*26 = 130 6*26 = 156 7*26 = 182 8*26 = 208 9*26 = 234 10*26 = 260 11*26 = 286 12*26 = 312 13*26 = 338 14*26 = 364 15*26 = 390 16*26 = 416 17*26 = 442 18*26 = 468 19*26 = 494 20*26 = 520 21*26 = 546 22*26 = 572 23*26 = 598 24*26 = 624 25*26 = 650 26*26 = 676 27*26 = 702 28*26 = 728 29*26 = 754 0*27 = 0 1*27 = 27 2*27 = 54 3*27 = 81 4*27 = 108 5*27 = 135 6*27 = 162 7*27 = 189 8*27 = 216 9*27 = 243 10*27 = 270 11*27 = 297 12*27 = 324 13*27 = 351 14*27 = 378 15*27 = 405 16*27 = 432 17*27 = 459 18*27 = 486 19*27 = 513 20*27 = 540 21*27 = 567 22*27 = 594 23*27 = 621 24*27 = 648 25*27 = 675 26*27 = 702 27*27 = 729 28*27 = 756 29*27 = 783 0*28 = 0 1*28 = 28 2*28 = 56 3*28 = 84 4*28 = 112 5*28 = 140 6*28 = 168 7*28 = 196 8*28 = 224 9*28 = 252 10*28 = 280 11*28 = 308 12*28 = 336 13*28 = 364 14*28 = 392 15*28 = 420 16*28 = 448 17*28 = 476 18*28 = 504 19*28 = 532 20*28 = 560 21*28 = 588 22*28 = 616 23*28 = 644 24*28 = 672 25*28 = 700 26*28 = 728 27*28 = 756 28*28 = 784 29*28 = 812 0*29 = 0 1*29 = 29 2*29 = 58 3*29 = 87 4*29 = 116 5*29 = 145 6*29 = 174 7*29 = 203 8*29 = 232 9*29 = 261 10*29 = 290 11*29 = 319 12*29 = 348 13*29 = 377 14*29 = 406 15*29 = 435 16*29 = 464 17*29 = 493 18*29 = 522 19*29 = 551 20*29 = 580 21*29 = 609 22*29 = 638 23*29 = 667 24*29 = 696 25*29 = 725 26*29 = 754 27*29 = 783 28*29 = 812 29*29 = 841 kaya-0.4.4/tests/test009/run0000644000175100017510000000025211170340767013656 0ustar cimcim#!/bin/bash ../../compiler/kayac test009.k -L ../../rts -L ../../stdlib -o test009 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test009 rm -f test009 test009.exe kaya-0.4.4/tests/test014/0000755000175100017510000000000011170340767013124 5ustar cimcimkaya-0.4.4/tests/test014/test014.k0000644000175100017510000000042411170340766014503 0ustar cimcimprogram testrefs; //-*-C-*-ish Void inc(var Int x) { x=x+1; } Void set(var [a] xs, Int i, a val) { xs[i]=val; } Void main() { y=6; foo = ["Fish","Chips","Mushy Peas"]; inc(y); set(foo,2,"Vinegar"); putStrLn(String(y)); putStrLn(foo[2]); } kaya-0.4.4/tests/test014/expected0000644000175100017510000000004511170340767014647 0ustar cimcimCompiling program testrefs 7 Vinegar kaya-0.4.4/tests/test014/run0000644000175100017510000000025211170340767013652 0ustar cimcim#!/bin/bash ../../compiler/kayac test014.k -L ../../rts -L ../../stdlib -o test014 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test014 rm -f test014 test014.exe kaya-0.4.4/tests/Makefile0000644000175100017510000000020611170340770013350 0ustar cimcimtest: perl ./runtest.pl all update: perl ./runtest.pl all -u diff: perl ./runtest.pl all -d distclean: rm -f *~ rm -f */outputkaya-0.4.4/tests/libtests/0000755000175100017510000000000011170340766013550 5ustar cimcimkaya-0.4.4/tests/libtests/Makefile0000644000175100017510000000036611170340766015215 0ustar cimcimKAYAC = ../../compiler/kayac KAYAINC = -I../../rts KAYALIB = -L ../../rts -L ../../stdlib test: runtests runtests: .PHONY # always build it ${KAYAC} runtests.k -force ${KAYAINC} ${KAYALIB} ./runtests clean: rm -f *.o *.ki runtests .PHONY: kaya-0.4.4/tests/libtests/preludetest.k0000644000175100017510000000226511170340766016271 0ustar cimcimmodule preludetest; // tests for the prelude and basic language features. import Testing; // Some basic conversion tests public Void coerce { x = randomInt; assert(Int(String(x)) == x, "Int coercion "+x+" -> " +String(x)); x2 = randomFloat; // Some error allowance needed! y2 = Float(String(x2)); assert((y2-x2)<0.0000001 || (x2-y2)<0.0000001, "Float coercion "+x2+" -> " +String(x2)); x3 = randomString(); y3 = string(array(x3)); assert(x3 == y3, "String/array coercion "+x3); } // Properties of prelude functions public Void rev { xs = randomIntArray(); ys = copy(xs); reverse(ys); if (size(xs)>0) { assert(xs[0] == ys[size(ys)-1]); } reverse(ys); assert(xs == ys); } public Void testRep { foo = randomString(); assert(length(rep(foo,5))==length(foo)*5); } public Void testSort { xs = [1..(1000+rand()%2000)]; ys = copy(xs); shuffle(xs); sort(xs); assert(xs == ys); } public Void testRange { assert([1..10] == [1,2,3,4,5,6,7,8,9,10]); assert([1,3..10] == [1,3,5,7,9]); assert([1,3..11] == [1,3,5,7,9,11]); assert([10,9..1] == [10,9,8,7,6,5,4,3,2,1]); assert([10..1] == []); } kaya-0.4.4/tests/libtests/closuretest.k0000644000175100017510000000142111170340766016276 0ustar cimcimmodule closuretest; // tests for closures and functional programming features import Testing; globals { Int glob1; // for testing (a) globals, and (b) side-effecting closures. } public Void closure1 { sc = 2; // Check scoping xs = map(lambda(x) -> { x*sc }, [1..5]); assert(xs == [2,4,6,8,10]); } Void rep(Void() fn, Int times) { for x in [1..times] { fn(); } } public Void closure2 { glob1 = 0; rep(lambda() { glob1 += 2; }, 100); assert(glob1 == 200); } Int runMarshalled(String function) { Int(Int,Int) realfn = unmarshal(function,888); return realfn(5,32); } public Void marshalClosure { z = 5; plus = lambda(Int x,Int y) -> { x+y+z }; plusm = marshal(plus,888); assert(runMarshalled(plusm) == 42); } kaya-0.4.4/tests/libtests/runtests.k0000644000175100017510000000135311170340766015615 0ustar cimcimprogram runtests; // Unit testing framework for kaya standard libraries. Since the compilar // and run-time system have to work for these to even run, we don't have // tests for the particularly basic features. // Separate tests are required to cover compiler errors. import Testing; import System; import preludetest; import closuretest; Void main() { Testing::init(); // Prelude tests add(@coerce, 100, "coercions"); add(@rev, 100, "reverse"); add(@testRep, 100, "rep"); add(@testSort, 100, "sort"); add(@testRange, 1, "range"); // Closures add(@closure1, 1, "closure1"); add(@closure2, 1, "closure2"); add(@marshalClosure, 1, "marshal closures"); if (!Testing::run()) { exit(1); } } kaya-0.4.4/tests/test008/0000755000175100017510000000000011170340767013127 5ustar cimcimkaya-0.4.4/tests/test008/test008.k0000644000175100017510000000154611170340766014517 0ustar cimcimprogram pair; // -*-C-*-ish data AnotherPair = Pair2(a snd, b fst); Void printPair((Int,Int) x) { putStr("("+String(x.fst)+","+String(x.snd)+")\n"); newpair = Pair2(x.fst,x.snd); putStr( "("+String(newpair.fst)+","+String(newpair.snd)+")\n"); } // Too easy - let's scare it a bit with an array of pairs. [(Int,[String])] mkPairs(Int x) { for(i=0;i = Bar; type Bar = List; type Quux = Baz; type Baz = Bat; type Bat = List; data Wibble = flob(Int x, Int y, Int y); public Void foo(Foo xs) { putStrLn(String(xs.head)); } public Void main() { Foo l = cons(5,nil); List m = l; foo(l); } kaya-0.4.4/tests/test032/0000755000175100017510000000000011170340767013124 5ustar cimcimkaya-0.4.4/tests/test032/test032.k0000644000175100017510000000102511170340767014502 0ustar cimcimprogram test032; Void foo(Int x, String y) { p = \(z) { putStrLn(y); return x+z; }; putStrLn(String(p(10))); } Void main() { xs = map(\(x) -> x*2, [1..5]); Int x = 0; for x in xs { putStr(x+","); } putStrLn("END"); foo(xs[0],String(xs[1])); list = zip([1..10], [2..20]); for pair in list { putStr("("+pair.fst+","+pair.snd+") "); } putStrLn("END"); list2 = zipWith(\(a,b) -> a+b, [1..10], [2..20]); for num in list2 { putStr(num+", "); } putStrLn("END"); } kaya-0.4.4/tests/test032/expected0000644000175100017510000000023111170340767014644 0ustar cimcimCompiling program test032 2,4,6,8,10,END 4 12 (1,2) (2,3) (3,4) (4,5) (5,6) (6,7) (7,8) (8,9) (9,10) (10,11) END 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, END kaya-0.4.4/tests/test032/run0000644000175100017510000000023011170340767013646 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test032.k -L ../../rts -L ../../stdlib ./test032 rm -f test032 test032.exe kaya-0.4.4/tests/test046/0000755000175100017510000000000011170340767013131 5ustar cimcimkaya-0.4.4/tests/test046/expected0000644000175100017510000000272511170340767014663 0ustar cimcimCompiling program test046 test The College of St Hild & St Bede The College of St Hild & St Bede <br>The College of St Hild &amp; St Bede &<br> test The College of St Hild & St Bede
The College of St Hild & St Bede <br>The College of St Hild &amp; St Bede &<br> test

The College of St Hild & St Bede

The College of St Hild & St Bede <br>

The College of St Hild &amp; St Bede &<br>

test

The College of St Hild & St Bede

The College of St Hild & St Bede <br>

The College of St Hild &amp; St Bede &<br>

kaya-0.4.4/tests/test046/run0000644000175100017510000000023011170340767013653 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test046.k -L ../../rts -L ../../stdlib ./test046 rm -f test046 test046.exe kaya-0.4.4/tests/test046/test046.k0000644000175100017510000000113411170340767014515 0ustar cimcimprogram test046; import HTMLDocument; Void main() { for safety in [UltraSafe,InlineOnly(Safe),AllElements(Unsafe),Unchecked] { doc = new(HTML4Strict,"test"); html[0] = "

The College of St Hild & St Bede "+"
"+"

"; html[1] = "

The College of St Hild & St Bede <br>

"; html[2] = "

The College of St Hild &amp; St Bede &<br>

"; for htm in html { readFromString(doc.body,htm,safety,HTML4Strict); } putStrLn(string(doc,LiteralUTF8)); } } kaya-0.4.4/tests/test061/0000755000175100017510000000000011170340770013120 5ustar cimcimkaya-0.4.4/tests/test061/test061.k0000644000175100017510000000063611170340770014507 0ustar cimcimprogram test061; Exception Error; Void incVar(var Int x, Int inc) { x+=inc; //return; if (inc==2) { throw(Error); } x+=inc; } Void app(Void(a) fn, a arg) { fn(arg); } Void main() { foo = 5; bar = 6; // app(incVar@(foo),3); try { bar = 7; app(incVar@(foo), 2); } catch(e) { putStrLn("Threw"); } putStrLn(foo+", "+bar+" IS THE WRONG ANSWER! FIXME!!!"); } kaya-0.4.4/tests/test061/expected0000644000175100017510000000010311170340770014636 0ustar cimcimCompiling program test061 Threw 5, 7 IS THE WRONG ANSWER! FIXME!!! kaya-0.4.4/tests/test061/run0000644000175100017510000000021411170340770013644 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test061.k -L ../../rts -L ../../stdlib ./test061 rm -f test061 kaya-0.4.4/tests/test021/0000755000175100017510000000000011170340767013122 5ustar cimcimkaya-0.4.4/tests/test021/expected0000644000175100017510000000007711170340767014652 0ustar cimcimCompiling program coerce 5 Sausages 12.5 Foo Sausages 2.55 7.5 kaya-0.4.4/tests/test021/run0000644000175100017510000000025211170340767013650 0ustar cimcim#!/bin/bash ../../compiler/kayac test021.k -L ../../rts -L ../../stdlib -o test021 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test021 rm -f test021 test021.exe kaya-0.4.4/tests/test021/test021.k0000644000175100017510000000032011170340764014470 0ustar cimcimprogram coerce; Void main() { x = 5; putStrLn(x + " Sausages"); y = 2.5; putStrLn(y*x + " Foo"); foo = "Sausage"+'s'; putStrLn(foo); putStrLn(""+y+x); putStrLn(y+x+""); } kaya-0.4.4/tests/test020/0000755000175100017510000000000011170340767013121 5ustar cimcimkaya-0.4.4/tests/test020/test020.k0000644000175100017510000000054611170340765014501 0ustar cimcimprogram test020; import Binary; Void main() { b = createBlock(5000); for x in range(0,4999) { poke(b,x,x*2); } setBlockData(b,3150,[0,0,0,0,0,0,0,0,257]); pokeString(b,1000,"Hello world!"); xs = getBlockChunk(b,3100,200); for x in xs { putStr(String(x)+":"); } putStrLn("End"); putStrLn(peekString(b,1003)); } kaya-0.4.4/tests/test020/expected0000644000175100017510000000135111170340767014645 0ustar cimcimCompiling program test020 56:58:60:62:64:66:68:70:72:74:76:78:80:82:84:86:88:90:92:94:96:98:100:102:104:106:108:110:112:114:116:118:120:122:124:126:128:130:132:134:136:138:140:142:144:146:148:150:152:154:0:0:0:0:0:0:0:0:1:174:176:178:180:182:184:186:188:190:192:194:196:198:200:202:204:206:208:210:212:214:216:218:220:222:224:226:228:230:232:234:236:238:240:242:244:246:248:250:252:254:0:2:4:6:8:10:12:14:16:18:20:22:24:26:28:30:32:34:36:38:40:42:44:46:48:50:52:54:56:58:60:62:64:66:68:70:72:74:76:78:80:82:84:86:88:90:92:94:96:98:100:102:104:106:108:110:112:114:116:118:120:122:124:126:128:130:132:134:136:138:140:142:144:146:148:150:152:154:156:158:160:162:164:166:168:170:172:174:176:178:180:182:184:186:188:190:192:194:196:198:End lo world! kaya-0.4.4/tests/test020/run0000644000175100017510000000025211170340767013647 0ustar cimcim#!/bin/bash ../../compiler/kayac test020.k -L ../../rts -L ../../stdlib -o test020 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test020 rm -f test020 test020.exe kaya-0.4.4/tests/test045/0000755000175100017510000000000011170340770013122 5ustar cimcimkaya-0.4.4/tests/test045/test045.k0000644000175100017510000000635311170340770014515 0ustar cimcimprogram test045; // -*-C-*-ish /* [Unfinished] evaluator for the untyped lambda calculus with integers, lazy version. */ // Raw values data Expr = Var(Int x) // de Bruijn indexed variable | Lam(Expr scope) // Binding | App(Expr f, Expr s) // Function application | Const(Int val) | Inc(Expr ni) | Dec(Expr nd) | PrimRec(Expr target,Expr mzero,Expr msuc) | If(Expr i, Expr t, Expr e); // Semantic representation of values. Difference from eager version is // that each recursive value is a suspension - Sem() rather than Sem. // We only evaluate these when we need them data Sem = SemLam(Sem(Sem()) scope) | SemConst(Int val) | SemPrimRec(Sem() target, Sem() mzero, Sem() msuc) | SemInc(Sem() ni) | SemDec(Sem() nd) | Blocked(Blocked f, [Sem()] args); // Irreducible terms data Blocked = BVar(Int x); data Spine
= Lin | Snoc(Spine init, a last); type Ctxt = Spine; Exception NoSuchVariable(); Sem lookup(Int v, Ctxt ctxt) { if (v==0) { return force(ctxt.last); // Evaluate it } else if (v>0) { return lookup(v-1,ctxt.init); } else { throw(NoSuchVariable); } } Sem eval(Ctxt ctxt, Expr e) { case e of { Var(v) -> return lookup(v,ctxt); | Lam(sc) -> return SemLam(\(arg) -> eval(Snoc(ctxt,@arg),sc)); | App(f,a) -> return app(ctxt,eval@(ctxt,f),eval@(ctxt,a)); | Const(c) -> return SemConst(c); | Inc(n) -> return increment(eval(ctxt,n)); | Dec(n) -> return decrement(eval(ctxt,n)); | PrimRec(t,z,s) -> return primrec(ctxt, eval@(ctxt,t),eval@(ctxt,z),eval@(ctxt,s)); | If(i,t,e) -> return runIf(ctxt, eval@(ctxt,i),eval@(ctxt,t),eval@(ctxt,e)); } } Sem app(Ctxt ctxt, Sem() f, Sem() a) { case f of { // Evaluate f SemLam(scfun) -> return scfun(@a); } } Sem increment(Sem n) { case n of { SemConst(c) -> return (SemConst(c+1)); } } Sem decrement(Sem n) { case n of { SemConst(c) -> return (SemConst(c-1)); } } Sem primrec(Ctxt ctxt, Sem() t, Sem() z, Sem() s) { case t of { // Evaluate t SemConst(x) -> if (x==0) { return z; // Evaluate z } else { dec = SemConst@(x-1); rec = primrec@(ctxt,dec,@z,@s); return app(ctxt,app@(ctxt,@s,@dec),@rec); } } } Sem runIf(Ctxt ctxt, Sem() i, Sem() t, Sem() e) { case i of { // Evaluate i, then t or e, but not both. SemConst(x) -> if (x!=0) { return t; } else { return e; } } } Void showSem(Sem v) { case v of { SemConst(x) -> putStrLn(String(x)); } } Void main() { // plus = \m n. primrec n m (\k ih. inc(ih)) plus = Lam(Lam(PrimRec(Var(0),Var(1), Lam(Lam(Inc(Var(0))))))); // mult = \m n. primrec n 0 (\k ih. plus m ih) mult = Lam(Lam(PrimRec(Var(0),Const(0), Lam(Lam(App(App(plus,Var(3)),Var(0))))))); // Wow, this works when we evaluate lazily! // y = \f . (\x. f (x x)) (\x. f (x x)) y = Lam(App(Lam(App(Var(1),App(Var(0),Var(0)))), Lam(App(Var(1),App(Var(0),Var(0)))))); // add4 = \x. y (\add4 x. if x==0 then 4 else 1+(add4 (x-1))) x addbody = Lam(Lam(If(Var(0),Inc(App(Var(1),(Dec(Var(0))))),Const(4)))); add4 = Lam(App(App(y,addbody),Var(0))); showSem(eval(Lin,App(App(mult, Const(6)),Const(7)))); // Wow, it works! showSem(eval(Lin,App(add4,Const(3)))); } kaya-0.4.4/tests/test045/expected0000644000175100017510000000003711170340767014654 0ustar cimcimCompiling program test045 42 7 kaya-0.4.4/tests/test045/run0000644000175100017510000000023011170340767013652 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test045.k -L ../../rts -L ../../stdlib ./test045 rm -f test045 test045.exe kaya-0.4.4/tests/test056/0000755000175100017510000000000011170340770013124 5ustar cimcimkaya-0.4.4/tests/test056/expected0000644000175100017510000000131011170340770014643 0ustar cimcimCompiling program test056 a:2000 b:0 a:4000 b:0 a:6000 b:0 a:8000 b:0 a:10000 b:0 a:12000 b:0 a:14000 b:0 a:16000 b:0 a:18000 b:0 a:20000 b:0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 !!--- 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 !!--- 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 !!--- 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 !!--- 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 !!--- 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 !!--- 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 !!--- 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 !!--- 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 !!--- 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 !!--- kaya-0.4.4/tests/test056/run0000644000175100017510000000023011170340770013646 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test056.k -L ../../rts -L ../../stdlib ./test056 rm -f test056 test056.exe kaya-0.4.4/tests/test056/test056.k0000644000175100017510000000174111170340770014515 0ustar cimcimprogram test056; Void main() { a = []; b = []; for j in [1..10] { for i in [1..10000] { push(a,i); } for i in [1..10000] { tmp = shift(a); unshift(tmp,b); } for i in [0..9999] { // putStrLn(b[i]+"."); tmp = b[i]; } for i in [1..10000] { // putStrLn(i+";"+size(b)); tmp = top(b); push(a,tmp); } for i in [1..10000] { // bi = b[i]; pop(b); pop(a); } for i in [1..1000] { push(a,i); unshift(i,a); } putStrLn("a:"+size(a)); putStrLn("b:"+size(b)); } c = createArray(8); for j in [1..10] { for i in [1..10000] { push(c,i); } for k in [1..10] { for i in [1..10000] { tmp = top(c); unshift(tmp,c); pop(c); } } for k in [1..20] { for i in [1..10000] { push(c,shift(c)); } } for i in [1..10000] { t = shift(c); if (i%1000==0) { putStr(t+"\n"); } } putStrLn("!!---"); } } kaya-0.4.4/tests/test059/0000755000175100017510000000000011170340770013127 5ustar cimcimkaya-0.4.4/tests/test059/test059.k0000644000175100017510000000072311170340770014522 0ustar cimcimprogram test059; String getA() { putStrLn("..."); return "A"; } String getB() { putStrLn("..."); return "B"; } Int getC() { putStrLn("..."); return 1; } Int getD() { putStrLn("..."); return 2; } Void main() { if (getA() == getB()) { putStrLn("oops"); } if (toLower(getA()) == toLower(getB())) { putStrLn("oops"); } if (getC() == getD()) { putStrLn("oops"); } if (abs(getC()) == abs(getD())) { putStrLn("oops"); } } kaya-0.4.4/tests/test059/expected0000644000175100017510000000007211170340770014652 0ustar cimcimCompiling program test059 ... ... ... ... ... ... ... ... kaya-0.4.4/tests/test059/run0000644000175100017510000000023011170340770013651 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test059.k -L ../../rts -L ../../stdlib ./test059 rm -f test059 test059.exe kaya-0.4.4/tests/test037/0000755000175100017510000000000011170340770013123 5ustar cimcimkaya-0.4.4/tests/test037/test037.k0000644000175100017510000000121311170340770014505 0ustar cimcimprogram test037; // tests Dict module import Dict; data TData(Int one, Char two); Void main() { test = Dict::new(1511,hashit); for i in [1..1000] { add(test,TData(i,Char(i)),i); } for i in [1,50,725,1123,2120] { maybetd = lookup(test,TData(i,Char(i))); case maybetd of { nothing() -> putStrLn("Not found "+i); | just(x) -> putStrLn("Found "+i+" is "+x); } } delete(test,TData(16,Char(16))); maybetd = lookup(test,TData(16,Char(16))); case maybetd of { nothing() -> putStrLn("Deleted 16"); | just(x) -> putStrLn("Failed to delete 16"); } } Int hashit (TData tohash) { return tohash.one + Int(tohash.two); } kaya-0.4.4/tests/test037/expected0000644000175100017510000000016011170340767014652 0ustar cimcimCompiling program test037 Found 1 is 1 Found 50 is 50 Found 725 is 725 Not found 1123 Not found 2120 Deleted 16 kaya-0.4.4/tests/test037/run0000644000175100017510000000023011170340767013653 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test037.k -L ../../rts -L ../../stdlib ./test037 rm -f test037 test037.exe kaya-0.4.4/tests/test019/0000755000175100017510000000000011170340770013123 5ustar cimcimkaya-0.4.4/tests/test019/test019.k0000644000175100017510000001171611170340770014516 0ustar cimcimprogram test019; import HTMLDocument; Void main() { // create a new HTML document doc = new(HTML4Strict,"Hello World!"); // add some document meta data addDocumentMetaData(doc,"generator","KayHTML"); addDocumentLink(doc,Rev("author"),"mailto:author@example.invalid"); addDocumentStylesheet(doc,[MTscreen,MTprojection],"http://www.example.com/styles.css"); // add a heading to the document heading = addHeading(doc.body,1,"Hello World!"); // set a CSS style on the heading setClass(heading,"first"); // add a paragraph to the text paragraph = addParagraph(doc.body,"This is a simple HTML document. It can also include special characters such as α, α, α or "+Char(945)+"."); //paragraph = addParagraph(doc.body,"This is a simple HTML document α α α."); // apply some emphasis to parts of the paragraph and make some of it // a hyperlink. em = addInlineElementAt(paragraph,Emphasis,10,15); link = addInlineElementAt(paragraph,Hyperlink("http://www.w3.org/TR/html4/"),8,30); // add an ordered list listitems = ["First list item", "Second list item", "Third list item", "Fourth list item", "Fifth list item"]; olist = addList(doc.body,Ordered,5,listitems); // get the fourth
  • fourthitem = getListItem(olist,3); // zero-indexed // and emphasise some of the text. strong = addInlineElementAt(fourthitem,StrongEmphasis,0,5); // we can nest lists, too ulist = addList(fourthitem,Unordered,2,["4a","4b"]); // can add items into lists later at arbitrary position pusheditem = addListItem(olist,3,"3.5th list item"); // images can be added too image = addImage(pusheditem,ImageData("http://www.example.com/image.png","(NEW!)",Specified(15,10))); linebreak = addLineBreak(pusheditem); // this is an alternative way to construct inline sections note = appendInlineElement(pusheditem,SmallerText,"This item's text should be renumbered"); // add a table (the complicated way) table = addTable(doc.body,"Table 1: Fish population 1989-1990"); // create a head section for it thead = getTableHeader(table); headerrow = addTableRow(thead); // add a body section and add two rows to that. tbody = addTableBodySection(table); row1 = addTableRow(tbody); row2 = addTableRow(tbody); // add two columns (we need at least one row in the table to do this // without bugs at the moment, though we should implement // to fix that up) addTableColumns(table,2); // make the header cells table headers and add some header text addString(makeHeaderCell(thead,0,0),"Year"); addString(makeHeaderCell(thead,0,1),"Population"); // now add some data cell contents (all cells start off as data cells) addString(getTableCell(tbody,0,0),"1989"); addString(getTableCell(tbody,0,1),"312"); addString(getTableCell(tbody,1,0),"1990"); addString(getTableCell(tbody,1,1),"304"); // add a table (the easy way) itd = InitialTableData([["Year","Average River Depth (m)"]],[[]],[[["1989","2.7"],["1990","2.6"]]]); table2 = initialiseTable(doc.body,itd,"Table 2: River Depth 1989-1990"); // add a form form = addLocalForm(doc.body); // make test platform-independent setAttribute(form,"action","test019.cgi"); // define a fieldset fs1 = addFieldset(form,"Personal information"); // add some basic fields in1 = addLabelledInput(fs1,"Your name:",InputText,"name","",30); in2 = addLabelledInput(fs1,"Your email:",InputText,"email","",30); in3 = addLabelledInput(fs1,"Your password:",InputPassword,"pwd","",30); // create another fieldset to hold some checkbox options mlists = [SelectOption("kaya-devel@compsoc.dur.ac.uk","kd",false), SelectOption("html-help@example.org.invalid","hh",true), SelectOption("bugs@example.net.invalid","bugs",true)]; fs2 = addOptionList(form,"Mailing lists to subscribe to","mlists",mlists,true); // add a text area to the fieldset tabox = addLabelledTextarea(fs2,"othermls","Are there any other mailing lists you think we should include?"); // another fieldset fs3 = addFieldset(form,"Terms and conditions"); // a select box with optgroups options = [("",[SelectOption("I have already agreed to the T&Cs","done",false)]), ("Selective agreement to T&Cs", [SelectOption("Minimum only","min",false), SelectOption("Minimum and voluntary code of conduct","vcc",false), SelectOption("Minimum and public contact details","pcd",false)]), ("",[SelectOption("I agree to all T&Cs","all",true)])]; selector = addSelectElement(fs3,"tac",0,options); // add the submit button in4 = addRemoteControlInput(fs3,InputSubmit,"","Register"); // make a document footer separator = addHorizontalRule(doc.body); address = addAddress(doc.body,"Email author@example.invalid to contact the author"); // convert the document to a string and print it // use numeric references for high characters. putStrLn(HTMLDocument::string(doc)); // putStrLn(HTMLDocument::toString(doc,NumericReference)); } kaya-0.4.4/tests/test019/expected0000644000175100017510000000704011170340770014650 0ustar cimcimCompiling program test019 Hello World!

    Hello World!

    This is a simple HTML document. It can also include special characters such as α, α, α or α.

    1. First list item
    2. Second list item
    3. Third list item
    4. 3.5th list item(NEW!)
      This item's text should be renumbered
    5. Fourth list item
      • 4a
      • 4b
    6. Fifth list item
    Table 1: Fish population 1989-1990
    Year Population
    1989 312
    1990 304
    Table 2: River Depth 1989-1990
    Year Average River Depth (m)
    1989 2.7
    1990 2.6
    Personal information
    Mailing lists to subscribe to

    Terms and conditions

    Email author@example.invalid to contact the author
    kaya-0.4.4/tests/test019/run0000644000175100017510000000025211170340770013651 0ustar cimcim#!/bin/bash ../../compiler/kayac test019.k -L ../../rts -L ../../stdlib -o test019 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test019 rm -f test019 test019.exe kaya-0.4.4/tests/test060/0000755000175100017510000000000011170340770013117 5ustar cimcimkaya-0.4.4/tests/test060/test060c.k0000644000175100017510000000063411170340770014646 0ustar cimcimprogram test060c; Int findThing(List xs, a x) { for v@i in xs { if (v==x) { return i; } for y in [1..50] { if (y==5) { break; } putStr("Trace "+y+" "); } if (i>20) { break; } } return -1; } Void main() { xs = nil; for x in [10000,9999..1] { xs = cons(x,xs); } putStrLn("p1: " + findThing(xs, 40)); putStrLn("p2: " + findThing(xs, 10)); } kaya-0.4.4/tests/test060/test060b.k0000644000175100017510000000017311170340770014643 0ustar cimcimmodule test060b; Int findThing(List xs, a x) { for v@i in xs { if (v==x) { return; } } return -1; } kaya-0.4.4/tests/test060/expected0000644000175100017510000000254111170340770014645 0ustar cimcimCompiling program test060 0: 3 1: 4 2: 5 3: 7 4: 8 5: 9 6: 10 7 things 0: 3 1: 4 2: 5 3: 1 Counted to 4 0: 3 1: 4 2: 5 3: 7 4: 8 5: 9 6: 10 7 things 0: 5 1: 10 2: 5 3: 7 4: 4 5: 9 6: 3 7: 8 8: 7 9: 10 10 things 0: 3 1: 5 2: 7 3: 9 4: 11 5: 13 6 things position 3 Compiling module test060b test060b.k:6:must return a value from non-void function Compiling program test060c Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 p1: -1 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 Trace 1 Trace 2 Trace 3 Trace 4 p2: 9 kaya-0.4.4/tests/test060/run0000644000175100017510000000043211170340770013645 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test060.k -L ../../rts -L ../../stdlib ./test060 ../../compiler/kayac test060b.k -L ../../rts -L ../../stdlib ../../compiler/kayac test060c.k -L ../../rts -L ../../stdlib ./test060c rm -f test060 test060c kaya-0.4.4/tests/test060/test060.k0000644000175100017510000000245111170340770014502 0ustar cimcimprogram test060; import Queue; import Lazy; import Set; Void main() { xs = newSet(); xsin = [5,10,5,7,4,9,3,8,7,10]; for v in xsin { add(xs, v); } foo = 0; for v@i in xs { putStrLn(i+": "+v); foo++; } putStrLn(foo+" things"); wibble = cons(3,cons(4,cons(5,cons(1,cons(6,Prelude::nil))))); foo = 0; for v@i in wibble { if (v==6) { break; } putStrLn(i+": "+v); foo++; } putStrLn("Counted to "+foo); ys = newHashSet(); ysin = [5,10,5,7,4,9,3,8,7,10]; for v in ysin { add(ys, v); } foo = 0; for v@i in ys { putStrLn(i+": "+v); foo++; } putStrLn(foo+" things"); zs = Queue::empty; zsin = [5,10,5,7,4,9,3,8,7,10]; for v in zsin { enqueue(zs,v); } foo = 0; for v@i in zs { putStrLn(i+": "+v); foo++; } putStrLn(foo+" things"); ws = countTo(3,2,16); foo = 0; for v@i in ws { putStrLn(i+": "+v); foo++; } putStrLn(foo+" things"); putStrLn("position " + findThing(ws, 9)); } Int findThing(Lazy::List xs, a x) { for v@i in xs { if (v==x) { return i; } } return -1; } Lazy::List countTo(Int x, Int step = 1, Int end) { if (x+step > end) { return Lazy::nil; } return Lazy::cons(x,countTo@(x+step,step,end)); } kaya-0.4.4/tests/test017/0000755000175100017510000000000011170340767013127 5ustar cimcimkaya-0.4.4/tests/test017/expected0000644000175100017510000000030111170340767014645 0ustar cimcimCompiling program pluralise 0 wheelbarrows 1 wheelbarrow 2 wheelbarrows 3 wheelbarrows 4 wheelbarrows 5 wheelbarrows 6 wheelbarrows 7 wheelbarrows 8 wheelbarrows 9 wheelbarrows 10 wheelbarrows kaya-0.4.4/tests/test017/run0000644000175100017510000000025211170340767013655 0ustar cimcim#!/bin/bash ../../compiler/kayac test017.k -L ../../rts -L ../../stdlib -o test017 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test017 rm -f test017 test017.exe kaya-0.4.4/tests/test017/test017.k0000644000175100017510000000031011170340764014501 0ustar cimcimprogram pluralise; // -*-C-*- String pluralise(String x, Int num) = x + (if (num!=1) "s" else ""); Void main() { for x in range(0,10) { putStrLn(String(x)+pluralise(" wheelbarrow",x)); } } kaya-0.4.4/tests/test038/0000755000175100017510000000000011170340770013124 5ustar cimcimkaya-0.4.4/tests/test038/test038.k0000644000175100017510000000130111170340770014505 0ustar cimcimprogram test038; import IO; import Strings; Void doCases(String name, Int num) { case num of { _ -> putStrLn("Foo "+num); // this one should always run | 0 -> putStrLn("None"); | 2 -> putStrLn("Two"); } case name of { "foo" -> putStrLn("Yay"); | "bar" -> putStrLn("Yayish"); | _ -> putStrLn("Boo"); } } Void arrCaseTest([Int] x) { case x of { [] -> putStrLn("No entry"); | [a,b,c,d] -> putStrLn("Four entries, third is " + c); | [a,b,c,d,e] -> putStrLn("Five entries, third is " + c); | _ -> putStrLn("..." + size(x)); } } Void main() { doCases("foo",2); doCases("bar",1); doCases("quux",0); for y in [1..10] { x = [2..y]; arrCaseTest(x); } } kaya-0.4.4/tests/test038/expected0000644000175100017510000000023111170340770014644 0ustar cimcimCompiling program test038 Foo 2 Yay Foo 1 Yayish Foo 0 Boo No entry ...1 ...2 ...3 Four entries, third is 4 Five entries, third is 4 ...6 ...7 ...8 ...9 kaya-0.4.4/tests/test038/run0000644000175100017510000000023011170340767013654 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test038.k -L ../../rts -L ../../stdlib ./test038 rm -f test038 test038.exe kaya-0.4.4/tests/test053/0000755000175100017510000000000011170340770013121 5ustar cimcimkaya-0.4.4/tests/test053/test053.k0000644000175100017510000000053211170340767014512 0ustar cimcimprogram test053; Void test(Int p) { sz = 7; if (p-sz < 0) { p = sz; putStr("."); } else if (p+sz >= 20) { putStr(".."); p = 20-(sz+1); } putStr(p+"\n"); } Void test2(Int p) { sz = 7; x = 1; case (p-sz) of { 0 -> x = 2; | 1 -> putStrLn(x+""); } } Void main() { test(16); test2(8); } kaya-0.4.4/tests/test053/expected0000644000175100017510000000004111170340767014646 0ustar cimcimCompiling program test053 ..12 1 kaya-0.4.4/tests/test053/run0000644000175100017510000000023011170340770013643 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test053.k -L ../../rts -L ../../stdlib ./test053 rm -f test053 test053.exe kaya-0.4.4/tests/test058/0000755000175100017510000000000011170340770013126 5ustar cimcimkaya-0.4.4/tests/test058/test058.k0000644000175100017510000000052311170340770014516 0ustar cimcimprogram test058; Int getInt() { return 1; } Int process(Int() fn) { return fn(); } Void main() { fn = @getInt; a = process(@fn); putStr("a="+a+"\n"); for i in [1..10] { putStrLn("i="+i); } for j@i in [1..10] { k = i+j; putStrLn("k="+k); } for j@bar in [10,9..2] { putStrLn(bar+": "+j); } } kaya-0.4.4/tests/test058/expected0000644000175100017510000000024211170340770014650 0ustar cimcimCompiling program test058 a=1 i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 k=1 k=3 k=5 k=7 k=9 k=11 k=13 k=15 k=17 k=19 0: 10 1: 9 2: 8 3: 7 4: 6 5: 5 6: 4 7: 3 8: 2 kaya-0.4.4/tests/test058/run0000644000175100017510000000023011170340770013650 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test058.k -L ../../rts -L ../../stdlib ./test058 rm -f test058 test058.exe kaya-0.4.4/tests/README0000644000175100017510000000641411170340770012577 0ustar cimcimTests ----- The test choice is quite ad-hoc - they are intended to cover all language features but some are more complex than others. Any programs which expose language bugs should be added to the test suite (preferably in some simplified form). 001: import public 002: Foreach loops, some higher order functions 003: Copying circular structures 004: Array initialisation 005: Mutually recursive data structures 006: URL encoding and decoding 007: Type inference error and regression 008: Structure field access 009: Multidimensional arrays 010: Global variables 011: Builtin functions 012: Arithmetic precedences 013: Tail recursion 014: Pass by reference 015: Dictionaries 016: Guarded definitions 017: Typed if expressions 018: Default function arguments 019: HTML Documents 020: Binary chunks 021: Implicit coercions 022: Sort, pass by reference, copying arrays. 023: Type synonyms. 024: More type synonyms, with complex/circular definitions. 025: Data type errors (add more!) 026: Boolean operators, shortcut evaluation 027: Syntactic sugar for array ranges 028: do...while loops 029: Uninitialised array elements 030: Simple logging 031: Partial application 032: Lambda lifting 033: Parser library 034: Lambda scoping and typechecking 035: Marshalling closures 036: Data structures, arrays, built-in equality 037: More dictionary functions, with user defined hash 038: Case analysis on constants and arrays 039: Check for substitutions behaviour 040: Test basic crypto library 041: Function name overloading (abs/join) 042: Overloaded functions as arguments to HOFs 043: Queue module 044: Var arguments and heap allocation 045: Partial application and laziness 046: HTML escaping and unescaping 047: Reflection and reification, with cycles in structures and pickling 048: Sets and Hash Sets (using Testing module for random test generation) 049: Reading and writing large files 050: Equality testing on circular structures. 051: New style exceptions 052: Circular modules via 'extern' function declarations 053: Constant propagation through if/case 054: List comprehensions 055: Function arguments requiring multiple temporary stack variables 056: Array operations, with lots of shuffling and reallocating 057: Program transformations (inlining, constant propagation) 058: Regressions in for loop optimisation and declaration adding 059: Regressions in infix tests 060: Generic traversals 061: Check variables modified inside 'try' do not get reset after 'throw' 062: Partial applications passing arguments correctly How regression testing works ---------------------------- Each testnnn subdirectory includes at least two files: * run, which is a script to run the test * expected, which is the expected output of the test. The script runtest.pl takes the name of the test to run (or "all") to run all of them, and runs the "run" script in the test directory. If the output matches the expected output, the test succeeds, otherwise it fails. runtest.pl has optional arguments: * -s shows the actual output of a test script. * -d shows the differences between the expected and actual output of a test. * -u updates the expected output to the current output. Check carefully before running this. If any tests fail in a release, it should be considered a bug. Do not make a release before ensuring that all tests succeed. kaya-0.4.4/tests/test062/0000755000175100017510000000000011170340770013121 5ustar cimcimkaya-0.4.4/tests/test062/test062.k0000644000175100017510000000030711170340770014504 0ustar cimcimprogram test062; Void main() { ts = []; for k in [0..2] { push(ts,test@(k)); } for t in ts { t(); } } Void test(Int k) { putStr(k+"\n"); } kaya-0.4.4/tests/test062/expected0000644000175100017510000000004011170340770014637 0ustar cimcimCompiling program test062 0 1 2 kaya-0.4.4/tests/test062/run0000644000175100017510000000021411170340770013645 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test062.k -L ../../rts -L ../../stdlib ./test062 rm -f test062 kaya-0.4.4/tests/test010/0000755000175100017510000000000011170340767013120 5ustar cimcimkaya-0.4.4/tests/test010/test010.k0000644000175100017510000000053311170340767014475 0ustar cimcimprogram test010; // -*-C-*- import globmod; globals { Int x = 5; String y; } Void printGlobals() { putStr(String(x)+" "+y+"\n"); x = x + 1; } Void main() { y="Sausages"; printGlobals(); printGlobals(); printVals(); setX(10); setY("Cheesecakes"); printVals(); printGlobals(); printVals(); } kaya-0.4.4/tests/test010/globmod.k0000644000175100017510000000052511170340767014721 0ustar cimcimmodule globmod; // -*-C-*- globals { Int x = mylength("sausages"); String y = "bottles of beer"; } Int mylength(String x) { return length(x)*2; } public Void setX(Int val) { putStrLn("Old x: " + x); x=val; } public Void setY(String val) { y=val; } public Void printVals() { putStr(String(x)+" "+y+"\n"); } kaya-0.4.4/tests/test010/expected0000644000175100017510000000021711170340767014644 0ustar cimcimCompiling module globmod Compiling program test010 5 Sausages 6 Sausages 16 bottles of beer Old x: 16 10 Cheesecakes 7 Sausages 10 Cheesecakes kaya-0.4.4/tests/test010/run0000644000175100017510000000025611170340767013652 0ustar cimcim#!/bin/bash ../../compiler/kayac test010.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test010 rm -f test010 test010.exe rm -f *.ki *.o kaya-0.4.4/tests/test027/0000755000175100017510000000000011170340767013130 5ustar cimcimkaya-0.4.4/tests/test027/test027.k0000644000175100017510000000063711170340764014517 0ustar cimcimprogram test027; Void main() { for x in [1..20] { putStrLn("Number "+x); } putStrLn("-------"); for x in [1,3..11] { putStrLn("Number "+x); } putStrLn("-------"); for x in [1,3..20] { putStrLn("Number "+x); } putStrLn("-------"); for x in [21,19..-5] { putStrLn("Number "+x); } putStrLn("-------"); for x in [1,5,6] { putStrLn("Number "+x); } } kaya-0.4.4/tests/test027/expected0000644000175100017510000000106111170340767014652 0ustar cimcimCompiling program test027 Number 1 Number 2 Number 3 Number 4 Number 5 Number 6 Number 7 Number 8 Number 9 Number 10 Number 11 Number 12 Number 13 Number 14 Number 15 Number 16 Number 17 Number 18 Number 19 Number 20 ------- Number 1 Number 3 Number 5 Number 7 Number 9 Number 11 ------- Number 1 Number 3 Number 5 Number 7 Number 9 Number 11 Number 13 Number 15 Number 17 Number 19 ------- Number 21 Number 19 Number 17 Number 15 Number 13 Number 11 Number 9 Number 7 Number 5 Number 3 Number 1 Number -1 Number -3 Number -5 ------- Number 1 Number 5 Number 6 kaya-0.4.4/tests/test027/run0000644000175100017510000000023711170340767013661 0ustar cimcim#!/bin/bash ../../compiler/kayac test027.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test027 rm -f test027 test027.exe kaya-0.4.4/tests/test003/0000755000175100017510000000000011170340767013122 5ustar cimcimkaya-0.4.4/tests/test003/expected0000644000175100017510000000024511170340767014647 0ustar cimcimCompiling program test003 [42][xxxxxxxx]U[[0][1][2]I[8]U[[1][1][2]I[5]C[0]]] [42][xxxxxxxx]U[[0][1][2]I[8]U[[1][1][2]I[5]U[[2][1][2]I[8]C[1]]]] 0 => 1 1 => 4 2 => 1 kaya-0.4.4/tests/test003/test003.k0000644000175100017510000000216211170340767014501 0ustar cimcimprogram test003; data Foo(Int p); /* for printing purposes, it's nicer if marshal doesn't have the function hash // so we don't have to update this test every single time the function table // changes! // Much easier with Regex, but I don't want to pull in additional modules */ String nofunpmarshal(any d, Int i) { m = marshal(d,i); cs = array(m); opensb = 0; closesb = 0; placeholder = false; out = ""; for c in cs { if (c == '[') { opensb++; out += "["; } else if (c == ']') { closesb++; out += "]"; } else { if (opensb == 2 && closesb == 1) { if (!placeholder) { out += "xxxxxxxx"; placeholder = true; } } else { out += String(c); } } } return out; } Void main() { thingy = cons(5,nil); thing2 = cons(8,thingy); thingy.tail = thing2; putStrLn(nofunpmarshal(thing2,42)); bar = copy(thing2); putStrLn(nofunpmarshal(bar,42)); x = Foo(1); foos = [x,x,x]; mstr = marshal(foos,1); [Foo] newfoos = unmarshal(mstr,1); newfoos[1] = Foo(4); for f@i in newfoos { putStrLn(i+" => "+f.p); } } kaya-0.4.4/tests/test003/run0000644000175100017510000000023011170340767013644 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test003.k -L ../../rts -L ../../stdlib ./test003 rm -f test003 test003.exe kaya-0.4.4/tests/mktest.pl0000644000175100017510000000063111170340765013562 0ustar cimcim#!/usr/bin/perl if ($#ARGV>=0) { $test=shift(@ARGV); } else { print "What's its name?\n"; exit; } mkdir($test); chdir($test); open(FOO,">run"); print FOO "#!/bin/bash\n"; print FOO "LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:../../rts/\n"; print FOO "../../compiler/kayac $test.k -L ../../rts -L ../../stdlib\n"; print FOO "./$test\n"; print FOO "rm -f $test\n"; close(FOO); system("chmod +x run"); kaya-0.4.4/tests/test043/0000755000175100017510000000000011170340770013120 5ustar cimcimkaya-0.4.4/tests/test043/test043.k0000644000175100017510000000214611170340770014505 0ustar cimcimprogram test043; import Queue; import Time; // Enqueue a list of ordered numbers. // Every so often, dequeue some and maintain a list of the dequeued numbers. // They should be strictly in sequence. // Might also be a good benchmark. Void testQueue(Int num) { srand(now()); xs = [1..num]; dequeued = []; q = empty; for x@i in xs { enqueue(q,x); // Every 50, on average, dequeue up to 20. if ((i+(rand()%5))%50 == 1) { for x in [0..(rand()%100)] { if (length(q)>0) { y = dequeue(q); push(dequeued,y); } } } } // Dequeue the rest. while (length(q)>0) { y = dequeue(q); push(dequeued,y); } // for y in dequeued { // putStr(y+","); // } // putStrLn("END"); if (xs == dequeued) { putStrLn("Dequeueing order is correct."); } else { putStrLn("QUEUES ARE BROKEN!"); } // Test array conversion. xs = [1..100]; for x in xs { enqueue(q,x); } dequeued = array(q); for y in dequeued { putStr(y+","); } putStrLn("END"); putStrLn("Queue length "+length(q)); } Void main() { testQueue(10000); } kaya-0.4.4/tests/test043/expected0000644000175100017510000000056011170340767014653 0ustar cimcimCompiling program test043 Dequeueing order is correct. 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,END Queue length 100 kaya-0.4.4/tests/test043/run0000644000175100017510000000023011170340767013650 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test043.k -L ../../rts -L ../../stdlib ./test043 rm -f test043 test043.exe kaya-0.4.4/tests/test052/0000755000175100017510000000000011170340770013120 5ustar cimcimkaya-0.4.4/tests/test052/test052.k0000644000175100017510000000010211170340767014501 0ustar cimcimprogram test052; import A; import B; Void main() { bar(); } kaya-0.4.4/tests/test052/B.k0000644000175100017510000000010711170340767013461 0ustar cimcimmodule B; import A; public Int getVal(A aval) { return aval.b; } kaya-0.4.4/tests/test052/A.k0000644000175100017510000000026011170340767013460 0ustar cimcimmodule A; public data A(Int b); extern public Int B::getVal(A aval); Void testThing(A x) { putStrLn("Val: " + getVal(x)); } public Void bar() { testThing(A(5)); } kaya-0.4.4/tests/test052/expected0000644000175100017510000000010711170340767014650 0ustar cimcimCompiling module A Compiling module B Compiling program test052 Val: 5 kaya-0.4.4/tests/test052/run0000644000175100017510000000024111170340770013644 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test052.k -L ../../rts -L ../../stdlib ./test052 rm -f test052 *.ki *.o test052.exe kaya-0.4.4/tests/test054/0000755000175100017510000000000011170340770013122 5ustar cimcimkaya-0.4.4/tests/test054/test054.k0000644000175100017510000000101511170340770014503 0ustar cimcimprogram test054; Void main() { max = 100; for triple in [(x,y,z) | y in [1..max], x in [1..y], z in [1..max], z*z == x*x + y*y] { (a,b,c) = triple; putStrLn(a+", "+b+", "+c); } primemax = 100; noprimes = [j | i in [2..primemax/2], j in [i*2,i*3..primemax]]; primes = [x | x in [2..primemax], !(elem(x, noprimes))]; for x in primes { putStr(x+", "); } putStrLn("..."); test = [x*x | x in [y*2 | y in [1..10]]]; for a in test { putStrLn(a+""); } } kaya-0.4.4/tests/test054/expected0000644000175100017510000000132511170340770014647 0ustar cimcimCompiling program test054 3, 4, 5 6, 8, 10 5, 12, 13 9, 12, 15 8, 15, 17 12, 16, 20 15, 20, 25 20, 21, 29 7, 24, 25 10, 24, 26 18, 24, 30 21, 28, 35 16, 30, 34 24, 32, 40 12, 35, 37 15, 36, 39 27, 36, 45 9, 40, 41 30, 40, 50 40, 42, 58 33, 44, 55 24, 45, 51 28, 45, 53 14, 48, 50 20, 48, 52 36, 48, 60 39, 52, 65 48, 55, 73 33, 56, 65 42, 56, 70 11, 60, 61 25, 60, 65 32, 60, 68 45, 60, 75 16, 63, 65 60, 63, 87 48, 64, 80 51, 68, 85 24, 70, 74 21, 72, 75 30, 72, 78 54, 72, 90 65, 72, 97 40, 75, 85 57, 76, 95 36, 77, 85 18, 80, 82 39, 80, 89 60, 80, 100 13, 84, 85 35, 84, 91 28, 96, 100 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, ... 4 16 36 64 100 144 196 256 324 400 kaya-0.4.4/tests/test054/run0000644000175100017510000000023111170340770013645 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test054.k -L ../../rts -L ../../stdlib ./test054 rm -f test054 test054.exe kaya-0.4.4/tests/test016/0000755000175100017510000000000011170340767013126 5ustar cimcimkaya-0.4.4/tests/test016/test016.k0000644000175100017510000000061011170340764014502 0ustar cimcimprogram guardtest; // -*-C-*- Int mag(Int x) | x<0 = (-x); String foo(Int x) | x==2 = "Exactly two" | x>100 = "Over a hundred" | default = "Something else"; Void main() { putStrLn(foo(2)); putStrLn(foo(3)); putStrLn(foo(300)); x=3; a | x==4 = (-x) | default = x*x; putStrLn(String(a)); putStrLn(String(mag(100))); } kaya-0.4.4/tests/test016/expected0000644000175100017510000000032111170340767014646 0ustar cimcimCompiling program guardtest Exactly two Something else Over a hundred 9 Builtins::Unguarded_Guard thrown at test016.k:3 guardtest::mag called from guardtest::main at test016.k:21 guardtest::main [entry point] kaya-0.4.4/tests/test016/run0000644000175100017510000000025211170340767013654 0ustar cimcim#!/bin/bash ../../compiler/kayac test016.k -L ../../rts -L ../../stdlib -o test016 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test016 rm -f test016 test016.exe kaya-0.4.4/tests/test039/0000755000175100017510000000000011170340767013133 5ustar cimcimkaya-0.4.4/tests/test039/test039.k0000644000175100017510000000051511170340766014522 0ustar cimcimprogram test039; public data Container = Container(Bool full); Void main() { boxes = []; for x in [0..5] { boxes[x] = Container(true); } testLeft(boxes,3); } public Void testLeft(var [Container] boxes, var Int x) { if (boxes[x-1].full) { putStrLn("Left is full"); } else { putStrLn("Left is empty"); } } kaya-0.4.4/tests/test039/expected0000644000175100017510000000004711170340767014660 0ustar cimcimCompiling program test039 Left is full kaya-0.4.4/tests/test039/run0000644000175100017510000000023011170340767013655 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test039.k -L ../../rts -L ../../stdlib ./test039 rm -f test039 test039.exe kaya-0.4.4/tests/test028/0000755000175100017510000000000011170340767013131 5ustar cimcimkaya-0.4.4/tests/test028/test028.k0000644000175100017510000000036011170340764014512 0ustar cimcimprogram test028; Void main() { n = 1; do { putStrLn("Done it "+n+" times"); n++; } while (n<-10); putStrLn("-----"); do { putStrLn("Done it "+n+" times"); n++; } while (n<10); putStrLn("n ends at "+n); } kaya-0.4.4/tests/test028/expected0000644000175100017510000000027511170340767014661 0ustar cimcimCompiling program test028 Done it 1 times ----- Done it 2 times Done it 3 times Done it 4 times Done it 5 times Done it 6 times Done it 7 times Done it 8 times Done it 9 times n ends at 10 kaya-0.4.4/tests/test028/run0000644000175100017510000000023711170340767013662 0ustar cimcim#!/bin/bash ../../compiler/kayac test028.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test028 rm -f test028 test028.exe kaya-0.4.4/tests/test022/0000755000175100017510000000000011170340767013123 5ustar cimcimkaya-0.4.4/tests/test022/test022.k0000644000175100017510000000076311170340766014507 0ustar cimcimprogram test022; Void showArray([Int] xs) { for x in xs { putStr(x+","); } putStrLn("END"); } Void main() { x = 10; y = 20; putStrLn("x = "+String(x)+"; y = "+String(y)); swap(x,y); putStrLn("x = "+String(x)+"; y = "+String(y)); xs = [9,8,7,18,3,2]; sort(xs); for x in xs { putStrLn(String(x)); } xs = []; for x in range(1,20) { push(xs,21-x); //rand() % 20); } showArray(xs); showArray(sorted(xs)); showArray(xs); } kaya-0.4.4/tests/test022/expected0000644000175100017510000000035211170340767014647 0ustar cimcimCompiling program test022 x = 10; y = 20 x = 20; y = 10 2 3 7 8 9 18 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,END 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,END 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,END kaya-0.4.4/tests/test022/run0000644000175100017510000000023711170340767013654 0ustar cimcim#!/bin/bash ../../compiler/kayac test022.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test022 rm -f test022 test022.exe kaya-0.4.4/tests/test007/0000755000175100017510000000000011170340770013120 5ustar cimcimkaya-0.4.4/tests/test007/test007b.k0000644000175100017510000000021311170340770014640 0ustar cimcimprogram test007b; // Returns the wrong type, so not general and should be an error. public a apply(b(a) f, a arg) { return f(arg); } kaya-0.4.4/tests/test007/test007.k0000644000175100017510000000036611170340766014514 0ustar cimcimprogram test007; // -*-C-*-ish import Array; Int double(Int x) { return x*2; } Void printArray([String] arr) { for x in arr { putStrLn(x); } } Void main() { x = [4,5,6,7,8]; printArray(map(double,x)); putStr("\n"); } kaya-0.4.4/tests/test007/expected0000644000175100017510000000036311170340770014646 0ustar cimcimCompiling program test007 test007.k:19:Type error in identifier 'double'; has type Int(Int), expected String(Int) Compiling program test007b test007b.k:5:Inferred type less general than given type - Inferred t1(t1(t1), t1), given a(b(a), a) kaya-0.4.4/tests/test007/run0000644000175100017510000000032011170340770013642 0ustar cimcim#!/bin/bash ../../compiler/kayac test007.k -L ../../rts -L ../../stdlib -o test007 ../../compiler/kayac test007b.k -L ../../rts -L ../../stdlib -o test007b export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ kaya-0.4.4/tests/test004/0000755000175100017510000000000011170340767013123 5ustar cimcimkaya-0.4.4/tests/test004/test004.k0000644000175100017510000000060711170340766014504 0ustar cimcimprogram test004; // -*-C-*-ish import Array; String foo(Int x) { return String(x); } Int double(Int x) { return x*2; } Void printArray([String] arr) { for x in arr { putStrLn(x); } } Void main() { x = ["foo","bar","quux"]; y = [5,6,7,20]; z = []; printArray(x); printArray(map(foo,map(double,y))); putStrLn(["scissors","paper","stone"][1]); } kaya-0.4.4/tests/test004/expected0000644000175100017510000000007111170340767014645 0ustar cimcimCompiling program test004 foo bar quux 10 12 14 40 paper kaya-0.4.4/tests/test004/run0000644000175100017510000000023711170340767013654 0ustar cimcim#!/bin/bash ../../compiler/kayac test004.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test004 rm -f test004 test004.exe kaya-0.4.4/tests/test048/0000755000175100017510000000000011170340770013125 5ustar cimcimkaya-0.4.4/tests/test048/test048.k0000644000175100017510000000277311170340770014525 0ustar cimcimprogram test048; // -*-C-*-ish import Set; import Time; import Testing; globals { Int seed = now; } Int aSum([Int] xs) = fold(\(Int a, Int b) -> a+b, xs, 0); Bool ordered([Int] xs) { for x@i in xs { if (i==0) last = x; else { if (x0, "Sets gone very badly wrong somewhere"); assert(ordered(array(set)), "Ordering broken before deletion with seed "+seed); sThen = size(array(set)); sumThen = aSum(array(set)); delete(set, y); sNow = size(array(set)); sumNow = aSum(array(set)); assert(sNow == sThen-1, "Sets broken with seed " + seed); assert(sumNow == sumThen-y, "Sets broken with seed " + seed); assert(ordered(array(set)), "Ordering broken after deletion with seed " + seed); seed = rand; } Void hashSetTest() { set = newHashSet(); srand(seed); for x in [1..100] { y = rand()%101; add(set, y); // putStr(y+","); } assert(size(array(set))>0, "Sets gone very badly wrong somewhere"); sumThen = aSum(array(set)); sThen = size(array(set)); delete(set, y); sNow = size(array(set)); sumNow = aSum(array(set)); assert(sNow == sThen-1, "Hash Sets broken with seed " + seed); seed = rand; } Void main() { add(@setTest, 1000, "Sets"); add(@hashSetTest, 1000, "Hash Sets"); x = run(); } kaya-0.4.4/tests/test048/expected0000644000175100017510000000013311170340767014654 0ustar cimcimCompiling program test048 Test 1 (Sets) success Test 2 (Hash Sets) success All tests pass kaya-0.4.4/tests/test048/run0000644000175100017510000000023011170340767013655 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test048.k -L ../../rts -L ../../stdlib ./test048 rm -f test048 test048.exe kaya-0.4.4/tests/test018/0000755000175100017510000000000011170340767013130 5ustar cimcimkaya-0.4.4/tests/test018/test018.k0000644000175100017510000000051711170340764014514 0ustar cimcimprogram testdef; Void printByFun(String x = "Sausages", Void(String) printfn = putStrLn) { printfn(x); } Void printThing(Int n, String y = "Cheese", String x = "Sausages") { putStrLn(String(n)+" "+x+" "+y); } Void main() { printThing(5,"Ping"); printByFun(); printByFun("Foo"); printByFun("Foo\n",putStr); } kaya-0.4.4/tests/test018/expected0000644000175100017510000000007311170340767014654 0ustar cimcimCompiling program testdef 5 Sausages Ping Sausages Foo Foo kaya-0.4.4/tests/test018/run0000644000175100017510000000025211170340767013656 0ustar cimcim#!/bin/bash ../../compiler/kayac test018.k -L ../../rts -L ../../stdlib -o test018 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test018 rm -f test018 test018.exe kaya-0.4.4/tests/test023/0000755000175100017510000000000011170340767013124 5ustar cimcimkaya-0.4.4/tests/test023/test023d.k0000644000175100017510000000035311170340764014646 0ustar cimcimprogram typeerr; import Dict; type Num = Int; type Foo = List; public Void foo(Foo xs) { putStrLn(String(xs.head)); } public Void main() { Foo l = cons(5,nil); List m = l; foo(l); } kaya-0.4.4/tests/test023/test023c.k0000644000175100017510000000026111170340764014643 0ustar cimcimprogram typeerr; import Dict; type Num = Int; type Foo = List; public Void foo(Foo xs) { putStrLn(String(xs.head)); } public Void main() { foo(cons(5,nil)); } kaya-0.4.4/tests/test023/test023a.k0000644000175100017510000000020311170340764014635 0ustar cimcimprogram typeerr; import Dict; type Num = Int; type Foo = List; public Void foo(Foo xs) { putStrLn("foo"); } kaya-0.4.4/tests/test023/test023e.k0000644000175100017510000000035311170340764014647 0ustar cimcimprogram typeerr; import Dict; type Num = Int; type Foo = List; public Void foo(Foo xs) { putStrLn(String(xs.head)); } public Void main() { Foo l = cons(5,nil); List m = l; foo(l); } kaya-0.4.4/tests/test023/test023b.k0000644000175100017510000000033711170340764014646 0ustar cimcimprogram typeerr; import Dict; type Num = Int; type Foo = List; public Void foo(Foo xs) { putStrLn(String(xs.head)); } public Void main() { Foo l = cons(5,nil); List m = l; foo(l); } kaya-0.4.4/tests/test023/test023f.k0000644000175100017510000000035511170340764014652 0ustar cimcimprogram typeerr; import Dict; type Num = Int; type Foo = List; public Void foo(Foo xs) { putStrLn(String(xs.head)); } public Void main() { Foo l = cons(5,nil); List m = l; foo(l); } kaya-0.4.4/tests/test023/expected0000644000175100017510000000055611170340767014656 0ustar cimcimCompiling program typeerr test023a.k:9:Type synonym Foo has too many parameters Compiling program typeerr 5 Compiling program typeerr test023c.k:9:Type synonym Foo has too few parameters Compiling program typeerr test023d.k:6:b not declared as a parameter Compiling program typeerr 5 Compiling program typeerr test023f.k:9:Type Prelude::List has too many parameters kaya-0.4.4/tests/test023/run0000644000175100017510000000102011170340767013644 0ustar cimcim#!/bin/bash ../../compiler/kayac test023a.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test023b.k -L ../../rts -L ../../stdlib ./typeerr rm -f typeerr typeerr.exe ../../compiler/kayac test023c.k -L ../../rts -L ../../stdlib ../../compiler/kayac test023d.k -L ../../rts -L ../../stdlib ../../compiler/kayac test023e.k -L ../../rts -L ../../stdlib ./typeerr rm -f typeerr typeerr.exe ../../compiler/kayac test023f.k -L ../../rts -L ../../stdlib rm -f typeerr typeerr.exe kaya-0.4.4/tests/test001/0000755000175100017510000000000011170340767013120 5ustar cimcimkaya-0.4.4/tests/test001/test001.k0000644000175100017510000000015011170340766014467 0ustar cimcimprogram test001; import B; import A; Void main() { foo(); // putStrLn(String(hash("Foo"))); } kaya-0.4.4/tests/test001/B.k0000644000175100017510000000012411170340766013451 0ustar cimcimmodule B; import Dict; import public A; Void test() { a = new(); } Void bar() { } kaya-0.4.4/tests/test001/A.k0000644000175100017510000000010411170340766013446 0ustar cimcimmodule A; import Dict; public Void foo() { putStrLn("Foo"); } kaya-0.4.4/tests/test001/expected0000644000175100017510000000010411170340767014637 0ustar cimcimCompiling module A Compiling module B Compiling program test001 Foo kaya-0.4.4/tests/test001/run0000644000175100017510000000025011170340767013644 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test001.k -L ../../rts -L ../../stdlib ./test001 rm -f test001 test001.exe rm -f *.o *.ki kaya-0.4.4/tests/test051/0000755000175100017510000000000011170340770013117 5ustar cimcimkaya-0.4.4/tests/test051/test051.k0000644000175100017510000000115511170340767014510 0ustar cimcimprogram test051; import newex; Void throwTest(Int i) { try { case i of { 1 -> throw(Not_Implemented); | 2 -> throw(TestExcept(3.14,"Sausages")); | 3 -> throw(TestExcept2); } } catch(TestExcept2) { putStrLn("Second one"); } catch(TestExcept(v,s)) { putStrLn("Oops, got float "+v+" and string "+s); // putStrLn("Appear to be here!"); throw(TestExcept(v,s)); } catch(all) { putStrLn("Catch all"); throw(all); } } Void main() { for x in [1..3] { try { throwTest(x); } catch(e) { putStrLn("Rethrew " + exceptionMessage(e)); } } throwTest(4); } kaya-0.4.4/tests/test051/newex.k0000644000175100017510000000013611170340767014427 0ustar cimcimmodule newex; Exception TestExcept(Float funnycode, String message); Exception TestExcept2; kaya-0.4.4/tests/test051/expected0000644000175100017510000000040311170340770014640 0ustar cimcimCompiling module newex Compiling program test051 Catch all Rethrew Builtins::Not_Implemented Oops, got float 3.14 and string Sausages Rethrew newex::TestExcept Second one Catch all Builtins::Missing_Case thrown at test051.k:7 test051::throwTest [entry point] kaya-0.4.4/tests/test051/run0000644000175100017510000000024111170340770013643 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test051.k -L ../../rts -L ../../stdlib ./test051 rm -f test051 *.o *.ki test051.exe kaya-0.4.4/tests/test033/0000755000175100017510000000000011170340770013117 5ustar cimcimkaya-0.4.4/tests/test033/test033.k0000644000175100017510000000071211170340770014500 0ustar cimcimprogram test033; // -*-C-*-ish import calclang; import Dict; globals { Context ctxt; } Void runExp(String exp) { putStrLn(exp+ " = " + calcExpr(ctxt,exp)); } Void main() { ctxt = Dict::new(); foo = calcExpr(ctxt, "y = 4"); foo = calcExpr(ctxt, "z = 6"); runExp("y+2*z+z"); runExp("(y+2)*z+z"); runExp("y+(2*z)+z"); runExp("y+2*(z+z)"); runExp("(y*2+z)*z"); runExp("y*(2+z*z)"); runExp("(y+2*z+z)"); } kaya-0.4.4/tests/test033/calclang.k0000644000175100017510000000463511170340770015047 0ustar cimcimmodule calclang; // -*-C-*-ish import IO; import Parse; import Dict; abstract data Expr = Var(String name) | Assign(String varname, Expr val) | Num(Int num) | Infix(Op op,Expr l, Expr r); data Op = Plus | Minus | Times | Divide; Exception NoSuchVariable(); Exception ParseException(String err, Int pos); Expr parseExpr(var ParseState st) = (parseAssign `or` parsePlusMinus `or` parseMultDiv `or` parseBrackets `or` parseVar `or` parseNum)(st); Expr parseVar(var ParseState st) = Var(identifier(st)); Expr parseNum(var ParseState st) { num = Num(integer(st)); return num; } Expr parseBrackets(var ParseState st) { c = char('(',st); exp = parseExpr(st); c = char(')',st); return exp; } Expr parsePlusMinus(var ParseState st) { left = (parseMultDiv `or` parseBrackets `or` parseNum `or` parseVar)(st); // putStrLn(st.input); whitespace(st); opch = ((char@('+')) `or` (char@('-')))(st); whitespace(st); if (opch=='+') { op = Plus; } else if (opch=='-') { op = Minus; } right = parseExpr(st); return Infix(op,left,right); } Expr parseAssign(var ParseState st) { name = identifier(st); whitespace(st); opch = char('=',st); whitespace(st); exp = parseExpr(st); return Assign(name, exp); } Expr parseMultDiv(var ParseState st) { left = (parseBrackets `or` parseNum `or` parseVar)(st); whitespace(st); opch = ((char@('*')) `or` (char@('/')))(st); whitespace(st); if (opch=='*') { op = Times; } else if (opch=='/') { op = Divide; } right = (parseBrackets `or` parseMultDiv `or` parseNum `or` parseVar)(st); return Infix(op,left,right); } type Context = Dict; Int eval(Context ctxt, Expr e) { case e of { Num(x) -> return x; | Var(v) -> case lookup(ctxt,v) of { nothing -> throw(NoSuchVariable); | just(val) -> return val; } | Assign(v,exp) -> ev = eval(ctxt,exp); add(ctxt, v, ev); return ev; | Infix(Plus,l,r) -> return eval(ctxt,l)+eval(ctxt,r); | Infix(Minus,l,r) -> return eval(ctxt,l)-eval(ctxt,r); | Infix(Times,l,r) -> return eval(ctxt,l)*eval(ctxt,r); | Infix(Divide,l,r) -> return eval(ctxt,l)/eval(ctxt,r); } } public Int calcExpr(Context ctxt, String strexp) { case parse(parseExpr, strexp) of { Success(exp) -> return eval(ctxt, exp); | ParseError(err,l,p) -> throw(ParseException(err,p)); } } kaya-0.4.4/tests/test033/expected0000644000175100017510000000023411170340767014650 0ustar cimcimCompiling module calclang Compiling program test033 y+2*z+z = 22 (y+2)*z+z = 42 y+(2*z)+z = 22 y+2*(z+z) = 28 (y*2+z)*z = 84 y*(2+z*z) = 152 (y+2*z+z) = 22 kaya-0.4.4/tests/test033/run0000644000175100017510000000024711170340767013657 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test033.k -L ../../rts -L ../../stdlib ./test033 rm -f test033 test033.exe rm -f *.ki *.o kaya-0.4.4/tests/test029/0000755000175100017510000000000011170340770013124 5ustar cimcimkaya-0.4.4/tests/test029/test029.k0000644000175100017510000000056311170340770014516 0ustar cimcimprogram test029; Void main() { xs = []; xs[100] = nothing; xs[45] = just(8); putStrLn("45th is "+deref(xs[45])); try { z = xs[46].val; } catch(e) { putStrLn(exceptionMessage(e)); } try { putStrLn("46th is "+deref(xs[46])); } catch(e) { putStrLn(exceptionMessage(e)); } putStrLn("100th is "+deref(xs[100])); } kaya-0.4.4/tests/test029/expected0000644000175100017510000000026711170340770014655 0ustar cimcimCompiling program test029 45th is 8 Builtins::Project_From_Non_Union Builtins::Getting_Tag_From_Non_Union Prelude::CantDerefNothing thrown at test029.k:25 test029::main [entry point] kaya-0.4.4/tests/test029/run0000644000175100017510000000023711170340767013663 0ustar cimcim#!/bin/bash ../../compiler/kayac test029.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test029 rm -f test029 test029.exe kaya-0.4.4/tests/test041/0000755000175100017510000000000011170340767013124 5ustar cimcimkaya-0.4.4/tests/test041/test041a.k0000644000175100017510000000110711170340766014643 0ustar cimcimprogram test041; import Strings; public Int my_abs(Int x) { if (x<0) return -x; else return x; } public Float my_abs(Float x) { if (x<0) return -x; else return x; } Void main() { putStrLn("Float abs(-5.2) = " + abs(-5.2)); putStrLn("Int abs(-5) = " + abs(-5)); putStrLn("Float my_abs(-5.2) = " + my_abs(-5.2)); putStrLn("Int my_abs(-5) = " + my_abs(-5)); str = join(["abc","def"],'\n'); str2 = join([str,"efg"],'-'); arr = join([[1,2,3,4],[5,6,7,8]]); putStrLn(str2); for x in arr { putStr(x+","); } putStrLn("END"); } kaya-0.4.4/tests/test041/test041b.k0000644000175100017510000000075011170340766014647 0ustar cimcimprogram test041; import Strings; Void main() { my_absI = abs@(-5); my_absF = abs@(-5.2); putStrLn("Float abs(-5.2) = " + abs(-5.2)); putStrLn("Int abs(-5) = " + abs(-5)); putStrLn("Float my_abs(-5.2) = " + my_absF()); putStrLn("Int my_abs(-5) = " + my_absI()); str = join(["abc","def"],"\n"); str2 = join([str,"efg"],'-'); arr = join([[1,2,3,4],[5,6,7,8]]); putStrLn(str2); for x in arr { putStr(x+","); } putStrLn("END"); } kaya-0.4.4/tests/test041/test041c.k0000644000175100017510000000074311170340766014652 0ustar cimcimprogram test041; import Strings; Void main() { my_absI = abs@(-5); my_absF = abs@(); putStrLn("Float abs(-5.2) = " + abs(-5.2)); putStrLn("Int abs(-5) = " + abs(-5)); putStrLn("Float my_abs(-5.2) = " + my_absF(-5.2)); putStrLn("Int my_abs(-5) = " + my_absI()); str = join(["abc","def"]); str2 = join([str,"efg"],'-'); arr = join([[1,2,3,4],[5,6,7,8]]); putStrLn(str2); for x in arr { putStr(x+","); } putStrLn("END"); } kaya-0.4.4/tests/test041/expected0000644000175100017510000000061011170340767014645 0ustar cimcimCompiling program test041 Float abs(-5.2) = 5.2 Int abs(-5) = 5 Float my_abs(-5.2) = 5.2 Int my_abs(-5) = 5 abc def-efg 1,2,3,4,5,6,7,8,END Compiling program test041 Float abs(-5.2) = 5.2 Int abs(-5) = 5 Float my_abs(-5.2) = 5.2 Int my_abs(-5) = 5 abc def-efg 1,2,3,4,5,6,7,8,END Compiling program test041 test041c.k:7:Ambiguous name: abs (Could be Builtins::abs(Float), Builtins::abs(Int)) kaya-0.4.4/tests/test041/run0000644000175100017510000000052111170340767013651 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test041a.k -L ../../rts -L ../../stdlib ./test041 rm -f test041 test041.exe ../../compiler/kayac test041b.k -L ../../rts -L ../../stdlib ./test041 rm -f test041 test041.exe ../../compiler/kayac test041c.k -L ../../rts -L ../../stdlib rm -f test041 test041.exe kaya-0.4.4/tests/test042/0000755000175100017510000000000011170340767013125 5ustar cimcimkaya-0.4.4/tests/test042/test042a.k0000644000175100017510000000034011170340766014643 0ustar cimcimprogram test042a; String tostring([String] xs) { str = ""; for x@i in xs { str += x; if (i longlist(List acc,Int x) { if (x==0) { return acc; } else { return longlist(cons((x*2)%100,acc),x-1); } } Int sumlist(Int acc,List l) { case l of { nil() -> return acc; | cons(x,xs) -> return sumlist(acc+x,xs); } } Void main() { /* putStrLn(String(silly(0,200000))); putStrLn(String(sumlist(0,longlist(nil(),200000)))); */ } kaya-0.4.4/tests/test013/expected0000644000175100017510000000003611170340767014646 0ustar cimcimCompiling program tailrecurse kaya-0.4.4/tests/test013/run0000644000175100017510000000025211170340767013651 0ustar cimcim#!/bin/bash ../../compiler/kayac test013.k -L ../../rts -L ../../stdlib -o test013 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test013 rm -f test013 test013.exe kaya-0.4.4/tests/test024/0000755000175100017510000000000011170340767013125 5ustar cimcimkaya-0.4.4/tests/test024/test024a.k0000644000175100017510000000047311170340764014650 0ustar cimcimprogram test024a; import Dict; type Num = Int; type Foo = Bar; type Bar = List; type Quux = Baz; type Baz = Bat; type Bat = Quux; public Void foo(Foo xs) { putStrLn(String(xs.head)); } public Void main() { Foo l = cons(5,nil); List m = l; foo(l); } kaya-0.4.4/tests/test024/test024b.k0000644000175100017510000000047311170340764014651 0ustar cimcimprogram test024b; import Dict; type Num = Int; type Foo = Bar; type Bar = List; type Quux = Baz; type Baz = Bat; type Bat = List; public Void foo(Foo xs) { putStrLn(String(xs.head)); } public Void main() { Foo l = cons(5,nil); List m = l; foo(l); } kaya-0.4.4/tests/test024/expected0000644000175100017510000000015411170340767014651 0ustar cimcimCompiling program test024a test024a.k:11:Cycle in type synonyms Baz, Quux, Bat Compiling program test024b 5 kaya-0.4.4/tests/test024/run0000644000175100017510000000034011170340767013651 0ustar cimcim#!/bin/bash ../../compiler/kayac test024a.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test024b.k -L ../../rts -L ../../stdlib ./test024b rm -f test024b test024b.exe kaya-0.4.4/tests/test030/0000755000175100017510000000000011170340767013122 5ustar cimcimkaya-0.4.4/tests/test030/test030.k0000644000175100017510000000041511170340767014500 0ustar cimcimprogram test030; import Logger; Void main() { l1 = makeLogFile("logfile"); l2 = makeLogString(); logs = [l1,l2]; logAll(logs,"Didn't do anything",false); Logger::log(logs[1],"Didn't do anything",false); putStrLn("Log was " + logs[1].log); } kaya-0.4.4/tests/test030/expected0000644000175100017510000000023611170340767014647 0ustar cimcimCompiling program test030 Log was Didn't do anything Didn't do anything Log was Didn't do anything Didn't do anything Didn't do anything Didn't do anything kaya-0.4.4/tests/test030/run0000644000175100017510000000030111170340767013643 0ustar cimcim#!/bin/bash ../../compiler/kayac test030.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test030 ./test030 cat logfile rm -f test030 test030.exe rm logfile kaya-0.4.4/tests/test034/0000755000175100017510000000000011170340770013120 5ustar cimcimkaya-0.4.4/tests/test034/test034c.k0000644000175100017510000000040311170340767014650 0ustar cimcimprogram test034c; import IO; Void main() { xs = [5,10..20]; mult = 2; xs = map(\(a) { putStrLn("mult = " + a*mult); }, xs); for x in xs { putStrLn("x = "+x); } foo = \(b) -> b*mult; mult = 5; putStrLn("Foo = "+foo(2)); } kaya-0.4.4/tests/test034/test034b.k0000644000175100017510000000071111170340767014651 0ustar cimcimprogram test034b; // -*-C-*-ish data Foo(String name); Bool eqFoo(Foo f1,Foo f2) { cmp = \(a,b) -> (f1.name==a && f2.name==b) || (f1.name==b && f2.name==a); if (cmp("abc","def") || cmp("ghi","jkl")) { return true; } return (f1.name==f2.name); } Void main() { putStrLn("Foo "+eqFoo(Foo("def"),Foo("abc"))); putStrLn("Foo "+eqFoo(Foo("abc"),Foo("def"))); putStrLn("Foo "+eqFoo(Foo("def"),Foo("ghi"))); } kaya-0.4.4/tests/test034/test034a.k0000644000175100017510000000064711170340767014660 0ustar cimcimprogram test034a; // -*-C-*-ish data Foo(String name); Bool eqFoo(Foo f1,Foo f2) { cmp = \(a,b) -> (f1==a && f2==b) || (f1==b && f2==a); if (cmp("abc","def") || cmp("ghi","jkl")) { return true; } return (f1.name==f2.name); } Void main() { putStrLn("Foo "+eqFoo(Foo("def"),Foo("abc"))); putStrLn("Foo "+eqFoo(Foo("abc"),Foo("def"))); putStrLn("Foo "+eqFoo(Foo("def"),Foo("ghi"))); } kaya-0.4.4/tests/test034/test034d.k0000644000175100017510000000053511170340767014657 0ustar cimcimprogram test034d; import IO; Void testFun(Void(Int) foo, Int x) { foo(x); } Void main() { xs = [5,10..20]; mult = 2; xs = map(\(a) { putStrLn("mult = " + a*mult); return a*mult; }, xs); for x in xs { testFun(\(q) { putStrLn("x = "+q); }, x); } foo = \(b) -> b*mult; mult = 5; putStrLn("Foo = "+foo(2)); } kaya-0.4.4/tests/test034/expected0000644000175100017510000000054111170340770014644 0ustar cimcimCompiling program test034a test034a.k:10:Type error in constant "def"; has type String, expected test034a::Foo Compiling program test034b Foo true Foo true Foo false Compiling program test034c test034c.k:9:not all branches of lambda return a value Compiling program test034d mult = 10 mult = 20 mult = 30 mult = 40 x = 10 x = 20 x = 30 x = 40 Foo = 10 kaya-0.4.4/tests/test034/run0000644000175100017510000000057311170340767013662 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test034a.k -L ../../rts -L ../../stdlib ../../compiler/kayac test034b.k -L ../../rts -L ../../stdlib ./test034b rm -f test034b test034b.exe ../../compiler/kayac test034c.k -L ../../rts -L ../../stdlib ../../compiler/kayac test034d.k -L ../../rts -L ../../stdlib ./test034d rm -f test034d test034d.exe kaya-0.4.4/tests/test015/0000755000175100017510000000000011170340767013125 5ustar cimcimkaya-0.4.4/tests/test015/test015.k0000644000175100017510000000075711170340767014517 0ustar cimcimprogram dicttest; // -*-C-*- import Dict; Void main() { x = Dict::new(); add(x,"Sausages",47); putStrLn(String(deref(lookup(x,"Sausages")))); add(x,"Sausages",100); add(x,"Cheese",42); add(x,"Petunias",17); putStrLn(String(deref(lookup(x,"Petunias")))); putStrLn(String(deref(lookup(x,"Sausages")))); ks = keys(x); sort(ks); // so the output order is independent of hash() for k in ks { putStrLn(k + "==>" + String(deref(lookup(x,k)))); } } kaya-0.4.4/tests/test015/expected0000644000175100017510000000011611170340767014647 0ustar cimcimCompiling program dicttest 47 17 100 Cheese==>42 Petunias==>17 Sausages==>100 kaya-0.4.4/tests/test015/run0000644000175100017510000000025211170340767013653 0ustar cimcim#!/bin/bash ../../compiler/kayac test015.k -L ../../rts -L ../../stdlib -o test015 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test015 rm -f test015 test015.exe kaya-0.4.4/tests/test011/0000755000175100017510000000000011170340770013113 5ustar cimcimkaya-0.4.4/tests/test011/test011.k0000644000175100017510000000404011170340770014466 0ustar cimcimprogram testbuiltins; // -*-C-*-ish import Array; /* for printing purposes, it's nicer if marshal doesn't have the function hash // so we don't have to update this test every single time the function table // changes! // Much easier with Regex, but I don't want to pull in additional modules */ String nofunpmarshal(any d, Int i) { m = marshal(d,i); cs = array(m); opensb = 0; closesb = 0; placeholder = false; out = ""; for c in cs { if (c == '[') { opensb++; out += "["; } else if (c == ']') { closesb++; out += "]"; } else { if (opensb == 2 && closesb == 1) { if (!placeholder) { out += "xxxxxxxx"; placeholder = true; } } else { out += String(c); } } } return out; } Void main() { putStrLn(String(compare(56,43)>0)); xs = [1,5,4,9,1,22,3]; sort(xs); putStrLn(nofunpmarshal("Sausages",1)); putStrLn(nofunpmarshal(xs,1)); lista = cons(5,cons(6,nil())); listb = cons(5,cons(2,nil())); listc = cons(5,cons(6,nil())); putStrLn(String(compare(lista,listb)>0)); putStrLn(nofunpmarshal(lista,1)); ha = hash(lista); hb = hash(listb); hc = hash(listc); if (ha == hc && ha != hb && hb != hc) { putStrLn("Hashing equivalence okay"); } else { putStrLn("Hashing equivalence broken:\n"+ha+"\n"+hb+"\n"+hc); } // can't allocate less than 8 for an array chunk size msh = "[1][" + funtableHash + "]A[[0][16]I[6]I[87]]"; // putStrLn(msh); [Int] ys = unmarshal(msh,1); putStr(String(ys[1])); if (marshal(ys,1) == msh) { putStrLn("Marshal equivalence okay."); } else { putStrLn("Marshal equivalence broken."); putStrLn(marshal(ys,1)); putStrLn(msh); } List val = cons(3,nil()); putStrLn(nofunpmarshal(val,255)); val.tail = val; putStrLn(nofunpmarshal(val,255)); newval = unmarshal(marshal(val,255),255); putStrLn(nofunpmarshal(newval,255)); x = val; for y in range(1,10) { putStrLn(String(x.head)); x = x.tail; } } kaya-0.4.4/tests/test011/expected0000644000175100017510000000056511170340770014645 0ustar cimcimCompiling program testbuiltins true [1][xxxxxxxx]S[[8][16]Sausages] [1][xxxxxxxx]A[[0][16]I[1]I[1]I[3]I[4]I[5]I[9]I[22]] true [1][xxxxxxxx]U[[0][1][2]I[5]U[[1][1][2]I[6]U[[2][0][0]]]] Hashing equivalence okay 87Marshal equivalence okay. [255][xxxxxxxx]U[[0][1][2]I[3]U[[1][0][0]]] [255][xxxxxxxx]U[[0][1][2]I[3]C[0]] [255][xxxxxxxx]U[[0][1][2]I[3]C[0]] 3 3 3 3 3 3 3 3 3 3 kaya-0.4.4/tests/test011/run0000644000175100017510000000025211170340767013647 0ustar cimcim#!/bin/bash ../../compiler/kayac test011.k -L ../../rts -L ../../stdlib -o test011 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test011 rm -f test011 test011.exe kaya-0.4.4/tests/test040/0000755000175100017510000000000011170340770013115 5ustar cimcimkaya-0.4.4/tests/test040/test040.k0000644000175100017510000000073311170340767014505 0ustar cimcimprogram test040; // -*-C-*-ish import Crypto; String rndString() { str = ""; for x in [0..4+(abs(rand())%40)] { str += Char('A'+abs(rand())%26); } return str; } Void main() { srand(12345); for x in [1..100] { // Make a random string of random length, encrypt and decrypt foo = rndString; foocrypt = encode(foo); foo2 = decode(foocrypt); putStr(x+": "); if (foo==foo2) { putStrLn("OK"); } else { putStrLn("Fail "+foo); } } } kaya-0.4.4/tests/test040/expected0000644000175100017510000000131611170340767014650 0ustar cimcimCompiling program test040 1: OK 2: OK 3: OK 4: OK 5: OK 6: OK 7: OK 8: OK 9: OK 10: OK 11: OK 12: OK 13: OK 14: OK 15: OK 16: OK 17: OK 18: OK 19: OK 20: OK 21: OK 22: OK 23: OK 24: OK 25: OK 26: OK 27: OK 28: OK 29: OK 30: OK 31: OK 32: OK 33: OK 34: OK 35: OK 36: OK 37: OK 38: OK 39: OK 40: OK 41: OK 42: OK 43: OK 44: OK 45: OK 46: OK 47: OK 48: OK 49: OK 50: OK 51: OK 52: OK 53: OK 54: OK 55: OK 56: OK 57: OK 58: OK 59: OK 60: OK 61: OK 62: OK 63: OK 64: OK 65: OK 66: OK 67: OK 68: OK 69: OK 70: OK 71: OK 72: OK 73: OK 74: OK 75: OK 76: OK 77: OK 78: OK 79: OK 80: OK 81: OK 82: OK 83: OK 84: OK 85: OK 86: OK 87: OK 88: OK 89: OK 90: OK 91: OK 92: OK 93: OK 94: OK 95: OK 96: OK 97: OK 98: OK 99: OK 100: OK kaya-0.4.4/tests/test040/run0000644000175100017510000000025011170340770013641 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test040.k -L ../../rts -L ../../stdlib -seedkey test ./test040 rm -f test040 test040.exe kaya-0.4.4/tests/test036/0000755000175100017510000000000011170340767013130 5ustar cimcimkaya-0.4.4/tests/test036/test036b.k0000644000175100017510000000171411170340766014660 0ustar cimcimprogram test036b; Void main() { test1(); test2(); test3(); test4(); } Void test1() { g = Input1; h = Input2; arr = [g]; if (inArray(h,arr)) { putStrLn("1: Is a match"); } else { putStrLn("1: Is no match"); } } Void test2() { if (Input2 == Input1) { putStrLn("2: Is a match"); } else { putStrLn("2: Is no match"); } } Void test3() { arr2 = [Input2]; if (inArray(Input2,arr2)) { putStrLn("3: Is a match"); } else { putStrLn("3: Is no match"); } } Void test4() { arr3 = [Input1]; if (inArray(Input2,arr3)) { putStrLn("4: Is a match"); } else { putStrLn("4: Is no match"); } } public Bool inArray(a needle, [a] haystack) { for element in haystack { if (needle == element) { return true; } } return false; } public data StringContainer(String contained); public StringContainer Input1 = StringContainer("."); public StringContainer Input2 = StringContainer(","); kaya-0.4.4/tests/test036/expected0000644000175100017510000000025411170340767014655 0ustar cimcimCompiling program test036a 1: Is no match 2: Is no match 3: Is a match 4: Is no match Compiling program test036b 1: Is no match 2: Is no match 3: Is a match 4: Is no match kaya-0.4.4/tests/test036/test036a.k0000644000175100017510000000153211170340766014655 0ustar cimcimprogram test036a; Void main() { g = Input1; h = Input2; arr = [g]; if (inArray(h,arr)) { putStrLn("1: Is a match"); } else { putStrLn("1: Is no match"); } if (Input2 == Input1) { putStrLn("2: Is a match"); } else { putStrLn("2: Is no match"); } arr2 = [Input2]; if (inArray(Input2,arr2)) { putStrLn("3: Is a match"); } else { putStrLn("3: Is no match"); } arr3 = [Input1]; if (inArray(Input2,arr3)) { putStrLn("4: Is a match"); } else { putStrLn("4: Is no match"); } } public Bool inArray(a needle, [a] haystack) { for element in haystack { if (needle == element) { return true; } } return false; } public data StringContainer(String contained); public StringContainer Input1 = StringContainer("."); public StringContainer Input2 = StringContainer(","); kaya-0.4.4/tests/test036/run0000644000175100017510000000040011170340767013651 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test036a.k -L ../../rts -L ../../stdlib ./test036a rm -f test036a test036a.exe ../../compiler/kayac test036b.k -L ../../rts -L ../../stdlib ./test036b rm -f test036b test036b.exe kaya-0.4.4/tests/test047/0000755000175100017510000000000011170340767013132 5ustar cimcimkaya-0.4.4/tests/test047/test047.k0000644000175100017510000000070611170340767014523 0ustar cimcimprogram test047; import Reflect; import Pickle; Void main() { stuff = [4,5,6]; morestuff = ("Foo","Bar"); val = cons((stuff,morestuff),nil); val.tail = val; reflected = reflect(val); putStrLn(pickle(reflected)); putStrLn(pickle(val)); List<([Int], (String,String))> val2 = reify(reflected); List<([Int], (String,String))> val3 = unpickle(pickle(val)); putStrLn(pickle(val2)); putStrLn(pickle(val3)); } kaya-0.4.4/tests/test047/expected0000644000175100017510000000063711170340767014664 0ustar cimcimCompiling program test047 P(1)U(0,4,[I(1),A(1,[U(2,4,[I(0),A(3,[U(4,3,[A(5,[U(6,0,[I(4)]),U(7,0,[I(5)]),U(8,0,[I(6)])])]),U(9,4,[I(0),A(10,[U(11,2,[S(Rm9v)]),U(12,2,[S(QmFy)])])])])]),C(0)])]) P(1)U(0,1,[U(1,0,[A(2,[I(4),I(5),I(6)]),U(3,0,[S(Rm9v),S(QmFy)])]),C(0)]) P(1)U(0,1,[U(1,0,[A(2,[I(4),I(5),I(6)]),U(3,0,[S(Rm9v),S(QmFy)])]),C(0)]) P(1)U(0,1,[U(1,0,[A(2,[I(4),I(5),I(6)]),U(3,0,[S(Rm9v),S(QmFy)])]),C(0)]) kaya-0.4.4/tests/test047/run0000644000175100017510000000023011170340767013654 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test047.k -L ../../rts -L ../../stdlib ./test047 rm -f test047 test047.exe kaya-0.4.4/tests/test012/0000755000175100017510000000000011170340767013122 5ustar cimcimkaya-0.4.4/tests/test012/test012.k0000644000175100017510000000030211170340766014472 0ustar cimcimprogram testarith; // -*-C-*-ish Void main() { x=4; y=5; z=6; putStr(x*y+z+"\n"); // 26 putStr(x+y*z+"\n"); // 34 putStr((x+y)*z+"\n"); // 54 putStr(x*(y+z)+"\n"); // 44 } kaya-0.4.4/tests/test012/expected0000644000175100017510000000005011170340767014641 0ustar cimcimCompiling program testarith 26 34 54 44 kaya-0.4.4/tests/test012/run0000644000175100017510000000025211170340767013650 0ustar cimcim#!/bin/bash ../../compiler/kayac test012.k -L ../../rts -L ../../stdlib -o test012 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test012 rm -f test012 test012.exe kaya-0.4.4/tests/test049/0000755000175100017510000000000011170340770013126 5ustar cimcimkaya-0.4.4/tests/test049/expected0000644000175100017510000000003611170340767014657 0ustar cimcimCompiling program test049 OK! kaya-0.4.4/tests/test049/run0000644000175100017510000000024211170340767013661 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test049.k -L ../../rts -L ../../stdlib ./test049 rm -f test049 test049.exe largefile kaya-0.4.4/tests/test049/test049.k0000644000175100017510000000127111170340770014517 0ustar cimcimprogram test049; // -*-C-*-ish import Time; import IO; Void main() { sdata = randomString(100000); writeFile("./largefile",sdata); back = readFile("./largefile"); if (sdata == back) { putStrLn("OK!"); } else { putStrLn("--- Original data ---"); putStr(sdata); putStrLn("--- Final data ---"); putStr(back); } } String randomString(Int len) { str = createString(len); srand(now()); while (len > 0) { linlen = abs(rand())%70; if (linlen >= len) { linlen = len-1; } for i in [1..linlen] { str += String(Char(abs((rand())%90)+32)); } str += "\n"; len -= (linlen+1); } return str; } kaya-0.4.4/tests/test031/0000755000175100017510000000000011170340767013123 5ustar cimcimkaya-0.4.4/tests/test031/test031a.k0000644000175100017510000000042011170340764014634 0ustar cimcimprogram test031a; Int plus(Int x, Int y) { putStrLn("Adding "+x+" and "+y); return x+y; } Void main() { putStrLn(String(apply(plus@(3),2))); xs = [1,2,3,4,5,6,7]; ys = map(plus@(10),xs); for y in ys { putStr(y+","); } putStrLn(""); } kaya-0.4.4/tests/test031/test031e.k0000644000175100017510000000051011170340764014640 0ustar cimcimprogram test031e; Int myapply(Int(Bool) f, Int x) { return f(x); } Int plus(Int x, Int y) { putStrLn("Adding "+x+" and "+y); return x+y; } Void main() { putStrLn(String(myapply(plus@(3),2))); xs = [1,2,3,4,5,6,7]; ys = map(plus@(10),xs); for y in ys { putStr(y+","); } putStrLn(""); } kaya-0.4.4/tests/test031/test031d.k0000644000175100017510000000042311170340764014642 0ustar cimcimprogram test031d; Int plus(Int x, Int y) { putStrLn("Adding "+x+" and "+y); return x+y; } Void main() { putStrLn(String(apply(plus@(true),2))); xs = [1,2,3,4,5,6,7]; ys = map(plus@(10),xs); for y in ys { putStr(y+","); } putStrLn(""); } kaya-0.4.4/tests/test031/test031b.k0000644000175100017510000000042411170340764014641 0ustar cimcimprogram test031b; Int plus(Int x, Int y) { putStrLn("Adding "+x+" and "+y); return x+y; } Void main() { putStrLn(String(apply(plus@(3,4,5),2))); xs = [1,2,3,4,5,6,7]; ys = map(plus@(10),xs); for y in ys { putStr(y+","); } putStrLn(""); } kaya-0.4.4/tests/test031/test031c.k0000644000175100017510000000042211170340764014640 0ustar cimcimprogram test031c; Int plus(Int x, Int y) { putStrLn("Adding "+x+" and "+y); return x+y; } Void main() { putStrLn(String(apply(plus@(3,4),2))); xs = [1,2,3,4,5,6,7]; ys = map(plus@(10),xs); for y in ys { putStr(y+","); } putStrLn(""); } kaya-0.4.4/tests/test031/test031f.k0000644000175100017510000000022311170340767014645 0ustar cimcimprogram test031f; Int(String) getLenFn() { return length; } Void main() { fn = getLenFn()@("foo"); putStrLn(""+fn()); } kaya-0.4.4/tests/test031/expected0000644000175100017510000000143411170340767014651 0ustar cimcimCompiling program test031a Compiling program test031f Adding 3 and 2 5 Adding 10 and 1 Adding 10 and 2 Adding 10 and 3 Adding 10 and 4 Adding 10 and 5 Adding 10 and 6 Adding 10 and 7 11,12,13,14,15,16,17, 3 Compiling program test031b test031b.k:10:Too many arguments in partial application Compiling program test031c test031c.k:10:Type error in partial application of 'plus'; has type Int(), expected t6(Int) (possible reason: too many arguments in function call) Compiling program test031d test031d.k:10:Type error in partial application of 'plus'; has type Int(Int, Int), expected Int(Bool, Int) Compiling program test031e test031e.k:4:Type error in identifier 'x'; has type Int, expected Bool test031e.k:14:Type error in partial application of 'plus'; has type Int(Int), expected Int(Bool) kaya-0.4.4/tests/test031/run0000644000175100017510000000077411170340767013662 0ustar cimcim#!/bin/bash ../../compiler/kayac test031a.k -L ../../rts -L ../../stdlib ../../compiler/kayac test031f.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test031a ./test031f rm -f test031a test031a.exe rm -f test031f test031f.exe ../../compiler/kayac test031b.k -L ../../rts -L ../../stdlib ../../compiler/kayac test031c.k -L ../../rts -L ../../stdlib ../../compiler/kayac test031d.k -L ../../rts -L ../../stdlib ../../compiler/kayac test031e.k -L ../../rts -L ../../stdlib kaya-0.4.4/tests/test006/0000755000175100017510000000000011170340767013125 5ustar cimcimkaya-0.4.4/tests/test006/expected0000644000175100017510000000026311170340767014652 0ustar cimcimCompiling program test006 abcdef-!+@?%$"=& abcdef%2d%21%2b%40%3f%25%24%22%3d%26 abcdef-!+@?%$"=& Okay WebCommon::urlDecodeError thrown at test006.k:16 test006::main [entry point] kaya-0.4.4/tests/test006/run0000644000175100017510000000023711170340767013656 0ustar cimcim#!/bin/bash ../../compiler/kayac test006.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test006 rm -f test006 test006.exe kaya-0.4.4/tests/test006/test006.k0000644000175100017510000000051211170340766014503 0ustar cimcimprogram test006; import WebCommon; Void main() { foo = "abcdef-!+@?%$\"=&"; putStrLn(foo); bar = urlEncode(foo); putStrLn(bar); baz = urlDecode(bar); putStrLn(baz); if (baz == foo) { putStrLn("Okay"); } // this should throw an exception quux = urlDecode("%32%8%e1"); putStrLn(quux); // so we don't get to do this } kaya-0.4.4/tests/test050/0000755000175100017510000000000011170340767013124 5ustar cimcimkaya-0.4.4/tests/test050/test050.k0000644000175100017510000000066511170340767014513 0ustar cimcimprogram test050; Void main() { a = circle(); test(a); b = circle2(); test(b); } Void test(List a) { putStrLn("Created"); b = copy(a); putStrLn("Copy okay"); if (a == b) { putStrLn("== okay"); } if (equal(a,b)) { putStrLn("equal() okay"); } } List circle() { a = cons(1,nil); b = cons(2,a); a.tail = b; return a; } List circle2() { a = cons(1,nil); a.tail = a; return a; } kaya-0.4.4/tests/test050/expected0000644000175100017510000000015011170340767014644 0ustar cimcimCompiling program test050 Created Copy okay == okay equal() okay Created Copy okay == okay equal() okay kaya-0.4.4/tests/test050/run0000644000175100017510000000023011170340767013646 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test050.k -L ../../rts -L ../../stdlib ./test050 rm -f test050 test050.exe kaya-0.4.4/tests/test044/0000755000175100017510000000000011170340770013121 5ustar cimcimkaya-0.4.4/tests/test044/test044.k0000644000175100017510000000111511170340770014502 0ustar cimcim// Contrived program to demonstrate various var argument regressions // (and check they still work...) program test044; Void assign(var Int x, Int y) { tmp = x; // Should fall off x = y; } [Int] inc(var Int x) { arr = [x,x+2]; x = x + 1; return arr; } [Int] main2() { z = 5; arr = inc(z); for x in arr { putStr(string(x)+","); } putStrLn("END"); putStrLn(string(z)); return arr; } Void main() { arr = main2; for x in arr { putStr(string(x)+","); } putStrLn("END"); z = 0; assign(z,20); putStrLn(z+""); } kaya-0.4.4/tests/test044/expected0000644000175100017510000000005711170340770014647 0ustar cimcimCompiling program test044 5,7,END 6 5,7,END 20 kaya-0.4.4/tests/test044/run0000644000175100017510000000023011170340767013651 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test044.k -L ../../rts -L ../../stdlib ./test044 rm -f test044 test044.exe kaya-0.4.4/tests/test005/0000755000175100017510000000000011170340770013116 5ustar cimcimkaya-0.4.4/tests/test005/test005.k0000644000175100017510000000411711170340770014501 0ustar cimcimprogram test005; // A bit like -*-C-*- // Look! Mutually recursive types! data NavItem = Page(String, Int) | SubMenu(String,Nav); data Nav = Nav([NavItem]); Nav mainmenu() { return Nav([Page("Index",0), SubMenu("More", Nav([Page("P1",1), Page("P2",2)])), Page("Something else",3)]); } Bool isOpen(Nav menu, Int loc) { case menu of { Nav(l) -> list = l; } for thing in list { case thing of { Page(x,i) -> if (i==loc) { return true; } | SubMenu(n,m) -> return isOpen(m,loc); } } return false; } Void printMenu(Nav menu, Int indent, Int loc) { // Euw, better projection wanted! "menu.list" would be nicer. case menu of { Nav(l) -> list = l; } for thing in list { for(i=0;i putStr(x + " | " + String(i)); if (i==loc) { putStr(" <-- Here"); } putStr("\n"); | SubMenu(n,m) -> putStr(n + "...\n"); if (isOpen(m,loc)) { printMenu(m,indent+1,loc); } } } } data Either = Left(a) | Right(b); data Unit = unit(); data Tree = leaf(a) | node(Tree,Tree); Void printList(List x) { case x of { cons(y,ys) -> putStrLn(String(y)+","); printList(ys); } } List append(List l, List r) { case l of { nil() -> return r; | cons(x,xs) -> return cons(x,module::append(xs,r)); } } List flatten(Tree x) { case x of { node(l,r) -> return module::append(flatten(l),flatten(r)); | leaf(z) -> return cons(z,nil()); } } data Cons = Con1(Int x) | Con2(Float y) | Con3(String z); Void doSomething(Cons c) { case c of { Con2(y) -> putStrLn("Float "+y); | _ -> putStrLn("Something else"); } } Void doNothing(Cons c) { case c of { _ -> putStrLn("Foo"); // Error? } } Void main() { printMenu(mainmenu(),0,2); doSomething(Con1(4)); doSomething(Con2(4.0)); doSomething(Con3("Four")); doNothing(Con1(4)); t = node(node(leaf(5),leaf(6)),node(leaf(6),leaf(7))); printList(flatten(t)); } kaya-0.4.4/tests/test005/expected0000644000175100017510000000074511170340767014656 0ustar cimcimCompiling program test005 Index | 0 More... P1 | 1 P2 | 2 <-- Here Something else | 3 Something else Float 4 Something else Foo 5, 6, 6, 7, Builtins::Missing_Case thrown at test005.k:72 test005::printList called from test005::printList at test005.k:74 test005::printList called from test005::printList at test005.k:74 test005::printList called from test005::printList at test005.k:74 test005::printList called from test005::printList at test005.k:74 test005::printList [entry point] kaya-0.4.4/tests/test005/run0000644000175100017510000000023711170340767013655 0ustar cimcim#!/bin/bash ../../compiler/kayac test005.k -L ../../rts -L ../../stdlib export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ./test005 rm -f test005 test005.exe kaya-0.4.4/tests/test057/0000755000175100017510000000000011170340770013125 5ustar cimcimkaya-0.4.4/tests/test057/test057a.k0000644000175100017510000000016011170340770014652 0ustar cimcimprogram test057a; Int foo(Int x, Int y) { return x+y; } Void main() { putStrLn(foo(3,4)+PI()+"\n"); } kaya-0.4.4/tests/test057/test057b.k0000644000175100017510000000075411170340770014664 0ustar cimcimprogram test057b; // Constant propagation and inlining Int foo(Int x, Int y) { z = 5*x; // No inlining because of z return z+y; } Int bar(Int x, Int y) { return x+y; } Void main() { z = 3; y = z+2; // First bar is inlined with constants propagated // Second bar is merely inlined, because we can't know what foo has // done to z and y. (At least, for now, we don't check if they are // var arguments). putStrLn(bar(z,y)+foo(z,y)+bar(z,y)+"\n"); } kaya-0.4.4/tests/test057/expected0000644000175100017510000000175211170340770014656 0ustar cimcimCompiling program test057a Void test057a::__start () { Exception err; Exception <"catchall"0>; try { test057a::main() } catch(err) { Builtins::exceptionBacktrace(err) } } Void test057a::__panic (String err, Int code) { pass; } Void test057a::main () { Prelude::putStrLn((String(10.141592653589793) + "\n")) } Int test057a::foo (Int x, Int y) { return (x + y); } Void test057a::__init NOINIT Compiling program test057b Void test057b::__start () { Exception err; Exception <"catchall"0>; try { test057b::main() } catch(err) { Builtins::exceptionBacktrace(err) } } Void test057b::__panic (String err, Int code) { pass; } Void test057b::main () { Int z; Int y; z = 3; y = 5; Prelude::putStrLn((String(((8 + test057b::foo(z, y)) + (z + y))) + "\n")) } Int test057b::bar (Int x, Int y) { return (x + y); } Int test057b::foo (Int x, Int y) { Int z; pass; return ((5 * x) + y); } Void test057b::__init NOINIT 10.1416 36 kaya-0.4.4/tests/test057/run0000644000175100017510000000042011170340770013650 0ustar cimcim#!/bin/bash LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../rts/ ../../compiler/kayac test057a.k -dumpsimpl -L ../../rts -L ../../stdlib ../../compiler/kayac test057b.k -dumpsimpl -L ../../rts -L ../../stdlib ./test057a ./test057b rm -f test057a test057a.exe test057b test057b.exe kaya-0.4.4/tests/test026/0000755000175100017510000000000011170340767013127 5ustar cimcimkaya-0.4.4/tests/test026/test026.k0000644000175100017510000000100011170340764014476 0ustar cimcimprogram test026; Bool a_se(Int x) { putStrLn("Evaluating a"); return (x==5); } Bool b_se(Int x) { putStrLn("Evaluating b"); return (x==5); } Void main() { a=100; b=50; c=200; d = (a==100 && b<100); e = (a*2 == c || b>c); f = (a==b || c/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : (as_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell autoconf@gnu.org about your system, echo including any error possibly output before this echo message } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="compiler/Main.hs" ac_default_prefix=~ # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datarootdir datadir sysconfdir sharedstatedir localstatedir includedir oldincludedir docdir infodir htmldir dvidir pdfdir psdir libdir localedir mandir DEFS ECHO_C ECHO_N ECHO_T LIBS build_alias host_alias target_alias GHC HAPPY LANGNAME TARGET EXT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP GREP EGREP ac_cv_sizeof_voidp ac_cv_sizeof_int ac_cv_sizeof_long ac_cv_sizeof_long_long KAYAPROF INTERPROF GHCOPTS LIBTOOL BENCHTIMER CXX CXXFLAGS ac_ct_CXX platform NETLIB PATHSEP EXECUTABLE POSIXMAN FPIC KLIBDIR GTOD_INTERNAL HASUTF8 CXXCPP PGOBJS PGSTUB PGMAN PGIFACE PGINC MYOBJS MYSTUB MYIFACE MYINC MYMAN SQLOBJS SQLSTUB SQLIFACE SQLIMAN SQLINC GDMAN GDOBJS GDIFACE SDLOBJS SDLIFACE SDLMAN GLOBJS GLIFACE CURSESWOBJS CURSESWIFACE CURSESWMAN CURSESOBJS CURSESIFACE CURSESMAN KAYIFACE KAYOBJ KAYMAN THREADSMAN THREADSOBJS THREADSIFACE GCCBINOPTS GCCDYNOPTS EXTRAGCCOPTS readlinemodule tmpdir version portmod packages showtupleon showtupleoff unameS unameM LIBOBJS LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias host_alias target_alias GHC HAPPY CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP CXX CXXFLAGS CCC CXXCPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=\$ac_optarg ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute directory names. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || { echo "$as_me: error: Working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$0" || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-debug Add debugging symbols --enable-profile Compile kayac, run-time system and standard library with profiling --disable-postgres Disable Postgres database support --disable-mysql Disable MySQL database support --disable-sqlite Disable SQLite database support --disable-gd Disable GD graphics library --disable-sdl Disable SDL media library --disable-opengl Disable OpenGL 3D library --disable-ncursesw Disable nCurses wide console libraries --disable-curses Disable Curses console libraries Some influential environment variables: GHC Haskell compiler to use HAPPY Parser generator CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then set x "$CONFIG_SITE" elif test "x$prefix" != xNONE; then set x "$prefix/share/config.site" "$prefix/etc/config.site" else set x "$ac_default_prefix/share/config.site" \ "$ac_default_prefix/etc/config.site" fi shift for ac_site_file do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # AC_ARG_VAR(GHCI,[Haskell interpereter to use]) LANGNAME=kaya TARGET=kayac EXT=k ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # # List of possible output files, starting from the most likely. # The algorithm is not robust to junk in `.', hence go to wildcards (a.*) # only as a last resort. b.out is created by i960 compilers. ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' # # The IRIX 6 linker writes into existing files which may not be # executable, retaining their permissions. Remove them first so a # subsequent execution test works. ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { (ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi { echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6; } if test -z "$ac_file"; then echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } { echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6; } { echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext { echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT { echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6; } ;; xno) { echo "$as_me:$LINENO: result: unsupported" >&5 echo "${ECHO_T}unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Extract the first word of "grep ggrep" to use in msg output if test -z "$GREP"; then set dummy grep ggrep; ac_prog_name=$2 if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS fi GREP="$ac_cv_path_GREP" if test -z "$GREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_GREP=$GREP fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 echo "${ECHO_T}$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else # Extract the first word of "egrep" to use in msg output if test -z "$EGREP"; then set dummy egrep; ac_prog_name=$2 if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS fi EGREP="$ac_cv_path_EGREP" if test -z "$EGREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_EGREP=$EGREP fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { echo "$as_me:$LINENO: checking for void*" >&5 echo $ECHO_N "checking for void*... $ECHO_C" >&6; } if test "${ac_cv_type_voidp+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef void* ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_voidp=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_voidp=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_voidp" >&5 echo "${ECHO_T}$ac_cv_type_voidp" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of void*" >&5 echo $ECHO_N "checking size of void*... $ECHO_C" >&6; } if test "${ac_cv_sizeof_voidp+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef void* ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef void* ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef void* ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef void* ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef void* ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_voidp=$ac_lo;; '') if test "$ac_cv_type_voidp" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (void*) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (void*) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_voidp=0 fi ;; esac else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef void* ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_voidp=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$ac_cv_type_voidp" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (void*) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (void*) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_voidp=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_voidp" >&5 echo "${ECHO_T}$ac_cv_sizeof_voidp" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_VOIDP $ac_cv_sizeof_voidp _ACEOF { echo "$as_me:$LINENO: checking for int" >&5 echo $ECHO_N "checking for int... $ECHO_C" >&6; } if test "${ac_cv_type_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_int=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_int=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5 echo "${ECHO_T}$ac_cv_type_int" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of int" >&5 echo $ECHO_N "checking size of int... $ECHO_C" >&6; } if test "${ac_cv_sizeof_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_int=$ac_lo;; '') if test "$ac_cv_type_int" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (int) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_int=0 fi ;; esac else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef int ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_int=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$ac_cv_type_int" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (int) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_int=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 echo "${ECHO_T}$ac_cv_sizeof_int" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_INT $ac_cv_sizeof_int _ACEOF { echo "$as_me:$LINENO: checking for long" >&5 echo $ECHO_N "checking for long... $ECHO_C" >&6; } if test "${ac_cv_type_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_long=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5 echo "${ECHO_T}$ac_cv_type_long" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of long" >&5 echo $ECHO_N "checking size of long... $ECHO_C" >&6; } if test "${ac_cv_sizeof_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_long=$ac_lo;; '') if test "$ac_cv_type_long" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (long) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_long=0 fi ;; esac else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_long=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$ac_cv_type_long" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (long) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_long=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 echo "${ECHO_T}$ac_cv_sizeof_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG $ac_cv_sizeof_long _ACEOF { echo "$as_me:$LINENO: checking for long long" >&5 echo $ECHO_N "checking for long long... $ECHO_C" >&6; } if test "${ac_cv_type_long_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_long_long=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_long_long=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5 echo "${ECHO_T}$ac_cv_type_long_long" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { echo "$as_me:$LINENO: checking size of long long" >&5 echo $ECHO_N "checking size of long long... $ECHO_C" >&6; } if test "${ac_cv_sizeof_long_long+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; int main () { static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_long_long=$ac_lo;; '') if test "$ac_cv_type_long_long" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long long) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_long_long=0 fi ;; esac else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef long long ac__type_sizeof_; static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (((long int) (sizeof (ac__type_sizeof_))) < 0) { long int i = longval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%ld\n", i); } else { unsigned long int i = ulongval (); if (i != ((long int) (sizeof (ac__type_sizeof_)))) return 1; fprintf (f, "%lu\n", i); } return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_long_long=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$ac_cv_type_long_long" = yes; then { { echo "$as_me:$LINENO: error: cannot compute sizeof (long long) See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (long long) See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } else ac_cv_sizeof_long_long=0 fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.val fi { echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5 echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long _ACEOF # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then enableval=$enable_debug; CXXFLAGS="-g -O0 -Wall -Wno-deprecated"; KAYAPROF="-g -O0"; INTERPROF="-g -O0"; GHCOPTS=""; else CXXFLAGS="-Wall -O2 -DNDEBUG -Wno-deprecated"; INTERPROF="-O2"; if test $ac_cv_sizeof_voidp = 4 ; then GHCOPTS="-O"; else GHCOPTS=""; fi fi # Check whether --enable-profile was given. if test "${enable_profile+set}" = set; then enableval=$enable_profile; CXXFLAGS="-Wall -DNDEBUG -pg"; KAYAPROF="-profile"; INTERPROF="-pg -O2"; GHCOPTS="-prof -auto-all"; fi { # Extract the first word of "ghc", so it can be a program name with args. set dummy ghc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_path_GHC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $GHC in [\\/]* | ?:[\\/]*) ac_cv_path_GHC="$GHC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_GHC="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi GHC=$ac_cv_path_GHC if test -n "$GHC"; then { echo "$as_me:$LINENO: result: $GHC" >&5 echo "${ECHO_T}$GHC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$GHC" || { { echo "$as_me:$LINENO: error: Can't find ghc" >&5 echo "$as_me: error: Can't find ghc" >&2;} { (exit 1); exit 1; }; } } # KAYA_MOO([GHCI],[ghci]) { # Extract the first word of "happy", so it can be a program name with args. set dummy happy; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_path_HAPPY+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $HAPPY in [\\/]* | ?:[\\/]*) ac_cv_path_HAPPY="$HAPPY" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_HAPPY="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi HAPPY=$ac_cv_path_HAPPY if test -n "$HAPPY"; then { echo "$as_me:$LINENO: result: $HAPPY" >&5 echo "${ECHO_T}$HAPPY" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$HAPPY" || { { echo "$as_me:$LINENO: error: Can't find happy" >&5 echo "$as_me: error: Can't find happy" >&2;} { (exit 1); exit 1; }; } } if ghc-pkg list | grep mtl- > /dev/null ; then { echo "$as_me:$LINENO: Found Haskell MTL package" >&5 echo "$as_me: Found Haskell MTL package" >&6;} else { { echo "$as_me:$LINENO: error: Can't find Haskell MTL package" >&5 echo "$as_me: error: Can't find Haskell MTL package" >&2;} { (exit 1); exit 1; }; } fi { # Extract the first word of "libtool", so it can be a program name with args. set dummy libtool; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_path_LIBTOOL+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $LIBTOOL in [\\/]* | ?:[\\/]*) ac_cv_path_LIBTOOL="$LIBTOOL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_LIBTOOL="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi LIBTOOL=$ac_cv_path_LIBTOOL if test -n "$LIBTOOL"; then { echo "$as_me:$LINENO: result: $LIBTOOL" >&5 echo "${ECHO_T}$LIBTOOL" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$LIBTOOL" || { echo "$as_me:$LINENO: Can't find libtool: needed for static linking with kayac -static" >&5 echo "$as_me: Can't find libtool: needed for static linking with kayac -static" >&6;} } # Extract the first word of "time", so it can be a program name with args. set dummy time; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_path_BENCHTIMER+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $BENCHTIMER in [\\/]* | ?:[\\/]*) ac_cv_path_BENCHTIMER="$BENCHTIMER" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_BENCHTIMER="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi BENCHTIMER=$ac_cv_path_BENCHTIMER if test -n "$BENCHTIMER"; then { echo "$as_me:$LINENO: result: $BENCHTIMER" >&5 echo "${ECHO_T}$BENCHTIMER" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { echo "$as_me:$LINENO: result: $CXX" >&5 echo "${ECHO_T}$CXX" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CXX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 echo "${ECHO_T}$ac_ct_CXX" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C++ compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } if test "${ac_cv_cxx_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } GXX=`test $ac_compiler_gnu = yes && echo yes` ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cxx_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CXXFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ####### Platform detection ############################# unameS=`uname -s` unameM=`uname -m` platform="" { echo "$as_me:$LINENO: checking for fork" >&5 echo $ECHO_N "checking for fork... $ECHO_C" >&6; } if test "${ac_cv_func_fork+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define fork to an innocuous variant, in case declares fork. For example, HP-UX 11i declares gettimeofday. */ #define fork innocuous_fork /* System header to define __stub macros and hopefully few prototypes, which can conflict with char fork (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef fork /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char fork (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_fork || defined __stub___fork choke me #endif int main () { return fork (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_fork=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_fork=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_fork" >&5 echo "${ECHO_T}$ac_cv_func_fork" >&6; } if test $ac_cv_func_fork = yes; then platform="posix" ; { echo "$as_me:$LINENO: Using Posix" >&5 echo "$as_me: Using Posix" >&6;} NETLIB="// "; PATHSEP=":"; EXECUTABLE=""; POSIXMAN="Syslog.posix ServerLoop.posix Posix.posix Sockets.posix SCGI.posix Signal.posix"; GCCBINOPTS="-Wl,-zrelro -fPIC"; ## 64-bit architectures seem to have problems with -pie and -lgc together ## Even on 32-bit there's problems with debugging. Maybe later... # if (test $ac_cv_sizeof_voidp != "8"); then # FPIC="-fPIC -fPIE"; # GCCDYNOPTS="-pie"; # AC_MSG_NOTICE([Using position independent executables]) # else FPIC="-fPIC"; GCCDYNOPTS=""; # AC_MSG_NOTICE([Not using position independent executables]) # fi else platform="windows" ; { echo "$as_me:$LINENO: Using Windows" >&5 echo "$as_me: Using Windows" >&6;} NETLIB=""; PATHSEP=";"; EXECUTABLE=".exe"; POSIXMAN=""; FPIC=""; GCCBINOPTS=""; GCCDYNOPTS=""; fi if test "$libdir" == '${exec_prefix}/lib' ; then if test "x$exec_prefix" = xNONE ; then if test "x$prefix" = xNONE ; then KLIBDIR=${ac_default_prefix}/lib else KLIBDIR=${prefix}/lib fi else KLIBDIR=${exec_prefix}/lib fi else KLIBDIR=$libdir fi #### Essential Library checks ############################################ { echo "$as_me:$LINENO: checking for gettimeofday" >&5 echo $ECHO_N "checking for gettimeofday... $ECHO_C" >&6; } if test "${ac_cv_func_gettimeofday+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define gettimeofday to an innocuous variant, in case declares gettimeofday. For example, HP-UX 11i declares gettimeofday. */ #define gettimeofday innocuous_gettimeofday /* System header to define __stub macros and hopefully few prototypes, which can conflict with char gettimeofday (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef gettimeofday /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gettimeofday (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_gettimeofday || defined __stub___gettimeofday choke me #endif int main () { return gettimeofday (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_gettimeofday=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_gettimeofday=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_gettimeofday" >&5 echo "${ECHO_T}$ac_cv_func_gettimeofday" >&6; } if test $ac_cv_func_gettimeofday = yes; then GTOD_INTERNAL=0 else GTOD_INTERNAL=1 fi { echo "$as_me:$LINENO: checking for swprintf" >&5 echo $ECHO_N "checking for swprintf... $ECHO_C" >&6; } if test "${ac_cv_func_swprintf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define swprintf to an innocuous variant, in case declares swprintf. For example, HP-UX 11i declares gettimeofday. */ #define swprintf innocuous_swprintf /* System header to define __stub macros and hopefully few prototypes, which can conflict with char swprintf (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef swprintf /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char swprintf (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_swprintf || defined __stub___swprintf choke me #endif int main () { return swprintf (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_swprintf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_swprintf=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_swprintf" >&5 echo "${ECHO_T}$ac_cv_func_swprintf" >&6; } if test $ac_cv_func_swprintf = yes; then : else # for wchar_t support (detects Cygwin non-support) { { echo "$as_me:$LINENO: error: Can't find wide character support" >&5 echo "$as_me: error: Can't find wide character support" >&2;} { (exit 1); exit 1; }; } fi if test $platform = "posix" ; then { echo "$as_me:$LINENO: checking for __gmpz_init in -lgmp" >&5 echo $ECHO_N "checking for __gmpz_init in -lgmp... $ECHO_C" >&6; } if test "${ac_cv_lib_gmp___gmpz_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgmp $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char __gmpz_init (); int main () { return __gmpz_init (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_gmp___gmpz_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_gmp___gmpz_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_gmp___gmpz_init" >&5 echo "${ECHO_T}$ac_cv_lib_gmp___gmpz_init" >&6; } if test $ac_cv_lib_gmp___gmpz_init = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBGMP 1 _ACEOF LIBS="-lgmp $LIBS" else # for ghc linking { { echo "$as_me:$LINENO: error: Can't find libgmp." >&5 echo "$as_me: error: Can't find libgmp." >&2;} { (exit 1); exit 1; }; } fi fi { echo "$as_me:$LINENO: checking for GC_malloc in -lgc" >&5 echo $ECHO_N "checking for GC_malloc in -lgc... $ECHO_C" >&6; } if test "${ac_cv_lib_gc_GC_malloc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgc $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char GC_malloc (); int main () { return GC_malloc (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_gc_GC_malloc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_gc_GC_malloc=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_gc_GC_malloc" >&5 echo "${ECHO_T}$ac_cv_lib_gc_GC_malloc" >&6; } if test $ac_cv_lib_gc_GC_malloc = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBGC 1 _ACEOF LIBS="-lgc $LIBS" else # for garbage collection { { echo "$as_me:$LINENO: error: Can't find libgc" >&5 echo "$as_me: error: Can't find libgc" >&2;} { (exit 1); exit 1; }; } fi #AC_CHECK_LIB(cgi, cgi_init, [], # for cgi gadgetry # AC_MSG_ERROR([Can't find libcgi])) #AC_CHECK_HEADER([libcgi/cgi.h],[CGIINC="-I/usr/include/libcgi"], # [AC_CHECK_HEADER([cgi.h],[CGIINC=""])]) { echo "$as_me:$LINENO: checking for pcre_compile in -lpcre" >&5 echo $ECHO_N "checking for pcre_compile in -lpcre... $ECHO_C" >&6; } if test "${ac_cv_lib_pcre_pcre_compile+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcre $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pcre_compile (); int main () { return pcre_compile (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pcre_pcre_compile=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pcre_pcre_compile=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pcre_pcre_compile" >&5 echo "${ECHO_T}$ac_cv_lib_pcre_pcre_compile" >&6; } if test $ac_cv_lib_pcre_pcre_compile = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBPCRE 1 _ACEOF LIBS="-lpcre $LIBS" else # Perl compatible regular expressions { { echo "$as_me:$LINENO: error: Can't find libpcre" >&5 echo "$as_me: error: Can't find libpcre" >&2;} { (exit 1); exit 1; }; } fi if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { const char* errptr; int erroffset; pcre* p = pcre_compile("abc",PCRE_UTF8,&errptr,&erroffset,NULL); if (p == NULL) { exit(1); } else { exit(0); } ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then { echo "$as_me:$LINENO: libpcre has UTF-8 support" >&5 echo "$as_me: libpcre has UTF-8 support" >&6;} HASUTF8=""; else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { echo "$as_me:$LINENO: *********************************** WARNING ********************************** libpcre does not support UTF-8 characters. Attempting to use UTF-8 characters when matching regular expressions will throw an Exception. We recommend you use a version of libpcre that supports UTF-8 if possible. ******************************************************************************" >&5 echo "$as_me: *********************************** WARNING ********************************** libpcre does not support UTF-8 characters. Attempting to use UTF-8 characters when matching regular expressions will throw an Exception. We recommend you use a version of libpcre that supports UTF-8 if possible. ******************************************************************************" >&6;} HASUTF8="-DNOUTF8"; fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi #AC_CHECK_LIB(ssl, EVP_EncryptInit, [], # OpenSSL # AC_MSG_ERROR([Can't find libssl]), [-lcrypto]) { echo "$as_me:$LINENO: checking for gcry_cipher_open in -lgcrypt" >&5 echo $ECHO_N "checking for gcry_cipher_open in -lgcrypt... $ECHO_C" >&6; } if test "${ac_cv_lib_gcrypt_gcry_cipher_open+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgcrypt $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gcry_cipher_open (); int main () { return gcry_cipher_open (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_gcrypt_gcry_cipher_open=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_gcrypt_gcry_cipher_open=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_gcrypt_gcry_cipher_open" >&5 echo "${ECHO_T}$ac_cv_lib_gcrypt_gcry_cipher_open" >&6; } if test $ac_cv_lib_gcrypt_gcry_cipher_open = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBGCRYPT 1 _ACEOF LIBS="-lgcrypt $LIBS" else # for crypto { { echo "$as_me:$LINENO: error: Can't find libgcrypt" >&5 echo "$as_me: error: Can't find libgcrypt" >&2;} { (exit 1); exit 1; }; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } if test -z "$CXXCPP"; then if test "${ac_cv_prog_CXXCPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { echo "$as_me:$LINENO: result: $CXXCPP" >&5 echo "${ECHO_T}$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test "${ac_cv_header_zlib_h+set}" = set; then { echo "$as_me:$LINENO: checking for zlib.h" >&5 echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6; } if test "${ac_cv_header_zlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5 echo "${ECHO_T}$ac_cv_header_zlib_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking zlib.h usability" >&5 echo $ECHO_N "checking zlib.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking zlib.h presence" >&5 echo $ECHO_N "checking zlib.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: zlib.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: zlib.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: zlib.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: zlib.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: zlib.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: zlib.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: zlib.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: zlib.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: zlib.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for zlib.h" >&5 echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6; } if test "${ac_cv_header_zlib_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_zlib_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5 echo "${ECHO_T}$ac_cv_header_zlib_h" >&6; } fi { echo "$as_me:$LINENO: checking for compress in -lz" >&5 echo $ECHO_N "checking for compress in -lz... $ECHO_C" >&6; } if test "${ac_cv_lib_z_compress+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char compress (); int main () { return compress (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_z_compress=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_z_compress=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_z_compress" >&5 echo "${ECHO_T}$ac_cv_lib_z_compress" >&6; } if test $ac_cv_lib_z_compress = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" else { { echo "$as_me:$LINENO: error: Can't find zlib" >&5 echo "$as_me: error: Can't find zlib" >&2;} { (exit 1); exit 1; }; } fi # added 3/2/06 by CIM #AC_CHECK_LIB(gnutls, gnutls_global_init, [], # for crypto # AC_MSG_ERROR([Can't find libgnutls])) { echo "$as_me:$LINENO: checking for gnutls_global_init in -lgnutls" >&5 echo $ECHO_N "checking for gnutls_global_init in -lgnutls... $ECHO_C" >&6; } if test "${ac_cv_lib_gnutls_gnutls_global_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnutls $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gnutls_global_init (); int main () { return gnutls_global_init (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_gnutls_gnutls_global_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_gnutls_gnutls_global_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_gnutls_gnutls_global_init" >&5 echo "${ECHO_T}$ac_cv_lib_gnutls_gnutls_global_init" >&6; } if test $ac_cv_lib_gnutls_gnutls_global_init = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBGNUTLS 1 _ACEOF LIBS="-lgnutls $LIBS" else { { echo "$as_me:$LINENO: error: Can't find gnutls" >&5 echo "$as_me: error: Can't find gnutls" >&2;} { (exit 1); exit 1; }; } fi #AC_SUBST(CGIINC) ####### Optional libraries ############################# # PostgreSQL PGOBJS="" PGIFACE="" PGMAN="" PGINC="" # Check whether --enable-postgres was given. if test "${enable_postgres+set}" = set; then enableval=$enable_postgres; if test "$enableval" = "yes"; then if test "${ac_cv_header_postgresql_libpq_fe_h+set}" = set; then { echo "$as_me:$LINENO: checking for postgresql/libpq-fe.h" >&5 echo $ECHO_N "checking for postgresql/libpq-fe.h... $ECHO_C" >&6; } if test "${ac_cv_header_postgresql_libpq_fe_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_postgresql_libpq_fe_h" >&5 echo "${ECHO_T}$ac_cv_header_postgresql_libpq_fe_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking postgresql/libpq-fe.h usability" >&5 echo $ECHO_N "checking postgresql/libpq-fe.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking postgresql/libpq-fe.h presence" >&5 echo $ECHO_N "checking postgresql/libpq-fe.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for postgresql/libpq-fe.h" >&5 echo $ECHO_N "checking for postgresql/libpq-fe.h... $ECHO_C" >&6; } if test "${ac_cv_header_postgresql_libpq_fe_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_postgresql_libpq_fe_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_postgresql_libpq_fe_h" >&5 echo "${ECHO_T}$ac_cv_header_postgresql_libpq_fe_h" >&6; } fi if test $ac_cv_header_postgresql_libpq_fe_h = yes; then PGINC="-I/usr/include/postgresql" fi { echo "$as_me:$LINENO: checking for PQconnectdb in -lpq" >&5 echo $ECHO_N "checking for PQconnectdb in -lpq... $ECHO_C" >&6; } if test "${ac_cv_lib_pq_PQconnectdb+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpq $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char PQconnectdb (); int main () { return PQconnectdb (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pq_PQconnectdb=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pq_PQconnectdb=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pq_PQconnectdb" >&5 echo "${ECHO_T}$ac_cv_lib_pq_PQconnectdb" >&6; } if test $ac_cv_lib_pq_PQconnectdb = yes; then PGSTUB="" PGMAN="PostgresDB.libs" PGOBJS="pg_inter.o PostgresDB.o" PGIFACE="PostgresDB.ki" else { echo "$as_me:$LINENO: Cannot find libpq, not compiling in postgres support" >&5 echo "$as_me: Cannot find libpq, not compiling in postgres support" >&6;} PGSTUB="_stub" PGOBJS="PostgresDB.o" PGIFACE="PostgresDB.ki" fi fi else if test "${ac_cv_header_postgresql_libpq_fe_h+set}" = set; then { echo "$as_me:$LINENO: checking for postgresql/libpq-fe.h" >&5 echo $ECHO_N "checking for postgresql/libpq-fe.h... $ECHO_C" >&6; } if test "${ac_cv_header_postgresql_libpq_fe_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_postgresql_libpq_fe_h" >&5 echo "${ECHO_T}$ac_cv_header_postgresql_libpq_fe_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking postgresql/libpq-fe.h usability" >&5 echo $ECHO_N "checking postgresql/libpq-fe.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking postgresql/libpq-fe.h presence" >&5 echo $ECHO_N "checking postgresql/libpq-fe.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: postgresql/libpq-fe.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: postgresql/libpq-fe.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for postgresql/libpq-fe.h" >&5 echo $ECHO_N "checking for postgresql/libpq-fe.h... $ECHO_C" >&6; } if test "${ac_cv_header_postgresql_libpq_fe_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_postgresql_libpq_fe_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_postgresql_libpq_fe_h" >&5 echo "${ECHO_T}$ac_cv_header_postgresql_libpq_fe_h" >&6; } fi if test $ac_cv_header_postgresql_libpq_fe_h = yes; then PGINC="-I/usr/include/postgresql" fi { echo "$as_me:$LINENO: checking for PQconnectdb in -lpq" >&5 echo $ECHO_N "checking for PQconnectdb in -lpq... $ECHO_C" >&6; } if test "${ac_cv_lib_pq_PQconnectdb+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpq $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char PQconnectdb (); int main () { return PQconnectdb (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pq_PQconnectdb=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pq_PQconnectdb=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pq_PQconnectdb" >&5 echo "${ECHO_T}$ac_cv_lib_pq_PQconnectdb" >&6; } if test $ac_cv_lib_pq_PQconnectdb = yes; then PGSTUB="" PGMAN="PostgresDB.libs" PGOBJS="pg_inter.o PostgresDB.o" PGIFACE="PostgresDB.ki" else { echo "$as_me:$LINENO: Cannot find libpq, not compiling in postgres support" >&5 echo "$as_me: Cannot find libpq, not compiling in postgres support" >&6;} PGSTUB="_stub" PGOBJS="PostgresDB.o" PGIFACE="PostgresDB.ki" fi fi # MySQL MYOBJS="" MYIFACE="" MYMAN="" MYINC="" # Check whether --enable-mysql was given. if test "${enable_mysql+set}" = set; then enableval=$enable_mysql; if test "$enableval" = "yes"; then if test "${ac_cv_header_mysql_mysql_h+set}" = set; then { echo "$as_me:$LINENO: checking for mysql/mysql.h" >&5 echo $ECHO_N "checking for mysql/mysql.h... $ECHO_C" >&6; } if test "${ac_cv_header_mysql_mysql_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_mysql_mysql_h" >&5 echo "${ECHO_T}$ac_cv_header_mysql_mysql_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking mysql/mysql.h usability" >&5 echo $ECHO_N "checking mysql/mysql.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking mysql/mysql.h presence" >&5 echo $ECHO_N "checking mysql/mysql.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: mysql/mysql.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: mysql/mysql.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: mysql/mysql.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: mysql/mysql.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: mysql/mysql.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: mysql/mysql.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: mysql/mysql.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: mysql/mysql.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for mysql/mysql.h" >&5 echo $ECHO_N "checking for mysql/mysql.h... $ECHO_C" >&6; } if test "${ac_cv_header_mysql_mysql_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_mysql_mysql_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_mysql_mysql_h" >&5 echo "${ECHO_T}$ac_cv_header_mysql_mysql_h" >&6; } fi { echo "$as_me:$LINENO: checking for mysql_init in -lmysqlclient" >&5 echo $ECHO_N "checking for mysql_init in -lmysqlclient... $ECHO_C" >&6; } if test "${ac_cv_lib_mysqlclient_mysql_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmysqlclient $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mysql_init (); int main () { return mysql_init (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_mysqlclient_mysql_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_mysqlclient_mysql_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_mysqlclient_mysql_init" >&5 echo "${ECHO_T}$ac_cv_lib_mysqlclient_mysql_init" >&6; } if test $ac_cv_lib_mysqlclient_mysql_init = yes; then { echo "$as_me:$LINENO: Found libmysqlclient, is it recent enough?" >&5 echo "$as_me: Found libmysqlclient, is it recent enough?" >&6;} { echo "$as_me:$LINENO: checking for mysql_stmt_init in -lmysqlclient" >&5 echo $ECHO_N "checking for mysql_stmt_init in -lmysqlclient... $ECHO_C" >&6; } if test "${ac_cv_lib_mysqlclient_mysql_stmt_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmysqlclient $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mysql_stmt_init (); int main () { return mysql_stmt_init (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_mysqlclient_mysql_stmt_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_mysqlclient_mysql_stmt_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_mysqlclient_mysql_stmt_init" >&5 echo "${ECHO_T}$ac_cv_lib_mysqlclient_mysql_stmt_init" >&6; } if test $ac_cv_lib_mysqlclient_mysql_stmt_init = yes; then MYSTUB="" MYMAN="MyDB.libs" MYOBJS="my_inter.o MyDB.o" MYIFACE="MyDB.ki" else { echo "$as_me:$LINENO: libmysqlclient is too old, not compiling in mysql support" >&5 echo "$as_me: libmysqlclient is too old, not compiling in mysql support" >&6;} MYOBJS="MyDB.o" MYIFACE="MyDB.ki" MYSTUB="_stub" fi else { echo "$as_me:$LINENO: No libmysqlclient, not compiling in mysql support" >&5 echo "$as_me: No libmysqlclient, not compiling in mysql support" >&6;} MYOBJS="MyDB.o" MYIFACE="MyDB.ki" MYSTUB="_stub" fi fi else if test "${ac_cv_header_mysql_mysql_h+set}" = set; then { echo "$as_me:$LINENO: checking for mysql/mysql.h" >&5 echo $ECHO_N "checking for mysql/mysql.h... $ECHO_C" >&6; } if test "${ac_cv_header_mysql_mysql_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_mysql_mysql_h" >&5 echo "${ECHO_T}$ac_cv_header_mysql_mysql_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking mysql/mysql.h usability" >&5 echo $ECHO_N "checking mysql/mysql.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking mysql/mysql.h presence" >&5 echo $ECHO_N "checking mysql/mysql.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: mysql/mysql.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: mysql/mysql.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: mysql/mysql.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: mysql/mysql.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: mysql/mysql.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: mysql/mysql.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: mysql/mysql.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: mysql/mysql.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: mysql/mysql.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for mysql/mysql.h" >&5 echo $ECHO_N "checking for mysql/mysql.h... $ECHO_C" >&6; } if test "${ac_cv_header_mysql_mysql_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_mysql_mysql_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_mysql_mysql_h" >&5 echo "${ECHO_T}$ac_cv_header_mysql_mysql_h" >&6; } fi { echo "$as_me:$LINENO: checking for mysql_init in -lmysqlclient" >&5 echo $ECHO_N "checking for mysql_init in -lmysqlclient... $ECHO_C" >&6; } if test "${ac_cv_lib_mysqlclient_mysql_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmysqlclient $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mysql_init (); int main () { return mysql_init (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_mysqlclient_mysql_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_mysqlclient_mysql_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_mysqlclient_mysql_init" >&5 echo "${ECHO_T}$ac_cv_lib_mysqlclient_mysql_init" >&6; } if test $ac_cv_lib_mysqlclient_mysql_init = yes; then { echo "$as_me:$LINENO: Found libmysqlclient, is it recent enough?" >&5 echo "$as_me: Found libmysqlclient, is it recent enough?" >&6;} { echo "$as_me:$LINENO: checking for mysql_stmt_init in -lmysqlclient" >&5 echo $ECHO_N "checking for mysql_stmt_init in -lmysqlclient... $ECHO_C" >&6; } if test "${ac_cv_lib_mysqlclient_mysql_stmt_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmysqlclient $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mysql_stmt_init (); int main () { return mysql_stmt_init (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_mysqlclient_mysql_stmt_init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_mysqlclient_mysql_stmt_init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_mysqlclient_mysql_stmt_init" >&5 echo "${ECHO_T}$ac_cv_lib_mysqlclient_mysql_stmt_init" >&6; } if test $ac_cv_lib_mysqlclient_mysql_stmt_init = yes; then MYSTUB="" MYMAN="MyDB.libs" MYOBJS="my_inter.o MyDB.o" MYIFACE="MyDB.ki" else { echo "$as_me:$LINENO: libmysqlclient is too old, not compiling in mysql support" >&5 echo "$as_me: libmysqlclient is too old, not compiling in mysql support" >&6;} MYOBJS="MyDB.o" MYIFACE="MyDB.ki" MYSTUB="_stub" fi else { echo "$as_me:$LINENO: No libmysqlclient, not compiling in mysql support" >&5 echo "$as_me: No libmysqlclient, not compiling in mysql support" >&6;} MYOBJS="MyDB.o" MYIFACE="MyDB.ki" MYSTUB="_stub" fi fi # SQLite 3 SQLOBJS="" SQLIFACE="" SQLINC="" SQLIMAN="" # Check whether --enable-sqlite was given. if test "${enable_sqlite+set}" = set; then enableval=$enable_sqlite; if test "$enableval" = "yes"; then if test "${ac_cv_header_sqlite3_h+set}" = set; then { echo "$as_me:$LINENO: checking for sqlite3.h" >&5 echo $ECHO_N "checking for sqlite3.h... $ECHO_C" >&6; } if test "${ac_cv_header_sqlite3_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_sqlite3_h" >&5 echo "${ECHO_T}$ac_cv_header_sqlite3_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking sqlite3.h usability" >&5 echo $ECHO_N "checking sqlite3.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking sqlite3.h presence" >&5 echo $ECHO_N "checking sqlite3.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sqlite3.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sqlite3.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sqlite3.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sqlite3.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sqlite3.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sqlite3.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sqlite3.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sqlite3.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sqlite3.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sqlite3.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for sqlite3.h" >&5 echo $ECHO_N "checking for sqlite3.h... $ECHO_C" >&6; } if test "${ac_cv_header_sqlite3_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sqlite3_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_sqlite3_h" >&5 echo "${ECHO_T}$ac_cv_header_sqlite3_h" >&6; } fi { echo "$as_me:$LINENO: checking for sqlite3_open in -lsqlite3" >&5 echo $ECHO_N "checking for sqlite3_open in -lsqlite3... $ECHO_C" >&6; } if test "${ac_cv_lib_sqlite3_sqlite3_open+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsqlite3 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sqlite3_open (); int main () { return sqlite3_open (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_sqlite3_sqlite3_open=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_sqlite3_sqlite3_open=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_sqlite3_sqlite3_open" >&5 echo "${ECHO_T}$ac_cv_lib_sqlite3_sqlite3_open" >&6; } if test $ac_cv_lib_sqlite3_sqlite3_open = yes; then SQLSTUB="" SQLIMAN="SQLiteDB.libs" SQLOBJS="sqlite_inter.o SQLiteDB.o" SQLIFACE="SQLiteDB.ki" else { echo "$as_me:$LINENO: No libsqlite3, not compiling in SQLite support" >&5 echo "$as_me: No libsqlite3, not compiling in SQLite support" >&6;} SQLOBJS="SQLiteDB.o" SQLIFACE="SQLiteDB.ki" SQLSTUB="_stub" fi fi else if test "${ac_cv_header_sqlite3_h+set}" = set; then { echo "$as_me:$LINENO: checking for sqlite3.h" >&5 echo $ECHO_N "checking for sqlite3.h... $ECHO_C" >&6; } if test "${ac_cv_header_sqlite3_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_sqlite3_h" >&5 echo "${ECHO_T}$ac_cv_header_sqlite3_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking sqlite3.h usability" >&5 echo $ECHO_N "checking sqlite3.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking sqlite3.h presence" >&5 echo $ECHO_N "checking sqlite3.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sqlite3.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sqlite3.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sqlite3.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sqlite3.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sqlite3.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sqlite3.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sqlite3.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sqlite3.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sqlite3.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sqlite3.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sqlite3.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for sqlite3.h" >&5 echo $ECHO_N "checking for sqlite3.h... $ECHO_C" >&6; } if test "${ac_cv_header_sqlite3_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sqlite3_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_sqlite3_h" >&5 echo "${ECHO_T}$ac_cv_header_sqlite3_h" >&6; } fi { echo "$as_me:$LINENO: checking for sqlite3_open in -lsqlite3" >&5 echo $ECHO_N "checking for sqlite3_open in -lsqlite3... $ECHO_C" >&6; } if test "${ac_cv_lib_sqlite3_sqlite3_open+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsqlite3 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sqlite3_open (); int main () { return sqlite3_open (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_sqlite3_sqlite3_open=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_sqlite3_sqlite3_open=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_sqlite3_sqlite3_open" >&5 echo "${ECHO_T}$ac_cv_lib_sqlite3_sqlite3_open" >&6; } if test $ac_cv_lib_sqlite3_sqlite3_open = yes; then SQLSTUB="" SQLIMAN="SQLiteDB.libs" SQLOBJS="sqlite_inter.o SQLiteDB.o" SQLIFACE="SQLiteDB.ki" else { echo "$as_me:$LINENO: No libsqlite3, not compiling in SQLite support" >&5 echo "$as_me: No libsqlite3, not compiling in SQLite support" >&6;} SQLOBJS="SQLiteDB.o" SQLIFACE="SQLiteDB.ki" SQLSTUB="_stub" fi fi # GD GDOBJS="" GDIFACE="" GDMAN="" # Check whether --enable-gd was given. if test "${enable_gd+set}" = set; then enableval=$enable_gd; if test "$enableval" = "yes"; then if test "${ac_cv_header_gd_h+set}" = set; then { echo "$as_me:$LINENO: checking for gd.h" >&5 echo $ECHO_N "checking for gd.h... $ECHO_C" >&6; } if test "${ac_cv_header_gd_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_gd_h" >&5 echo "${ECHO_T}$ac_cv_header_gd_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking gd.h usability" >&5 echo $ECHO_N "checking gd.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking gd.h presence" >&5 echo $ECHO_N "checking gd.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: gd.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: gd.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: gd.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: gd.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: gd.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: gd.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: gd.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: gd.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: gd.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: gd.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for gd.h" >&5 echo $ECHO_N "checking for gd.h... $ECHO_C" >&6; } if test "${ac_cv_header_gd_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_gd_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_gd_h" >&5 echo "${ECHO_T}$ac_cv_header_gd_h" >&6; } fi { echo "$as_me:$LINENO: checking for gdImageCreate in -lgd" >&5 echo $ECHO_N "checking for gdImageCreate in -lgd... $ECHO_C" >&6; } if test "${ac_cv_lib_gd_gdImageCreate+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgd $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gdImageCreate (); int main () { return gdImageCreate (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_gd_gdImageCreate=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_gd_gdImageCreate=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_gd_gdImageCreate" >&5 echo "${ECHO_T}$ac_cv_lib_gd_gdImageCreate" >&6; } if test $ac_cv_lib_gd_gdImageCreate = yes; then { echo "$as_me:$LINENO: Found libgd, is it recent enough?" >&5 echo "$as_me: Found libgd, is it recent enough?" >&6;} { echo "$as_me:$LINENO: checking for gdImageCreateTrueColor in -lgd" >&5 echo $ECHO_N "checking for gdImageCreateTrueColor in -lgd... $ECHO_C" >&6; } if test "${ac_cv_lib_gd_gdImageCreateTrueColor+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgd $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gdImageCreateTrueColor (); int main () { return gdImageCreateTrueColor (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_gd_gdImageCreateTrueColor=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_gd_gdImageCreateTrueColor=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_gd_gdImageCreateTrueColor" >&5 echo "${ECHO_T}$ac_cv_lib_gd_gdImageCreateTrueColor" >&6; } if test $ac_cv_lib_gd_gdImageCreateTrueColor = yes; then GDOBJS="Image.o image_glue.o" GDIFACE="Image.ki" GDMAN="Image.libs" else { echo "$as_me:$LINENO: libgd is too old, not compiling in image support" >&5 echo "$as_me: libgd is too old, not compiling in image support" >&6;} fi else { echo "$as_me:$LINENO: Can't find libgd, not compiling in image support" >&5 echo "$as_me: Can't find libgd, not compiling in image support" >&6;} fi fi else if test "${ac_cv_header_gd_h+set}" = set; then { echo "$as_me:$LINENO: checking for gd.h" >&5 echo $ECHO_N "checking for gd.h... $ECHO_C" >&6; } if test "${ac_cv_header_gd_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_gd_h" >&5 echo "${ECHO_T}$ac_cv_header_gd_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking gd.h usability" >&5 echo $ECHO_N "checking gd.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking gd.h presence" >&5 echo $ECHO_N "checking gd.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: gd.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: gd.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: gd.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: gd.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: gd.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: gd.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: gd.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: gd.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: gd.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: gd.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: gd.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for gd.h" >&5 echo $ECHO_N "checking for gd.h... $ECHO_C" >&6; } if test "${ac_cv_header_gd_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_gd_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_gd_h" >&5 echo "${ECHO_T}$ac_cv_header_gd_h" >&6; } fi { echo "$as_me:$LINENO: checking for gdImageCreate in -lgd" >&5 echo $ECHO_N "checking for gdImageCreate in -lgd... $ECHO_C" >&6; } if test "${ac_cv_lib_gd_gdImageCreate+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgd $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gdImageCreate (); int main () { return gdImageCreate (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_gd_gdImageCreate=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_gd_gdImageCreate=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_gd_gdImageCreate" >&5 echo "${ECHO_T}$ac_cv_lib_gd_gdImageCreate" >&6; } if test $ac_cv_lib_gd_gdImageCreate = yes; then { echo "$as_me:$LINENO: Found libgd, is it recent enough?" >&5 echo "$as_me: Found libgd, is it recent enough?" >&6;} { echo "$as_me:$LINENO: checking for gdImageCreateTrueColor in -lgd" >&5 echo $ECHO_N "checking for gdImageCreateTrueColor in -lgd... $ECHO_C" >&6; } if test "${ac_cv_lib_gd_gdImageCreateTrueColor+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgd $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gdImageCreateTrueColor (); int main () { return gdImageCreateTrueColor (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_gd_gdImageCreateTrueColor=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_gd_gdImageCreateTrueColor=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_gd_gdImageCreateTrueColor" >&5 echo "${ECHO_T}$ac_cv_lib_gd_gdImageCreateTrueColor" >&6; } if test $ac_cv_lib_gd_gdImageCreateTrueColor = yes; then GDOBJS="Image.o image_glue.o" GDIFACE="Image.ki" GDMAN="Image.libs" else { echo "$as_me:$LINENO: libgd is too old, not compiling in image support" >&5 echo "$as_me: libgd is too old, not compiling in image support" >&6;} fi else { echo "$as_me:$LINENO: Can't find libgd, not compiling in image support" >&5 echo "$as_me: Can't find libgd, not compiling in image support" >&6;} fi fi # SDL SDLOBJS="" SDLIFACE="" SDLMAN="" # Check whether --enable-sdl was given. if test "${enable_sdl+set}" = set; then enableval=$enable_sdl; if test "$enableval" = "yes"; then if test "${ac_cv_header_SDL_SDL_h+set}" = set; then { echo "$as_me:$LINENO: checking for SDL/SDL.h" >&5 echo $ECHO_N "checking for SDL/SDL.h... $ECHO_C" >&6; } if test "${ac_cv_header_SDL_SDL_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_SDL_SDL_h" >&5 echo "${ECHO_T}$ac_cv_header_SDL_SDL_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking SDL/SDL.h usability" >&5 echo $ECHO_N "checking SDL/SDL.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking SDL/SDL.h presence" >&5 echo $ECHO_N "checking SDL/SDL.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: SDL/SDL.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: SDL/SDL.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: SDL/SDL.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: SDL/SDL.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: SDL/SDL.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: SDL/SDL.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: SDL/SDL.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: SDL/SDL.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for SDL/SDL.h" >&5 echo $ECHO_N "checking for SDL/SDL.h... $ECHO_C" >&6; } if test "${ac_cv_header_SDL_SDL_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_SDL_SDL_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_SDL_SDL_h" >&5 echo "${ECHO_T}$ac_cv_header_SDL_SDL_h" >&6; } fi { echo "$as_me:$LINENO: checking for SDL_Init in -lSDL" >&5 echo $ECHO_N "checking for SDL_Init in -lSDL... $ECHO_C" >&6; } if test "${ac_cv_lib_SDL_SDL_Init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lSDL $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char SDL_Init (); int main () { return SDL_Init (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_SDL_SDL_Init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_SDL_SDL_Init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_SDL_SDL_Init" >&5 echo "${ECHO_T}$ac_cv_lib_SDL_SDL_Init" >&6; } if test $ac_cv_lib_SDL_SDL_Init = yes; then SDLOBJS="SDL.o sdl_glue.o" SDLIFACE="SDL.ki" SDLMAN="SDL.libs" else { echo "$as_me:$LINENO: Can't find libsdl, not compiling in SDL support" >&5 echo "$as_me: Can't find libsdl, not compiling in SDL support" >&6;} fi fi else if test "${ac_cv_header_SDL_SDL_h+set}" = set; then { echo "$as_me:$LINENO: checking for SDL/SDL.h" >&5 echo $ECHO_N "checking for SDL/SDL.h... $ECHO_C" >&6; } if test "${ac_cv_header_SDL_SDL_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_SDL_SDL_h" >&5 echo "${ECHO_T}$ac_cv_header_SDL_SDL_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking SDL/SDL.h usability" >&5 echo $ECHO_N "checking SDL/SDL.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking SDL/SDL.h presence" >&5 echo $ECHO_N "checking SDL/SDL.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: SDL/SDL.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: SDL/SDL.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: SDL/SDL.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: SDL/SDL.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: SDL/SDL.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: SDL/SDL.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: SDL/SDL.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: SDL/SDL.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for SDL/SDL.h" >&5 echo $ECHO_N "checking for SDL/SDL.h... $ECHO_C" >&6; } if test "${ac_cv_header_SDL_SDL_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_SDL_SDL_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_SDL_SDL_h" >&5 echo "${ECHO_T}$ac_cv_header_SDL_SDL_h" >&6; } fi { echo "$as_me:$LINENO: checking for SDL_Init in -lSDL" >&5 echo $ECHO_N "checking for SDL_Init in -lSDL... $ECHO_C" >&6; } if test "${ac_cv_lib_SDL_SDL_Init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lSDL $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char SDL_Init (); int main () { return SDL_Init (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_SDL_SDL_Init=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_SDL_SDL_Init=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_SDL_SDL_Init" >&5 echo "${ECHO_T}$ac_cv_lib_SDL_SDL_Init" >&6; } if test $ac_cv_lib_SDL_SDL_Init = yes; then SDLOBJS="SDL.o sdl_glue.o" SDLIFACE="SDL.ki" SDLMAN="SDL.libs" else { echo "$as_me:$LINENO: Can't find libsdl, not compiling in SDL support" >&5 echo "$as_me: Can't find libsdl, not compiling in SDL support" >&6;} fi fi # OpenGL GLOBJS="" GLIFACE="" # Check whether --enable-opengl was given. if test "${enable_opengl+set}" = set; then enableval=$enable_opengl; if test "$enableval" = "yes"; then if test "${ac_cv_header_GL_gl_h+set}" = set; then { echo "$as_me:$LINENO: checking for GL/gl.h" >&5 echo $ECHO_N "checking for GL/gl.h... $ECHO_C" >&6; } if test "${ac_cv_header_GL_gl_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 echo "${ECHO_T}$ac_cv_header_GL_gl_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking GL/gl.h usability" >&5 echo $ECHO_N "checking GL/gl.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking GL/gl.h presence" >&5 echo $ECHO_N "checking GL/gl.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: GL/gl.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: GL/gl.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: GL/gl.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: GL/gl.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: GL/gl.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for GL/gl.h" >&5 echo $ECHO_N "checking for GL/gl.h... $ECHO_C" >&6; } if test "${ac_cv_header_GL_gl_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_GL_gl_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 echo "${ECHO_T}$ac_cv_header_GL_gl_h" >&6; } fi { echo "$as_me:$LINENO: checking for glEnable in -lGL" >&5 echo $ECHO_N "checking for glEnable in -lGL... $ECHO_C" >&6; } if test "${ac_cv_lib_GL_glEnable+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lGL $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char glEnable (); int main () { return glEnable (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_GL_glEnable=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_GL_glEnable=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_GL_glEnable" >&5 echo "${ECHO_T}$ac_cv_lib_GL_glEnable" >&6; } if test $ac_cv_lib_GL_glEnable = yes; then # The assumption here is that if you have GL, you'll have GLU and glut... { echo "$as_me:$LINENO: checking for glutInit in -lglut" >&5 echo $ECHO_N "checking for glutInit in -lglut... $ECHO_C" >&6; } if test "${ac_cv_lib_glut_glutInit+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lglut $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char glutInit (); int main () { return glutInit (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_glut_glutInit=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_glut_glutInit=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_glut_glutInit" >&5 echo "${ECHO_T}$ac_cv_lib_glut_glutInit" >&6; } if test $ac_cv_lib_glut_glutInit = yes; then { echo "$as_me:$LINENO: checking for gluPerspective in -lGLU" >&5 echo $ECHO_N "checking for gluPerspective in -lGLU... $ECHO_C" >&6; } if test "${ac_cv_lib_GLU_gluPerspective+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lGLU $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gluPerspective (); int main () { return gluPerspective (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_GLU_gluPerspective=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_GLU_gluPerspective=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_GLU_gluPerspective" >&5 echo "${ECHO_T}$ac_cv_lib_GLU_gluPerspective" >&6; } if test $ac_cv_lib_GLU_gluPerspective = yes; then GLOBJS="Glut.o GL.o glglue.o glutglue.o" GLIFACE="Glut.ki GL.ki" else { echo "$as_me:$LINENO: Can't find GLU, not compiling in OpenGL support" >&5 echo "$as_me: Can't find GLU, not compiling in OpenGL support" >&6;} fi else { echo "$as_me:$LINENO: Can't find glut, not compiling in OpenGL support" >&5 echo "$as_me: Can't find glut, not compiling in OpenGL support" >&6;} fi else { echo "$as_me:$LINENO: Can't find GL, not compiling in OpenGL support" >&5 echo "$as_me: Can't find GL, not compiling in OpenGL support" >&6;} fi fi else if test "${ac_cv_header_GL_gl_h+set}" = set; then { echo "$as_me:$LINENO: checking for GL/gl.h" >&5 echo $ECHO_N "checking for GL/gl.h... $ECHO_C" >&6; } if test "${ac_cv_header_GL_gl_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 echo "${ECHO_T}$ac_cv_header_GL_gl_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking GL/gl.h usability" >&5 echo $ECHO_N "checking GL/gl.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking GL/gl.h presence" >&5 echo $ECHO_N "checking GL/gl.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: GL/gl.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: GL/gl.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: GL/gl.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: GL/gl.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: GL/gl.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for GL/gl.h" >&5 echo $ECHO_N "checking for GL/gl.h... $ECHO_C" >&6; } if test "${ac_cv_header_GL_gl_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_GL_gl_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 echo "${ECHO_T}$ac_cv_header_GL_gl_h" >&6; } fi { echo "$as_me:$LINENO: checking for glEnable in -lGL" >&5 echo $ECHO_N "checking for glEnable in -lGL... $ECHO_C" >&6; } if test "${ac_cv_lib_GL_glEnable+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lGL $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char glEnable (); int main () { return glEnable (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_GL_glEnable=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_GL_glEnable=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_GL_glEnable" >&5 echo "${ECHO_T}$ac_cv_lib_GL_glEnable" >&6; } if test $ac_cv_lib_GL_glEnable = yes; then # The assumption here is that if you have GL, you'll have GLU and glut... { echo "$as_me:$LINENO: checking for glutInit in -lglut" >&5 echo $ECHO_N "checking for glutInit in -lglut... $ECHO_C" >&6; } if test "${ac_cv_lib_glut_glutInit+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lglut $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char glutInit (); int main () { return glutInit (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_glut_glutInit=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_glut_glutInit=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_glut_glutInit" >&5 echo "${ECHO_T}$ac_cv_lib_glut_glutInit" >&6; } if test $ac_cv_lib_glut_glutInit = yes; then { echo "$as_me:$LINENO: checking for gluPerspective in -lGLU" >&5 echo $ECHO_N "checking for gluPerspective in -lGLU... $ECHO_C" >&6; } if test "${ac_cv_lib_GLU_gluPerspective+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lGLU $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gluPerspective (); int main () { return gluPerspective (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_GLU_gluPerspective=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_GLU_gluPerspective=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_GLU_gluPerspective" >&5 echo "${ECHO_T}$ac_cv_lib_GLU_gluPerspective" >&6; } if test $ac_cv_lib_GLU_gluPerspective = yes; then GLOBJS="Glut.o GL.o glglue.o glutglue.o" GLIFACE="Glut.ki GL.ki" else { echo "$as_me:$LINENO: Can't find GLU, not compiling in OpenGL support" >&5 echo "$as_me: Can't find GLU, not compiling in OpenGL support" >&6;} fi else { echo "$as_me:$LINENO: Can't find glut, not compiling in OpenGL support" >&5 echo "$as_me: Can't find glut, not compiling in OpenGL support" >&6;} fi else { echo "$as_me:$LINENO: Can't find GL, not compiling in OpenGL support" >&5 echo "$as_me: Can't find GL, not compiling in OpenGL support" >&6;} fi fi # CursesW CURSESWOBJS="" CURSESWIFACE="" CURSESWMAN="" # Check whether --enable-ncursesw was given. if test "${enable_ncursesw+set}" = set; then enableval=$enable_ncursesw; if test "$enableval" = "yes"; then if test "${ac_cv_header_ncursesw_ncurses_h+set}" = set; then { echo "$as_me:$LINENO: checking for ncursesw/ncurses.h" >&5 echo $ECHO_N "checking for ncursesw/ncurses.h... $ECHO_C" >&6; } if test "${ac_cv_header_ncursesw_ncurses_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_ncursesw_ncurses_h" >&5 echo "${ECHO_T}$ac_cv_header_ncursesw_ncurses_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking ncursesw/ncurses.h usability" >&5 echo $ECHO_N "checking ncursesw/ncurses.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking ncursesw/ncurses.h presence" >&5 echo $ECHO_N "checking ncursesw/ncurses.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for ncursesw/ncurses.h" >&5 echo $ECHO_N "checking for ncursesw/ncurses.h... $ECHO_C" >&6; } if test "${ac_cv_header_ncursesw_ncurses_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_ncursesw_ncurses_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_ncursesw_ncurses_h" >&5 echo "${ECHO_T}$ac_cv_header_ncursesw_ncurses_h" >&6; } fi if test "${ac_cv_header_locale_h+set}" = set; then { echo "$as_me:$LINENO: checking for locale.h" >&5 echo $ECHO_N "checking for locale.h... $ECHO_C" >&6; } if test "${ac_cv_header_locale_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 echo "${ECHO_T}$ac_cv_header_locale_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking locale.h usability" >&5 echo $ECHO_N "checking locale.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking locale.h presence" >&5 echo $ECHO_N "checking locale.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: locale.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: locale.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: locale.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: locale.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: locale.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: locale.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: locale.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for locale.h" >&5 echo $ECHO_N "checking for locale.h... $ECHO_C" >&6; } if test "${ac_cv_header_locale_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_locale_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 echo "${ECHO_T}$ac_cv_header_locale_h" >&6; } fi { echo "$as_me:$LINENO: checking for has_colors in -lncursesw" >&5 echo $ECHO_N "checking for has_colors in -lncursesw... $ECHO_C" >&6; } if test "${ac_cv_lib_ncursesw_has_colors+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lncursesw $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char has_colors (); int main () { return has_colors (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_ncursesw_has_colors=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_ncursesw_has_colors=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_ncursesw_has_colors" >&5 echo "${ECHO_T}$ac_cv_lib_ncursesw_has_colors" >&6; } if test $ac_cv_lib_ncursesw_has_colors = yes; then CURSESWOBJS="CursesW.o cursesw_glue.o" CURSESWMAN="CursesW.libs" CURSESWIFACE="CursesW.ki" else { echo "$as_me:$LINENO: Can't find libncursesw, not compiling in wide ncurses support" >&5 echo "$as_me: Can't find libncursesw, not compiling in wide ncurses support" >&6;} fi fi else if test "${ac_cv_header_ncursesw_ncurses_h+set}" = set; then { echo "$as_me:$LINENO: checking for ncursesw/ncurses.h" >&5 echo $ECHO_N "checking for ncursesw/ncurses.h... $ECHO_C" >&6; } if test "${ac_cv_header_ncursesw_ncurses_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_ncursesw_ncurses_h" >&5 echo "${ECHO_T}$ac_cv_header_ncursesw_ncurses_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking ncursesw/ncurses.h usability" >&5 echo $ECHO_N "checking ncursesw/ncurses.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking ncursesw/ncurses.h presence" >&5 echo $ECHO_N "checking ncursesw/ncurses.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: ncursesw/ncurses.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: ncursesw/ncurses.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for ncursesw/ncurses.h" >&5 echo $ECHO_N "checking for ncursesw/ncurses.h... $ECHO_C" >&6; } if test "${ac_cv_header_ncursesw_ncurses_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_ncursesw_ncurses_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_ncursesw_ncurses_h" >&5 echo "${ECHO_T}$ac_cv_header_ncursesw_ncurses_h" >&6; } fi if test "${ac_cv_header_locale_h+set}" = set; then { echo "$as_me:$LINENO: checking for locale.h" >&5 echo $ECHO_N "checking for locale.h... $ECHO_C" >&6; } if test "${ac_cv_header_locale_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 echo "${ECHO_T}$ac_cv_header_locale_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking locale.h usability" >&5 echo $ECHO_N "checking locale.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking locale.h presence" >&5 echo $ECHO_N "checking locale.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: locale.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: locale.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: locale.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: locale.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: locale.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: locale.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: locale.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for locale.h" >&5 echo $ECHO_N "checking for locale.h... $ECHO_C" >&6; } if test "${ac_cv_header_locale_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_locale_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 echo "${ECHO_T}$ac_cv_header_locale_h" >&6; } fi { echo "$as_me:$LINENO: checking for has_colors in -lncursesw" >&5 echo $ECHO_N "checking for has_colors in -lncursesw... $ECHO_C" >&6; } if test "${ac_cv_lib_ncursesw_has_colors+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lncursesw $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char has_colors (); int main () { return has_colors (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_ncursesw_has_colors=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_ncursesw_has_colors=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_ncursesw_has_colors" >&5 echo "${ECHO_T}$ac_cv_lib_ncursesw_has_colors" >&6; } if test $ac_cv_lib_ncursesw_has_colors = yes; then CURSESWOBJS="CursesW.o cursesw_glue.o" CURSESWMAN="CursesW.libs" CURSESWIFACE="CursesW.ki" else { echo "$as_me:$LINENO: Can't find libncursesw, not compiling in wide ncurses support" >&5 echo "$as_me: Can't find libncursesw, not compiling in wide ncurses support" >&6;} fi fi # Curses CURSESOBJS="" CURSESIFACE="" CURSESMAN="" KAYOBJS="" KAYIFACE="" KAYMAN="" # Check whether --enable-curses was given. if test "${enable_curses+set}" = set; then enableval=$enable_curses; if test "$enableval" = "yes"; then if test "${ac_cv_header_curses_h+set}" = set; then { echo "$as_me:$LINENO: checking for curses.h" >&5 echo $ECHO_N "checking for curses.h... $ECHO_C" >&6; } if test "${ac_cv_header_curses_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_curses_h" >&5 echo "${ECHO_T}$ac_cv_header_curses_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking curses.h usability" >&5 echo $ECHO_N "checking curses.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking curses.h presence" >&5 echo $ECHO_N "checking curses.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: curses.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: curses.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: curses.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: curses.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: curses.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: curses.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: curses.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: curses.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: curses.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: curses.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for curses.h" >&5 echo $ECHO_N "checking for curses.h... $ECHO_C" >&6; } if test "${ac_cv_header_curses_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_curses_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_curses_h" >&5 echo "${ECHO_T}$ac_cv_header_curses_h" >&6; } fi if test "${ac_cv_header_locale_h+set}" = set; then { echo "$as_me:$LINENO: checking for locale.h" >&5 echo $ECHO_N "checking for locale.h... $ECHO_C" >&6; } if test "${ac_cv_header_locale_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 echo "${ECHO_T}$ac_cv_header_locale_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking locale.h usability" >&5 echo $ECHO_N "checking locale.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking locale.h presence" >&5 echo $ECHO_N "checking locale.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: locale.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: locale.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: locale.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: locale.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: locale.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: locale.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: locale.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for locale.h" >&5 echo $ECHO_N "checking for locale.h... $ECHO_C" >&6; } if test "${ac_cv_header_locale_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_locale_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 echo "${ECHO_T}$ac_cv_header_locale_h" >&6; } fi { echo "$as_me:$LINENO: checking for has_colors in -lcurses" >&5 echo $ECHO_N "checking for has_colors in -lcurses... $ECHO_C" >&6; } if test "${ac_cv_lib_curses_has_colors+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcurses $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char has_colors (); int main () { return has_colors (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_curses_has_colors=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_curses_has_colors=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_curses_has_colors" >&5 echo "${ECHO_T}$ac_cv_lib_curses_has_colors" >&6; } if test $ac_cv_lib_curses_has_colors = yes; then CURSESOBJS="Curses.o curses_glue.o" CURSESIFACE="Curses.ki" CURSESMAN="Curses.libs" KAYMAN="Kayurses.contrib" KAYIFACE="Kayurses.ki" KAYOBJ="Kayurses.o" else { echo "$as_me:$LINENO: Can't find libcurses, not compiling in curses support" >&5 echo "$as_me: Can't find libcurses, not compiling in curses support" >&6;} fi fi else if test "${ac_cv_header_curses_h+set}" = set; then { echo "$as_me:$LINENO: checking for curses.h" >&5 echo $ECHO_N "checking for curses.h... $ECHO_C" >&6; } if test "${ac_cv_header_curses_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_curses_h" >&5 echo "${ECHO_T}$ac_cv_header_curses_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking curses.h usability" >&5 echo $ECHO_N "checking curses.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking curses.h presence" >&5 echo $ECHO_N "checking curses.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: curses.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: curses.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: curses.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: curses.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: curses.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: curses.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: curses.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: curses.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: curses.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: curses.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for curses.h" >&5 echo $ECHO_N "checking for curses.h... $ECHO_C" >&6; } if test "${ac_cv_header_curses_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_curses_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_curses_h" >&5 echo "${ECHO_T}$ac_cv_header_curses_h" >&6; } fi if test "${ac_cv_header_locale_h+set}" = set; then { echo "$as_me:$LINENO: checking for locale.h" >&5 echo $ECHO_N "checking for locale.h... $ECHO_C" >&6; } if test "${ac_cv_header_locale_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 echo "${ECHO_T}$ac_cv_header_locale_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking locale.h usability" >&5 echo $ECHO_N "checking locale.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking locale.h presence" >&5 echo $ECHO_N "checking locale.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: locale.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: locale.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: locale.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: locale.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: locale.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: locale.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: locale.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: locale.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for locale.h" >&5 echo $ECHO_N "checking for locale.h... $ECHO_C" >&6; } if test "${ac_cv_header_locale_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_locale_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 echo "${ECHO_T}$ac_cv_header_locale_h" >&6; } fi { echo "$as_me:$LINENO: checking for has_colors in -lcurses" >&5 echo $ECHO_N "checking for has_colors in -lcurses... $ECHO_C" >&6; } if test "${ac_cv_lib_curses_has_colors+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcurses $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char has_colors (); int main () { return has_colors (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_curses_has_colors=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_curses_has_colors=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_curses_has_colors" >&5 echo "${ECHO_T}$ac_cv_lib_curses_has_colors" >&6; } if test $ac_cv_lib_curses_has_colors = yes; then CURSESOBJS="Curses.o curses_glue.o" CURSESIFACE="Curses.ki" CURSESMAN="Curses.libs" KAYMAN="Kayurses.contrib" KAYIFACE="Kayurses.ki" KAYOBJ="Kayurses.o" else { echo "$as_me:$LINENO: Can't find libcurses, not compiling in curses support" >&5 echo "$as_me: Can't find libcurses, not compiling in curses support" >&6;} fi fi # Compress (moved to essential checks) #COMPRESSOBJS="" #COMPRESSIFACE="" #AC_CHECK_HEADER([zlib.h]) #AC_CHECK_LIB(z, compress, # [COMPRESSOBJS="Compress.o zlib_glue.o" # COMPRESSIFACE="Compress.ki"], # [AC_MSG_NOTICE([Can't find libz, not compiling in compression support])#]) # #AC_SUBST(COMPRESSOBJS) #AC_SUBST(COMPRESSIFACE) # Threads THREADSOBJS="" THREADSIFACE="" THREADSMAN="" if test "${ac_cv_header_pthread_h+set}" = set; then { echo "$as_me:$LINENO: checking for pthread.h" >&5 echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6; } if test "${ac_cv_header_pthread_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi { echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 echo "${ECHO_T}$ac_cv_header_pthread_h" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking pthread.h usability" >&5 echo $ECHO_N "checking pthread.h usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking pthread.h presence" >&5 echo $ECHO_N "checking pthread.h presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: pthread.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: pthread.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: pthread.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: pthread.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: pthread.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: pthread.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: pthread.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: pthread.h: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for pthread.h" >&5 echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6; } if test "${ac_cv_header_pthread_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_pthread_h=$ac_header_preproc fi { echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 echo "${ECHO_T}$ac_cv_header_pthread_h" >&6; } fi { echo "$as_me:$LINENO: checking for pthread_exit in -lpthread" >&5 echo $ECHO_N "checking for pthread_exit in -lpthread... $ECHO_C" >&6; } if test "${ac_cv_lib_pthread_pthread_exit+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_exit (); int main () { return pthread_exit (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pthread_pthread_exit=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread_pthread_exit=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_exit" >&5 echo "${ECHO_T}$ac_cv_lib_pthread_pthread_exit" >&6; } if test $ac_cv_lib_pthread_pthread_exit = yes; then THREADSOBJS="Threads.o Multicore.o thread_glue.o" THREADSIFACE="Threads.ki Multicore.ki" THREADSMAN="Threads.libs Multicore.libs" else { echo "$as_me:$LINENO: Can't find libpthread, not compiling in threading support" >&5 echo "$as_me: Can't find libpthread, not compiling in threading support" >&6;} fi #### FIN. #################################################################### #libdir=${prefix}/lib/${LANGNAME} # cygwin hack if (test -d "/cygdrive/c/temp/"); then tmpdir='c:/temp'; # MinGW hack (CIM 28/7/05) elif (test -d "/c/temp/"); then tmpdir='c:/temp'; elif (test -d "/tmp"); then tmpdir='/tmp'; else tmpdir='.'; fi version=`cat ${srcdir}/VERSION` ## Extra GCC options ## # linking works differently on different systems. Here's another hack to # guess what we're running on. # Useful 'safety net' options suggested by # http://lists.debian.org/debian-devel-announce/2008/01/msg00006.html #EXTRAGCCOPTS="-D_FORTIFY_SOURCE=2 -fstack-protector -Wl,-zrelro -FPIE -pie" EXTRAGCCOPTS="-D_FORTIFY_SOURCE=2 " #always ### -fstack-protector breaks static linking #if (test $(expr `gcc -dumpversion` ">=" 4.1) -eq 1); then #"-fstack-protector" # GCC 4.1 or later ## not available on alpha, ia64 yet, doesn't work on arm ## if it works on armel can fix later... # if (test $unameM != "ia64" && test $unameM != "alpha" && test `uname -m | sed -e 's/^\(...\).*/\1/'` != 'arm'); then # EXTRAGCCOPTS="-fstack-protector "${EXTRAGCCOPTS} # fi #fi # set in platform detection # set in platform detection # GHC library changes in version 6.4... ghcmajor=`ghc --numeric-version | cut -d '.' -f 1` ghcminor=`ghc --numeric-version | cut -d '.' -f 2` if [ $ghcmajor -gt 6 ] || ( [ $ghcmajor -eq 6 ] && [ $ghcminor -ge 4 ] ); then portmod='Portability64'; else portmod='Portability5'; fi # and also in 6.6 if [ $ghcmajor -gt 6 ] || ( [ $ghcmajor -eq 6 ] && [ $ghcminor -ge 6 ] ); then packages=''; showtupleon='{-'; showtupleoff='-}'; else packages='-package util -package lang'; showtupleon=''; showtupleoff=''; fi # and also in 6.10 if [ $ghcmajor -gt 6 ] || ( [ $ghcmajor -eq 6 ] && [ $ghcminor -ge 10 ] ); then readlinemodule='System.Console.Editline.Readline' else readlinemodule='System.Console.Readline' fi ac_config_files="$ac_config_files Makefile compiler/Makefile rts/Makefile rts/sizes.h rts_opt/Makefile rts_fast/Makefile stdlib/Makefile windows/Makefile posix/Makefile libs/Makefile contrib/Makefile stdlib/Net.k man/Makefile bframe/Makefile example-programs/Makefile tools/Makefile compiler/Lib.hs compiler/REPL.hs compiler/Portability.hs" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2006 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 CONFIG_SHELL=$SHELL export CONFIG_SHELL exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "compiler/Makefile") CONFIG_FILES="$CONFIG_FILES compiler/Makefile" ;; "rts/Makefile") CONFIG_FILES="$CONFIG_FILES rts/Makefile" ;; "rts/sizes.h") CONFIG_FILES="$CONFIG_FILES rts/sizes.h" ;; "rts_opt/Makefile") CONFIG_FILES="$CONFIG_FILES rts_opt/Makefile" ;; "rts_fast/Makefile") CONFIG_FILES="$CONFIG_FILES rts_fast/Makefile" ;; "stdlib/Makefile") CONFIG_FILES="$CONFIG_FILES stdlib/Makefile" ;; "windows/Makefile") CONFIG_FILES="$CONFIG_FILES windows/Makefile" ;; "posix/Makefile") CONFIG_FILES="$CONFIG_FILES posix/Makefile" ;; "libs/Makefile") CONFIG_FILES="$CONFIG_FILES libs/Makefile" ;; "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; "stdlib/Net.k") CONFIG_FILES="$CONFIG_FILES stdlib/Net.k" ;; "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; "bframe/Makefile") CONFIG_FILES="$CONFIG_FILES bframe/Makefile" ;; "example-programs/Makefile") CONFIG_FILES="$CONFIG_FILES example-programs/Makefile" ;; "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;; "compiler/Lib.hs") CONFIG_FILES="$CONFIG_FILES compiler/Lib.hs" ;; "compiler/REPL.hs") CONFIG_FILES="$CONFIG_FILES compiler/REPL.hs" ;; "compiler/Portability.hs") CONFIG_FILES="$CONFIG_FILES compiler/Portability.hs" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # # Set up the sed scripts for CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "$CONFIG_FILES"; then _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF SHELL!$SHELL$ac_delim PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim PACKAGE_NAME!$PACKAGE_NAME$ac_delim PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim PACKAGE_STRING!$PACKAGE_STRING$ac_delim PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim exec_prefix!$exec_prefix$ac_delim prefix!$prefix$ac_delim program_transform_name!$program_transform_name$ac_delim bindir!$bindir$ac_delim sbindir!$sbindir$ac_delim libexecdir!$libexecdir$ac_delim datarootdir!$datarootdir$ac_delim datadir!$datadir$ac_delim sysconfdir!$sysconfdir$ac_delim sharedstatedir!$sharedstatedir$ac_delim localstatedir!$localstatedir$ac_delim includedir!$includedir$ac_delim oldincludedir!$oldincludedir$ac_delim docdir!$docdir$ac_delim infodir!$infodir$ac_delim htmldir!$htmldir$ac_delim dvidir!$dvidir$ac_delim pdfdir!$pdfdir$ac_delim psdir!$psdir$ac_delim libdir!$libdir$ac_delim localedir!$localedir$ac_delim mandir!$mandir$ac_delim DEFS!$DEFS$ac_delim ECHO_C!$ECHO_C$ac_delim ECHO_N!$ECHO_N$ac_delim ECHO_T!$ECHO_T$ac_delim LIBS!$LIBS$ac_delim build_alias!$build_alias$ac_delim host_alias!$host_alias$ac_delim target_alias!$target_alias$ac_delim GHC!$GHC$ac_delim HAPPY!$HAPPY$ac_delim LANGNAME!$LANGNAME$ac_delim TARGET!$TARGET$ac_delim EXT!$EXT$ac_delim CC!$CC$ac_delim CFLAGS!$CFLAGS$ac_delim LDFLAGS!$LDFLAGS$ac_delim CPPFLAGS!$CPPFLAGS$ac_delim ac_ct_CC!$ac_ct_CC$ac_delim EXEEXT!$EXEEXT$ac_delim OBJEXT!$OBJEXT$ac_delim CPP!$CPP$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim ac_cv_sizeof_voidp!$ac_cv_sizeof_voidp$ac_delim ac_cv_sizeof_int!$ac_cv_sizeof_int$ac_delim ac_cv_sizeof_long!$ac_cv_sizeof_long$ac_delim ac_cv_sizeof_long_long!$ac_cv_sizeof_long_long$ac_delim KAYAPROF!$KAYAPROF$ac_delim INTERPROF!$INTERPROF$ac_delim GHCOPTS!$GHCOPTS$ac_delim LIBTOOL!$LIBTOOL$ac_delim BENCHTIMER!$BENCHTIMER$ac_delim CXX!$CXX$ac_delim CXXFLAGS!$CXXFLAGS$ac_delim ac_ct_CXX!$ac_ct_CXX$ac_delim platform!$platform$ac_delim NETLIB!$NETLIB$ac_delim PATHSEP!$PATHSEP$ac_delim EXECUTABLE!$EXECUTABLE$ac_delim POSIXMAN!$POSIXMAN$ac_delim FPIC!$FPIC$ac_delim KLIBDIR!$KLIBDIR$ac_delim GTOD_INTERNAL!$GTOD_INTERNAL$ac_delim HASUTF8!$HASUTF8$ac_delim CXXCPP!$CXXCPP$ac_delim PGOBJS!$PGOBJS$ac_delim PGSTUB!$PGSTUB$ac_delim PGMAN!$PGMAN$ac_delim PGIFACE!$PGIFACE$ac_delim PGINC!$PGINC$ac_delim MYOBJS!$MYOBJS$ac_delim MYSTUB!$MYSTUB$ac_delim MYIFACE!$MYIFACE$ac_delim MYINC!$MYINC$ac_delim MYMAN!$MYMAN$ac_delim SQLOBJS!$SQLOBJS$ac_delim SQLSTUB!$SQLSTUB$ac_delim SQLIFACE!$SQLIFACE$ac_delim SQLIMAN!$SQLIMAN$ac_delim SQLINC!$SQLINC$ac_delim GDMAN!$GDMAN$ac_delim GDOBJS!$GDOBJS$ac_delim GDIFACE!$GDIFACE$ac_delim SDLOBJS!$SDLOBJS$ac_delim SDLIFACE!$SDLIFACE$ac_delim SDLMAN!$SDLMAN$ac_delim GLOBJS!$GLOBJS$ac_delim GLIFACE!$GLIFACE$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF CEOF$ac_eof _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF CURSESWOBJS!$CURSESWOBJS$ac_delim CURSESWIFACE!$CURSESWIFACE$ac_delim CURSESWMAN!$CURSESWMAN$ac_delim CURSESOBJS!$CURSESOBJS$ac_delim CURSESIFACE!$CURSESIFACE$ac_delim CURSESMAN!$CURSESMAN$ac_delim KAYIFACE!$KAYIFACE$ac_delim KAYOBJ!$KAYOBJ$ac_delim KAYMAN!$KAYMAN$ac_delim THREADSMAN!$THREADSMAN$ac_delim THREADSOBJS!$THREADSOBJS$ac_delim THREADSIFACE!$THREADSIFACE$ac_delim GCCBINOPTS!$GCCBINOPTS$ac_delim GCCDYNOPTS!$GCCDYNOPTS$ac_delim EXTRAGCCOPTS!$EXTRAGCCOPTS$ac_delim readlinemodule!$readlinemodule$ac_delim tmpdir!$tmpdir$ac_delim version!$version$ac_delim portmod!$portmod$ac_delim packages!$packages$ac_delim showtupleon!$showtupleon$ac_delim showtupleoff!$showtupleoff$ac_delim unameS!$unameS$ac_delim unameM!$unameM$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 26; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF :end s/|#_!!_#|//g CEOF$ac_eof _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF fi # test -n "$CONFIG_FILES" for ac_tag in :F $CONFIG_FILES do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 echo "$as_me: error: Invalid tag $ac_tag." >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac ac_file_inputs="$ac_file_inputs $ac_f" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input="Generated from "`IFS=: echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} fi case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin";; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s&@configure_input@&$configure_input&;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out"; rm -f "$tmp/out";; *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; esac ;; esac done # for ac_tag { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi kaya-0.4.4/tools/0000755000175100017510000000000011170340770011710 5ustar cimcimkaya-0.4.4/tools/kayadoc2man.k0000644000175100017510000001332511170340770014261 0ustar cimcim/* kayadoc2man - Makes man pages out of -xmldocs XML Copyright (C) 2006 Chris Morris This file is distributed under the terms of the GNU General Public Licence. See COPYING for licence. */ program kayadoc2man; import Dict; import Regex; import KayaDoc; import System; import ElementTree; import IO; import Time; String authors = "Kaya standard library by Edwin Brady, Chris Morris and others (kaya@kayalang.org). For further information see http://kayalang.org/\n.SH LICENSE\nThe Kaya standard library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (version 2.1 or any later version) as published by the Free Software Foundation."; String maninfo = ".\\\" This man page is automatically generated using .\\\" kayadoc2man from the Kaya development tools and the -xmldocs compile .\\\" option. Editing it directly is not encouraged. .\\\" It is under the same license as the source .k file that it was .\\\" generated from.\n"; Void main() { try { args = getArgs(); if (size(args) <= 1) { putStrLn("Usage: kayadoc2man XMLFILE DONEFILE LICENSEFILE"); } if (size(args) > 3) { authfile = args[3]; dauthors = readFile(args[3]); } file = args[1]; doc = readDoc(file); // Invalid filename detection and error reporting contributed by // Boris Jakubith re = compile("(^.*/)?([A-Za-z_][A-Za-z_0-9]*)\\.xml$"); m = match(re,file); case m of { noMatch -> putStr (stderr, "kayadoc2man: invalid filename \""+file+"\"\n"); exit (1); | _ -> modname = m.matches[2]; } // modname = match(compile("/([A-Za-z]+)\\.xml$"),file).matches[1]; datypes = listDataTypes(doc); for datype in datypes { loc = EntryLocation(datype.dname,EntryData,0); entry = findEntry(doc,loc); if (size(args) > 3) { manpage = describeDataMan(entry,modname,dauthors); } else { manpage = describeDataMan(entry,modname,authors); } replace("::",".",datype.dname); manfile = datype.dname+".3kaya"; // already includes modname writeFile(manfile,maninfo+manpage); } fdone = Dict::new(); fns = listFunctions(doc); for fn in fns { case lookup(fdone,fn.fname) of { nothing -> counter = 0; | just(counter) -> ; } loc = EntryLocation(fn.fname,EntryFunction,counter); entry = findEntry(doc,loc); if (size(args) > 3) { manpage = describeFunctionMan(entry,modname,dauthors); } else { manpage = describeFunctionMan(entry,modname,authors); } if (counter != 0) { manfile = modname+"."+fn.fname+"_"+counter+".3kaya"; } else { manfile = modname+"."+fn.fname+".3kaya"; } writeFile(manfile,maninfo+manpage); add(fdone,fn.fname,counter+1); } extypes = listExceptions(doc); for extype in extypes { loc = EntryLocation(extype.ename,EntryException,0); entry = findEntry(doc,loc); if (size(args) > 3) { manpage = describeExceptionMan(entry,modname,dauthors); } else { manpage = describeExceptionMan(entry,modname,authors); } replace("::",".",extype.ename); manfile = extype.ename+".3kaya"; // already includes modname writeFile(manfile,maninfo+manpage); } // mark it as done for the benefit of Make! if (size(args) > 3) { writeSummary(doc,modname,dauthors); } else { writeSummary(doc,modname,authors); } if (size(args) > 2) { completed = args[2]; writeFile(completed,file); } } catch(InputError(s)) { putStrLn("Input Error parsing API docs: "+s); exit(1); } catch(UnexpectedEnd(p)) { putStrLn("Unexpected end of document: "+p); exit(1); } catch(ExpectedChar(c,p)) { putStrLn("Error parsing API docs - expected '"+c+"': "+p); exit(1); } catch(UnexpectedChar(c,p)) { putStrLn("Error parsing API docs - unexpected '"+c+"': "+p); exit(1); } catch(NoSuchEntry(str)) { putStrLn("Can't find reference " + str); exit(1); } catch(e) { exceptionBacktrace(e); exit(1); } } Void writeSummary(ElementTree doc, String modname, String authors) { modsummary = moduleSummary(doc); manstr = ".TH \""+modname+"\" \"3kaya\" \""+manTime+"\" \"Kaya\" \"Kaya module reference\"\n"; manstr += ".SH \"NAME\"\n"+modname+" \\- "+manSummary(deref(extractSummary(modsummary)))+"\n"; manstr += toMan(modsummary,modname,""); tysyns = listTypes(doc); if (size(tysyns) > 0) { manstr += ".SH \"TYPE SYNONYMS\"\n"; manstr += ".PD 0\n"; for tysyn in tysyns { manstr += ".PP\n.B "+tysyn.alias+" = "+tysyn.meaning+"\n"; } manstr += ".PD 0.4v\n"; } dats = listDataTypes(doc); if (size(dats) > 0) { manstr += ".SH \"DATA TYPES\"\n"; manstr += ".PD 0\n"; for dat in dats { lfunname = manFilename(dat.dname); manstr += ".PP\n.B \""+lfunname+"\"(3kaya)\n"; } manstr += ".PD 0.4v\n"; } exs = listExceptions(doc); if (size(exs) > 0) { manstr += ".SH \"EXCEPTIONS\"\n"; manstr += ".PD 0\n"; for ex in exs { lfunname = manFilename(ex.ename); manstr += ".PP\n.B \""+lfunname+"\"(3kaya)\n"; } manstr += ".PD 0.4v\n"; } fns = listFunctions(doc); if (size(fns) > 0) { manstr += ".SH \"FUNCTIONS\"\n"; manstr += ".PD 0\n"; fdone = Dict::new(); for fn in fns { case lookup(fdone,fn.fname) of { nothing -> counter = 0; | just(counter) -> ; } lfunname = modname+"."+fn.fname; if (counter > 0) { lfunname += "_"+counter; } manstr += ".PP\n.B \""+lfunname+"\"(3kaya)\n"; add(fdone,fn.fname,counter+1); } manstr += ".PD 0.4v\n"; } if (authors != "") { manstr += ".SH \"AUTHORS\"\n"+authors+"\n"; } writeFile(modname+".3kaya",maninfo+manstr); } kaya-0.4.4/tools/kaya-rekey.k0000644000175100017510000000565611170340770014142 0ustar cimcim/* kaya-rekey - Regenerates application keys for Kaya binaries Copyright (C) 2006 Chris Morris This file is distributed under the terms of the GNU General Public Licence. See COPYING for licence. */ // TODO: fix the parser so this doesn't need -o to be kaya-rekey program kayarekey; import System; import Time; import IO; import Binary; Void main() { args = getArgs(); if (size(args) < 2) { putStrLn("Usage: kayarekey [ [...]]"); } else { self = shift(args); // otherwise things get messy ;) for f in args { if (fileReadable(f) && fileWritable(f)) { rekey(f); } else { putStrLn("Can't rekey "+f+" - need read+write permission."); } } } } Int keyLength = 32; Int ivecLength1 = 32; Int ivecLength2 = 16; Void rekey(var String f) { fp = open(f,[Read,Write,Binary]); fseek(fp,0); keylocs = []; iveclocs = []; while (!eof(fp)) { c = getChar(fp); if (c == 'K') { oldpos = fpos(fp)-1; nc = getChar(fp); if (nc == 'S' || nc == 'I') { if (getChar(fp) == 'B') { if (nc == 'S') { if (checkKey(fp)) { push(keylocs,oldpos); } } else { // Ivec length changed in 0.2.6->0.2.7 // check longer length first if (checkIVec1(fp)) { push(iveclocs,oldpos); ilength = ivecLength1; } else { fseek(fp,oldpos+3); if (checkIVec2(fp)) { push(iveclocs,oldpos); ilength = ivecLength2; } } } } else { fseek(fp,oldpos+2); } } else { fseek(fp,oldpos+1); } } } // do things with keylocs, iveclocs if (size(keylocs) == 1 && size(iveclocs) == 1) { replaceKey(fp,3+keylocs[0],keyLength); replaceKey(fp,3+iveclocs[0],ilength); putStrLn("Rekeyed "+f); } else { putStrLn("Can't rekey "+f+" - found "+size(keylocs)+" possible key(s) and "+size(iveclocs)+" possible ivec(s)"); } close(fp); } Bool checkKey(var File fp) = checkBin(fp,keyLength,'S'); Bool checkIVec1(var File fp) = checkBin(fp,ivecLength1,'I'); Bool checkIVec2(var File fp) = checkBin(fp,ivecLength2,'I'); Bool checkBin(var File fp, var Int offset, var Char mark) { fseek(fp,fpos(fp)+offset); if (getChar(fp) == 'K') { if (getChar(fp) == mark) { if (getChar(fp) == 'E') { return true; } } } return false; } Void replaceKey(var File fp, var Int pos, var Int len) { try { random = open("/dev/random",[Read]); rdata = []; for i in [1..len] { push(rdata,Int(getChar(random))); } close(random); doReplaceKey(fp,pos,rdata); } catch(e) { putStrLn("Warning: using software PRNG. Key is deterministic"); srand(pos+now()+rand()); rdata = []; for i in [1..len] { push(rdata,abs(rand())%256); } doReplaceKey(fp,pos,rdata); } } Void doReplaceKey(var File fp, var Int pos, var [Int] rdata) { fseek(fp,pos); bin = createBlock(size(rdata)); for rd@p in rdata { poke(bin,p,rd); } writeBlock(fp,bin); } kaya-0.4.4/tools/Makefile.in0000644000175100017510000000156511170340770013764 0ustar cimcimRVPATH=@srcdir@ VPATH=${RVPATH} KAYAC = ../compiler/@TARGET@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ CXXFLAGS = -I../rts -O2 KAYAINC = @KAYAPROF@ -noenvlibs -I../stdlib -I../rts -deprfail -L ${VPATH}/../rts -L ${VPATH} INSTALLFLAGS = -m 644 SRCS = kaya-rekey.@EXT@ kayadoc2man.@EXT@ OBJS = kaya-rekey@EXECUTABLE@ kayadoc2man@EXECUTABLE@ all: ${OBJS} install: mkdir -p ${DESTDIR}${bindir} install ${OBJS} ${DESTDIR}${bindir} clean: rm -f ${OBJS} distclean: clean rm -f *~ Makefile rm -rf autom4te.cache kaya-rekey@EXECUTABLE@ : kaya-rekey.@EXT@ ../stdlib/Binary.o ../stdlib/IO.o ${KAYAC} $< -force -nochase ${KAYAINC} -nortchecks -L ../rts_opt -L ../rts -L ../stdlib -o kaya-rekey@EXECUTABLE@ kayadoc2man@EXECUTABLE@ : kayadoc2man.@EXT@ ../stdlib/KayaDoc.o ${KAYAC} $< -force -nochase ${KAYAINC} -nortchecks -L ../rts_opt -L ../rts -L ../stdlib kaya-0.4.4/rts_fast/0000755000175100017510000000000011170340770012375 5ustar cimcimkaya-0.4.4/rts_fast/stdfuns.cc0000644000175100017510000000003511170340770014370 0ustar cimcim#include "../rts/stdfuns.cc" kaya-0.4.4/rts_fast/VM.cc0000644000175100017510000000003011170340770013217 0ustar cimcim#include "../rts/VM.cc" kaya-0.4.4/rts_fast/repl_glue.cc0000644000175100017510000000003711170340770014662 0ustar cimcim#include "../rts/repl_glue.cc" kaya-0.4.4/rts_fast/COPYING0000644000175100017510000006346311170340770013444 0ustar cimcim GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 library 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 Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! kaya-0.4.4/rts_fast/ValueFuns.cc0000644000175100017510000000003711170340770014614 0ustar cimcim#include "../rts/ValueFuns.cc" kaya-0.4.4/rts_fast/VMState.cc0000644000175100017510000000003511170340770014225 0ustar cimcim#include "../rts/VMState.cc" kaya-0.4.4/rts_fast/Heap.cc0000644000175100017510000000003211170340770013554 0ustar cimcim#include "../rts/Heap.cc" kaya-0.4.4/rts_fast/KayaAPI.cc0000644000175100017510000000003511170340770014121 0ustar cimcim#include "../rts/KayaAPI.cc" kaya-0.4.4/rts_fast/Closure.cc0000644000175100017510000000003511170340770014316 0ustar cimcim#include "../rts/Closure.cc" kaya-0.4.4/rts_fast/Array.cc0000644000175100017510000000003311170340770013756 0ustar cimcim#include "../rts/Array.cc" kaya-0.4.4/rts_fast/FnCache.cc0000644000175100017510000000003511170340770014171 0ustar cimcim#include "../rts/FnCache.cc" kaya-0.4.4/rts_fast/unpickler.cc0000644000175100017510000000003711170340770014700 0ustar cimcim#include "../rts/unpickler.cc" kaya-0.4.4/rts_fast/Makefile.in0000644000175100017510000000312211170340770014440 0ustar cimcimRVPATH=@srcdir@ VPATH=${RVPATH} CXX = @CXX@ CXXFLAGS = @EXTRAGCCOPTS@ @FPIC@ -fno-rtti -DNOCHECK -DMEM_POOLSIZE=16 -I${VPATH}/../rts -I../rts @CXXFLAGS@ LANGNAME = @LANGNAME@ LIBS = -lgc LDFLAGS = ${LIBS} prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@/@LANGNAME@ VCCDIR = ${libdir} INSTALLFLAGS = -m 644 SRCS = Heap.cc ValueFuns.cc VM.cc VMState.cc stdfuns.cc unpickler.cc Array.cc \ KayaAPI.cc Closure.cc FnCache.cc repl_glue.cc OBJS = Heap.o ValueFuns.o VM.o VMState.o stdfuns.o unpickler.o Array.o \ KayaAPI.o Closure.o FnCache.o repl_glue.o TARGET = libkayavm-fast.so LIBTARGET = libkayavm-fast.a GLUE = repl_glue.o all: ${LIBTARGET} #all: ${LIBTARGET} # ${CXX} ${CXXFLAGS} -shared ${OBJS} -o ${TARGET} ${LIBS} ${LIBTARGET}: ${OBJS} ar r ${LIBTARGET} ${OBJS} ranlib ${LIBTARGET} # ${CXX} ${CXXFLAGS} ${LDFLAGS} ${OBJS} -o ${TARGET} install: mkdir -p ${DESTDIR}${libdir} mkdir -p ${DESTDIR}${VCCDIR} install ${INSTALLFLAGS} ${LIBTARGET} ${DESTDIR}${libdir} # install ${INSTALLFLAGS} ${GLUE} ${DESTDIR}${libdir}/imports # install ${INSTALLFLAGS} ${TARGET} ${DESTDIR}${libdir} ranlib ${DESTDIR}${libdir}/${LIBTARGET} clean: rm -f ${LIBTARGET} *.o distclean: rm -f *~ Makefile depend: @makedepend -Y ${SRCS} 2> /dev/null %.out: %.vcc ${TARGET} ${CXX} -x c++ ${OPTS} $< -o $@ ${LIBS} -L. -lvm Heap.o: ../rts/Heap.o ValueFuns.o: ../rts/ValueFuns.o VM.o: ../rts/VM.o VMState.o: ../rts/VMState.o stdfuns.o: ../rts/stdfuns.o unpickler.o: ../rts/unpickler.o Array.o: ../rts/Array.o KayaAPI.o: ../rts/KayaAPI.o Closure.o: ../rts/Closure.o repl_glue.o: ../rts/repl_glue.o kaya-0.4.4/.htaccess0000644000175100017510000000002211170340770012340 0ustar cimcimRewriteEngine Off kaya-0.4.4/rts/0000755000175100017510000000000011170340770011360 5ustar cimcimkaya-0.4.4/rts/VMState.h0000644000175100017510000002430311170340770013056 0ustar cimcim#ifndef _VMSTATE_H // -*-C++-*- #define _VMSTATE_H /** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ using namespace std; #ifndef WIN32 #include #define GC_THREADS #else #include #define GC_WIN32_THREADS #endif #include #include #include #include #include #include "Heap.h" // Defined by compiling Builtins.k, so obviously any binary of a kaya // program needs to be linked to at least Builtins.o! #define PROJECT_FROM_NON_UNION K_ns__D_Builtins__D_Project_UN_From_UN_Non_UN_Union #define LOOKUP_FROM_NON_ARRAY K_ns__D_Builtins__D_Lookup_UN_From_UN_Non_UN_Array #define NEGATIVE_ARRAY_INDEX K_ns__D_Builtins__D_Negative_UN_Array_UN_Index #define WRONG_CONSTRUCTOR K_ns__D_Builtins__D_Wrong_UN_Constructor #define GETTING_TAG_FROM_NON_UNION K_ns__D_Builtins__D_Getting_UN_Tag_UN_From_UN_Non_UN_Union #define INVALID_MARSHALLING_ID K_ns__D_Builtins__D_Invalid_UN_Marshalling_UN_ID #define INVALID_FUNCTION_TABLE_HASH K_ns__D_Builtins__D_Invalid_UN_Function_UN_Table_UN_Hash #define CANT_MARSHAL_EXCEPTIONS K_ns__D_Builtins__D_Cant_UN_Marshal_UN_Exceptions #define CANT_REFLECT_EXCEPTIONS K_ns__D_Builtins__D_Cant_UN_Reflect_UN_Exceptions #define INVALID_VALUE K_ns__D_Builtins__D_Invalid_UN_Value #define NOT_IMPLEMENTED K_ns__D_Builtins__D_Not_UN_Implemented #define INVALID_CIRCULAR_STRUCTURE K_ns__D_Builtins__D_Invalid_UN_Circular_UN_Structure //#define UNKNOWN_FUNCTION_ID K_ns__D_Builtins__D_Unknown_UN_Function_UN_ID #define DIVIDE_BY_ZERO K_ns__D_Builtins__D_Divide_UN_By_UN_Zero extern "C" const char* PROJECT_FROM_NON_UNION; extern "C" const char* LOOKUP_FROM_NON_ARRAY; extern "C" const char* NEGATIVE_ARRAY_INDEX; extern "C" const char* WRONG_CONSTRUCTOR; extern "C" const char* GETTING_TAG_FROM_NON_UNION; extern "C" const char* INVALID_MARSHALLING_ID; extern "C" const char* INVALID_FUNCTION_TABLE_HASH; extern "C" const char* INVALID_VALUE; extern "C" const char* NOT_IMPLEMENTED; extern "C" const char* INVALID_CIRCULAR_STRUCTURE; extern "C" const char* CANT_MARSHAL_EXCEPTIONS; extern "C" const char* CANT_REFLECT_EXCEPTIONS; //extern "C" const char* UNKNOWN_FUNCTION_ID; extern "C" const char* DIVIDE_BY_ZERO; /// Function map is global to all threads. //extern map m_funmap; void initFunMap(kint sz, kint fmhash); void addToFunMap(kint id, func fn); func getFn(kint id); kint getFnID(func fn); kint getFnHash(); class Exception; class VMState: public gc { friend class Exception; public: VMState(bool panic=false); Value* doPop() { Value* tmp=*(--m_stackptr); *m_stackptr=NULL; return tmp; } // sometimes just shortening the stack so this is faster than doPop() void discardPop() { *(--m_stackptr) = NULL; } void push(Value* val) { // TODO: doing this check on every single push() is quite slow // Is there a way to calculate the maximum stack increase a // single function will use and do a single check at the start // of the function? // In normal code the default stack size is enough anyway... if ((m_stackptr-m_valstack)>=m_stackalloc) { realloc_stack(); } *m_stackptr = val; ++m_stackptr; } // Next ones are for efficiency void push2(Value* val, Value* val2); void push3(Value* val, Value* val2, Value* val3); void push4(Value* val, Value* val2, Value* val3,Value *val4); // Push then settop is common, so combine. void pushsettop(Value* val) { val->setPtr(*(--m_stackptr)); *m_stackptr=NULL; } void pushrv(void* ptr, valtype type) { Value t(ptr,type); (*(m_stackptr-1))->setPtr(&t); } // Setting the top as a temp is also common. void tmpsettop(kint val) { (*(--m_stackptr))->setInt(val); *m_stackptr=NULL; } double topint2real(); void mkArray(kint size); void mkArray(Value* v, kint size); void finish(); bool emptyStack(); /// Replace the top stack item with its ith argument. /// Let's see if inlining helps void projarg(ukint i, ukint t) { #ifndef NOCHECK Value*& topval = (*(m_stackptr-1)); if (topval==NULL) { kaya_rtsError(INVALID_VALUE); } if (topval->getType()getType() << endl; kaya_rtsError(PROJECT_FROM_NON_UNION); } Union* top = (Union*)topval->getRaw(); if ((ukint)(topval->getType()-KVT_UNION)!=t) { kaya_rtsError(WRONG_CONSTRUCTOR); } if (U_ARITY(top) <= i) { kaya_rtsError(INVALID_VALUE); } topval=top->args[i]; #else (*(m_stackptr-1)) = ((Union*)(((Value*&)(*(m_stackptr-1)))->getRaw()))->args[i]; #endif // push(arg); } void setprojarg(Value*& src, ukint i, ukint t, Value* dest) { #ifndef NOCHECK if (src==NULL) { kaya_rtsError(INVALID_VALUE); } if (src->getType()getRaw(); if ((ukint)(src->getType()-KVT_UNION)!=t) { kaya_rtsError(WRONG_CONSTRUCTOR); } if (U_ARITY(top) <= i) { kaya_rtsError(INVALID_VALUE); } top->args[i] = dest; #else ((Value*&)(((Union*)(src->getRaw()))->args[i])) = dest; #endif // push(arg); } void goToIndex(); void pushToIndex(Value* v) { kint idx = v->getInt(); (*(m_stackptr-1)) = (*(m_stackptr-1))->lookup(this,idx); } /** Replace the top stack item with the contents of the second stack item, then remove both (mutation, not evaluation) */ void setTop() { (*(m_stackptr-1))->setPtr((*(m_stackptr-2))); (*(m_stackptr-2)) = (*(m_stackptr-1)); *(m_stackptr-1)=NULL; m_stackptr-=2; } void setRV() { (*(m_stackptr-2))->setPtr((*(m_stackptr-1))); *(m_stackptr-1)=NULL; m_stackptr--; } void setRVreal(double r) { (*(m_stackptr-1))->setReal(m_rpool,r); } // Add the top stack value to the next one, then remove both. void addTop() { (*(m_stackptr-2))->addVal(*(m_stackptr-1)); *(m_stackptr-1)=NULL; m_stackptr-=2; } void subTop() { (*(m_stackptr-2))->subVal(*(m_stackptr-1)); *(m_stackptr-1)=NULL; m_stackptr-=2; } void mulTop() { (*(m_stackptr-2))->mulVal(*(m_stackptr-1)); *(m_stackptr-1)=NULL; m_stackptr-=2; } void divTop() { (*(m_stackptr-2))->divVal(*(m_stackptr-1)); *(m_stackptr-1)=NULL; m_stackptr-=2; } void appendTop() { // append top stack item onto top-1 stack item String* topstr = (*(--m_stackptr))->getString(); (*(m_stackptr-1))->getString()->append(topstr); *m_stackptr = NULL; } void appendTopInt() { // append top stack item onto top-1 stack item wchar_t topstr = (wchar_t)((*(--m_stackptr))->getInt()); // and now adjust the stack to correct for an explicit coercion // being removed. // FIXME: probably a better way to do this than a peephole optimisation // anyway! discardPop(); // add the right values (*(m_stackptr-1))->getString()->append(topstr); *m_stackptr = NULL; } /// Return the top stack item. Value* topItem() { return (*(m_stackptr-1)); } void pushglobal(Value**& globtable, kint i); void createglobal(wchar_t* modid,kint i); kint tag(); void doAppend(); void doAppendChar(const wchar_t x); void doAppendStr(const wchar_t* x); void doEqExcept(bool inv); void doEqString(); void doEqString(const wchar_t* str); void doNeString(); void doNeString(const wchar_t* str); bool doTopStrEq(const wchar_t* str); void str2int(); void int2str(); void real2str(); void str2real(); void str2chr(); void chr2str(); void bool2str(); void real2int(); void int2real(); void newjmp_buf(); void kaya_throw(wchar_t* msg, kint code); void kaya_internalError(kint code); void kaya_rtsError(const char* exceptionID); void throw_ex(); jmp_buf* top_ex(); void tried(); void restore(); void getindex(); void pushgetindex(Value* v) { kint idx = v->getInt(); --m_stackptr; Value* array = *m_stackptr; Value* el = array->lookup(this,idx); push(el); } void setlookup(kint idx, Value* v) { Value* array = *(m_stackptr-1); Value* el = array->lookup(this,idx); v->setPtr(el); } Value* mkstr(wchar_t* str); Value* mkint(void* i); void lineno(const wchar_t* src, int ln); void pushBT(const wchar_t* src, const wchar_t* mod, int ln); void popBT(); void memstat(); int maxMemUsage() { return m_maxmem; } // Implement print via write void writestdout(); void returnVal(Value* ret) { m_return.setPtr(ret); } Value* getReturnVal() { return &m_return; } // Throw divide by zero exception void divideByZero() { kaya_rtsError(DIVIDE_BY_ZERO); } void realloc_stack(); void realloc_callstack(); ValuePool* getVPool() { return m_vpool; } UnionPool* getUPool() { return m_upool; } StringPool* getSPool() { return m_spool; } RealPool* getRPool() { return m_rpool; } ArrayPool* getAPool() { return m_apool; } // Temporary string buffer to reduce allocations needed in string handling // If this works well then it should be done in a neater way! wchar_t* allocString(kint alloc) { strbuffer = (wchar_t*)KMALLOC_BLOCK(alloc*sizeof(wchar_t)); strbuflen = alloc; strbuffer[0] = '\0'; return strbuffer; } wchar_t* strbuffer; kint strbuflen; private: Value** m_valstack; Value** m_stackptr; CallStackEntry** m_btptr; // int m_stacksize; ValuePool* m_vpool; UnionPool* m_upool; StringPool* m_spool; RealPool* m_rpool; ArrayPool* m_apool; int m_stackalloc; int m_callstackalloc; int m_globalloc; struct StackData { Value** stackptr; CallStackEntry** csptr; }; stack m_except_stack; stack m_stack_stack; // Stack size when an exception happens. // Tracing details CallStackEntry** m_backtrace; wchar_t* m_sourcefile; int m_lineno; int m_maxmem; Value m_return; // Place to put return values (sort of a register). }; #endif // whole file kaya-0.4.4/rts/stdfuns.h0000644000175100017510000001470211170340770013223 0ustar cimcim#ifndef _STDFUNS_H #define _STDFUNS_H /** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ // Standard functions for linking into the standard library #include #include #include #include #include "Heap.h" #include "KayaAPI.h" #include "unpickler.h" #include #include "sizes.h" typedef map ArgMap; extern KayaArray args; wchar_t* inttostr(kint s, kint base); kint strtoint(wchar_t* str, kint base); VMState* getsubstr(void* vmptr, wchar_t* x,kint i,kint len); void str_offset(Value* str, kint inc); void str_chop(Value* str, kint inc); VMState* getstrend(void* vmptr, wchar_t* x,kint i); wchar_t* readstr(); wchar_t getIndex(wchar_t* str,kint i); void setIndex(wchar_t* str, wchar_t c,kint i); VMState* do_urlencode(void* vm, wchar_t* strinwide, kint len); VMState* do_urldecode(void* vm, wchar_t* strinwide, kint len); void* do_tmpFile(); VMState* getLine(void* vmptr, void* file); void getLineTo(void* file, KayaValue strv); wchar_t do_fgetc(void* fptr); void do_fputc(kint ch, void* fptr); VMState* getString(void* vmptr, void* file); void putString(void* f, wchar_t* c, kint len); void putLine(void* f, wchar_t* c, kint len); void do_fseek(void* f, kint p); kint do_ftell(void* f); bool do_feof(void* f); kint do_fflush(void* f); void do_fclose(void* f); void putStr(wchar_t* c, kint len); // Check if a string has any UTF8 characters in it (return non-zero if so) kint topSet(const char* str); kint checkUTF8(wchar_t* str); void* getstdin(); void* getstdout(); void* getstderr(); void setStdErr(FILE* f); bool validFile(void* f); void printArray(KayaArray foo); KayaArray reverseArray(KayaArray foo); void shortenArray(KayaArray foo); KayaValue shiftArray(KayaArray foo); void unshiftArray(KayaValue val, KayaArray foo); KayaArray createArray(void* vmptr, kint size); void resizeArray(KayaArray foo, kint size); kint arraySize(KayaArray foo); // these really are char* and int void storeArgs(int argc,char* argv[]); KayaArray getArgs(); kint gettime(); kint getclock(); kint dogettimeofday(); #ifdef GTOD_INTERNAL kint gettimeofday (struct timeval *tp, void *tz); #endif KayaValue dogmtime(kint secs); KayaValue dolocaltime(kint secs); kint domktime(KayaValue time); kint runProgram(wchar_t* prog, KayaArray args); kint dofork(); kint dowait(); kint dowaitpid(kint pid); void reap(); kint dogetpid(); kint do_wcsstr(wchar_t* needle, wchar_t* haystack); bool do_wcschr(wchar_t c, wchar_t* s); kint do_wcscspn(wchar_t c, wchar_t* s); kint offset_wcscspn(wchar_t c, wchar_t* s, kint i); wchar_t* b64enc(wchar_t* block, kint len); wchar_t* b64dec(wchar_t* block, KayaValue len); char* b64enc(char* block, kint len); char* b64dec(char* block, KayaValue len); wchar_t* mkString(KayaValue x); void quicksort(void* vm, KayaArray xs, KayaValue sortfn); #define FUNTABLE_OP(op,x,y) \ switch (x->getFunTable()) { \ case KVT_INT: \ r = inttable_##op(x,y); \ break; \ case KVT_STRING: \ r = stringtable_##op(x,y); \ break; \ case KVT_FUNC: \ r = fntable_##op(x,y); \ break; \ case KVT_ARRAY: \ r = arraytable_##op(x,y); \ break; \ case KVT_CUNION: \ r = cuniontable_##op(x,y); \ break; \ case KVT_EXCEPTION: \ r = exceptiontable_##op(x,y); \ break; \ case KVT_REAL: \ r = realtable_##op(x,y); \ break; \ case KVT_NULL: \ r = inttable_##op(x,y); \ break; \ case KVT_UNION: \ default: \ r = uniontable_##op(x,y); \ break; \ } /* KVT_NULL can't happen KVT_UNION has to be last and default because anything > KVT_UNION is also a union */ // #define funtable_compare(x,y) x->getFunTable()->cmp(x,y) #define funtable_eq(v,x,y) (x==y || funtable_equal(v,x,y)) #define funtable_eq_aux(x,y,done) (x==y || funtable_equal_aux(x,y,done)) kint funtable_compare(void* vmptr, KayaValue x, KayaValue y); bool funtable_equal(void* vmptr, KayaValue x, KayaValue y); bool funtable_equal_aux(KayaValue x, KayaValue y, map& done); kint funtable_memusage(KayaValue x); kint funtable_hash(KayaValue x); kint funtable_hash_aux(KayaValue x, vector& done); VMState* funtable_marshal(void* vmptr,KayaValue x,kint id); void funtable_marshal_aux(void* vmptr,String* mdata,vector& done,KayaValue x, kint i); Value* funtable_reflect(void* vmptr,KayaValue x); Value* funtable_reflect_aux(void* vmptr, map& done,KayaValue x); KayaValue funtable_copy(void* vmptr, KayaValue x); KayaValue funtable_copy_aux(VMState* vm, KayaValue x, map& done); KayaValue reifyUnion(kint tag, kint arity); void reifyUnionArgs(KayaValue v, KayaArray flds); KayaValue reifyClosure(kint tag, kint arity); void reifyClosureArgs(KayaValue v, KayaArray flds); bool is_initialised(KayaValue x); KayaValue unsafe_id(KayaValue x); wchar_t* getAddr(KayaValue x); wchar_t* except_msg(KayaValue x); kint except_code(KayaValue x); void except_dumpbt(KayaValue x); kint doGetFnID(KayaValue fn); //void callFnID(void* vmptr, kint id, KayaValue arg); kint memusage(); kint isNull(void* p); kint isIdentical(KayaValue x, KayaValue y); kint maxMemUsage(void* vmptr); // Added by Chris Morris, 18/6/05 kint do_access(wchar_t* pathname, KayaValue mode); // Added by Chris Morris, 5/9/05 kint do_unlink(const wchar_t* fn); wchar_t* dogetcwd(); kint do_mkdir(const wchar_t* fn, kint um); kint do_setrlimit(KayaValue lim, kint soft, kint hard); // Directory functions, 28/8/05 void* do_opendir(wchar_t* name); kint do_closedir(void* dir); void* do_readdir(void* dir); VMState* dir_getname(void* vmptr, void* ent); KayaValue do_stat(void* vm, wchar_t* name); void* do_fopen(const wchar_t* path, const wchar_t* mode); void* do_freopen(const wchar_t* path, const wchar_t* mode, void* stream); void do_rename(const wchar_t* oldfile, const wchar_t* newfile); void do_chdir(const wchar_t* newdir); wchar_t* do_getenv(const wchar_t* env); kint binary_length(const wchar_t* str, kint len); #ifndef WIN32 kint do_system(const wchar_t* prog); void* do_popen(const wchar_t* prog, kint read); kint do_pclose(void* stream); #endif // Return next biggest power of 2. kint nextPower(kint x); kint strAlloc(Value* str); Value* createString(void* vmptr, kint len); void do_GC_enable_incremental(); void do_GC_finalizer(Value* obj, Value* finalizer); void do_sleep(kint len); void do_usleep(kint len); kint strHash(wchar_t* m, kint len); kint rtchecks(); #endif kaya-0.4.4/rts/stdfuns.cc0000644000175100017510000011262411170340770013363 0ustar cimcim/** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ #ifndef WIN32 #include #include #else // CIM: for unlink and mkdir #include #include #endif // CIM: we now need this in mingw too #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include // CIM: pthread.h is outside the thread definitions since we need it anyway // for the gmtime_r functions. #include #ifndef WIN32 #define GC_THREADS #else #define GC_WIN32_THREADS #endif #include #include "stdfuns.h" #include "Heap.h" #include "Closure.h" #include "VM.h" #include "VMState.h" #include "KayaAPI.h" // Read lines from files this many characters at a time #define LINE_CHUNK 1024 KayaArray args; ArgMap httpargs; wchar_t* inttostr(kint s, kint base) { // CIM: I'm sure we can make this smaller int sz = 255; wchar_t* buf=(wchar_t*)GC_MALLOC_ATOMIC(sz*sizeof(wchar_t)); switch(base) { case 10: SWPRINTF(buf,sz,DIGITFORMAT,s); break; case 16: SWPRINTF(buf,sz,L"%x",s); break; case 8: SWPRINTF(buf,sz,L"%o",s); break; default: SWPRINTF(buf,sz,DIGITFORMAT,s); // Can't do weird bases yet. break; } return buf; } kint strtoint(wchar_t* str, kint base) { #ifdef KAYA_SHORT_INTS return wcstoimax(str,NULL,base); #else return wcstol(str,NULL,base); #endif } VMState* getsubstr(void* vmptr, wchar_t* x,kint i,kint len) { VMState* vm = (VMState*)vmptr; wchar_t* n = vm->allocString(len<<1); if (len > 0) { wcsncpy(n,x+i,len); } n[len] = '\0'; return vm; } void str_offset(Value* str, kint inc) { str->getString()->offset(inc); } void str_chop(Value* str, kint inc) { str->getString()->chop(inc); } VMState* getstrend(void* vmptr, wchar_t* x,kint i) { kint max = wcslen(x); VMState* vm = (VMState*)vmptr; wchar_t* n = vm->allocString(max+1-i); if (max-i > 0) { wcsncpy(n,x+i,max-i); } n[max-i] = '\0'; return vm; } wchar_t getIndex(wchar_t* str,kint i) { return str[i]; } void setIndex(wchar_t* str, wchar_t c,kint i) { str[i] = c; } void getLineTo(void* fptr,KayaValue strv) { String* str = strv->getString(); FILE* f = (FILE*)fptr; unsigned size = LINE_CHUNK; // #define at top of file // buffer to read into (since it's not going anywhere near the // Kaya VM except as a stack variable, no need to allocate) char buf[LINE_CHUNK+1]; // accumulator for result; but only allocate it when it turns out to be // needed (i.e., when one chunk isn't enough). char* res=NULL; char* r; do { r = fgets(buf,LINE_CHUNK,f); if (r == NULL) { // End of file, or read error. FIXME: Check which. if (res==NULL) { // Fail silently (should this throw an exception?) // free(buf); str->getForeign(""); // vm->allocString(1); return; } else { // File finished without a newline, return what we've got. str->getForeign(res); free(res); // free(buf); return; } } if (res==NULL) { // FIXME: We're relying on \n or \r\n line endings. How much // can we rely on this? // C defines \n to be the native newline when reading // or writing files in text mode so maybe we're okay... if (strlen(buf)<(size-1) || buf[LINE_CHUNK-2]=='\n') { str->getForeign(buf); //KVSTRING(vm,buf); // Success in one chunk // free(buf); return; } // Begin allocation for accumulator and carry on as normal. size += LINE_CHUNK-1; res = (char*)malloc(size*sizeof(char)+1); strcpy(res,buf); } else { strcat(res,buf); if (strlen(res)<(size-1) || buf[LINE_CHUNK-2]=='\n') { // Finished successfully str->getForeign(res); // KVSTRING(vm,res); free(res); // free(buf); return; } else { size += LINE_CHUNK-1; // -1 to account for null termination of // string read into buf res = (char*)realloc(res, size*sizeof(char)+1); } } } while (r!=NULL); // free(buf); if (res != NULL) { free(res); } // vm->allocString(1); str->getForeign(""); // return vm; // Failed, although we shouldn't get here } VMState* getLine(void* vmptr,void* fptr) { VMState* vm = (VMState*)vmptr; FILE* f = (FILE*)fptr; unsigned size = LINE_CHUNK; // #define at top of file // buffer to read into (since it's not going anywhere near the // Kaya VM except as a stack variable, no need to allocate) char buf[LINE_CHUNK+1]; // accumulator for result; but only allocate it when it turns out to be // needed (i.e., when one chunk isn't enough). char* res=NULL; char* r; do { r = fgets(buf,LINE_CHUNK,f); if (r == NULL) { // End of file, or read error. FIXME: Check which. if (res==NULL) { // Fail silently (should this throw an exception?) // free(buf); vm->allocString(1); return vm; } else { // File finished without a newline, return what we've got. KVSTRING(vm,res); free(res); // free(buf); return vm; } } if (res==NULL) { // FIXME: We're relying on \n or \r\n line endings. How much // can we rely on this? // C defines \n to be the native newline when reading // or writing files in text mode so maybe we're okay... if (strlen(buf)<(size-1) || buf[LINE_CHUNK-2]=='\n') { KVSTRING(vm,buf); // Success in one chunk // free(buf); return vm; } // Begin allocation for accumulator and carry on as normal. size += LINE_CHUNK-1; res = (char*)malloc(size*sizeof(char)+1); strcpy(res,buf); } else { strcat(res,buf); if (strlen(res)<(size-1) || buf[LINE_CHUNK-2]=='\n') { // Finished successfully KVSTRING(vm,res); free(res); // free(buf); return vm; } else { size += LINE_CHUNK-1; // -1 to account for null termination of // string read into buf res = (char*)realloc(res, size*sizeof(char)+1); } } } while (r!=NULL); // free(buf); if (res != NULL) { free(res); } vm->allocString(1); return vm; // Failed, although we shouldn't get here } wchar_t do_fgetc(void* fptr) { return (wchar_t)fgetc((FILE*)fptr); } void do_fputc(kint ch, void* fptr) { fputc(ch,(FILE*)fptr); } void* do_tmpFile() { return (void*)tmpfile(); } VMState* getString(void* vmptr, void* fptr) { VMState* vm = (VMState*)vmptr; FILE* f = (FILE*)fptr; unsigned size = LINE_CHUNK; // #define at top of file // buffer to read into (since it's not going anywhere near the // Kaya VM itself, use malloc rather than KMALLOC and free before exit) char* buf=(char*)malloc(LINE_CHUNK*sizeof(char)+1); // accumulator for result; but only allocate it when it turns out to be // needed (i.e., when one chunk isn't enough). int i=0; do { do { int c = fgetc(f); if (c == EOF) { buf[i] = '\0'; KVSTRING(vm,buf); free(buf); return vm; } buf[i] = (unsigned char)c; if (buf[i] == '\0') { KVSTRING(vm,buf); free(buf); return vm; } i++; } while (i%LINE_CHUNK != 0); size += LINE_CHUNK; buf = (char*)realloc(buf, (size+1)*sizeof(char)); } while (true); // replaces != EOF because the check above will get that // ...and unsigned char can never equal EOF anyway. free(buf); vm->allocString(1); return vm; // Failed, although we can't get here } void putLine(void* fptr, wchar_t* c, kint len) { FILE* f = (FILE*)fptr; CNPSTRING(r,c,len); fputs(r,f); } void putString(void* fptr, wchar_t* c, kint len) { FILE* f = (FILE*)fptr; CNPSTRING(r,c,len); fputs(r,f); fputc('\0',f); } void do_fseek(void* f, kint p) { fseek((FILE*)f,(long)p,SEEK_SET); } kint do_ftell(void* f) { return KINT(ftell((FILE*)f)); } bool do_feof(void* f) { return feof((FILE*)f); } kint do_fflush(void* f) { return fflush((FILE*)f); } void do_fclose(void* f) { fclose((FILE*)f); } void putStr(wchar_t* rawc, kint rlen) { kint i = sizeof(char)*(++rlen)*4; char c[i]; mkUTF8(rawc,c,rlen); cout << c; } // Check if the top bit is set in a string (i.e., whether it is ASCII or // includes UTF-8 characters) kint topSet(const char* str) { const char* sptr = str; for(;(*sptr)!=0;++sptr) { if (((*sptr)&128)!=0) { return 1; } } return 0; } kint checkUTF8(wchar_t* str) { wchar_t* sptr = str; for(;(*sptr)!=0;++sptr) { if ((*sptr)>127) { return 1; } } return 0; } void printArray(KayaArray foo) { for(ukint i=0;isize();++i) { cout << wctostr(foo->lookup(i)->getString()->getVal()) << endl; } } KayaArray reverseArray(KayaArray foo) { KayaArray bar = new Array(); for(ukint i=foo->size();i>0;i--) { bar->push_back(foo->lookup(i-1)); } return bar; } void shortenArray(KayaArray foo) { if (foo->size()>0) { foo->resize(foo->size()-1); } } KayaValue shiftArray(KayaArray foo) { return foo->shift(); } void unshiftArray(KayaValue val, KayaArray foo) { return foo->unshift(val); } KayaArray createArray(void* vmptr, kint size) { return newKayaArray2(vmptr,size); } void resizeArray(KayaArray foo, kint size) { foo->resize(size); } kint arraySize(KayaArray foo) { return foo->size(); } void* getstdin() { return (void*)stdin; } void* getstdout() { return (void*)stdout; } void* getstderr() { return (void*)stderr; } void setStdErr(FILE* f) { #ifndef WIN32 // stderr = f; #endif } bool validFile(void* f) { return (FILE*)f!=NULL; } void storeArgs(int argc,char* argv[]) { args = new Array(argc); for (int i=0;ipush_back(arg); } } KayaArray getArgs() { return args; } kint gettime() { return (kint)(time(NULL)); } kint dogettimeofday() { timeval tv; gettimeofday(&tv,NULL); return tv.tv_usec; } #ifdef GTOD_INTERNAL // taken from libiberty (LGPL) in the GCC libraries // needed for old GCC versions on Windows kint gettimeofday (struct timeval *tp, void *tz) { /* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */ static const unsigned long long W32_FT_OFFSET = 116444736000000000ULL; SYSTEMTIME s_time; union { unsigned long long ns100; FILETIME f_time; } now; if (tz) abort (); /* GetSystemTimeAsFileTime, introduced with NT version 3.5 and also available on Win9x, would be more efficient. We use this instead to provide support for NT versions back to 3.1. This will also work on WinCE. We don't worry about NT 3.0 and earlier since the CRT used by mingw (msvcrt.dll) is not compatible with NT 3.0 either. */ GetSystemTime (&s_time); if (!SystemTimeToFileTime (&s_time, &now.f_time)) GetSystemTime (&s_time); if (!SystemTimeToFileTime (&s_time, &now.f_time)) return -1; tp->tv_usec=(long)((now.ns100 / 10ULL) % 1000000ULL ); tp->tv_sec= (long)((now.ns100 - W32_FT_OFFSET) / 10000000ULL); return 0; } #endif KayaValue dogmtime(kint secs) { Union* tu = new Union(NULL,9,false); struct tm ts; time_t t = (time_t)secs; gmtime_r(&t,&ts); // Union* mon = new Union(NULL,ts.tm_mon,0,false); // Union* wday = new Union(NULL,ts.tm_wday,0,false); tu->args[0]=mkint((void*)ts.tm_sec); tu->args[1]=mkint((void*)ts.tm_min); tu->args[2]=mkint((void*)ts.tm_hour); tu->args[3]=mkint((void*)ts.tm_mday); tu->args[4]=MKVAL((void*)ts.tm_mon,KVT_CUNION); tu->args[5]=mkint((void*)(ts.tm_year+1900)); tu->args[6]=MKVAL((void*)ts.tm_wday,KVT_CUNION); tu->args[7]=mkint((void*)ts.tm_yday); tu->args[8]=mkint((void*)ts.tm_isdst); return MKVAL((void*)tu,KVT_UNION); } KayaValue dolocaltime(kint secs) { Union* tu = new Union(NULL,9,false); struct tm ts; time_t t = (time_t)secs; localtime_r(&t,&ts); // Union* mon = new Union(NULL,ts.tm_mon,0,false); // Union* wday = new Union(NULL,ts.tm_wday,0,false); tu->args[0]=mkint((void*)ts.tm_sec); tu->args[1]=mkint((void*)ts.tm_min); tu->args[2]=mkint((void*)ts.tm_hour); tu->args[3]=mkint((void*)ts.tm_mday); tu->args[4]=MKVAL((void*)ts.tm_mon,KVT_CUNION); tu->args[5]=mkint((void*)(ts.tm_year+1900)); tu->args[6]=MKVAL((void*)ts.tm_wday,KVT_CUNION); tu->args[7]=mkint((void*)ts.tm_yday); tu->args[8]=mkint((void*)ts.tm_isdst); return MKVAL((void*)tu,KVT_UNION); } kint domktime(KayaValue time) { struct tm t; Union* tu = time->getUnion(); t.tm_sec = tu->args[0]->getInt(); t.tm_min = tu->args[1]->getInt(); t.tm_hour = tu->args[2]->getInt(); t.tm_mday = tu->args[3]->getInt(); t.tm_year = (tu->args[5]->getInt())-1900; t.tm_yday = tu->args[7]->getInt(); t.tm_isdst = tu->args[8]->getInt(); t.tm_mon = KayaUnionGetTag(tu->args[4]); t.tm_wday = KayaUnionGetTag(tu->args[6]); kint x = (kint)mktime(&t); return x; } kint getclock() { return (kint)(clock()); } #ifndef WIN32 kint runProgram(wchar_t* prog, KayaArray args) { char** argv = new char*[args->size()+2]; argv[0]=wctostr(prog); for(ukint i=0;isize();++i) { argv[i+1]=wctostr(args->lookup(i)->getString()->getVal()); } argv[args->size()+1]=NULL; pid_t pid = fork(); int status; if (pid==0) { execvp(wctostr(prog),argv); exit(0); } else { wait(&status); } delete argv; return status; } kint dofork() { kint i = (kint)fork(); if (i<0) { if (errno == ENOMEM) { return -1; } else if (errno == EAGAIN) { return -2; } } return i; } void reap() { waitpid(-1,NULL,WNOHANG); } kint dowait() { int status; wait(&status); return status; } kint dowaitpid(kint pid) { int status; waitpid(pid,&status,0); return (kint)status; } #endif kint dogetpid() { pid_t t = getpid(); return (kint)t; } bool do_wcschr(wchar_t c, wchar_t* s) { return wcschr(s,c)!=NULL; } kint do_wcscspn(wchar_t c, wchar_t* s) { wchar_t buf[2]; buf[0] = c; buf[1] = '\0'; return wcscspn(s,buf); } kint do_wcsstr(wchar_t* needle, wchar_t* haystack) { wchar_t* hptr = wcsstr(haystack,needle); if (hptr == NULL) { return -1; } else { return hptr-haystack; } } kint offset_wcscspn(wchar_t c, wchar_t* s, kint i) { wchar_t buf[2]; buf[0] = c; buf[1] = '\0'; return wcscspn(s+i,buf); } /** The following base64 functions are adapted from * http://base64.sourceforge.net/b64.c * By Bob Trower, Copyright (c) Trantor Standard Systems Inc., 2001 * See COPYING.b64 for redistribution conditions */ // Modified by CIM to work with wchar_t input and for other // integration with Kaya /* ** Translation Table as described in RFC1113 */ static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* ** Translation Table to decode (created by author) */ static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; /* ** encodeblock ** ** encode 3 8-bit binary bytes as 4 '6-bit' characters */ void encodeblock( unsigned char in[3], unsigned char out[4], kint len ) { out[0] = cb64[ in[0] >> 2 ]; out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '='); out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '='); } /* ** decodeblock ** ** decode 4 '6-bit' characters into 3 8-bit binary bytes */ void decodeblock( unsigned char in[4], unsigned char out[3] ) { out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4); out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2); out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]); } wchar_t* b64enc(wchar_t* wblock, kint len) { return strtowc(b64enc(wctostr(wblock),len)); } // since may want to encode binary data char* b64enc(char* block, kint len) { char* outblock = (char*)GC_malloc(sizeof(char)*len*2); unsigned char in[3], out[4]; int i,x,y; x=0; // Input pointer y=0; // Output pointer while(x=len) { in[i]=0; } else { unsigned char v = (unsigned char)block[x]; in[i]=v; } ++x; } encodeblock(in,out,3); for(i=0;i<4;++i) { outblock[y] = out[i]; ++y; } } outblock[y]='\0'; return outblock; } wchar_t* b64dec(wchar_t* wblock, KayaValue outlen) { return strtowc(b64dec(wctostr(wblock),outlen)); } // again, may want to return binary data char* b64dec(char* block, KayaValue outlen) { kint len = strlen(block); char* outblock = (char*)GC_malloc(sizeof(char)*len); unsigned char in[4], out[3]; kint i,x,y; x=0; // Input pointer y=0; // Output pointer while(x=len) { in[i]=0; } else { unsigned char v = (unsigned char)block[x]; v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]); if( v ) { v = (unsigned char) ((v == '$') ? 0 : v - 61); } in[i]=v-1; } ++x; } decodeblock(in,out); for(i=0;i<3;++i) { outblock[y] = out[i]; ++y; } } outblock[y]='\0'; KayaSetInt(outlen,y); return outblock; } /** End of Bob Trower's code */ typedef enum { GENERAL, INTQS, STRQS } QSver; void qs(VMState* vm, KayaArray xs,int l, int r,Closure* f, QSver version); int partition(VMState* vm, KayaArray xs, int l, int r, int pi, Closure* sortfn, QSver version); void quicksort(void* vmptr, KayaArray xs, KayaValue sortfn) { VMState* vm = (VMState*)vmptr; Closure* f = sortfn->getFunc(); qs(vm,xs,0,xs->size()-1,f, GENERAL); } void qs(VMState* vm,KayaArray xs,int l, int r,Closure* f, QSver version) { if (r>l) { int pi = partition(vm,xs,l,r,(l+r)/2,f, version); qs(vm,xs,l,pi-1,f, version); qs(vm,xs,pi+1,r,f, version); } } int partition(VMState* vm, KayaArray xs, int l, int r, int pi, Closure* sortfn, QSver version) { KayaValue xpi = xs->lookup(pi); Value pivotval_stack(NULL,xpi->getFunTable()); KayaValue pivotval=&pivotval_stack; Value tmp_stack(NULL,KVT_INT); KayaValue tmp=&tmp_stack; // static KayaValue pivotval = MKVAL(NULL,inttable); // static KayaValue tmp = MKVAL(NULL,inttable); pivotval->setPtr(xpi); // swap(xpi,xs->lookup(r)); KayaValue xsr = xs->lookup(r); KayaValue xssi, xsi; tmp->setPtr(xsr); xsr->setPtr(xpi); xpi->setPtr(tmp); /* cout << "Before Partition " << l << " - " << r << " : "; for(unsigned i=0;isize();i++) { cout << xs->lookup(i)->getInt() << ","; } cout << endl;*/ int si = l; int res; Value rv(NULL,KVT_NULL); for(int i=l; ilookup(i); xssi = xs->lookup(si); switch(version) { case INTQS: res = xsi->getInt()-pivotval->getInt(); break; case STRQS: res = wcscmp(xsi->getString()->getVal(), pivotval->getString()->getVal()); break; default: vm->push(&rv); vm->push(pivotval); vm->push(xsi); sortfn->run(vm); res = vm->doPop()->getInt(); break; } if (res<0) { tmp->setPtr(xssi); xssi->setPtr(xsi); xsi->setPtr(tmp); // swap(xs->lookup(si),xs->lookup(i)); ++si; } } // swap(xs->lookup(r),xs->lookup(si)); xssi = xs->lookup(si); tmp->setPtr(xsr); xsr->setPtr(xssi); xssi->setPtr(tmp); /* cout << "Partition: "; for(unsigned i=0;isize();i++) { cout << xs->lookup(i)->getInt() << ","; } cout << endl;*/ return si; } kint funtable_compare(void* vmptr,KayaValue x,KayaValue y) { #ifndef NOCHECK // NULL pointer for vmptr means something else is confident x and y exist if (vmptr != NULL && (x == NULL || x->getType() == KVT_NULL || y == NULL || y->getType() == KVT_NULL)) { VMState* vm = (VMState*)vmptr; vm->kaya_rtsError(INVALID_VALUE); } #endif kint r = 0; FUNTABLE_OP(cmp,x,y) return r; } bool funtable_equal(void* vmptr,KayaValue x, KayaValue y) { #ifndef NOCHECK if (vmptr != NULL && (x == NULL || x->getType() == KVT_NULL || y == NULL || y->getType() == KVT_NULL)) { VMState* vm = (VMState*)vmptr; vm->kaya_rtsError(INVALID_VALUE); } #endif valtype vt = x->getType(); switch (vt) { case KVT_INT: return inttable_fasteq(x,y); case KVT_STRING: return stringtable_fasteq(x,y); case KVT_REAL: return realtable_fasteq(x,y); case KVT_EXCEPTION: return exceptiontable_fasteq(x,y); default: map done; return funtable_equal_aux(x,y,done); } } bool funtable_equal_aux(KayaValue x, KayaValue y, map& done) { bool r = 0; if (x->getFunTable() != y->getFunTable()) { return 0; } switch (x->getFunTable()) { case KVT_INT: r = inttable_eq(x,y,done); break; case KVT_STRING: r = stringtable_eq(x,y,done); break; case KVT_FUNC: r = fntable_eq(x,y,done); break; case KVT_ARRAY: r = arraytable_eq(x,y,done); break; case KVT_CUNION: r = cuniontable_eq(x,y,done); break; case KVT_EXCEPTION: r = exceptiontable_eq(x,y,done); break; case KVT_REAL: r = realtable_eq(x,y,done); break; case KVT_NULL: r = inttable_eq(x,y,done); break; // can't happen case KVT_UNION: default: r = uniontable_eq(x,y,done); break; } return r; } kint funtable_memusage(KayaValue x) { kint r = 0; switch (x->getFunTable()) { case KVT_INT: r = inttable_memusage(x); break; case KVT_STRING: r = stringtable_memusage(x); break; case KVT_FUNC: r = fntable_memusage(x); break; case KVT_ARRAY: r = arraytable_memusage(x); break; case KVT_CUNION: r = cuniontable_memusage(x); break; case KVT_EXCEPTION: r = exceptiontable_memusage(x); break; case KVT_REAL: r = realtable_memusage(x); break; case KVT_NULL: r = inttable_memusage(x); break; case KVT_UNION: default: r = uniontable_memusage(x); break; } return r; } kint funtable_hash(KayaValue x) { vector done; return funtable_hash_aux(x,done); } kint funtable_hash_aux(KayaValue x,vector& done) { kint r = 0; switch (x->getFunTable()) { case KVT_INT: r = inttable_hash(x); break; case KVT_STRING: r = stringtable_hash(x); break; case KVT_FUNC: r = fntable_hash(x,done); break; case KVT_ARRAY: r = arraytable_hash(x,done); break; case KVT_CUNION: r = cuniontable_hash(x); break; case KVT_EXCEPTION: r = exceptiontable_hash(x); break; case KVT_REAL: r = realtable_hash(x); break; case KVT_NULL: r = inttable_hash(x); break; case KVT_UNION: default: r = uniontable_hash(x,done); break; } return r; } VMState* funtable_marshal(void* vmptr,KayaValue x, kint i) { VMState* vm = (VMState*)vmptr; #ifndef NOCHECK if (vmptr != NULL && (x == NULL || x->getType() == KVT_NULL)) { vm->kaya_rtsError(INVALID_VALUE); } #endif vector done; wchar_t mid[50]; // can be negative SWPRINTF(mid,50,MARSHAL2FORMAT,i,getFnHash()); String* idmdata = NEWPSTRING(vm->getSPool(),mid); funtable_marshal_aux(vmptr,idmdata,done,x,i); vm->strbuffer = idmdata->getVal(); // FIXME: this isn't strictly right, but as long as m_offset in // the String is 0 which it will be for this String, it's correct. vm->strbuflen = idmdata->space(); return vm; } void funtable_marshal_aux(void* vmptr,String* mdata,vector& done,KayaValue x, kint i) { VMState* vm = (VMState*)vmptr; switch (x->getFunTable()) { case KVT_INT: inttable_marshal(vm,mdata,done,x,i); break; case KVT_STRING: stringtable_marshal(vm,mdata,done,x,i); break; case KVT_FUNC: fntable_marshal(vm,mdata,done,x,i); break; case KVT_ARRAY: arraytable_marshal(vm,mdata,done,x,i); break; case KVT_CUNION: cuniontable_marshal(vm,mdata,done,x,i); break; case KVT_EXCEPTION: exceptiontable_marshal(vm,mdata,done,x,i); break; case KVT_REAL: realtable_marshal(vm,mdata,done,x,i); break; case KVT_NULL: inttable_marshal(vm,mdata,done,x,i); break; //can't happen case KVT_UNION: default: uniontable_marshal(vm,mdata,done,x,i); break; } } Value* funtable_reflect(void* vmptr,KayaValue x) { #ifndef NOCHECK if (vmptr != NULL && (x == NULL || x->getType() == KVT_NULL)) { VMState* vm = (VMState*)vmptr; vm->kaya_rtsError(INVALID_VALUE); } #endif map done; return funtable_reflect_aux(vmptr,done,x); } Value* funtable_reflect_aux(void* vmptr, map& done,KayaValue x) { VMState* vm = (VMState*)vmptr; Value* r; // = MKVAL(NULL,KVT_NULL); switch (x->getFunTable()) { case KVT_INT: r = inttable_reflect(vm,done,x); break; case KVT_STRING: r = stringtable_reflect(vm,done,x); break; case KVT_FUNC: r = fntable_reflect(vm,done,x); break; case KVT_ARRAY: r = arraytable_reflect(vm,done,x); break; case KVT_CUNION: r = cuniontable_reflect(vm,done,x); break; case KVT_EXCEPTION: r = exceptiontable_reflect(vm,done,x); break; case KVT_REAL: r = realtable_reflect(vm,done,x); break; case KVT_NULL: r = inttable_reflect(vm,done,x); break; //can't happen case KVT_UNION: default: r = uniontable_reflect(vm,done,x); break; } return r; } KayaValue reifyUnion(kint tag, kint arity) { return KayaUnion(tag, arity); } void reifyUnionArgs(KayaValue v, KayaArray flds) { for(ukint i=0;isize();++i) { KayaUnionSetArg(v,i,KayaArrayLookup(flds,i)); } } KayaValue reifyClosure(kint fnid, kint arity) { Closure* c = new Closure(NULL, getFn(fnid), arity, arity, false); return MKVAL((void*)c,KVT_FUNC); } void reifyClosureArgs(KayaValue v, KayaArray flds) { Closure* c = v->getFunc(); for(ukint i=0;isize();++i) { c->setArg(i,KayaArrayLookup(flds,i)); } } KayaValue funtable_copy(void* vmptr,KayaValue x) { VMState* vm = (VMState*)vmptr; #ifndef NOCHECK if (x == NULL || x->getType() == KVT_NULL) { vm->kaya_rtsError(INVALID_VALUE); } #endif valtype vt = x->getType(); switch (vt) { case KVT_INT: return inttable_fastcopy(vm,x); case KVT_STRING: return stringtable_fastcopy(vm,x); case KVT_REAL: return realtable_fastcopy(vm,x); case KVT_EXCEPTION: return exceptiontable_fastcopy(x); default: map done; return funtable_copy_aux(vm,x,done); } } KayaValue funtable_copy_aux(VMState* vm, KayaValue x, map& done) { KayaValue r; // = MKVAL(NULL,KVT_NULL); switch (x->getFunTable()) { case KVT_INT: r = inttable_fastcopy(vm,x); break; case KVT_STRING: r = stringtable_fastcopy(vm,x); break; case KVT_FUNC: r = fntable_copy(vm,x,done); break; case KVT_ARRAY: r = arraytable_copy(vm,x,done); break; case KVT_CUNION: r = cuniontable_copy(vm,x,done); break; case KVT_EXCEPTION: r = exceptiontable_fastcopy(x); break; case KVT_REAL: r = realtable_fastcopy(vm,x); break; case KVT_NULL: r = inttable_fastcopy(vm,x); break; //can't happen case KVT_UNION: default: r = uniontable_copy(vm,x,done); break; } return r; } bool is_initialised(KayaValue x) { return (x->getType() != KVT_NULL); } KayaValue unsafe_id(KayaValue x) { // cout << "Unsafe id: " << x->getRaw() << endl; return x; } wchar_t* getAddr(KayaValue x) { wchar_t* buf=(wchar_t*)GC_MALLOC_ATOMIC(65536*sizeof(wchar_t)); SWPRINTF(buf,65536,L"Address of value at %p is %p",x,x->getRaw()); return buf; } wchar_t* except_msg(KayaValue x) { return x->getExcept()->err->getVal(); } kint except_code(KayaValue x) { return (kint)x->getExcept()->code; } void except_dumpbt(KayaValue x) { x->getExcept()->dumpBacktrace(); } kint doGetFnID(KayaValue fn) { // if (fn->getType()!=KVT_FUNC) { return -1; } // cout << "Raw: " << fn->getRaw() << endl; return (kint)getFnID(fn->getFunc()->getfn()); } /*void callFnID(void* vmptr, kint id, KayaValue arg) { VMState* vm = (VMState*)vmptr; func f = getFn(id); if (f!=NULL) { PUSH(arg); f(vm); } else { vm->kaya_rtsError(UNKNOWN_FUNCTION_ID); } }*/ #ifndef WIN32 kint memusage() { /* struct rusage usage; int x = getrusage(RUSAGE_SELF,&usage); if (x!=0) return -1; int total = usage.ru_idrss+usage.ru_isrss+usage.ru_maxrss; return total; */ // struct mallinfo info = mallinfo(); // return info.arena; return 0; } #endif kint isNull(void* p) { return p==NULL; } kint isIdentical(KayaValue x, KayaValue y) { return (x->getRaw()==y->getRaw()); } /* Code to handle do_access() in IO.k // Added by Chris Morris, 18/6/05 */ kint do_access(wchar_t* pathname, KayaValue mode) { kint tag = KayaUnionGetTag(mode); kint acmode = 0; switch(tag) { case 0: acmode = F_OK; break; case 1: acmode = X_OK; break; case 2: acmode = W_OK; break; case 3: acmode = R_OK; break; } return (kint)access(wctostr(pathname),acmode); } #ifndef WIN32 kint getres(KayaValue lim, bool& ok) { ok = true; switch(KayaUnionGetTag(lim)) { case 0: return RLIMIT_AS; break; case 1: return RLIMIT_CORE; break; case 2: return RLIMIT_CPU; break; case 3: return RLIMIT_DATA; break; case 4: return RLIMIT_FSIZE; break; case 5: #ifdef RLIMIT_LOCKS return RLIMIT_LOCKS; #else ok = false; return 0; #endif break; case 6: #ifdef RLIMIT_MEMLOCK return RLIMIT_MEMLOCK; #else ok = false; return 0; #endif break; case 7: return RLIMIT_NOFILE; break; case 8: #ifdef RLIMIT_NPROC return RLIMIT_NPROC; #else ok = false; return 0; #endif break; case 9: #ifdef RLIMIT_RSS return RLIMIT_RSS; #else ok = false; return 0; #endif break; case 10: return RLIMIT_STACK; break; default: return RLIMIT_AS; // Can't happen anyway } } kint do_setrlimit(KayaValue lim, kint soft, kint hard) { struct rlimit r; if (soft==-1) { r.rlim_cur = RLIM_INFINITY; } else { r.rlim_cur=soft; } if (soft==-1) { r.rlim_max=RLIM_INFINITY; } else { r.rlim_max=hard; } bool ok; int res = getres(lim,ok); if (ok) { setrlimit(res,&r); return 1; } else { return 0; } } #endif kint do_unlink(const wchar_t* fn) { return unlink(wctostr(fn)); } wchar_t* dogetcwd() { unsigned int sz = 1024; char* buf; char* rv; do { buf = (char*)GC_MALLOC_ATOMIC(sz*sizeof(char)); rv = getcwd(buf,sz); sz = sz*2; } while (rv == NULL); return KSTRING(buf); } kint do_mkdir(const wchar_t* fn, kint um) { #ifdef WIN32 return mkdir(wctostr(fn)); #else return mkdir(wctostr(fn),um); #endif } void* do_opendir(wchar_t* name) { DIR* d = opendir(wctostr(name)); if (errno!=0) { // cout << strerror(errno) << endl; } return (void*)d; } kint do_closedir(void* dir) { return closedir((DIR*)dir); } void* do_readdir(void* dir) { struct dirent* ent = readdir((DIR*)dir); return (void*)ent; } VMState* dir_getname(void* vmptr, void* ent) { VMState* vm = (VMState*)vmptr; struct dirent* entd = (struct dirent*)ent; KVSTRING(vm,entd->d_name); return vm; } #define SSET(x,y) KayaUnionSetArg(val,x,KayaInt((int)(buf->y))) #define MSET(x,y) if (x(mode)) { \ KayaUnionSetArg(mval, y, KayaInt(1)); \ } else { \ KayaUnionSetArg(mval, y, KayaInt(0)); \ } #define MFSET(x,y) if (x & mode) { \ KayaUnionSetArg(mval, y, KayaInt(1)); \ } else { \ KayaUnionSetArg(mval, y, KayaInt(0)); \ } KayaValue getKayaMode(mode_t mode) { KayaValue mval = KayaUnion(0,13); KayaArray uperm = newKayaArray(3); KayaArray gperm = newKayaArray(3); KayaArray operm = newKayaArray(3); static KayaValue read = KayaUnion(0,0); static KayaValue write = KayaUnion(1,0); static KayaValue exec = KayaUnion(2,0); // User permissions if (S_IRUSR & mode) { KayaArrayPush(uperm, read); } if (S_IWUSR & mode) { KayaArrayPush(uperm, write); } if (S_IXUSR & mode) { KayaArrayPush(uperm, exec); } #ifndef WIN32 // Group permissions if (S_IRGRP & mode) { KayaArrayPush(gperm, read); } if (S_IWGRP & mode) { KayaArrayPush(gperm, write); } if (S_IXGRP & mode) { KayaArrayPush(gperm, exec); } // Other permissions if (S_IROTH & mode) { KayaArrayPush(operm, read); } if (S_IWOTH & mode) { KayaArrayPush(operm, write); } if (S_IXOTH & mode) { KayaArrayPush(operm, exec); } #endif KayaUnionSetArg(mval,0,KayaArrayVal(uperm)); KayaUnionSetArg(mval,1,KayaArrayVal(gperm)); KayaUnionSetArg(mval,2,KayaArrayVal(operm)); #ifndef WIN32 MSET(S_ISSOCK,3); #endif #ifdef S_ISLNK MSET(S_ISLNK,4); #endif MSET(S_ISREG,5); MSET(S_ISBLK,6); MSET(S_ISDIR,7); MSET(S_ISCHR,8); MSET(S_ISFIFO,9); #ifndef WIN32 MFSET(S_ISUID,10); MFSET(S_ISGID,11); MFSET(S_ISVTX,12); #endif return mval; } KayaValue do_stat(void* vmptr, wchar_t* name) { VMState* vm = (VMState*)vmptr; struct stat* buf = (struct stat*)KayaAlloc(sizeof(struct stat)); int ret = stat(wctostr(name), buf); if (ret==-1) { vm->kaya_internalError(errno); } KayaValue val = KayaUnion(0,5); SSET(1,st_nlink); SSET(2,st_atime); SSET(3,st_mtime); SSET(4,st_ctime); KayaUnionSetArg(val,0,getKayaMode(buf->st_mode)); return val; } kint maxMemUsage(void* vmptr) { VMState* vm = (VMState*)vmptr; return (kint)vm->maxMemUsage(); } VMState* do_urlencode(void* vm, wchar_t* strinwide, kint len) { // char strin[( len +1)*4]; // wcnptostr(strin,strinwide,len); CNPSTRING(si,strinwide,len); char* strin = si; VMState* vmptr = (VMState*)vm; int maxlen = strlen(strin)*3+1; char s[maxlen]; if (s==NULL) { // something broke, probably duff input. vmptr->kaya_internalError(1); } char* r = s; char* strout = s; while(*strin!='\0') { if (*strin==' ') { *strout = '+'; ++strout; } else if (ispunct(*strin) || *strin<32) { // 4 for length because we need to temporarily let snprintf // put a \0 there snprintf(strout,4,"%%%2x", (int)*strin); strout+=3; } else { *strout = *strin; ++strout; } ++strin; } *strout='\0'; KVSTRING(vmptr,r); return vmptr; } VMState* do_urldecode(void* vm, wchar_t* strinwide, kint len) { CNPSTRING(si,strinwide,len); char* strin = si; VMState* vmptr = (VMState*)vm; int maxlen = strlen(strin)+1; char s[maxlen]; char* strout = s; if (strout==NULL) { // something broke, probably duff input. vmptr->kaya_internalError(1); } char* r = strout; char buf[3]; char* convcheck; buf[2]='\0'; while(*strin!='\0') { if (*strin=='+') { *strout = ' '; ++strout; } else if (*strin == '%') { if (strlen(strin)<3) { vmptr->kaya_internalError(1); } buf[0] = strin[1]; buf[1] = strin[2]; *strout = (char)strtol(buf,&convcheck,16); if (*convcheck != '\0') { vmptr->kaya_internalError(1); } strin+=2; ++strout; } else { *strout = *strin; ++strout; } ++strin; } *strout='\0'; KVSTRING(vmptr,r); return vmptr; } void* do_fopen(const wchar_t* path, const wchar_t* mode) { return (void*)fopen(wctostr(path),wctostr(mode)); } void* do_freopen(const wchar_t* path, const wchar_t* mode, void* stream) { return (void*)freopen(wctostr(path),wctostr(mode),(FILE*)stream); } void do_rename(const wchar_t* oldfile, const wchar_t* newfile) { rename(wctostr(oldfile),wctostr(newfile)); } void do_chdir(const wchar_t* newdir) { chdir(wctostr(newdir)); } wchar_t* do_getenv(const wchar_t* env) { return strtowc(getenv(wctostr(env))); } #ifndef WIN32 kint do_system(const wchar_t* prog) { return system(wctostr(prog)); } void* do_popen(const wchar_t* prog, kint read) { if (read) { return (void*)popen(wctostr(prog),"r"); } else { return (void*)popen(wctostr(prog),"w"); } } kint do_pclose(void* stream) { return pclose((FILE*)stream); } #endif kint binary_length(const wchar_t* str, kint len) { CNPSTRING(rawstr,str,len); return (kint)strlen(rawstr); } kint nextPower(kint x) { kint next = 1; while(x>next) { next<<=1; } return next; } kint strAlloc(Value* str) { return str->getString()->space()*sizeof(wchar_t); } Value* createString(void* vmptr,kint len) { VMState* vm = (VMState*) vmptr; return MKPVAL(vm->getVPool(),(void*)(NEWPSTRING(vm->getSPool(),len)),KVT_STRING); } void do_GC_enable_incremental() { #ifdef NOCHECK GC_enable_incremental(); #endif } void runFn(void* obj, void* finalizer) { KayaCall((Value*)finalizer, 1, (Value*)obj); } void do_GC_finalizer(Value* obj, Value* finalizer) { GC_register_finalizer(obj, runFn, finalizer, NULL, NULL); } void do_sleep(kint len) { #ifdef WIN32 Sleep(len*1000); #else sleep(len); #endif } void do_usleep(kint len) { #ifdef WIN32 Sleep(len/1000); #else usleep(len); #endif } kint strHash(wchar_t* m, kint len) { int hash = 0; for(int i=0;i #define GC_THREADS #else #define GC_WIN32_THREADS #endif #include #include #include #include #include #include #include #include using namespace std; #include "VM.h" #include "VMState.h" VMState* initstack() { #ifdef __arm__ /* This works around a very wierd behaviour on arm with g++ -O2 where this function segfaults (see Debian build logs for 0.2.7) */ if (getenv("DISPLAY_KAYA_ARM_WIERDNESS") != NULL) { if (getenv("DISPLAY_KAYA_ARM_WIERDNESS") == NULL) { cout << "Starting" << endl; } } #endif return new VMState(); } void finish(VMState* vm) { vm->finish(); } Value* mkstr(const wchar_t* str) { return MKVAL((void*)(NEWSTRING(str)),KVT_STRING); } Value* mkstr2(VMState* vm,const wchar_t* str) { return MKPVAL(vm->getVPool(),(void*)(NEWPSTRING(vm->getSPool(),str)),KVT_STRING); } Value* mkint(void* i) { return MKVAL(i,KVT_INT); } Value* mkint2(VMState* vm, void* i) { return MKPVAL(vm->getVPool(),i,KVT_INT); } Value* mkarrayval(void* i) { return MKVAL(i,KVT_ARRAY); } /// Maths operators kint intpower(kint x, kint y) { return (kint)pow((double)x,(double)y); } double realpower(double x, double y) { return pow(x,y); } /// String conversions wchar_t* strtowc(const char* str) { int inlen = 0; if (str == NULL) { inlen = 0; } else { inlen = strlen(str); } wchar_t* dest = (wchar_t*)GC_MALLOC_ATOMIC(sizeof(wchar_t)*(inlen+1)); mkUCS(str,dest,inlen); return dest; } void strtovwc(VMState* vm, const char* str) { int inlen = 0; if (str == NULL) { inlen = 0; } else { inlen = strlen(str); } wchar_t* dest = (wchar_t*)GC_MALLOC_ATOMIC(sizeof(wchar_t)*(inlen+1)); mkUCS(str,dest,inlen); vm->strbuffer = dest; vm->strbuflen = inlen+1; } wchar_t chrtowc(const char chr) { return *strtowc(&chr); } char* wctostr(const wchar_t* wc) { ukint len = wcslen(wc); return wcntostr(wc,len); } void wcnptostr(const wchar_t* wc, kint len, char* target) { mkUTF8(wc,target,len); } char* wcntostr(const wchar_t* wc, kint len) { char* dest = (char*)GC_MALLOC_ATOMIC(sizeof(char)*(++len)*4); mkUTF8(wc,dest,len); return dest; } // note that even one wchar_t may be bigger than a char... char wctochr(const wchar_t c) { // result is therefore undefined if wchar_t represents something outside 0-127 return *wctostr(&c); } /* UTF8 mbc constructor based on Jeff Bezanson's public domain code */ void mkUTF8(const wchar_t* raw, char* dest, ukint len) { // char* dest = (char*)GC_MALLOC_ATOMIC(sizeof(char)*(1+wcslen(raw))*4); int dpos = -1; for (ukint i=0;i>6) | 0xC0; dest[++dpos] = (ch & 0x3F) | 0x80; } else if (ch < 0x10000) { dest[++dpos] = (ch>>12) | 0xE0; dest[++dpos] = ((ch>>6) & 0x3F) | 0x80; dest[++dpos] = (ch & 0x3F) | 0x80; } else if (ch < 0x200000) { dest[++dpos] = (ch>>18) | 0xF0; dest[++dpos] = ((ch>>12) & 0x3F) | 0x80; dest[++dpos] = ((ch>>6) & 0x3F) | 0x80; dest[++dpos] = (ch & 0x3F) | 0x80; } } dest[++dpos] = '\0'; } /* UTF8 mbc unconstructor loosely based on Jeff Bezanson's public domain code */ void mkUCS(const char* utf8, wchar_t* dest, kint inlen) { int cpos = 0; int dpos = -1; while (cpos < inlen) { unsigned char first = (unsigned char)utf8[cpos]; // cout << first << endl; if (first < 128) { // single byte character dest[++dpos] = (wchar_t)first; ++cpos; } else if (first < 192) { // bad continuation character, skip it. ++cpos; } else if (first < 224 && cpos+1 < inlen) { // two-byte character dest[++dpos] = (wchar_t)((((int)utf8[cpos] & 31) << 6) + ((int)utf8[cpos+1] & 63)); cpos+=2; } else if (first < 240 && cpos+2 < inlen) { // three-byte character // cout << "three-byte = " << first << endl; dest[++dpos] = (wchar_t)((((int)utf8[cpos] & 15) << 12) + (((int)utf8[cpos+1] & 63) << 6) + (((int)utf8[cpos+2] & 63))); cpos+=3; } else if (first < 248 && cpos+3 < inlen) { // four-byte character dest[++dpos] = (wchar_t)((((int)utf8[cpos] & 7) << 18) + (((int)utf8[cpos+1] & 63) << 12) + (((int)utf8[cpos+2] & 63) << 6) + ((int)utf8[cpos+3] & 63)); cpos+=4; } else { // start of illegal 5+-byte character? skip it ++cpos; } } dest[++dpos] = '\0'; } kaya-0.4.4/rts/repl_glue.cc0000644000175100017510000001117111170340770013646 0ustar cimcim#ifdef WIN32 /* Wu Yongwei's quick hacks for MinGW, referenced in http://osdir.com/ml/gnu.mingw.devel/2003-03/msg00070.html */ #include #include #define dlsym(D,F) (void*)GetProcAddress((HMODULE)D,F) #define dlerror() (char*)GetLastError() #define dlopen(P,G) (void*)LoadLibrary(P) #define dlclose(D) FreeLibrary((HMODULE)D) #else #include #endif #include #include "repl_glue.h" #define OP_PLUS 0 #define OP_MINUS 1 #define OP_TIMES 2 #define OP_DIVIDE 3 #define OP_MODULO 4 #define OP_POWER 5 #define OP_EQUAL 6 #define OP_NEQUAL 7 #define OP_LT 8 #define OP_GT 9 #define OP_LE 10 #define OP_GE 11 #define OP_AND 12 #define OP_OR 13 #define OP_XOR 14 #define OP_BAND 15 #define OP_BOR 16 #define OP_SHLEFT 17 #define OP_SHRIGHT 18 #define OP_ANDBOOL 19 #define OP_ORBOOL 20 #define OP_NOT 0 #define OP_NEG 1 static VMState* vm; void interp_init() { GC_init(); vm = initstack(); } /* void interp_load(const char* pathname) { program = dlopen(pathname, RTLD_LAZY); if (program==NULL) { cout << dlerror() << endl; exit(-1); } } */ void interp_prepare_call() { // Create space for the result on the stack vm->push(newKayaValue()); } void interp_clear() { while(!vm->emptyStack()) { vm->discardPop(); } } void interp_push_int(kint v) { vm->push(MKINT(v)); } void interp_push_float(double v) { vm->push(MKREAL(v)); } void interp_push_string(char* v) { vm->push(MKSTR(KSTRING(v))); } // Call a function in the given vm, in the loaded program. // FIXME: This has to deal with exceptions at some point! Probably putting // try/catch VM instructions around it will work... kint interp_call(void* handle, const char* function) { // Look up the function symbol and run it func sym = (func)(dlsym(handle, function)); if (sym==NULL) { cout << dlerror() << endl; exit(-1); } TRY(catchcode); sym(vm); TRIED; JUMP(okay); LABEL(catchcode); PRINTEXC; return 0; LABEL(okay); return 1; } void interp_array(kint len) { MKARRAY(len); } void interp_op(kint opid) { kint l,r; kint ans = 0; GETVAL(l); GETVAL(r); switch(opid) { case OP_PLUS: ans = l+r; break; case OP_MINUS: ans = l-r; break; case OP_TIMES: ans = l*r; break; case OP_DIVIDE: ans = l/r; break; case OP_MODULO: ans = l%r; break; case OP_POWER: ans = intpower(l, r); break; case OP_EQUAL: ans = l == r; break; case OP_NEQUAL: ans = l != r; break; case OP_LT: ans = l < r; break; case OP_GT: ans = l > r; break; case OP_LE: ans = l <= r; break; case OP_GE: ans = l >= r; break; case OP_AND: ans = l & r; break; case OP_OR: ans = l | r; break; case OP_XOR: ans = l ^ r; break; case OP_BAND: ans = l && r; break; case OP_BOR: ans = l || r; break; case OP_SHLEFT: ans = l << r; break; case OP_SHRIGHT: ans = l >> r; break; case OP_ANDBOOL: ans = l && r; break; case OP_ORBOOL: ans = l || r; break; default: cerr << "Warning; unknown operator" << endl; } vm->push(mkint((void*)ans)); } void interp_floatopfn(kint opid) { double l,r; double ans = 0; GETRVAL(l); GETRVAL(r); switch(opid) { case OP_PLUS: ans = l+r; break; case OP_MINUS: ans = l-r; break; case OP_TIMES: ans = l*r; break; case OP_DIVIDE: ans = l/r; break; case OP_POWER: ans = realpower(l, r); break; case OP_EQUAL: ans = l == r; break; case OP_NEQUAL: ans = l != r; break; case OP_LT: ans = l < r; break; case OP_GT: ans = l > r; break; case OP_LE: ans = l <= r; break; case OP_GE: ans = l >= r; break; default: cerr << "Warning; unknown operator" << endl; } vm->push(MKREAL(ans)); } void interp_unop(kint opid) { kint l; kint ans = 0; GETVAL(l); switch(opid) { case OP_NOT: ans = !l; break; case OP_NEG: ans = -l; break; default: cerr << "Warning; unknown operator" << endl; } vm->push(mkint((void*)ans)); } void interp_floatunop(kint opid) { double l; double ans = 0; GETRVAL(l); switch(opid) { case OP_NEG: ans = -l; break; default: cerr << "Warning; unknown operator" << endl; } vm->push(MKREAL(ans)); } void interp_append() { APPEND; } void interp_str2int() { STR2INT; } void interp_int2str() { INT2STR; } void interp_str2real() { STR2REAL; } void interp_real2str() { REAL2STR; } void interp_str2chr() { STR2CHR; } void interp_chr2str() { CHR2STR; } void interp_int2real() { INT2REAL; } void interp_real2int() { REAL2INT; } void interp_bool2str() { BOOL2STR; } kaya-0.4.4/rts/VM.h0000644000175100017510000002434411170340770012062 0ustar cimcim#ifndef _VM_H // -*-C++-*- #define _VM_H /** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ using namespace std; #include "Heap.h" #include #include #include //#include "stdfuns.h" #include "Array.h" #include "ValueFuns.h" #include "Closure.h" #include #include class VMState; //extern VMState* vm; #define STARTFN int tmp; #define DECLARE(x) Value *x = NEWVAL; x->setInt(0); // Args get initialised immediately anyway #define DECLAREARG(x) Value stack_##x(NULL,KVT_INT); #define DECLAREQUICK(x) Value stack_##x(NULL,KVT_INT); Value* x = &stack_##x; #define HEAPVAL(x) if (x==&stack_##x) { x = MKPVAL(vm->getVPool(),stack_##x.getRaw(), stack_##x.getFunTable()); } // cout << "Made heap val of " << &stack_##x << " -> " << x << endl; cout << x->getRaw() << endl; } //#define DECLAREQUICK(x) Value *x = new Value(NULL,inttable); #define TMPINT(x) int x #define TMPREAL(x) double x //#define ARRAY(x) x=new Value(ARRAY); #define MKINT(x) mkint2(vm,(void*)(x)) //&(Value((void*)x,inttable)) #define MKREAL(x) (MKPVAL(vm->getVPool(),(void*)(NEWPREAL(vm->getRPool(),x)),KVT_REAL)) #define MKCHAR(x) (MKPVAL(vm->getVPool(),(void*)((int)x),KVT_INT)) #define MKFUN(x,i) (MKPVAL(vm->getVPool(),(void*)(new Closure(vm,x,0,i,false)),KVT_FUNC)) #define MKSTR(x) mkstr2(vm,x) #define EMPTYSTR (MKPVAL(vm->getVPool(),(void*)(NEWPSTRING(vm->getSPool(),(wchar_t*)NULL)),KVT_STRING)) //doesn't work any more //#define MKUNION(x) (MKVAL((void*)x,KVT_UNION)) #define MKCON(t,a) vm->push(MKPVAL(vm->getVPool(),new(vm->getUPool()) Union(vm,a),KVT_UNION+t)); #define MKCONRV(t,a) vm->pushrv((void*)(new(vm->getUPool()) Union(vm,a)),KVT_UNION+t); #define MKNEWEXCEPT(e,a) vm->pushrv((void*)(new Exception(vm,e,a)),KVT_EXCEPTION) #define MKCONZERO(t) { vm->push(MKPVAL(vm->getVPool(),(void*)t,KVT_CUNION)); } #define MKCONZERORV(t) { vm->pushrv((void*)t,KVT_CUNION); } #define MKEXCEPT vm->push(MKPVAL(vm->getVPool(),(void*)(new Exception(vm)),KVT_EXCEPTION)) //#define SET(x,i,y) x->setIdxPtr(y,i); #define MKARRAYVAL(x) mkarrayval((void*)(x)) #define TOINDEX vm->goToIndex(); #define TOFIELD(i) vm->goToField(i); #define MKARRAY(i) vm->mkArray(i) #define MKARRAY2(s,i) vm->mkArray(s,i) #define CALL(x) (x(vm)); //vm->push(vm->getReturnVal()); #define CALLFUN(x) (x->runClosure(vm)); //vm->push(vm->getReturnVal()); #define TAILCALL(x) (x(vm)) #define TAILCALLFUN(x) (x->runClosure(vm)) #define CALLTOP (vm->doPop()->runClosure(vm)); //vm->push(vm->getReturnVal()); #define TAILCALLTOP (vm->doPop()->runClosure(vm)) #define CLOSURE(x,i,tot,lam) vm->push(MKPVAL(vm->getVPool(),(void*)(new Closure(vm,x,i,tot,lam)),KVT_FUNC)) #define CLOSURELOC(x,i,lam) vm->push(x->clone()->addClosureArgs(vm,i,lam)); #define CLOSURETOP(i,lam) vm->push(vm->doPop()->clone()->addClosureArgs(vm,i,lam)); //#define GETFUN(x) (x->getFunc()) #define GETVAL(t) (t=vm->doPop()->getInt()) #define TOPINT vm->topItem()->getInt() #define PUSHGETVAL(x,t) t=x->getInt() #define GETRVAL(t) (t=vm->doPop()->getReal()) #define INTGETRVAL(t) t=vm->topint2real(); #define PUSHGETRVAL(x,t) t=x->getReal() #define GETINDEX vm->getindex(); #define INTINFIX(t,op,x,y) t=(x op y) #define ADDINPLACE(t,x) t->addInt(x); #define SUBINPLACE(t,x) t->addInt(-x); #define INTDIV(t,x,y) if (y==0) { vm->divideByZero(); } else { t=(x/y); } #define REALINFIX(t,op,x,y) t=(x op y) #define REALDIV(t,x,y) if (y==0) { vm->divideByZero(); } else { t=(x/y); } #define REALINFIXBOOL(op,x,y) vm->push(mkint2(vm,(void*)(x op y))) // CIM: optimise infix jumps #define INFIXJFALSE(op,x,y,l) if ((x op y)==0) goto l #define INFIXJTRUE(op,x,y,l) if ((x op y)!=0) goto l #define UNARYJFALSE(op,x,l) if ((op x)==0) goto l #define UNARYJTRUE(op,x,l) if ((op x)!=0) goto l #define INTUNARY(t,op,x) t=(op x) #define REALUNARY(t,op,x) t=(op x) #define INTPOWER(t,x,y) t=intpower(x,y); #define REALPOWER(t,x,y) t=realpower(x,y); #define APPEND vm->doAppend(); #define APPENDINT(x) vm->doAppendChar(x); #define APPENDSTR(x) vm->doAppendStr(x); #define EQEXCEPT vm->doEqExcept(false); #define NEEXCEPT vm->doEqExcept(true); #define EQSTRING vm->doEqString(); #define NESTRING vm->doNeString(); #define EQSTRINGW(x) vm->doEqString(x); #define NESTRINGW(x) vm->doNeString(x); #define JEQSTRING(l) if(vm->doPop()->getString()->eq(vm->doPop()->getString())) goto l #define JNESTRING(l) if(!vm->doPop()->getString()->eq(vm->doPop()->getString())) goto l #define JEQSTRINGW(l,x) if(vm->doPop()->getString()->eq(x)) goto l #define JNESTRINGW(l,x) if(!vm->doPop()->getString()->eq(x)) goto l #define TOPSTREQ(x) vm->doTopStrEq(x) //#define TOPEXCEQ(x) vm->doTopExcEq(x) #define PRINTINT cout << vm->doPop()->getInt(); #define PRINTSTR vm->writestdout(); #define PRINTEXC vm->doPop()->getExcept()->dumpBacktrace(); #define NEWLINE cout << endl #define LABEL(x) x: #define JUMP(x) goto x #define JZ(x,y) if ((x->getInt())==0) goto y #define JNZ(x,y) if ((x->getInt())!=0) goto y #define JNEG(x,y) if ((x->getInt())<0) goto y #define JPOS(x,y) if ((x->getInt())>0) goto y #define JFALSE(x) if (vm->doPop()->getInt()==0) goto x #define JTRUE(x) if (vm->doPop()->getInt()!=0) goto x #define JTFALSE(t,x) if (t==0) goto x #define JTTRUE(t,x) if (t!=0) goto x #define JEXNE(ex,l) if (vm->topItem()->getExcept()->tag != ex) goto l #define PUSH(x) vm->push(x) #define PUSH2(x,y) vm->push2(x,y) #define PUSH3(x,y,z) vm->push3(x,y,z) #define PUSH4(x,y,z,w) vm->push4(x,y,z,w) #define TMPSETTOP(t) vm->tmpsettop(t) #define PUSHSETTOP(x) vm->pushsettop(x); #define PUSHGETINDEX(x) vm->pushgetindex(x); #define SETLOOKUP(i,x) vm->setlookup(i,x); #define PUSHTOINDEX(x) vm->pushToIndex(x); #define DUMMY vm->push(MKVAL(0,KVT_INT)) #define POP(x) x->setPtr(vm->doPop()) #define POPARG(x) x=vm->doPop() //#define POPANDCOPYARG(x) x=vm->doPop() //#define POPANDCOPYARG(x) x=new Value(vm->topItem()->getRaw(), // vm->topItem()->getFunTable()); vm->doPop(); //#define POPANDCOPYARG(x) memcpy(&(stack_##x),(vm->doPop()),8); #define POPANDCOPYARG(x) stack_##x.setPtr(vm->doPop()); #define COPYARG(x) stack_##x.setPtr(x); x = &stack_##x; #define NOTEVAR(x) Value* remem_##x = x; #define REMEMBER(x) remem_##x->setPtr(x); #define DISCARD vm->discardPop() #define STACKINT(x,i) stack_##x.setInt(i); vm->push(x); #define STACKREAL(x,r) stack_##x.setReal(r); vm->push(x); // doesn't quite work yet #define STACKSTR(x,s) stack_##x.setString(new(vm->getSPool()) String(s)); vm->push(x); #define STACKRAW(x,i) stack_##x.setPtr((void*)(i), KVT_INT); vm->push(x); //#define SETVAL(x,y) x->setPtr(new Value((void*)y)); #define SETINT(x,y) x->setInt(y); #define SETVAR(x,y) x->setPtr(y); #define SETRV vm->setRV() #define SETRVREAL(r) vm->setRVreal(r) #define SETTOP vm->setTop(); #define ADDTOP vm->addTop(); #define SUBTOP vm->subTop(); #define MULTOP vm->mulTop(); #define DIVTOP vm->divTop(); #define APPENDTOP vm->appendTop(); #define APPENDTOPINT vm->appendTopInt(); #define PROJ(x,i) x->fastproject(vm->topItem(),i); #define PROJARG(a,t) vm->projarg(a,t); #define SETPROJARG(s,a,t,d) vm->setprojarg(s,a,t,d); #define EXPROJARG(x,i) x->exceptionproject(vm->topItem(),i); /* CIM 12/7/05: changed ERROR to KERROR for MinGW compatibility */ #define KERROR cerr << vm->doPop()->getString()->getVal(); exit(-1); #define PUSHGLOBAL(t,i) vm->push(KAYA_GLOBAL_##i) //#define PUSHGLOBAL(t,i) vm->pushglobal(t,i) #define CREATEGLOBAL(x,i) vm->newglobal(x,i) // definitely don't use MKPVAL here! #define DECLGLOBAL(i) static Value* KAYA_GLOBAL_##i = MKINITVAL(0, KVT_INT); #define TAG vm->tag() #define VMPTR vm->push(MKPVAL(vm->getVPool(),(void*)vm,KVT_INT)); #define STRLENGTH vm->push(MKPVAL(vm->getVPool(),(void*)(vm->doPop()->getString()->length()),KVT_INT)) #define GETLENGTH vm->push(MKPVAL(vm->getVPool(),(void*)(vm->topItem()->length()),KVT_INT)) #define GETFNID vm->push(MKPVAL(vm->getVPool(),(void*)(getFnID(vm->doPop()->getFunc())),KVT_INT)) // Coercions #define STR2INT vm->str2int(); #define INT2STR vm->int2str(); #define REAL2STR vm->real2str(); #define STR2REAL vm->str2real(); #define STR2CHR vm->str2chr(); #define CHR2STR vm->chr2str(); #define BOOL2STR vm->bool2str(); #define INT2REAL vm->int2real(); #define REAL2INT vm->real2int(); /* CIM 12/7/05: changed VOID to KVOID for MinGW compatibility */ #define KVOID(x) x // Exceptions #define TRY(x) \ vm->newjmp_buf(); \ if (setjmp(*(vm->top_ex()))==2) goto x; \ #define THROW vm->throw_ex(); #define TRIED vm->tried(); #define RESTORE vm->restore(); #define CHECKCACHE(x) #define STORECACHE0() //cache.addEntry(vm->topItem()); #define STORECACHE1(x) #define STORECACHE2(x,y) #define STORECACHE3(x,y,z) #define STORECACHE4(x,y,z,w) #define RETURN return; //vm->returnVal(vm->doPop()); return; #define GETRETURNED vm->push(vm->getReturnVal()); #define NOP #ifdef NOCHECK #define LINENO(f,l) #define PUSHBT(fn,f,l) #define INLAM(f) #define POPBT /* #define CHECKCACHE(x) static FnCache cache(vm); \ static Value* cache_val; \ if (cache_val = cache.checkCache(x)) { vm->push(cache_val); return; } */ #define RTCHECKS 0 #else //#define LINENO(f,l) vm->memstat(); vm->lineno(f,l) #define LINENO(f,l) vm->lineno(f,l); #define PUSHBT(fn,f,l) vm->pushBT(fn,f,l) #define INLAM(f) vm->pushBT(f,f,-1) #define POPBT vm->popBT() #define RTCHECKS 1 /* #define CHECKCACHE(x) static FnCache cache(vm); \ static Value* cache_val; \ if (cache_val = cache.checkCache(x)) { vm->popBT(); vm->push(cache_val); return; } */ #endif VMState* initstack(); void finish(VMState* vm); Value* mkstr(const wchar_t* str); Value* mkstr2(VMState* vm,const wchar_t* str); Value* mkint(void* i); Value* mkint2(VMState* vm,void* i); Value* mkarrayval(void* i); /// Maths operators. kint intpower(kint x, kint y); double realpower(double x, double y); /// Wide char/string conversions wchar_t* strtowc(const char* str); void strtovwc(VMState* vm, const char* str); wchar_t chrtowc(const char str); char* wctostr(const wchar_t* wc); char* wcntostr(const wchar_t* wc, kint len); // must manually ensure that char* target can hold (worst-case) // 4*len*sizeof(char) bytes when using wcnptostr void wcnptostr(const wchar_t* wc, kint len, char* target); char wctochr(const wchar_t* c); void mkUCS(const char* utf8, wchar_t* dest, kint inlen); void mkUTF8(const wchar_t* raw, char* c, ukint len); #endif kaya-0.4.4/rts/repl_glue.h0000644000175100017510000000227211170340770013512 0ustar cimcim#ifndef _REPL_GLUE_H #define _REPL_GLUE_H #include "KayaAPI.h" #include "VMState.h" extern "C" { // Load a program, living in a shared object // void interp_load(const char* pathname); // Initialise the interpreter (i.e. set up garbage collection) void interp_init(); // Push a value onto the stack for the return value of a function void interp_prepare_call(); // Clear the stack void interp_clear(); // Push values void interp_push_int(kint v); void interp_push_float(double v); void interp_push_string(char* v); // Call a function in the given vm, in the loaded program. kint interp_call(void* handle, const char* function); // Make an array void interp_array(kint size); // Run operators void interp_op(kint opid); void interp_floatopfn(kint opid); void interp_unop(kint opid); void interp_floatunop(kint opid); void interp_append(); // Coercions void interp_str2int(); void interp_int2str(); void interp_str2real(); void interp_real2str(); void interp_str2chr(); void interp_chr2str(); void interp_int2real(); void interp_real2int(); void interp_bool2str(); } #endif kaya-0.4.4/rts/FnCache.h0000644000175100017510000000141411170340766013025 0ustar cimcim#ifndef _FNCACHE_H // -*-C++-*- #define _FNCACHE_H class Value; class VMState; // Cache for pure function results. Currently only handles nullary // functions (so handy for complicated constant functions, for example). // HOWEVER: I'm not sure this is actually valid in general... so it remains // unimplemented for the moment. Consider, for example, the pure function // which creates a structure, but then that structure gets modified, thus // invalidating the cache. Curse these mutable structures! class FnCache { public: FnCache(VMState* vm); void addEntry(Value* result); void addEntry(Value* arg1, Value* result); Value* checkCache(int args); private: VMState* m_vm; Value** m_cache; Value** m_cacheptr; Value** m_cacheend; }; #endif kaya-0.4.4/rts/sizes.h.in0000644000175100017510000000276711170340770013307 0ustar cimcim#ifndef _SIZES_H #define _SIZES_H #if @GTOD_INTERNAL@ == 1 #define GTOD_INTERNAL #endif #if @ac_cv_sizeof_int@ == @ac_cv_sizeof_voidp@ #define KAYA_SHORT_INTS 1 typedef int kint; typedef unsigned int ukint; #define DIGITFORMAT L"%d" #define SDIGITFORMAT "%d" #define INTMARSHAL L"I[%d]" #define MARSHAL2FORMAT L"[%d][%d]" #ifdef WIN32 #define STRMARSHAL L"S[[%d][%d]%s]" #else #define STRMARSHAL L"S[[%d][%d]%S]" #endif #define CIRCMARSHAL L"C[%d]" #define FUNMARSHAL L"F[[%d]" #define ARRMARSHAL L"A[[%d][%d]" #define UNIMARSHAL L"U[[%d]" #elif @ac_cv_sizeof_long@ == @ac_cv_sizeof_voidp@ #define KAYA_LONG_INTS 1 typedef long kint; typedef unsigned long ukint; #define DIGITFORMAT L"%ld" #define SDIGITFORMAT "%ld" #define INTMARSHAL L"I[%ld]" #define MARSHAL2FORMAT L"[%ld][%ld]" #ifdef WIN32 #define STRMARSHAL L"S[[%ld][%ld]%s]" #else #define STRMARSHAL L"S[[%ld][%ld]%S]" #endif #define CIRCMARSHAL L"C[%ld]" #define FUNMARSHAL L"F[[%ld]" #define ARRMARSHAL L"A[[%ld][%ld]" #define UNIMARSHAL L"U[[%d]" #elif @ac_cv_sizeof_long_long@ == @ac_cv_sizeof_voidp@ #define KAYA_VERYLONG_INTS 1 typedef long long kint; typedef unsigned long long ukint; #define DIGITFORMAT L"%lld" #define SDIGITFORMAT "%lld" #define INTMARSHAL L"I[%lld]" #define MARSHAL2FORMAT L"[%lld][%lld]" #ifdef WIN32 #define STRMARSHAL L"S[[%lld][%lld]%s]" #else #define STRMARSHAL L"S[[%lld][%lld]%S]" #endif #define CIRCMARSHAL L"C[%lld]" #define FUNMARSHAL L"F[[%lld]" #define ARRMARSHAL L"A[[%lld][%lld]" #define UNIMARSHAL L"U[[%d]" #endif #endif kaya-0.4.4/rts/COPYING0000644000175100017510000006346311170340764012432 0ustar cimcim GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 library 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 Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! kaya-0.4.4/rts/ValueFuns.h0000644000175100017510000001016011170340770013437 0ustar cimcim#ifndef _VALUEFUNS_H #define _VALUEFUNS_H /** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ #include #include #include "sizes.h" class Value; class VMState; class String; typedef kint valtype; // doesn't really matter what order these go in, as long as KVT_UNION is zero, // and all the others are negative. Any positive is then the U_TAG. // valtype being signed #define KVT_INT -8 #define KVT_CUNION -7 #define KVT_STRING -6 #define KVT_FUNC -5 #define KVT_ARRAY -4 #define KVT_EXCEPTION -3 #define KVT_REAL -2 #define KVT_NULL -1 #define KVT_UNION 0 //typedef enum { KVT_NULL, KVT_INT, KVT_STRING, KVT_FUNC, KVT_ARRAY, KVT_UNION, KVT_EXCEPTION, KVT_REAL } valtype; extern "C" { kint inttable_eq(Value*, Value*, map& done); kint inttable_fasteq(Value*, Value*); kint inttable_cmp(Value*, Value*); Value* inttable_fastcopy(VMState*,Value*); void inttable_marshal(VMState*, String*, vector&, Value*, kint id); Value* inttable_reflect(VMState*, map&, Value*); int inttable_memusage(Value*); kint inttable_hash(Value*); kint fntable_eq(Value*, Value*, map& done); kint fntable_cmp(Value*, Value*); Value* fntable_copy(VMState*, Value*, map& done); void fntable_marshal(VMState*, String*, vector&, Value*, kint id); Value* fntable_reflect(VMState*, map&, Value*); int fntable_memusage(Value*); kint fntable_hash(Value*,vector&); kint realtable_eq(Value*, Value*, map& done); kint realtable_fasteq(Value*, Value*); kint realtable_cmp(Value*, Value*); Value* realtable_fastcopy(VMState*,Value*); void realtable_marshal(VMState*, String*, vector&, Value*, kint id); Value* realtable_reflect(VMState*, map&, Value*); int realtable_memusage(Value*); kint realtable_hash(Value*); kint stringtable_eq(Value*, Value*, map& done); kint stringtable_fasteq(Value*, Value*); kint stringtable_cmp(Value*, Value*); Value* stringtable_fastcopy(VMState*,Value*); void stringtable_marshal(VMState*, String*, vector&, Value*, kint id); Value* stringtable_reflect(VMState*, map&, Value*); int stringtable_memusage(Value*); kint stringtable_hash(Value*); kint arraytable_eq(Value*, Value*, map& done); kint arraytable_cmp(Value*, Value*); Value* arraytable_copy(VMState*, Value*, map& done); void arraytable_marshal(VMState*, String*, vector&, Value*, kint id); Value* arraytable_reflect(VMState*, map&, Value*); int arraytable_memusage(Value*); kint arraytable_hash(Value*,vector&); kint uniontable_eq(Value*, Value*, map& done); kint uniontable_cmp(Value*, Value*); Value* uniontable_copy(VMState*, Value*, map& done); void uniontable_marshal(VMState*, String*, vector&, Value*, kint id); Value* uniontable_reflect(VMState*, map&, Value*); int uniontable_memusage(Value*); kint uniontable_hash(Value*,vector&); kint cuniontable_eq(Value*, Value*, map& done); kint cuniontable_cmp(Value*, Value*); Value* cuniontable_copy(VMState*, Value*, map& done); void cuniontable_marshal(VMState*, String*, vector&, Value*, kint id); Value* cuniontable_reflect(VMState*, map&, Value*); int cuniontable_memusage(Value*); kint cuniontable_hash(Value*); kint exceptiontable_eq(Value*, Value*, map& done); kint exceptiontable_fasteq(Value*, Value*); kint exceptiontable_cmp(Value*, Value*); Value* exceptiontable_fastcopy(Value*); void exceptiontable_marshal(VMState*, String*, vector&, Value*, kint id); Value* exceptiontable_reflect(VMState*, map&, Value*); int exceptiontable_memusage(Value*); kint exceptiontable_hash(Value*); } #endif kaya-0.4.4/rts/ValueFuns.cc0000644000175100017510000003567611170340770013620 0ustar cimcim/** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ #include "VMState.h" #include "VM.h" #include "Heap.h" #include "ValueFuns.h" #include "stdfuns.h" #include "Closure.h" /// Functions on int kint inttable_eq(Value* x, Value* y, map& done) { return (x->getInt()==y->getInt()); } kint inttable_fasteq(Value* x, Value* y) { return (x->getInt()==y->getInt()); } kint inttable_hash(Value* x) { return x->getInt(); } kint inttable_cmp(Value* x, Value* y) { int xi = x->getInt(); int yi = y->getInt(); if (xigetVPool(),(void*)(x->getInt()),KVT_INT); } void inttable_marshal(VMState* vm,String* mdata,vector& done,Value* x, kint id) { wchar_t buf[50]; SWPRINTF(buf,50,INTMARSHAL,x->getInt()); mdata->append(buf); } Value* inttable_reflect(VMState* vm,map& done,Value* x) { Value* v = KayaUnion(0,1); Value* i = KayaInt(x->getInt()); KayaUnionSetArg(v,0,i); return v; } int inttable_memusage(Value* x) { return sizeof(x); } /// Functions on String kint stringtable_eq(Value* x, Value* y, map& done) { return (x->getString()->eq(y->getString())); } kint stringtable_fasteq(Value* x, Value* y) { return (x->getString()->eq(y->getString())); } kint stringtable_cmp(Value* x, Value* y) { int ret = x->getString()->cmp(y->getString()); if (ret<0) return -1; else if (ret>0) return 1; else return 0; } kint stringtable_hash(Value* x) { return strHash(x->getString()->getVal(),x->getString()->length()); } Value* stringtable_fastcopy(VMState* vm, Value* x) { return MKSTR(x->getString()->getVal()); } void stringtable_marshal(VMState* vm,String* mdata,vector& done,Value* x, kint id) { String* s = x->getString(); int len = s->length(); int sz = len+50; wchar_t buf[sz]; // cout << << endl; //#ifdef WIN32 // now handled by STRMARSHAL macro SWPRINTF(buf,sz,STRMARSHAL,len,s->space(),s->getVal()); //#else // SWPRINTF(buf,sz,L"S[[%d][%d]%S]",len,s->space(),s->getVal()); //#endif mdata->append(buf); } Value* stringtable_reflect(VMState* vm,map& done,Value* x) { Value* v = KayaUnion(2,1); Value* s = KayaString(x->getString()->getVal()); KayaUnionSetArg(v,0,s); return v; } int stringtable_memusage(Value* x) { return sizeof(String)+(x->getString()->space()*sizeof(wchar_t)); } /// Functions on closures kint fntable_eq(Value* x, Value* y, map& done) { if (done.find(x)!=done.end()) { return (done[x]==y); } done[x]=y; //safe since we short-circuit if anything's unequal kint eq = (x->getFunc()->eq(y->getFunc(),done)); return eq; } /// This is probably quite meaningless kint fntable_cmp(Value* x, Value* y) { return (kint)(x->getRaw())-(kint)(y->getRaw()); } Value* fntable_copy(VMState* vm, Value* x, map& done) { return MKPVAL(vm->getVPool(),(void*)(x->getFunc()->copy(vm,done)),KVT_FUNC); } kint fntable_hash(Value* x,vector& done) { int idx; vector::iterator it = done.begin(); for(idx=0;it!=done.end();++it,++idx) { if ((*it)->getRaw()==x->getRaw()) { return 0; } } idx = done.size(); done.push_back(x); kint hash = 1; Closure *c = x->getFunc(); Value** cargs = c->getArgs(); for(int i=0;igetNumArgs();++i) { hash += funtable_hash_aux(cargs[i],done); } return hash; } void fntable_marshal(VMState* vm,String* mdata,vector& done,Value* x, kint id) { // Check for circles. int idx; vector::iterator it = done.begin(); for(idx=0;it!=done.end();++it,++idx) { if ((*it)->getRaw()==x->getRaw()) { // Already done it, just spit out a reference to it. wchar_t buf[25]; SWPRINTF(buf,25,CIRCMARSHAL,idx); mdata->append(buf); return; } } idx = done.size(); done.push_back(x); Closure *c = x->getFunc(); wchar_t buf[26]; SWPRINTF(buf,26,FUNMARSHAL,idx); mdata->append(buf); wchar_t cfnid[50]; SWPRINTF(cfnid,50,MARSHAL2FORMAT,c->getFnID(),c->getNumArgs()); mdata->append(cfnid); Value** cargs = c->getArgs(); for(int i=0;igetNumArgs();++i) { funtable_marshal_aux(vm,mdata,done,cargs[i],id); } mdata->append(L"]"); } KayaValue findIdentical(KayaValue v,map done) { map::iterator it = done.begin(); for(;it!=done.end();++it) { if ((*it).first->getRaw() == v->getRaw()) { return (*it).second; } } return NULL; } Value* fntable_reflect(VMState* vm,map& done,Value* x) { // Check for circles. KayaValue c = findIdentical(x,done); if (c!=NULL) return c; Closure* inc = x->getFunc(); Value* v = KayaUnion(5,2); done[x] = v; KArray args = newKayaArray(inc->getNumArgs()); Value** cargs = inc->getArgs(); for(int i=0;igetNumArgs();++i) { Value* el = funtable_reflect_aux(vm,done,cargs[i]); KayaArrayPush(args,el); } Value* uarr = KayaArrayVal(args); KayaUnionSetArg(v,0,KayaInt(inc->getFnID())); KayaUnionSetArg(v,1,uarr); return v; } int fntable_memusage(Value* x) { int size = sizeof(Value)+sizeof(Closure); Value** args = x->getFunc()->getArgs(); for(int i=0;igetFunc()->getNumArgs();++i) { size+=4; size+=funtable_memusage(args[i]); } return size; } /// Functions on Reals kint realtable_eq(Value* x, Value* y, map& done) { return (x->getReal()==y->getReal()); } kint realtable_fasteq(Value* x, Value* y) { return (x->getReal()==y->getReal()); } kint realtable_cmp(Value* x, Value* y) { double xv = x->getReal(); double yv = y->getReal(); if (yv>xv) return -1; else if (yv==xv) return 0; else return 1; } Value* realtable_fastcopy(VMState* vm, Value* x) { double xv = x->getReal(); Value* v=MKPVAL(vm->getVPool(),NULL,KVT_REAL); v->setReal(vm->getRPool(),xv); return v; } void realtable_marshal(VMState* vm,String* mdata,vector& done,Value* x, kint id) { wchar_t buf[255]; SWPRINTF(buf,255,L"R[%e]",x->getReal()); mdata->append(buf); } Value* realtable_reflect(VMState* vm,map& done,Value* x) { Value* v = KayaUnion(1,1); Value* f = KayaFloat(KFLOAT(x->getReal())); KayaUnionSetArg(v,0,f); return v; } kint realtable_hash(Value* x) { return (kint)x->getReal(); } int realtable_memusage(Value* x) { return sizeof(Value)+sizeof(Real); } /// Functions on Arrays kint arraytable_eq(Value* x, Value* y, map& done) { if (done.find(x)!=done.end()) { return (done[x]==y); } done[x]=y; kint eq = (x->getArray()->eq(y->getArray(),done)); return eq; } kint arraytable_cmp(Value* x, Value* y) { int ret = x->getArray()->cmp(y->getArray()); if (ret<0) return -1; else if (ret>0) return 1; else return 0; } Value* arraytable_copy(VMState* vm, Value* x, map& done) { // if x is already copied, return the copied value if (done.find(x)!=done.end()) { return done[x]; } Value* copied = MKPVAL(vm->getVPool(),x->getArray()->copy(vm,done),KVT_ARRAY); done[x]=copied; return copied; } kint arraytable_hash(Value* x, vector& done) { int idx; vector::iterator it = done.begin(); for(idx=0;it!=done.end();++it,++idx) { if ((*it)->getRaw()==x->getRaw()) { return 0; } } idx = done.size(); done.push_back(x); kint hash = 1; Array* v = x->getArray(); for(ukint i=0;isize();++i) { hash += funtable_hash_aux(v->lookup(i),done); } return hash; } void arraytable_marshal(VMState* vm,String* mdata,vector& done,Value* x, kint id) { // Check for circles. int idx; vector::iterator it = done.begin(); for(idx=0;it!=done.end();++it,++idx) { if ((*it)->getRaw()==x->getRaw()) { // Already done it, just spit out a reference to it. wchar_t buf[26]; SWPRINTF(buf,26,CIRCMARSHAL,idx); mdata->append(buf); return; } } idx = done.size(); done.push_back(x); Array* v = x->getArray(); wchar_t buf[34]; SWPRINTF(buf,34,ARRMARSHAL,idx,v->reserved_size()); mdata->append(buf); for(ukint i=0;isize();++i) { funtable_marshal_aux(vm,mdata,done,v->lookup(i),id); } mdata->append(L"]"); } Value* arraytable_reflect(VMState* vm,map& done,Value* x) { // Check for circles. KayaValue c = findIdentical(x,done); if (c!=NULL) return c; Array* inarr = x->getArray(); Value* v = KayaUnion(3,1); done[x] = v; KArray ar = newKayaArray(inarr->size()); for(ukint i=0;isize();++i) { Value* el = funtable_reflect_aux(vm,done,inarr->lookup(i)); KayaArrayPush(ar,el); } Value* varr = KayaArrayVal(ar); KayaUnionSetArg(v,0,varr); return v; } int arraytable_memusage(Value* x) { int size = sizeof(Value); size+=x->getArray()->memusage(); return size; } /// Functions on Unions kint uniontable_eq(Value* x, Value* y, map& done) { if (done.find(x)!=done.end()) { return (done[x]==y); } done[x]=y; if (x->getType() != y->getType()) { return false; // would be even better with module-unique tags, but generally // compiler type-safety should sort that out } kint eq = (x->getUnion()->eq(y->getUnion(),done)); return eq; } kint uniontable_cmp(Value* x, Value* y) { kint xt = x->getType(); kint yt = y->getType(); if (xt == yt) { int ret = x->getUnion()->cmp(y->getUnion()); if (ret<0) return -1; else if (ret>0) return 1; else return 0; } else if (xt < yt) { return -1; } else { return 1; } } Value* uniontable_copy(VMState* vm,Value* x, map& done) { Value* thisval = MKPVAL(vm->getVPool(),NULL,KVT_NULL); done[x] = thisval; // Value* copied = MKVAL(,x->getType()); thisval->setPtr(x->getUnion()->copy(vm,done),x->getType()); return thisval; } kint uniontable_hash(Value* x, vector& done) { int idx; vector::iterator it = done.begin(); for(idx=0;it!=done.end();++it,++idx) { if ((*it)->getRaw()==x->getRaw()) { return 0; } } idx = done.size(); done.push_back(x); kint hash = 1; Union *u = x->getUnion(); hash += x->getType(); for(ukint i=0;iargs[i],done); } return hash; } void uniontable_marshal(VMState* vm,String* mdata,vector& done,Value* x, kint id) { // Check for circles. int idx; vector::iterator it = done.begin(); for(idx=0;it!=done.end();++it,++idx) { if ((*it)->getRaw()==x->getRaw()) { // Already done it, just spit out a reference to it. wchar_t buf[26]; SWPRINTF(buf,26,CIRCMARSHAL,idx); mdata->append(buf); return; } } idx = done.size(); done.push_back(x); Union *u = x->getUnion(); wchar_t buf[30]; SWPRINTF(buf,30,UNIMARSHAL,idx); mdata->append(buf); wchar_t utag[50]; SWPRINTF(utag,50,MARSHAL2FORMAT,x->getType()-KVT_UNION,U_ARITY(u)); mdata->append(utag); for(ukint i=0;iargs[i],id); } mdata->append(L"]"); } Value* uniontable_reflect(VMState* vm,map& done,Value* x) { // Check for circles. KayaValue c = findIdentical(x,done); if (c!=NULL) return c; Union* inu = x->getUnion(); Value* v = KayaUnion(4,2); done[x] = v; KArray flds = newKayaArray(U_ARITY(inu)); for(ukint i=0;iargs[i]); KayaArrayPush(flds,el); } Value* uarr = KayaArrayVal(flds); KayaUnionSetArg(v,0,KayaInt(x->getType()-KVT_UNION)); KayaUnionSetArg(v,1,uarr); return v; } int uniontable_memusage(Value* x) { int size = sizeof(Value); size+=x->getUnion()->memusage(); return size; } /// Functions on Unions with no parameters kint cuniontable_eq(Value* x, Value* y, map& done) { return (x->getInt()==y->getInt()); } kint cuniontable_cmp(Value* x, Value* y) { int xi = x->getInt(); int yi = y->getInt(); if (xi& done) { Value* thisval = MKPVAL(vm->getVPool(),(void*)x->getInt(),KVT_CUNION); return thisval; } void cuniontable_marshal(VMState* vm,String* mdata,vector& done,Value* x, kint id) { // Check for circles. int idx; vector::iterator it = done.begin(); for(idx=0;it!=done.end();++it,++idx) { if ((*it)->getRaw()==x->getRaw()) { // Already done it, just spit out a reference to it. wchar_t buf[30]; SWPRINTF(buf,30,CIRCMARSHAL,idx); mdata->append(buf); return; } } idx = done.size(); done.push_back(x); wchar_t buf[30]; SWPRINTF(buf,30,UNIMARSHAL,idx); mdata->append(buf); wchar_t utag[50]; SWPRINTF(utag,50,MARSHAL2FORMAT,x->getInt(),0); mdata->append(utag); mdata->append(L"]"); } Value* cuniontable_reflect(VMState* vm,map& done,Value* x) { // Check for circles. KayaValue c = findIdentical(x,done); if (c!=NULL) return c; Value* v = KayaUnion(4,2); done[x] = v; KArray flds = newKayaArray(0); Value* uarr = KayaArrayVal(flds); KayaUnionSetArg(v,0,KayaInt(x->getInt())); KayaUnionSetArg(v,1,uarr); return v; } kint cuniontable_hash(Value* x) { return x->getInt(); } int cuniontable_memusage(Value* x) { int size = sizeof(Value); return size; } /// Functions on Exceptions kint exceptiontable_hash(Value* x) { return 0; } kint exceptiontable_eq(Value* x, Value* y, map& done) { return (x->getExcept()->eq(y->getExcept())); } kint exceptiontable_fasteq(Value* x, Value* y) { return (x->getExcept()->eq(y->getExcept())); } kint exceptiontable_cmp(Value* x, Value* y) { kint ret = x->getExcept()->cmp(y->getExcept()); if (ret<0) return -1; else if (ret>0) return 1; else return 0; } Value* exceptiontable_copy(Value* x, map& done) { // No point since they're immutable return x; } Value* exceptiontable_fastcopy(Value* x) { // No point since they're immutable return x; } void exceptiontable_marshal(VMState* vm,String* mdata,vector& done,Value* x, kint id) { vm->kaya_rtsError(CANT_MARSHAL_EXCEPTIONS); } Value* exceptiontable_reflect(VMState* vm,map& done,Value* x) { vm->kaya_rtsError(CANT_REFLECT_EXCEPTIONS); return NULL; } int exceptiontable_memusage(Value* x) { int size = sizeof(Value)+sizeof(Exception); return size; // FIXME: This is wrong, but not important. } kaya-0.4.4/rts/unpickler.h0000644000175100017510000000155611170340770013534 0ustar cimcim#ifndef _UNPICKLER_H #define _UNPICKLER_H /** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ #include "wchar.h" #include "Heap.h" Value* unmarshal(void* vmptr, wchar_t* x, kint id); Value* unpickle(VMState* vm, vector&,wchar_t* &x,kint id); kint read_int(VMState* vm, wchar_t* &x); Value* un_int(VMState* vm, vector&,wchar_t* &x); Value* un_real(VMState* vm, vector&,wchar_t* &x); Value* un_circle(VMState* vm, vector&,wchar_t* &x); Value* un_string(VMState* vm, vector&,wchar_t* &x); Value* un_array(VMState* vm, vector&,wchar_t* &x,kint id); Value* un_union(VMState* vm, vector&,wchar_t* &x,kint id); Value* un_closure(VMState* vm, vector&,wchar_t* &x,kint id); #endif kaya-0.4.4/rts/KayaAPI.h0000644000175100017510000000637511170340770012763 0ustar cimcim#ifndef _KAYAAPI_H // -*-C++-*- #define _KAYAAPI_H /** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ #ifndef WIN32 #include #define GC_THREADS #else #define GC_WIN32_THREADS #endif #include #include "VM.h" class Value; class Array; typedef Value* KValue; typedef Array* KArray; // FIXME: Following two are deprecated, and kept for old code. // Remove when all uses in the distribution are replaced. typedef KValue KayaValue; typedef KArray KayaArray; typedef wchar_t KChar; typedef wchar_t* KString; typedef kint KInt; typedef double KFloat; /// String conversion macros // char* to KString #define KSTRING(x) strtowc(x) #define KVSTRING(vm,x) strtovwc(vm,x) // char to KChar #define KCHAR(x) chrtowc(x) // curses alt-chars to KChar #define KACHAR(x) (wchar_t)x // KString to char* #define CSTRING(x) wctostr(x) #define CNSTRING(x,i) wcntostr(x,i) #define CNPSTRING(narrow,wide,len) char narrow[(len+1)*4]; wcnptostr(wide,len,narrow); // KChar to char #define CCHAR(x) wctochr(x) // Following conversion macros are no-ops, but should be used in case // the kaya representation changes. #define KINT(x) (kint)x #define CINT(x) (int)x #define KFLOAT(x) x #define CFLOAT(x) x extern "C" { /// Make a new, uninitialised value. KValue newKayaValue(); /// Make a new, empty array, with room for elements. /// Give size 0 to let the rts choose the size. KArray newKayaArray(kint size); // same as above, but with the VM pointer supplied KArray newKayaArray2(void* vmptr, kint size); // Make new, initialised values. KValue KayaInt(KInt x); KValue KayaPtr(void* x); KValue KayaChar(KChar c); KValue KayaFloat(KFloat f); KValue KayaString(KString str); KValue KayaString2(VMState* vm); KValue KayaCharString(char* str); KValue KayaUnion(kint tag, kint args); KValue KayaArrayVal(KArray ar); // Query basic values KInt KayaGetInt(KValue v); KChar KayaGetChar(KValue v); KFloat KayaGetFloat(KValue v); KString KayaGetString(KValue v); KArray KayaGetArray(KValue v); // Set basic values void KayaSetInt(KValue v,KInt i); void KayaSetChar(KValue v,KChar c); void KayaSetFloat(KValue v,KFloat f); void KayaSetString(KValue v,KString s); void KayaSetCharString(KValue v,char* s); void KayaSetArray(KValue v,KArray a); // Array manipulation void KayaArrayPush(KArray a,KValue v); void KayaArraySet(KArray a, kint index, KValue v); KValue KayaArrayLookup(KArray a, kint index); kint KayaArraySize(KArray a); // Unions kint KayaUnionGetTag(KValue v); KValue KayaUnionGetArg(KValue v,kint i); void KayaUnionSetArg(KValue v,kint i,KValue val); // Callbacks KValue KayaCall(KValue fn, kint args, ...); // Allocate a garbage collected block of memory (uses libgc) void* KayaAlloc(kint size); // Handy function for combining an array into a bitmask. // The function converts a kaya value (presumably a union) into a // C side bitmask; orArray iterates through the array ORing these values // together. kint orArray(KArray a, kint(*func)(KValue)); } #endif kaya-0.4.4/rts/Closure.h0000644000175100017510000000242511170340770013150 0ustar cimcim#ifndef _CLOSURE_H // -*-C++-*- #define _CLOSURE_H /** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ #ifndef WIN32 #include #define GC_THREADS #else #define GC_WIN32_THREADS #endif #include #include "VMState.h" #include "Heap.h" #include class Closure : public gc_cleanup { public: // Create a closure from a function, which will have as its locals, // and space for arguments. Closure(VMState* vm, func fn,kint args, kint arity, bool lam, bool stack=true); Closure(Closure& x); ~Closure(); // Run the closure. Pushes m_args onto the stack, then runs the function // as normal. void run(VMState* vm); func getfn() { return m_fn; } kint getFnID() { return ::getFnID(m_fn); } kint getNumArgs() { return m_numargs; } Value** getArgs() { return m_args; } void setArg(kint i,Value* v) { m_args[i]=v; } void addArgs(VMState* vm, kint i, bool lam); bool eq(Closure* c,map& done); Closure* copy(VMState* vm, map& done); private: func m_fn; Value** m_args; kint m_numargs; kint m_arity; }; #endif kaya-0.4.4/rts/VMState.cc0000644000175100017510000003034411170340770013216 0ustar cimcim/** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ #include "VMState.h" #include "VM.h" #include "ValueFuns.h" #include "KayaAPI.h" #include "stdfuns.h" #include #include #include /// function map is global to all threads. func* m_funmap[1]; kint m_funmapsize; kint m_funmaphash; // Defined by compiling Builtins.k, so obviously any binary of a kaya // program needs to be linked to at least Builtins.o! #define INTERNAL_ERROR K_ns__D_Builtins__D_InternalError extern char* INTERNAL_ERROR; void initFunMap(kint sz, kint fmhash) { func* funcs = (func*)GC_MALLOC_UNCOLLECTABLE(sizeof(func)*sz); m_funmap[0] = funcs; m_funmapsize = sz; m_funmaphash = fmhash; } void addToFunMap(kint id, func fn) { (m_funmap[0])[id] = fn; } func getFn(kint id) { if (id > 0 && id < m_funmapsize) { return (m_funmap[0])[id]; } else { // FIXME: do something sensible with this result in the calling context return NULL; } } kint getFnID(func fn) { kint i; for (i=1;i) for(int i=0;igetType(); if (t >= KVT_UNION) { return t-KVT_UNION; } else if (t == KVT_CUNION) { return (*(m_stackptr-1))->getInt(); } else { // no extra cost to doing this check now... kaya_rtsError(GETTING_TAG_FROM_NON_UNION); // doesn't matter what we return, but it keeps the compiler happy return 0; } } void VMState::doAppend() { Value* str2=doPop(); Value* str1=doPop(); String* str=NEWSTRING(str1->getString()->getVal()); str->append(str2->getString()); push(MKPVAL(m_vpool,(void*)str,KVT_STRING)); } void VMState::doAppendChar(const wchar_t x) { // append x onto top stack item (*(m_stackptr-1))->getString()->append(x); // removed explicit coercion, so need to correct stack (*(m_stackptr-2))->setPtr(*(m_stackptr-1)); discardPop(); } void VMState::doAppendStr(const wchar_t* x) { // append x onto top stack item (*(m_stackptr-1))->getString()->append(x); } void VMState::doEqExcept(bool inv) { Value* e2=doPop(); Value* e1=doPop(); bool eq = (e2->getExcept()->eq(e1->getExcept())); if (inv) { eq = !eq; } if (eq) { push(one); } else { push(zero); } } void VMState::doEqString() { Value* e2=doPop(); Value* e1=doPop(); bool eq = (e2->getString()->eq(e1->getString())); if (eq) { push(one); } else { push(zero); } } void VMState::doNeString() { Value* e2=doPop(); Value* e1=doPop(); bool eq = (e2->getString()->eq(e1->getString())); if (eq) { push(zero); } else { push(one); } } void VMState::doEqString(const wchar_t* str) { Value* e1=doPop(); bool eq = (e1->getString()->eq(str)); if (eq) { push(one); } else { push(zero); } } void VMState::doNeString(const wchar_t* str) { Value* e1=doPop(); bool eq = (e1->getString()->eq(str)); if (eq) { push(zero); } else { push(one); } } bool VMState::doTopStrEq(const wchar_t* str) { wchar_t* topstr = (*(m_stackptr-1))->getString()->getVal(); return (!wcscmp(topstr,str)); } void VMState::int2str() { // Need to do this on a copy or we break types. Value* y = doPop(); Value* x = (*(m_stackptr-1)); x->setPtr(y); x->int2str(m_spool); } void VMState::real2str() { // Need to do this on a copy or we break types. Value* y = doPop(); Value* x = (*(m_stackptr-1)); x->setPtr(y); x->real2str(m_spool); } void VMState::str2int() { // Need to do this on a copy or we break types. Value* y = doPop(); Value* x = (*(m_stackptr-1)); x->setPtr(y); x->str2int(); } void VMState::str2real() { Value* y = doPop(); Value* x = (*(m_stackptr-1)); x->setPtr(y); x->str2real(m_rpool); } void VMState::chr2str() { // Need to do this on a copy or we break types. Value* y = doPop(); Value* x = (*(m_stackptr-1)); x->setPtr(y); x->chr2str(m_spool); } void VMState::bool2str() { // Need to do this on a copy or we break types. Value* y = doPop(); Value* x = (*(m_stackptr-1)); x->setPtr(y); x->bool2str(m_spool); } void VMState::str2chr() { // valstack[stacksize-1]->str2chr(); assert(false); } void VMState::real2int() { // Need to do this on a copy or we break types. Value* y = doPop(); Value* x = (*(m_stackptr-1)); x->setPtr(y); x->real2int(); } void VMState::int2real() { // Need to do this on a copy or we break types. Value* y = doPop(); Value* x = (*(m_stackptr-1)); x->setPtr(y); x->int2real(m_rpool); } double VMState::topint2real() { // Need to do this on a copy or we break types. kint i = doPop()->getInt(); discardPop(); // normally coercions push an extra stack item return (double)i; } void VMState::mkArray(kint i) { Array* array = new(m_apool) Array(i*2); // leave a bit of room for expansion (costs a little memory) if (i > 0){ while(i>0) { i--; Value* v= doPop(); array->push_back(v->cloneTo(m_vpool)); } } push(MKPVAL(m_vpool,array,KVT_ARRAY)); } void VMState::mkArray(Value* v, kint i) { Array* array = new(m_apool) Array(i*2); // leave a bit of room for expansion (costs a little memory) if (i > 0){ while(i>0) { i--; Value* v= doPop(); array->push_back(v->cloneTo(m_vpool)); } } v->setArray(array); push(v); } void VMState::goToIndex() { --m_stackptr; kint idx = (*m_stackptr)->getInt(); (*(m_stackptr-1)) = (*(m_stackptr-1))->lookup(this,idx); } void VMState::pushglobal(Value**& globtable, kint j) { if (globtable == NULL) { globtable = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*m_globalloc); for(kint i=0;idata = valstack; // s->size = stacksize; StackData d; d.stackptr = m_stackptr; d.csptr = m_btptr; m_stack_stack.push(d); // cout << "Inside " << except_stack.size() << " tries" << endl; } void VMState::kaya_throw(wchar_t* msg,kint code) { push(mkstr(msg)); push(mkint((void*)code)); push(MKPVAL(m_vpool,(void*)(new Exception(this)), KVT_EXCEPTION)); throw_ex(); } void VMState::kaya_internalError(kint code) { push(mkint((void*)code)); push(MKPVAL(m_vpool,(void*)(new Exception(this, INTERNAL_ERROR, 1)), KVT_EXCEPTION)); throw_ex(); } void VMState::kaya_rtsError(const char* exceptionID) { push(MKPVAL(m_vpool,(void*)(new Exception(this, exceptionID, 0)), KVT_EXCEPTION)); throw_ex(); } void VMState::throw_ex() { longjmp(*(m_except_stack.top()),2); } jmp_buf* VMState::top_ex() { return m_except_stack.top(); } void VMState::tried() { delete m_except_stack.top(); m_except_stack.pop(); m_stack_stack.pop(); } void VMState::restore() { m_stackptr = m_stack_stack.top().stackptr; m_btptr = m_stack_stack.top().csptr; } void VMState::getindex() { kint idx = doPop()->getInt(); Value* array = doPop(); Value* el = array->lookup(this,idx); push(el); } Value* VMState::mkstr(wchar_t* str) { return MKPVAL(m_vpool,(void*)(NEWPSTRING(m_spool,str)),KVT_STRING); } Value* VMState::mkint(void* i) { return MKPVAL(m_vpool,i,KVT_INT); } void VMState::lineno(const wchar_t* src, int ln) { #ifndef NOCHECK // copy is necessary again m_sourcefile = (wchar_t*)GC_MALLOC_ATOMIC(sizeof(wchar_t)*(wcslen(src)+1)); wcscpy(m_sourcefile,src); m_lineno = ln; #endif } void VMState::pushBT(const wchar_t* fn, const wchar_t* mod, int ln) { #ifndef NOCHECK CallStackEntry* c = *m_btptr; c->fn_name = fn; //(char*)KayaAlloc(strlen(fn)+1); c->file = mod; //(char*)KayaAlloc(strlen(mod)+1); c->call_file = m_sourcefile; // already gcmalloced c->line = ln; c->call_line = m_lineno; ++m_btptr; if ((m_btptr-m_backtrace)>=m_callstackalloc) { realloc_callstack(); // kaya_rtsError(CALL_STACK_OVERFLOW); } #endif } void VMState::popBT() { #ifndef NOCHECK // cout << "pop backtrace!" << endl; if (m_btptr==m_backtrace) { cout << "Warning! Call stack underflow!" << endl; } --m_btptr; // *m_btptr = NULL; // set end marker #endif } void VMState::memstat() { #ifndef NOCHECK int mem = GC_get_heap_size(); if (mem>m_maxmem) m_maxmem=mem; #endif } void VMState::writestdout() { wchar_t* str=doPop()->getString()->getVal(); write(1,wctostr(str),strlen(wctostr(str))); #ifndef WIN32 fsync(1); #endif } void VMState::realloc_stack() { // cerr << "realloc:" << m_stackalloc << endl; Value** newstack = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*(m_stackalloc<<3)); memset(newstack,0,sizeof(Value*)*(m_stackalloc<<3)); for (kint i=0;i #define GC_THREADS #else #define GC_WIN32_THREADS #endif #include //#include #include #include #include #include "sizes.h" #include "ValueFuns.h" class VMState; typedef void(*func)(VMState*); class Value; class String; class Array; class Exception; class Union; class Real; class Closure; class ValuePool; class StringPool; class UnionPool; class RealPool; class ArrayPool; #define KMALLOC(x) GC_MALLOC(x) #define KMALLOC_BLOCK(x) GC_MALLOC_ATOMIC(x) #define KMALLOC_ROOT(x) GC_MALLOC_UNCOLLECTABLE(x) #define KREALLOC(x) GC_REALLOC(x) #define NEWVAL (new Value(NULL,KVT_INT)) //(Value*)(KMALLOC(sizeof(Value)))) #define MKVAL(ptr,ft) new Value(ptr,ft) #define MKINITVAL(ptr,ft) new(GCInit) Value(ptr,ft) #define MKPVAL(place,ptr,ft) new(place) Value(ptr,ft) //NEWVAL->setPtr(ptr,ft) #define NEWREAL(n) new Real(n) #define NEWPREAL(p,n) new(p) Real(n) //(((Real*)(KMALLOC(sizeof(Real))))->setNum(n)) // If we're allocating globals, we'd better do a GC_init first. Use this // as a placement to the 'new' operator on Values. enum DoInit { GCInit, NoGCInit }; class ValuePool { public: void *operator new(size_t num_bytes) { return (KMALLOC_ROOT(num_bytes)); } ValuePool(); void* next(); private: Value* m_pool; int m_usage; void refill(); }; class StringPool { public: void *operator new(size_t num_bytes) { return (KMALLOC_ROOT(num_bytes)); } StringPool(); void* next(); private: String* m_pool; int m_usage; void refill(); }; class UnionPool { public: void *operator new(size_t num_bytes) { return (KMALLOC_ROOT(num_bytes)); } UnionPool(); void* next(); private: Union* m_pool; int m_usage; void refill(); }; class RealPool { public: void *operator new(size_t num_bytes) { return (KMALLOC_ROOT(num_bytes)); } RealPool(); void* next(); private: Real* m_pool; int m_usage; void refill(); }; class ArrayPool { public: void *operator new(size_t num_bytes) { return (KMALLOC_ROOT(num_bytes)); } ArrayPool(); void* next(); private: Array* m_pool; int m_usage; void refill(); }; // I really shouldn't call this Real! Float/Double better. class Real { public: void *operator new(size_t num_bytes) { return (KMALLOC(num_bytes)); } void *operator new(size_t num_bytes, void* place) { return place; } // create in preallocated memory void *operator new(size_t num_bytes, RealPool* allocator) { return allocator->next(); } Real(double n):number(n) {} // Real* setNum(double n) { number = n; return this; } double number; }; // cached values extern Value *zero, *one, *minusone; extern "C" { wchar_t* emptyString(); } //#define U_TAG(x) ((x->tag_arity) >> 16) #define U_ARITY(x) x->arity //#define THIS_TAG (tag_arity >> 16) #define THIS_ARITY arity class Union : public gc_cleanup { public: // If getargs is true, get arguments from the stack in vm. // create in preallocated memory void *operator new(size_t num_bytes, UnionPool* allocator) { return allocator->next(); } void *operator new(size_t num_bytes) { return (void*)GC_MALLOC(num_bytes); } Union(VMState* vm, ukint arity, bool getargs = true); ~Union() { if (args != NULL) { GC_FREE(args); } } bool eq(Union* x, map& done); kint cmp(Union* x); ukint memusage(); Union* copy(VMState* vm, map& done); ukint arity; Value** args; }; #ifdef WIN32 /* No, still doesn't work. Error is: d:/MINgw/include/c++/3.2.3/bits/stl_construct.h: In function `void std::_Construct(_T1*, const _T2&) [with _T1 = CallStackEntry, _T2 = CallStackEntry]': Heap.cc:494: instantiated from `void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = CallStackEntry, _Alloc = std::allocator]' Heap.cc:455: instantiated from here d:/MINgw/include/c++/3.2.3/bits/stl_construct.h:78: no matching function for call to `CallStackEntry::operator new(unsigned int, void*&)' Heap.h:104: candidates are: static void* CallStackEntry::operator new(unsigned int) */ struct CallStackEntry : public gc { # else class CallStackEntry { public: void *operator new(size_t num_bytes) { return (KMALLOC(num_bytes)); } #endif const wchar_t* fn_name; const wchar_t* file; int line; const wchar_t* call_file; int call_line; }; class Exception { public: void *operator new(size_t num_bytes) { return (KMALLOC(num_bytes)); } void *operator new(size_t num_bytes, void* place) { return place; } Exception(VMState* vm); Exception(VMState* vm, const char* tag, kint arity); void show(); bool eq(Exception* x); kint cmp(Exception* x); void dumpBacktrace(); String* err; kint code; const char* tag; kint arity; Value** args; wchar_t* throwfile; kint throwline; // Need a copy of entire backtrace. Ick. vector backtrace; }; class Value { public: /// Create an initialised value. Value(void* ptr, valtype ft):m_val(ptr),m_funtable(ft) {} void *operator new(size_t num_bytes) { return (KMALLOC(num_bytes)); } // create in preallocated memory void *operator new(size_t num_bytes, void* allocptr) { return allocptr; } // create in preallocated memory void *operator new(size_t num_bytes, ValuePool* allocator) { return allocator->next(); } // Create a global, better do initialisation first void *operator new(size_t num_bytes, DoInit init) { if (init==GCInit) { GC_init(); } return KMALLOC(num_bytes); } valtype getType() { return m_funtable; } // returns a new value pointing to the same thing Value* clone() { return MKVAL(m_val,m_funtable); } Value* cloneTo(ValuePool* valpool) { return MKPVAL(valpool,m_val,m_funtable); } /// Get an integer out. Assumes you've checked/know. kint getInt() { return (kint)m_val; }; /// Get a real number out double getReal() { // FIXME: I don't know if turning this check off is 'safe'. It doesn't // throw an exception after all. Maybe it should? #ifndef NOCHECK if (m_funtable==KVT_REAL) return ((Real*)m_val)->number; else return 0.0; // Not too much of an overhead here. #else return ((Real*)m_val)->number; #endif } /// Get the function pointer. Assumes you've checked/know. Closure* getFunc() { return (Closure*)m_val; } /// Get the string String* getString(); /// Get the array. Array* getArray(); /// Get the union. Union* getUnion(); /// Get the exception. Exception* getExcept(); /// Run the closure stored here. void runClosure(VMState *vm); /// Add more arguments from the stack to the closure stored here. Value* addClosureArgs(VMState *vm, kint i, bool lam); /// Coercions void int2str(); void int2str(StringPool*); void str2int(); void str2real(); void str2real(RealPool*); void chr2str(); void chr2str(StringPool*); void bool2str(); void bool2str(StringPool*); void str2chr(); void int2real(); void int2real(RealPool*); void real2int(); void real2str(); void real2str(StringPool*); /// Get the tag out of a union kint getTag() { return m_funtable-KVT_UNION; } /// Get the raw pointer out. void* getRaw() { return m_val; } /// Update to be an integer. void setInt(kint i) { m_val=(void*)i; m_funtable = KVT_INT; } /// Update to be an integer and return a pointer Value* setIntReturn(kint i) { setInt(i); return this; } /// Update to be a real void setReal(double i); void setReal(RealPool* r, double v); /// Update to be a function. void setFunc(Closure* f); /// Update to be ana rray. void setString(String* str) { m_val=(void*)str; m_funtable = KVT_STRING; } void setArray(Array* a); /// Set a raw pointer. void setPtr(Value* p) { // cout << "Making " << this << " to " << p->m_val << endl; // memcpy(this,p,sizeof(Value*)); m_val=p->m_val; m_funtable=p->m_funtable; } Value* setPtr(void* raw, valtype ft) { m_val = raw; m_funtable = ft; return this; } void addInt(kint x) { m_val = (void*)((kint)m_val+x); } void addVal(Value* v) { m_val=(void*)((kint)m_val+(kint)(v->m_val)); } void subVal(Value* v) { m_val=(void*)((kint)m_val-(kint)(v->m_val)); } void mulVal(Value* v) { m_val=(void*)((kint)m_val*(kint)(v->m_val)); } void divVal(Value* v) { m_val=(void*)((kint)m_val/(kint)(v->m_val)); } /// Set a value from the projection of the top stack item void project(VMState* vm, kint i); void fastproject(Value* topitem, kint i) { Union* top=(Union*)(topitem->m_val); Value* arg=top->args[i]; m_val=arg->m_val; m_funtable = arg->m_funtable; } void exceptionproject(Value* topitem, kint i) { Exception* top=(Exception*)(topitem->m_val); Value* arg=top->args[i]; m_val=arg->m_val; m_funtable = arg->m_funtable; } void fastproject(VMState* vm, kint i); /// Lookup a value in an array --- resize/create if necessary. Value* lookup(VMState* vm, kint i); /// Get the length of an array kint length(); /// Get the function table out valtype getFunTable() { return m_funtable; } private: void* m_val; valtype m_funtable; }; // Get the actual string, considering offset #define M_STR (m_str+m_offset) // Get the actual length available, considering offset #define M_ALLOC (m_alloc-m_offset) // Prepared to waste 8k before reallocating a string (this is quite a lot...) #define OFFSET_LIMIT 8192 #define NEWSTRING(x) new String(x) #define NEWPSTRING(p,x) new(p) String(x) //(((String*)(KMALLOC(sizeof(String))))->setVal(x)) class String { public: String(const wchar_t* val); String(wchar_t val); String(kint len); String(VMState* vm); void *operator new(size_t num_bytes) { return (KMALLOC(num_bytes)); } void *operator new(size_t num_bytes, void* place) { return place; } // create in preallocated memory void *operator new(size_t num_bytes, StringPool* allocator) { return allocator->next(); } String* setVal(const wchar_t* val); String* setVal(wchar_t val); String* setVal(kint len); wchar_t* getVal() { return M_STR; } kint length() { return m_len; } wchar_t getIndex(kint i) { return M_STR[i]; } void setIndex(kint i,wchar_t c) { M_STR[i]=c; } void append(String* s); void append(wchar_t c); void append(const wchar_t* s); void getForeign(const char* c); bool eq(String* s); bool eq(const wchar_t* s); kint cmp(String* s); // Increase the offset. If it goes over OFFSET_LIMIT, reallocate void offset(kint x); // Chop last x characters off. void chop(kint x); // debug/marshalling purposes kint space() { return M_ALLOC; } private: wchar_t* m_str; kint m_alloc; kint m_offset; // How much of the start of the string to ignore // (Optimisation if we're just chopping off the start of // the string) kint m_len; }; #endif kaya-0.4.4/rts/Heap.cc0000644000175100017510000003375211170340770012556 0ustar cimcim/** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ #include #include "sizes.h" #include #include "Heap.h" #include #include #include #include "ValueFuns.h" #include "stdfuns.h" #include "Array.h" #include "VMState.h" #include "Closure.h" #include "VM.h" #include // cached values Value* zero = MKVAL((void*)0,KVT_INT); Value* one = MKVAL((void*)1,KVT_INT); Value* minusone = MKVAL((void*)(-1),KVT_INT); wchar_t* emptyString() { wchar_t* buf = (wchar_t*)GC_MALLOC_ATOMIC(sizeof(wchar_t)); buf[0] = '\0'; return buf; } String* Value::getString() { /// TODO - throw if it's not a string.. if (m_val!=NULL) return (String*)m_val; else return NEWSTRING(emptyString()); } Exception* Value::getExcept() { /// TODO - throw if it's not an exception. if (m_val!=NULL) { if (m_funtable!=KVT_EXCEPTION) { assert(false); return NULL; } return (Exception*)m_val; } else { assert(false); return NULL; } } void Value::runClosure(VMState* vm) { // cout << m_val << endl; ((Closure*)m_val)->run(vm); // ((func)m_val)(vm); } Value* Value::addClosureArgs(VMState *vm, kint i, bool lam) { // Copy the closure first, because it may be used again in the same // way, and we want it to be in the same state then. m_val = (void*)(new Closure(*((Closure*)m_val))); ((Closure*)m_val)->addArgs(vm,i,lam); return this; } Array* Value::getArray() { /// TODO - throw if it's not an array. if (m_val!=NULL) return (Array*)m_val; else return new Array(); } Union* Value::getUnion() { /// TODO - throw if it's not a union. if (m_val!=NULL) return (Union*)m_val; assert(false); return NULL; // Can't happen. } void Value::int2str() { kint v=getInt(); wchar_t buf[50]; // *Ick* SWPRINTF(buf,50,DIGITFORMAT,v); setString(NEWSTRING(buf)); } void Value::int2str(StringPool* sp) { kint v=getInt(); wchar_t buf[50]; // *Ick* SWPRINTF(buf,50,DIGITFORMAT,v); setString(NEWPSTRING(sp,buf)); } void Value::real2str() { double v=getReal(); wchar_t buf[100]; // *Ick* SWPRINTF(buf,50,L"%g",v); setString(NEWSTRING(buf)); m_funtable = KVT_STRING; } void Value::real2str(StringPool* sp) { double v=getReal(); wchar_t buf[100]; // *Ick* SWPRINTF(buf,50,L"%g",v); setString(NEWPSTRING(sp,buf)); m_funtable = KVT_STRING; } void Value::str2int() { String* s=getString(); kint val=(kint)(wcstol(s->getVal(),NULL,10)); setInt(val); m_funtable = KVT_INT; } void Value::str2real() { String* s=getString(); double val=wcstod(s->getVal(),NULL); setReal(val); m_funtable = KVT_REAL; } void Value::str2real(RealPool* r) { String* s=getString(); double val=wcstod(s->getVal(),NULL); setReal(r,val); m_funtable = KVT_REAL; } void Value::chr2str() { //CIM: wchar_t is an integer type storing the UCS position wchar_t v=(wchar_t)getInt(); setString(NEWSTRING(v)); m_funtable = KVT_STRING; } void Value::chr2str(StringPool* s) { //CIM: wchar_t is an integer type storing the UCS position wchar_t v=(wchar_t)getInt(); setString(NEWPSTRING(s,v)); m_funtable = KVT_STRING; } void Value::bool2str() { kint v=getInt(); if (v==1) { setString(NEWSTRING(L"true")); } else { setString(NEWSTRING(L"false")); } } void Value::bool2str(StringPool* s) { kint v=getInt(); if (v==1) { setString(NEWPSTRING(s,L"true")); } else { setString(NEWPSTRING(s,L"false")); } } void Value::str2chr() { assert(false); // Makes no sense! } void Value::int2real() { kint v=getInt(); setReal((double)v); m_funtable = KVT_REAL; } void Value::int2real(RealPool* rp) { kint v=getInt(); setReal(rp,(double)v); m_funtable = KVT_REAL; } void Value::real2int() { double v=getReal(); setInt((kint)v); m_funtable = KVT_INT; } void Value::setReal(double v) { m_val=(void*)(new Real(v)); m_funtable = KVT_REAL; } void Value::setReal(RealPool* r, double v) { m_val=(void*)(new(r) Real(v)); m_funtable = KVT_REAL; } void Value::setFunc(Closure* f) { m_val=(void*)f; m_funtable = KVT_FUNC; } void Value::setArray(Array* a) { m_val=(void*)a; m_funtable = KVT_ARRAY; } void Value::project(VMState* vm, kint i) { if (vm->topItem()->getType()!=KVT_UNION) { vm->kaya_rtsError(PROJECT_FROM_NON_UNION); } Union* top=(Union*)(vm->topItem()->m_val); Value* arg=top->args[i]; m_val=arg->m_val; m_funtable = arg->m_funtable; } Value* Value::lookup(VMState* vm, kint i) { #ifndef NOCHECK if (m_val && getType()!=KVT_ARRAY) { // cout << m_val << "," << getType() << endl; vm->kaya_rtsError(LOOKUP_FROM_NON_ARRAY); } #endif if (i<0) { vm->kaya_rtsError(NEGATIVE_ARRAY_INDEX); } Array* v = (Array*)m_val; if (v==NULL) { v = new(vm->getAPool()) Array(); m_val=v; m_funtable = KVT_ARRAY; } kint extras = i-v->size(); if (extras>=0) { // v->expectedSize(i); for(int l=extras;l>=0;--l) { Value* n = MKPVAL(vm->getVPool(),NULL, KVT_NULL); v->push_back(n); if (l == 0) { return n; } } } return v->lookup(i); } kint Value::length() { Array* v = (Array*)m_val; if (v==NULL) { v = new Array(); m_val=v; } return v->size(); } // for returns from foreign function calls // it can be a significant memory saving, though doesn't make much // difference to speed String::String(VMState* vm) { m_offset=0; m_len = wcslen(vm->strbuffer); m_alloc = vm->strbuflen; m_str=vm->strbuffer; } String::String(const wchar_t* val) { m_offset=0; if (val!=NULL) { m_len = wcslen(val); m_alloc = m_len*2; m_str=(wchar_t*)KMALLOC_BLOCK(m_alloc*sizeof(wchar_t)); wcscpy(m_str,val); } else { m_len=0; m_alloc = 128; m_str=(wchar_t*)KMALLOC_BLOCK(m_alloc*sizeof(wchar_t)); // strcpy(m_str,"(none)"); // Debugging purposes //wcscpy(m_str,emptyString()); m_str[0] = '\0'; } } String::String(wchar_t val) { m_alloc = 16; m_offset = 0; m_len = 1; m_str=(wchar_t*)KMALLOC_BLOCK(m_alloc*sizeof(wchar_t)); m_str[0]=val; m_str[1]='\0'; } String::String(kint len) { m_alloc = len+1; m_offset = 0; m_len = 0; m_str=(wchar_t*)KMALLOC_BLOCK(m_alloc*sizeof(wchar_t)); m_str[0]='\0'; } void String::append(String* s) { // reallocation is safe with strings, because there will be no // references into the middle. m_len += s->length(); if (m_len>=M_ALLOC) { m_alloc = (m_len+8)*2; //(newlen+10)*2; // cout << "Realloc " << m_alloc << " to " << wctostr(m_str) << " + " << wctostr(s->getVal()) << endl; wchar_t* newstr = (wchar_t*)KMALLOC_BLOCK(sizeof(wchar_t)*m_alloc); wcscpy(newstr,M_STR); m_str=newstr; m_offset=0; } wcscat(m_str,s->getVal()); } void String::append(wchar_t c) { if (c == '\0') { return; } // does nothing m_len++; if (m_len>=M_ALLOC) { m_alloc = (m_len+8)*2; //(newlen+10)*2; // cout << "Realloc " << m_alloc << " to " << wctostr(m_str) << endl; wchar_t* newstr = (wchar_t*)KMALLOC_BLOCK(sizeof(wchar_t)*m_alloc); wcscpy(newstr,M_STR); m_str=newstr; m_offset=0; } m_str[m_len-1]=c; m_str[m_len]='\0'; } void String::append(const wchar_t* s) { m_len += wcslen(s); if (m_len>=M_ALLOC) { m_alloc = (m_len+8)*2; //(newlen+10)*2; // cout << "Realloc " << m_alloc << " to " << wctostr(m_str) << endl; wchar_t* newstr = (wchar_t*)KMALLOC_BLOCK(sizeof(wchar_t)*m_alloc); wcscpy(newstr,M_STR); m_str=newstr; m_offset=0; } wcscat(m_str,s); } void String::getForeign(const char* c) { kint clen = strlen(c); if (clen >= m_alloc) { m_alloc = clen+1; cerr << "REALLOC!" << endl; wchar_t* newstr = (wchar_t*)KMALLOC_BLOCK(sizeof(wchar_t)*(m_alloc)); m_str = newstr; m_offset = 0; m_len = 0; } else { m_len = 0; m_offset = 0; M_STR[0] = '\0'; } mkUCS(c,m_str,clen); m_len = wcslen(m_str); } bool String::eq(String* s) { // cout << "Comparing " << s->getVal() << " and " << m_str << "." << endl; return (wcscmp(M_STR,s->getVal())==0); } bool String::eq(const wchar_t* s) { return (wcscmp(M_STR,s)==0); } kint String::cmp(String* s) { // cout << "Comparing " << s->getVal() << " and " << m_str << "." << endl; return (wcscmp(M_STR,s->getVal())); } void String::offset(kint inc) { m_offset+=inc; m_len-=inc; // If it's got too long, reallocate. if (m_offset>OFFSET_LIMIT) { // CIM: should we recalculate m_alloc at this point? wchar_t* newstr = (wchar_t*)KMALLOC_BLOCK(sizeof(wchar_t)*m_alloc); wcscpy(newstr,M_STR); m_str=newstr; m_offset=0; } } void String::chop(kint inc) { M_STR[m_len-inc]='\0'; m_len -= inc; } Union::Union(VMState* vm, ukint ar, bool getargs) :arity(ar) { // Make space for the data, then take items off the stack and // put them into the structure. // cout << "Making union with tag " << t << " and arity " << ar << endl; // cout << "tag_arity = " << tag_arity << endl; if (ar > 0) { args = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*ar); if (getargs) { for(ukint i=0;idoPop()->cloneTo(vm->getVPool()); } } } else { // never happens now, hopefully args = NULL; } } bool Union::eq(Union* x, map& done) { // if (THIS_TAG!=U_TAG(x)) return false; for(ukint i=0;iargs[i],done)) { return false; } } return true; } kint Union::cmp(Union* x) { // if (THIS_TAGU_TAG(x)) return 1; for(ukint i=0;iargs[i]); if (cmp!=0) return cmp; } return 0; } Union* Union::copy(VMState* vm, map& done) { Union* u = new(vm->getUPool()) Union(NULL,THIS_ARITY,false); for(ukint i=0;iargs[i]=copied; } return u; } ukint Union::memusage() { ukint size = sizeof(Union); for(ukint x=0;xdoPop(); Value* errval = vm->doPop(); code = codeval->getInt(); err = errval->getString(); throwfile = vm->m_sourcefile; throwline = vm->m_lineno; CallStackEntry** c = vm->m_btptr-1; for(;(c>vm->m_backtrace);--c) { CallStackEntry nc(**c); backtrace.push_back(nc); } } Exception::Exception(VMState* vm, const char* t, kint ar): tag(t), arity(ar) { err = NEWSTRING(strtowc(t)); code = 0; if (ar > 0) { args = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*ar); for(int i=0;idoPop()->clone(); } } else { args = NULL; } throwfile = vm->m_sourcefile; throwline = vm->m_lineno; CallStackEntry** c = vm->m_btptr-1; for(;(c>vm->m_backtrace);--c) { CallStackEntry nc(**c); backtrace.push_back(nc); } } void Exception::show() { cout << wctostr(err->getVal()) << endl; } bool Exception::eq(Exception* x) { /* cout << "Comparing..." << endl; show(); x->show(); cout << ((err->eq(x->err)) && (code==x->code)) << endl;*/ return (err->eq(x->err)) && (code==x->code); } kint Exception::cmp(Exception* x) { return (code-x->code); } void Exception::dumpBacktrace() { vector::iterator it = backtrace.begin(); cout << wctostr(err->getVal()); if (throwline!=0) { cout << " thrown at " << wctostr(throwfile) << ":" << throwline << endl; } else { cout << " thrown" << endl; } for(int x=0;it!=backtrace.end() && x<=20;++it,++x) { if ((*it).line==-1) { cout << "lambda in " << wctostr((*it).fn_name); } else { cout << wctostr((*it).fn_name); } if ((it+1)==backtrace.end()) { cout << " [entry point]" << endl; } else { cout << " called from " << wctostr((*(it+1)).fn_name) << " at " << wctostr((*it).call_file) << ":" << (*it).call_line << endl; } if (x==20) { kint num = backtrace.size()-20; cout << "[... " << num << " more elided...]" << endl; } } } /* Value pools */ ValuePool::ValuePool() { refill(); } void ValuePool::refill() { m_pool = (Value*)KMALLOC(sizeof(Value)*MEM_POOLSIZE); m_usage = 0; } void* ValuePool::next() { if (m_usage >= MEM_POOLSIZE) { refill(); } void* nextval = (void*)(m_pool+m_usage); m_usage++; return nextval; } UnionPool::UnionPool() { refill(); } void UnionPool::refill() { m_pool = (Union*)KMALLOC(sizeof(Union)*MEM_POOLSIZE); m_usage = 0; } void* UnionPool::next() { if (m_usage >= MEM_POOLSIZE) { refill(); } void* nextval = (void*)(m_pool+m_usage); m_usage++; return nextval; } StringPool::StringPool() { refill(); } void StringPool::refill() { m_pool = (String*)KMALLOC(sizeof(String)*MEM_POOLSIZE); m_usage = 0; } void* StringPool::next() { if (m_usage >= MEM_POOLSIZE) { refill(); } void* nextval = (void*)(m_pool+m_usage); m_usage++; return nextval; } RealPool::RealPool() { refill(); } void RealPool::refill() { m_pool = (Real*)KMALLOC(sizeof(Real)*MEM_POOLSIZE); m_usage = 0; } void* RealPool::next() { if (m_usage >= MEM_POOLSIZE) { refill(); } void* nextval = (void*)(m_pool+m_usage); m_usage++; return nextval; } ArrayPool::ArrayPool() { refill(); } void ArrayPool::refill() { m_pool = (Array*)KMALLOC(sizeof(Array)*MEM_POOLSIZE); m_usage = 0; } void* ArrayPool::next() { if (m_usage >= MEM_POOLSIZE) { refill(); } void* nextval = (void*)(m_pool+m_usage); m_usage++; return nextval; } kaya-0.4.4/rts/KayaAPI.cc0000644000175100017510000001004411170340770013105 0ustar cimcim/** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ #include "KayaAPI.h" #include "Heap.h" #include "Array.h" #include "VM.h" #include "VMState.h" #include #include KValue newKayaValue() { return MKVAL(NULL,KVT_NULL); } KValue KayaInt(kint x) { KValue v = newKayaValue(); KayaSetInt(v,x); return v; } KValue KayaPtr(void* x) { KValue v = newKayaValue(); KayaSetInt(v,(kint)x); return v; } KValue KayaChar(wchar_t c) { KValue v = newKayaValue(); KayaSetChar(v,c); return v; } KValue KayaFloat(double f) { KValue v = newKayaValue(); KayaSetFloat(v,f); return v; } KValue KayaString(wchar_t* str) { KValue v = newKayaValue(); KayaSetString(v,str); return v; } KValue KayaString2(VMState* vm) { return new Value(new String(vm),KVT_STRING); } KValue KayaCharString(char* str) { KValue v = newKayaValue(); KayaSetCharString(v,str); return v; } kint KayaGetInt(KValue v) { return v->getInt(); } wchar_t KayaGetChar(KValue v) { return (wchar_t)(v->getInt()); } double KayaGetFloat(KValue v) { return v->getReal(); } wchar_t* KayaGetString(KValue v) { return v->getString()->getVal(); } void KayaSetInt(KValue v,kint i) { v->setInt(i); } void KayaSetChar(KValue v,wchar_t c) { v->setInt((int)c); } void KayaSetFloat(KValue v,double f) { v->setReal(f); } void KayaSetString(KValue v,wchar_t* s) { v->setString(NEWSTRING(s)); } void KayaSetCharString(KValue v,char* s) { v->setString(NEWSTRING(strtowc(s))); } KArray newKayaArray(kint size) { return new Array(size); } KArray newKayaArray2(void* vmptr, kint size) { VMState* vm = (VMState*) vmptr; return new(vm->getAPool()) Array(size); } KArray KayaGetArray(KValue v) { return v->getArray(); } void KayaSetArray(KValue v, KArray a) { v->setArray(a); } void KayaArrayPush(KArray a,KValue v) { a->push_back(v); } void KayaArraySet(KArray a, kint index, KValue v) { Value* vloc = a->lookup(index); vloc->setPtr(v); } KValue KayaArrayLookup(KArray a, kint index) { return a->lookup(index); } kint KayaArraySize(KArray a) { return a->size(); } KValue KayaCall(KValue fn, kint args, ...) { VMState* vm = initstack(); // Value* arg; Value** arglist = new Value*[args]; va_list argp; va_start(argp,args); kint i; // Gah! Need to push backwards! for(i=0;iemptyStack()) { return NULL; } else return vm->doPop(); LABEL(cbexcept); // There was an exception in the callback. This is fatal. cerr << "Exception in callback: "; Exception* except = vm->doPop()->getExcept(); except->show(); exit(1); } KValue KayaUnion(kint tag, kint args) { if (args == 0) { return MKVAL((void*)tag,KVT_CUNION); } else { Union* u = new Union(NULL,args,false); return MKVAL((void*)u,KVT_UNION+tag); } } KValue KayaArrayVal(KArray ar) { KValue v = newKayaValue(); KayaSetArray(v,ar); return v; } kint KayaUnionGetTag(KValue v) { kint vt = v->getType(); if (vt >= KVT_UNION) { return vt-KVT_UNION; } else if (vt == KVT_CUNION) { return v->getInt(); } else { return -1; // shouldn't happen if API used correctly, but API users should error // check for it. } } KValue KayaUnionGetArg(KValue v,kint i) { Union* u = v->getUnion(); return u->args[i]; } void KayaUnionSetArg(KValue v,kint i,KValue val) { Union* u = v->getUnion(); u->args[i] = val; } void* KayaAlloc(kint size) { // Just use libgc... return GC_MALLOC_ATOMIC(size); } kint orArray(KArray a, kint(*func)(KValue)) { kint val = 0; kint size = KayaArraySize(a); for(kint i=0;i #define GC_THREADS #else #define GC_WIN32_THREADS #endif #include #include #include "Heap.h" class Value; // An array is stored as an array of pointers to blocks of values. // Each block's length is some power of 2 (all blocks in an array are the // same length) so it's quick to find which block a particular index is in // by bit shifting. // We can't just have one block, since the array needs to grow dynamically, // and there may be pointers into the array from elsewhere. So once something // is in the array, it can't move. // If we ever write our own garbage collector, it probably ought to compact // arrays (so that at least they aren't stored in lots of // blocks all over memory). class Array : public gc_cleanup { public: void *operator new(size_t num_bytes, ArrayPool* allocator) { return allocator->next(); } void *operator new(size_t num_bytes) { return (void*)GC_MALLOC(num_bytes); } Array(ukint size=0); ~Array(); void push_back(Value* v); Value* lookup(ukint i); inline ukint size() { return m_size-m_offset; } ukint reserved_size(); Array* copy(VMState* vm, map& done); void resize(ukint i); Value* shift(); void unshift(Value* v); /// Make sure there's enough space for at least i things. void expectedSize(ukint i); ukint memusage(); bool eq(Array* x,map& done); kint cmp(Array* x); private: ukint m_offset; ukint m_numBlocks; ukint m_alloc; ukint m_size; Value*** m_blocks; // array of pointers to a list of values }; #endif kaya-0.4.4/rts/COPYING.b640000644000175100017510000000207511170340767013017 0ustar cimcimCopyright (c) 2001 Bob Trower, Trantor Standard Systems Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. kaya-0.4.4/rts/Closure.cc0000644000175100017510000000531411170340770013306 0ustar cimcim/** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ using namespace std; #include #include "Closure.h" #include "VMState.h" #include "stdfuns.h" Closure::Closure(VMState* vm, func fn, kint args, kint arity, bool lam, bool stack):m_fn(fn),m_arity(arity) { // cout << "Making closure " << (void*)(m_fn) << endl; m_args=(Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*arity); m_numargs=args; if (stack) { for(kint i=0;idoPop(); } else { m_args[i]=vm->doPop()->cloneTo(vm->getVPool()); } } } } Closure::Closure(Closure& x) { // Shallow copy everything, we just need a new argument list. m_numargs = x.m_numargs; m_arity = x.m_arity; m_fn = x.m_fn; m_args=(Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*m_arity); for(kint i=0;iclone(); } } void Closure::addArgs(VMState* vm, kint added, bool lam) { kint newnum = m_numargs+added; kint i; // Better make sure there's enough room! (it really should have been // allocated, but there may be circumstances where it hasn't, if someone // is abusing the type system...) if (newnum>m_arity) { m_args = (Value**)GC_REALLOC(m_args, newnum); } for(i=m_numargs; idoPop(); } else { m_args[i]=vm->doPop()->cloneTo(vm->getVPool()); } } m_numargs = newnum; } Closure::~Closure() { GC_FREE(m_args); } void Closure::run(VMState* vm) { for(kint i=m_numargs;i>0;i--) { vm->push(m_args[i-1]); } m_fn(vm); } bool Closure::eq(Closure* c, map& done) { if (getFnID()!=c->getFnID()) { return false; } if (m_numargs!=c->m_numargs) { return false; } for(kint i=0;im_args[i],done)) { return false; } } return true; } Closure* Closure::copy(VMState* vm, map& done) { Closure* c = new Closure(NULL,m_fn,m_numargs,m_arity,false); for(kint i=0;isetArg(i,copied); } return c; } kaya-0.4.4/rts/Array.cc0000644000175100017510000001235211170340770012750 0ustar cimcim/** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ #include "Array.h" #include #include #include "Heap.h" #include "ValueFuns.h" #include "stdfuns.h" #include #define ALLOC_SHIFT 10 #define ALLOC (1u << m_alloc) #define ALLOC_MASK ((1u << m_alloc)-1) #define ALLOC_CHUNK (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*(1 << m_alloc)) Array::Array(ukint size):m_offset(0),m_size(0) { // Make an initial block if (size != 0) { // allocate next bigger power of 2. Use a couple of shortcuts for // really small arrays so we don't waste too much time. if (size<8) { m_alloc=3; } else if (size<16) { m_alloc=4; } else if (size<32) { m_alloc=5; } else { m_alloc = ukint(log2((double)size))+1; } } else { m_alloc = ALLOC_SHIFT; } m_blocks = (Value***)GC_MALLOC_UNCOLLECTABLE(sizeof(Value**)); m_blocks[0] = ALLOC_CHUNK; m_numBlocks = 1; } Array::~Array() { for(ukint i=0;i> m_alloc; // cerr<> m_alloc; ukint chunkpos = m_offset & ALLOC_MASK; m_blocks[chunk][chunkpos] = v; } // } Value* Array::shift() { Value* head = lookup(0); m_offset++; // m_size--; return head; } ukint Array::reserved_size() { return m_numBlocks*ALLOC; } void Array::push_back(Value *v) { ukint chunk = (m_size) >> m_alloc; ukint chunkpos = (m_size) & ALLOC_MASK; if ((chunk+1)>m_numBlocks) { // maybe there's a spare block on the left we can use if (m_offset > ALLOC) { // cerr<<"A:"<m_size) { // cerr<> m_alloc; ukint chunkpos = i & ALLOC_MASK; // cerr<& done) { if (x->size()!=size()) return false; for(ukint i=0;i<(m_size-m_offset);++i) { Value* idx = lookup(i); Value* xidx = x->lookup(i); if (!funtable_eq_aux(idx,xidx,done)) return false; } return true; } kint Array::cmp(Array* x) { if (x->size()size()>size()) return 1; for(ukint i=0;i<(m_size-m_offset);++i) { Value* idx = lookup(i); Value* xidx = x->lookup(i); kint cmp = funtable_compare(NULL,idx,xidx); if (cmp!=0) return cmp; } return 0; } Array* Array::copy(VMState* vm, map& done) { Array* a = new(vm->getAPool()) Array(m_size-m_offset); for(ukint i=0;i<(m_size-m_offset);++i) { Value* copied; Value* x = lookup(i); // if x is already copied, return the copied value if (done.find(x)!=done.end()) { copied = done[x]; } else { copied = funtable_copy_aux(vm, x, done); done[x] = copied; } a->push_back(copied); } return a; } ukint Array::memusage() { ukint size = 0; for(ukint i=0;i #define CACHE_SIZE 1 FnCache::FnCache(VMState* vm):m_vm(vm) { m_cache = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*CACHE_SIZE); m_cacheptr = m_cache; m_cacheend = m_cache+CACHE_SIZE; } void FnCache::addEntry(Value* result) { // Easy. special case cout << "Storing " << result << endl; *m_cache = result; } void FnCache::addEntry(Value* arg1, Value* result) { // Easy. special case *m_cache = arg1; *(m_cache+1) = result; m_cache+=2; } Value* FnCache::checkCache(int args) { if (args==0) { // Easy, special case cout << "Cached " << *m_cache << endl; return *m_cache; } return NULL; } kaya-0.4.4/rts/unpickler.cc0000644000175100017510000001465611170340770013677 0ustar cimcim/** Kaya run-time system Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ using namespace std; #include #include #include #include #include "wchar.h" #include "Heap.h" #include "VMState.h" #include "VM.h" #include "stdfuns.h" #include "unpickler.h" Value* unmarshal(void* vmptr,wchar_t* x, kint id) { VMState* vm = (VMState*)vmptr; vector done; kint i = read_int(vm,x); if (i!=id) { vm->kaya_rtsError(INVALID_MARSHALLING_ID); } kint h = read_int(vm,x); if (h!=getFnHash()) { /* cout << "marshal hash: " << h << endl; cout << "ftable hash: " << getFnHash() << endl; */ vm->kaya_rtsError(INVALID_FUNCTION_TABLE_HASH); } Value* v = unpickle(vm, done, x, id); return v; } Value* unpickle(VMState* vm, vector& done, wchar_t*& x, kint id) { Value *v; switch(x[0]) { case 'I': v=un_int(vm,done,++x); return v; case 'S': v=un_string(vm,done,++x); return v; case 'U': v=un_union(vm,done,++x,id); return v; case 'F': v=un_closure(vm,done,++x,id); return v; case 'A': v=un_array(vm,done,++x,id); return v; case 'R': v=un_real(vm,done,++x); return v; case 'C': v=un_circle(vm,done,++x); return v; default: vm->kaya_rtsError(INVALID_VALUE); return MKVAL(NULL,KVT_NULL); } } kint read_int(VMState* vm, wchar_t* &x) { wchar_t buf[30]; // = (wchar_t*)GC_MALLOC_ATOMIC(sizeof(wchar_t)*20); kint i=-1; if (*x!='[') { vm->kaya_rtsError(INVALID_VALUE); } ++x; // Move past the initial [ while(*x!=']' && i<30) { buf[++i]=*x; ++x; } if (i == 50) { vm->kaya_rtsError(INVALID_VALUE); } buf[++i]='\0'; #ifdef KAYA_SHORT_INTS kint val = wcstoimax(buf,NULL,10); #else kint val = wcstol(buf,NULL,10); #endif // = atoi(wctostr(buf)); ++x; return val; } Value* un_int(VMState* vm,vector& done,wchar_t* &x) { // Expecting [num] return mkint2(vm,(void*)read_int(vm,x)); } Value* un_real(VMState* vm,vector& done,wchar_t* &x) { // Expecting [num] wchar_t buf[100]; // = (wchar_t*)GC_MALLOC_ATOMIC(sizeof(wchar_t)*100); // Yeah, horrible, I know. kint i=-1; if (*x!='[') { vm->kaya_rtsError(INVALID_VALUE); } ++x; // Move past the initial [ while(*x!=']' && i<100) { buf[++i]=*x; ++x; } buf[++i]='\0'; double val = wcstod(buf,NULL); ++x; return MKREAL(val); } Value* un_circle(VMState* vm,vector& done,wchar_t* &x) { if (*x!='[') vm->kaya_rtsError(INVALID_CIRCULAR_STRUCTURE); kint circid = read_int(vm,x); // cout << circid << "," << done.size() << endl; if (done.size()<(ukint)circid) vm->kaya_rtsError(INVALID_CIRCULAR_STRUCTURE); // clone or we get some very odd effects - CIM return done[circid]->clone(); } Value* un_string(VMState* vm,vector& done,wchar_t* &x) { // Expecting [num]string // cout << "Doing string, x is " << x << endl; if (*x!='[') vm->kaya_rtsError(INVALID_VALUE); ++x; kint len = read_int(vm,x); kint alloc = read_int(vm,x); if (alloc < len) { alloc = len; } wchar_t buf[len+1]; // = (wchar_t*)GC_MALLOC_ATOMIC(sizeof(wchar_t)*len+1); kint i=0; while(igetString()->append(buf); return str; } Value* un_array(VMState* vm,vector& done,wchar_t* &x, kint id) { // cout << "Doing array " << endl; if (*x!='[') vm->kaya_rtsError(INVALID_VALUE); ++x; kint circid = read_int(vm,x); kint sz = read_int(vm,x); // advisory only, but it makes memory usage much more efficient if it's right... if (sz == 0) { // unless it's zero, in which case explictly set a small size sz = 5; } // sz-1 because of taking the *next* power of two // means that unmarshal(marshal()) == identity() Array* ar = new(vm->getAPool()) Array(sz-1); Value* thisval = MKPVAL(vm->getVPool(),ar,KVT_ARRAY); // Remember the value in case we get a circular structure done.push_back(thisval); if ((ukint)circid!=done.size()-1) { vm->kaya_internalError(252); } while(x[0]!=']') { Value* v = unpickle(vm,done,x,id); ar->push_back(v); } ++x; // thisval->setPtr(MKVAL(ar,arraytable)); return thisval; } Value* un_union(VMState* vm,vector& done,wchar_t* &x, kint id) { // cout << "Doing union " << endl; if (*x!='[') vm->kaya_rtsError(INVALID_VALUE); ++x; kint circid = read_int(vm,x); kint tag = read_int(vm,x); kint arity = read_int(vm,x); Value* thisval; if (arity > 0) { Union* u; u = new(vm->getUPool()) Union(NULL,arity,false); thisval = MKPVAL(vm->getVPool(),(void*)u,KVT_UNION+tag); // Remember the value in case we get a circular structure done.push_back(thisval); if ((ukint)circid!=done.size()-1) { vm->kaya_internalError(252); } // cout << "Adding " << circid << "," << done.size() << endl; kint i=0; while(iargs[i]=v; ++i; } } else { thisval = MKPVAL(vm->getVPool(),(void*)tag,KVT_CUNION); // annoyingly necessary this next bit, for now. // could change the marshal format so CUNIONs didn't have a // circid, perhaps done.push_back(thisval); if ((ukint)circid!=done.size()-1) { vm->kaya_internalError(252); } } ++x; return thisval; } Value* un_closure(VMState* vm,vector& done,wchar_t* &x, kint id) { // cout << "Doing union " << endl; if (*x!='[') vm->kaya_rtsError(INVALID_VALUE); ++x; kint circid = read_int(vm,x); kint fnid = read_int(vm,x); kint arity = read_int(vm,x); Closure* c = new Closure(NULL,getFn(fnid),arity,arity,false,false); Value* thisval = MKPVAL(vm->getVPool(),(void*)c,KVT_FUNC); // Remember the value in case we get a circular structure done.push_back(thisval); if ((ukint)circid!=done.size()-1) { vm->kaya_internalError(252); } // cout << "Adding " << circid << "," << done.size() << endl; kint i=0; while(isetArg(i,v); ++i; } ++x; return thisval; } kaya-0.4.4/rts/startup.vcc0000644000175100017510000000066211170340770013563 0ustar cimcim// -*-C++-*- void nowarn(char *msg, GC_word arg) { // Do nothing, as it's unhelpful to the user... } int main(int argc,char* argv[]) { GC_init(); VMState* vm = initstack(); DECLARE(ex); DECLAREQUICK(varg); GC_set_warn_proc(nowarn); storeArgs(argc,argv); _my_initfunmap(vm); _my_runatstartup(vm); PUSH(varg); CALL(%__start_F); storeArgs(argc,argv); finish(vm); return 0; } kaya-0.4.4/rts/header.vcc0000644000175100017510000000016411170340766013313 0ustar cimcim// -*-C++-*- #include "VM.h" #include "VMState.h" #include "stdfuns.h" #include "FnCache.h" using namespace std; kaya-0.4.4/rts/Makefile.in0000644000175100017510000000471311170340770013432 0ustar cimcimRVPATH=@srcdir@ VPATH=${RVPATH} CXX = @CXX@ CXXFLAGS = @EXTRAGCCOPTS@ @FPIC@ -fno-rtti @CXXFLAGS@ -I${VPATH} -I. LANGNAME = @LANGNAME@ LIBS = -lgc LDFLAGS = ${LIBS} prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@/@LANGNAME@ IMPORTDIR = ${libdir}/imports VCCDIR = ${libdir} INSTALLFLAGS = -m 644 SRCS = Heap.cc ValueFuns.cc VM.cc VMState.cc stdfuns.cc unpickler.cc Array.cc \ KayaAPI.cc Closure.cc FnCache.cc repl_glue.cc OBJS = Heap.o ValueFuns.o VM.o VMState.o stdfuns.o unpickler.o Array.o \ KayaAPI.o Closure.o FnCache.o repl_glue.o INSTALLHDRS = ${VPATH}/stdfuns.h ${VPATH}/VM.h ${VPATH}/VMState.h \ ${VPATH}/Heap.h ${VPATH}/ValueFuns.h ${VPATH}/unpickler.h \ ${VPATH}/Array.h ${VPATH}/KayaAPI.h ${VPATH}/Closure.h \ ${VPATH}/FnCache.h sizes.h ${VPATH}/repl_glue.h MAINFILES = ${VPATH}/header.vcc ${VPATH}/program.ks ${VPATH}/cgi.ks \ ${VPATH}/webapp.ks ${VPATH}/startup.vcc ${VPATH}/__REPLMain.k TARGET = libkayavm.so LIBTARGET = libkayavm.a GLUE = repl_glue.o all: ${LIBTARGET} #all: ${LIBTARGET} # ${CXX} ${CXXFLAGS} -shared ${OBJS} -o ${TARGET} ${LIBS} ${LIBTARGET}: ${OBJS} ar r ${LIBTARGET} ${OBJS} ranlib ${LIBTARGET} # ${CXX} ${CXXFLAGS} ${LDFLAGS} ${OBJS} -o ${TARGET} install: mkdir -p ${DESTDIR}${libdir} mkdir -p ${DESTDIR}${IMPORTDIR} mkdir -p ${DESTDIR}${VCCDIR} install ${INSTALLFLAGS} ${LIBTARGET} ${INSTALLHDRS} ${DESTDIR}${libdir} install ${INSTALLFLAGS} ${GLUE} ${DESTDIR}${libdir}/imports # install ${INSTALLFLAGS} ${TARGET} ${DESTDIR}${libdir} install ${INSTALLFLAGS} ${MAINFILES} ${DESTDIR}${VCCDIR} ranlib ${DESTDIR}${libdir}/${LIBTARGET} clean: rm -f ${LIBTARGET} *.o distclean: rm -f *~ Makefile sizes.h depend: @makedepend -Y ${SRCS} 2> /dev/null %.out: %.vcc ${TARGET} ${CXX} -x c++ ${OPTS} $< -o $@ ${LIBS} -L. -lvm # DO NOT DELETE Heap.o: Heap.h ValueFuns.h stdfuns.h unpickler.h Array.h VMState.h Closure.h sizes.h ValueFuns.o: VMState.h Heap.h VM.h Array.h ValueFuns.h stdfuns.h unpickler.h sizes.h VM.o: VM.h Heap.h Array.h ValueFuns.h VMState.h sizes.h VMState.o: VMState.h Heap.h VM.h Array.h ValueFuns.h sizes.h stdfuns.o: stdfuns.h Heap.h unpickler.h VM.h Array.h ValueFuns.h sizes.h unpickler.o: Heap.h VMState.h VM.h Array.h ValueFuns.h unpickler.h sizes.h Array.o: Array.h Heap.h ValueFuns.h stdfuns.h unpickler.h sizes.h KayaAPI.o: KayaAPI.h Heap.h VM.h Array.h ValueFuns.h sizes.h Closure.o: Closure.h Heap.h ValueFuns.h stdfuns.h sizes.h repl_glue.o: repl_glue.h VM.h VMState.h KayaAPI.h sizes.h kaya-0.4.4/rts/program.ks0000644000175100017510000000030011170340766013364 0ustar cimcim// -*-C-*-ish Void __panic(String err, Int code) { } Void __start() { // Crypto::initKeys(); try { module::main(); } catch(err) { Builtins::exceptionBacktrace(err); } } kaya-0.4.4/docs/0000755000175100017510000000000011170340767011506 5ustar cimcimkaya-0.4.4/docs/macros.ltx0000644000175100017510000000141511170340767013524 0ustar cimcim\newcommand{\Kaya}{\textsc{Kaya}} \newcommand{\TODO}[1]{[\textbf{TODO:} #1]} \newcommand{\SL}{$\backslash$} \newcommand{\CD}{\texttt} \newcommand{\MC}{\textsf} \newcommand{\demph}{\textbf} \newcommand{\remph}{\emph} \newcommand{\oneplus}[1]{#1$^+$} \newcommand{\zeroplus}[1]{#1$^*$} \newcommand{\maybe}[1]{#1$^?$} \newcommand{\FIG}[3]{\begin{figure}[h]#1\caption{#2}\label{#3}\end{figure}} \newcommand{\FFIG}[3]{\begin{figure}[h]\begin{center}\fbox{#1}\end{center}\caption{#2}\label{#3}\end{figure}} \newcommand{\BNF}[1] { \medskip \begin{tabular}{rcl} #1 \end{tabular} \medskip } \newcommand{\Rule}[2] { #1 & ::= & #2 \\ } \newcommand{\Or}[1] { & $\mid$ & #1 \\ } \newcommand{\fragment}[1]{ \medskip \framebox[12cm][l]{ \begin{minipage}{11cm} #1 \end{minipage} } \medskip } kaya-0.4.4/docs/functions.tex0000644000175100017510000001107611170340767014245 0ustar cimcim\section{Functions} \subsection{Function Definitions} \fragment{ \BNF{ \Rule{\MC{function}}{\zeroplus{\MC{opt}} \MC{type} \MC{identifier} \CD{(} \zeroplus{\MC{arg},} \CD{)}} \MC{func\_body} \Or{\zeroplus{\MC{func\_opt}} \MC{type} \MC{identifier} \MC{func\_body}} \Rule{\MC{arg}}{\maybe{\CD{var}} \MC{type} \MC{identifier} \maybe{$\langle$\CD{=} \MC{typed\_expr}$\rangle$}} \Rule{\MC{func\_body}}{\CD{\{} \maybe{\MC{expr}} \CD{\}}} \Or{ \MC{rvalue} } \Rule{\MC{rvalue}}{\CD{=} \MC{typed\_expr}} \Or{\oneplus{$\langle$\CD{|} \MC{typed\_expr} \CD{=} \MC{typed\_expr} $\rangle$}} \Rule{\MC{func\_opt}}{\CD{public}} \Or{\CD{private}} \Or{\CD{pure}} \Or{\CD{default}} } } The basic form of a function definition is to declare the return type, give the name, and list the arguments, e.g.: \begin{verbatim} Float plus(Int a,Float b,Int c) { putStrLn("Doing some sums"); return a+b*c; } \end{verbatim} If the return type is given as \CD{Void}, the function must not return a value. Otherwise, it is a compile time error if any code branch does not return a value or throw an exception. \subsection{Type Inference and Scope} The compiler will infer the type of variables used in the function body. For any name which occurs in a function body, name resolution works as follows: \begin{enumerate} \item Look up the name in the list of defined functions. \item Look up the name in the list of global variables. \item If the name is not found, create a local variable and infer a type. \end{enumerate} A type will not be inferred for names which occur \remph{only} as an argument to a function, because the compiler cannot guarantee that values are defined for such names. Variables are statically scoped. If a variable is explicitly declared, it goes out of scope when the block in which it is declared exits. Otherwise, variables go out of scope on exit from the function. \subsection{Argument Passing Convention} Arguments are passed by reference. On entry to the function, a new reference to each argument is created. If an argument is marked \CD{var}, the reference is passed directly (i.e. no new reference is created), allowing the value to be modified. e.g., the following function swaps two values \begin{verbatim} Void swap(var a x, var a y) { tmp = x; x = y; y = tmp; } \end{verbatim} Without the \CD{var} modifiers, this function would have no effect. \subsection{Type Constructors} Type constructors (see section \ref{usertypes}) are effectively functions which create an instance of the relevant type. They are treated like an ordinary function in every way, except in that their implementation is compiler generated. \subsection{Options} The four options which a function can have are \CD{public}, \CD{private}, \CD{pure} and \CD{default}. \CD{public} and \CD{private} define the function's visibility outside the current module or compilation unit (see section \ref{sect:modules}). \CD{pure} declares that the function does not have any side effects and is used as an optimisation hint. \CD{default} functions are ignored if a definition already exists; this is used in the definition of program types (see section \ref{sect:progtype}). \subsection{Overloading} A function can use the same name as another function, provided that they can be disambiguated by the argument types. For example, the following functions can be defined in the same program: \begin{verbatim} Int abs(Int x) { ... } Float abs(Float x) { ... } \end{verbatim} However, functions cannot be disambiguated purely on return type. \subsection{Shorthands} \subsubsection{Zero argument functions} A function which takes no arguments does not need to give an explicit argument list, e.g. \begin{verbatim} Void usage { putStrLn("Error!"); } \end{verbatim} \subsubsection{Returning Expressions} A function which returns a single expression can simply give the expression to be returned, e.g.: \begin{verbatim} Float square(Float x) = x*x; \end{verbatim} If there are no arguments, the function can be written as a form of constant, e.g.: \begin{verbatim} Float pi = 3.141592653589793; \end{verbatim} Note that \CD{pi} is still a function here; the value cannot be modified. In practice, this can be inlined and used exactly the same way as a constant. \subsubsection{Guarded definitions} A function which returns a simple expression based on a number of boolean tests can be defined by listing the tests and results, e.g.: \begin{verbatim} Int abs(Int x) | x<0 = -x | default = x; \end{verbatim} This is equivalent to the following basic form: \begin{verbatim} Int abs(Int x) { return (if (x<0) -x else x); } \end{verbatim}kaya-0.4.4/docs/future.tex0000644000175100017510000000106211170340766013540 0ustar cimcim\section{Future Plans} \subsection{Planned Features for Version 1.0} \begin{itemize} \item Full pattern matching syntax. \item Complete module system. \item A comprehensive library. \item A large, well-designed test suite. \item Efficiency, stability, users. \end{itemize} \subsection{Wishlist} \begin{itemize} \item A selection of optimisations, including arbitrary user defined program transformations. \item Running via a special purpose Apache module, rather than CGI. \item Some form of overloading function names. Possibly subtyping? \end{itemize} kaya-0.4.4/docs/expressions.tex0000644000175100017510000001345711170340767014624 0ustar cimcim\section{Expressions} \label{sect:expressions} \Kaya{} expressions can, approximately, be divided into three groups. These are typed expressions (i.e., those which compute a value), void expressions (i.e., those which do not compute a value and therefore exist for their side effects) and control expressions (i.e., those which affect program flow). Void expressions and control expressions roughly correspond to statements in traditional languages. Typed expressions occur only in typed contexts (e.g. arguments to function calls). A top level expression is either a void expression or a control expression. \fragment{ \BNF{ \Rule{\MC{expr}}{\MC{void\_expr} \CD{;} \maybe{\MC{expr}}} \Or{\MC{control\_expr} \CD{;} \maybe{\MC{expr}}} } } \subsection{Typed Expressions} \subsubsection{Variables} \fragment{ \BNF{ \Rule{\MC{typed\_expr}}{\ldots} \Or{\MC{var\_expr}} \Rule{\MC{var\_expr}}{\MC{identifier}} \Or{\CD{@}\MC{identifier}} \Or{\MC{var\_expr} \CD{.} \MC{identifier}} \Or{\MC{typed\_expr}\CD{[}\MC{typed\_expr}\CD{]}} } } There are four kinds of variable expression: \begin{enumerate} \item An identifier, which refers to a variable or a function definition. If the name refers to a zero argument function then the name becomes a function application. \item A quoted identifier, \CD{@}\MC{identifier}. This refers to a function, but does not apply it even if it is a zero argument function. \item Field access from a structure, \MC{var\_expr}\CD{.}\MC{identifier}. \item Array lookup, \MC{typed\_expr}\CD{[}\MC{typed\_expr}\CD{]}. The array does not have to be a variable, but can arise as the result of a typed computation. \end{enumerate} \subsubsection{Operators} \fragment{ \BNF{ \Rule{\MC{typed\_expr}}{\MC{typed\_expr} \MC{infix} \MC{typed\_expr}} \Or{\MC{prefix} \MC{typed\_expr}} \Or{\CD{(}\MC{typed\_expr}\CD{)}} } } \Kaya{} includes the usual set of operators, with the usual precedence, using brackets to override precedence. The operators are given in Table \ref{optable}, in increasing order of precedence. All associate from left to right. \begin{table}[h] \begin{center} \begin{tabular}{|l|l|l|} \hline Precedence & Operator & Description \\ \hline 1 & \CD{|} & Bitwise OR \\ & \CD{||} & Boolean OR \\ \hline 2 & \CD{\&} & Bitwise AND \\ & \CD{\&\&} & Boolean AND \\ \hline 3 & \CD{==} & Equality \\ &\CD{!=} & Inequality \\ \hline 4 & \CD{<} & Less than \\ & \CD{>} & Greater than \\ & \CD{<=} & Less than or equal\\ & \CD{>=} & Greater than or equal\\ \hline 5 & \CD{<<} & Bitwise shift left \\ & \CD{>>} & Bitwise shift right \\ \hline 6 & \CD{+} & Addition \\ & \CD{-} & Subtraction \\ \hline 7 & \CD{*} & Multiplication \\ & \CD{/} & Division \\ & \CD{\%} & Modulus (remainder) \\ & \CD{**} & Power \\ \hline 8 & \CD{-} & Numerical negation (unary) \\ \hline 9 & \CD{!} & Boolean negation (unary) \\ \hline 10 & \CD{(} \CD{)} & Grouping \\ \hline \end{tabular} \end{center} \caption{Operators} \label{optable} \end{table} \subsubsection{Functions} Including partial application and infix calls. \subsubsection{Lambda Expressions} \subsubsection{Coercions} \subsubsection{Tuples} \subsubsection{Typed Control Structures} See sections \ref{ifexp} and \ref{caseexp} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Control Expressions} Control expressions are used to direct the program flow. They typically manage the execution of blocks of code; blocks may be empty, or complex expressions, or single statements. \fragment{ \BNF{ \Rule{\MC{block}}{\CD{\{}\CD{\}}} \Or{\CD{\{} \MC{expr} \CD{\}}} \Or{\MC{void\_expr}\CD{;}} } } \subsubsection{\CD{if...then...else}} \label{ifexp} % don't forget typed if expressions \subsubsection{\CD{for} loops} \CD{for} loops are used to iterate through an array: \fragment{ \BNF{ \Rule{\MC{control\_expr}}{\ldots} \Or{ \CD{for} \MC{identifier} \maybe{\MC{counter}} \CD{in} \MC{typed\_expr} \MC{block} } \Rule{\MC{counter}}{\CD{@}\MC{identifier}} } } The \MC{variable} can be either a variable name or a reference into an array, and the \MC{expression} must be of type \CD{Void}. Where the iteration is across a range of numbers, the following syntax may be used to generate the array: \begin{itemize} \item \CD{[a,b]} creates an array from \CD{a} to \CD{b}, where a$\le$b. This is equivalent to \CD{range(a,b)}. e.g. \CD{for x in [1..10] \{ ... \} } iterates over the numbers 1 to 10. \item \CD{[a,b..c]} creates an array from \CD{a} to \CD{c}, with step \CD{b-a}. This is equivalent to \CD{range(a,c,b-a)}. e.g. \CD{for x in [10,9..1] \{ ... \} } iterates over the numbers from 10 down to 1. \end{itemize} C-style for loops may also be used, although usually the above style should be preferred: \fragment{ \BNF{ \Rule{\MC{control\_expr}}{\ldots} \Or{ \CD{for (}\MC{void\_expr} \CD{;} \MC{typed\_expr} \CD{;} \MC{void\_expr}\CD{)} \MC{block} } } } %It is also possible to iterate across a \CD{LazyArray} using a for loop. %(TODO: More detail on using LazyArrays with for) \subsubsection{\CD{while} loops} Inluding while and do...while. \subsubsection{\CD{case} statements} \label{caseexp} % don't forget typed case expressions \subsubsection{\CD{try...catch} blocks} \subsubsection{\CD{repeat} loops} \CD{repeat} loops execute the given control statement forever; useful e.g. for repeatedly evaluating a case expression. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Void Expressions} \subsubsection{Assignment} Including tuple assignment, guarded assignment. Also include binding assignment; i.e., assignment with a type declaration. \subsubsection{Maths Shorthand} i.e. +=, ++, etc. \subsubsection{Throwing Exceptions} \subsubsection{Return} \subsubsection{Function calls} As for typed expressions, but for void functions. \subsubsection{Breaking out of loops} \subsubsection{Tracing} trace statement. \subsubsection{No-operations} kaya-0.4.4/docs/Makefile0000644000175100017510000000127111170340767013147 0ustar cimcimLATEX = latex BIBTEX = bibtex MAKEIDX = makeindex DVIPS = dvips DVIPDF = dvipdf TARGET = kaya.ps SRCS = kaya.tex macros.ltx builtins.tex functions.tex structure.tex \ expressions.tex future.tex lexical.tex types.tex \ foreign.tex internals.tex modules.tex progtypes.tex all: kaya.ps kaya.pdf kaya.dvi: ${SRCS} references.bib html: latex2html kaya.tex -local_icons -bottom_navigation -style kaya.css cp kaya.css kaya tidy -modify kaya/*.html clean: rm -f *.aux *.bbl *.blg *.dvi *.log *.pdf *.ps rm -rf kaya distclean: clean rm -f *~ %.ps: %.dvi dvips -f $< > $@ %.pdf: %.dvi dvipdfm $< %.dvi: %.tex ${SRCS} ${LATEX} $< ${BIBTEX} $* ${LATEX} $< ${LATEX} $< kaya-0.4.4/docs/lexical.tex0000644000175100017510000000702111170340767013651 0ustar cimcim\section{Lexical Structure} \subsection{Constants} Constants available in \Kaya{} include integers, floating point values, strings, characters and booleans, as shown in Figure \ref{consts}. \FFIG{ \begin{tabular}{rcl} \MC{constant} & ::= & \MC{int} \\ & $\mid$ & \MC{float} \\ & $\mid$ & \MC{string} \\ & $\mid$ & \MC{bool} \\ & $\mid$ & \MC{char} \\ \\ \MC{int} & ::= & \oneplus{\MC{digit}} \\ \MC{float} & ::= & \oneplus{\MC{digit}} . \oneplus{\MC{digit}} \maybe{\MC{exp}}\\ \MC{string} & ::= & \CD{"}\zeroplus{\MC{ascii}}\CD{"} \\ \MC{char} & ::= & \CD{'}\MC{ascii}\CD{'} \\ \MC{boolean} & ::= & \CD{true} $\mid$ \CD{false} \\ \\ \MC{digit} & ::= & 0 $\mid$ 1 $\mid$ \ldots $\mid$ 9 \\ \MC{exp} & ::= & \CD{e+} \oneplus{\MC{digit}} \\ & $\mid$ & \CD{e-} \oneplus{\MC{digit}} \\ & $\mid$ & \CD{e} \oneplus{\MC{digit}} \\ \MC{ascii} & ::= & $\langle$any printable ASCII character$\rangle$ \\ & $\mid$ & $\langle$an escape sequence$\rangle$ \\ \end{tabular} } {Constants} {consts} \subsection{Variables} A variable name is any sequence of characters (other than a reserved word, see section \ref{reserved}) beginning with a letter or underscore, and containing only letters, underscores, digits or apostrophes. In the BNF, we refer to variable names as \MC{identifier}. Names which must begin with an upper case letter are referred to as \MC{uc\_identifier}. Names which must begin with a lower case letter are referred to as \MC{lc\_identifier}. \subsection{Operators} The following tokens are operators: \begin{tabular}{ccccccc} \CD{+} & \CD{-} & \CD{*} & \CD{/} & \CD{\%} & \CD{**} & \CD{!} \\ \CD{++} & \CD{--} & \CD{+=} & \CD{-=} & \CD{*=} & \CD{/=} \\ \CD{==} & \CD{!=} & \CD{<} & \CD{>} & \CD{<=} & \CD{>=} \\ \CD{\&} & \CD{|} & \CD{\^} & \CD{\&\&} & \CD{||} & \CD{<<} & \CD{>>} \\ \end{tabular} \subsection{Reserved Words} \label{reserved} The lexical analyser recognises the following as reserved words, and hence they cannot be used as type or variable names: \CD{Bool}, \CD{Char}, \CD{Exception}, \CD{File}, \CD{Float}, \CD{Int}, \CD{Ptr}, \CD{String}, \CD{Void}, \CD{abstract}, \CD{break}, \CD{case}, \CD{catch}, \CD{data}, \CD{default}, \CD{do}, \CD{else}, \CD{end}, \CD{false}, \CD{finally}, \CD{fnid}, \CD{foreign}, \CD{for}, \CD{globals}, \CD{if}, \CD{import}, \CD{include}, \CD{in}, \CD{lambda}, \CD{module}, \CD{of}, \CD{pass}, \CD{pure}, \CD{private}, \CD{public}, \CD{repeat}, \CD{return}, \CD{size}, \CD{throw}, \CD{trace}, \CD{true}, \CD{try}, \CD{type}, \CD{var}, \CD{while}. \subsection{Delimiters} The following tokens are used as delimiters: \begin{tabular}{ccccccc} \CD{\{} & \CD{\}} & \CD{(} & \CD{)} & \CD{[} & \CD{]} \\ \CD{.} & \CD{=} & \CD{,} & \CD{|} & \CD{;} & \CD{`} & \CD{->} \\ \end{tabular} \subsection{Comments} A single line comment is introduced with \CD{//}, and continues to the end of a line, e.g.: \begin{verbatim} pi = 3.0; // unreasonable approximation \end{verbatim} A multi line comment is introduced with \CD{/*} and continues until \CD{*/}, e.g.: \begin{verbatim} /* We should probably use something more accurate than this, but I can't remember any more decimal places */ pi = 3.14; \end{verbatim} \subsection{Directives} Directives (special instructions to the compiler) are prefixed with a \CD{\%} sign. These may be implementation dependent; those required by all implementations are: \CD{imported}, \CD{include}, \CD{link}, \CD{VM}. \noindent An implementation is free to introduce others as required. kaya-0.4.4/docs/internals.tex0000644000175100017510000000006211170340766014224 0ustar cimcim\section{Virtual Machine and Data Representation} kaya-0.4.4/docs/types.tex0000644000175100017510000002026411170340767013400 0ustar cimcim\section{Types} \subsection{Rationale} \Kaya{} is a polymorphic statically typed language; i.e., types are checked at compile time and values retain the same type throughout their lifetime. There are two major advantages to this over more dynamically typed languages. Firstly, several classes of programming error are caught before the program is run, rather than at some possibly obscure and difficult to reproduce point during execution. Secondly, static typing allows the programmer to describe data structures more precisely, which is a valuable aid both for the programmer and the compiler. Besides, there are already lots of dynamically typed scripting languages! Unlike more traditional statically typed languages such as C++ and Java it is not usually necessary to declare the types of local variables, since these can (in almost all cases) be inferred from context. \Kaya{}'s type system also allows you to create and use variables freely without declaring them in advance, and without explicit casting. Programming is about manipulating data, and if data structures are well designed, manipulating them should be easy. This was a point made by Fred Brooks many years ago \cite{manmonth} and repeated by Eric Raymond \cite{esr}. Therefore, \Kaya{} provides a notation for accurately describing and manipulating data structures as algebraic data types (a feature more commonly seen in functional languages such as Haskell \cite{haskell-report} and ML \cite{ml}). Before looking at program structure, and how to manipulate data, let us consider the datatypes available in \Kaya{}. \subsection{Primitive Types} \fragment{ \BNF{ \Rule{\MC{type}}{\CD{Int}} \Or{\CD{Char}} \Or{\CD{Bool}} \Or{\CD{Float}} \Or{\CD{String}} \Or{\CD{File}} \Or{\CD{Ptr}} \Or{\CD{Exception}} \Or{\CD{Void}} \Or{\ldots} } } There are a number of primitive types, which can be combined into various forms of compund types. Compound types can be built as arrays (discussed in section \ref{arrays}), user defined types (in section \ref{usertypes}), or function types (discussed in section \ref{funtypes}). The primitive types in \Kaya{} are described in Table \ref{primtable}. \begin{table}[h] \begin{tabular}{|l|l|l|} \hline Type name & Meaning & Example values\\ \hline \CD{Int} & 32 bit Integers & \CD{42}, \CD{6}, \ldots \\ \CD{Char} & Characters & \CD{'a'}, \CD{'Z'}, \CD{'\SL{}n'}, \ldots \\ \CD{Bool} & Boolean & \CD{true}, \CD{false} \\ \CD{Float} & Floating point values & \CD{42.0}, \CD{3.1415}, \CD{2.718}, \ldots \\ \CD{String} & Strings of characters & \CD{"Fish"},\CD{"Hello world\SL{}n"}, \ldots \\ \CD{File} & File handles & N/A \\ \CD{Exception} & Exceptions & \CD{Exception("Out Of Cheese Error",1)} \\ \CD{Ptr} & Foreign language pointers & N/A \\ \CD{Void} & Empty type & none \\ \hline \end{tabular} \caption{Primitive Types} \label{primtable} \end{table} There are no pointer types, other than pointers to foreign objects. In \Kaya{} everything is a reference (and therefore, internally, a pointer). The programmer never needs to worry about any memory management details; it is all handled by the run-time system and the garbage collector\footnote{The current implementation usesthe Boehm garbage collector~\cite{boehm-gc}}. C and Java programmers should note that all concrete types begin with a capital letter. This is to allow a distinction with polymorphic type variables (see section \ref{polymorphic}). \subsection{Arrays} \label{arrays} \fragment{ \BNF{ \Rule{\MC{type}}{\ldots} \Or{\CD{[} \MC{type} \CD{]}} } } Given a type \CD{t}, an array containing values of type \CD{t} is denoted by \CD{[t]}. An array value can be constructed by listing the values between square brackets, \CD{[]}, e.g.: \begin{verbatim} empty = []; count = [1,2,3,4,5,6,7,8,9,10]; // Type is [Int] people = ["Fred","Jim","Sheila"]; // Type is [String] \end{verbatim} Integer arrays can also be constructed with \demph{ranges}, e.g.: \begin{verbatim} count = [1..100]; evens = [2,4..100]; downards = [10,9..0]; \end{verbatim} \subsection{Function Types} \label{funtypes} \fragment{ \BNF{ \Rule{\MC{type}}{\ldots} \Or{\MC{type} \CD{(} \oneplus{\MC{type},} \CD{)}} } } Functions are first class values, and so have types like any other value. A function type expresses the return type and type argument types, e.g. \CD{Int(Float,String)} is the type of a function which takes a \CD{Float} and a \CD{String} and returns an \CD{Int}. \subsection{Polymorphic Types} \label{polymorphic} \fragment{ \BNF{ \Rule{\MC{type}}{\ldots} \Or{\MC{lc\_identifier}} } } A polymorphic type (i.e. a generic type which can be instantiating by another concrete type) is denoted by an identifier beginning with a lower case identifier. The case of the initial letter distinguishes polymorphic type variables from concrete types. \subsection{User Defined Types} \label{usertypes} \fragment{ \BNF{ \Rule{\MC{type}}{\ldots} \Or{\CD{uc\_identifier}} \Or{\CD{uc\_identifier} \CD{<} \oneplus{\MC{type},} \CD{>}} } } User defined types can describe enumerations, records or discriminated unions. The grammar for declaring a data type is as follows: \fragment{ \BNF{ \Rule{\MC{data\_decl}}{\zeroplus{\MC{data\_opt}} \CD{data} \MC{uc\_identifier} \MC{params} \MC{data\_def}} \Rule{\MC{params}}{} \Or{\CD{<}\zeroplus{\MC{lc\_identifier},}\CD{>}} \Rule{\MC{data\_def}}{ \CD{(} \zeroplus{$\langle$\MC{type} \maybe{\MC{identifier}}$\rangle$,} \CD{)} } \Or{\oneplus{$\langle$\MC{constructor}\CD{|}$\rangle$}} \Rule{\MC{constructor}}{\MC{identifier}} \Or{\MC{identifier} \CD{(} \zeroplus{$\langle$\MC{type} \maybe{\MC{identifier}}$\rangle$,} \CD{)} } \Rule{\MC{data\_opt}}{\CD{public}} \Or{\CD{private}} \Or{\CD{abstract}} } } Any type variable used in the data definition must have been listed in \MC{params}, otherwise there is a compile time error. Identifier names are optional, and a name can occur at most once within a data declaration. The options \CD{public}, \CD{private} and \CD{abstract} define the type's visibility outside the current module or compilation unit (see section \ref{sect:modules}). \CD{public} means the type is completely visible, \CD{private} means the type is invisible. \CD{abstract} means that the type is visible, but the constructors are invisibile. Some brief examples follow. \subsubsection{Enumerations} An enumeration consists of a number of constructor declarations with no arguments, e.g.: \begin{verbatim} data Colour = Red | Green | Blue; data Weather = Sunny | Cloudy | Rainy | Snowy; \end{verbatim} \subsubsection{Records} A record is a data type with only one constructor, e.g.: \begin{verbatim} data Person(String name, Int age); data Location(Int x, Int y, Int z); \end{verbatim} Values of these types are constructed as follows: \begin{verbatim} bob = Person("Bob",30); wheresbob = Location(1900,762,800); \end{verbatim} Field values can be projected out of such values by referring to the field name: \begin{verbatim} bobsname = bob.name; bobsheight = wheresbob.z; \end{verbatim} \subsubsection{Discriminated Unions} Discriminated unions combine enumerations and records, e.g.: \begin{verbatim} data IntOrString = mkInt(Int num) | mkString(String str); data List = nil | cons(a head, List tail); \end{verbatim} \CD{IntOrString} represents either an integer or string, depending on whether it is constructed with \CD{mkInt} or \CD{mkString}. \CD{List} is a polymorphic type representing a linked list. Projection of a value from a discriminated union checks whether the correct constructor was used; e.g. the following are ok: \begin{verbatim} x = mkInt(5); list = cons("Fred",cons("Jim",cons("Sheila",nil))); number = x.num; first = list.head; \end{verbatim} The following would generate an error at run-time: \begin{verbatim} x = mkString("Sossidges"); number = x.num; // Oops, didn't use mkInt. \end{verbatim} See section \ref{caseexp} (\CD{case} statements) for more on how to work with discriminated unions. \subsection{Exceptions} \label{exceptions} An exception is a value describing what went wrong. It is simply a pair of a string (the error message) and an integer (the error code). \fragment{ \BNF{ \Rule{\MC{exception}} {\CD{Exception} \CD{(} \MC{typed\_expr} \CD{,} \MC{typed\_expr} \CD{)}} } } See section \ref{sect:expressions} for the definition of \MC{typed\_expr}.kaya-0.4.4/docs/README.KayHTML0000644000175100017510000000637411170340766013607 0ustar cimcim* KayHTML - advanced HTML handling for Kaya The aim of the KayHTML modules is to provide a set of (X)HTML handling libraries for Kaya, that encourage (and enforce where possible) good quality code, allow straightforward construction and templating of web pages, and interface well with Kaya's built-in session handling to allow as much separation of logic from template as is possible. Additionally, to provide an alternative Webprog library suitable for larger web applications. This document is intended as a developer's reference - also see comments in the source code and the generated documentation. * Files ** HTMLDocument.k This file sets out the basic structure of a HTML document and provides general editing capability. High-level operations such as templating should probably be provided by another module. It is divided into several parts: 1) Data type definitions 2) Document constructor and toString convertor 3) data editing (including HTTP headers) 4) Setting generic attributes on elements 5) Handling block-level elements 6) Handling inline elements 7) Handling tables 8) Handling forms (webapp/webprog-enabled or otherwise) TODO: Need a fromString function that will appropriately fill an ElementTree. Writing one that will deal with HTML as well as XHTML may be tricky, due to optional end tags such as

    , and even optional start tags such as . ** ElementTree.k This file provides low-level operations on a document tree structure. Note that its print-out operation will always escape < to < and so on, so it's only possible to add HTML tags as part of an element. This guarantees well-formedness of code. TODO: This needs a generic fromString function that will construct an ElementTree from a String of XML data. ** ElementTreeData.k This file defines the document tree structure. Nothing other than data definitions should live here. ** HTMLnesting.k This file partially defines the nesting behaviour allowed in the HTML DTD. Any divergence from the HTML 4.01 DTD's allowed nesting is a bug and should be fixed. ** HTMLentities.k and XMLentities.k Processing functions to convert between literal UTF-8 characters (which are stored in Kaya as a UCS Char()), numeric references, and named references (where they exist in the standard). Output from KayHTML should always use either literal UTF-8 characters or numeric references, but users may find it convenient to enter named entities. Internal storage should always be as literal UCS Char's, to make length-dependent functions work properly. Use of XMLentities.k for non-(X)HTML documents will require adding an option to disable the processing of the HTMLentities.k data except for the five standard named entities. ** Webprog.k Base functions for the 'webprog' program type. Similar to 'Webapp.k' ** URL.k [TODO] URL manipulation functions to make constructing and properly URLencoding URLs a bit easier. * User documentation When it gets stable enough it will need some. At the moment the HTMLtest.k program gives a quick example of how the HTMLDocument API works, and the webprog.k -> simple.cgi very simply demonstrates webprog-style programs. * Authors and copyright KayHTML is copyright Chris Morris 2005 except where otherwise stated. It is released under the GNU Lesser General Public License 2.1 kaya-0.4.4/docs/README.MinGW0000644000175100017510000001032511170340766013346 0ustar cimcimThis file loosely explains how to compile Kaya on Windows. You may need to consult the documentation of the packages you install at times. Leave plenty of time. ============================================================================== Step 1: Basic environment ============================================================================== Go to http://www.mingw.org/ and download the following packages: - Binutils, MinGW-make, mingw-runtime, mingw-utils, w32api Unpack them all to the same directory. Download (still from mingw) and install - msys, msysDTK, msys-autoconf, msys-automake, msys-libtool Finally, download and install a C compiler into your mingw package. - 3.2 definitely works, you can try 3.3 or later if you want (they should work, they do on other platforms) Run Msys to generate your home directory. ============================================================================== Step 2: Build-dependencies ============================================================================== Now, get the build dependencies (and compile them in this order via MSys): Always configure with --prefix=/mingw (some of these have windows binaries available at the moment from 3rd parties) - libgc garbage collector Version 6.5 works, probably others do. Make sure you use --enable-threads=win32 --enable-cplusplus. If this bit goes wrong, every Kaya app will immediately segfault when run. If you can't get it to work, and it does seem a bit hit-and-miss, the binary distribution of the windows development environment has working libgc{,cpp}.a files. - libpcre (perl compatible regular expressions) This one is straightforward from gnuwin32.sourceforge.net - libgpg-error This one is straightforward, just get it from GnuPG and compile. - libgcrypt (cryptography) Again, get it from GnuPG. www.securitypunk.com describes how to patch this to make it work on minGW. http://www.securitypunk.com/libgcrypt/index.html The bit missing is that you also need to manually install the libgcrypt-config into /mingw/bin because the build failure on the random file misses that. - zlib (compression) Get it via minGWport (you'll need to either install wget or download the source tarball yourself - it's pretty straightforward to figure out) - libiconv minGWport again - libintl-0.14.4 (wide character support) Available from gnuwin32.sourceforge.net You'll need to make libintl.la and libiconv.la via http://www.wormux.org/wiki/compile_under_mingw.php (or just take the .la files from the binary distribution) - gnutls (TLS) Once the above's in, it will compile from plain sources. The documentation won't compile - if you get to that build error, just do make install and you'll get the libraries (which is the bit you need). - pdcurses (Text console library) www.mingw.org has this one. Easy install. - pthreads (Posix threads) This only actually gets use for a couple of time-related functions on windows (it's essential for everything on Linux, of course). sources.redhat.com has a windows version. ============================================================================== Step 3: Yet more build dependencies ;) ============================================================================== Both of these are from http://www.haskell.org/ - you'll have to install them outside your minGW path. - ghc Haskell compiler Get a windows binary build of this or you'll be here all week. - happy parser generator Again, just get the binary. Edit the /etc/profile file in Msys to put GHC and Happy into your path, restart MSys. ============================================================================== Step 4: Actually compiling Kaya ============================================================================== Put the kaya distribution directory somewhere inside the MinGW tree (Msys-install-directory/home/your-username/... is usual) ./configure --prefix=c:/kaya (or wherever you want to install it) make clean all make test (if you start getting segfaults, go back to the top of step 2 and try poking libgc, if you get other failures, let us know - except test019, which has harmless line-ending issues but appears to fail) make install Edit the /etc/profile in Msys to put c:/kaya/bin into your path and restart Msys. You can now use kayac via Msys. kaya-0.4.4/docs/progtypes.tex0000644000175100017510000000005611170340767014265 0ustar cimcim\section{Program Type} \label{sect:progtype} kaya-0.4.4/docs/modules.tex0000644000175100017510000000014711170340767013702 0ustar cimcim\section{Module System} \label{sect:modules} \subsection{Namespaces} \subsection{Global Variables} kaya-0.4.4/docs/kaya.tex0000644000175100017510000000436511170340767013165 0ustar cimcim\documentclass[a4paper]{article} \input{macros.ltx} \usepackage{palatino} \setlength{\parindent}{0cm} \setlength{\parskip}{1ex} \begin{document} \title{The \Kaya{} Programming Language, Version \input{../VERSION}} % Note: Please add yourself as an author if you add anything else! \author{Edwin Brady \and Chris Morris \and [Your Name Here!] \\ email: \texttt{kaya@compsoc.dur.ac.uk}} \maketitle \section{Introduction} This document is eventually intended to evolve into reference documentation for the \Kaya{} programming language. It is not intended to be a tutorial, but rather an accurate description of the language and compiler features. The language itself, its type system and its data and execution models are introduced. At present, there is no formal and unambiguous definition of the language, besides the implementation itself. The lexical structure is implemented by \texttt{Lexer.hs} and the grammar by \texttt{Parser.y}. Since the implementation is constantly evolving, so is this document. If you find any errors or inconsistencies, please let us know. %One day, of course, it would be nice to have a document %describing the precise language details, but that will have to wait! %\TODO{At the very least, we might add the type inference rules at some %point.} Throughout, code is presented in \CD{this style} and meta-code (i.e., something standing for code) is presented in \MC{this style}. We use the convention that \oneplus{\MC{x}} means a sequence of at least one \MC{x}, and \zeroplus{\MC{x}} means a sequence of zero or more \MC{x}s. \oneplus{\MC{x},} means a delimited sequence of one or more \MC{x}s (where the delimiter is an arbitrary symbol), and correspondingly \zeroplus{\MC{x},}. \maybe{\MC{x}} denotes an optional \MC{x}. Complex BNF expressions may be enclosed in angle brackets, e.g. \zeroplus{$\langle$\MC{type} \MC{identifier}$\rangle$,} denotes a comma separated list of types followed by identifiers. \input{lexical.tex} \input{types.tex} \input{structure.tex} \input{functions.tex} \input{expressions.tex} \input{builtins.tex} \input{progtypes.tex} \input{modules.tex} \input{foreign.tex} \input{internals.tex} \input{future.tex} \nocite{pj-imp} \nocite{compilers} \bibliographystyle{alpha} \bibliography{references} \end{document}kaya-0.4.4/docs/builtins.tex0000644000175100017510000000003511170340766014056 0ustar cimcim\section{Built-in Functions} kaya-0.4.4/docs/kaya.css0000644000175100017510000000243311170340764013144 0ustar cimcim/* Century Schoolbook font is very similar to Computer Modern Math: cmmi */ .MATH { font-family: "Century Schoolbook", serif; } .MATH I { font-family: "Century Schoolbook", serif; font-shape: italic } .BOLDMATH { font-family: "Century Schoolbook", serif; font-weight: bold } BODY { font-family: Verdana, Tahoma, "Myriad Web", Syntax, sans-serif; color: #202040; background: #e0e0f0; } TH { font-family: Verdana, Tahoma, "Myriad Web", Syntax, sans-serif; color: #404040; background: #B0B0B0; } TD { font-family: Verdana, Tahoma, "Myriad Web", Syntax, sans-serif; color: #000000; background: #F0F0F0; } /* implement both fixed-size and relative sizes */ SMALL.XTINY { font-size : xx-small } SMALL.TINY { font-size : x-small } SMALL.SCRIPTSIZE { font-size : smaller } SMALL.FOOTNOTESIZE { font-size : small } SMALL.SMALL { } BIG.LARGE { } BIG.XLARGE { font-size : large } BIG.XXLARGE { font-size : x-large } BIG.HUGE { font-size : larger } BIG.XHUGE { font-size : xx-large } /* heading styles */ H1 { } H2 { } H3 { } H4 { } H5 { } /* mathematics styles */ DIV.kisplaymath { } /* math displays */ TD.eqno { } /* equation-number cells */ /* document-specific styles come next */ kaya-0.4.4/docs/structure.tex0000644000175100017510000000265511170340767014300 0ustar cimcim\section{Program Structure} A program consists of the header followed by a list of bindings. \fragment{ \BNF{ \Rule{\MC{program}}{\MC{intro} \oneplus{\MC{binding}}} \Rule{\MC{intro}}{\CD{module} \MC{identifier}} \Or{\MC{identifier} \MC{identifier}} \Or{\MC{shebang}} } } The header is either a module declaration, giving the module name, a program declaration, or a \CD{\#!} path. \begin{itemize} \item If a module declaration, it will be compiled as a module, generating a \texttt{.o} file containing code and a \texttt{.ki} file containing interface details. \item If a program declaration, the first identifier gives the name of the file containing startup code (this is often one of \CD{program}, \CD{cgi} or \CD{webapp}), the second gives the root name of the output file. See section \ref{sect:progtype}. \item If a \texttt{\#!} path, the file is assumed to be a \CD{program} and will be executed immediately after compilation --- this allows \Kaya{} to be used for scripting. \end{itemize} Bindings contain the body of the program. They may be used to import other modules; they may be functions, data declarations (already seen in section \ref{usertypes}, global variable declarations or foreign function declarations. They may also contain compiler directives. \fragment{ \BNF{ \Rule{\MC{binding}}{\MC{import}} \Or{\MC{function}} \Or{\MC{data\_decl}} \Or{\MC{global\_block}} \Or{\MC{foreign\_block}} \Or{\MC{directive}} } } kaya-0.4.4/docs/foreign.tex0000644000175100017510000000006511170340766013661 0ustar cimcim\section{Foreign Function Interface} \label{foreign} kaya-0.4.4/docs/references.bib0000644000175100017510000000314411170340764014304 0ustar cimcim@book{compilers, title = {Compilers --- Principles, Techniques and Tools}, year = {1986}, publisher = {Addison-Wesley}, author = {Alfred Aho and Ravi Sethi and Jeffrey Ullman} } @book{pj-imp, title = {The Implementation of Functional Programming Languages}, year = {1987}, publisher = {Prentice-Hall}, author = {Simon {Peyton Jones}} } @misc{boehm-gc, howpublished = {\verb+http://www.hpl.hp.com/personal/Hans_Boehm/gc/+}, title = {A garbage collector for {C} and {C++}}, year = {2001}, author = {Hans-J. Boehm and Alan J. Demers and {Xerox Corporation Silicon Graphic} and {Hewlett-Packard Company}} } @book{manmonth, title = {The Mythical Man-month: Essays on Software Engineering}, year = {1975}, publisher = {Addison Wesley}, author = {Frederick P. Brooks} } @book{esr, month = {October}, title = {The Cathedral And The Bazaar}, year = {1999}, publisher = {O'Reilly}, author = {Eric Raymond} } @misc{haskell-report, title = {Haskell 98 Language and Libraries --- The Revised Report}, year = {2002}, month = {December}, author = {Simon {Peyton Jones} and others}, howpublished = {Available from \verb+http://www.haskell.org/+} } @book{ml, title = {The Definition of Standard ML --- Revised}, year = {1997}, publisher = {MIT Press}, author = {Robin Milner and Mads Tofte and Robert Harper and David MacQueen} } @misc{ typinghaskell, author = "Mark Jones", title = "Typing {Haskell} in {Haskell}", howpublished = "In Haskell Workshop, September 1999.", year = "1999", url = "citeseer.ist.psu.edu/article/jones99typing.html" } kaya-0.4.4/contrib/0000755000175100017510000000000011170340770012210 5ustar cimcimkaya-0.4.4/contrib/glutglue.cc0000644000175100017510000000724211170340770014354 0ustar cimcim#include "glutglue.h" #include #include KayaValue displayfun, reshapefun, idlefun, keyfun, keyupfun, specialfun, specialupfun, mousefun, motionfun, visibilityfun; KayaValue displaydata, reshapedata, idledata, keydata, keyupdata, specialdata, specialupdata, mousedata, motiondata, visibilitydata; #define UTAG(x) switch(KayaUnionGetTag(x)) void do_glutCreateWindow(KString title) { glutCreateWindow(CSTRING(title)); } void display_cb(KayaValue fn, KayaValue data) { displayfun = fn; displaydata = data; glutDisplayFunc(display); } void reshape_cb(KayaValue fn, KayaValue data) { reshapefun = fn; reshapedata = data; glutReshapeFunc(reshape); } void idle_cb(KayaValue fn, KayaValue data) { idlefun = fn; idledata = data; glutIdleFunc(idle); } void key_cb(KayaValue fn, KayaValue data) { keyfun = fn; keydata = data; glutKeyboardFunc(keyboard); } void keyup_cb(KayaValue fn, KayaValue data) { keyupfun = fn; keyupdata = data; glutKeyboardUpFunc(keyboardup); } void special_cb(KayaValue fn, KayaValue data) { specialfun = fn; specialdata = data; glutSpecialFunc(special); } void specialup_cb(KayaValue fn, KayaValue data) { specialfun = fn; specialdata = data; glutSpecialUpFunc(specialup); } void mouse_cb(KayaValue fn, KayaValue data) { mousefun = fn; mousedata = data; glutMouseFunc(mouse); } void motion_cb(KayaValue fn, KayaValue data) { motionfun = fn; motiondata = data; glutMotionFunc(motion); } void visibility_cb(KayaValue fn, KayaValue data) { motionfun = fn; motiondata = data; glutVisibilityFunc(visibility); } void display() { KayaCall(displayfun,1,displaydata); } void reshape(int x, int y) { KayaCall(reshapefun,3,KayaInt(x),KayaInt(y),reshapedata); } void idle() { KayaCall(idlefun,1,idledata); } void keyboard(unsigned char c, int x, int y) { KayaCall(keyfun,4,KayaChar(c),KayaInt(x),KayaInt(y),keydata); } void keyboardup(unsigned char c, int x, int y) { KayaCall(keyupfun,4,KayaChar(c),KayaInt(x),KayaInt(y),keyupdata); } void special(int key, int x, int y) { KayaCall(specialfun,4,KayaInt(key),KayaInt(x),KayaInt(y),specialdata); } void specialup(int key, int x, int y) { KayaCall(specialupfun,4,KayaInt(key),KayaInt(x),KayaInt(y),specialupdata); } void mouse(int buttonv, int statev, int x, int y) { KayaValue button; KayaValue buttonstate; switch(buttonv) { case GLUT_LEFT_BUTTON: button = KayaUnion(0,0); break; case GLUT_MIDDLE_BUTTON: button = KayaUnion(1,0); break; case GLUT_RIGHT_BUTTON: button = KayaUnion(2,0); break; } switch(statev) { case GLUT_UP: buttonstate = KayaUnion(0,0); break; case GLUT_DOWN: buttonstate = KayaUnion(1,0); break; } KayaCall(mousefun,5,button,buttonstate,KayaInt(x),KayaInt(y), mousedata); } void motion(int x, int y) { KayaCall(motionfun,3,KayaInt(x),KayaInt(y),motiondata); } void visibility(int state) { KayaCall(visibilityfun,2,KayaInt(state),visibilitydata); } kint _glut_getMode(KayaValue k) { UTAG(k) { case 0: return GLUT_RGB; case 1: return GLUT_RGBA; case 2: return GLUT_INDEX; case 3: return GLUT_SINGLE; case 4: return GLUT_DOUBLE; case 5: return GLUT_ACCUM; case 6: return GLUT_ALPHA; case 7: return GLUT_DEPTH; case 8: return GLUT_STENCIL; case 9: return GLUT_MULTISAMPLE; case 10: return GLUT_STEREO; case 11: return GLUT_LUMINANCE; } } void doGlutInit(KayaArray modes) { int fake_argc = 1; char *fake_argv[1]; fake_argv[0]=(char*)"test"; glutInit(&fake_argc, fake_argv) ; glutInitDisplayMode((int)orArray(modes,_glut_getMode)); } kaya-0.4.4/contrib/glglue.cc0000644000175100017510000001603711170340770014005 0ustar cimcim#include "glglue.h" #include #include #include #include #include #define UTAG(x) switch(KayaUnionGetTag(x)) #define UARG KayaUnionGetArg // Yuck /*bool getglBool(GLboolean b) { return (b==GL_TRUE); }*/ kint glGetMatrixMode(KayaValue k) { UTAG(k) { case 0: return GL_PROJECTION; case 1: return GL_MODELVIEW; case 2: return GL_TEXTURE; } } kint glGetShadeModel(KayaValue k) { UTAG(k) { case 0: return GL_FLAT; case 1: return GL_SMOOTH; } } kint glGetBuffer(KayaValue k) { UTAG(k) { case 0: return GL_COLOR_BUFFER_BIT; case 1: return GL_DEPTH_BUFFER_BIT; case 2: return GL_ACCUM_BUFFER_BIT; case 3: return GL_STENCIL_BUFFER_BIT; } } kint maskBuffers(KayaArray ks) { return orArray(ks,glGetBuffer); } kint glGetPrimitive(KayaValue k) { UTAG(k) { case 0: return GL_POINTS; case 1: return GL_LINES; case 2: return GL_LINE_STRIP; case 3: return GL_LINE_LOOP; case 4: return GL_TRIANGLES; case 5: return GL_TRIANGLE_STRIP; case 6: return GL_TRIANGLE_FAN; case 7: return GL_QUADS; case 8: return GL_QUAD_STRIP; case 9: return GL_POLYGON; } } kint glGetFeature(KayaValue k) { int x; UTAG(k) { case 0: return GL_DEPTH_TEST; case 1: return GL_BLEND; case 2: return GL_FOG; case 3: return GL_LINE_STIPPLE; case 4: return GL_LIGHTING; case 5: x = KayaGetInt(KayaUnionGetArg(k,0)); switch(x) { case 0: return GL_LIGHT0; case 1: return GL_LIGHT1; case 2: return GL_LIGHT2; case 3: return GL_LIGHT3; case 4: return GL_LIGHT4; case 5: return GL_LIGHT5; case 6: return GL_LIGHT6; case 7: return GL_LIGHT7; } case 6: return GL_NORMALIZE; case 7: return GL_COLOR_MATERIAL; case 8: return GL_POINT_SMOOTH; case 9: return GL_LINE_SMOOTH; case 10: return GL_CULL_FACE; case 11: return GL_TEXTURE_1D; case 12: return GL_TEXTURE_2D; case 13: return GL_SCISSOR_TEST; case 14: return GL_ALPHA_TEST; case 15: return GL_STENCIL_TEST; case 16: return GL_AUTO_NORMAL; } } bool doGLIsEnabled(int f) { return (glIsEnabled(f)==GL_TRUE); } kint glGetListMode(KayaValue k) { UTAG(k) { case 0: return GL_COMPILE; case 1: return GL_COMPILE_AND_EXECUTE; } } kint glGetFace(KayaValue k) { UTAG(k) { case 0: return GL_FRONT; case 1: return GL_BACK; case 2: return GL_FRONT_AND_BACK; } } kint glGetMaterialMode(KayaValue k) { UTAG(k) { case 0: return GL_AMBIENT; case 1: return GL_DIFFUSE; case 2: return GL_AMBIENT_AND_DIFFUSE; case 3: return GL_SPECULAR; case 4: return GL_EMISSION; } } kint glGetTexFunc(KayaValue k) { UTAG(k) { case 0: return GL_DECAL; case 1: return GL_REPLACE; case 2: return GL_MODULATE; case 3: return GL_BLEND; } } kint glGetPixelFormat(KayaValue k) { UTAG(k) { case 0: return GL_RGBA; case 1: return GL_RED; case 2: return GL_GREEN; case 3: return GL_BLUE; case 4: return GL_ALPHA; case 5: return GL_LUMINANCE; case 6: return GL_LUMINANCE_ALPHA; case 7: return GL_DEPTH_COMPONENT; } } kint glGetType(KayaValue k) { UTAG(k) { case 0: return GL_UNSIGNED_BYTE; case 1: return GL_BYTE; case 2: return GL_BITMAP; case 3: return GL_UNSIGNED_SHORT; case 4: return GL_SHORT; case 5: return GL_UNSIGNED_INT; case 6: return GL_INT; case 7: return GL_FLOAT; } } kint glGetTexTarget(KayaValue k, int dim) { if (dim==2) { UTAG(k) { case 0: return GL_TEXTURE_2D; case 1: return GL_PROXY_TEXTURE_2D; } } else { UTAG(k) { case 0: return GL_TEXTURE_1D; case 1: return GL_PROXY_TEXTURE_1D; } } } kint glGetTexType(KayaValue k) { UTAG(k) { case 0: return GL_TEXTURE_1D; case 1: return GL_TEXTURE_2D; } } kint glGetTexWrap(KayaValue k) { UTAG(k) { case 0: return GL_CLAMP; case 1: return GL_REPEAT; } } kint glGetTexFilter(KayaValue k) { UTAG(k) { case 0: return GL_NEAREST; case 1: return GL_LINEAR; case 2: return GL_NEAREST_MIPMAP_NEAREST; case 3: return GL_NEAREST_MIPMAP_LINEAR; case 4: return GL_LINEAR_MIPMAP_NEAREST; case 5: return GL_LINEAR_MIPMAP_LINEAR; } } #define COPYARR(a,v) \ a[0] = (float)KayaGetFloat(KayaUnionGetArg(v,0)); \ a[1] = (float)KayaGetFloat(KayaUnionGetArg(v,1)); \ a[2] = (float)KayaGetFloat(KayaUnionGetArg(v,2)); \ a[3] = (float)KayaGetFloat(KayaUnionGetArg(v,3)); #define COPYARR3(a,v) \ a[0] = (float)KayaGetFloat(KayaUnionGetArg(v,0)); \ a[1] = (float)KayaGetFloat(KayaUnionGetArg(v,1)); \ a[2] = (float)KayaGetFloat(KayaUnionGetArg(v,2)); #define FARG(x,i) ((float)KayaGetFloat(KayaUnionGetArg(x,i))) void doglLight(int l, KayaValue p) { GLfloat arr[] = { 0.0, 0.0, 0.0, 0.0 }; UTAG(p) { case 0: COPYARR(arr,p); glLightfv(l,GL_AMBIENT,arr); break; case 1: COPYARR(arr,p); glLightfv(l,GL_DIFFUSE,arr); break; case 2: COPYARR(arr,p); glLightfv(l,GL_SPECULAR,arr); break; case 3: COPYARR(arr,p); glLightfv(l,GL_POSITION,arr); break; case 4: COPYARR3(arr,p); glLightfv(l,GL_SPOT_DIRECTION,arr); break; case 5: glLightf(l,GL_SPOT_EXPONENT,FARG(p,0)); break; case 6: glLightf(l,GL_SPOT_CUTOFF,FARG(p,0)); break; case 7: glLightf(l,GL_CONSTANT_ATTENUATION,FARG(p,0)); break; case 8: glLightf(l,GL_LINEAR_ATTENUATION,FARG(p,0)); break; case 9: glLightf(l,GL_QUADRATIC_ATTENUATION,FARG(p,0)); break; } } void doglMaterial(int l, KayaValue p) { GLfloat arr[] = { 0.0, 0.0, 0.0, 0.0 }; UTAG(p) { case 0: COPYARR(arr,p); glMaterialfv(l,GL_AMBIENT,arr); break; case 1: COPYARR(arr,p); glMaterialfv(l,GL_DIFFUSE,arr); break; case 2: COPYARR(arr,p); glMaterialfv(l,GL_AMBIENT_AND_DIFFUSE,arr); break; case 3: COPYARR(arr,p); glLightfv(l,GL_SPECULAR,arr); break; case 4: glMaterialf(l,GL_SHININESS,FARG(p,0)); break; case 5: COPYARR(arr,p); glMaterialfv(l,GL_EMISSION,arr); break; } } void doglTexParam(int target, KayaValue p) { GLfloat arr[] = { 0.0, 0.0, 0.0, 0.0 }; UTAG(p) { case 0: glTexParameterf(target, GL_TEXTURE_WRAP_S, glGetTexWrap(UARG(p,0))); break; case 1: glTexParameterf(target, GL_TEXTURE_WRAP_T, glGetTexWrap(UARG(p,0))); break; case 2: glTexParameterf(target, GL_TEXTURE_MAG_FILTER, glGetTexFilter(UARG(p,0))); break; case 3: glTexParameterf(target, GL_TEXTURE_MIN_FILTER, glGetTexFilter(UARG(p,0))); break; case 4: COPYARR(arr,p); glTexParameterfv(target,GL_TEXTURE_BORDER_COLOR, arr); break; case 5: glTexParameterf(target, GL_TEXTURE_PRIORITY, FARG(p,0)); break; } } kint doGenTexture() { GLuint t; glGenTextures(1,&t); return t; } kint doDeleteTexture(GLuint t) { glDeleteTextures(1,&t); } void glTexMode(int f) { glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,f); } bool checkError(void *vmptr, KayaValue errmsg) { VMState* vm = (VMState*)vmptr; GLenum err = glGetError(); if (err!=GL_NO_ERROR) { // printf("%s\n",gluErrorString(err)); KayaSetString(errmsg, KSTRING((char*)(gluErrorString(err)))); return false; } return true; } kaya-0.4.4/contrib/glglue.h0000644000175100017510000000203711170340770013642 0ustar cimcim#ifndef _GLGLUE_H // -*-C++-*- #define _GLGLUE_H #include #include extern "C" { // bool getglBool(GLboolean b); kint glGetMatrixMode(KayaValue k); kint glGetShadeModel(KayaValue k); kint glGetBuffer(KayaValue k); kint glGetPrimitive(KayaValue k); kint glGetFeature(KayaValue k); kint glGetListMode(KayaValue k); kint glGetFace(KayaValue k); kint glGetMaterialMode(KayaValue k); kint glGetTexFunc(KayaValue k); kint glGetPixelFormat(KayaValue k); kint glGetType(KayaValue k); kint glGetTexTarget(KayaValue k, int dim); kint glGetTexType(KayaValue k); kint glGetTexWrap(KayaValue k); kint glGetTexFilter(KayaValue k); kint maskBuffers(KayaArray ks); bool doGLIsEnabled(int f); void doglLight(int l, KayaValue p); void doglMaterial(int l, KayaValue m); void doglTexParam(int target, KayaValue p); kint doGenTexture(); kint doDeleteTexture(GLuint t); void glTexMode(int f); bool checkError(void *vmptr, KayaValue err); } #endif kaya-0.4.4/contrib/Kayurses.k0000644000175100017510000001611311170340770014174 0ustar cimcim/* High-level (n|pd)Curses access functions Copyright (C) 2005,2007 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence version 2.1. */ "High-level Curses functions This module contains high-level functions for setting up basic interactive Curses applications, without requiring deep familiarity with the Curses API. It also provides useful convenience functions for those familiar with the API. Historically this module provided a cross-platform interface to ncurses and pdcurses, but the Curses module is now fully cross-platform itself. Programs importing Kayurses should also import Curses." module Kayurses; import public Curses; type ColourName = Int; /*"Text colours This data type represents various text colours." public data ColourName = Black | Red | Green | Yellow | Blue | Magenta | Cyan | White; */ "Text weights This data type represents weights for text supported on common terminals." public data WeightName = Heavy | Light | Inverse | HeavyInverse; "Initialise Curses This function initialises the curses library, setting some commonly-used parameters for interactive applications. endScreen" public Void startScreen() { initScreen(); cbreakMode(true); echoMode(false); startColour(); if (hasColours()) { initPair(1,Curses::Red,Curses::Black); initPair(2,Curses::Green,Curses::Black); initPair(3,Curses::Yellow,Curses::Black); initPair(4,Curses::Blue,Curses::Black); initPair(5,Curses::Magenta,Curses::Black); initPair(6,Curses::Cyan,Curses::Black); initPair(7,Curses::White,Curses::Black); initPair(8,Curses::Black,Curses::Black); } try { keypad(stdscr,true); hideCursor(); } catch(CursesError) {} // mask failure on Windows } "End Curses This function ends Curses windowing mode, and should be called before the application exits. See the notes on Curses::endWin on effects on output after this function is called. startScreen" public Void endScreen() { try { showCursor(); } catch(CursesError) {} cbreakMode(false); echoMode(true); endWin(); } "Update the screen Update the screen, printing any changes since the last update." public Void updateScreen() { refresh(); } "Clear the screen Clear the screen completely." public Void clearScreen() { clear(); } "The screen row The screen column The text to add Add new text Add new text (in the default colour and weight) at the specified position. printAtColour" public Void printAt(Int x, Int y, String text) { move(y,x); addStr(text); } /*"The screen row The screen column The text to add The colour of the text (as a ColourName) The weight of the text Add new coloured text Add new text at the specified position, with the specified colour and weight. ColourName WeightName printAt" public Void printAtColour (Int x, Int y, String text, ColourName colour, WeightName weight) { if (!hasColours()) { printAt(x,y,text); } else { colournum = getColourNumber(colour); case weight of { Kayurses::Bold -> attrs = [Curses::Bold,ColourPair(colournum)]; |Kayurses::Inverse -> attrs = [Curses::Reverse,ColourPair(colournum)]; |Kayurses::InverseBold -> attrs = [Curses::Reverse,Curses::Bold,ColourPair(colournum)]; |Kayurses::Normal -> attrs = [ColourPair(colournum)]; } attributes(attrs,true); printAt(x,y,text); attributes(attrs,false); } } */ "The screen row The screen column The text to add The colour of the text (from functions such as Curses::Cyan The weight of the text Add new coloured text Add new text at the specified position, with the specified colour and weight. ColourName WeightName printAt" public Void printAtColour (Int x, Int y, String text, Int colour, WeightName weight) { if (!hasColours()) { printAt(x,y,text); } else { colournum = getColourNumber2(colour); case weight of { Heavy -> attrs = [Curses::Bold,ColourPair(colournum)]; |Inverse -> attrs = [Curses::Reverse,ColourPair(colournum)]; |HeavyInverse -> attrs = [Curses::Reverse,Curses::Bold,ColourPair(colournum)]; |Light -> attrs = [ColourPair(colournum)]; } attributes(attrs,true); printAt(x,y,text); attributes(attrs,false); } } "Hide the cursor Hide the cursor showCursor" public Void hideCursor() { setCursor(Invisible); } "Show the cursor Show the cursor hideCursor" public Void showCursor() { setCursor(NormalVisible); } "Read a character Read the next character of input waitChar" public Char readChar() { return Curses::getChar(); } "Wait for input Wait until input appears (and then discard that input) - useful for 'press any key' situations. readChar" public Void waitChar() { void(Curses::getChar()); } /*Int getColourNumber(ColourName colour) { c = case colour of { Kayurses::Red -> 1; | Kayurses::Green -> 2; | Kayurses::Yellow -> 3; | Kayurses::Blue -> 4; | Kayurses::Magenta -> 5; | Kayurses::Cyan -> 6; | Kayurses::White -> 7; | Kayurses::Black -> 8; }; return c; }*/ Int getColourNumber2(Int c) { if (c == Curses::Black()) { return 8; } if (c == Curses::White()) { return 7; } if (c == Curses::Cyan()) { return 6; } if (c == Curses::Magenta()) { return 5; } if (c == Curses::Blue()) { return 4; } if (c == Curses::Yellow()) { return 3; } if (c == Curses::Green()) { return 2; } if (c == Curses::Red()) { return 1; } return 7; } /* ColourName getNumberColour(Int colour) { [ColourName] cols = [Kayurses::Black,Kayurses::Red,Kayurses::Green,Kayurses::Yellow,Kayurses::Blue,Kayurses::Magenta,Kayurses::Cyan,Kayurses::White,Kayurses::Black]; return cols[colour]; }*/ kaya-0.4.4/contrib/Lfrand.k0000644000175100017510000001101111170340770013564 0ustar cimcim/** -*-C-*-ish Lagged Fibonacci Random Number Generator Copyright (C) 2005 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence version 2.1. */ "'Lagged Fibonacci' random number generator This module implements a 'Lagged Fibonacci' pseudo-random number generator. This type of RNG gives considerably better quality numbers than the standard Builtins::rand function, and so is suitable for use in simulations requiring a good degree of randomness (though not in cryptography). You should call lfSrand before using other functions from this module." module Lfrand; "Dice specification. rolls is the number of rolls, faces is the number of faces on each die, and modifier is then added to the sum of the dice rolls. In the standard dice notation, rollsdfaces+modified. lfDice" public data Dicespec(Int rolls, Int faces, Int modifier); "Negative value This value is thrown if a negative size is specified for the range in lfRand or lfIntRand" Exception ValueOutOfRange(); private data LfState(List nextpoint, List currentpoint, List lagpoint); globals { // should still seed it properly on use, but this at least stops // segfaults if you don't Lfrand::LfState lfstate = lfInit(0); } "The initial seed Seed the generator Seed the random number generator. You should usually only do this once at the start of your program. Depending on the unpredictability of random numbers needed, Time::now, Time::microtime, /dev/urandom and /dev/random may be appropriate sources for the seed value." public Void lfSrand(Int seed) { lfstate = lfInit(seed); } LfState lfInit(Int seed) { srand(seed); floop[0] = nil; for x in [1..54] { floop[x] = cons(newSeed(),floop[x-1]); } floop[1].tail = cons(newSeed(),floop[54]); // lfstate = LfState(floop[54],floop[53],floop[22]); return LfState(floop[1].tail,floop[1],floop[32]); } private Int newSeed() { return abs(rand())%(2**31-1); } private Int lfGetRand() { // remember to seed it before use. Int newx = (lfstate.currentpoint.head + lfstate.lagpoint.head) % (2**31-1); if (newx < 0) { newx += 2**31-1; } lfstate.nextpoint.head = newx; lfstate.lagpoint = lfstate.lagpoint.tail; lfstate.currentpoint = lfstate.currentpoint.tail; lfstate.nextpoint = lfstate.nextpoint.tail; return newx; } "The range to return over Return a random Float Returns a random Float in the range 0 <= x < randsize. lfIntRand lfRawRand" public Float lfRand(Float randsize) { if (randsize < 0) { throw(ValueOutOfRange); } newx = lfGetRand(); maxrand = 2**31-1; randval = Float(newx) * randsize / Float(maxrand); return randval; } "The range to return over Return a random Int Returns a random Int in the range 0 <= x < randsize. lfRand lfRawRand" public Int lfIntRand(Int randsize) { if (randsize <= 0) { throw(ValueOutOfRange); } newx = lfGetRand(); randval = newx % randsize; return randval; } "Return the next value Returns a random Int in the range 0 <= x < (2**31)-1. lfRand lfIntRand" public Int lfRawRand() { return lfGetRand(); } "The dice to simulate Simulate rolling dice Simulates rolling the specified dice and returns the sum of the rolls plus the modifier. Dicespec" public Int lfDice(Dicespec dicespec) { roll = dicespec.modifier; for (i=0;i 0) { roll += 1+lfIntRand(dicespec.faces); } } return roll; } kaya-0.4.4/contrib/Complex.k0000644000175100017510000001341311170340770013775 0ustar cimcim/** -*-C-*-ish Complex Number data type and functions Copyright (C) 2005 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence version 2.1. */ "Complex numbers This module contains functions for manipulating complex numbers." module Complex; import Maths; "A complex number A complex number, with real and imaginary components." public data Complex(Float real, Float imaginary); private data PolarCoordinate = mkPolarCoordinate(Float r, Float theta); "A complex number Convert a complex number to a string Return a string representation of a complex number (e.g. 2.2-1.3i Complex" public String string (Complex a) { if (a.imaginary<0.0) { rep = String(a.real) + " - " + String(-1.0*a.imaginary) + 'i'; } else { rep = String(a.real) + " + " + String(a.imaginary) + 'i'; } return rep; } "A complex number Magnitude of complex number Returns the magnitude of a complex number Complex argument" public Float magnitude (Complex a) { polar = ComplexToPolar(a); return polar.r; } "A complex number Argument of complex number Returns the argument of a complex number Complex argument" public Float argument(Complex a) { polar = ComplexToPolar(a); return polar.theta; } "A complex number A complex number Add complex numbers Returns a+b. Complex divide multiply power subtract" public Complex add(Complex a, Complex b) { return Complex(a.real+b.real,a.imaginary+b.imaginary); } "A complex number A complex number Subtract complex numbers Returns a-b. Complex add divide multiply power" public Complex subtract(Complex a, Complex b) { return Complex(a.real-b.real,a.imaginary-b.imaginary); } "A complex number A complex number Multiply complex numbers Returns a*b. Complex add divide power subtract" public Complex multiply(Complex a, Complex b) { polara = ComplexToPolar(a); polarb = ComplexToPolar(b); newr = polara.r * polarb.r; newt = polara.theta + polarb.theta; // conversion to Cartesian will bounds-fix theta newp = mkPolarCoordinate(newr,newt); return PolarToComplex(newp); } "A complex number A complex number Divide complex numbers Returns a/b. Complex add multiply power subtract" public Complex divide(Complex a, Complex b) { polara = ComplexToPolar(a); polarb = ComplexToPolar(b); newr = polara.r / polarb.r; newt = polara.theta - polarb.theta; // conversion to Cartesian will bounds-fix theta newp = mkPolarCoordinate(newr,newt); return PolarToComplex(newp); } "A complex number A complex number Powers of complex numbers Returns a**b. Note that for fractional powers, only one of the possible roots will be returned. Complex add divide multiply subtract" public Complex power(Complex a, Complex b) { // note, for fractional powers will only return one of the possible roots polara = ComplexToPolar(a); rpower = b.imaginary * polara.theta; newr = (pow(polara.r,b.real)) * exp(-rpower); newt = (polara.theta * b.real) + (b.imaginary * log(polara.r)); newp = mkPolarCoordinate(newr,newt); return PolarToComplex(newp); } private PolarCoordinate ComplexToPolar (Complex a) { r = ((a.real**2)+(a.imaginary**2))**0.5; theta = atan(a.imaginary/a.real); if (compare(a.real,0.0) <= 0) { if (compare(theta,0.0) > 0 && compare(a.real,0.0) != 0) { theta -= PI; } else if (compare(theta,0.0) < 0) { theta += PI; } } return mkPolarCoordinate(r,theta); } private Complex PolarToComplex(PolarCoordinate a) { real = a.r * cos(a.theta); imag = a.r * sin(a.theta); return Complex(real,imag); } kaya-0.4.4/contrib/GL.k0000644000175100017510000002446511170340767012707 0ustar cimcim/** -*-C-*-ish Kaya OpenGL bindings Copyright (C) 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ module GL; %include "glglue.h"; %include "GL/glut.h"; %imported "glglue"; %link "glut"; %link "GL"; %link "GLU"; import Binary; // For texture images. // GL constants public data MatrixMode = Projection | ModelView | Texture; public data ShadeModel = Flat | Smooth; public data Buffer = Color | Depth | Accum | Stencil; public data Primitive = Points | Lines | LineStrip | LineLoop | Triangles | TriangleStrip | TriangleFan | Quads | QuadStrip | Polygon; public data Feature = DepthTest | Blend | Fog | LineStipple | Lighting | Light(Int) | Normalize | ColorMaterial | PointSmooth | LineSmooth | CullFace | Texture1D | Texture2D | ScissorTest | AlphaTest | StencilTest | AutoNormal; public data ListMode = Compile | CompileAndExecute; public data LightParam = Ambient(Float,Float,Float,Float) | Diffuse(Float,Float,Float,Float) | Specular(Float,Float,Float,Float) | Position(Float,Float,Float,Float) | SpotDirection(Float,Float,Float) | SpotExponent(Float) | SpotCutoff(Float) | ConstantAttenuation(Float) | LinearAttenuation(Float) | QuadraticAttentuation(Float); public data Material = AmbientMat(Float,Float,Float,Float) | DiffuseMat(Float,Float,Float,Float) | AmbientAndDiffuseMat(Float,Float,Float,Float) | SpecularMat(Float,Float,Float,Float) | Shininess(Float) | Emission(Float,Float,Float,Float); public data MaterialMode = AmbientMode | DiffuseMode | AmbientAndDiffuseMode | SpecularMode | EmissionMode; public data Face = Front | Back | FrontAndBack; public data Color = Color3f(Float,Float,Float) | Color4f(Float,Float,Float,Float) | Color3i(Int,Int,Int) | Color4i(Int,Int,Int,Int); public data TextureFunc = Decal | Replace | Modulate | BlendTex; public data TextureTarget = TexNormal | TexProxy; public data TextureType = Tex1D | Tex2D; public data TextureFormat = Format(Int internal); public data TextureWrap = Clamp | Repeat; public data TextureFilter = Nearest | Linear | NearestMipmapNearest | NearestMipmapLinear | LinearMipmapNearest | LinearMipmapLinear; public data TextureParam = WrapS(TextureWrap) | WrapT(TextureWrap) | MagFilter(TextureFilter) | MinFilter(TextureFilter) | TextureBorderColor(Float, Float, Float, Float) | TexturePriority(Float); public data PixelFormat = RGBA | Red | Green | Blue | Alpha | Luminance | LuminanceAlpha | DepthComponent; public data Type = UnsignedByte | Byte | Bitmap | UnsignedShort | Short | UnsignedInt | IntType | FloatType; // Useful data structures public data Matrix = Matrixf([[Float]]) | Matrixi([[Int]]); public data Vector = Vecf(Float,Float,Float) | Veci(Int,Int,Int) | Vec2f(Float,Float) | Vec2i(Int,Int) | Vec4f(Float,Float,Float,Float) | Vec4i(Int,Int,Int,Int); public data Point = Pointf(Float, Float, Float) | Pointi(Int, Int, Int) | Point2f(Float, Float) | Point2i(Int, Int) | Point4f(Float, Float, Float, Float) | Point4i(Int, Int, Int, Int); //////////////////////////// foreign "glglue" { public Void loadIdentity() = glLoadIdentity; public Void frustum(Float left, Float right, Float bottom, Float top, Float near, Float far) = glFrustum; public Void ortho(Float left, Float right, Float bottom, Float top, Float near, Float far) = glOrtho; public Void ortho2D(Float left, Float right, Float bottom, Float top) = gluOrtho2D; public Void perspective(Float fovy, Float aspect, Float near, Float far) = gluPerspective; public Void viewport(Int x, Int y, Int width, Int height) = glViewport; public Void pushMatrix() = glPushMatrix; public Void popMatrix() = glPopMatrix; Int glGetMatrixMode(MatrixMode m) = glGetMatrixMode; Void glMatrixMode(Int m) = glMatrixMode; public Void clearColor(Float r, Float g, Float b, Float a) = glClearColor; public Void clearDepth(Float v) = glClearDepth; public Void flush() = glFlush; public Void finish() = glFinish; Void glColor3f(Float r, Float g, Float b) = glColor3f; Void glColor4f(Float r, Float g, Float b , Float a) = glColor4f; Void glColor3i(Int r, Int g, Int b) = glColor3i; Void glColor4i(Int r, Int g, Int b, Int a) = glColor4i; Void glVertex2f(Float x, Float y) = glVertex2d; Void glVertex2i(Int x, Int y) = glVertex2i; Void glVertex3f(Float x, Float y, Float z) = glVertex3d; Void glVertex3i(Int x, Int y, Int z) = glVertex3i; Void glVertex4f(Float x, Float y, Float z, Float w) = glVertex4d; Void glVertex4i(Int x, Int y, Int z, Int w) = glVertex4i; Void glNormal3f(Float x, Float y, Float z) = glNormal3d; Void glNormal3i(Int x, Int y, Int z) = glNormal3i; Void glTexCoord2f(Float x, Float y) = glTexCoord2d; Void glTexCoord2i(Int x, Int y) = glTexCoord2i; Void glTexCoord3f(Float x, Float y, Float z) = glTexCoord3d; Void glTexCoord3i(Int x, Int y, Int z) = glTexCoord3i; public Void translate(Float x, Float y, Float z = 0.0) = glTranslated; public Void rotate(Float angle, Float x, Float y, Float z = 0.0) = glRotated; public Void scale(Float x, Float y, Float z = 1.0) = glScaled; public Void lookAt(Float eyex, Float eyey, Float eyez, Float centrex, Float centrey, Float centrez, Float upx, Float upy, Float upz) = gluLookAt; Void glClear(Int x) = glClear; Int maskBuffers([Buffer] bs) = maskBuffers; Void glBegin(Int m) = glBegin; public Void end() = glEnd; Int glGetPrimitive(Primitive p) = glGetPrimitive; Int glGetFeature(Feature f) = glGetFeature; Void glEnable(Int f) = glEnable; Void glDisable(Int f) = glDisable; Bool glIsEnabled(Int f) = doGLIsEnabled; // Bool getglBool(Int x) = getglBool; Void glNewList(Int l, Int m) = glNewList; public Int genLists(Int num) = glGenLists; public Void endList() = glEndList; Int glGetListMode(ListMode l) = glGetListMode; public Void callList(Int l) = glCallList; Void glShadeModel(Int i) = glShadeModel; Int glGetShadeModel(ShadeModel m) = glGetShadeModel; Void doglLight(Int f, LightParam p) = doglLight; Void doglMaterial(Int f, Material p) = doglMaterial; Int glGetFace(Face f) = glGetFace; Int glGetMaterialMode(MaterialMode m) = glGetMaterialMode; Int glGetTexFunc(TextureFunc f) = glGetTexFunc; Int glGetPixelFormat(PixelFormat f) = glGetPixelFormat; Int glGetType(Type f) = glGetType; Int glGetTexTarget(TextureTarget f, Int dim) = glGetTexTarget; Int glGetTexType(TextureType f) = glGetTexType; Int glGetTexWrap(TextureWrap f) = glGetTexWrap; Void glTexMode(Int f) = glTexMode; Void glTexImage2D(Int t, Int level, Int internalFormat, Int width, Int height, Int border, Int format, Int ty, Ptr pixels) = glTexImage2D; Int gluBuild2DMipmaps(Int t, Int components, Int width, Int height, Int format, Int ty, Ptr pixels) = gluBuild2DMipmaps; Void glBindTexture(Int t, Int name) = glBindTexture; Void doglTexParam(Int f, TextureParam p) = doglTexParam; Int doGenTexture() = doGenTexture; Void doDeleteTexture(Int t) = doDeleteTexture; Bool docheckError(Ptr vm, a err) = checkError; } Exception GLUerror(Int code); Exception GLerror(String msg); ////////////////////////////// public Void matrixMode(MatrixMode m) { glMatrixMode(glGetMatrixMode(m)); } public Void color(Color col) { case col of { Color3f(r,g,b) -> glColor3f(r,g,b); | Color4f(r,g,b,a) -> glColor4f(r,g,b,a); | Color3i(ri,gi,bi) -> glColor3i(ri,gi,bi); | Color4i(ri,gi,bi,ai) -> glColor4i(ri,gi,bi,ai); } } public Void clear([Buffer] bs) { glClear(maskBuffers(bs)); } public Void begin(Primitive p) { glBegin(glGetPrimitive(p)); } public Void vertex(Point p) { case p of { Point2f(xf,yf) -> glVertex2f(xf,yf); | Point2i(xi,yi) -> glVertex2i(xi,yi); | Pointf(xf,yf,zf) -> glVertex3f(xf,yf,zf); | Pointi(xi,yi,zi) -> glVertex3i(xi,yi,zi); | Point4f(xf,yf,zf,wf) -> glVertex4f(xf,yf,zf,wf); | Point4i(xi,yi,zi,wi) -> glVertex4i(xi,yi,zi,wi); } } public Void normal(Vector p) { case p of { Vecf(xf,yf,zf) -> glNormal3f(xf,yf,zf); | Veci(xi,yi,zi) -> glNormal3i(xi,yi,zi); } } public Void texCoord(Point p) { case p of { Point2f(xf,yf) -> glTexCoord2f(xf,yf); | Point2i(xi,yi) -> glTexCoord2i(xi,yi); | Pointf(xf,yf,zf) -> glTexCoord3f(xf,yf,zf); | Pointi(xi,yi,zi) -> glTexCoord3i(xi,yi,zi); } } public Void enable(Feature f) { glEnable(glGetFeature(f)); } public Void disable(Feature f) { glDisable(glGetFeature(f)); } public Bool isEnabled(Feature f) = glIsEnabled(glGetFeature(f)); public Void newList(Int l, ListMode m) { glNewList(l,glGetListMode(m)); } public Void shadeModel(ShadeModel m) { glShadeModel(glGetShadeModel(m)); } public Void light(Int light, LightParam p) { f = glGetFeature(Light(light)); doglLight(f,p); } public Void material(Face face, Material mat) { doglMaterial(glGetFace(face),mat); } public Void texMode(TextureFunc f) { glTexMode(glGetTexFunc(f)); } public Void texImage2D(TextureTarget t, Int level, TextureFormat tf, Int width, Int height, Int border, PixelFormat pf, Type pt, Binary pixels) { glTexImage2D(glGetTexTarget(t,2), level, tf.internal, width, height, border, glGetPixelFormat(pf), glGetType(pt), blockData(pixels)); } public Void build2DMipmaps(TextureTarget t, Int components, Int width, Int height, PixelFormat pf, Type pt, Binary pixels) { ret = gluBuild2DMipmaps(glGetTexTarget(t,2), components, width,height, glGetPixelFormat(pf), glGetType(pt), blockData(pixels)); if (ret!=0) { throw(GLUerror(ret)); } } public Void texParameter(TextureType t, TextureParam p) { doglTexParam(glGetTexType(t),p); } public Int genTexture() { return doGenTexture(); } public Void bindTexture(TextureType tt, Int texid) { glBindTexture(glGetTexType(tt), texid); } public Void deleteTexture(Int texid) { doDeleteTexture(texid); } public Void checkError() { err = ""; if (docheckError(getVM, err)==false) { throw(GLerror(err)); } } kaya-0.4.4/contrib/DiskCache.k0000644000175100017510000001013011170340770014175 0ustar cimcim/* Disk-caching functions Copyright (C) 2005 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence version 2.1. */ "Caching of temporary data to disk This module contains function to temporarily store data on disk. Data stored in this way is recoverable using these functions only by the executable that stored it (though it is not encrypted and so is trivially readable)." module DiskCache; import System; import IO; import Regex; /* This module will store a data item to disk, or alternatively // retrieve it. Because of the way marshal works, this is only // suitable where the stored data is to be reloaded by the same // executable on the same platform. */ "The Directory is unsafe This Exception is thrown if the directory for object retrieval is considered unsafe." Exception UnsafeDirectory(); "The object is unsafe This Exception is thrown if the object to be retrieved is considered unsafe." Exception UnsafeObject(); private Void makeCacheDir(String dirname) { if (!fileExists(dirname)) { mkdir(dirname,Permissions([ReadP,WriteP,ExecuteP],[],[],false,false,false)); // make save dir if it doesn't exist at current umask } // this will throw an exception if the directory doesn't exist. if (!quickMatch("/$",dirname)) { dirname = dirname + "/"; // ensure a trailing slash } } // this makes sure that user cache directories are in a sensible place private Void verifySafe (String dirname, Bool allowsubdirs=false) { if (quickMatch("\\.\\.",dirname)) { throw(UnsafeDirectory); } if (!allowsubdirs && quickMatch("/",dirname)) { throw(UnsafeObject); } } "The name of the cache directory. On Unix-based systems, .appname is traditional. Get a cache directory Returns a sub-directory of the user's home directory suitable for passing to the Cache functions." public String userCacheDir(String specific) { home = getEnv("HOME"); if (home == "") { home = "."; } return home + "/" + specific + "/"; } private Void verifyCache(String cachedir, String cacheid) { verifySafe(cacheid,false); verifySafe(cachedir,true); makeCacheDir(cachedir); } "The variable to store. The directory to store to The name of the stored object An optional function to help ensure that the cache data is correct when reloaded. Stores a cacheable variable to disk Stores a cacheable variable to disk" public Void toCache(a state, String cachedir, String cacheid, Int(String) verifier=strHash) { verifyCache(cachedir,cacheid); cachedata = marshal(state,verifier(cacheid)); writeFile(cachedir+cacheid,cachedata); } "The directory to store to The name of the stored object An optional function to help ensure that the cache data is correct when reloaded. This must be the same function used to store the object. Returns a cacheable variable from disk Returns a cacheable variable from disk, or nothing if the variable does not exist." public Maybe
    fromCache(String cachedir, String cacheid, Int(String) verifier=strHash) { verifyCache(cachedir,cacheid); if (!fileExists(cachedir+cacheid)) { return nothing(); } else { cachedata = readFile(cachedir+cacheid); state = unmarshal(cachedata,verifier(cacheid)); return just(state); } } "The cache directory The object name Deletes a cached variable if it exists Deletes the cached variable." public Void delCache(String cachedir, String cacheid) { verifyCache(cachedir,cacheid); if (fileExists(cachedir+cacheid)) { unlink(cachedir+cacheid); } } kaya-0.4.4/contrib/Glut.k0000644000175100017510000000634011170340767013310 0ustar cimcim/** -*-C-*-ish Kaya GLUT bindings Copyright (C) 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ module Glut; %include "glutglue.h"; %include "GL/glut.h"; %imported "glutglue"; %link "glut"; %link "GL"; %link "GLU"; public data Mode = RGB | RGBA | INDEX | SINGLE | DOUBLE | ACCUM | ALPHA | DEPTH | STENCIL | MULTISAMPLE | STEREO | LUMINANCE; public data Button = Left | Middle | Right; public data ButtonState = Up | Down; foreign "glutglue" { Void glutInitWindowPosition(Int x, Int y) = glutInitWindowPosition; Void glutInitWindowSize(Int width, Int height) = glutInitWindowSize; public Void initMode([Mode] modes) = doGlutInit; public Void createWindow(String title) = do_glutCreateWindow; Void glutIgnoreKeyRepeat(Int ig) = glutIgnoreKeyRepeat; public Void mainLoop() = glutMainLoop; public Void postRedisplay() = glutPostRedisplay; public Void swapBuffers() = glutSwapBuffers; public Void setColor(Int index, Float r, Float g, Float b) = glutSetColor; public Void fullScreen() = glutFullScreen; // Callbacks public Void display(Void(a) callback, a dat) = display_cb; public Void reshape(Void(Int,Int,a) callback, a dat) = reshape_cb; public Void idle(Void(a) callback, a dat) = idle_cb; public Void keyboard(Void(Char,Int,Int,a) callback, a dat) = key_cb; public Void keyboardUp(Void(Char,Int,Int,a) callback, a dat) = keyup_cb; public Void special(Void(Int,Int,Int,a) callback, a dat) = special_cb; public Void specialUp(Void(Int,Int,Int,a) callback, a dat) = specialup_cb; public Void mouse(Void(Button,ButtonState,Int,Int,a) callback, a dat) = mouse_cb; public Void motion(Void(Int,Int,a) callback, a dat) = motion_cb; public Void visibility(Void(Bool,a) callback, a dat) = visibility_cb; // Predefined objects public Void wireSphere(Float radius, Int slices, Int stacks) = glutWireSphere; public Void solidSphere(Float radius, Int slices, Int stacks) = glutSolidSphere; public Void wireCube(Float size) = glutWireCube; public Void SolidCube(Float size) = glutSolidCube; public Void wireTorus(Float innerRadius, Float outerRadius, Int sides, Int rings) = glutWireTorus; public Void solidTorus(Float innerRadius, Float outerRadius, Int sides, Int rings) = glutSolidTorus; public Void wireIcosahedron() = glutWireIcosahedron; public Void solidIcosahedron() = glutSolidIcosahedron; public Void wireOctahedron() = glutWireOctahedron; public Void solidOctahedron() = glutSolidOctahedron; public Void wireTetrahedron() = glutWireTetrahedron; public Void solidTetrahedron() = glutSolidTetrahedron; public Void wireDodecahedron() = glutWireDodecahedron; public Void solidDodecahedron() = glutSolidDodecahedron; public Void wireTeapot(Float size) = glutWireTeapot; public Void solidTeapot(Float size) = glutSolidTeapot; } public Void initWindow(Int x, Int y, Int width, Int height) { glutInitWindowPosition(x,y); glutInitWindowSize(width,height); } public Void ignoreKeyRepeat(Bool ignore = true) { if (ignore) glutIgnoreKeyRepeat(1); else glutIgnoreKeyRepeat(0); } kaya-0.4.4/contrib/glutglue.h0000644000175100017510000000204411170340767014217 0ustar cimcim#ifndef _GLUTGLUE_H // -*-C++-*- #define _GLUTGLUE_H #include extern "C" { void do_glutCreateWindow(KString title); void display_cb(KayaValue fn, KayaValue data); void reshape_cb(KayaValue fn, KayaValue data); void idle_cb(KayaValue fn, KayaValue data); void key_cb(KayaValue fn, KayaValue data); void keyup_cb(KayaValue fn, KayaValue data); void special_cb(KayaValue fn, KayaValue data); void specialup_cb(KayaValue fn, KayaValue data); void mouse_cb(KayaValue fn, KayaValue data); void motion_cb(KayaValue fn, KayaValue data); void visibility_cb(KayaValue fn, KayaValue data); void display(); void reshape(int x, int y); void idle(); void keyboard(unsigned char c, int x, int y); void keyboardup(unsigned char c, int x, int y); void special(int key, int x, int y); void specialup(int key, int x, int y); void mouse(int button, int state, int x, int y); void motion(int x, int y); void visibility(int state); void doGlutInit(KayaArray mode); } #endif kaya-0.4.4/contrib/Makefile.in0000644000175100017510000000267111170340770014263 0ustar cimcimRVPATH=@srcdir@ VPATH=${RVPATH} LANGNAME = @LANGNAME@ KAYAC = ../compiler/@TARGET@ prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@/${LANGNAME} IMPORTDIR = ${libdir}/imports CXXFLAGS = @FPIC@ @EXTRAGCCOPTS@ -I../rts -O2 -I${VPATH}/../rts -I${VPATH}/../libs -I${VPATH}/../stdlib KAYAINC = @KAYAPROF@ -noenvlibs -I../rts -I../@platform@ -I../libs -L ${VPATH}/../rts -L ${VPATH} INSTALLFLAGS = -m 644 SRCS = Lfrand.@EXT@ Complex.@EXT@ Kayurses.@EXT@ DiskCache.@EXT@ \ GL.@EXT@ Glut.@EXT@ IFACE = Lfrand.ki Complex.ki @KAYIFACE@ DiskCache.ki @GLIFACE@ OBJS = Lfrand.o Complex.o @KAYOBJ@ DiskCache.o @GLOBJS@ all: ${OBJS} install: mkdir -p ${DESTDIR}${libdir} mkdir -p ${DESTDIR}${IMPORTDIR} # install ${TARGET} ${LIBDIR} # install ${LIBTARGET} ${LIBDIR} install ${INSTALLFLAGS} ${IFACE} ${DESTDIR}${IMPORTDIR} install ${INSTALLFLAGS} ${OBJS} ${DESTDIR}${IMPORTDIR} clean: rm -f ${OBJS} ${IFACE} ${LIBTARGET} ${TARGET} rm -f *.html *.xml rm -rf docs distclean: clean rm -f *~ Makefile rm -rf autom4te.cache DiskCache.o: ../stdlib/Regex.ki ../stdlib/System.ki glutglue.o: glutglue.h glglue.o: glglue.h # temporarily while function migrated to private Kayurses.o : Kayurses.@EXT@ ${KAYAC} $< -nochase -nortchecks ${KAYAINC} -L ../rts -L ../stdlib -L ../@platform@ -L ../libs -xmldocs %.o : %.@EXT@ ${KAYAC} $< -nochase -nortchecks ${KAYAINC} -L ../rts -L ../stdlib -L ../@platform@ -L ../libs -xmldocs -deprfail %.ki : %.o @: kaya-0.4.4/posix/0000755000175100017510000000000011170340770011712 5ustar cimcimkaya-0.4.4/posix/signal_glue.h0000644000175100017510000000041611170340766014362 0ustar cimcim#ifndef _SIGNALD_H // -*-C++-*- #define _SIGNALD_H class Value; class VMState; // List of handlers, initially all undefined. extern Value** hlist; extern VMState* ourvm; extern "C" { void setHandler(void* vm, int signo, Value* handlerfn); } #endif // Whole file kaya-0.4.4/posix/sockets_glue.cc0000644000175100017510000000574011170340770014716 0ustar cimcim#include #include "sockets_glue.h" #include "Heap.h" #include "VM.h" #include "stdfuns.h" #include "KayaAPI.h" #include KArray do_socketpair() { int sv[2]; socketpair(PF_UNIX,SOCK_STREAM,0,&sv[0]); KArray arr = newKayaArray(2); KayaArrayPush(arr,KayaPtr((void*)sv[0])); KayaArrayPush(arr,KayaPtr((void*)sv[1])); return arr; } void do_closesocket(void* sptr) { close((kint)sptr); } void do_socketsend(void* vmptr, void* sptr, wchar_t* msg) { char* data = CSTRING(msg); VMState* vm = (VMState*)vmptr; int rlen; do { rlen = send((kint)sptr, data,strlen(data),0); } while (errno == EINTR); if (rlen<0) { vm->kaya_internalError(0); } } void do_socketsendchars(void* vmptr, void* sptr, void* data, int len) { VMState* vm = (VMState*)vmptr; int rlen; do { rlen = send((kint)sptr, (char*)data,len,0); } while (errno == EINTR); if (rlen<0) { vm->kaya_internalError(0); } } void do_socketsendbyte(void* vmptr, void* sptr, kint byte) { char data[2]; data[0] = (char)byte; VMState* vm = (VMState*)vmptr; int rlen; do { rlen = send((kint)sptr, &data[0],1,0); } while (errno == EINTR); if (rlen<0) { vm->kaya_internalError(0); } } wchar_t* do_socketrecv(void* vmptr, void* sptr, KayaValue len) { VMState* vm = (VMState*)vmptr; int lenval = KayaGetInt(len); char* buf = (char*)GC_MALLOC_ATOMIC((lenval+1)*sizeof(char)); int rlen; do { rlen = recv((kint)sptr, buf,lenval,0); } while (errno == EINTR); KayaSetInt(len,rlen); if (rlen<0) { // cout << rlen << endl; // buf[0]='\0'; vm->kaya_internalError(1); } return KSTRING(buf); } void* do_socketrecvchars(void* vmptr, void* sptr, KayaValue len) { VMState* vm = (VMState*)vmptr; int lenval = KayaGetInt(len); char* buf = (char*)GC_MALLOC_ATOMIC((lenval+1)*sizeof(char)); memset((void*)buf,0,(lenval+1)*sizeof(char)); int rlen; do { rlen = recv((kint)sptr, buf,lenval,0); } while (errno == EINTR); KayaSetInt(len,rlen); if (rlen<0) { // cout << rlen << endl; // buf[0]='\0'; vm->kaya_internalError(1); } return (void*)buf; } kint do_socketrecvbyte(void* vmptr, void* sptr) { VMState* vm = (VMState*)vmptr; char* buf = (char*)GC_MALLOC_ATOMIC(2*sizeof(char)); int rlen; do { rlen = recv((kint)sptr, buf,1,0); } while (errno == EINTR); if (rlen<0) { // cout << rlen << endl; // buf[0]='\0'; vm->kaya_internalError(1); } return (kint)buf[0]; } bool do_socketpending(void* vmptr,void* conn, int timeout) { VMState* vm = (VMState*)vmptr; kint connid = (kint)conn; fd_set rfds; struct timeval tv; FD_ZERO(&rfds); FD_SET(connid,&rfds); tv.tv_sec = timeout/1000000; tv.tv_usec = timeout%1000000; int rv; do { rv = select(connid+1,&rfds,NULL,NULL,&tv); } while (errno == EINTR); if (rv==-1) { vm->kaya_internalError(6); } else { return rv; } } kaya-0.4.4/posix/signal_glue.cc0000644000175100017510000000265311170340770014520 0ustar cimcim#include #include #include "signal_glue.h" #include #include Value** hlist = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*63); VMState* ourvm; void callHandler(int signo) { signal(signo,callHandler); // Block all other signals while we're working. sigset_t blk; sigset_t sigsv; sigfillset(&blk); sigdelset(&blk,signo); sigprocmask(SIG_BLOCK,&blk,&sigsv); /* Block sigs */ VMState* vm = ourvm; Value* h = hlist[signo]; /* cout << "Calling handler for signal " << signo << endl; cout << "Got handler " << h << endl; cout << "Got handler " << h->getRaw() << endl;*/ PUSH(MKINT(0)); /* this temp value is for the return value (which of course gets DISCARDed) */ PUSH(MKINT(signo)); CALLFUN(h); sigprocmask(SIG_SETMASK,&sigsv,0); } void setHandler(void *vm, int signo, Value* handlerfn) { struct sigaction sa_old; struct sigaction sa_new; sa_new.sa_handler = callHandler; // Point to our function hlist[signo] = handlerfn; // Set it in our lookup table ourvm = (VMState*)vm; // cout << "Set handler to " << handlerfn << endl; // cout << "Set handler value to " << handlerfn->getRaw() << endl; sigemptyset(&sa_new.sa_mask); // Clear mask sa_new.sa_flags = 0; // No special flags sigaction(signo,&sa_new,&sa_old); // Set handler } kaya-0.4.4/posix/syslog_glue.cc0000644000175100017510000000341311170340766014563 0ustar cimcim#include #include "syslog_glue.h" #include #include #include void do_openlog(wchar_t* rawident, int opt, int fac) { char* ident = CSTRING(rawident); int option = 0; if (opt & 1) { option = option | LOG_PID; } if (opt & 2) { option = option | LOG_CONS; } if (opt & 4) { option = option | LOG_PERROR; } int facility = 0; if (fac == 1) { facility = LOG_AUTHPRIV; } else if (fac == 2) { facility = LOG_CRON; } else if (fac == 3) { facility = LOG_DAEMON; } else if (fac == 4) { facility = LOG_FTP; } else if (fac == 5) { facility = LOG_KERN; } else if (fac == 6) { facility = LOG_LPR; } else if (fac == 7) { facility = LOG_MAIL; } else if (fac == 8) { facility = LOG_NEWS; } else if (fac == 9) { facility = LOG_SYSLOG; } else if (fac == 10) { facility = LOG_USER; } else if (fac == 11) { facility = LOG_UUCP; } else if (fac == 12) { facility = LOG_LOCAL0; } else if (fac == 13) { facility = LOG_LOCAL1; } else if (fac == 14) { facility = LOG_LOCAL2; } else if (fac == 15) { facility = LOG_LOCAL3; } else if (fac == 16) { facility = LOG_LOCAL4; } else if (fac == 17) { facility = LOG_LOCAL5; } else if (fac == 18) { facility = LOG_LOCAL6; } else if (fac == 19) { facility = LOG_LOCAL7; } openlog(ident,option,facility); } void do_syslog(int pri, wchar_t* rawmsg) { char* msg = CSTRING(rawmsg); int priority = 0; if (pri == 0) { priority = LOG_EMERG; } else if (pri == 1) { priority = LOG_ALERT; } else if (pri == 2) { priority = LOG_CRIT; } else if (pri == 3) { priority = LOG_ERR; } else if (pri == 4) { priority = LOG_WARNING; } else if (pri == 5) { priority = LOG_NOTICE; } else if (pri == 6) { priority = LOG_INFO; } else if (pri == 7) { priority = LOG_DEBUG; } syslog(priority,msg); } kaya-0.4.4/posix/Sockets.k0000644000175100017510000002314411170340770013505 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2007 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Unix Sockets This module implements interprocess communication using sockets. This is useful for communicating between two processes started with Posix::fork using the socketPair function to create the sockets. Sockets are represented by the Socket data type, and are generally similar to the Net::NetHandle type in the Net module." module Sockets; import Posix; import Binary; import Net; import Prelude; "A socket This data type represents a local socket close socketPair" abstract data Socket(Ptr socket); "Timeout while waiting for data This exception is thrown if the timeout is reached while waiting for data on a socket. recv recvByte recvBytes" Exception SocketTimeout; %include "sockets_glue.h"; %imported "sockets_glue"; foreign "sockets_glue.o" { // socketpair [Ptr] do_socketpair() = do_socketpair; Void do_closesocket(Ptr sptr) = do_closesocket; String do_socketrecv(Ptr vm, Ptr handle, a len) = do_socketrecv; Ptr do_socketrecvchars(Ptr vm, Ptr handle, a len) = do_socketrecvchars; Int do_socketrecvbyte(Ptr vm, Ptr handle) = do_socketrecvbyte; Void do_socketsend(Ptr vm, Ptr h, String d) = do_socketsend; Void do_socketsendchars(Ptr vm, Ptr handle, Ptr sdata, Int len) = do_socketsendchars; Void do_socketsendbyte(Ptr vm, Ptr handle, Int byte) = do_socketsendbyte; Bool do_socketpending(Ptr vm, Ptr h, Int timeout) = do_socketpending; } "Create a joined pair of sockets This function creates a pair of sockets that can be used for bi-directional communication. The most common use of this is for setting up communications between a process and its Posix::fork()ed child - each process closes one of the sockets after the fork. sockets = socketPair(); pid = fork(); if (pid == 0) { // child process close(sockets.fst); // do something } else { close(sockets.snd); // do something else } Socket close Posix::fork" public (Socket,Socket) socketPair() { sockets = do_socketpair(); s1 = Socket(sockets[0]); s2 = Socket(sockets[1]); return (subvert(s1),subvert(s2)); } "The socket Close a socket Close a socket Socket" public Void close(Socket s) { do_closesocket(s.socket); } "The socket Text data to send Send data to a socket Send text data to a socket. Socket sendByte sendBytes recv" public Void send(Socket s, String msg) { do_socketsend(getVM,s.socket,msg); } "The socket The byte to send (must be between 0 and 255) Send a single byte to a socket Send a single byte to a socket. Socket send sendBytes recvByte" public Void sendByte(Socket s, Int byte) { do_socketsendbyte(getVM,s.socket,byte); } "The socket The data to send Send binary data to a socket Send binary data to a socket. Binary::Binary Socket send sendBytes recvByte" public Void sendBytes(Socket s, Binary bindata) { do_socketsendchars(getVM,s.socket,blockData(bindata),blockSize(bindata)); } "The socket The time to wait for data in microseconds before giving up (the default is 1000000, or 1 second) Receive a single byte from a socket Receive a single byte from a socket. Socket pending sendByte recv recvBytes" public Int recvByte(Socket s, Int timeout=1000000) { if (timeout == -1 || pending(s,timeout)) { return do_socketrecvbyte(getVM,s.socket); } else { throw(SocketTimeout); } } "The socket The maximum number of bytes to receive. This must be a positive integer (the default is 1024) The time to wait for data in microseconds before giving up (the default is 1000000, or 1 second) Receive binary data from a socket Receive binary data from a socket. Binary::Binary Socket pending sendBytes recv recvByte" public Binary recvBytes(Socket s, Int maxlen=1024, Int timeout=1000000) { if (maxlen < 1) { throw(NegativeLength); } if (timeout == -1 || pending(s,timeout)) { ptr = do_socketrecvchars(getVM,s.socket,maxlen); return createInitialisedBlock(ptr,maxlen); } else { throw(SocketTimeout); } } "The socket The maximum number of bytes to receive. This must be a positive integer (the default is 1024), or -1 for no limit. Note that if the data to be received contains multi-byte characters, care must be taken to avoid ending receiving part-way through a multi-byte character. The time to wait for data in microseconds before giving up (the default is 1000000, or 1 second). -1 can be used to wait until data arrives. Receive text data from a socket Receive text data from a socket. Socket pending send recvByte recvBytes" public String recv(Socket s, Int maxlen=-1, Int timeout=1000000) { if (maxlen > 0) { if (timeout == -1 || pending(s,timeout)) { return do_socketrecv(getVM,s.socket,maxlen); } else { throw(SocketTimeout); } } else { str = ""; do { len = 65536; if (timeout == -1 || pending(s,timeout)) { str += do_socketrecv(getVM,s.socket,len); } else { len = 0; } } while (len != 0 || (timeout <= 0 && len != 65536)); return str; } } "The socket The time to wait (in microseconds) before returning false. This argument may be omitted for a default of 1000000 (1 second) Check for pending data on a socket Returns whether data is pending on a socket Socket recv recvByte recvBytes" public Bool pending(Socket s, Int timeout=1000000) { return do_socketpending(getVM,s.socket,timeout); } // binary-safe "A network connection A socket Transfer data from network to socket Transfer any currently pending data from the network connection to the socket. The data is transferred as binary data, so null bytes, and multi-byte characters are handled safely. Net::NetHandle Socket socketToNet" public Void netToSocket(NetHandle net, Socket s) { do { b = recvBytes(net,1024,10); len = blockSize(b); if (len > 0) { sendBytes(s,b); } } while (len == 1024); } "A socket A network connection Transfer data from socket to network Transfer any currently pending data from the socket to the network connection. The data is transferred as binary data, so null bytes, and multi-byte characters are handled safely. Net::NetHandle Socket netToSocket" public Void socketToNet(Socket s, NetHandle net) { do { b = recvBytes(s,1024,10); len = blockSize(b); if (len > 0) { sendBytes(net,b); } } while (len == 1024); } kaya-0.4.4/posix/ServerLoop.k0000644000175100017510000000403711170340770014172 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Forking server loop implementation This module provides a basic implementation of a server loop." module ServerLoop; import Builtins; import System; import Posix; import Net; import Prelude; "The protocol (Net::Protocol) to listen on The port to listen on The maximum number of simultaneous connections to accept. The function that processes each new connection. The connection will be closed automatically when this function exits, so it need not. This function is run by the old process after the new process is forked, and is given the process ID of the new process. This argument may be omitted, in which case a default function that does nothing will be used. A basic implementation of a server loop. This function provides a basic implementation of a forking server loop, similar in architecture to sshd." public Void serverLoop(Protocol proto, Int port, Int maxcon, Void(NetHandle) commfun, Void(NetHandle,Int) forkfun = forkfunDefault) { x = listen(proto,port,maxcon); while(true) { while (!connWaiting (x, 5)) { reap(); } c = accept(x); pid = fork(); if (pid==0) { closeSocket(x); commfun(c); closeConnection(c); break; } else { closeConnection(c); forkfun(c,pid); } } } "The (closed) network connection handle The process ID of the forked process handling the connection. Default function to run on forking. A default function to run on forking, which does nothing." public Void forkfunDefault(NetHandle h, Int pid) { // Do nothing } kaya-0.4.4/posix/Signal.k0000644000175100017510000000463011170340770013306 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Signal handling This module allows signal handlers to be set up. It is currently experimental and under-tested." module Signal; /* I am not at all convinced this works! It seems to sometimes, but my understanding of signal handling is not good enough to work out what the problems are. Please have a go at fixing it if you want -- ECB, 24/11/04 */ import Builtins; %include "signal_glue.h"; %imported "signal_glue"; "Signal types Signal types. For completeness, signals such as SIGKILL are listed even though they cannot be caught." public data Signal = SIGHUP | SIGINT | SIGQUIT | SIGILL | SIGTRAP | SIGABRT | SIGBUS | SIGFPE | SIGKILL | SIGUSR1 | SIGSEGV | SIGUSR2 | SIGPIPE | SIGALRM | SIGTERM | SIGCHLD | SIGCONT | SIGSTOP | SIGXCPU; Int sigToInt(Signal s) = case s of { SIGHUP -> 1; | SIGINT -> 2; | SIGQUIT -> 3; | SIGILL -> 4; | SIGTRAP -> 5; | SIGABRT -> 6; | SIGBUS -> 7; | SIGFPE -> 8; | SIGKILL -> 9; | SIGUSR1 -> 10; | SIGSEGV -> 11; | SIGUSR2 -> 12; | SIGPIPE -> 13; | SIGALRM -> 14; | SIGTERM -> 15; | SIGCHLD -> 17; | SIGCONT -> 18; | SIGSTOP -> 19; | SIGXCPU -> 24; }; foreign "signald.o" { Void setHandler(Ptr vm, Int sig,Void(Int) handler) = setHandler; } foreign "stdfuns.o" { "The number of seconds to wait before sending the alarm. Set an alarm. Set an alarm - sends the current process a SIGALRM after secs seconds." public Void alarm(Int secs) = alarm; } "The Signal to handle The function to call when the signal appears. It takes one parameter - an integer giving the numeric value of the signal, to allow a single function to be used for multiple signals. Set a signal handler. Set a signal handler. The function specified will then be called whenever the signal is received." public Void signal(Signal sig, Void(Int) handler) { setHandler(getVM, sigToInt(sig),handler); } kaya-0.4.4/posix/scgi.ks0000644000175100017510000001222711170340770013202 0ustar cimcim// -*-C-*-ish import Net; import Posix; import Sockets; import Webapp; import WebCommon; import Crypto; import HTMLDocument; import SCGI; import IO; default Void webconfig() {} default SCGI scgiconfig() = SCGI(7597,2,2,4,10,100,10); Void __panic(String err, Int code) { /* putStrLn("Status: 500 Internal Server Error"); putStrLn("Content-type: text/plain; charset=UTF-8"); putStrLn("Cache-control: no-cache,private"); putStrLn("");*/ put(stderr,"Kaya panic: "+err+" ("+code+")"); } Void __start() { Prelude::gcIncremental(); try { sconf = module::scgiconfig(); __loop(sconf); } catch(err) { put(stderr,exceptionMessage(err)); } } Void __loop(SCGI config) { lsock = listen(TCP,config.port,config.maxbacklog); children = createArray(config.maxservers); for x in [0..config.maxservers-1] { children[x] = nothing; } do { try { // check if there are enough spare servers up to the limit if (numSpareServers(children) < config.minspareservers) { // // start some more case firstEmptySlot(children) of { nothing -> ; // can't start anything | just(slot) -> ; // can start something comm = socketPair; oob = socketPair; pid = fork(); if (pid == 0) { // child process closeSocket(lsock); close(comm.snd); close(oob.snd); for child in children { case child of { nothing -> ; |just(cproc) -> case cproc.client of { nothing -> ; // forked one mustn't hang on to these! |just(client) -> closeConnection(client); } } } __forked(config,comm.fst,oob.fst); close(oob.fst); close(comm.fst); return; } else { close(comm.fst); close(oob.fst); children[slot] = just(ChildProcess(comm.snd,oob.snd,nothing,config.maxchildpages)); } } } if (pid != 0) { // only in the superserver // check if there are too many spare servers if (numSpareServers(children) > config.maxspareservers) { // // send oobkills case firstSpareSlot(children) of { nothing -> ; // shouldn't happen | just(slot) -> cproc = deref(children[slot]); // send kill to child process, send(cproc.oobsock,"KILL"); // close sockets close(cproc.oobsock); close(cproc.cgisock); // set slot to nothing children[slot] = nothing; } } // if any spare servers, check if anything is pending on listen() case firstSpareSlot(children) of { nothing -> ; // can't accept any more for now // // accept() and pass it on to a spare server | just(slot) -> cproc = deref(children[slot]); if (pending(cproc.oobsock,1)) { if (recv(cproc.oobsock,4,10) == "DEAD") { close(cproc.oobsock); close(cproc.cgisock); // set slot to nothing children[slot] = nothing; } } else if (connWaiting(lsock)) { // check for pending, accept, set inuse, send data client = accept(lsock); cproc.client = just(client); send(cproc.oobsock,"OKAY"); netToSocket(deref(cproc.client),cproc.cgisock); } } // check if anything is pending and ready on oobs for child@slot in children { case child of { nothing -> ; | just(cproc) -> case cproc.client of { nothing -> ; | just(client) -> if (pending(cproc.oobsock,10)) { // // throw back the written data to the accept()ed and close, unset inuse okay = recv(cproc.oobsock,4); if (okay != "DONE") { put(stderr,"Received: "+okay+" rather than DONE\n"); } if (pending(cproc.cgisock,10)) { socketToNet(cproc.cgisock,client); } closeConnection(client); cproc.client = nothing; cproc.remaining--; if (cproc.remaining < 1) { send(cproc.oobsock,"KILL"); // close sockets close(cproc.oobsock); close(cproc.cgisock); // set slot to nothing children[slot] = nothing; } } else if (pending(cproc.cgisock,10)) { // just shift what we have socketToNet(cproc.cgisock,client); // and we'll clean up next time round } } } } } reap(); microSleep(100); } catch(e) { // shouldn't be a wildcard exceptionBacktrace(e); } } while (true); } Void __forked(SCGI config, Socket comm, Socket oob) { module::webconfig(); /*** remaining should be handled by main server as otherwise there's a race condition that comes up rather a lot ***/ do { command = recv(oob,4,-1); if (command == "KILL") { send(oob,"DEAD"); return; } else if (command == "OKAY") { try { SCGI::initEnv(comm); // initWebApp needs to be able to read POST from socket rather than stdin WebCommon::initWebApp("",SCGI::scgiEnv,SCGI::nextChar@(comm),SCGI::finishedInput@(comm)); scgiPage(comm,module::webmain()); } catch(e) { if (!Webapp::headersSent) { send(comm,"Status: 500 Internal Server Error\r\n"); send(comm,"Content-type: text/plain; charset=UTF-8\r\n"); send(comm,"Cache-control: no-cache,private\r\n"); send(comm,"\r\n"); } send(comm,"An error has occurred.\r\n"); } removeTemporaryUploaded(); // try to garbage collect as much memory as possible // before taking on a new request old = gcSetFSD(20); gc(); void(gcSetFSD(old)); } send(oob,"DONE"); } while(true); } kaya-0.4.4/posix/syslog_glue.h0000644000175100017510000000030311170340766014420 0ustar cimcim#ifndef _SYSLOGGLUE_H // -*-C++-*- #define _SYSLOGGLUE_H extern "C" { void do_openlog(wchar_t* rawident, int opt, int fac); void do_syslog(int pri, wchar_t* rawmsg); } #endif // Whole file kaya-0.4.4/posix/Syslog.k0000644000175100017510000001037611170340770013355 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2006 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "System logging This module allows logging to the system log service. Only one system log handle may be opened at once." module Syslog; import Builtins; import Array; import System; %include "syslog.h"; %include "syslog_glue.h"; %imported "syslog_glue"; foreign "syslog_glue.o" { "Close the log handle Close the previously opened log handle open write" public Void close() = closelog; Void do_openlog(String ident, Int option, Int facility) = do_openlog; Void do_syslog(Int level, String message) = do_syslog; } "Options for opening the logging handle Options for opening the logging handle: LogPid includes the process id with the log, LogConsole prints the log message to the console if logging fails, and LogStderr copies the log to standard error." public data LogOption = LogPid | LogConsole | LogStderr; "The logging facility to use. The logging facility to use. These have the same meanings as the similarly named facilities in syslog(3). The facility number for LogLocal must be between 0 and 7 inclusive." public data LogFacility = LogAuthPriv | LogCron | LogDaemon | LogFtp | LogKern | LogLpr | LogMail | LogNews | LogSyslog | LogUser | LogUUCP | LogLocal(Int facility); "Log message urgencies The level of urgency for the log message. The syslog(3) manual page contains details of the conventional meanings." public data LogLevel = LogEmergency | LogAlert | LogCritical | LogError | LogWarning | LogNotice | LogInfo | LogDebug; "Bad logging facility This Exception is thrown if open is called with a LogFacility of LogLocal with a facility number outside the 0-7 range." Exception BadFacility; "The identifier for logging, conventionally (and by default) the program name. The logging options. The default is to include the process ID with logging. The logging facility to use. The default is LogUser. Open the logging handle Opens the new logging handle with the specified options. close write" public Void open(String identifier = progName(), [LogOption] opts = [LogPid], LogFacility facility = LogUser) { // make opts and facility into ints, and call do_openlog opti = 0; if (elem(LogPid,opts)) { opti += 1; } if (elem(LogConsole,opts)) { opti += 2; } if (elem(LogStderr,opts)) { opti += 4; } case facility of { LogAuthPriv -> fi = 1; | LogCron -> fi = 2; | LogDaemon -> fi = 3; | LogFtp -> fi = 4; | LogKern -> fi = 5; | LogLpr -> fi = 6; | LogMail -> fi = 7; | LogNews -> fi = 8; | LogSyslog -> fi = 9; | LogUser -> fi = 10; | LogUUCP -> fi = 11; | LogLocal(level) -> if (level >=0 && level <= 7) { fi = 12+level; } else { throw(BadFacility); } } do_openlog(identifier,opti,fi); } "The message to write The LogLevel (urgency) of the message. The default is LogInfo Write a log entry Write a message to the open log handle with the specified priority. close open" public Void write(String logmessage, LogLevel level = LogInfo) { // make level into an int and call do_syslog case level of { LogEmergency -> li = 0; | LogAlert -> li = 1; | LogCritical -> li = 2; | LogError -> li = 3; | LogWarning -> li = 4; | LogNotice -> li = 5; | LogInfo -> li = 6; | LogDebug -> li = 7; } do_syslog(li,logmessage); } kaya-0.4.4/posix/Posix.k0000644000175100017510000002071211170340770013172 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "POSIX-compatible system interaction This module contains additional system interaction functions to those in the System module that are only available on POSIX-compatible systems." module Posix; import public IO; import Array; import System; %include "stdlib.h"; %include "unistd.h"; // %include "crypt.h"; //%link "crypt"; "Resource limits Available resource limits. setRLimit" public data Resource = VirtualMem | Core | CPU | Data | FileSize | Locks | MemLock | NumFiles | NumProcs | RSS | Stack; foreign "stdfuns.o" { Int callsystem(String prog) = do_system; Ptr callpopen(String prog, Bool read) = do_popen; Int do_pclose(Ptr stream) = do_pclose; "Fork a new process. Returns the pid (in the parent) or 0 (in the child)" Int dofork() = dofork; "Clean up dead child processes. Clean up dead child processes. fork" public Void reap() = reap; "Wait for a child to terminate. Wait for a child to terminate. Returns the child's exit code. fork waitPid" public Int wait() = dowait; "The process ID of the child Wait for a specific child to terminate. Wait for a specific child to terminate. Returns the child's exit code. fork wait" public Int waitPid(Int pid) = dowaitpid; "Get the process ID. Get the current process ID. fork waitPid" public Int getPid() = getpid; "Get effective user ID Get the effective user ID of the current process getEGid getGid getUid" public Int getEUid() = geteuid; "Get real user ID Get the real user ID of the current process getEGid getEUid getGid" public Int getUid() = getuid; "Get effective group ID Get the effective group ID of the current process getEUid getGid getUid" public Int getEGid() = getegid; "Get real group ID Get the real group ID of the current process getEGid getEUid getUid" public Int getGid() = getgid; Int do_setPGid(Int pid, Int pgid) = setpgid; Int do_setRLimit(Resource res, Int soft, Int hard) = do_setrlimit; // more trouble than it's worth... // "System crypt function." // public String crypt(String key, String salt) = crypt; Bool validFile(Ptr h) = validFile; } "The exit code Non-zero exit code A child process exited with a non-zero exit code" Exception NonZeroExit(Int code); "Out of memory There was insufficient memory to create a new process." Exception OutOfMemory; "Over resource limit A resource limit was exceeded while trying to create a new process." Exception OverResourceLimit; "No such resource The specified resource limit does not exist on this system." Exception NoSuchResource; "Invalid file mode The IO::FileMode for opening pipes must be either Read or Write." Exception InvalidFileMode; "Failed to set process group An attempt to set the process group ID failed." Exception SetPGidFailed; "The process ID to set the group of, or zero to use the current process. The new process group ID, or zero to use the current process' group ID Set a process group ID Set the process group id of pid to pgid." public Void setPGid(Int pid, Int pgid) { r = do_setPGid(pid,pgid); if (r != 0) { throw(SetPGidFailed); } } "Fork a new process. Fork a new process, returning the process ID of the new process in the parent process, or zero in the child process. An OutOfMemory or OverResourceLimit if the process cannot be created. reap wait waitPid" public Int fork() { r = dofork(); if (r>=0) { return r; } else if (r==-1) { throw(OutOfMemory); } else if (r==-2) { throw(OverResourceLimit); } else throw(InternalError(r)); } "The command to run Run an external program Run an external program. If the external program exits with a non-zero status, a NonZeroExit exception will be thrown. call fork popen" public Void system(String cmd) { ok = callsystem(cmd); if (ok!=0) { throw(NonZeroExit(-ok)); } } "The command to run Whether to open Read (get command's output), or Write (send input to the command) Open a pipe to a command. Open a pipe to a command. call fork pclose system" public File popen(String cmd, FileMode mode) { case mode of { Read -> f = file(callpopen(cmd,true),[Read]); | Write -> f = file(callpopen(cmd,false),[Write]); | _ -> throw(InvalidFileMode); } if (validFile(ptr(f))) { return f; } else { throw(FileError); } } "The open pipe Close a pipe Close a pipe to a command. If the command's exit status is non-zero, then a NonZeroExit exception will be throw. popen" public Void pclose(File stream) { openCheck(stream); ok = do_pclose(ptr(stream)); if (ok!=0) { throw(NonZeroExit(ok)); } } "The command to run Get the output of an external program Return the output of an external program. If the external program exits with a non-zero status, a NonZeroExit exception will be thrown. fork popen system" public String call(String cmd) { f = popen(cmd, Read); contents = ""; while(!eof(f)) { contents = contents+get(f); } pclose(f); return contents; } "The resource limit to set The soft limit to set (-1 for unlimited) The hard limit to set (-1 for unlimited). This parameter may be omitted and defaults to -1. Set a resource limit. Set the hard and soft limits for the specified resource. Resource" public Void setRLimit(Resource res, Int soft, Int hard = -1) { if (do_setRLimit(res,soft,hard)==0) { throw(NoSuchResource); } } kaya-0.4.4/posix/sockets_glue.h0000644000175100017510000000126211170340770014553 0ustar cimcim#ifndef _SOCKETS_H #define _SOCKETS_H #include "Heap.h" #include "VM.h" #include "stdfuns.h" #include "KayaAPI.h" #include #include extern "C" { KArray do_socketpair(); void do_closesocket(void* sptr); void do_socketsend(void* vmptr, void* sptr, wchar_t* msg); void do_socketsendchars(void* vmptr, void* sptr, void* data, int len); void do_socketsendbyte(void* vmptr, void* sptr, kint byte); wchar_t* do_socketrecv(void* vmptr, void* sptr, KayaValue len); void* do_socketrecvchars(void* vmptr, void* sptr, KayaValue len); kint do_socketrecvbyte(void* vmptr, void* sptr); bool do_socketpending(void* vm, void* conn, int timeout); } #endif kaya-0.4.4/posix/SCGI.k0000644000175100017510000002727111170340770012624 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2007 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "SCGI interface This module provides functions needed by the SCGI interface (SCGI protocol). The majority of these functions are used by the SCGI template (scgi.ks) and should not be called directly by programs. The exceptions are scgiEnv, which should replace any call to System::getEnv within an SCGI program, and scgiPage, which may be overloaded in the same way that Webapp::displayPage is overloaded in web applications." module SCGI; import Regex; import Webapp; import Posix; import Sockets; import System; import Net; import Dict; import Prelude; import Binary; import HTMLDocument; globals { Dict environment; Bool headerssent; } "Bad NetString SCGI header data is encoded as a NetString. This Exception is thrown if it was not possible to parse the SCGI header as a valid NetString" Exception BadNetString; "Malformed headers This Exception is thrown if the SCGI header data was a parseable NetString, but did not contain valid header data." Exception MalformedHeaders; "SCGI configuration This data type describes the configuration of an SCGI server. The scgiconfig function can be used to set the configuration, as well as performing any initialisation that should be specific to the entire server group (generally, unless only select queries are needed, database connections should be initialised in the per-process webconfig function). port: The TCP port to listen on startservers: The number of initial sub-server processes minspareservers: The minimum number of spare sub-server processes to have maxspareservers: The maximum number of spare sub-server processes to have maxservers: The maximum number of spare server processes to have. If there are more simultaneous connections than this, then additional connections will be held in the backlog. This number should be set as high as possible, but not so high that physical memory runs out trying to serve them all. maxbacklog: The maximum backlog of unaccepted connections to allow. Additional connections once the backlog is full will be rejected. maxchildpages: The maximum number of pages a single sub-server can handle. Once a sub-server has served this many pages it will be killed and restarted, which may keep memory usage down. The default values, if no scgiconfig function is present, are SCGI(7597,2,2,4,10,100,10)." public data SCGI(Int port, Int startservers, Int minspareservers, Int maxspareservers, Int maxservers, Int maxbacklog, Int maxchildpages ); type ChildSlot = Maybe; "Internal data type This data type is used to internally represent the processes within the SCGI server." public data ChildProcess(Socket cgisock, Socket oobsock, Maybe client, Int remaining); "Internal function This function is used internally by the SCGI server to count the number of sub-servers currently free to handle new requests." public Int numSpareServers([ChildSlot] children) { n = 0; for child in children { case child of { just(ChildProcess(_,_,nothing,_)) -> n++; | _ ->; } } return n; } "Internal function This function is used internally by the SCGI server to find an empty server slot." public Maybe firstEmptySlot([ChildSlot] children) { for child@idx in children { case child of { nothing -> return just(idx); | _ -> ; } } return nothing; } "Internal function This function is used internally by the SCGI server to find a sub-server to process a HTTP request." public Maybe firstSpareSlot([ChildSlot] children) { for child@idx in children { case child of { just(ChildProcess(_,_,nothing,_)) -> return just(idx); | _ -> ; } } return nothing; } "Internal function This function is used internally by the SCGI server to initialise environment variables." public Void initEnv(Socket comm) { headerssent = false; hlen = createArray(5); do { c = Char(recvByte(comm)); if (c!=':') { push(hlen,c); } } while (c!=':'); len = Int(string(hlen)); if (len > 0) { edata = recvBytes(comm,len); } if (Char(recvByte(comm)) != ',') { throw(BadNetString); } strs = createArray(50); offset = 0; while (offset < len) { str = peekString(edata,offset); push(strs,str); offset+=byteLength(str)+1; } if (size(strs) % 2 != 0) { throw(MalformedHeaders); } environment = Dict::new(53,strHash); while (size(strs) > 0) { key = shift(strs); val = shift(strs); add(environment,key,val); } if (!exists(environment,"CONTENT_LENGTH")) { throw(MalformedHeaders); } case lookup(environment,"SCGI") of { nothing -> throw(MalformedHeaders); | just(s) -> if (s != "1") { throw(MalformedHeaders); } } } "Name of the environment variable Get the value of an environment variable Since environment variables are handled differently under the SCGI protocol to the conventional manner, this function must be used instead of System::getEnv to read environment variables within an SCGI application." public String scgiEnv(String key) { case lookup(environment,key) of { nothing -> return ""; | just(val) -> return val; } } "Internal function This function returns the next byte from a socket as a Char. It is used internally to read POST data." public Char nextChar(Socket s) { return Char(recvByte(s,1)); } "The SCGI program's data output socket. All output data should be written to this socket. A HTMLDocument page Displays a HTML page Displays a HTML page. The scgiPage functions are called automatically by a SCGI webapp based on the return value of webmain and should only be called directly for debugging purposes and when constructing custom scgiPage functions. HTMLDocument::HTMLDocument scgiPage (string data) scgiPage (binary data) scgiPage (void functions)" public Void scgiPage(Socket comm, HTMLDocument page) { sendHeaders(comm,page.httpheaders); send(comm,"\n"); // end headers writeTo(page,send@(comm)); if (debugMode) { send(comm,""); } } // we have the generic String and Binary output methods here. Other modules // should have their own scgiPage() functions for appropriate output. // HTMLDocument is above as an exception to this. "The SCGI program's data output socket. All output data should be written to this socket. The string to output as the content A list of key-value pairs of HTTP headers Displays String content Displays String content. The scgiPage functions are called automatically by a SCGI webapp based on the return value of webmain and should only be called directly for debugging purposes and when constructing custom scgiPage functions. scgiPage (HTML documents) scgiPage (binary data) scgiPage (void functions)" public Void scgiPage(Socket comm, String sdata, [(String,String)] headers) { sendHeaders(comm,headers); // last header send(comm,"Content-length: "+length(sdata)+"\n\n"); send(comm,sdata); } "The SCGI program's data output socket. All output data should be written to this socket. The binary block containing the content A list of key-value pairs of HTTP headers Displays binary data Displays binary data (for example an Image). The scgiPage functions are called automatically by a SCGI webapp based on the return value of webmain and should only be called directly for debugging purposes and when constructing custom scgiPage functions. Binary::Binary Image scgiPage (HTML documents) scgiPage (string data) scgiPage (void functions)" public Void scgiPage(Socket comm, Binary bdata, [(String,String)] headers) { sendHeaders(comm,headers); // last header send(comm,"Content-length: "+blockSize(bdata)+"\n\n"); for i in [0..(blockSize(bdata)-1)] { ch = peek(bdata,i); sendByte(comm,ch); } } "The SCGI program's data output socket. All output data should be written to this socket. A Void function taking a socket, that uses Sockets::send to output the data. A list of key-value pairs of HTTP headers Displays a function result Displays a function result. The scgiPage functions are called automatically by a SCGI webapp based on the return value of webmain and should only be called directly for debugging purposes and when constructing custom scgiPage functions. This function may be useful for output of very large amounts of content where reading the entire content into a string or binary block before printing it is not practical. scgiPage (HTML documents) scgiPage (string data) scgiPage (binary data)" public Void scgiPage(Socket comm, Void(Socket) fn, [(String,String)] headers) { sendHeaders(comm,headers); send(comm,"\n"); // end headers fn(comm); } // check that headers are in reasonable format // let's not let people stick a response body in the headers, for example private Void sendHeaders(Socket comm, [(String,String)] headers) { if (headersent) { return; } hkey = compile("[()<>@,;:\\\"/[\\]?={}[:cntrl:]\r\n]"); hval = compile("[[:cntrl:]\r\n]"); for header in headers { if (quickMatch(hkey,header.fst)) { throw(BadHeadersKey(header.fst,header.snd)); } if (quickMatch(hval,header.snd)) { throw(BadHeadersVal(header.fst,header.snd)); } send(comm,header.fst+": "+header.snd+"\n"); } headersent = true; } "Internal function This function is used internally for reading POST data" public Bool finishedInput(Socket comm) { return !pending(comm,1); } kaya-0.4.4/posix/Makefile.in0000644000175100017510000000414111170340770013757 0ustar cimcimRVPATH=@srcdir@ VPATH=${RVPATH} LANGNAME = @LANGNAME@ KAYAC = ../compiler/@TARGET@ prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@/${LANGNAME} LIBDIR = ${libdir} IMPORTDIR = ${libdir}/imports CXXFLAGS = @FPIC@ @EXTRAGCCOPTS@ -I../rts -O2 -I${VPATH}/../rts -I${VPATH}/../posix KAYAINC = @KAYAPROF@ -noenvlibs -I ../rts -I ../stdlib -L ../stdlib -deprfail -L ${VPATH}/../rts -L ${VPATH} INSTALLFLAGS = -m 644 LIBTARGET = lib@LANGNAME@std.so lib@LANGNAME@web.so lib@LANGNAME@re.so LIBSTATIC = lib@LANGNAME@std.a lib@LANGNAME@web.a lib@LANGNAME@re.a LIBINFO = @LANGNAME@std.ddl @LANGNAME@web.ddl @LANGNAME@re.ddl SRCS = Posix.@EXT@ SCGI.@EXT@ \ ServerLoop.@EXT@ Signal.@EXT@ Syslog.@EXT@ Sockets.@EXT@ IFACE = Posix.ki SCGI.ki \ ServerLoop.ki Signal.ki Syslog.ki Sockets.ki LOCALOBJS = Posix.o SCGI.o \ Signal.o ServerLoop.o Syslog.o Sockets.o \ signal_glue.o syslog_glue.o sockets_glue.o OBJS = ${LOCALOBJS} #${TARGET}: ${LIBTARGET} # ${CXX} -fpic ${CXXFLAGS} -shared ${OBJS} -o ${TARGET} all: ${OBJS} dynlink: ${LIBTARGET} #${LIBTARGET}: ${OBJS} # ../tools/dynlink @LANGNAME@std ${STDOBJS} # ../tools/dynlink @LANGNAME@web -lssl -lcrypt -lcgi ${WEBOBJS} # ../tools/dynlink @LANGNAME@re -lpcre ${REOBJS} install: mkdir -p ${DESTDIR}${libdir} mkdir -p ${DESTDIR}${IMPORTDIR} # install ${TARGET} ${LIBDIR} # install ${LIBTARGET} ${LIBSTATIC} ${LIBINFO} ${LIBDIR} install ${INSTALLFLAGS} ${IFACE} ${DESTDIR}${IMPORTDIR} install ${INSTALLFLAGS} ${OBJS} ${DESTDIR}${IMPORTDIR} install ${INSTALLFLAGS} ${VPATH}/scgi.ks ${DESTDIR}${IMPORTDIR} clean: rm -f ${OBJS} ${IFACE} ${LIBTARGET} ${TARGET} rm -f *.html *.xml rm -rf docs distclean: clean rm -f *~ Makefile rm -rf autom4te.cache ServerLoop.o: Posix.ki SCGI.o: Posix.ki Sockets.ki Sockets.o: ../stdlib/Net.ki sockets_glue.h Posix.ki Signal.o: signal_glue.h Syslog.o: syslog_glue.h signal_glue.o: signal_glue.h sockets_glue.o: sockets_glue.h syslog_glue.o: syslog_glue.h #Prelude.o: Prelude.ki Builtins.ki Maths.ki Array.ki %.o : %.@EXT@ ${KAYAC} $< -noprelude -nochase ${KAYAINC} -nortchecks -L ../rts_opt -L ../rts -xmldocs %.ki : %.o @: kaya-0.4.4/INSTALL0000644000175100017510000000573711170340767011623 0ustar cimcimGeneral: -------- Additional information about obtaining the libraries and tools needed to install Kaya is available at http://kayalang.org/download/compiling Please contact us by emailing kaya@kayalang.org, or by subscribing to the kaya-devel@kayalang.org mailing list, if you have problems with any part of these instructions on your system. Before starting: ---------------- Make sure your system has: - The usual development tools (make, g++, etc) - The Glasgow Haskell Compiler (ghc) - The Happy parser generator - The libraries and development headers for: * libgc * zlib * libgcrypt * libpcre * libgnutls - On Windows, libintl-2.dll - Any optional libraries and development headers (database access, curses, etc) Building on Linux/Unix/MacOS X: ------------------------------- Compiling Kaya on Unix based systems is generally fairly straightforward, and all the required development libraries should be available from your distribution. Building on Windows: -------------------- Compiling Kaya on Windows is not yet as easy as we'd like, and you should read http://kayalang.org/download/compiling/windows for windows-specific instructions. Unless you are already a MinGW user, you will need to construct your build environment from scratch, which will take some time. Please ask on the mailing list for help if you have problems with this. Building Kaya: -------------- Building Kaya should usually be a simple matter of ./configure && make 'configure' will warn you about missing essential libraries at this stage. On Windows, use './configure --prefix=c:/kaya' (or wherever you want to install). 'make' will then go through the build process, building the compiler, run-time system, standard and optional libraries, extra tools, and library API documentation. If 'make' exits with an error, this may be a bug in kaya, but is most likely to be an oddity of your build environment - either way, please let us know at the email addresses above so we can investigate and help fix it. Generally, however, if 'configure' has been able to detect the needed libraries, 'make' will work normally. You may then want to run the regression tests with 'make test'. All tests should pass (test019 is known to fail on Windows, but this is harmless). Finally, do 'make install' to install the compiler, libraries and documentation. After installation: ------------------- Make sure you add the location you installed the compiler to your PATH. The default is ~/bin You will then be able to run the 'kayac' compiler. If you would like to receive notices of future Kaya version releases, subscribe to the kaya-announce mailing list at http://lists.kayalang.org/lists/listinfo/kaya-announce This is a very low-traffic list only used for new version releases and other very important announcements. If you have any comments about Kaya, or would like help with any aspect of Kaya programming, email kaya@kayalang.org or join the kaya-devel mailing list at http://lists.kayalang.org/lists/listinfo/kaya-develkaya-0.4.4/bframe/0000755000175100017510000000000011170340770012004 5ustar cimcimkaya-0.4.4/bframe/stringbuild.k0000644000175100017510000000133111170340770014504 0ustar cimcimprogram stringbuild; // -*-C-*-ish import memuse; // String operations. Build lots of strings by adding stuff on in various ways. // we need a consistent RNG for this, and ideally a fast one, since it's // not supposed to be a test of RNG speed. globals { Int randseed = 12345; } Int arand() { randseed = randseed*62089911; return abs(randseed>>16); } String buildStr { startstr = "Sausage machine 1 "; x = arand() % 50; for i in [0..x] { startstr+=Char(arand()%26+'A'); startstr+='q'; startstr+="foo"; } // putStrLn(startstr); return startstr; } Void main() { strs = createArray(10000); for x in [1..10000] { push(strs,buildStr); } putStrLn(strs[375]); memStat(); } kaya-0.4.4/bframe/fibonacci.k0000644000175100017510000000026511170340767014106 0ustar cimcimprogram fibonacci; import memuse; Void main() { putStrLn("Fib("+28+"): "+fib(28)); memStat(); } Int fib(Int x) { if (x < 2) { return 1; } return fib(x-1)+fib(x-2); } kaya-0.4.4/bframe/relspeed.cc0000644000175100017510000000023411170340767014123 0ustar cimcim#include int main(int argc, char *argv[]) { long N; long C; for (N=0; N<100000000; N++) { C+=N; } printf("%d\n",C); return(0); } kaya-0.4.4/bframe/lists3.k0000644000175100017510000000121311170340770013376 0ustar cimcimprogram lists3; import memuse; /* Modularise this section */ // head node is special Void main() { testsize = 100000; list1 = initList(testsize); list2 = copy(list1); list3 = createArray(testsize); while (size(list2)>0) { push(list3,shift(list2)); } while (size(list3)>0) { push(list2,top(list3)); pop(list3); } reverse(list1); if (list1[0] == testsize) { if (list1 == list2) { if (size(list1) == testsize) { putStrLn(testsize+" ok"); } } } memStat(); } [Int] initList(Int testsize) { thelist = createArray(testsize); for i in [1..testsize] { push(thelist,i); } return thelist; } kaya-0.4.4/bframe/random.k0000644000175100017510000000047211170340770013443 0ustar cimcimprogram random; import memuse; globals { Int seed = 42; } Void main() { iter = 1000000; max = 100.0; for i in [1..iter-1] { void(genrand(max)); } putStrLn(String(genrand(max))); memStat(); } Float genrand(Float max) { seed = ((seed * 3877)+29573)%139968; return ((max*seed) / 139968.0); } kaya-0.4.4/bframe/heapsort.k0000644000175100017510000000156011170340767014015 0ustar cimcimprogram heapsort; import memuse; globals { Int seed; } Void main() { seed = 42; arsize = 20000; tosort = createArray(arsize); for i in [0..arsize-1] { tosort[i] = genrand(1); } heapsort(arsize-1,tosort); putStrLn(String(tosort[arsize-1])); memStat(); } Float genrand(var Int max) { seed = ((seed * 3877)+29573)%139968; return (Float(max*seed) / 139968.0); } Void heapsort(Int arsize, var [Float] ra) { ir = arsize; l = (arsize >> 1) + 1; while (true) { if (l > 1) { l--; rra = ra[l]; } else { rra = ra[ir]; ra[ir] = ra[1]; ir--; if (ir == 1) { ra[1] = rra; return; } } i = l; j = l << 1; while (j <= ir) { if (j < ir && ra[j] < ra[j+1]) { j++; } if (rra < ra[j]) { ra[i] = ra[j]; i = j; j += i; } else { j = ir + 1; } } ra[i] = rra; } } kaya-0.4.4/bframe/primes.k0000644000175100017510000000077511170340766013475 0ustar cimcimprogram primes; import memuse; Void main() { for i in [1..100] { sieve = genSieve; primes = runSieve(sieve); } putStrLn("Found "+primes+" primes"); memStat(); } [Bool] genSieve() { sieve = createArray(8193); for i in [2..8192] { sieve[i] = true; } s[0] = false; s[1] = false; return sieve; } Int runSieve(var [Bool] sieve) { co = 0; for i in [2..8192] { if (sieve[i]) { for (j=2*i;j<=8192;j+=i) { sieve[j] = false; } co++; } } return co; } kaya-0.4.4/bframe/vm.k0000644000175100017510000000004611170340766012607 0ustar cimcimprogram vm; Void main() { i = 0; } kaya-0.4.4/bframe/lists2.k0000644000175100017510000000601011170340770013375 0ustar cimcimprogram lists2; import memuse; /* Modularise this section */ // head node is special data DLLnode = notset | DLLnode(Int val, DLLnode elnext, DLLnode elprev, Bool ishead); Exception ListIsEmpty; Int length(DLLnode head) = head.val; Bool empty(DLLnode head) { return (head.val <= 0); } DLLnode first(DLLnode head) = head.elnext; DLLnode last(DLLnode head) = head.elprev; Void pushTail(DLLnode head, DLLnode item) { head.elprev.elnext = item; item.elnext = head; item.elprev = head.elprev; head.elprev = item; head.val++; } DLLnode popTail(DLLnode head) { if (empty(head)) { throw(ListIsEmpty); } tail = head.elprev; head.elprev = tail.elprev; tail.elprev.elnext = head; head.val--; return tail; } Void pushHead(DLLnode head, DLLnode item) { head.elnext.elprev = item; item.elnext = head.elnext; head.elnext = item; item.elprev = head; head.val++; } DLLnode popHead(DLLnode head) { if (empty(head)) { throw(ListIsEmpty); } elnext = head.elnext; head.elnext = elnext.elnext; elnext.elnext.elprev = head; head.val--; return elnext; } DLLnode newList() { list = DLLnode(0,notset,notset,true); list.elnext = list; list.elprev = list; return list; } Bool equalLists(DLLnode head1, DLLnode head2) { // return (head1 == head2); // works, but takes too much memory p = head1; q = head2; while(true) { if (p.val != q.val) { return false; } p = p.elnext; q = q.elnext; if (p.ishead) { return (q.ishead); } } return false; // can't happen } DLLnode copyList(DLLnode list) { // return copy(list); // works, but takes too much memory copied = newList(); p = list.elnext; n = notset; while(true) { pushTail(copied,DLLnode(p.val,n,n,false)); p = p.elnext; if (p.ishead) { return copied; } } return copied; // can't happen } Void reverse(DLLnode head) { p = head; while(true) { tmp = p.elnext; p.elnext = p.elprev; p.elprev = tmp; p = p.elprev; if (p.ishead) { return; } } /* fowd = copyList(head); revd = newList(); while (!empty(fowd)) { pushTail(revd,popTail(fowd)); } return revd; */ } /* p = head.elnext; itdone = false; while (!itdone) { tmp = p.elnext; p.elnext = p.elprev; p.elprev = tmp; if (p.ishead) { itdone = true; } } tmp2 = head.elnext; head.elnext = head.elprev; head.elprev = tmp2; } */ /* End module */ Void main() { testsize = 100000; list1 = initList(testsize); list2 = copyList(list1); list3 = newList(); while (!empty(list2)) { pushTail(list3,popHead(list2)); } while (!empty(list3)) { pushTail(list2,popTail(list3)); } module::reverse(list1); if (first(list1).val == testsize) { if (equalLists(list1,list2)) { if (module::length(list1) == testsize) { putStrLn(testsize+" ok"); } } } memStat(); } DLLnode initList(Int testsize) { thelist = newList(); n = notset; for i in [1..testsize] { pushTail(thelist,DLLnode(i,n,n,false)); } return thelist; } kaya-0.4.4/bframe/README0000644000175100017510000000542711170340767012702 0ustar cimcim* Benchmark tests: The benchmark tests are intended to check the behaviour of optimisations in the compiler and rts. Use 'make bench' in this directory or 'make benchmark' in the main build directory to run the tests. * Current tests: ** Ackermann This tests performance with a highly recursive algorithm. ** Fibonacci This is another recursion performance test. ** Heapsort This tests array and mathematical comparison performance ** HTML This tests the performance of the HTML construction and output used in webprogs. ** Lists This tests the performance of user-defined data types with large amounts of data and argument projection. ** Lists2 An alternative implementation of Lists (this is approximately testing the advantage of using a compiler-optimisable type, and some better caching of notset values, compared to lists) ** Primes A test of arrays and loops ** Random This tests integer and float operations, and also global variable speed. ** Stringbuild This tests construction of strings. ** Takfp This tests recursive operations using floats ** Takint Same as takfp, but using ints. Together with takfp gives a measure of the relative speed of ints and floats. * Adding additional tests Additional tests should have a source file 'testname.k' that compiles to a 'testname' executable. Simply add to the appropriate parts of Makefile.in and reconfigure. Tests must not write to stderr, though writes to stdout are fine. Tests must also not rely on any checks removed by -nortchecks (which is bad practice anyway), nor require any user input (either from the keyboard, or command-line parameters). * What do the results mean The benchmark program first runs a simple C program to get a measure of the computer's relative speed. It then runs a simple Kaya program to check the startup time for Kaya apps. Using these figures, it then normalises the time taken to run each test to give a performance number. Performance numbers are *not* generally comparable between tests (so the ackermann test being faster than the lists test is not important) but can be compared for the same test, and should be reasonably comparable between different computers. The lower the number the better, but what the number actually means is debatable. * Performance tests and 'cheating' Yes, 'fibonacci' would be considerably faster if it had a cache in its recursion. Adding the cache in the .k is cheating. Rewriting kaya so that it detects it's a recursive function without side-effects and automatically adds a little cache when compiling is not cheating (though not necessarily a good idea either - who knows until someone tries it...). Of course, if there's an unintentional inefficiency in the implementation (for example, if the ackermann implementation was set up to stop tail-recursion working), that should be fixed. kaya-0.4.4/bframe/vm.sh0000644000175100017510000000014711170340767012772 0ustar cimcim#!/bin/sh for j in 1 2 3 4 5 6 7 8 9 10; do for i in 1 2 3 4 5 6 7 8 9 10; do ./vm done done exit 0;kaya-0.4.4/bframe/takfp.k0000644000175100017510000000041711170340766013274 0ustar cimcimprogram takfp; import memuse; Void main() { n = 8.0; putStrLn("TAK(24.0,16.0,8.0) = "+TAK(3.0*n,2.0*n,n)); memStat(); } Float TAK(Float x, Float y, Float z) { if (y >= x) { return z; } return TAK(TAK(x-1.0,y,z), TAK(y-1.0,z,x), TAK(z-1.0,x,y)); } kaya-0.4.4/bframe/lists.k0000644000175100017510000000775611170340770013335 0ustar cimcimprogram lists; import memuse; /* Modularise this section */ // head node is special data DLLnode = notset | DLLnode(a val, DLLnode elnext, DLLnode elprev ); data DLLhead = DLLhead(Int val, DLLnode elnext, DLLnode elprev); Exception ListIsEmpty; Int length(DLLhead head) = head.val; Bool empty(DLLhead head) { return (head.val <= 0); } DLLnode first(DLLhead head) = head.elnext; DLLnode last(DLLhead head) = head.elprev; Void pushTail(DLLhead head, DLLnode item) { tail = head.elprev; case tail of { notset -> item.elnext = notset; item.elprev = notset; head.elprev = item; head.elnext = item; | _ -> tail.elnext = item; item.elnext = notset; // notset for head head.elprev = item; item.elprev = tail; }; head.val++; } DLLnode popTail(DLLhead head) { if (empty(head)) { throw(ListIsEmpty); } tail = head.elprev; case tail.elprev of { notset -> head.elprev = notset; head.elnext = notset; | _ -> head.elprev = tail.elprev; tail.elprev.elnext = notset; // notset for head } head.val--; return tail; } Void pushHead(DLLhead head, DLLnode item) { elnext = head.elnext; case elnext of { notset -> item.elnext = notset; item.elprev = notset; head.elprev = item; head.elnext = item; | _ -> head.elnext = item; elnext.elprev = item; item.elnext = elnext; item.elprev = notset; // notset for head }; head.val++; } DLLnode popHead(DLLhead head) { if (empty(head)) { throw(ListIsEmpty); } elnext = head.elnext; case elnext.elnext of { notset -> head.elprev = notset; head.elnext = notset; | _ -> head.elnext = elnext.elnext; elnext.elnext.elprev = notset; // notset for head } /* if (head.val > 1) { head.elnext = elnext.elnext; elnext.elnext.elprev = notset; // notset for head } else { head.elnext = notset; head.elprev = notset; }*/ head.val--; return elnext; } DLLhead newList() { return DLLhead(0,notset,notset); // list.elnext = list; // list.elprev = list; // return list; } DLLnode newNode(a val) { return DLLnode(val,notset,notset); } Bool equalLists(DLLhead head1, DLLhead head2) { if (head1.val != head2.val) { return false; } p = head1.elnext; q = head2.elnext; itdone = false; while (!itdone) { if (p.val != q.val) { return false; } p = p.elnext; q = q.elnext; case p of { notset -> itdone = true; | _ -> ; }; } case q of { notset -> return true; | _ -> return false; }; } DLLhead copyList(DLLhead list) { copied = newList(); itdone = false; p = list.elnext; while (!itdone) { pushTail(copied,newNode(p.val)); p = p.elnext; case p of { notset -> itdone = true; | _ -> ; }; } return copied; } Void reverse(DLLhead head) { p = head.elnext; itdone = false; while (!itdone) { tmp = p.elnext; p.elnext = p.elprev; p.elprev = tmp; p = p.elprev; case p of { notset -> itdone = true; | _ -> ; } } tmp = head.elnext; head.elnext = head.elprev; head.elprev = tmp; } /* p = head.elnext; itdone = false; while (!itdone) { tmp = p.elnext; p.elnext = p.elprev; p.elprev = tmp; if (p.ishead) { itdone = true; } } tmp2 = head.elnext; head.elnext = head.elprev; head.elprev = tmp2; } */ /* End module */ Void main() { testsize = 100000; list1 = initList(testsize); list2 = copyList(list1); list3 = newList(); while (!empty(list2)) { pushTail(list3,popHead(list2)); } while (!empty(list3)) { pushTail(list2,popTail(list3)); } module::reverse(list1); if (first(list1).val == testsize) { if (equalLists(list1,list2)) { if (module::length(list1) == testsize) { putStrLn(testsize+" ok"); } } } // system("ps -o cmd,m_size,vsz"); memStat(); } DLLhead initList(Int testsize) { thelist = newList(); for i in [1..testsize] { pushTail(thelist,newNode(i)); } return thelist; } kaya-0.4.4/bframe/benchmarker.k0000644000175100017510000000410311170340767014445 0ustar cimcimprogram benchmarker; import Posix; import System; import Regex; import Strings; import IO; Void main() { args = getArgs(); if (size(args) < 3) { putStrLn("Usage: benchmarker TIMEPROG RELSPEEDPROG STARTPROG [BENCHPROGS]"); } else { timeprog = args[1]; relspeedbaseline = args[2]; startupbaseline = args[3]; for i in [0..3] { discard = shift(args); } programs = args; relspeed = Float(getRunTime(timeprog,relspeedbaseline,true))/1000.0; putStrLn("Relative computer speed = "+relspeed); starttime = Float(getRunTime(timeprog,startupbaseline,true))/100.0; putStrLn("Kaya VM startup time = "+starttime); if (size(programs) == 0) { putStrLn("No benchmark executables specified."); } else { summary = ""; for benchprog in programs { putStrLn("Trying "+benchprog); putStrLn("...start test..."); exectime = 0.0; for i in [1..5] { // take average of five runs progspeed = getRunTime(timeprog,benchprog,(i==1 && benchprog!="html")); exectime += (Float(progspeed) - starttime)/100.0; } putStrLn("...end test..."); reltime = floor(100* (exectime/5) / relspeed)/100; putStrLn("Completed in "+String(exectime)+" seconds."); putStrLn("Normalised completion time: "+reltime); dots = strRepeat(".",12-length(benchprog)); summary += benchprog+dots+": "+reltime+"\n"; } putStrLn("\n-----------------------"); putStrLn("Summary:"); putStrLn("-----------------------"); putStrLn(summary); } } } Int getRunTime(String timeprog, String testprog, Bool stdout) { if (stdout) { system(timeprog+" -f'%U' ./"+testprog+" 2>timing"); } else { system(timeprog+" -f'%U' ./"+testprog+" 2>timing >/dev/null"); putStrLn("...repeating test for average run time"); } result = open("timing",[Read]); timeline = get(result); close(result); rtrim(timeline,isLineEnding); timeparts = split("\\.",timeline); return (100*Int(timeparts[0]))+Int(timeparts[1]); } String strRepeat(String c, Int num) { result = ""; for i in [1..num] { result = result + c; } return result; } kaya-0.4.4/bframe/ackermann.k0000644000175100017510000000062511170340770014122 0ustar cimcimprogram ackermann; import memuse; Void main() { putStrLn("Ack(3,7): "+ack(3,7)); memStat(); } Int ack(Int x, Int y) { case x of { 0 -> return y+1; |_ -> case y of { 0 -> return ack(x-1,1); |_ -> return ack(x-1,ack(x,y-1)); } } } /*Int ack(Int x, Int y) { if (x == 0) { return y+1; } else if (y == 0) { return ack(x-1,1); } return ack(x-1,ack(x,y-1)); }*/ kaya-0.4.4/bframe/takint.k0000644000175100017510000000036611170340766013464 0ustar cimcimprogram takint; import memuse; Void main() { n = 8; putStrLn("TAK(24,16,8) = "+TAK(3*n,2*n,n)); memStat(); } Int TAK(Int x, Int y, Int z) { if (y >= x) { return z; } return TAK(TAK(x-1,y,z), TAK(y-1,z,x), TAK(z-1,x,y)); } kaya-0.4.4/bframe/html.k0000644000175100017510000000355311170340770013132 0ustar cimcimprogram html; import memuse; import HTMLDocument; import Webapp; globals { Int randseed = 12345; } Void main() { doc = new(HTML4Strict,"Hello World!"); // add some document meta data addDocumentMetaData(doc,"generator","KayHTML"); addDocumentLink(doc,Rev("author"),"mailto:author@example.invalid"); addDocumentStylesheet(doc,[MTscreen,MTprojection],"http://www.example.com/styles.css"); void(addHeading(doc.body,1,"Test Document")); divs = []; for i in [0..100] { divs[i] = addDivision(doc.body); void(addHeading(divs[i],2,"Section "+i)); addContent(divs[i]); } displayPage(doc); memStat(); } Void addContent(ElementTree tree) { for i in [0..(2+arand()%3)] { case (arand()%5) of { 0 -> void(addParagraph(tree,ranStr)); | 1 -> list = addList(tree,Unordered,0); for j in [0..(1+arand()%10)] { case (arand()%5) of { 0 -> li = pushListItem(list,ranStr); appendGenerator(tree,@getContent); | _ -> void(pushListItem(list,ranStr)); } } | 2 -> ranPara(tree); | 3 -> appendGenerator(tree,@getContent); | _ -> addString(tree,ranStr); } } } ElementTree getContent() { tree = anonymousBlock(); if (arand()%5 == 0) { addContent(tree); } else { void(addParagraph(tree,ranStr)); } return tree; } String ranStr() { str = Char(40+(arand()%40))+"abcdef "; return rep(str,2+(arand()%20)); } Void ranPara(ElementTree tree) { p = addParagraph(tree,ranStr()); for k in [0..(2+arand()%5)] { case (arand()%3) of { 0 -> addString(p,ranStr); | 1 -> void(appendInlineElement(p,StrongEmphasis,ranStr)); | _ -> void(appendInlineElement(p,Hyperlink("foo"),ranStr)); } } } // we need a consistent RNG for this, and ideally a fast one, since it's // not supposed to be a test of RNG speed. Int arand() { randseed = randseed*62089911; return abs(randseed>>16); } kaya-0.4.4/bframe/memuse.k0000644000175100017510000000017311170340766013461 0ustar cimcimmodule memuse; public Void memStat() { putStrLn("Heap Size: "+gcHeapSize()); putStrLn("Heap Free: "+gcFreeBytes()); } kaya-0.4.4/bframe/xmlparse.k0000644000175100017510000000024211170340770014011 0ustar cimcimprogram xmlparse; import memuse; import ElementTree; import KayaDoc; import Dict; Void main() { profile = readDoc("../stdlib/HTMLDocument.xml"); memStat(); } kaya-0.4.4/bframe/Makefile.in0000644000175100017510000000201411170340770014046 0ustar cimcimLANGNAME = @LANGNAME@ KAYAC = ../compiler/@TARGET@ prefix = @prefix@ exec_prefix = @exec_prefix@ CXXFLAGS = -I../rts -I../stdlib -I../@platform@ KAYAINC = -I../rts -I../stdlib -I../@platform@ -nochase -noenvlibs -fastvm -L ../rts_fast -L ../rts -L ../stdlib -L ../@platform@ BENCHTIMER = @BENCHTIMER@ SRCS = ackermann.k fibonacci.k heapsort.k html.k lists.k lists2.k lists3.k \ primes.k random.k stringbuild.k takfp.k takint.k xmlparse.k TESTS = ackermann fibonacci heapsort html lists lists2 lists3 primes \ random stringbuild takfp takint xmlparse BASIS = vm relspeed benchmarker OBJS = ${BASIS} ${TESTS} memuse.o all: ${OBJS} bench: all chmod u+x vm.sh ./benchmarker ${BENCHTIMER} relspeed vm.sh ${TESTS} clean: rm -f ${OBJS} timing distclean: clean rm -f *~ Makefile rm -rf autom4te.cache relspeed: relspeed.cc ${CXX} -O0 $< -o $@ vm: vm.k ${KAYAC} $< -nortchecks ${KAYAINC} benchmarker: benchmarker.k memuse.o ${KAYAC} $< ${KAYAINC} % : %.@EXT@ ${KAYAC} $< ${KAYAINC} %.o : %.@EXT@ ${KAYAC} $< ${KAYAINC} kaya-0.4.4/COPYING0000644000175100017510000000272711170340770011613 0ustar cimcimThe files in this distribution may be copied under the following licenses: Standard library, run-time system and library documentation =========================================================== All files in the following directories (and any compiled code and documentation generated from these files as part of the Kaya build process), unless explicitly stated otherwise in the file, are licensed under the Lesser GNU Public License version 2.1 or any later version as published by the Free Software Foundation. Copies of versions 2.1 and 3 of this license are provided in the LGPL2.1 and LGPL3 files respectively. rts/ stdlib/ posix/ windows/ libs/ contrib/ Compiler, website, examples, documentation and other files ========================================================== All other files, unless explicitly stated otherwise in the file, are licensed under the GNU Public License version 2 (or any later version) as published by the Free Software Foundation. Copies of versions 2 and 3 of this license are provided in the GPL2 and GPL3 files respectively. No warranty =========== Kaya 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 individual license files for more details. Contributors ============ Details of the contributors to each file in the distribution may be determined from the darcs repository: see the CREDITS file for an overview. kaya-0.4.4/libs/0000755000175100017510000000000011170340770011501 5ustar cimcimkaya-0.4.4/libs/CursesCommon.k0000644000175100017510000011053611170340770014300 0ustar cimcim"Curses window structure This data type represents a Curses window." abstract data Window = Window(Ptr ptr); "Curses screen structure This data type represents a Curses screen, and is not currently used." abstract data Screen = Screen(Ptr ptr); "Text attributes This data type represents various text attributes. Not all terminals support all attributes, or support attributes in the same way, though Bold, Reverse and ColourPair are generally well-supported." public data Attr = Normal | Standout | Underline | Reverse | Blink | Dim | Bold | Protect | Invis | AltCharset | CharText | ColourPair(Int n); foreign "curses_glue.o" { Ptr getstdscr() = getstdscr; Void cbreak() = docbreak; Void nocbreak() = donocbreak; Void echo() = doecho; Void noecho() = donoecho; Void nl() = donl; Void nonl() = dononl; Void raw() = doraw; Void noraw() = donoraw; Void dointrflush(Ptr ptr,Bool bf) = dointrflush; Void dokeypad(Ptr ptr,Bool bf) = dokeypad; Void dometa(Ptr ptr,Bool bf) = dometa; Void donodelay(Ptr ptr, Bool bf) = donodelay; Void donotimeout(Ptr ptr, Bool bf) = donotimeout; "Time to wait for input, in tenths of a second (must be between 1 and 255) Enable half-delay mode Enable half-delay mode. Half-delay mode is similar to cbreak mode, but if no key is pressed within the specified delay, then the input function will fail with an error. cbreakMode" public Void halfDelay(Int tenths) = halfdelay; Ptr doinitscr() = doinitscr; Ptr doendwin() = endwin; "Check for end of windowing mode Return true if endWin has been called, with no subsequent call to wRefresh, and false otherwise (i.e. if the terminal is currently in Curses mode)." public Bool isEndWin() = isendwin; Bool dotesterr(Ptr x) = testerr; "Refresh the screen Refresh the screen, painting any updates since the last refresh. This is equivalent to wRefresh(stdscr);. stdscr wRefresh" public Void refresh() = dorefresh; Void dowrefresh(Ptr win) = dowrefresh; "Get a character Get the next input character. If the screen has been modified, then refresh will automatically be called first. getStr mvgetChar wmvgetChar refresh ungetChar wgetChar" public Char getChar() = dogetch; Char dowgetch(Ptr w) = dowgetch; "New row position of cursor New column position of cursor Move and get a character Move the cursor to the given co-ordinates, and get the next input character. getChar wmvgetChar ungetChar wgetChar" public Char mvgetChar(Int y, Int x) = domvgetch; Char dowmvgetch(Ptr w,Int y, Int x) = dowmvgetch; "The character to unget Unget a character Unget a character. This character will then be the next character returned by a call to getChar. getChar mvgetChar wmvgetChar wgetChar" public Void ungetChar(Char c) = ungetch; "Get an input string up to newline Get an input string up to newline, or a maximum length of 255 characters. getChar wgetStr" public String getStr() = dogetstr; String dowgetstr(Ptr w) = dowgetstr; "New row position New column position Move the cursor Move the cursor to the new position. mvgetChar wMove" public Void move(Int y, Int x) = domove; Void dowmove(Ptr w, Int y, Int x) = dowmove; "The string to print Print a string Print a string at the current cursor position. waddStr" public Void addStr(String s) = doaddstr; Void dowaddstr(Ptr w, String s) = dowaddstr; Ptr doattron([Attr] attribs) = doattron; Ptr doattroff([Attr] attribs) = doattroff; Ptr dowattron(Ptr w, [Attr] attribs) = dowattron; Ptr dowattroff(Ptr w, [Attr] attribs) = dowattroff; "Enable colours Enable colours (has no effect if the terminal does not support colour) hasColours" public Void startColour() = start_color; "Check for support for colours Returns true if the current terminal has colour support, false otherwise. startColour" public Bool hasColours() = has_colors; Ptr doinit_colour(Int col, Int r, Int g, Int b) = init_color; Ptr doinit_pair(Int pair, Int f, Int b) = init_pair; "Black colour Return the Int corresponding to the colour black. Blue ColourPairs Colours Cyan Green initPair initColour Magenta Red White Yellow" public Int Black() = getBlack; "Red colour Return the Int corresponding to the colour red. Black Blue ColourPairs Colours Cyan Green initPair initColour Magenta White Yellow" public Int Red() = getRed; "Green colour Return the Int corresponding to the colour green. Black Blue ColourPairs Colours Cyan initPair initColour Magenta Red White Yellow" public Int Green() = getGreen; "Yellow colour Return the Int corresponding to the colour yellow. Black Blue ColourPairs Colours Cyan Green initPair initColour Magenta Red White" public Int Yellow() = getYellow; "Blue colour Return the Int corresponding to the colour blue. Black ColourPairs Colours Cyan Green initPair initColour Magenta Red White Yellow" public Int Blue() = getBlue; "Magenta colour Return the Int corresponding to the colour magenta. Black Blue ColourPairs Colours Cyan Green initPair initColour Red White Yellow" public Int Magenta() = getMagenta; "Cyan colour Return the Int corresponding to the colour cyan. Black Blue ColourPairs Colours Cyan Green initPair initColour Magenta Red White Yellow" public Int Cyan() = getCyan; "White colour Return the Int corresponding to the colour white. Black Blue ColourPairs Colours Cyan Green initPair initColour Magenta Red Yellow" public Int White() = getWhite; "Number of supported colour pairs Return the maximum number of colour pairs supported by the terminal initPair" public Int ColourPairs() = getColourPairs; "Number of supported colours Return the maximum number of distinct colours supported by the terminal initColour" public Int Colours() = getColours; Ptr donewwin(Int lines,Int cols, Int beginy, Int beginx) = donewwin; Ptr dodelwin(Ptr w) = dodelwin; Ptr domvwin(Ptr w, Int y, Int x) = domvwin; Ptr docurs_set(Int x) = docurs_set; "Down arrow key Return the Char constant corresponding to the down arrow key getch" public Char KeyDown() = key_DOWN; "Up arrow key Return the Char constant corresponding to the up arrow key getch" public Char KeyUp() = key_UP; "Left arrow key Return the Char constant corresponding to the left arrow key getch" public Char KeyLeft() = key_LEFT; "Right arrow key Return the Char constant corresponding to the right arrow key getch" public Char KeyRight() = key_RIGHT; "Home key Return the Char constant corresponding to the home key. On some keyboards this may also correspond to Numpad 7 getch" public Char KeyHome() = key_HOME; "End key Return the Char constant corresponding to the end key. On some keyboards this may also correspond to Numpad 1 getch" public Char KeyEnd() = key_END; "Page up key Return the Char constant corresponding to the previous page (page up) key. On some keyboards this may also correspond to Numpad 9 getch" public Char KeyPPage() = key_PPAGE; "Page down key Return the Char constant corresponding to the next page (page down) key. On some keyboards this may also correspond to Numpad 3 getch" public Char KeyNPage() = key_NPAGE; "Backspace key Return the Char constant corresponding to the backspace key. getch" public Char KeyBackspace() = key_BACKSPACE; "A1 key Return the Char constant corresponding to the A1 key (the top-left keypad key) getch" public Char KeyA1() = key_A1; "A3 key Return the Char constant corresponding to the A3 key (the top-right keypad key) getch" public Char KeyA3() = key_A3; "B2 key Return the Char constant corresponding to the B2 key (the centre keypad key) getch" public Char KeyB2() = key_B2; "C1 key Return the Char constant corresponding to the C1 key (the bottom-left keypad key) getch" public Char KeyC1() = key_C1; "C3 key Return the Char constant corresponding to the C3 key (the bottom-right keypad key) getch" public Char KeyC3() = key_C3; "Function key 1 Return the Char constant corresponding to the first function key (F1) getch" public Char KeyF1() = key_F1; "Function key 2 Return the Char constant corresponding to the second function key (F2) getch" public Char KeyF2() = key_F2; "Function key 3 Return the Char constant corresponding to the third function key (F3) getch" public Char KeyF3() = key_F3; "Function key 4 Return the Char constant corresponding to the fourth function key (F4) getch" public Char KeyF4() = key_F4; "Function key 5 Return the Char constant corresponding to the fifth function key (F5) getch" public Char KeyF5() = key_F5; "Function key 6 Return the Char constant corresponding to the sixth function key (F6) getch" public Char KeyF6() = key_F6; "Function key 7 Return the Char constant corresponding to the seventh function key (F7) getch" public Char KeyF7() = key_F7; "Function key 8 Return the Char constant corresponding to the eighth function key (F8) getch" public Char KeyF8() = key_F8; "Function key 9 Return the Char constant corresponding to the ninth function key (F9) getch" public Char KeyF9() = key_F9; "Function key 10 Return the Char constant corresponding to the tenth function key (F10) getch" public Char KeyF10() = key_F10; "Function key 11 Return the Char constant corresponding to the eleventh function key (F11) getch" public Char KeyF11() = key_F11; "Function key 12 Return the Char constant corresponding to the twelth function key (F12) getch" public Char KeyF12() = key_F12; Ptr dobox(Ptr w, Char v, Char h) = dobox; "Beep to alert the user Beep to alert the user if possible, otherwise flash, otherwise do nothing." public Void beep() = beep; "Flash the screen to alert the user Flash the screen to alert the user if possible, otherwise beep, otherwise do nothing." public Void flash() = flash; Void doclear() = doclear; Void doerase() = doerase; Void doclrtobot() = doclrtobot; Void doclrtoeol() = doclrtoeol; Void dowclear(Ptr p) = dowclear; Void dowerase(Ptr p) = dowerase; Void dowclrtobot(Ptr p) = dowclrtobot; Void dowclrtoeol(Ptr p) = dowclrtoeol; } "True to enable, false to disable Enable or disable cbreak mode Enable or disable cbreak mode (character-at-a-time input). Most interactive Curses programs should enable this. rawMode" public Void cbreakMode(Bool enable) { if (enable) { cbreak(); } else { nocbreak(); } } "True to enable, false to disable Enable or disable echo Enable or disable echoing of typed characters to the screen. Most interactive Curses programs should disable this." public Void echoMode(Bool enable) { if (enable) { echo(); } else { noecho(); } } "True to enable, false to disable Enable or disable return key to newline translation Enable or disable return key to newline translation. Disabling this allows the return key to be detected as a separate key, and may be slightly more efficient, but possibly less convenient." public Void newlineMode(Bool enable) { if (enable) { nl(); } else { nonl(); } } "True to enable, false to disable Enable or disable raw mode Raw mode is similar to cbreak mode, but when enabled interrupt, quit, suspend and flow control characters are passed straight through to the program rather than generating signals. cbreakMode" public Void rawMode(Bool enable) { if (enable) { raw(); } else { noraw(); } } "Curses Error This Exception is thrown when an error occurs in Curses functions." Exception CursesError(); "Can't create Window This Exception is thrown when newwin cannot create a new window." Exception CantCreateWindow(); "Return the standard screen This function returns the Window object corresponding to the standard screen." public Window stdscr = Window(getstdscr()); "The window to apply to (in ncurses, this argument is ignored: use stdscr) Whether interrupt flushing should be enabled. Enable or disable interrupt flushing Enable or disable interrupt flushing. If this is enabled, then all output in the terminal driver will be flushed when an interrupt (e.g. break) is received, giving an apparent faster response, but causing the curses library to not know what is currently on-screen." public Void intrFlush(Window win, Bool bf) { dointrflush(win.ptr,bf); } "The window to apply to Whether to enable the keypad Enable or disable the keypad Enable or disable the keypad. If the keypad is enabled, then curses will translate keypad keys to their character constants (e.g. KeyA3). Otherwise, the raw escape sequences will be returned. This function does nothing on Windows" public Void keypad(Window win, Bool bf) { dokeypad(win.ptr,bf); } "The window to apply to Whether to enable 8 bit input Enable or disable 8 bit input Enable or disable 8 bit input." public Void meta(Window win, Bool bf) { dometa(win.ptr,bf); } "The window to apply to Whether wgetch will wait for input. Enable non-blocking input Enable or disable non-blocking input. If this is enabled and no input is waiting, then getch will return ERR (probably -1). If it is disabled, then getch will wait for input. This function does nothing on Windows halfDelay" public Void noDelay(Window win, Bool bf) { donodelay(win.ptr,bf); } "The window to apply to Whether to disable timeouts on escape sequences Disable escape sequence timeout If escape sequence timeouts are enabled, then curses will timeout and return the raw characters if a partial escape sequence has too much delay before the next character. This is usually useful, but may be inconvenient where users are manually entering escape sequences." public Void noTimeout(Window win, Bool bf) { donotimeout(win.ptr,bf); } /// Screen initialisation and manipulation Void testerr(Ptr x) { // putStrLn("testing "+x); if (dotesterr(x)) { throw(CursesError()); } } "Initialise curses Initialise the curses library. This must be called before any other function is called. endWin" public Void initScreen { testerr(doinitscr()); } "End curses windowing End curses windowing. This should always be called before the program exits, regardless of the cause of the exit. Note that the Curses library changes the buffering of standard output, and so functions such as Prelude::putStr will not always work as expected. If you need to output further text after Curses windowing is ended but before the program finishes, and it is important that this text is immediately visible, then use IO::flush on stdout initscr" public Void endWin { testerr(doendwin()); } "The window to refresh Refresh a window Refresh a window, painting any updates since the last refresh. refresh" public Void wRefresh(Window w) { dowrefresh(w.ptr); } /// Get characters "The window to get from Get a character in a window Get a character from a particular window (and so refresh only that window instead of the whole screen). getChar mvgetChar ungetChar wmvgetChar" public Char wgetChar(Window w) = dowgetch(w.ptr); "The window to get from The new row position The new column position Move and get a character in a window Move the cursor to the new position and get a character from a particular window (and so refresh only that window instead of the whole screen). getChar mvgetChar ungetChar wgetChar" public Char wmvgetChar(Window w,Int y, Int x) = dowmvgetch(w.ptr,y,x); "The window to get from Get an input string up to newline from a window Get an input string up to newline, or a maximum length of 255 characters. getStr wgetChar" public String wgetStr(Window w) = dowgetstr(w.ptr); /// Move "The window to move in New row position (relative to the top-left corner of the window) New column position (relative to the top-left corner of the window) Move the cursor within a window Move the cursor to the new position in the window. wmvgetChar move" public Void wMove(Window w, Int y, Int x) = dowmove(w.ptr,y,x); /// Add strings "The window to print within The string to print Print a string in a window Print a string at the current cursor position in the specified window. addStr" public Void waddStr(Window win, String s) { dowaddstr(win.ptr,s); } /// Attributes "A list of Attr to enable or disable True to enable, false to disable Enable or disable text attributes Enables or disables the specified text attributes for future addStr operations. wAttributes" public Void attributes([Attr] attribs, Bool enable) { if (enable) { testerr(doattron(attribs)); } else { testerr(doattroff(attribs)); } } "The window A list of Attr to enable or disable True to enable, false to disable Enable or disable text attributes in a window Enables or disables the specified text attributes for future waddStr operations in this window. wAttributes" public Void wAttributes(Window w, [Attr] attribs, Bool enable) { if (enable) { testerr(dowattron(w.ptr,attribs)); } else { testerr(dowattroff(w.ptr,attribs)); } } "The colour number to redefine (0 to Colours) The new red channel value (0-1000) The new green channel value (0-1000) The new blue channel value (0-1000) Initialise a new colour Initialise a new colour, or change an existing colour, provided that the terminal supports this operation. initPair" public Void initColour(Int col, Int r, Int g, Int b) { testerr(doinit_colour(col,r,g,b)); } "The pair number to redefine (0 to ColourPairs) The foreground colour (either a constant such as Blue or one defined with initColour) The background colour (either a constant such as Blue or one defined with initColour) Define a colour pair Define a colour pair. These can then be used as text attributes using the ColourPair constructor of Attr Black Blue ColourPairs Colours Cyan Green initPair initColour Magenta Red White Yellow" public Void initPair(Int pair, Int f, Int b) { testerr(doinit_pair(pair,f,b)); } // Windows "Number of lines in window Number of columns in window Position of top of window Position of left of window Create a new window Create a new window at the specified position. Window delWin mvWin" public Window newWin(Int lines,Int cols, Int beginy, Int beginx) { win = donewwin(lines,cols,beginy,beginx); if (null(win)) { throw(CantCreateWindow()); } else return Window(win); } "Window to delete Delete a window Delete a window (any current window contents will remain on the screen). Window mvWin newWin" public Void delwin(Window w) { testerr(dodelwin(w.ptr)); } "Window to move New position of top edge New position of left edge Move a window Move a window to the new position. This will fail if it would move the window off the screen. Window delWin newWin" public Void mvWin(Window w, Int y, Int x) { testerr(domvwin(w.ptr,y,x)); } // Low level routines "Cursor visibility Cursor visibility levels curs_set" public data Visibility = Invisible | NormalVisible | VeryVisible; "New cursor visibility Set cursor visibility Set the new cursor visiblity level. This function always fails and throws an Exception on Windows Visibility" public Void setCursor(Visibility mode) { x = case mode of { Invisible -> 0; | NormalVisible -> 1; | VeryVisible -> 2; }; testerr(docurs_set(x)); } // Borders R"The window to draw a box border on The character to use on the vertical sides (the default, '\0', uses the curses default) The character to use on the horizontal sides (the default, '\0', uses the curses default) Draw a box border on a window Draw a box border around the edges of the specified window" public Void box(Window w, Char v = '\0', Char h = '\0') { testerr(dobox(w.ptr,v,h)); } // Clearing "Clear screen Clear the screen, repainting completely on refresh. clearDown clearRight erase wClear" public Void clear() { doclear(); } "Erase screen Erase the screen by writing blanks to all character positions. clear clearDown clearRight wErase" public Void erase() { doerase(); } "Clear to bottom of screen Clear all lines below the current cursor, and everything to the right of the cursor on the current line. clear clearRight erase wClearDown" public Void clearDown() { doclrtobot(); } "Clear to end of line Clear everything to the right of the cursor on the current line. clear clearDown erase wClearRight" public Void clearRight() { doclrtoeol(); } "The window to apply to Clear window Clear the window, repainting completely on refresh. Window clear wClearDown wClearRight wErase" public Void wClear(Window w) { dowclear(w.ptr); } "The window to apply to Erase window Erase the window by writing blanks to all character positions. Window erase wClear wClearDown wClearRight" public Void wErase(Window w) { dowerase(w.ptr); } "The window to apply to Clear to bottom of window Clear all lines below the current cursor within the window, and everything to the right of the cursor on the current line. Window clearDown wClear wClearRight wErase" public Void wClearDown(Window w) { dowclrtobot(w.ptr); } "The window to apply to Clear to end of line in a window Clear everything to the right of the cursor in the current window on the current line. Window clearRight wClear wClearDown wErase" public Void wClearRight(Window w) { dowclrtoeol(w.ptr); } kaya-0.4.4/libs/Curses.head0000644000175100017510000000172511170340770013575 0ustar cimcim/** -*-C-*-ish Curses module Copyright (C) 2004-2007 Edwin Brady, Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Curses terminal control library interface This module provides an interface to the ncurses (on Linux) or pdcurses (on Windows) terminal control library. An alternate interfaces is provided by CursesW (which should be used if multi-byte characters - i.e. characters Char(128) and above - are needed) The initscr must be called before most of the functions in this module will work, and endwin must be called before program exit. The Kayurses module provides a higher-level interface to the curses functions." module Curses; import Prelude; %include "curses_glue.h"; %imported "curses_glue"; %link "curses"; kaya-0.4.4/libs/SDL.k0000644000175100017510000003047511170340770012310 0ustar cimcim"Interface to the Simple DirectMedia Layer This module is under development and the interface may change. SDL provides a low-level interface to video output, and keyboard and mouse input. This module currently supports making windowed or full-screen graphical applications, reading keyboard and mouse input, and displaying the contents of BMP graphics. See the examples/sdl directory in the Kaya distribution for a simple example program." module SDL; import Prelude; import Builtins; %include "sdl_glue.h"; %imported "sdl_glue"; %link "SDL"; "An illegal display mode was selected An illegal display mode was selected" Exception IllegalMode; "A BMP file could not be loaded There was an error loading a BMP file. More information on the error may be available from sdlError." Exception LoadingError; "The SDL application quit The SDL application quit. This is usually caused by the window containing the application being closed." Exception SDLQuit; "An SDL surface This data type represents an SDL surface. This may be the screen, or it may be a bitmap loaded for use with blitSurface." abstract data SDLSurface(Ptr ptr); // should check that width, height are positive "A rectangle A rectangle for display. left and top represent the distance of the top-left corner of the rectangle from the top-left corner of the surface. width and height are the width and height of the rectangle (and may not be negative). All values are measured in pixels." public data Rect(Int left, Int top, Int width, Int height); "An input event An input event - either a key being pressed, the mouse being moved to a particular location, or a mouse button being pressed while the mouse is at a particular location. The left mouse button is usually button 1, with the right button given number 2. In theory, a sufficiently large mouse could go up to button 255. The KeyModifier list allows detection of whether particular modifier keys are pressed, allowing combinations such as 'Ctrl-Numpad7' to be detected. SDLKey" public data SDLEvent = KeyDown(SDLKey key, [KeyModifier] modifiers) | MouseMove(Int x, Int y) | MouseButton(Int button, Int bx, Int by); "A key modifier Represents a modifier key being pressed at the same time as the key. SDLEvent SDLKey" public data KeyModifier = ModShift | ModCtrl | ModAlt | ModMeta; "A colour depth. A colour depth in bits per pixel." public data BPP = BPP8 | BPP15 | BPP16 | BPP24 | BPP32; "A colour A colour in RGBA format. Each component varies between 0 and 255 (from darkest to brightest for colours, and from opaque to transparent for alpha)" public data SDLColour(Int r, Int g, Int b, Int a); "A key press A key press. Most keys are represented by NormalKey, which contains the key in Char form. Numeric pad numbers are represented using NumpadKey, and function keys with FunctionKey. Additional constructors represent other special keys such as 'Page up' or 'Left arrow'. If the key is unrecognised, UnknownKey is returned." public data SDLKey = UnknownKey | NormalKey(Char c) | NumpadKey(Int n) | FunctionKey(Int f) | ArrowUpKey | ArrowDownKey | ArrowLeftKey | ArrowRightKey | InsertKey | HomeKey | EndKey | PageUpKey | PageDownKey; foreign "libsdl" { "Describe SDL error Get a text description of the most recent SDL error. Useful for debugging." public String sdlError() = do_sdlerror; "Initialise SDL libraries Initialise the SDL libraries. This must be called before any other functions are used." public Void sdlInit() = sdl_init; "Shutdown SDL libraries Shutdown the SDL libraries. You should always call this before the program exits. Remember to catch the SDLQuit exception." public Void sdlQuit() = SDL_Quit; Ptr do_newSurface(Ptr vm, Int x, Int y, Int bpp, Int flags) = do_newsurface; Void do_SDLFlip(Ptr screen) = do_sdlflip; Ptr do_loadSurface(Ptr vm, String file) = do_loadsurface; Int do_SDLblit(Ptr src, Ptr dest, Int sl, Int st, Int sw, Int sh, Int dl, Int dt, Int dw, Int dh) = do_sdlblit; Ptr do_waitevent() = do_waitevent; Int event_type(Ptr p) = event_type; Int do_getkeynum(Ptr p) = do_getkeynum; Int do_getkeymod(Ptr p) = do_getkeymod; Int do_getmmx(Ptr p) = do_getmmx; Int do_getmmy(Ptr p) = do_getmmy; Int do_getmpx(Ptr p) = do_getmpx; Int do_getmpy(Ptr p) = do_getmpy; Int do_getmbp(Ptr p) = do_getmbp; Void do_sdltransparency(Ptr p, Int r, Int g, Int b, Int a) = do_sdltransparency; Void do_drawRect(Ptr p, Int l, Int t, Int w, Int h, Int r, Int g, Int b, Int a) = do_drawrect; "The window title The icon title Set window title Set the window title and icon title for this application in the window manager. setWMIcon" public Void setWMTitle(String wmtitle, String icontitle) = do_setwmtitles; Void do_seticon(Ptr ptr) = do_seticon; } "The icon surface Set window icon Set the window icon for this application in the window manager. setWMTitle" public Void setWMIcon(SDLSurface icon) { do_seticon(icon.ptr); } "The width of the screen in pixels The height of the screen in pixels The colour depth (may be ignored if not fullscreen) Whether to display fullscreen (if true) or windowed (if false). This parameter may be ignored in some graphical environments. Create a new display window or screen This function creates a new display window or screen with the specified parameters. You must create one of these to display any output." public SDLSurface newSurface(Int x, Int y, BPP bpp, Bool fullscreen) { case bpp of { BPP8 -> bppi = 8; | BPP15 -> bppi = 15; | BPP16 -> bppi = 16; | BPP24 -> bppi = 24; | BPP32 -> bppi = 32; } if (fullscreen) { flags = 1; } else { flags = 0; } try { p = do_newSurface(getVM,x,y,bppi,flags); return SDLSurface(p); } catch(e) { throw(IllegalMode); } } "The SDLSurface representing the screen Update the screen Update any changes made since the last update to the screen. This function is relatively slow, so try to avoid calling it unnecessarily." public Void updateScreen(SDLSurface screen) { do_SDLFlip(screen.ptr); } "The surface to fill The rectangle on the surface to fill The colour to fill Draw a filled rectangle Draw a filled rectangle of the specified colour on the surface Rect SDLColour SDLSurface" public Void drawRectangle(SDLSurface surface, Rect rect, SDLColour colour) { do_drawRect(surface.ptr,rect.left,rect.top,rect.width,rect.height,colour.r,colour.g,colour.b,colour.a); } "The filename of a windows bitmap (BMP format) image file. Load an image file Load the specified image file into a new surface. You can then copy all or part of this image file onto another surface (often the screen) using blitSurface." public SDLSurface loadSurface(String file) { try { p = do_loadSurface(getVM,file); return SDLSurface(p); } catch(e) { throw(LoadingError); } } "The surface to set The RGBA value of the transparent pixel. Generally A will be 255 Set surface transparency Select a particular colour on the surface to be considered transparent when copying the surface. setTransparency(pic,RGBA(0,255,0,255)); // green is transparent" public Void setTransparency(SDLSurface surface, SDLColour rgba) { do_sdltransparency(surface.ptr,rgba.r,rgba.g,rgba.b,rgba.a); } "The source surface The portion of the source surface to copy The destination surface The location on the destination surface to copy to (the width and height of this rectangle are ignored) Copy from one surface to another Copy a rectangle of pixels from one surface to another, for example from a loaded image to the screen. screen = newSurface(640,480,BPP24,false); pic = loadSurface(\"mypic.bmp\"); blitSurface(pic,Rect(0,0,40,40),screen,Rect(200,200,px,py)); updateScreen(screen); If you are copying to the screen surface, remember that these updates will not be displayed until you call updateScreen. Rect loadSurface newSurface updateScreen" public Void blitSurface(SDLSurface src, Rect srcrect, SDLSurface dest, Rect destrect) { r = do_SDLblit(src.ptr,dest.ptr, srcrect.left,srcrect.top,srcrect.width,srcrect.height, destrect.left,destrect.top,destrect.width,destrect.height); if (r != 0) { putStrLn("Failed "+r); // debugging, should throw an exception } } "Get the next input event Get the next input event. Currently key presses, mouse movements, and mouse button presses are supported. An SDLQuit Exception will be thrown if the application window is closed. You should catch this, and run appropriate program shutdown routines, including sdlQuit." public SDLEvent nextEvent() { p = do_waitevent(); case event_type(p) of { 0 -> return nextEvent(); // ignoring this type of event | 1 -> return keypressEvent(p); | 3 -> return mousemoveEvent(p); | 4 -> return mousebuttonEvent(p); | 6 -> throw(SDLQuit); } // never here } //public data SDLKey = NormalKey(Char c) | NumpadKey(Int n) | FunctionKey(Int f) | ArrowUpKey | ArrowDownKey | ArrowLeftKey | ArrowRightKey | InsertKey | HomeKey | EndKey | PageUpKey | PageDownKey; SDLEvent keypressEvent(Ptr p) { n = do_getkeynum(p); if (n>0) { k = NormalKey(Char(n)); } else if (n == 0) { k = UnknownKey; } else if (n > -11) { k = NumpadKey(abs(n)%10); } else if (n == -11) { k = ArrowUpKey; } else if (n == -12) { k = ArrowDownKey; } else if (n == -13) { k = ArrowLeftKey; } else if (n == -14) { k = ArrowRightKey; } else if (n == -15) { k = InsertKey; } else if (n == -16) { k = HomeKey; } else if (n == -17) { k = EndKey; } else if (n == -18) { k = PageUpKey; } else if (n == -19) { k = PageDownKey; } else if (n <= -21 && n > -40) { k = FunctionKey(-20-n); } else { k = UnknownKey; } return KeyDown(k,keyMods(p)); } [KeyModifier] keyMods(Ptr p) { i = do_getkeymod(p); mods = createArray(4); if ((i & 1) > 0) { push(mods,ModShift); } if ((i & 2) > 0) { push(mods,ModCtrl); } if ((i & 4) > 0) { push(mods,ModAlt); } if ((i & 8) > 0) { push(mods,ModMeta); } return mods; } SDLEvent mousemoveEvent(Ptr p) { return MouseMove(do_getmmx(p),do_getmmy(p)); } SDLEvent mousebuttonEvent(Ptr p) { return MouseButton(do_getmbp(p),do_getmpx(p),do_getmpy(p)); } kaya-0.4.4/libs/thread_glue.h0000644000175100017510000000111211170340770014130 0ustar cimcim#ifndef _THREAD_H // -*-C++-*- #define _THREAD_H #include #include class ThreadData : public gc { public: pthread_t t_id; }; class ThreadStartup : public gc { public: Value* fn; Value* arg; }; class ThreadMutex : public gc { public: pthread_mutex_t m_id; }; extern "C" { void* createThread(Value* fn,Value* arg); void* createThreadNullary(Value* fn); void endThread(); Value* waitForThread(void* tid); void killThread(void* tid); void* createMutex(); void lock(void* mutex); void unlock(void* mutex); } #endif kaya-0.4.4/libs/SQLiteDB.k0000644000175100017510000001152011170340770013223 0ustar cimcim/** -*-C-*-ish SQLite interface library for Kaya Copyright (C) 2006 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "SQLite database interface module This module allows querying of SQLite database files, using the standard DB API." module SQLiteDB; import Builtins; // SQLite API suitable for use with the DB module. // sqlite3_bind_* import Prelude; import public DB; %include "sqlite_inter.h"; %imported "sqlite_inter"; %link "sqlite3"; "An SQLite database connection This data type holds information about a database connection. The type SQLiteDB is a type synonym for DB::DBHandle<SQLiteConnection> DB" abstract data SQLiteConnection = SQLiteCon(Ptr cdata); type SQLiteDB = DBHandle; "The String contains the error message Database error This Exception is thrown if an error occurs while opening or querying a database file." Exception SQLiteError(String msg); "Tried to read too many rows This Exception is thrown if you try to read more rows from an incremental database query than actually exist." Exception TooManyRows(); foreign "sqlite_inter.o" { Ptr do_sqlite_connect(String info) = sqlite_connect; Bool sqlite_ok(Ptr con) = sqlite_ok; String sqlite_getError(Ptr con) = sqlite_getError; Void sqlite_close(Ptr con) = sqlite_close; Ptr sqlite_exec(Ptr con, String query) = sqlite_exec; Ptr sqlite_incexec(Ptr con, String query) = sqlite_incexec; [DBValue] sqlite_getrow(Ptr vm, Ptr res) = sqlite_getrow; Void sqlite_discard(Ptr res) = sqlite_discard; Ptr sqlite_execp(Ptr con, [Maybe] params) = sqlite_execp; Ptr do_sqliprepare(Ptr vm, Ptr con, String query) = sqlite_prepare; [[DBValue]] sql_getrestable(Ptr pr) = sql_getrestable; [String] sql_getcolnames(Ptr pr) = sql_getcolnames; Int sql_numrows(Ptr pr) = sql_numrows; Int sql_numcols(Ptr pr) = sql_numcols; Int sql_resrc(Ptr pr) = sql_resrc; } "The filename of the database Open a database file. Use this function to open the database file (creating it if it does not exist). You can then use the functions from DB to query the database. db = SQLiteDB::connect(\"site.db\"); res = exec(db,\"SELECT * FROM pagedata WHERE page_id = 10\"); DB" public SQLiteDB connect(String fname) { sqlc = do_sqlite_connect(fname); con = SQLiteCon(sqlc); if (sqlite_ok(sqlc)==false) { throw(SQLiteError(sqlite_getError(sqlc))); } return DBh(con, sqli_exec, sqli_incexec, sqli_prepare, sqli_execp, defaultIncExecPrepared, sqli_getrow, sqli_discard, sqli_close); } "Execute a query on the given connection." DBResult sqli_exec(SQLiteConnection con, String query) { rc = sqlite_exec(con.cdata, query); if (sql_resrc(rc)==0) { dbvs = sql_getrestable(rc); rows = sql_numrows(rc); cols = sql_numcols(rc); colnames = sql_getcolnames(rc); return DBRes(dbvs, rows, cols, colnames, rc); } else { throw(SQLiteError(sqlite_getError(con.cdata))); } } DBIncResult sqli_incexec(SQLiteConnection con, String query, SQLiteDB dbc) { rc = sqlite_incexec(con.cdata, query); if (sql_resrc(rc)==0) { rows = sql_numrows(rc); cols = sql_numcols(rc); colnames = sql_getcolnames(rc); return DBIncRes(dbc, rows, cols, colnames, rc); } else { throw(SQLiteError(sqlite_getError(con.cdata))); } } [DBValue] sqli_getrow(DBIncResult res) { try { return sqlite_getrow(getVM(),res.resptr); } catch(InternalError(e)) { if (e==0) { throw(TooManyRows()); } else throw(InternalError(e)); } } Void sqli_discard(DBIncResult res) { sqlite_discard(res.resptr); } "Close a connection to the database." Void sqli_close(SQLiteConnection con) { sqlite_close(con.cdata); } DBStatement sqli_prepare(SQLiteDB con, String query) { try { return DBStatement(con,do_sqliprepare(getVM,con.handle.cdata,query)); } catch(InternalError(e)) { throw(SQLiteError(sqlite_getError(con.handle.cdata))); } } DBResult sqli_execp(DBStatement prep, [Maybe] params) { rc = sqlite_execp(prep.statement, params); if (sql_resrc(rc)==0) { dbvs = sql_getrestable(rc); rows = sql_numrows(rc); cols = sql_numcols(rc); colnames = sql_getcolnames(rc); return DBRes(dbvs, rows, cols, colnames, rc); } else { throw(SQLiteError(sqlite_getError(prep.con.handle.cdata))); } } kaya-0.4.4/libs/sdl_glue.cc0000644000175100017510000001055711170340770013616 0ustar cimcim#include "sdl_glue.h" wchar_t* do_sdlerror() { return KSTRING(SDL_GetError()); } void sdl_init() { SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO); SDL_EnableUNICODE(1); } void* do_newsurface(void* vmptr, kint x, kint y, kint bpp, kint flags) { VMState* vm = (VMState*) vmptr; int sdlflags = (flags*SDL_FULLSCREEN)|SDL_HWSURFACE|SDL_DOUBLEBUF; SDL_Surface* s = SDL_SetVideoMode(x,y,bpp,sdlflags); if (s == NULL) { vm->kaya_internalError(1); } return (void*)s; } void* do_loadsurface(void* vmptr, wchar_t* rawfn) { char* fn = CSTRING(rawfn); VMState* vm = (VMState*) vmptr; SDL_Surface* s = SDL_LoadBMP(fn); if (s == NULL) { vm->kaya_internalError(1); } return (void*)s; } void do_sdlflip(void* screen) { SDL_Surface* s = (SDL_Surface*)screen; SDL_Flip(s); } int do_sdlblit(void* srcptr, void* destptr, kint sl, kint st, kint sw, kint sh, kint dl, kint dt, kint dw, kint dh) { SDL_Surface* src = (SDL_Surface*)srcptr; SDL_Surface* dest = (SDL_Surface*)destptr; SDL_Rect srcrect = {sl,st,sw,sh}; SDL_Rect destrect = {dl,dt,dw,dh}; return SDL_BlitSurface(src,&srcrect,dest,&destrect); } void* do_waitevent() { SDL_Event* event = (SDL_Event*)GC_MALLOC(sizeof(SDL_Event)); int r = SDL_WaitEvent(event); return (void*)event; } kint event_type(void* eptr) { SDL_Event* e = (SDL_Event*)eptr; switch(e->type) { case SDL_KEYDOWN: return 1; // case SDL_KEYUP: return 2; case SDL_MOUSEMOTION: return 3; case SDL_MOUSEBUTTONDOWN: return 4; // case SDL_MOUSEBUTTONUP: return 5; case SDL_QUIT: return 6; } return 0; } kint do_getkeymod(void* eptr) { SDL_Event* e = (SDL_Event*)eptr; SDLMod m = e->key.keysym.mod; kint r = 0; if (m & KMOD_SHIFT) r+=1; if (m & KMOD_CTRL) r+=2; if (m & KMOD_ALT) r+=4; if (m & KMOD_META) r+=8; return r; } kint do_getkeynum(void* eptr) { SDL_Event* e = (SDL_Event*)eptr; switch (e->key.keysym.sym) { case SDLK_KP1: return -1; case SDLK_KP2: return -2; case SDLK_KP3: return -3; case SDLK_KP4: return -4; case SDLK_KP5: return -5; case SDLK_KP6: return -6; case SDLK_KP7: return -7; case SDLK_KP8: return -8; case SDLK_KP9: return -9; case SDLK_KP0: return -10; case SDLK_UP: return -11; case SDLK_DOWN: return -12; case SDLK_LEFT: return -13; case SDLK_RIGHT: return -14; case SDLK_INSERT: return -15; case SDLK_HOME: return -16; case SDLK_END: return -17; case SDLK_PAGEUP: return -18; case SDLK_PAGEDOWN: return -19; // no -20 yet case SDLK_F1: return -21; case SDLK_F2: return -22; case SDLK_F3: return -23; case SDLK_F4: return -24; case SDLK_F5: return -25; case SDLK_F6: return -26; case SDLK_F7: return -27; case SDLK_F8: return -28; case SDLK_F9: return -29; case SDLK_F10: return -30; case SDLK_F11: return -31; case SDLK_F12: return -32; // reserved until -40 } return (kint)e->key.keysym.unicode; } kint do_getmmx(void* eptr) { SDL_Event* e = (SDL_Event*)eptr; return (kint)e->motion.x; } kint do_getmmy(void* eptr) { SDL_Event* e = (SDL_Event*)eptr; return (kint)e->motion.y; } kint do_getmpx(void* eptr) { SDL_Event* e = (SDL_Event*)eptr; return (kint)e->button.x; } kint do_getmpy(void* eptr) { SDL_Event* e = (SDL_Event*)eptr; return (kint)e->button.y; } kint do_getmbp(void* eptr) { SDL_Event* e = (SDL_Event*)eptr; return (kint)e->button.button; } void do_setwmtitles(wchar_t* window, wchar_t* icon) { SDL_WM_SetCaption(CSTRING(window),CSTRING(icon)); } void do_sdltransparency(void* sptr, kint r, kint g, kint b, kint a) { SDL_Surface* s = (SDL_Surface*)sptr; Uint8 rv = (Uint8)r; Uint8 gv = (Uint8)g; Uint8 bv = (Uint8)b; Uint8 av = (Uint8)a; Uint32 key = SDL_MapRGB(s->format,rv,gv,bv); // slightly annoying to need to do this, since if SDL change their pixel // format it will hurt... key = key | (av<<24); // cout << key << endl; // SDL_SetAlpha(s,0,SDL_ALPHA_OPAQUE); SDL_SetColorKey(s,SDL_SRCCOLORKEY,key); } void do_drawrect(void* sptr, kint l, kint t, kint w, kint h, kint r, kint g, kint b, kint a) { SDL_Surface* s = (SDL_Surface*)sptr; Uint8 rv = (Uint8)r; Uint8 gv = (Uint8)g; Uint8 bv = (Uint8)b; Uint8 av = (Uint8)a; Uint32 colour = SDL_MapRGB(s->format,rv,gv,bv); SDL_Rect rect = {l,t,w,h}; SDL_FillRect(s,&rect,colour); } void do_seticon(void* sptr) { SDL_Surface* icon = (SDL_Surface*) sptr; SDL_WM_SetIcon(icon,NULL); } kaya-0.4.4/libs/my_inter.cc0000644000175100017510000002036311170340770013642 0ustar cimcim/** -*-C-*-ish MySQL interface library for Kaya Copyright (C) 2005,2006 Chris Morris Based on the Postgres interface library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. When linked against a version of libmysqlclient that is GPL licensed then you must either use section 3 of the LGPL to change the copy used for linking to GPL, or use the FLOSS Exception published by MySQL if that is applicable to your circumstances. */ #include "my_inter.h" #include #include #include MyRes::MyRes() { myres = NULL; rows = 0; cols = 0; colnames = NULL; res_table = NULL; } void* do_mysql_connect(KString rawhost, KString rawuser, KString rawpass, KString rawdb, KInt rawport) { char* host = CSTRING(rawhost); char* user = CSTRING(rawuser); char* pass = CSTRING(rawpass); char* db = CSTRING(rawdb); int port = CINT(rawport); MYSQL* mc = mysql_init(NULL); mc = mysql_real_connect(mc,host,user,pass,db,port,NULL,0); MyCon * myc = new MyCon(); myc->con = mc; myc->ok = 1; if (mc == NULL) { myc->ok = 0; } return (void*)myc; } bool my_ok(void* conn) { MyCon* myc = (MyCon*)conn; // cout << pgc->ok << endl; return myc->ok; } /*wchar_t* pg_getError(void* conn) { PGconn* pgc = ((PGCon*)conn)->con; return strtowc(PQerrorMessage(pgc)); }*/ /* we don't need this function for now, and it needs calling something else when we do bring it back DBtype getDBtype(wchar_t* rawval) { // MySQL doesn't appear to have a convenient type interface return DBTEXT; } */ void* do_mysql_query(void* vmptr,void* conn,KString rawquery) { char* query = CSTRING(rawquery); VMState* vm = (VMState*)vmptr; MyCon* myc = (MyCon*)conn; int success = mysql_query(myc->con,query); if (success!=0) { // TODO: make this more helpful vm->kaya_internalError(1); } MYSQL_RES* res = mysql_store_result(myc->con); MyRes* myr = new MyRes(); if (res != NULL) { int numrows = mysql_num_rows(res); int numflds = mysql_num_fields(res); KayaArray resarray = newKayaArray(numrows); for(int i = 0; i res_table = resarray; myr -> rows = numrows; myr -> cols = numflds; myr -> colnames = colarray; mysql_free_result(res); } return myr; } void* do_mysql_incquery(void* vmptr,void* conn,KString rawquery) { char* query = CSTRING(rawquery); VMState* vm = (VMState*)vmptr; MyCon* myc = (MyCon*)conn; int success = mysql_query(myc->con,query); if (success!=0) { // TODO: make this more helpful vm->kaya_internalError(1); } MYSQL_RES* res = mysql_store_result(myc->con); MyRes* myr = new MyRes(); if (res != NULL) { int numrows = mysql_num_rows(res); int numflds = mysql_num_fields(res); KayaArray colarray = newKayaArray(numflds); MYSQL_FIELD* mfields = mysql_fetch_fields(res); for(int k = 0; k rows = numrows; myr -> cols = numflds; myr -> colnames = colarray; myr -> myres = res; } return myr; } Array* my_getrow(void* vmptr, void* resptr) { VMState* vm = (VMState*)vmptr; MYSQL_RES* res = ((MyRes*)resptr)->myres; int numflds = mysql_num_fields(res); KayaArray row = newKayaArray(numflds); MYSQL_ROW myrow = mysql_fetch_row(res); if (myrow == NULL) { vm->kaya_internalError(2); } for(int j = 0; jmyres; mysql_free_result(res); } Array* my_getstrs(void* res) { return ((MyRes*)res)->res_table; } Array* my_colnames(void* res) { return ((MyRes*)res)->colnames; } int my_numrows(void* res) { return ((MyRes*)res)->rows; } int my_numcols(void* res) { return ((MyRes*)res)->cols; } void do_mysql_close(void* conn) { mysql_close(((MyCon*)conn)->con); } void* do_mysqlprepare(wchar_t* query) { return (void*)CSTRING(query); } void* do_mysql_execp(void* vmptr, void* conn, void* queryptr, KArray params) { char* query = (char*)queryptr; VMState* vm = (VMState*)vmptr; MyCon* myc = (MyCon*)conn; MYSQL_STMT* stmt = mysql_stmt_init(myc->con); int prep = mysql_stmt_prepare(stmt,query,strlen(query)); if (prep!=0) { // TODO: make this more helpful vm->kaya_internalError(1); } int sz = KayaArraySize(params); MYSQL_BIND bind[sz]; unsigned long lens[sz]; memset(bind, 0, sizeof(bind)); my_bool is_true = (my_bool)1; for (int i=0;ikaya_internalError(1); } MYSQL_RES* res = mysql_stmt_result_metadata(stmt); MyRes* myr = new MyRes(); if (res != NULL) { /* CIM: What on earth convinced the MySQL developers that this byzantine mess made a decent C API for prepared statements?! If Postgres and SQLite can have an API where executing a prepared statement returns the results in much the same format as a normal statement, why does MySQL have this mess where you have to know what the statement result rows will contain before you get them... */ int asuccess = mysql_stmt_attr_set(stmt,STMT_ATTR_UPDATE_MAX_LENGTH,&is_true); int ssuccess = mysql_stmt_store_result(stmt); int numrows = mysql_stmt_num_rows(stmt); int numflds = mysql_num_fields(res); KayaArray resarray = newKayaArray(numrows); MYSQL_FIELD* mfields = mysql_fetch_fields(res); MYSQL_BIND rbind[numflds]; memset(rbind, 0, sizeof(rbind)); unsigned long rlength[numflds]; my_bool rnull[numflds]; for(int i=0;i res_table = resarray; myr -> rows = numrows; myr -> cols = numflds; myr -> colnames = colarray; mysql_free_result(res); } return myr; } kaya-0.4.4/libs/PostgresDB_stub.k0000644000175100017510000000152311170340770014727 0ustar cimcimmodule PostgresDB; import DB; import Prelude; "The String contains a description of the error Connection error This Exception is thrown if the connection failed." Exception CantConnect(String err); "The String contains a description of the error Query error This Exception is thrown if a query failed." Exception ExecError(String err); "Column out of range. This Exception should never occur. It is thrown if an attempt is made to read a column that doesn't exist." Exception ColumnOutOfRange(); abstract data PGConnection = PGCon(Ptr cdata); type PGDB = DBHandle; public PGDB connect(var String conn) { throw(Not_Implemented); } public PGDB connect_pg(String info) = connect(info); kaya-0.4.4/libs/sdl_glue.h0000644000175100017510000000175011170340770013453 0ustar cimcim#ifndef _SDL_GLUE_H #define _SDL_GLUE_H #include #include #include "SDL/SDL.h" extern "C" { wchar_t* do_sdlerror(); void sdl_init(); void* do_newsurface(void* vmptr, kint x, kint y, kint bpp, kint flags); void do_sdlflip(void* screen); void* do_loadsurface(void* vmptr, wchar_t* rawfn); int do_sdlblit(void* srcptr, void* destptr, kint sl, kint st, kint sw, kint sh, kint dl, kint dt, kint dw, kint dh); void* do_waitevent(); kint event_type(void* eptr); kint do_getkeymod(void* eptr); kint do_getkeynum(void* eptr); kint do_getmmx(void* eptr); kint do_getmmy(void* eptr); kint do_getmbp(void* eptr); kint do_getmpx(void* eptr); kint do_getmpy(void* eptr); void do_sdltransparency(void* sptr, kint r, kint g, kint b, kint a); void do_drawrect(void* sptr, kint l, kint t, kint w, kint h, kint r, kint g, kint b, kint a); void do_setwmtitles(wchar_t* window, wchar_t* icon); void do_seticon(void* icon); } #endif kaya-0.4.4/libs/MyDB.k0000644000175100017510000001500411170340770012450 0ustar cimcim/** -*-C-*-ish MySQL interface library for Kaya Copyright (C) 2005 Chris Morris Based on the Postgres interface library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. When linked against a version of libmysqlclient that is GPL licensed then you must either use section 3 of the LGPL to change the copy used for linking to GPL, or use the FLOSS Exception published by MySQL if that is applicable to your circumstances. Note that unless you modify the C-side of the interface library to remove the prepared statement support, you will not be able to link with the old LGPL versions of libmysqlclient anyway. */ "MySQL database interface module This module allows querying of MySQL databases, using the standard DB API." module MyDB; import Builtins; // MySQL API suitable for use with the DB module. import Time; import Prelude; import public DB; %include "my_inter.h"; %imported "my_inter"; %link "mysqlclient"; %link "z"; "A MySQL database connection This data type holds information about a database connection. The type MyDB is a type synonym for DB::DBHandle<MyConnection> DB" abstract data MyConnection = MyCon(Ptr cdata); type MyDB = DBHandle; foreign "my_inter.o" { Ptr do_mysql_connect(String host, String user, String pwd, String db, Int port) = do_mysql_connect; Bool my_ok(Ptr conn) = my_ok; Ptr do_mysql_query(Ptr vm, Ptr cdata, String query) = do_mysql_query; Ptr do_mysql_incquery(Ptr vm, Ptr cdata, String query) = do_mysql_incquery; [[DBValue]] my_getstrs(Ptr pr) = my_getstrs; [DBValue] my_getrow(Ptr vm, Ptr pr) = my_getrow; Void my_discard(Ptr pr) = my_discard; Int my_numrows(Ptr pr) = my_numrows; Int my_numcols(Ptr pr) = my_numcols; [String] my_colnames(Ptr pr) = my_colnames; Void do_mysql_close(Ptr cdata) = do_mysql_close; Ptr do_mysqlprepare(String query) = do_mysqlprepare; Ptr mysql_execp(Ptr vm, Ptr cdata, Ptr query, [Maybe] params) = do_mysql_execp; } "Can't connect to database This Exception is thrown if the database connection failed, for example if the password was incorrect." Exception CantConnect(); "Query error This Exception is thrown if there was a syntax error in the query." Exception QueryError(); "Tried to read too many rows This Exception is thrown if you try to read more rows from an incremental database query than actually exist." Exception TooManyRows(); "The database host to connect to The database user to connect as The password for that user The database to connect to The port that the database server is running on. This defaults to zero, which is suitable when connecting to a server on 'localhost'. The usual MySQL port for remote servers is 3306. Connect to a database. Use this function to connect to the database. You can then use the functions from DB to query the database. db = MyDB::connect(\"localhost\",\"web\",\"WHSpWXPPh5\",\"mysite\"); res = exec(db,\"SELECT * FROM pagedata WHERE page_id = 10\"); DB" public MyDB connect(String host, String user, String pwd, String db, Int port=0) { myc = do_mysql_connect(host,user,pwd,db,port); con = MyCon(myc); if (!my_ok(con.cdata)) { throw(CantConnect()); } return(DBh(con, mysql_query, mysql_incquery, mysql_prepare, mysql_execp, defaultIncExecPrepared, mysql_getrow, mysql_discard, mysql_close)); } DBStatement mysql_prepare(MyDB con, String query) { return DBStatement(con,do_mysqlprepare(query)); } "Execute a query on the given connection." DBResult mysql_query(MyConnection con, String query) { try { pr = do_mysql_query(getVM(),con.cdata, query); } catch(InternalError(e)) { if (e==1) { throw(QueryError); } else throw(InternalError(e)); } strs = my_getstrs(pr); rows = my_numrows(pr); cols = my_numcols(pr); colnames = my_colnames(pr); return DBRes(strs,rows,cols,colnames,pr); } "Execute an incremental query on the given connection." DBIncResult mysql_incquery(MyConnection con, String query, MyDB dbc) { try { pr = do_mysql_incquery(getVM(),con.cdata, query); } catch(InternalError(e)) { if (e==1) { throw(QueryError); } else throw(InternalError(e)); } rows = my_numrows(pr); cols = my_numcols(pr); colnames = my_colnames(pr); return DBIncRes(dbc,rows,cols,colnames,pr); } [DBValue] mysql_getrow(DBIncResult res) { try { return my_getrow(getVM(),res.resptr); } catch(InternalError(e)) { if (e==2) { throw(TooManyRows()); } else throw(InternalError(e)); } } Void mysql_discard(DBIncResult res) { return my_discard(res.resptr); } "Close a connection to the database." Void mysql_close(MyConnection con) { do_mysql_close(con.cdata); } DBResult mysql_execp(DBStatement prep, [Maybe] params) { try { pr = mysql_execp(getVM(),prep.con.handle.cdata, prep.statement, params); } catch(InternalError(e)) { if (e==1) { throw(QueryError); } else throw(InternalError(e)); } strs = my_getstrs(pr); rows = my_numrows(pr); cols = my_numcols(pr); colnames = my_colnames(pr); return DBRes(strs,rows,cols,colnames,pr); } "The Time Return a MySQL database time Format a Time for insertion into MySQL datetime or timestamp fields. Generally, you should use the Time::isoTime function for greater compatibility with other databases. Previous to Kaya 0.3 this function was in the Time module. Time::Time" public String mySQLTime(Time t) { return t.year+"-"+twodigits(int(t.mon))+"-"+twodigits(t.mday)+" "+twodigits(t.hour)+":"+twodigits(t.minute)+":"+twodigits(t.second); } String twodigits(Int i) { if (i > 9) { return String(i); } return "0"+i; } kaya-0.4.4/libs/Multicore.k0000644000175100017510000004535011170340770013627 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2007 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Support for programming on Multicore machines Contains functions for easy creation of threads for subcomputations. " module Multicore; import Prelude; import Threads; globals { // Set to false if all functions in this module should be single threaded Bool multicore = true; } "Set whether to take advantage of multiple cores If mcore is true, always run the functions in the module in multi-threaded mode, otherwise run them single threaded. Default is true. " public Void setMulticore(Bool mcore) { multicore = mcore; } "Threaded map Returns the array created by appliction function f to every element of xs. The applications are divided between a number of threads. f should not modify global state. The number of threads created can be limited with limit, the default being no limit. Array::map Array::zipWith " public [b] tmap(b(a) f, [a] xs, Int limit = 0) { if (!multicore || limit==1) return map(f,xs); if (limit>1) return tmapLim(f,xs,limit); threads = createArray(size(xs)); new = createArray(size(xs)); for x@i in xs { push(threads, create(f, x)); } for thread@i in threads { // putStrLn("Waiting for " + i); push(new, waitFor(thread)); } return new; } "Threaded zip Returns the array created by appliction function f to every element of xs and ys. The applications are divided between a number of threads. f should not modify global state. The number of threads created can be limited with limit, the default being no limit. Array::zipWith Array::map " public [c] tzipWith(c(a,b) f, [a] xs, [b] ys, Int limit = 0) { if (!multicore || limit==1) return zipWith(f,xs,ys); if (size(xs)1) return tzipWithLim(f,xs,ys,max,limit); threads = createArray(max); new = createArray(max); for i in [0..max-1] { putStrLn("Thread "+i); push(threads, create(f@(xs[i],ys[i]))); } for thread@i in threads { // putStrLn("Waiting for " + i); push(new, waitFor(thread)); } return new; } [b] tmapLim(b(a) f, [a] xs, Int lim) { new = createArray(size(xs)); sz = size(xs)/lim; if ((size(xs)%lim)!=0) sz+=1; for i in [0..lim-1] { thread[i] = create(submap@(f, xs, sz*i, (sz*i)+sz-1)); } for i in [0..lim-1] { // putStrLn("Waiting for "+i); subnew = waitFor(thread[i]); for res in subnew { push(new, res); } } return new; } [b] submap (b(a) f, [a] xs, Int start, Int end) { if (end>=size(xs)) { end = size(xs)-1; } newxs = []; //createArray(end-start); for i in [start..end] { push(newxs, f(xs[i])); } return newxs; } [c] tzipWithLim(c(a,b) f, [a] xs, [b] ys, Int max, Int lim) { new = createArray(max); sz = max/lim; if ((max%lim)!=0) sz+=1; for i in [0..lim-1] { thread[i] = create(subzip@(f, xs, ys, max, sz*i, (sz*i)+sz-1)); } for i in [0..lim-1] { // putStrLn("Waiting for "+i); subnew = waitFor(thread[i]); for res in subnew { push(new, res); } } return new; } [c] subzip (c(a,b) f, [a] xs, [b] ys, Int max, Int start, Int end) { if (end>=max) { end = size(xs)-1; } newxs = []; //createArray(end-start); for i in [start..end] { push(newxs, f(xs[i], ys[i])); } return newxs; } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public a tapply(a(a1,a2) f, a1() arg1, a2() arg2) { if (!multicore) return f(arg1,arg2); t1 = create(@arg1); t2 = create(@arg2); r1 = waitFor(t1); r2 = waitFor(t2); return f(r1,r2); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public a tapply(a(a1,a2,a3) f, a1() arg1, a2() arg2, a3() arg3) { if (!multicore) return f(arg1,arg2,arg3); t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); return f(r1,r2,r3); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public a tapply(a(a1,a2,a3,a4) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4) { if (!multicore) return f(arg1,arg2,arg3,arg4); t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); return f(r1,r2,r3,r4); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public a tapply(a(a1,a2,a3,a4,a5) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5) { if (!multicore) return f(arg1,arg2,arg3,arg4,arg5); t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); return f(r1,r2,r3,r4,r5); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public a tapply(a(a1,a2,a3,a4,a5,a6) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5, a6() arg6) { if (!multicore) return f(arg1,arg2,arg3,arg4,arg5,arg6); t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); t6 = create(@arg6); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); r6 = waitFor(t6); return f(r1,r2,r3,r4,r5,r6); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public a tapply(a(a1,a2,a3,a4,a5,a6,a7) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5, a6() arg6, a7() arg7) { if (!multicore) return f(arg1,arg2,arg3,arg4,arg5,arg6,arg7); t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); t6 = create(@arg6); t7 = create(@arg7); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); r6 = waitFor(t6); r7 = waitFor(t7); return f(r1,r2,r3,r4,r5,r6,r7); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public a tapply(a(a1,a2,a3,a4,a5,a6,a7,a8) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5, a6() arg6, a7() arg7, a8() arg8) { if (!multicore) return f(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); t6 = create(@arg6); t7 = create(@arg7); t8 = create(@arg8); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); r6 = waitFor(t6); r7 = waitFor(t7); r8 = waitFor(t8); return f(r1,r2,r3,r4,r5,r6,r7,r8); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public a tapply(a(a1,a2,a3,a4,a5,a6,a7,a8,a9) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5, a6() arg6, a7() arg7, a8() arg8, a9() arg9) { if (!multicore) return f(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9); t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); t6 = create(@arg6); t7 = create(@arg7); t8 = create(@arg8); t9 = create(@arg9); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); r6 = waitFor(t6); r7 = waitFor(t7); r8 = waitFor(t8); r9 = waitFor(t9); return f(r1,r2,r3,r4,r5,r6,r7,r8,r9); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public a tapply(a(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5, a6() arg6, a7() arg7, a8() arg8, a9() arg9, a10() arg10) { if (!multicore) return f(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10); t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); t6 = create(@arg6); t7 = create(@arg7); t8 = create(@arg8); t9 = create(@arg9); t10 = create(@arg10); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); r6 = waitFor(t6); r7 = waitFor(t7); r8 = waitFor(t8); r9 = waitFor(t9); r10 = waitFor(t10); return f(r1,r2,r3,r4,r5,r6,r7,r8,r9,r10); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public Void texec(Void(a1,a2) f, a1() arg1, a2() arg2) { if (!multicore) { f(arg1,arg2); return; } t1 = create(@arg1); t2 = create(@arg2); r1 = waitFor(t1); r2 = waitFor(t2); f(r1,r2); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public Void texec(Void(a1,a2,a3) f, a1() arg1, a2() arg2, a3() arg3) { if (!multicore) { f(arg1,arg2,arg3); return; } t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); f(r1,r2,r3); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public Void texec(Void(a1,a2,a3,a4) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4) { if (!multicore) { f(arg1,arg2,arg3,arg4); return; } t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); f(r1,r2,r3,r4); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public Void texec(Void(a1,a2,a3,a4,a5) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5) { if (!multicore) { f(arg1,arg2,arg3,arg4,arg5); return; } t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); f(r1,r2,r3,r4,r5); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public Void texec(Void(a1,a2,a3,a4,a5,a6) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5, a6() arg6) { if (!multicore) { f(arg1,arg2,arg3,arg4,arg5,arg6); return; } t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); t6 = create(@arg6); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); r6 = waitFor(t6); f(r1,r2,r3,r4,r5,r6); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public Void texec(Void(a1,a2,a3,a4,a5,a6,a7) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5, a6() arg6, a7() arg7) { if (!multicore) { f(arg1,arg2,arg3,arg4,arg5,arg6,arg7); return; } t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); t6 = create(@arg6); t7 = create(@arg7); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); r6 = waitFor(t6); r7 = waitFor(t7); f(r1,r2,r3,r4,r5,r6,r7); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public Void texec(Void(a1,a2,a3,a4,a5,a6,a7,a8) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5, a6() arg6, a7() arg7, a8() arg8) { if (!multicore) { f(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); return; } t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); t6 = create(@arg6); t7 = create(@arg7); t8 = create(@arg8); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); r6 = waitFor(t6); r7 = waitFor(t7); r8 = waitFor(t8); f(r1,r2,r3,r4,r5,r6,r7,r8); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public Void texec(Void(a1,a2,a3,a4,a5,a6,a7,a8,a9) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5, a6() arg6, a7() arg7, a8() arg8, a9() arg9) { if (!multicore) { f(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9); return; } t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); t6 = create(@arg6); t7 = create(@arg7); t8 = create(@arg8); t9 = create(@arg9); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); r6 = waitFor(t6); r7 = waitFor(t7); r8 = waitFor(t8); r9 = waitFor(t9); f(r1,r2,r3,r4,r5,r6,r7,r8,r9); } "Threaded application Apply function f to the results of running a1-an. Each argument ai is a computation which will be run concurrently with the other arguments, so they must be independent (i.e. not modify any shared state)." public Void texec(Void(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) f, a1() arg1, a2() arg2, a3() arg3, a4() arg4, a5() arg5, a6() arg6, a7() arg7, a8() arg8, a9() arg9, a10() arg10) { if (!multicore) { f(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10); return; } t1 = create(@arg1); t2 = create(@arg2); t3 = create(@arg3); t4 = create(@arg4); t5 = create(@arg5); t6 = create(@arg6); t7 = create(@arg7); t8 = create(@arg8); t9 = create(@arg9); t10 = create(@arg10); r1 = waitFor(t1); r2 = waitFor(t2); r3 = waitFor(t3); r4 = waitFor(t4); r5 = waitFor(t5); r6 = waitFor(t6); r7 = waitFor(t7); r8 = waitFor(t8); r9 = waitFor(t9); r10 = waitFor(t10); f(r1,r2,r3,r4,r5,r6,r7,r8,r9,r10); } kaya-0.4.4/libs/Image.k0000644000175100017510000004525711170340770012714 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005, 2006, 2007 Edwin Brady, Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Image manipulation This module interfaces to the GD library for creating and editing JPEG and PNG images. It also provides a displayPage function so that the generated images may be easily output by webapps. See the Shape CGI for an example of the use of this module on the web." module Image; import Prelude; import IO; import Binary; import Webapp; %include "image_glue.h"; %imported "image_glue"; %link "gd"; "Image data. An editable image" abstract data Image = Image(Ptr imptr,Int xsize, Int ysize); "Web image data An uneditable image ready to be displayed on the web" abstract data WebImage = WebImage(Binary img, String ctype, [(String,String)] headers); "Drawing colour. A drawing colour" abstract data Colour = Col(Int col); "Drawing font. A drawing font" abstract data Font = Font(Ptr fontptr); "Arc fill styles. Fill styles for arcs." public data ArcStyle = Arc | Chord | Pie | NoFill | Edged; type Color = Colour; // Euw foreign "image.o" { Ptr do_createImage(Int x,Int y, Bool tc) = createImage; Void do_destroyImage(Ptr imptr) = destroyImage; Image do_createImageFromPNG(Ptr f) = createImageFromPNG; Image do_createImageFromJPEG(Ptr f) = createImageFromJPEG; Int imageColourAllocate(Ptr ptr, Int r, Int g, Int b, Int a) = imageColourAllocate; Ptr fontGetSmall() = fontGetSmall; Ptr fontGetLarge() = fontGetLarge; Ptr fontGetMediumBold() = fontGetMediumBold; Ptr fontGetGiant() = fontGetGiant; Ptr fontGetTiny() = fontGetTiny; Void imageString(Ptr ptr, Ptr font, Int x, Int y, String str, Int col, Bool up) = imageString; Void imageLine(Ptr ptr, Int x1, Int y1, Int x2, Int y2, Int col) = imageLine; Void imageDashedLine(Ptr ptr, Int x1, Int y1, Int x2, Int y2, Int col) = imageDashedLine; Void imageRectangle(Ptr ptr, Int x1, Int y1, Int x2, Int y2, Int col, Bool filled) = imageRectangle; Void imageSetPixel(Ptr ptr, Int x, Int y, Int col) = imageSetPixel; Void imageDrawPoly(Ptr ptr,[(Int,Int)] points, Int col, Bool filled) = imageDrawPoly; Void imageArc(Ptr ptr, Int cx, Int cy, Int w,Int h, Int start, Int end, Int col, [ArcStyle] style, Bool filled) = imageArc; Void imageCopy(Ptr dest, Ptr src, Int dstx, Int dsty, Int srcx, Int srcy, Int w, Int h) = imageCopy; Void imageCopyResized(Ptr dest, Ptr src, Int dstx, Int dsty, Int srcx, Int srcy, Int destw, Int desth, Int srcw, Int srch) = imageCopyResized; Void imageWritePNG(Ptr ptr, Ptr f) = imageWritePNG; Void imageWriteJPEG(Ptr ptr, Ptr f, Int qual) = imageWriteJPEG; Binary imageGetPNG(Ptr ptr) = imageGetPNG; Binary imageGetJPEG(Ptr ptr, Int qual) = imageGetJPEG; } "Colour value out of range This Exception is thrown if a colour red, green or blue component is outside the range 0-255, or the alpha component is outside the range 0-127." Exception ColourOutOfRange(); /// Image creation "Image width in pixels Image height in pixels Is the image true colour (optional, defaulting to false) Create a new image Create a new image with the specified dimensions and colour. create" public Image create(Int x, Int y, Bool truecolour=false) { imgdata = do_createImage(x,y,truecolour); return Image(imgdata,x,y); } "Destroy an image Destroy an image Destroy an image." public Void destroy(Image img) { do_destroyImage(img.imptr); } "The image Get image width Get the width of an image in pixels height" public Int width(Image img) = img.xsize; "The image Get image height Get the height of an image in pixels width" public Int height(Image img) = img.ysize; "Image format What data format is used for the image. JPEG is better for photographic images, PNG for abstract graphics." public data ImageType = PNG | JPEG; "The filename of the image to load Whether the image to be loaded is PNG or JPEG Create an image from a file Loads an image from a file and returns the resulting Image. create" public Image create(String fname, ImageType ty) { f = open(fname,[Read,Binary]); case ty of { PNG -> img = do_createImageFromPNG(ptr(f)); | JPEG -> img = do_createImageFromJPEG(ptr(f)); } close(f); return img; } "The image The red channel (0..255) The green channel (0..255) The blue channel (0..255) The alpha channel (0..127). 127 represents full transparency. This argument may be omitted for a default of 0 (fully opaque) Allocate a colour. Allocate the specified colour for use in the image." public Colour makeColour(Image img, Int r, Int g, Int b, Int a = 0) { if (r<0 || r>255 || g<0 || g>255 || b<0 || b>255 || a<0 || a>127) { throw(ColourOutOfRange()); } return Col(imageColourAllocate(img.imptr, r, g, b, a)); } /// Fonts and text "Small font A small font" public Font small() = Font(fontGetSmall()); "Large font A large font" public Font large() = Font(fontGetLarge()); "Medium bold font A medium and bold font" public Font mediumBold() = Font(fontGetMediumBold()); "Giant font A giant font" public Font giant() = Font(fontGetGiant()); "Tiny font A tiny font" public Font tiny() = Font(fontGetTiny()); "The image The font to use (e.g. small) The left-right position of the start of the text The top-bottom position of the start of the text The text to add The colour of the text Normally text is drawn left to right. If this parameter is true, it will be drawn bottom to top instead. Draw a text string. Writes a text string at the given location." public Void drawString(Image img, Font font, Int x, Int y, String str, Colour col, Bool up = false) { imageString(img.imptr, font.fontptr, x,y,str,col.col, up); } /// Drawing "The image X coordinate of first endpoint Y coordinate of first endpoint X coordinate of second endpoint Y coordinate of second endpoint Colour of the line Draw a line. Draws a line on the image from (x1,y1) to (x2,y2). dashedLine rectangle" public Void line(Image img, Int x1, Int y1, Int x2, Int y2, Colour col) { imageLine(img.imptr, x1, y1, x2, y2, col.col); } "The image X coordinate of first endpoint Y coordinate of first endpoint X coordinate of second endpoint Y coordinate of second endpoint Colour of the line Draw a dashed line. Draws a dashed line on the image from (x1,y1) to (x2,y2). line rectangle" public Void dashedLine(Image img, Int x1, Int y1, Int x2, Int y2, Colour col) { imageDashedLine(img.imptr, x1, y1, x2, y2, col.col); } "The image X coordinate of first corner Y coordinate of first corner X coordinate of opposite corner Y coordinate of opposite corner Colour of the rectangle's border If this is true, the rectangle will be filled with the same colour as the border. Draw a rectangle. Draws a rectangle with opposite corners at (x1,y1) and (x2,y2). dashedLine ellipse line poly" public Void rectangle(Image img, Int x1, Int y1, Int x2, Int y2, Colour col, Bool filled = false) { imageRectangle(img.imptr, x1, y1, x2, y2, col.col, filled); } "The image The X coordinate of the pixel The Y coordinate of the pixel The colour to paint the pixel Set a pixel's colour. Sets the colour of the specified pixel." public Void setPixel(Image img, Int x, Int y, Colour col) { imageSetPixel(img.imptr, x, y, col.col); } "The image A list of pairs (in X,Y order) giving the corners of the polygon. Colour of the polygon's border If this is true, the polygon will be filled with the same colour as the border. Draw a polygon. Draws a polygon with the specified corners. ellipse rectangle" public Void poly(Image img, [(Int,Int)] points, Colour col, Bool filled = false) { imageDrawPoly(img.imptr,points,col.col,filled); } "The image The X coordinate of the centre of the ellipse The Y coordinate of the centre of the ellipse The width of the ellipse The height of the ellipse The starting angle (in degrees measured clockwise from rightwards) The ending angle (in degrees measured clockwise from rightwards) Colour of the arc Whether the arc is filled (defaults to false) If the arc is filled, a list of ArcStyles to apply. Draw an arc of an ellipse. Draw an arc of an ellipse, optionally filled, with the specified parameters. ellipse" public Void arc(Image img, Int cx, Int cy, Int w, Int h, Int start, Int end, Colour col, Bool filled = false, [ArcStyle] style = [Arc]) { imageArc(img.imptr,cx,cy,w,h,start,end,col.col,style,filled); } "The image The X coordinate of the centre of the ellipse The Y coordinate of the centre of the ellipse The width of the ellipse The height of the ellipse Colour of the ellipse Whether the ellipse is filled (defaults to false) Draw an ellipse. Draw an ellipse at the specified position. arc poly rectangle" public Void ellipse(Image img, Int cx, Int cy, Int w, Int h, Colour col, Bool filled = false) { arc(img,cx,cy,w,h,0,360,col,filled,[Arc]); } /// Copying/resizing "Destination image Source image Destination left edge Destination top edge Source left edge Source top edge Width of area to copy Height of area to copy Copy a portion of an image. Copy a portion of an image from one image to another. copyResized" public Void copy(Image dest, Image src, Int dstx, Int dsty, Int srcx, Int srcy, Int w, Int h) { imageCopy(dest.imptr,src.imptr,dstx,dsty,srcx,srcy,w,h); } "Destination image Source image Destination left edge Destination top edge Source left edge Source top edge Width of area to copy in to Height of area to copy in to Width of area to copy out of Height of area to copy out of Copy and resize a portion of an image. Copy a portion of an image from one image to another, resizing the copied area to fit within a particular destination rectangle. copy" public Void copyResized(Image dest, Image src, Int dstx, Int dsty, Int srcx, Int srcy, Int destw, Int desth, Int srcw, Int srch) { imageCopyResized(dest.imptr,src.imptr,dstx,dsty,srcx,srcy, destw,desth,srcw,srch); } /// Output "The image The file name to write to. This argument may be omitted to use standard output, which is useful in CGI scripts - call CGI::flush first to ensure the headers have been sent. Output a PNG. Outputs a PNG from the image. This function should not be used with standard output in the webapp model - use webPNG instead. makeJPEG" public Void makePNG(Image img, String file = "") { if (file=="") { f = stdout; } else { f = open(file,[Write,Binary]); } imageWritePNG(img.imptr, ptr(f)); if (file!="") { close(f); } } "The image Get PNG data Returns a Binary object containing the image data in PNG format. getJPEG" public Binary getPNG(Image img) { return imageGetPNG(img.imptr); } "The image The image quality (0..95). Alternatively, any negative number will use the default output quality. The file name to write to. This argument may be omitted to use standard output, which is useful in CGI scripts - call CGI::flush first to ensure the headers have been sent. Output a JPEG. Outputs a JPEG from the image. This function should not be used with standard output in the webapp model - use webJPEG instead. makePNG" public Void makeJPEG(Image img, Int qual = -1, String file = "") { if (file=="") { f = stdout; } else { f = open(file,[Write,Binary]); } imageWriteJPEG(img.imptr, ptr(f), qual); if (file!="") { close(f); } } "The image The image quality (0..95). Alternatively, any negative number will use the default output quality. Get JPEG data Returns a Binary object containing the image data in JPEG format. getPNG" public Binary getJPEG(Image img, Int qual=-1) { return imageGetJPEG(img.imptr,qual); } "The image Any additional HTTP headers to send with the image Get a PNG for webmain Returns a PNG image suitable for returning from a webapp's webmain function. webJPEG" public WebImage webPNG(Image img, [(String,String)] extraheaders) { return WebImage(getPNG(img),"image/png",extraheaders); } "The image Any additional HTTP headers to send with the image The image quality (0..95). Alternatively, any negative number will use the default output quality. Get a JPEG for webmain Returns a JPEG image suitable for returning from a webapp's webmain function. webPNG" public WebImage webJPEG(Image img, [(String,String)] extraheaders, Int qual=-1) { return WebImage(getJPEG(img,qual),"image/jpeg",extraheaders); } "A WebImage produced with webPNG or webJPEG. Display function for webapps Display an image via HTTP. This function should be called automatically by a web application when the return type of webmain is WebImage. Calling this function directly is generally only necessary for debugging purposes. Webapp" public Void displayPage(WebImage image) { push(image.headers,("Content-type",image.ctype)); displayPage(image.img,image.headers); } kaya-0.4.4/libs/PostgresDB.k0000644000175100017510000001001511170340770013666 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "PostgreSQL database interface module This module allows querying of PostgreSQL databases, using the standard DB API." module PostgresDB; import Builtins; // Postgres API suitable for use with the DB module. import Prelude; import public DB; %include "pg_inter.h"; %imported "pg_inter"; %link "pq"; "A PostgreSQL database connection This data type holds information about a database connection. The type PGDB is a type synonym for DB::DBHandle<PGConnection> DB" abstract data PGConnection = PGCon(Ptr cdata); type PGDB = DBHandle; foreign "pg_inter.o" { Ptr pg_connect(String info) = pg_connect; Bool pg_ok(Ptr p) = pg_ok; Ptr pg_exec(Ptr vm, Ptr cdata, String query, a errstr) = pg_exec; [[DBValue]] pg_getstrs(Ptr pr) = pg_getstrs; Int pg_numrows(Ptr pr) = pg_numrows; Int pg_numcols(Ptr pr) = pg_numcols; [String] pg_colnames(Ptr pr) = pg_colnames; String pg_getError(Ptr pgc) = pg_getError; Void pg_close(Ptr cdata) = pg_close; Ptr do_pgprepare(String query) = do_pg_prepare; Ptr pg_execp(Ptr vm, Ptr cdata, Ptr query, a errstr, [Maybe] params) = pg_execp; } "The String contains a description of the error Connection error This Exception is thrown if the connection failed." Exception CantConnect(String err); "The String contains a description of the error Query error This Exception is thrown if a query failed." Exception ExecError(String err); "Column out of range. This Exception should never occur. It is thrown if an attempt is made to read a column that doesn't exist." Exception ColumnOutOfRange(); "The database host to connect to. The syntax for this argument is described in the Postgres documentation. Connect to a database. Use this function to connect to the database. You can then use the functions from DB to query the database. conninfo = \"dbname='mysite' user='web' password='WHSpWXPPh5'\"; db = PostgresDB::connect(conninfo); res = exec(db,\"SELECT * FROM pagedata WHERE page_id = 10\"); DB" public DBHandle connect(String info) { pgc = pg_connect(info); if (pg_ok(pgc)==false) { throw(CantConnect(pg_getError(pgc))); } con = PGCon(pgc); return(DBh(con, exec_pg, defaultIncExec, prepare_pg, execp_pg, defaultIncExecPrepared, defaultGetRow, defaultIncDiscard, close_pg)); } DBStatement prepare_pg(PGDB con, String query) { return DBStatement(con,do_pgprepare(query)); } DBResult execp_pg(DBStatement prep, [Maybe] params) { err = "Unknown error"; pr = pg_execp(getVM(),prep.con.handle.cdata, prep.statement, err, params); if (null(pr)) { throw(ExecError(err)); } strs = pg_getstrs(pr); rows = pg_numrows(pr); cols = pg_numcols(pr); colnames = pg_colnames(pr); return DBRes(strs,rows,cols,colnames,pr); } "Execute a query on the given connection." DBResult exec_pg(PGConnection con, String query) { err = "Unknown error"; pr = pg_exec(getVM(),con.cdata, query, err); if (null(pr)) { throw(ExecError(err)); } strs = pg_getstrs(pr); rows = pg_numrows(pr); cols = pg_numcols(pr); colnames = pg_colnames(pr); return DBRes(strs,rows,cols,colnames,pr); } "Close a connection to the database." Void close_pg(PGConnection con) { pg_close(con.cdata); } kaya-0.4.4/libs/thread_glue.cc0000644000175100017510000000270011170340770014272 0ustar cimcim#include #include "thread_glue.h" #include #include void* threadFn(void* vfn) { ThreadStartup* ts = (ThreadStartup*)vfn; // Make new vm data, push the argument, call the function. VMState* vm = initstack(); // cout << "Making new vm " << vm << endl; PUSH(new Value(NULL,KVT_NULL)); // return value if (ts->arg!=NULL) { PUSH(ts->arg); } CALLFUN(ts->fn); return vm->doPop(); } void* createThread(Value* fn,Value* arg) { ThreadStartup* ts = new ThreadStartup(); ts->fn = fn; ts->arg = arg; pthread_t t; pthread_create(&t,NULL,threadFn,(void*)ts); ThreadData* td = new ThreadData(); td->t_id = t; return (void*)td; } void* createThreadNullary(Value* fn) { createThread(fn, NULL); } Value* waitForThread(void* tid) { ThreadData* td = (ThreadData*)tid; void* status; pthread_join(td->t_id,&status); return (Value*)status; } void killThread(void* tid) { ThreadData* td = (ThreadData*)tid; pthread_cancel(td->t_id); } void endThread() { pthread_exit(0); } void* createMutex() { pthread_mutex_t m; pthread_mutex_init(&m,NULL); ThreadMutex* tm = new ThreadMutex(); tm->m_id = m; return (void*)tm; } void lock(void* mutex) { ThreadMutex* tm = (ThreadMutex*)mutex; pthread_mutex_lock(&(tm->m_id)); } void unlock(void* mutex) { ThreadMutex* tm = (ThreadMutex*)mutex; pthread_mutex_unlock(&(tm->m_id)); } kaya-0.4.4/libs/MyDB_stub.k0000644000175100017510000000140211170340770013502 0ustar cimcimmodule MyDB; import DB; import Prelude; "Can't connect to database This Exception is thrown if the database connection failed, for example if the password was incorrect." Exception CantConnect(); "Query error This Exception is thrown if there was a syntax error in the query." Exception QueryError(); "Tried to read too many rows This Exception is thrown if you try to read more rows from an incremental database query than actually exist." Exception TooManyRows(); abstract data MyConnection = MyCon(Ptr cdata); type MyDB = DBHandle; public MyDB connect(String host, String user, String pwd, String db, Int port=0) { throw(Not_Implemented); } kaya-0.4.4/libs/my_inter.h0000644000175100017510000000315011170340770013477 0ustar cimcim#ifndef _MY_INTER_H // -*-C++-*- #define _MY_INTER_H // Glue functions for talking to libmysqlclient #include #include #include #include using namespace std; typedef enum { DBTEXT, DBINT, DBFLOAT, DBBOOL, DBTIME } DBtype; /// These class names are rubbish and confusing!!!!1!!! class MyCon : public gc { public: MYSQL* con; int ok; map typids; }; class MyRes : public gc { public: MyRes(); KayaArray res_table; int rows; int cols; KayaArray colnames; MYSQL_RES* myres; }; extern "C" { /// Returns a MyCon void* do_mysql_connect(KString rawhost, KString rawuser, KString rawpass, KString rawdb, KInt rawport); /// Tests if a connection is ok bool my_ok(void* conn); /// Returns an error message // wchar_t* pg_getError(void* conn); /// Returns a PGRes void* do_mysql_query(void* vmptr,void* conn,wchar_t* query); void* do_mysql_incquery(void* vmptr,void* conn,wchar_t* query); Array* my_getrow(void* vmptr, void* resptr); void my_discard(void* resptr); /// Returns a column name // wchar_t* pg_columnname(void* vmptr,void* res, int col); /// Gets the strings from a PGRes KayaArray my_getstrs(void* res); /// Return the number of rows in a result int my_numrows(void* res); /// Return the number of columns in a result int my_numcols(void* res); /// Get the columnames KayaArray my_colnames(void* res); /// Close the connection void do_mysql_close(void* conn); void* do_mysqlprepare(wchar_t* query); void* do_mysql_execp(void* vmptr, void* conn, void* query, KArray params); } #endif kaya-0.4.4/libs/CursesW.head0000644000175100017510000000137211170340770013722 0ustar cimcim/** -*-C-*-ish CursesWide module Copyright (C) 2004-2007 Edwin Brady, Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Curses terminal control library interface (multibyte) This module provides an interface to the ncursesw terminal control library, a version of Curses that supports multi-byte characters. The initscr must be called before most of the functions in this module will work, and endwin must be called before program exit." module CursesW; import Prelude; %include "cursesw_glue.h"; %imported "cursesw_glue"; %link "ncursesw"; kaya-0.4.4/libs/sqlite_inter.cc0000644000175100017510000001601211170340770014512 0ustar cimcim#include "sqlite_inter.h" #include void* sqlite_connect(wchar_t* info) { sqlite3* db; int rc = sqlite3_open(wctostr(info), &db); SQLiteConnection* con = new SQLiteConnection(); con->db = db; con->ok = (rc==0); return (void*)con; } int sqlite_ok(void* con) { return ((SQLiteConnection*)con)->ok; } wchar_t* sqlite_getError(void* con) { sqlite3* db = ((SQLiteConnection*)con)->db; return strtowc(sqlite3_errmsg(db)); } void sqlite_close(void* con) { sqlite3* db = ((SQLiteConnection*)con)->db; sqlite3_close(db); } void sqlite_buildRow(sqlite3_stmt* stmt, SQLiteResult* sqlr) { int cols = sqlite3_column_count(stmt); int getnames = 0; if (KayaArraySize(sqlr->col_names)==0) { getnames = 1; } KValue entry; int intval; double dblval; const char* txt; KArray row = newKayaArray(cols); sqlr->cols = cols; for(int x = 0; xcol_names, KayaString(KSTRING(txt))); } } KayaArrayPush(sqlr->res_table, KayaArrayVal(row)); } KArray sqlite_get(sqlite3_stmt* stmt, SQLiteResult* sqlr) { int cols = sqlite3_column_count(stmt); int getnames = 0; if (KayaArraySize(sqlr->col_names)==0) { getnames = 1; } KValue entry; int intval; double dblval; const char* txt; KArray row = newKayaArray(cols); sqlr->cols = cols; for(int x = 0; xcol_names, KayaString(KSTRING(txt))); } } return row; } void* sqlite_incexec(void* con, wchar_t* query) { // result array had better be empty here! sqlite3_stmt* stmt; // statement handle const char* tail; // unused, from sqlite3_prepare sqlite3* db = ((SQLiteConnection*)con)->db; SQLiteResult* result = new SQLiteResult(); result->res = 0; result->res_table = newKayaArray(0); result->col_names = newKayaArray(0); result->rows = 0; result->cols = 0; int rc = sqlite3_prepare(db, wctostr(query), -1, &stmt, &tail); result->resptr = stmt; if (rc!=0) { result->res = 2; } return (void*)result; } KArray sqlite_getrow(void* vmptr, void* resptr) { SQLiteResult* result = (SQLiteResult*) resptr; VMState* vm = (VMState*) vmptr; sqlite3_stmt* stmt = result->resptr; while(true) { int res = sqlite3_step(stmt); switch(res) { case SQLITE_BUSY: result->res = 1; vm->kaya_internalError(1); break; case SQLITE_ERROR: case SQLITE_MISUSE: result->res = 2; vm->kaya_internalError(2); break; case SQLITE_ROW: result->rows++; return sqlite_get(stmt, result); case SQLITE_DONE: vm->kaya_internalError(0); // no more rows break; default: result->res = 3; // vm->kaya_internalError(3); } } return newKayaArray(1); } void* sqlite_exec(void* con, wchar_t* query) { // result array had better be empty here! sqlite3_stmt* stmt; // statement handle const char* tail; // unused, from sqlite3_prepare sqlite3* db = ((SQLiteConnection*)con)->db; SQLiteResult* result = new SQLiteResult(); result->res = 0; result->res_table = newKayaArray(0); result->col_names = newKayaArray(0); result->rows = 0; result->cols = 0; int rc = sqlite3_prepare(db, wctostr(query), -1, &stmt, &tail); if (rc!=0) { result->res = 2; return result; } int res; do { res = sqlite3_step(stmt); switch(res) { case SQLITE_BUSY: result->res = 1; break; case SQLITE_ERROR: case SQLITE_MISUSE: result->res = 2; break; case SQLITE_ROW: result->rows++; sqlite_buildRow(stmt, result); case SQLITE_DONE: break; default: result->res = 3; } } while (res!=SQLITE_DONE); sqlite3_finalize(stmt); return (void*)result; } void sqlite_discard(void* sptr) { sqlite3_finalize((sqlite3_stmt*)sptr); } KArray sql_getcolnames(void* res) { return ((SQLiteResult*)res)->col_names; } KArray sql_getrestable(void* res) { return ((SQLiteResult*)res)->res_table; } int sql_numrows(void* res) { return ((SQLiteResult*)res)->rows; } int sql_numcols(void* res) { return ((SQLiteResult*)res)->cols; } int sql_resrc(void* res) { return ((SQLiteResult*)res)->res; } void* sqlite_prepare(void* vmptr, void* con, wchar_t* query) { sqlite3_stmt* stmt; // statement handle const char* tail; // unused, from sqlite3_prepare sqlite3* db = ((SQLiteConnection*)con)->db; int rc = sqlite3_prepare(db, wctostr(query), -1, &stmt, &tail); if (rc!=0) { VMState* vm = (VMState*) vmptr; vm->kaya_internalError(1); } SQLiteStatement* statement = new SQLiteStatement(stmt); return (void*) statement; } void* sqlite_execp(void* stptr, KArray params) { SQLiteStatement* statement = (SQLiteStatement*) stptr; sqlite3_stmt* stmt = statement->stmt; SQLiteResult* result = new SQLiteResult(); result->res = 0; result->res_table = newKayaArray(0); result->col_names = newKayaArray(0); result->rows = 0; result->cols = 0; sqlite3_reset(stmt); int sz = KayaArraySize(params); for (int i=0;ires = 1; break; case SQLITE_ERROR: result->res = 2; break; case SQLITE_ROW: result->rows++; sqlite_buildRow(stmt, result); case SQLITE_DONE: break; default: result->res = 3; } } while (res!=SQLITE_DONE); return (void*)result; } kaya-0.4.4/libs/image_glue.h0000644000175100017510000000312611170340770013752 0ustar cimcim#ifndef _IMAGE_H #define _IMAGE_H #include #include #include #include extern "C" { void* createImage(int x, int y, int tc); void destroyImage(void* img); /// Return Images directly KayaValue createImageFromPNG(void* fn); KayaValue createImageFromJPEG(void* fn); int imageColourAllocate(void* img, int r, int g, int b, int a); void imageLine(void* img, int x1, int y1, int x2, int y2, int col); void imageDashedLine(void* img, int x1, int y1, int x2, int y2, int col); void imageSetPixel(void* img, int x, int y, int col); void imageDrawPoly(void* img, KayaArray pts, int col, int filled); void imageRectangle(void* img, int x1, int y1, int x2, int y2, int col, int filled); void imageArc(void* img, int cx, int cy, int w, int h, int s, int e, int col, KayaArray style, int filled); void imageCopy(void* dest,void* src, int dstx, int dsty, int srcx, int srcy, int w, int h); void imageCopyResized(void* dest,void* src, int dstx, int dsty, int srcx, int srcy, int destw, int desth, int srcw, int srch); void imageWritePNG(void* img, void* out); void imageWriteJPEG(void* img, void* out, int quality); KayaValue imageGetPNG(void* img); KayaValue imageGetJPEG(void* img, int quality); KayaValue imageGetBinary(void* bindata, int binsize); void* fontGetSmall(); void* fontGetLarge(); void* fontGetMediumBold(); void* fontGetGiant(); void* fontGetTiny(); void imageString(void* img, void* font, int x, int y, wchar_t* str, int col, int up); } #endif kaya-0.4.4/libs/pg_inter.cc0000644000175100017510000001476711170340770013636 0ustar cimcim #include "pg_inter.h" #include #include #include #include void* pg_connect(wchar_t* rawconninfo) { char* conninfo = wctostr(rawconninfo); PGconn* pc = PQconnectdb(conninfo); PGCon * pgc = new PGCon(); pgc->con = pc; pgc->ok = 1; // cout << pc << "," << pgc << endl; // cout << PQstatus(pc) << endl; if (pc==NULL || PQstatus(pc) == CONNECTION_BAD) { pgc->ok = 0; } return (void*)pgc; } bool pg_ok(void* conn) { PGCon* pgc = (PGCon*)conn; // cout << pgc->ok << endl; return pgc->ok; } wchar_t* pg_getError(void* conn) { PGconn* pgc = ((PGCon*)conn)->con; return strtowc(PQerrorMessage(pgc)); } DBtype getDBtype(wchar_t* rawval) { char* val = wctostr(rawval); if (strncmp(val,"int",3)==0 && val[3]!='8') { // limit to 32 bit return DBINT; } else if (strncmp(val,"float",5)==0) { return DBFLOAT; } else if (strcmp(val,"bool")==0) { return DBBOOL; } else { return DBTEXT; } } // Work out what OIDs mean what types, so we can build the right structure // kaya-side. void pg_getTypeIDs(VMState* vm, PGCon* pgc) { if (pgc->typids.size()!=0) { return; // Already done it } PGresult *res = PQexec(pgc->con,"SELECT oid,* FROM pg_type"); int numrows = PQntuples(res); for(int i = 0; itypids[oid] = getDBtype(strtowc(val)); // printf("%d: %s\n", oid, val); } } void* pg_exec(void* vmptr,void* conn,wchar_t* rawquery, KayaValue err) { char* query = wctostr(rawquery); VMState* vm = (VMState*)vmptr; PGCon* pgc = (PGCon*)conn; pg_getTypeIDs(vm,pgc); PGresult *res = PQexec(pgc->con,query); if (res==NULL) { KayaSetString(err, KSTRING(PQerrorMessage(pgc->con))); return NULL; } if ((PQresultStatus(res)!=PGRES_COMMAND_OK) && (PQresultStatus(res) != PGRES_TUPLES_OK)) { KayaSetString(err, KSTRING(PQresultErrorMessage(res))); return NULL; } int numrows = PQntuples(res); int numflds = PQnfields(res); KayaArray col_names = newKayaArray(numflds); for (int i = 0; itypids[ty]) { case DBINT: /// If it's an int, make a DBInt(val) pv = KayaInt(atoi(val)); fld = KayaUnion(1,1); KayaUnionSetArg(fld,0,pv); KayaArrayPush(row,fld); break; case DBFLOAT: /// If it's a float, make a DBFloat(val) pv = KayaFloat(atof(val)); fld = KayaUnion(2,1); KayaUnionSetArg(fld,0,pv); KayaArrayPush(row,fld); break; case DBBOOL: /// If it's a bool, make a DBBool(val) if (val[0]=='t') { pv = KayaInt(1); } else { pv = KayaInt(0); } fld = KayaUnion(4,1); KayaUnionSetArg(fld,0,pv); KayaArrayPush(row,fld); break; case DBTIME: /// TODO: If it's a date, parse it and make a timestamp default: /// Default is to make a DBText pv = KayaString(strtowc(val)); fld = KayaUnion(0,1); KayaUnionSetArg(fld,0,pv); KayaArrayPush(row,fld); } } KayaArrayPush(resarray,KayaArrayVal(row)); } PGRes* pgr = new PGRes(); pgr -> res_table = resarray; pgr -> rows = numrows; pgr -> cols = numflds; pgr -> col_names = col_names; PQclear(res); return pgr; } Array* pg_getstrs(void* res) { return ((PGRes*)res)->res_table; } int pg_numrows(void* res) { return ((PGRes*)res)->rows; } int pg_numcols(void* res) { return ((PGRes*)res)->cols; } Array* pg_colnames(void* res) { return ((PGRes*)res)->col_names; } void pg_close(void* conn) { PQfinish(((PGCon*)conn)->con); } // not genuine prepared statements for now void* do_pg_prepare(wchar_t* query) { return (void*)CSTRING(query); } void* pg_execp(void* vmptr,void* conn,void* queryptr, KayaValue err, KArray params) { char* query = (char*)queryptr; VMState* vm = (VMState*)vmptr; PGCon* pgc = (PGCon*)conn; pg_getTypeIDs(vm,pgc); int sz = KayaArraySize(params); char** cparams; if (sz == 0) { cparams = NULL; } else { cparams = (char**)malloc(sizeof(char*)*sz); for (int i=0;icon,query, sz,// number of params NULL, // untyped cparams, // params NULL, // text params NULL, // text params 0 ); if (cparams != NULL) { free(cparams); } if (res==NULL) { KayaSetString(err, KSTRING(PQerrorMessage(pgc->con))); return NULL; } if ((PQresultStatus(res)!=PGRES_COMMAND_OK) && (PQresultStatus(res) != PGRES_TUPLES_OK)) { KayaSetString(err, KSTRING(PQresultErrorMessage(res))); return NULL; } int numrows = PQntuples(res); int numflds = PQnfields(res); KayaArray resarray = newKayaArray(numrows); for(int i = 0; itypids[ty]) { case DBINT: /// If it's an int, make a DBInt(val) pv = KayaInt(atoi(val)); fld = KayaUnion(1,1); KayaUnionSetArg(fld,0,pv); KayaArrayPush(row,fld); break; case DBFLOAT: /// If it's a float, make a DBFloat(val) pv = KayaFloat(atof(val)); fld = KayaUnion(2,1); KayaUnionSetArg(fld,0,pv); KayaArrayPush(row,fld); break; case DBBOOL: /// If it's a bool, make a DBBool(val) if (val[0]=='t') { pv = KayaInt(1); } else { pv = KayaInt(0); } fld = KayaUnion(4,1); KayaUnionSetArg(fld,0,pv); KayaArrayPush(row,fld); break; case DBTIME: /// TODO: If it's a date, parse it and make a timestamp default: /// Default is to make a DBText pv = KayaString(strtowc(val)); fld = KayaUnion(0,1); KayaUnionSetArg(fld,0,pv); KayaArrayPush(row,fld); } } KayaArrayPush(resarray,KayaArrayVal(row)); } PGRes* pgr = new PGRes(); pgr -> res_table = resarray; pgr -> rows = numrows; pgr -> cols = numflds; PQclear(res); return pgr; } kaya-0.4.4/libs/curses_glue.cc0000644000175100017510000001107211170340770014331 0ustar cimcim#include "curses_glue.h" #include bool testerr(void* x) { return (kint)x == ERR; } void docbreak() { cbreak(); } void donocbreak() { nocbreak(); } void doecho() { echo(); } void donoecho() { noecho(); } void donl() { nl(); } void dononl() { nonl(); } void doraw() { raw(); } void donoraw() { noraw(); } void* getstdscr() { return (void*)stdscr; } void* doinitscr() { return (void*)initscr(); } void dointrflush(void* v, bool bf) { intrflush((WINDOW*)v,bf); } void dokeypad(void* v, bool bf) { #ifndef WIN32 keypad((WINDOW*)v,bf); #endif } void dometa(void* v, bool bf) { meta((WINDOW*)v,bf); } void donodelay(void* v, bool bf) { #ifndef WIN32 nodelay((WINDOW*)v,bf); #endif } void donotimeout(void* v, bool bf) { notimeout((WINDOW*)v,bf); } void dorefresh() { refresh(); } void dowrefresh(void* win) { // char buf[50]; // sprintf(buf,"Refreshing %d",win); // addstr(buf); wrefresh((WINDOW*)win); } void dowmove(void* w, int y, int x) { wmove((WINDOW*)w,y,x); } void domove(int y, int x) { move(y,x); } void doaddstr(wchar_t * s) { addstr(wctostr(s)); } void dowaddstr(void* w, wchar_t * s) { waddstr((WINDOW*)w, wctostr(s)); } int mkAtt(KayaValue v) { int tag = KayaUnionGetTag(v); switch(tag) { case 0: return A_NORMAL; break; case 1: return A_STANDOUT; break; case 2: return A_UNDERLINE; break; case 3: return A_REVERSE; break; case 4: return A_BLINK; break; case 5: return A_DIM; break; case 6: return A_BOLD; break; case 7: return A_PROTECT; break; case 8: return A_INVIS; break; case 9: return A_ALTCHARSET; break; case 10: return A_CHARTEXT; break; case 11: return COLOR_PAIR(KayaGetInt(KayaUnionGetArg(v,0))); break; } } int att_to_int(KayaArray attribs) { int a=0; for(int i=0;i bool testerr(void* x) { return (kint)x == ERR; } void docbreak() { cbreak(); } void donocbreak() { nocbreak(); } void doecho() { echo(); } void donoecho() { noecho(); } void donl() { nl(); } void dononl() { nonl(); } void doraw() { raw(); } void donoraw() { noraw(); } void* getstdscr() { return (void*)stdscr; } void dointrflush(void* v, bool bf) { intrflush((WINDOW*)v,bf); } void* doinitscr() { setlocale(LC_ALL,""); return (void*)initscr(); } void dokeypad(void* v, bool bf) { keypad((WINDOW*)v,bf); } void dometa(void* v, bool bf) { meta((WINDOW*)v,bf); } void donodelay(void* v, bool bf) { nodelay((WINDOW*)v,bf); } void donotimeout(void* v, bool bf) { notimeout((WINDOW*)v,bf); } void dorefresh() { refresh(); } void dowrefresh(void* win) { // char buf[50]; // sprintf(buf,"Refreshing %d",win); // addstr(buf); wrefresh((WINDOW*)win); } void dowmove(void* w, int y, int x) { wmove((WINDOW*)w,y,x); } void domove(int y, int x) { move(y,x); } void doaddstr(wchar_t * s) { addstr(wctostr(s)); } void dowaddstr(void* w, wchar_t * s) { waddstr((WINDOW*)w, wctostr(s)); } int mkAtt(KayaValue v) { int tag = KayaUnionGetTag(v); switch(tag) { case 0: return A_NORMAL; break; case 1: return A_STANDOUT; break; case 2: return A_UNDERLINE; break; case 3: return A_REVERSE; break; case 4: return A_BLINK; break; case 5: return A_DIM; break; case 6: return A_BOLD; break; case 7: return A_PROTECT; break; case 8: return A_INVIS; break; case 9: return A_ALTCHARSET; break; case 10: return A_CHARTEXT; break; case 11: return COLOR_PAIR(KayaGetInt(KayaUnionGetArg(v,0))); break; } } int att_to_int(KayaArray attribs) { int a=0; for(int i=0;i #include #include using namespace std; class SQLiteConnection : public gc { public: sqlite3* db; int ok; }; class SQLiteStatement : public gc_cleanup { public: sqlite3_stmt* stmt; SQLiteStatement(sqlite3_stmt* s):stmt(s) {} ~SQLiteStatement() { if (stmt != NULL) { sqlite3_finalize(stmt); } } }; class SQLiteResult : public gc { public: KArray res_table; KArray col_names; int rows; int cols; int res; sqlite3_stmt* resptr; }; extern "C" { void* sqlite_connect(wchar_t* info); int sqlite_ok(void* con); wchar_t* sqlite_getError(void* con); void sqlite_close(void* con); void* sqlite_exec(void* con, wchar_t* query); void* sqlite_incexec(void* con, wchar_t* query); KArray sqlite_getrow(void* vmptr, void* con); void sqlite_discard(void* sptr); void* sqlite_execp(void* stptr, KArray params); void* sqlite_prepare(void* vmptr, void* con, wchar_t* query); KArray sql_getcolnames(void* res); KArray sql_getrestable(void* res); int sql_numrows(void* res); int sql_numcols(void* res); int sql_resrc(void* res); } #endif kaya-0.4.4/libs/image_glue.cc0000644000175100017510000001302311170340770014105 0ustar cimcim#include "image_glue.h" #include #include #include #include #include #include "binary_glue.h" #include void* createImage(int x,int y, int tc) { if (tc) { return (void*)(gdImageCreateTrueColor(x, y)); } else { return (void*)(gdImageCreate(x, y)); } } void destroyImage(void* img) { gdImagePtr p = (gdImagePtr)img; gdImageDestroy(p); } /// Returns an Image directly KayaValue createImageFromPNG(void* f) { gdImagePtr p = gdImageCreateFromPng((FILE*)f); int x = p->sx; int y = p->sy; KayaValue img = KayaUnion(0,3); KayaUnionSetArg(img,0,KayaInt((kint)p)); KayaUnionSetArg(img,1,KayaInt(x)); KayaUnionSetArg(img,2,KayaInt(y)); return img; } /// Returns an Image directly KayaValue createImageFromJPEG(void* f) { gdImagePtr p = gdImageCreateFromJpeg((FILE*)f); int x = p->sx; int y = p->sy; KayaValue img = KayaUnion(0,3); KayaUnionSetArg(img,0,KayaInt((kint)p)); KayaUnionSetArg(img,1,KayaInt(x)); KayaUnionSetArg(img,2,KayaInt(y)); return img; } int imageColourAllocate(void* img, int r, int g, int b, int a) { gdImagePtr p = (gdImagePtr)img; return gdImageColorAllocateAlpha(p,r,g,b,a); } void imageLine(void* img, int x1, int y1, int x2, int y2, int col) { gdImagePtr p = (gdImagePtr)img; gdImageLine(p, x1,y1,x2,y2, col); } void imageDashedLine(void* img, int x1, int y1, int x2, int y2, int col) { gdImagePtr p = (gdImagePtr)img; gdImageDashedLine(p, x1,y1,x2,y2, col); } void imageSetPixel(void* img, int x, int y, int col) { gdImagePtr p = (gdImagePtr)img; gdImageSetPixel(p, x,y, col); } void imageDrawPoly(void* img, KayaArray pts, int col, int filled) { gdImagePtr p = (gdImagePtr)img; int size = KayaArraySize(pts); gdPoint* points = new gdPoint[size]; for(int i=0;iargs[0] = new Value(bindata,KVT_INT); bin->args[1] = MKINT(binsize); return new Value((void*)bin,KVT_UNION); */ KayaValue bin = KayaUnion(0,2); KayaUnionSetArg(bin,0,KayaInt((kint)bindata)); KayaUnionSetArg(bin,1,KayaInt(binsize)); return bin; } void* fontGetSmall() { return (void*)(gdFontSmall); } void* fontGetLarge() { return (void*)(gdFontLarge); } void* fontGetMediumBold() { return (void*)(gdFontMediumBold); } void* fontGetGiant() { return (void*)(gdFontGiant); } void* fontGetTiny() { return (void*)(gdFontTiny); } void imageString(void* img, void* font, int x, int y, wchar_t* rawstr, int col, int up) { char* str = wctostr(rawstr); gdImagePtr p = (gdImagePtr)img; gdFontPtr f = (gdFontPtr)font; if (up) { gdImageStringUp(p,f,x,y,(unsigned char*)str,col); } else { gdImageString(p,f,x,y,(unsigned char*)str,col); } } kaya-0.4.4/libs/cursesw_glue.h0000644000175100017510000000501211170340770014357 0ustar cimcim/* Chris Morris 26 June 2005, based on curses_glue.h by Edwin Brady and released under the same license */ #ifndef _CURSESW_GLUE_H #define _CURSESW_GLUE_H #include #include #include #include #define DECLKEY(x) wchar_t key_## x(); #define DEFKEY(x) wchar_t key_## x() { return KACHAR(KEY_## x); } #define DECLKEYF(x) wchar_t key_F## x(); #define DEFKEYF(x) wchar_t key_F## x() { return KACHAR(KEY_F(x)); } extern "C" { bool testerr(void* x); void docbreak(); void donocbreak(); void doecho(); void donoecho(); void donl(); void dononl(); void doraw(); void donoraw(); void* doinitscr(); void* getstdscr(); void dointrflush(void* v, bool bf); void dokeypad(void* v, bool bf); void dometa(void* v, bool bf); void donodelay(void* v, bool bf); void donotimeout(void* v, bool bf); void dorefresh(); void dowrefresh(void* win); void dowmove(void* w, int y, int x); void domove(int y, int x); wchar_t dogetch(); wchar_t domvgetch(int x, int y); wchar_t dowgetch(void* win); wchar_t dowmvgetch(void* win, int x, int y); wchar_t* dogetstr(); wchar_t* dowgetstr(void* win); void doaddstr(wchar_t * s); void dowaddstr(void* w, wchar_t * s); int doattron(KayaArray attribs); int doattroff(KayaArray attribs); int dowattron(void* w,KayaArray attribs); int dowattroff(void* w,KayaArray attribs); int getBlack(); int getRed(); int getGreen(); int getYellow(); int getBlue(); int getMagenta(); int getCyan(); int getWhite(); int getColourPairs(); int getColours(); void* donewwin(int l, int c,int y, int x); int dodelwin(void* win); int domvwin(void* win, int y, int x); DECLKEY(DOWN); DECLKEY(UP); DECLKEY(LEFT); DECLKEY(RIGHT); DECLKEY(BACKSPACE); DECLKEY(A1); DECLKEY(A3); DECLKEY(B2); DECLKEY(C1); DECLKEY(C3); DECLKEY(HOME); DECLKEY(END); DECLKEY(PPAGE); DECLKEY(NPAGE); DECLKEYF(1); DECLKEYF(2); DECLKEYF(3); DECLKEYF(4); DECLKEYF(5); DECLKEYF(6); DECLKEYF(7); DECLKEYF(8); DECLKEYF(9); DECLKEYF(10); DECLKEYF(11); DECLKEYF(12); void* docurs_set(int s); int dobox(void* win,wchar_t x, wchar_t y); void doclear(); void doerase(); void doclrtobot(); void doclrtoeol(); void dowclear(void* p); void dowerase(void* p); void dowclrtobot(void* p); void dowclrtoeol(void* p); } #endif kaya-0.4.4/libs/curses_glue.h0000644000175100017510000000457411170340770014204 0ustar cimcim#ifndef _CURSES_GLUE_H #define _CURSES_GLUE_H #include #include #include #define DECLKEY(x) wchar_t key_## x(); #define DEFKEY(x) wchar_t key_## x() { return KACHAR(KEY_## x); } #define DECLKEYF(x) wchar_t key_F## x(); #define DEFKEYF(x) wchar_t key_F## x() { return KACHAR(KEY_F(x)); } extern "C" { bool testerr(void* x); void docbreak(); void donocbreak(); void doecho(); void donoecho(); void donl(); void dononl(); void doraw(); void donoraw(); void* doinitscr(); void* getstdscr(); void dointrflush(void* v, bool bf); void dokeypad(void* v, bool bf); void dometa(void* v, bool bf); void donodelay(void* v, bool bf); void donotimeout(void* v, bool bf); void dorefresh(); void dowrefresh(void* win); void dowmove(void* w, int y, int x); void domove(int y, int x); wchar_t dogetch(); wchar_t domvgetch(int x, int y); wchar_t dowgetch(void* win); wchar_t dowmvgetch(void* win, int x, int y); wchar_t* dogetstr(); wchar_t* dowgetstr(void* win); void doaddstr(wchar_t * s); void dowaddstr(void* w, wchar_t * s); int doattron(KayaArray attribs); int doattroff(KayaArray attribs); int dowattron(void* w,KayaArray attribs); int dowattroff(void* w,KayaArray attribs); int getBlack(); int getRed(); int getGreen(); int getYellow(); int getBlue(); int getMagenta(); int getCyan(); int getWhite(); int getColourPairs(); int getColours(); void* donewwin(int l, int c,int y, int x); int dodelwin(void* win); int domvwin(void* win, int y, int x); DECLKEY(DOWN); DECLKEY(UP); DECLKEY(LEFT); DECLKEY(RIGHT); DECLKEY(BACKSPACE); DECLKEY(A1); DECLKEY(A3); DECLKEY(B2); DECLKEY(C1); DECLKEY(C3); DECLKEY(HOME); DECLKEY(END); DECLKEY(PPAGE); DECLKEY(NPAGE); DECLKEYF(1); DECLKEYF(2); DECLKEYF(3); DECLKEYF(4); DECLKEYF(5); DECLKEYF(6); DECLKEYF(7); DECLKEYF(8); DECLKEYF(9); DECLKEYF(10); DECLKEYF(11); DECLKEYF(12); int dobox(void* win,wchar_t x, wchar_t y); void* docurs_set(int s); void doclear(); void doerase(); void doclrtobot(); void doclrtoeol(); void dowclear(void* p); void dowerase(void* p); void dowclrtobot(void* p); void dowclrtoeol(void* p); } #endif kaya-0.4.4/libs/SQLiteDB_stub.k0000644000175100017510000000037511170340770014266 0ustar cimcimmodule SQLiteDB; import DB; import Prelude; Exception SQLiteError(String msg); abstract data SQLiteConnection = SQLiteCon(Ptr cdata); type SQLiteDB = DBHandle; public SQLiteDB connect(String fname) { throw(Not_Implemented); } kaya-0.4.4/libs/pg_inter.h0000644000175100017510000000244211170340770013463 0ustar cimcim#ifndef _PG_INTER_H // -*-C++-*- #define _PG_INTER_H // Glue functions for talking to libpq #include #include #include #include using namespace std; typedef enum { DBTEXT, DBINT, DBFLOAT, DBBOOL, DBTIME } DBtype; /// These class names are rubbish and confusing!!!!1!!! class PGCon : public gc { public: PGconn* con; int ok; map typids; }; class PGRes : public gc { public: KayaArray res_table; KayaArray col_names; int rows; int cols; }; extern "C" { /// Returns a PGCon void* pg_connect(wchar_t* conninfo); /// Tests if a connection is ok bool pg_ok(void* conn); /// Returns an error message wchar_t* pg_getError(void* conn); /// Returns a PGRes void* pg_exec(void* vmptr,void* conn,wchar_t* query, KayaValue err); /// Gets the strings from a PGRes KayaArray pg_getstrs(void* res); /// Return the number of rows in a result int pg_numrows(void* res); /// Return the number of columns in a result int pg_numcols(void* res); /// Returns the field names in a result Array* pg_colnames(void* res); /// Close the connection void pg_close(void* conn); void* do_pg_prepare(wchar_t* query); void* pg_execp(void* vmptr,void* conn,void* queryptr, KayaValue err, KArray params); } #endif kaya-0.4.4/libs/Threads.k0000644000175100017510000000776511170340770013266 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "POSIX thread threading support This module supports threading using the \"pthread\" library." module Threads; import Builtins; %include "thread_glue.h"; %imported "thread_glue"; %link "pthread"; foreign "thread_glue.o" { "Terminate the current thread. Terminate the current thread. Returning from the function used to create the thread also ends the thread. kill waitFor" public Void end() = endThread; Ptr docreateThread(fn func,arg fnarg) = createThread; Ptr docreateThreadNullary(fn func) = createThreadNullary; Void dokillThread(Ptr tid) = killThread; a dowaitForThread(Ptr tptr) = waitForThread; Ptr docreateMutex() = createMutex; Void dolock(Ptr m) = lock; Void dounlock(Ptr m) = unlock; } "A thread. Threads are parameterised using their return type for type safety in waitFor. create" abstract data Thread = Thread(Ptr tptr); "A Mutex. This data type represents a mutex. mutex" abstract data Mutex = Mutex(Ptr mptr); "The function to execute. The argument to pass to the function. Create a thread. Create a new thread that executes the specified function. waitFor may be used to find the return value of the function. create" public Thread create(b(a) fn, a arg) { id = docreateThread(fn,arg); return Thread(id); } "The parameterless function to execute. Create a thread. Create a new thread that executes the specified function. waitFor may be used to find the return value of the function. create" public Thread create(b() fn) { id = docreateThreadNullary(@fn); return Thread(id); } "The thread to wait for Wait for a thread to terminate. Wait for a thread to terminate and return the thread's return value. end kill" public rettype waitFor(Thread id) { return dowaitForThread(id.tptr); } "The thread to kill Kill a thread immediately Kill a thread immediately end waitFor" public Void kill(Thread id) { dokillThread(id.tptr); } "Create a mutex. Create a new mutex. lock unlock" public Mutex mutex() { m = docreateMutex(); return Mutex(m); } "A mutex Lock a mutex. Lock a mutex. All other threads which attempt to lock this mutex will have to wait until it is unlocked. This prevents simultaneous access to shared resources. mutex unlock" public Void lock(Mutex m) { dolock(m.mptr); } "A mutex Unlock a mutex. Unlock a mutex, allowing other threads to lock it. lock mutex" public Void unlock(Mutex m) { dounlock(m.mptr); } kaya-0.4.4/libs/Makefile.in0000644000175100017510000000451611170340770013554 0ustar cimcimRVPATH=@srcdir@ VPATH=${RVPATH} LANGNAME = @LANGNAME@ KAYAC = ../compiler/@TARGET@ prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@/${LANGNAME} IMPORTDIR = ${libdir}/imports CXXFLAGS = @FPIC@ @EXTRAGCCOPTS@ -I../rts -I../@platform@ @PGINC@ -O2 -I../stdlib -I${VPATH}/../rts -I${VPATH}/../libs -I${VPATH}/../stdlib KAYAINC = @KAYAPROF@ -noenvlibs -I../rts -I../@platform@ @PGINC@ KAYAPARAM = -noprelude -nortchecks -nochase ${KAYAINC} -L ../rts -L ../stdlib -L../@platform@ -xmldocs -L ${VPATH}/../rts -L ${VPATH} INSTALLFLAGS = -m 644 SRCS = PostgresDB@PGSTUB@.@EXT@ Image.@EXT@ CursesW.@EXT@ Curses.@EXT@ \ Threads.@EXT@ Multicore.@EXT@ MyDB@MYSTUB@.@EXT@ \ SQLiteDB@SQLSTUB@.@EXT@ SDL.@EXT@ IFACE = @PGIFACE@ @GDIFACE@ @CURSESWIFACE@ @CURSESIFACE@ @THREADSIFACE@ \ @MYIFACE@ @SQLIFACE@ @SDLIFACE@ OBJS = @PGOBJS@ @GDOBJS@ @CURSESWOBJS@ @CURSESOBJS@ @THREADSOBJS@ \ @MYOBJS@ @SQLOBJS@ @SDLOBJS@ all: ${OBJS} install: mkdir -p ${DESTDIR}${libdir} mkdir -p ${DESTDIR}${IMPORTDIR} # install ${TARGET} ${LIBDIR} # install ${LIBTARGET} ${LIBDIR} -install ${INSTALLFLAGS} ${IFACE} ${DESTDIR}${IMPORTDIR} -install ${INSTALLFLAGS} ${OBJS} ${DESTDIR}${IMPORTDIR} clean: rm -f ${OBJS} ${IFACE} ${LIBTARGET} ${TARGET} rm -f Curses.k CursesW.k rm -f *.html *.xml rm -rf docs distclean: clean rm -f *~ Makefile rm -rf autom4te.cache Multicore.o: Threads.ki Threads.o: thread_glue.h MyDB.o: my_inter.h ../stdlib/DB.ki PostgresDB.o: pg_inter.h ../stdlib/DB.ki SQLiteDB.o: sqlite_inter.h ../stdlib/DB.ki Image.o: image_glue.h ../stdlib/Webapp.ki SDL.o: sdl_glue.h my_inter.o: my_inter.h pg_inter.o: pg_inter.h sqlite_inter.o: sqlite_inter.h thread_glue.o: thread_glue.h image_glue.o: image_glue.h sdl_glue.o: sdl_glue.h PostgresDB.o : PostgresDB@PGSTUB@.@EXT@ ${KAYAC} $< ${KAYAPARAM} -deprfail MyDB.o : MyDB@MYSTUB@.@EXT@ ${KAYAC} $< ${KAYAPARAM} -deprfail SQLiteDB.o : SQLiteDB@SQLSTUB@.@EXT@ ${KAYAC} $< ${KAYAPARAM} -deprfail Curses.o: Curses.@EXT@ ${KAYAC} $< ${KAYAPARAM} CursesW.o: CursesW.@EXT@ ${KAYAC} $< ${KAYAPARAM} Curses.@EXT@: Curses.head CursesCommon.@EXT@ cat ${VPATH}/Curses.head ${VPATH}/CursesCommon.@EXT@ > Curses.@EXT@ CursesW.@EXT@: CursesW.head CursesCommon.@EXT@ cat ${VPATH}/CursesW.head ${VPATH}/CursesCommon.@EXT@ > CursesW.@EXT@ %.o : %.@EXT@ ${KAYAC} $< ${KAYAPARAM} -deprfail %.ki : %.o @: kaya-0.4.4/configure.ac0000644000175100017510000003316611170340770013047 0ustar cimcimdnl -*- m4 -*- Andrew Chadwick dnl (Originally written by atc for mote, adapted by ecb for kaya) dnl Process this file with autoconf to produce ./configure dnl #AC_LANG_CPLUSPLUS #test `uname -m | sed -e 's/^\(...\).*/\1/'` == 'arm' dnl I'm surprised this isn't in the default set of macros - CIM AC_DEFUN(AC_ARG_DISABLE, [AC_ARG_ENABLE([$1],[$2],if test "$enableval" = "yes"; then [$3] fi, [$3])]) # KAYA_NEED_PROC definition m4_define([KAYA_MOO], [{ AC_PATH_PROG([$1], $2) test -n "[$]$1" || AC_MSG_ERROR([Can't find $2]) } ])# end KAYA_NEED_PROC # KAYA_USEFUL_PROC definition m4_define([KAYA_MAYBE], [{ AC_PATH_PROG([$1], $2) test -n "[$]$1" || AC_MSG_NOTICE([Can't find $2: $3]) } ])# end KAYA_USEFUL_PROC AC_INIT(compiler/Main.hs) AC_PREFIX_DEFAULT(~) AC_ARG_VAR(GHC,[Haskell compiler to use]) # AC_ARG_VAR(GHCI,[Haskell interpereter to use]) AC_ARG_VAR(HAPPY,[Parser generator]) AC_SUBST(LANGNAME,[kaya]) AC_SUBST(TARGET,[kayac]) AC_SUBST(EXT,[k]) AC_CHECK_SIZEOF(void*) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF([long long]) AC_SUBST(ac_cv_sizeof_voidp) AC_SUBST(ac_cv_sizeof_int) AC_SUBST(ac_cv_sizeof_long) AC_SUBST(ac_cv_sizeof_long_long) dnl Handle configure flags AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [Add debugging symbols]), [CXXFLAGS="-g -O0 -Wall -Wno-deprecated"; KAYAPROF="-g -O0"; INTERPROF="-g -O0"; GHCOPTS=""; ], [CXXFLAGS="-Wall -O2 -DNDEBUG -Wno-deprecated"; INTERPROF="-O2"; if test $ac_cv_sizeof_voidp = 4 ; then GHCOPTS="-O"; else GHCOPTS=""; fi ]) AC_ARG_ENABLE([profile], AS_HELP_STRING([--enable-profile], [Compile kayac, run-time system and standard library with profiling]), [CXXFLAGS="-Wall -DNDEBUG -pg"; KAYAPROF="-profile"; INTERPROF="-pg -O2"; GHCOPTS="-prof -auto-all"; ]) AC_SUBST(KAYAPROF) AC_SUBST(INTERPROF) AC_SUBST(GHCOPTS) dnl Checks for programs (after setting $CXXFLAGS ?). KAYA_MOO([GHC],[ghc]) # KAYA_MOO([GHCI],[ghci]) KAYA_MOO([HAPPY],[happy]) if [ ghc-pkg list | grep mtl- > /dev/null ] ; then AC_MSG_NOTICE([Found Haskell MTL package]) else AC_MSG_ERROR([Can't find Haskell MTL package]) fi KAYA_MAYBE([LIBTOOL],[libtool],[needed for static linking with kayac -static]) AC_PATH_PROG([BENCHTIMER],[time]) AC_PROG_CXX AC_LANG_CPLUSPLUS ####### Platform detection ############################# unameS=`uname -s` unameM=`uname -m` platform="" AC_CHECK_FUNC(fork, [platform="posix" ; AC_MSG_NOTICE([Using Posix]) NETLIB="// "; PATHSEP=":"; EXECUTABLE=""; POSIXMAN="Syslog.posix ServerLoop.posix Posix.posix Sockets.posix SCGI.posix Signal.posix"; GCCBINOPTS="-Wl,-zrelro -fPIC"; ## 64-bit architectures seem to have problems with -pie and -lgc together ## Even on 32-bit there's problems with debugging. Maybe later... # if (test $ac_cv_sizeof_voidp != "8"); then # FPIC="-fPIC -fPIE"; # GCCDYNOPTS="-pie"; # AC_MSG_NOTICE([Using position independent executables]) # else FPIC="-fPIC"; GCCDYNOPTS=""; # AC_MSG_NOTICE([Not using position independent executables]) # fi ], [platform="windows" ; AC_MSG_NOTICE([Using Windows]) NETLIB=""; PATHSEP=";"; EXECUTABLE=".exe"; POSIXMAN=""; FPIC=""; GCCBINOPTS=""; GCCDYNOPTS=""; ]) AC_SUBST(platform) AC_SUBST(NETLIB) AC_SUBST(PATHSEP) AC_SUBST(EXECUTABLE) AC_SUBST(POSIXMAN) AC_SUBST(FPIC) if test "$libdir" == '${exec_prefix}/lib' ; then if test "x$exec_prefix" = xNONE ; then if test "x$prefix" = xNONE ; then KLIBDIR=${ac_default_prefix}/lib else KLIBDIR=${prefix}/lib fi else KLIBDIR=${exec_prefix}/lib fi else KLIBDIR=$libdir fi AC_SUBST(KLIBDIR) #### Essential Library checks ############################################ AC_CHECK_FUNC(gettimeofday, [GTOD_INTERNAL=0], [GTOD_INTERNAL=1]) AC_SUBST(GTOD_INTERNAL) AC_CHECK_FUNC(swprintf, [], # for wchar_t support (detects Cygwin non-support) AC_MSG_ERROR([Can't find wide character support])) if test $platform = "posix" ; then AC_CHECK_LIB(gmp, __gmpz_init, [], # for ghc linking AC_MSG_ERROR([Can't find libgmp.])) fi AC_CHECK_LIB(gc, GC_malloc, [], # for garbage collection AC_MSG_ERROR([Can't find libgc])) #AC_CHECK_LIB(cgi, cgi_init, [], # for cgi gadgetry # AC_MSG_ERROR([Can't find libcgi])) #AC_CHECK_HEADER([libcgi/cgi.h],[CGIINC="-I/usr/include/libcgi"], # [AC_CHECK_HEADER([cgi.h],[CGIINC=""])]) AC_CHECK_LIB(pcre, pcre_compile, [], # Perl compatible regular expressions AC_MSG_ERROR([Can't find libpcre])) AC_RUN_IFELSE([AC_LANG_PROGRAM([#include #include ],[const char* errptr; int erroffset; pcre* p = pcre_compile("abc",PCRE_UTF8,&errptr,&erroffset,NULL); if (p == NULL) { exit(1); } else { exit(0); }])], [AC_MSG_NOTICE([libpcre has UTF-8 support]) HASUTF8=""; ],[ AC_MSG_NOTICE([ *********************************** WARNING ********************************** libpcre does not support UTF-8 characters. Attempting to use UTF-8 characters when matching regular expressions will throw an Exception. We recommend you use a version of libpcre that supports UTF-8 if possible. ******************************************************************************]) HASUTF8="-DNOUTF8"; ],[]) AC_SUBST(HASUTF8) #AC_CHECK_LIB(ssl, EVP_EncryptInit, [], # OpenSSL # AC_MSG_ERROR([Can't find libssl]), [-lcrypto]) AC_CHECK_LIB(gcrypt, gcry_cipher_open, [], # for crypto AC_MSG_ERROR([Can't find libgcrypt])) AC_CHECK_HEADER([zlib.h]) AC_CHECK_LIB(z, compress, [], AC_MSG_ERROR([Can't find zlib])) # added 3/2/06 by CIM #AC_CHECK_LIB(gnutls, gnutls_global_init, [], # for crypto # AC_MSG_ERROR([Can't find libgnutls])) AC_CHECK_LIB(gnutls, gnutls_global_init, [], AC_MSG_ERROR([Can't find gnutls])) #AC_SUBST(CGIINC) ####### Optional libraries ############################# # PostgreSQL PGOBJS="" PGIFACE="" PGMAN="" PGINC="" AC_ARG_DISABLE([postgres], AS_HELP_STRING([--disable-postgres], [Disable Postgres database support]), [AC_CHECK_HEADER([postgresql/libpq-fe.h],[PGINC="-I/usr/include/postgresql"]) AC_CHECK_LIB(pq, PQconnectdb, [PGSTUB="" PGMAN="PostgresDB.libs" PGOBJS="pg_inter.o PostgresDB.o" PGIFACE="PostgresDB.ki"], [AC_MSG_NOTICE([Cannot find libpq, not compiling in postgres support]) PGSTUB="_stub" PGOBJS="PostgresDB.o" PGIFACE="PostgresDB.ki"])] ) AC_SUBST(PGOBJS) AC_SUBST(PGSTUB) AC_SUBST(PGMAN) AC_SUBST(PGIFACE) AC_SUBST(PGINC) # MySQL MYOBJS="" MYIFACE="" MYMAN="" MYINC="" AC_ARG_DISABLE([mysql], AS_HELP_STRING([--disable-mysql], [Disable MySQL database support]), [AC_CHECK_HEADER([mysql/mysql.h]) AC_CHECK_LIB(mysqlclient, mysql_init, [AC_MSG_NOTICE([Found libmysqlclient, is it recent enough?]) AC_CHECK_LIB(mysqlclient, mysql_stmt_init, [MYSTUB="" MYMAN="MyDB.libs" MYOBJS="my_inter.o MyDB.o" MYIFACE="MyDB.ki"], [AC_MSG_NOTICE([libmysqlclient is too old, not compiling in mysql support]) MYOBJS="MyDB.o" MYIFACE="MyDB.ki" MYSTUB="_stub"])], [AC_MSG_NOTICE([No libmysqlclient, not compiling in mysql support]) MYOBJS="MyDB.o" MYIFACE="MyDB.ki" MYSTUB="_stub"])]) AC_SUBST(MYOBJS) AC_SUBST(MYSTUB) AC_SUBST(MYIFACE) AC_SUBST(MYINC) AC_SUBST(MYMAN) # SQLite 3 SQLOBJS="" SQLIFACE="" SQLINC="" SQLIMAN="" AC_ARG_DISABLE([sqlite], AS_HELP_STRING([--disable-sqlite], [Disable SQLite database support]), [AC_CHECK_HEADER([sqlite3.h]) AC_CHECK_LIB(sqlite3, sqlite3_open, [SQLSTUB="" SQLIMAN="SQLiteDB.libs" SQLOBJS="sqlite_inter.o SQLiteDB.o" SQLIFACE="SQLiteDB.ki"], [AC_MSG_NOTICE([No libsqlite3, not compiling in SQLite support]) SQLOBJS="SQLiteDB.o" SQLIFACE="SQLiteDB.ki" SQLSTUB="_stub"])]) AC_SUBST(SQLOBJS) AC_SUBST(SQLSTUB) AC_SUBST(SQLIFACE) AC_SUBST(SQLIMAN) AC_SUBST(SQLINC) # GD GDOBJS="" GDIFACE="" GDMAN="" AC_ARG_DISABLE([gd], AS_HELP_STRING([--disable-gd], [Disable GD graphics library]), [AC_CHECK_HEADER([gd.h]) AC_CHECK_LIB(gd, gdImageCreate, [AC_MSG_NOTICE([Found libgd, is it recent enough?]) AC_CHECK_LIB(gd, gdImageCreateTrueColor, [GDOBJS="Image.o image_glue.o" GDIFACE="Image.ki" GDMAN="Image.libs"], [AC_MSG_NOTICE([libgd is too old, not compiling in image support])])], [AC_MSG_NOTICE([Can't find libgd, not compiling in image support])]) ]) AC_SUBST(GDMAN) AC_SUBST(GDOBJS) AC_SUBST(GDIFACE) # SDL SDLOBJS="" SDLIFACE="" SDLMAN="" AC_ARG_DISABLE([sdl], AS_HELP_STRING([--disable-sdl], [Disable SDL media library]), [AC_CHECK_HEADER([SDL/SDL.h]) AC_CHECK_LIB(SDL, SDL_Init, [SDLOBJS="SDL.o sdl_glue.o" SDLIFACE="SDL.ki" SDLMAN="SDL.libs"], [AC_MSG_NOTICE([Can't find libsdl, not compiling in SDL support])])]) AC_SUBST(SDLOBJS) AC_SUBST(SDLIFACE) AC_SUBST(SDLMAN) # OpenGL GLOBJS="" GLIFACE="" AC_ARG_DISABLE([opengl], AS_HELP_STRING([--disable-opengl], [Disable OpenGL 3D library]), [AC_CHECK_HEADER([GL/gl.h]) AC_CHECK_LIB(GL,glEnable, # The assumption here is that if you have GL, you'll have GLU and glut... [AC_CHECK_LIB(glut, glutInit, [AC_CHECK_LIB(GLU, gluPerspective, [GLOBJS="Glut.o GL.o glglue.o glutglue.o" GLIFACE="Glut.ki GL.ki"], [AC_MSG_NOTICE([Can't find GLU, not compiling in OpenGL support])])], [AC_MSG_NOTICE([Can't find glut, not compiling in OpenGL support])])], [AC_MSG_NOTICE([Can't find GL, not compiling in OpenGL support])])]) AC_SUBST(GLOBJS) AC_SUBST(GLIFACE) dnl Added 24/8/05 by CIM dnl Added 26/5/05 by CIM # CursesW CURSESWOBJS="" CURSESWIFACE="" CURSESWMAN="" AC_ARG_DISABLE([ncursesw], AS_HELP_STRING([--disable-ncursesw], [Disable nCurses wide console libraries]), [AC_CHECK_HEADER([ncursesw/ncurses.h]) AC_CHECK_HEADER([locale.h]) AC_CHECK_LIB(ncursesw, has_colors, [CURSESWOBJS="CursesW.o cursesw_glue.o" CURSESWMAN="CursesW.libs" CURSESWIFACE="CursesW.ki"], [AC_MSG_NOTICE([Can't find libncursesw, not compiling in wide ncurses support])])]) AC_SUBST(CURSESWOBJS) AC_SUBST(CURSESWIFACE) AC_SUBST(CURSESWMAN) dnl Moved Curses and Threads to libs - CIM 5/9/05 # Curses CURSESOBJS="" CURSESIFACE="" CURSESMAN="" KAYOBJS="" KAYIFACE="" KAYMAN="" AC_ARG_DISABLE([curses], AS_HELP_STRING([--disable-curses], [Disable Curses console libraries]), [AC_CHECK_HEADER([curses.h]) AC_CHECK_HEADER([locale.h]) AC_CHECK_LIB(curses, has_colors, [CURSESOBJS="Curses.o curses_glue.o" CURSESIFACE="Curses.ki" CURSESMAN="Curses.libs" KAYMAN="Kayurses.contrib" KAYIFACE="Kayurses.ki" KAYOBJ="Kayurses.o"], [AC_MSG_NOTICE([Can't find libcurses, not compiling in curses support])])]) AC_SUBST(CURSESOBJS) AC_SUBST(CURSESIFACE) AC_SUBST(CURSESMAN) AC_SUBST(KAYIFACE) AC_SUBST(KAYOBJ) AC_SUBST(KAYMAN) # Compress (moved to essential checks) #COMPRESSOBJS="" #COMPRESSIFACE="" #AC_CHECK_HEADER([zlib.h]) #AC_CHECK_LIB(z, compress, # [COMPRESSOBJS="Compress.o zlib_glue.o" # COMPRESSIFACE="Compress.ki"], # [AC_MSG_NOTICE([Can't find libz, not compiling in compression support])#]) # #AC_SUBST(COMPRESSOBJS) #AC_SUBST(COMPRESSIFACE) # Threads THREADSOBJS="" THREADSIFACE="" THREADSMAN="" AC_CHECK_HEADER([pthread.h]) AC_CHECK_LIB(pthread, pthread_exit, [THREADSOBJS="Threads.o Multicore.o thread_glue.o" THREADSIFACE="Threads.ki Multicore.ki" THREADSMAN="Threads.libs Multicore.libs"], [AC_MSG_NOTICE([Can't find libpthread, not compiling in threading support])]) AC_SUBST(THREADSMAN) AC_SUBST(THREADSOBJS) AC_SUBST(THREADSIFACE) #### FIN. #################################################################### #libdir=${prefix}/lib/${LANGNAME} # cygwin hack if (test -d "/cygdrive/c/temp/"); then tmpdir='c:/temp'; # MinGW hack (CIM 28/7/05) elif (test -d "/c/temp/"); then tmpdir='c:/temp'; elif (test -d "/tmp"); then tmpdir='/tmp'; else tmpdir='.'; fi version=`cat ${srcdir}/VERSION` ## Extra GCC options ## # linking works differently on different systems. Here's another hack to # guess what we're running on. # Useful 'safety net' options suggested by # http://lists.debian.org/debian-devel-announce/2008/01/msg00006.html #EXTRAGCCOPTS="-D_FORTIFY_SOURCE=2 -fstack-protector -Wl,-zrelro -FPIE -pie" EXTRAGCCOPTS="-D_FORTIFY_SOURCE=2 " #always ### -fstack-protector breaks static linking #if (test $(expr `gcc -dumpversion` ">=" 4.1) -eq 1); then #"-fstack-protector" # GCC 4.1 or later ## not available on alpha, ia64 yet, doesn't work on arm ## if it works on armel can fix later... # if (test $unameM != "ia64" && test $unameM != "alpha" && test `uname -m | sed -e 's/^\(...\).*/\1/'` != 'arm'); then # EXTRAGCCOPTS="-fstack-protector "${EXTRAGCCOPTS} # fi #fi AC_SUBST(GCCBINOPTS) # set in platform detection AC_SUBST(GCCDYNOPTS) # set in platform detection AC_SUBST(EXTRAGCCOPTS) # GHC library changes in version 6.4... ghcmajor=`ghc --numeric-version | cut -d '.' -f 1` ghcminor=`ghc --numeric-version | cut -d '.' -f 2` if [[ $ghcmajor -gt 6 ]] || ( [[ $ghcmajor -eq 6 ]] && [[ $ghcminor -ge 4 ]] ); then portmod='Portability64'; else portmod='Portability5'; fi # and also in 6.6 if [[ $ghcmajor -gt 6 ]] || ( [[ $ghcmajor -eq 6 ]] && [[ $ghcminor -ge 6 ]] ); then packages=''; showtupleon='{-'; showtupleoff='-}'; else packages='-package util -package lang'; showtupleon=''; showtupleoff=''; fi # and also in 6.10 if [[ $ghcmajor -gt 6 ]] || ( [[ $ghcmajor -eq 6 ]] && [[ $ghcminor -ge 10 ]] ); then readlinemodule='System.Console.Editline.Readline' else readlinemodule='System.Console.Readline' fi AC_SUBST(readlinemodule) AC_SUBST(tmpdir) AC_SUBST(version) AC_SUBST(portmod) AC_SUBST(packages) AC_SUBST(showtupleon) AC_SUBST(showtupleoff) AC_SUBST(unameS) AC_SUBST(unameM) AC_OUTPUT(Makefile compiler/Makefile rts/Makefile rts/sizes.h rts_opt/Makefile rts_fast/Makefile stdlib/Makefile windows/Makefile posix/Makefile libs/Makefile contrib/Makefile stdlib/Net.k man/Makefile bframe/Makefile example-programs/Makefile tools/Makefile compiler/Lib.hs compiler/REPL.hs compiler/Portability.hs) kaya-0.4.4/LGPL2.10000644000175100017510000006364011170340766011470 0ustar cimcim GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 library 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 Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! kaya-0.4.4/README0000644000175100017510000000633211170340770011434 0ustar cimcimWhat is Kaya? ------------- Kaya is a compiled scripting language, distributed for free under the GNU GPL. It is statically typed, meaning that the compiler will help you by checking for consistent variable usage and reporting errors before you run your program. It also uses type inference, meaning that the types of variables are worked out by the compiler, so there is no need for you to declare local variables, or use type casts. Kaya also has built-in abstractions for web application development, making it easy to write a CGI program without paying too much attention to low level details such as state management and form handling. The language design also ensures high quality HTML output and removes many possibilities for common web application security vulnerabilities. Installation and obtaining: --------------------------- See the INSTALL file for more information on installing Kaya. You can obtain new versions of Kaya from http://kayalang.org/download The very low traffic kaya-announce mailing list (subscribe at http://lists.kayalang.org/lists/listinfo/kaya-announce) carries new version releases and other important Kaya announcements. Documentation: -------------- The Kaya install process will automatically build API man pages for those modules where it is supported. All API documentation is also available on the web at http://kayalang.org/library Several tutorials introducing various aspects of Kaya and covering common tasks are also on the web at http://kayalang.org/tutorial What's new? ----------- If you're upgrading from an older version of Kaya, you should read the CHANGELOG file to see the important new features, bug fixes, etc. in this version. Support and community: ---------------------- If you have any questions about using or installing Kaya, find a bug, have an idea for future features, want to help with Kaya development, or just want to say hello and let us know what you're using Kaya for, then you can either: - email kaya@kayalang.org - join the kaya-devel mailing list at http://lists.kayalang.org/lists/listinfo/kaya-devel Licensing: ---------- All files in the Kaya distribution, unless otherwise stated in the file, are distributed under one of two licenses: - the 'kayac' compiler itself, and all documentation, miscellaneous utilities and everything else not explicitly mentioned below are licensed under the GNU General Public License (GPL) Version 2 or later - the run-time system, standard library, and optional libraries are licensed under the GNU Lesser General Public License (LGPL) Version 2.1 or later Please read the COPYING file for more details of exactly which files are covered by which license. The implications of this are that you may use Kaya to develop programs under any license you like (including closed-source licenses) for whatever purpose. However, any modifications you make to files from the Kaya distribution remain free, and if you distribute these modified files it must be under the license you have received them. Please note that some of the Kaya libraries (such as the MySQL connection library) link to third-party libraries under more restrictive licenses. If you develop programs that use these libraries you must of course *also* follow any provisions in that library's license. kaya-0.4.4/GPL20000644000175100017510000004310511170340766011207 0ustar cimcim GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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 Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. kaya-0.4.4/BUGS0000644000175100017510000000346711170340770011245 0ustar cimcimCurrently known bugs (09/06/08 v 0.4.2) Major (i.e. must be fixed for next version): * Problem with documentation generation on Mac Minor: * Functions which return Void behave incorrectly in HOFs where the function argument is polymorphic in its return type. * 'var' arguments do not work with partial function application. * Function applications need to be on names, rather than complex expressions. This should be more general, eg f.a[5](args) should be allowed. (5/2/05 - bit better now; as long as it's not a Void function, you can apply any typed expression). * Attempting to marshal Foreign Ptrs should be an error - need a built-in function table for Ptr. * The compiler should attempt to report as many errors as possible (might be tricky). * Should be a warning if module name doesn't correspond with filename, as module chasing won't work in that case. Not a problem for programs or webapps however. * Unhelpful error if main/Default/etc has the wrong type * Dependency chasing and recompiling doesn't work with include()d parts of modules, and nor does documentation generation. * Overloading functions with the same name and parameters but different return type compiles in the kayac stage but not in gcc stage * Overloading functions with different parameters types where the difference is based on type variables (e.g. Int(a,b,String) and Int(String,a,b(a))) gives functions with the same C name. * Overloading functions where the parameters of one type are a subset of the parameters of the other fails. * Error report for adding the same constructor twice in a case statement is unhelpful. * Building a .k file in a different directory doesn't generate -xmldocs correctly. * Pattern matcher can be very slow with some data types. * import public gives odd information in exception backtraces kaya-0.4.4/stdlib/0000755000175100017510000000000011170340770012031 5ustar cimcimkaya-0.4.4/stdlib/gcrypt_glue.cc0000644000175100017510000001335311170340770014671 0ustar cimcim#include "gcrypt_glue.h" #include extern char* kaya_secret; extern char* kaya_ivec; int ciphermode(KayaValue c) { switch(KayaUnionGetTag(c)) { case 0: return GCRY_CIPHER_MODE_ECB; break; case 1: return GCRY_CIPHER_MODE_CFB; break; case 2: return GCRY_CIPHER_MODE_CBC; break; case 3: return GCRY_CIPHER_MODE_STREAM; break; case 4: return GCRY_CIPHER_MODE_OFB; break; case 5: // return GCRY_CIPHER_MODE_CTR; return GCRY_CIPHER_MODE_NONE; break; } } int cipheralgo(KayaValue c) { switch(KayaUnionGetTag(c)) { case 0: return GCRY_CIPHER_IDEA; break; case 1: return GCRY_CIPHER_3DES; break; case 2: return GCRY_CIPHER_CAST5; break; case 3: return GCRY_CIPHER_BLOWFISH; break; case 4: return GCRY_CIPHER_AES128; break; case 5: return GCRY_CIPHER_AES192; break; case 6: return GCRY_CIPHER_AES256; break; case 7: return GCRY_CIPHER_TWOFISH; break; case 8: return GCRY_CIPHER_ARCFOUR; break; case 9: return GCRY_CIPHER_DES; break; default: return GCRY_CIPHER_NONE; // Can't happen break; } } int hashalgo(KayaValue c) { switch(KayaUnionGetTag(c)) { case 0: return GCRY_MD_SHA1; break; case 1: return GCRY_MD_RMD160; break; case 2: return GCRY_MD_MD5; break; case 3: return GCRY_MD_MD4; break; case 4: return GCRY_MD_TIGER; break; case 5: return GCRY_MD_SHA256; break; case 6: // return GCRY_MD_CRC32; return GCRY_MD_NONE; break; default: return GCRY_MD_NONE; // Can't happen break; } } int cipherKeySize(int c) { size_t len = 4; gcry_cipher_algo_info(c, GCRYCTL_GET_KEYLEN, 0, &len); return len; } int cipherBlockLength(int c) { size_t len = 4; gcry_cipher_algo_info(c, GCRYCTL_GET_BLKLEN, 0, &len); return len; } void* cipherOpen(KayaValue algo, KayaValue mode, int flags) { int cflags = 0; if (flags & 1) cflags += GCRY_CIPHER_SECURE; if (flags & 2) cflags += GCRY_CIPHER_ENABLE_SYNC; if (flags & 4) cflags += GCRY_CIPHER_CBC_CTS; if (flags & 8) cflags += GCRY_CIPHER_CBC_MAC; GcryptData* d = new GcryptData(); gcry_cipher_open(&(d->handle), cipheralgo(algo), ciphermode(mode), cflags); d->algo = cipheralgo(algo); return (void*)d; } void cipherClose(void* ptr) { GcryptData* d = (GcryptData*)ptr; gcry_cipher_close(d->handle); } void do_setkey(void* ptr, KayaArray key) { GcryptData* d = (GcryptData*)ptr; int size = KayaArraySize(key); char* keydata = (char*)KayaAlloc(size); for(int i=0;ihandle, keydata, size); } void do_setivec(void* ptr, KayaArray vec) { GcryptData* d = (GcryptData*)ptr; int size = KayaArraySize(vec); char* keydata = (char*)KayaAlloc(size); for(int i=0;ihandle, keydata, size); } void* do_encrypt(void* h, void* data, int size, KayaValue outsize) { GcryptData* d = (GcryptData*)h; int blklen = cipherBlockLength(d->algo); int newsize; void* newblock, *outbuf; // If size isn't a multiple of blklen, copy the data to a block which // is a multiple of blklen. newsize= size+blklen+(blklen-(size%blklen)); newblock = KayaAlloc(newsize); memcpy(newblock,data,size); data = newblock; size = newsize; // Create an output buffer of the right length. outbuf = KayaAlloc(size); gcry_cipher_encrypt(d->handle, (unsigned char*)outbuf, size, (unsigned char*)data, size); // printf("Size %d", size); KayaSetInt(outsize,size); return outbuf; } void* do_decrypt(void* h, void* data, int size, KayaValue outsize) { GcryptData* d = (GcryptData*)h; int blklen = cipherBlockLength(d->algo); int newsize; void* newblock, *outbuf; // If size isn't a multiple of blklen, copy the data to a block which // is a multiple of blklen. newsize= size+blklen+(blklen-(size%blklen)); newblock = KayaAlloc(newsize); // cout<<"decrypt:"<handle, (unsigned char*)outbuf, size, (unsigned char*)data, size); KayaSetInt(outsize,size); return outbuf; } void* hashOpen(KayaValue algo, int flags) { int hflags = 0; if (flags & 1) hflags += GCRY_MD_FLAG_SECURE; if (flags & 2) hflags += GCRY_MD_FLAG_HMAC; GcryptHash* d = new GcryptHash(); gcry_md_open(&(d->handle), hashalgo(algo),hflags); d->size = gcry_md_get_algo_dlen(hashalgo(algo)); d->algo = hashalgo(algo); return (void*)d; } void hashClose(void* ptr) { GcryptHash* d = (GcryptHash*)ptr; gcry_md_close(d->handle); } void hashReset(void* ptr) { GcryptHash* d = (GcryptHash*)ptr; gcry_md_reset(d->handle); } void hashWrite(void* ptr, void* data, int size) { GcryptHash* d = (GcryptHash*)ptr; gcry_md_write(d->handle, data, size); } void hashFinal(void* ptr) { GcryptHash* d = (GcryptHash*)ptr; gcry_md_final(d->handle); } void* hashGet(void* ptr, KayaValue size) { GcryptHash* d = (GcryptHash*)ptr; KayaSetInt(size,d->size); void* block = KayaAlloc(d->size); block = (unsigned char*)(gcry_md_read(d->handle,d->algo)); return block; } KayaArray appKey() { KayaArray key = newKayaArray(32); for(int i=3;i<35;++i) { KayaArrayPush(key,KayaChar(kaya_secret[i])); } return key; } KayaArray appIVec() { KayaArray key = newKayaArray(16); for(int i=3;i<19;++i) { KayaArrayPush(key,KayaChar(kaya_ivec[i])); } return key; } kaya-0.4.4/stdlib/WebCommon.k0000644000175100017510000007102511170340770014100 0ustar cimcim/** -*-C-*-ish WebCommon.k Copyright (C) 2004, 2005, 2006 Edwin Brady, Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ /* Functions common to Webapp.k and CGI.k */ "Common web application functions This module contains functions used in both the Webapp and CGI programming models, mostly covering the processing of user-supplied data and file uploading. The following tutorials from the Kaya website may be useful: Handling user-supplied data Processing file uploads" module WebCommon; import Prelude; import Dict; import Time; import System; import Strings; import Regex; import IO; import Mime; foreign "stdfuns.o" { String do_urlencode(Ptr vm, String str, Int len) = do_urlencode; String do_urldecode(Ptr vm, String str, Int len) = do_urldecode; } globals { Dict get_vars; Dict post_vars; Dict cookie_vars; Dict uploaded_files; Bool kaya_allow_fileuploads = false; String kaya_upload_dir = webProgTmp(); Int kaya_max_post_size = webProgPostMax(); } "An uploaded file. Represents a file uploaded using HTTP POST. These files can be retrieved with incomingFile or incomingFiles, and information about the file can be returned with originalName (to retrieve the original filename), tempPath (to get the temporary filesystem path) and contentType (to get the browser-reported content-type). There are various ways to set a temporary directory for file uploads. If none of these are used, the directory containing the CGI will be used, which is strongly discouraged except for testing purposes. incomingFile incomingFiles originalName tempPath contentType" abstract data Uploaded(String origname, String tmppath, String ctype); "The String contains the name of the missing key Specified key not in incoming data This Exception is thrown by incomingData and incomingValue if the specified key is not found in the specified data source. This can be avoided by using incomingExists to check if the key exists before trying to retrieve data. DataSource incomingData incomingExists incomingValue" Exception NotIncoming(String key); "URL encoding error This Exception is thrown if URL encoding fails. In practice, this should not happen. urlEncode" Exception urlEncodeError(); "URL decoding error This Exception is thrown if URL decoding fails. This happens if a % character in the string being decoded is not followed by a pair of hexadecimal digits. urlDecode" Exception urlDecodeError(); "A description of the error that caused this Exception The cookie was invalid This Exception is thrown if setCookie is given a parameter that does not meet the cookie standards." Exception InvalidCookie(String details); "The string to encode URL encode a string URL encode a string. You should use this to encode reserved characters in URLs that you wish to be passed literally. // trying to pass \"http://www.example.com\" as a parameter url = \"http://localhost/test.cgi?url=\"; url += urlEncode(\"http://www.example.com\"); // url = http://localhost/test.cgi?url=http%3A%2F%2Fwww.example.com Note that in the example above, encoding the whole URL would be incorrect - that would create a relative URL beginning \"http://\". urlDecode" public String urlEncode(String x) { try { return do_urlencode(getVM, x, length(x)); } catch(e) { throw(urlEncodeError); } } "The string to decode URL decode a string URL decode a string. This reverses the effect of urlEncode. This processing is already done by Kaya when handling GET and POST data, and so it is not necessary (and will usually cause data errors) to use this function on data from these sources. urlEncode" public String urlDecode(String x) { try { return do_urldecode(getVM, x, length(x)); } catch(e) { throw(urlDecodeError); } } "Data sources for incoming data Data sources for user-supplied data. DataGet is GET data, DataPost is POST data. DataRequest is a combination of the two (except that if any keys that occur in both sources, only the values from POST will be available for these sources). DataCookie retrieves cookies, and DataNone is always empty. DataRequest should only be used where the application is genuinely expected to receive user-supplied data by both request methods (for example, a search form). incomingData incomingExists incomingKeys incomingValue" public data DataSource = DataGet | DataPost | DataRequest | DataCookie | DataNone; /*** Initialisation and shutdown functions ***/ "Initialise the CGI or webapp. Do not call this function in a CGI or webapp This function initialises a CGI or webapp program, reading in GET, POST and cookie data. It is automatically called by the CGI and webapp 'template', and so should never need to be called again in a CGI or webapp (doing so will damage the GET and POST values)." public Void initWebApp(String queryString, String(String) env, Char() getbody, Bool() endbody) { // hopefully a reasonable amount of unpredictability here. srand((now()*microTime())%(now()+microTime())*getPID()); initVars(queryString,env,@getbody,@endbody); } "Remove uploaded files Uploaded files will be deleted from their temporary location at the end of CGI or webapp execution by this function, and so must be moved to some form of permanent storage if necessary. This function is automatically run at the end of CGI or webapp execution, but it is safe to call it earlier if you want to delete files before then." public Void removeTemporaryUploaded() { uploaded = vals(uploaded_files); for uploads in uploaded { for upload in uploads { tmpfile = upload.tmppath; try { unlink(tmpfile); } catch(e) { // let's just ignore this... } } } } Void initVars(String queryString, String(String) env, Char() getbody, Bool() endbody) { if (queryString == "") { query = env("QUERY_STRING"); } else { query = queryString; } cookie = env("HTTP_COOKIE"); len = Int(env("CONTENT_LENGTH")); postvars = ""; if (len > 0 && len <= kaya_max_post_size) { ctype = env("CONTENT_TYPE"); if (ctype == "application/x-www-form-urlencoded") { for x in [1..len] { postvars += getbody(); } post_vars = parseVars(postvars,['&']); uploaded_files = Dict::new(1); } else if (kaya_allow_fileuploads && length(ctype) >= 19 && substr(ctype,0,19) == "multipart/form-data") { mimeobjs = mimeDecode(@getbody,@endbody,len,findMimeBoundary(ctype),kaya_upload_dir); parseMime(mimeobjs); } else { // unrecognised content type for post post_vars = Dict::new(1,strHash); uploaded_files = Dict::new(1); } } else { // no post data post_vars = Dict::new(1,strHash); uploaded_files = Dict::new(1); } get_vars = parseVars(query,['&',';']); cookie_vars = parseVars(cookie,[';'],true); } Void parseMime([Mime] mimeobjs) { post_vars = Dict::new(47,strHash); uploaded_files = Dict::new(47); for mimeobj in mimeobjs { case mimeobj.mdata of { MimeString(text) -> case lookup(post_vars,mimeobj.name) of { nothing -> add(post_vars,copy(mimeobj.name),[copy(text)]); | just(x) -> push(x,copy(text)); } | MimeFile(fname,tname) -> case lookup(uploaded_files,mimeobj.name) of { nothing -> add(uploaded_files,copy(mimeobj.name),[Uploaded(copy(fname),copy(tname),copy(mimeobj.ctype))]); | just(y) -> push(y,Uploaded(copy(fname),copy(tname),copy(mimeobj.ctype))); } } } } Dict parseVars(String variables,[Char] separators,Bool oldcookies=false) { dict = Dict::new(47,strHash); if (variables == "") { return dict; } units = split("["+string(separators)+"]",variables); eqre = compile("="); for unit in units { if (unit != "") { parseUnit(dict,unit,eqre,oldcookies); } } return dict; } Void parseUnit(Dict dict, String unit, Regex eqre, Bool oldcookies=false) { dat = split(eqre,unit); if (size(dat) == 1) { val = ""; } else { val = dat[1]; } name = urlDecode(dat[0]); if (oldcookies && head(name) == '$') { return; // Set-Cookie or Set-Cookie2 -style cookies. Can be ignored. } val = urlDecode(val); case lookup(dict,name) of { nothing -> add(dict,name,[val]); | just(x) -> push(x,val); } } /*** GET/POST/Cookie/Files inspection functions ***/ "The source for user-supplied data Return keys for user-supplied data Returns all keys (in no particular order) with at least one value for the specified DataSource. // called with ?a=1;b=2;b=5 keys = incomingKeys(DataGet); // keys = [\"a\",\"b\"] or [\"b\",\"a\"] DataSource incomingData incomingExists incomingValue" public [String] incomingKeys(DataSource ds) { case ds of { DataGet -> return keys(get_vars); | DataPost -> return keys(post_vars); | DataCookie -> return keys(cookie_vars); | DataRequest -> dkeys = keys(post_vars); concat(dkeys,keys(get_vars)); nub(dkeys); return dkeys; | DataNone -> return createArray(1); } } "The key to retrieve data for The source for user-supplied data Returns all values for the specified key from user-supplied data Returns an array of all values for the key from the specified data source, or throws a NotIncoming Exception if no such key exists. // GET /example.cgi?a=1;b=3;b=5;z=;z;z vals = incomingData(\"a\",DataGet); // vals = [\"1\"] vals = incomingData(\"b\",DataGet); // vals = [\"3\",\"5\"] vals = incomingData(\"c\",DataGet); // NotIncoming exception thrown vals = incomingData(\"z\",DataGet); // vals = [\"\",\"\",\"\"] This is useful for processing the output from forms containing checkboxes with the same name or multiple selects. <form action='example.cgi' method='get'> <fieldset><legend>Example form</legend> <select multiple='multiple' name='a'> <option value='1'>Option 1</option> <option value='2'>Option 2</option> <option value='3'>Option 3</option> <option value='4'>Option 4</option> </select> <input type='submit' value='Test!'> </fieldset> </form> DataSource incomingExists incomingKeys incomingValue" // note, if same key in get and post, and DataRequest used, *all* // values in get will be ignored. public [String] incomingData(String key, DataSource ds) { lookups = createArray(2); case ds of { DataGet -> push(lookups,lookup(get_vars,key)); | DataPost -> push(lookups,lookup(post_vars,key)); | DataCookie -> push(lookups,lookup(cookie_vars,key)); | DataRequest -> push(lookups,lookup(post_vars,key)); push(lookups,lookup(get_vars,key)); | DataNone -> return createArray(1); // always succeeds but returns no values } for l in lookups { case l of { nothing -> ; | just(x) -> return copy(x); // incomingData must be read only! } } throw(NotIncoming(key)); } "The key to retrieve data for The source for user-supplied data Returns the first value for the specified key from user-supplied data Returns the first value for the key from the specified data source, or throws a NotIncoming Exception if no such key exists. // GET /example.cgi?a=1;b=3;b=5;z=;z;z val = incomingData(\"a\",DataGet); // val = \"1\" val = incomingData(\"b\",DataGet); // val = \"3\" val = incomingData(\"c\",DataGet); // NotIncoming exception thrown val = incomingData(\"z\",DataGet); // val = \"\" This is generally easier to use than incomingData if only one value is expected for that key. DataSource incomingData incomingExists incomingKeys" public String incomingValue(String key, DataSource ds) { return incomingData(key,ds)[0]; } "The key to check The source for user-supplied data Checks a key exists in user-supplied data Returns true if the key exists in the data source, and false otherwise. // GET /example.cgi?a=1;b=3;b=5;z=;z;z val = incomingExists(\"a\",DataGet); // val = true val = incomingExists(\"b\",DataGet); // val = true val = incomingExists(\"c\",DataGet); // val = false val = incomingExists(\"z\",DataGet); // val = true This is useful for avoiding Exceptions when using incomingData or incomingValue, or for checking if a checkbox has been selected. DataSource incomingData incomingKeys incomingValue" public Bool incomingExists(String key, DataSource ds) { case ds of { DataGet -> return exists(get_vars,key); | DataPost -> return exists(post_vars,key); | DataCookie -> return exists(cookie_vars,key); | DataRequest -> if (exists(post_vars,key)) { return true; } else { return exists(get_vars,key); } | DataNone -> return false; // never exists } } "Return keys for user-uploaded files Returns all keys (in no particular order) with at least one user-uploaded file associated. Browser behaviour differs on whether a key is sent when no file is uploaded, but in Kaya unused file upload keys are treated as not existing regardless of whether the browser sent no key or an empty key. allowFileUploads incomingFile incomingFileExists incomingFiles incomingKeys" public [String] incomingFileKeys() { return keys(uploaded_files); } "The key to return files for Return all files uploaded with a particular key name Returns an array of Uploaded for all user-uploaded files with the specified key, or throws a NotIncoming Exception if these are not present. allowFileUploads incomingData incomingFile incomingFileExists incomingFileKeys" public [Uploaded] incomingFiles(String key) { case lookup(uploaded_files,key) of { nothing -> throw(NotIncoming(key)); | just(uploaded) -> return uploaded; } } "The key to return files for Return the first file uploaded with a particular key name Returns an Uploaded for the first user-uploaded file with the specified key, or throws a NotIncoming Exception if these are not present. This is generaly easier than using incomingFiles if you are expecting multiple files. allowFileUploads incomingFileExists incomingFileKeys incomingFiles incomingValue" public Uploaded incomingFile(String key) { return incomingFiles(key)[0]; } "The key to check for files Check if any files are uploaded with a particular key name Returns true if any files have been uploaded with this key name. This is generally better than catching NotIncoming exceptions from incomingFile. if (incomingFileExists(\"picture\")) { pic = incomingFile(\"picture\"); myUploadProcessor(pic); } allowFileUploads incomingExists incomingFile incomingFileKeys incomingFiles" public Bool incomingFileExists(String key) { case lookup(uploaded_files,key) of { nothing -> return false; | just(uploaded) -> return true; } } /*** Configuration options ***/ // much easier if this isn't public - it doesn't need to be String webProgTmp() { if (getEnv("HTTP_KAYA_UPLOAD_DIR") != "") { return getEnv("HTTP_KAYA_UPLOAD_DIR"); } else { return "."; } } "The temporary directory. Set a temporary directory for Kaya file uploads. User file uploads are placed in a temporary directory. The default directory is the current directory for the CGI program or webapp, which is strongly discouraged for production use. There are two ways to set the new temporary directory, which should ideally be an otherwise empty directory outside the public website, only readable and writeable by the user the program runs as. Firstly, calling this function from within the CGI or webapp's webconfig function will set the directory. (Calls from any other location have no effect, because the uploaded files have already been saved to the temporary location by then!) Secondly, if this function has not been used, the HTTP_KAYA_UPLOAD_DIR environment variable (consult your webserver documentation for setting environment variables), will be read and used. This feature should not be used by application developers, who should use this function and provide an installer-configurable way to set the directory - it is intended to provide a means for Kaya application users to deal with applications which do not use this function. webapp example; import Webapp; import HTMLDocument; Void webconfig() { allowFileUploads(); setKayaUploadDir(\"/users/kaya/tmp\"); } HTMLDocument webmain() { // program goes here! } Note that Kaya (from 0.2.4 onwards) will not accept file uploads at all unless allowFileUploads is called first, so you don't need to use this function in applications that do not require file uploads unless your Kaya version is 0.2.2 or 0.2.3 allowFileUploads setKayaMaxPost" public Void setKayaUploadDir(String newdir) { kaya_upload_dir = newdir; } "Allow file uploads This function must be called from a webapp or CGI program's webconfig function to have any effect. It enables handling of user-uploaded files. If it is not called, HTTP POSTs with a content type of \"multipart/form-data\" (the type required for file uploads) will be treated as an unrecognised POST content type, and the POST data will be ignored. This is a security feature to avoid all webapps needing to use setKayaUploadDir even if they never need to handle files. If you do need file upload support and so use this function, you must also set a temporary upload directory. setKayaUploadDir" public Void allowFileUploads() { kaya_allow_fileuploads = true; } // again, easier if this is private Int webProgPostMax() { if (getEnv("HTTP_KAYA_POST_MAX_SIZE") != "") { return Int(getEnv("HTTP_KAYA_POST_MAX_SIZE")); } else { return 2097152; // 2Mb } } "The maximum size in bytes Sets the maximum size of POST data Sets the maximum size of POST data (in bytes) that the webapp or CGI will accept. This has no useful effect unless called from a webconfig function, as it will have already been called by then. POST data received above this size will be entirely discarded. The default value if this function is not called is 2097152 bytes (2 megabytes), unless the HTTP_KAYA_POST_MAX_SIZE environment variable is set. This will generally be sufficient unless you are handling large file uploads. setKayaUploadDir" public Void setKayaMaxPost(Int newmax) { kaya_max_post_size = newmax; } /*** retrieving Uploaded values */ // mustn't ever return a reference to the original value here. "A user-uploaded file Get the real name for the file Returns the name for the file supplied by the web browser. Note that this is usually but not necessarily the same as its name on the user's computer, but could be any string. You should filter this value for acceptable characters before using it! Uploaded allowFileUploads contentType tempPath" public String originalName(Uploaded file) = copy(file.origname); "A user-uploaded file Get the temporary filesystem path of the file Returns the temporary location of the user-uploaded file. The file will be deleted from this location when the webapp exits, so you must either copy it to a permanent location (filesystem, database, etc), or complete all your processing by the end of the webapp. Uploaded allowFileUploads contentType originalName" public String tempPath(Uploaded file) = copy(file.tmppath); "A user-uploaded file Get the content type of the file Returns the user-reported content type of the uploaded file (e.g. text/plain, application/pdf or image/png). Depending on the configuration of the user's system, this information may not be completely reliable, and of course a malicious user could deliberately give an incorrect content type, so you may need to perform additional checks in some circumstances. Uploaded allowFileUploads originalName tempPath" public String contentType(Uploaded file) = copy(file.ctype); "Return a local link URL to the current webapp or CGI Returns the URL to the current webapp or CGI. This function assumes that './executable' is a valid URL. If you are using Apache's mod_rewrite or another URL-rewriting system then this assumption may not be true and you should construct your own URL." public String webappName() { pn = getArgs()[0]; if (quickMatch("/",pn)) { // can't be true on windows replace(".*/","",pn); } else { // windows replace(".*\\\\","",pn); } // FIXME: will give the wrong answer if a file with a '\' in the filename // is an executable on a POSIX system. Unlikely as that is... return "./"+pn; } "The name of the cookie The value of the cookie The time that the cookie expires, which must be in GMT, or nothing if the cookie is a \"session cookie\" that expires when the web browser is closed (the default). The URL path to which the cookie will be returned. The default is nothing which sets it to the URL path of the current document. The URL path must begin with a '/' if it is explicitly set. The domain that the cookies will be sent to. The default of nothing gives the current hostname. If true (the default is false) this cookie will only be sent back to the server over HTTPS connections. Use this if the cookie contains or can be used to access any sensitive information unless you do not have HTTPS available. Create a cookie header Creates a cookie header that can be passed to HTMLDocument::addHTTPHeader or added to the headers list for functions such as Webapp::displayPage. Remember that cookies are not available in the page that sets them, since the web browser has not yet received them to send back at that point. expires = gmTime(time()+3600); // one hour later cookie = setCookie(\"session\",newSession(),just(expires)); addHTTPHeader(doc,cookie); The original Netscape cookie specification has more detail on the use of these fields. The functioning of the domain part is sometimes problematic. For example, there is no way to set a cookie that should be returned to server.example.com but not to test.server.example.com. CGI::header HTMLDocument::addHTTPHeader Webapp::displayPage" public (String,String) setCookie(String key, String value, Maybe = DBIncRes(DBHandle con, Int rows, Int cols, [String] colnames, Ptr resptr); "A prepared database statement A prepared database statement, for use with the prepared statement execution functions. execPrepared incExecPrepared prepare" public data DBStatement = DBStatement(DBHandle con, Ptr statement); "A database handle A database connection handle. The parameter is the specific handle type for a database, for example PGConnection for Postgres. The database-specific library will supply a function to create the handle. Note that this data type is not declared abstract as the database connection libraries need to modify its data - users should not do so! MyDB::connect PostgresDB::connect SQLiteDB::connect" public data DBHandle = DBh(a handle, DBResult(a,String) exec, DBIncResult(a,String,DBHandle) incexec, DBStatement(DBHandle,String) prep, DBResult(DBStatement,[Maybe]) execp, DBIncResult(DBStatement,[Maybe]) incexecp, [DBValue](DBIncResult) getrow, Void(DBIncResult) incdiscard, Void(a) close); "Execute a query Execute a query with the given connection handle. res = exec(conn,\"SELECT id,name FROM People\"); if (res.rows > 0) { for row in res.table { // row[0] = DBInt(id) // row[1] = DBText(name) } } Non-SELECT queries will generally not return any result rows. DBHandle DBResult DBValue incExec" public DBResult exec(DBHandle con, String query) { // fn = con.exec; return con.exec(con.handle, query); } "Execute an incremental query Execute a query with the given connection handle for incremental retrieval of results. Results are then retrieved one row at a time using getRow. Once you have finished with the query you must call incDiscard to discard any remaining rows. res = incExec(conn,\"SELECT id,name FROM People\"); row = getRow(res); // row[0] = DBInt(id) // row[1] = DBText(name) incDiscard(res); DBHandle DBIncResult DBValue exec getRow incDiscard" public DBIncResult incExec(DBHandle con, String query) { // fn = con.exec; return con.incexec(con.handle, query, con); } "Retrieve a row from an incremental query Retrieve a row from an incremental query. The row, once retrieved, is identical to one retrieved from a normal query. An Exception will be thrown if getRow is called on a result with no remaining rows. res = incExec(\"SELECT id,name FROM People\"); try { while(true) { row = getRow(res); processRow(row); } } catch(TooManyRows) { incDiscard(res); } DBIncResult DBValue incDiscard incExec" public [DBValue] getRow(DBIncResult res) { return res.con.getrow(res); } "Discard an incremental query Discard an incremental query once it is no longer needed. This may be once all rows have been read, or it may be sooner. Failing to use this function may cause memory usage to rise. DBIncResult getRow incExec" public Void incDiscard(DBIncResult res) { fn = res.con.incdiscard; fn(res); } "Close a connection Closes a database connection. DBHandle" public Void close(DBHandle con) { /// FIXME: Bah. The parser should be fixed to allow this to be done properly. fn = con.close; fn(con.handle); } "Get a column name Get a column name from a result. res = exec(conn,\"SELECT id,name FROM People\"); col = column(res,1); // \"name\" DBResult" public String column(DBResult res, Int col) { return (res.colnames[col]); } "Default function Databases that do not support incremental retrieval should use this function as the getrow field of their DBHandle. It will throw the Builtins::Not_Implemented Exception if called." public [DBValue] defaultGetRow(DBIncResult res) { throw(Not_Implemented); } "Default function Databases that do not support incremental retrieval should use this function as the incexec field of their DBHandle. It will throw the Builtins::Not_Implemented Exception if called." public DBIncResult defaultIncExec(a con, String query, DBHandle cptr) { throw(Not_Implemented); } "Default function Databases that do not support incremental retrieval should use this function as the incdiscard field of their DBHandle. It will throw the Builtins::Not_Implemented Exception if called." public Void defaultIncDiscard(DBIncResult res) { throw(Not_Implemented); } "Default function Databases that do not support prepared statements should use this function in the prep field of their DBHandle. It will throw the Builtins::Not_Implemented Exception if called." public DBStatement defaultPrepare(DBHandle con, String query) { throw(Not_Implemented); } "Default function Databases that do not support prepared statements should use this function in the execp field of their DBHandle. It will throw the Builtins::Not_Implemented Exception if called." public DBResult defaultExecPrepared(DBStatement con, [Maybe] params) { throw(Not_Implemented); } "Default function Databases that do not support prepared statements should use this function in the incexecp field of their DBHandle. It will throw the Builtins::Not_Implemented Exception if called." public DBIncResult defaultIncExecPrepared(DBStatement con, [Maybe] params) { throw(Not_Implemented); } "A database result cell Convert a database result to a String Convert a database result to a String DBValue bool float int time" public String string(DBValue val) { case val of { DBText(t) -> return t; | DBInt(i) -> return String(i); | DBFloat(f) -> return String(f); | DBBool(b) -> return String(b); // | DBTime(e) -> return mySQLTime(localTime(e)); | DBTime(e) -> return isoTime(e, [TwoFields]); } } "A database result cell Convert a database result to a Time Convert a database result to a Time. The coercion from DBBool is undefined and throws an Exception. DBValue Time::Time bool float int string" public Time time(DBValue val) { case val of { DBText(t) -> return strToTime(t); | DBInt(i) -> return localTime(i); | DBFloat(f) -> return localTime(Int(f)); | DBBool(b) -> return throw(Not_Implemented); // doesn't make sense | DBTime(e) -> return localTime(e); } } Time strToTime(String tstr) { return parseISO8601(tstr); } "A database result cell Convert a database result to an Int Convert a database result to an Int DBValue bool float string time" public Int int(DBValue val) { case val of { DBInt(i) -> return i; | DBText(t) -> return Int(t); | DBFloat(f) -> return Int(f); | DBBool(b) -> if(b) { return 1; } else { return 0; } | DBTime(e) -> return e; // a Unix Timestamp } } "A database result cell Convert a database result to a Bool Convert a database result to an Bool DBValue float int string time" public Bool bool(DBValue val) { case val of { DBInt(i) -> return i!=0; | DBText(t) -> return Int(t)!=0; | DBFloat(f) -> return f!=0.0; | DBBool(b) -> return b; | DBTime(e) -> return true; // doesn't make much sense } } "A database result cell Convert a database result to a Float Convert a database result to a Float DBValue bool int string time" public Float float(DBValue val) { case val of { DBInt(i) -> return Float(i); | DBText(t) -> return Float(t); | DBFloat(f) -> return f; | DBBool(b) -> if(b) { return 1.0; } else { return 0.0; } | DBTime(e) -> return Float(e); // not very meaningful } } "The database connection The query template. This may contain replacement characters at some places (consult the manual for the specific database to find out what replacement syntax should be used) which will be replaced with variables in the execPrepared function. Prepare a database query Prepare a database query. Prepared queries can then be executed later, using a parameter-replacement method that generally avoids SQL injection attacks. st = prepare(con,\"SELECT * FROM Users WHERE username = $1\"); DBStatement execPrepared" public DBStatement prepare(DBHandle con, String query) { return con.prep(con,query); } "The prepared database statement A list of parameters to be inserted into the query. An Exception may be thrown if the number of parameters does not match the expected number. nothing should be used for parameters that are to be replaced by NULL. If none of the parameters are NULL, then the other version of this function may be easier to use. Execute a prepared statement Execute a prepared statement, replacing parameters as specified. A single prepared statement may be used by multiple execPrepared functions, which increases efficiency. DBResult DBStatement exec execPrepared incExecPrepared prepare" public DBResult execPrepared(DBStatement statement, [Maybe] params) { return statement.con.execp(statement,params); } "The prepared database statement A list of parameters to be inserted into the query. An Exception may be thrown if the number of parameters does not match the expected number. This version of the function may not be used to insert NULL values. Execute a prepared statement Execute a prepared statement, replacing parameters as specified. A single prepared statement may be used by multiple execPrepared functions, which increases efficiency. DBResult DBStatement exec execPrepared incExecPrepared prepare" public DBResult execPrepared(DBStatement statement, [String] params) { ps = createArray(size(params)); for p in params { push(ps,just(p)); } return statement.con.execp(statement,ps); } "The prepared database statement A list of parameters to be inserted into the query. An Exception may be thrown if the number of parameters does not match the expected number. nothing should be used for parameters that are to be replaced by NULL. Incrementally execute a prepared statement Incrementally execute a prepared statement, replacing parameters as specified. A single prepared statement may be used by multiple incExecPrepared functions, which increases efficiency. DBIncResult DBStatement exec execPrepared prepare" public DBIncResult incExecPrepared(DBStatement statement, [Maybe] params) { return statement.con.incexecp(statement,params); } "The String to escape Escape a string to be used as part of a query Escapes backslashes, apostrophes and quotes in a string to protect against SQL injection attacks. This function should be used only as a last resort - prepared statements using prepare and execPrepared are supported by all database libraries, and are far less prone to human error." public String escape(String val) { /* // If there's any double quotes or \' somebody is probably trying to // outwit us... replace(r"'+", "'", val, [Global]); replace(r"\\'", "'", val, [Global]); // Now we only have single quotes next. replace("'", "''", val, [Global]); */ replace("\\\\","\\\\",val,[Global]); replace("'","\\'",val,[Global]); replace("\"","\\\"",val,[Global]); return val; } kaya-0.4.4/stdlib/Set.k0000644000175100017510000003414311170340770012745 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Sets: collections of unique values This module contains two implementations for collections of unique values. Set stores the values in order, whereas HashSet is unordered but has faster insertion and lookup. The Dict module may also be useful." module Set; import Prelude; "Collection of unique values. A collection of unique values stored as a hash table, which is usually faster than a Set but loses ordering." abstract data HashSet([[a]] entries, Int buckets, Int(a) hashfn); // TODO: If it seems worth it, replace this with a balanced binary tree. // The current version will be too slow for big sets where elements are // inserted in some kind of order. data STree = leaf | node(STree left, a val, STree right); "Ordered collection of unique values. An ordered collection of unique values stored as a binary tree. If ordering is not crucial, then HashSet is likely to be faster. Sets may be iterated over using a for loop." abstract data Set(STree entries, Int(a,a) cmp); "The comparison function to use for ordering. It must take two parameters, returning a negative number if the first parameter is smaller (whatever 'smaller' means in this context), positive if it is bigger, and zero if the two parameters are equal. For Ints, for example, the function Int icmp(Int a, Int b) = a-b; could be used. This argument may be omitted and defaults to Builtins::compare. Create a new empty set. Create a new empty set. Set add array delete elem empty" public Set newSet(Int(a,a) cmp = compare) = Set(leaf, cmp); "The set to add to The value to add Add an element into a Set. Add a new element to a Set. If the value is already in the set, does nothing. Set array delete elem empty newSet" public Void add(var Set set, a val) { add(set.entries,set.cmp,val); } Void add(var STree t, Int(a,a) cmp, a val) { case t of { leaf -> t = node(leaf, val, leaf); return; | node(l,v,r) -> cv = cmp(val,v); if (cv<0) { add(l, cmp, val); t.left = l; } else if (cv==0) return; else { add(r, cmp, val); t.right = r; } } } "The value to check for The set to check Check for an element in a Set. Returns true if the value exists in the set, and false otherwise. Set add array delete empty newSet" public Bool elem(a val, Set set) { t = set.entries; repeat case t of { leaf -> return false; | node(l,v,r) -> cv = set.cmp(val,v); if (cv<0) t = l; else if (cv==0) return true; else t = r; } return false; } "The set to delete from The value to delete Remove an element from a Set. Remove an element from a Set. If the value is not in the set, does nothing. Set add array elem empty newSet" public Void delete(var Set set, a val) { delete(set.entries, val, set.cmp); } "The block of code to execute for each set element. The set to traverse Iteration over Sets Used by for loops to traverse Set data structure. It is unlikely that you will need to call this function directly." public Void traverse(Bool(a, Int) block, Set set) { traverseAux(0, block, set.entries); } Void traverseAux(var Int i, Bool(a,Int) block, STree t) { case t of { leaf -> return; | node(l,v,r) -> traverseAux(i, block, l); if (!block(v, i)) return; i=i+1; traverseAux(i, block, r); } } Void delete(var STree t, a val, Int(a,a) cmp) { // First find the node case t of { leaf -> return; // phew, easy | node(l,v,r) -> cv = cmp(val,v); if (cv<0) { delete(l, val, cmp); t.left = l; } else if (cv == 0) { // Found it deleteRoot(t); } else { delete(r, val, cmp); t.right = r; } } } Void deleteRoot(var STree t) { // No left child, replace with right child. // (Obviously works if no child at all, since t then becomes a leaf) if (t.left==leaf) { // putStrLn("in case 1"); t = t.right; return; } // No right child, replace node with left child. if (t.right==leaf) { // putStrLn("in case 2"); t = t.left; return; } // Now we definitely have two children // Find the leftmost value in the right tree and use that as the // value of the node. val = deleteLeftmost(t.right); t.val = val; } a deleteLeftmost(var STree t) { // putStrLn("in deleteLeftmost"); if (t.left == leaf) { val = t.val; t = t.right; return val; } else { return deleteLeftmost(t.left); } } "The set to check Check whether a Set is empty Returns true if the Set is empty, false otherwise. Set add array delete elem newSet" public Bool empty(Set set) = set.entries == leaf; "The set to coerce Return all elements of a Set Return all the elements of a Set as an array, ordered according to the set's ordering predicate. Set add delete elem empty newSet" public [a] array(Set set) { arr = []; arrAux(set.entries, arr); return arr; } Void arrAux(STree t, var [a] arr) { case t of { leaf -> ; | node(l,v,r) -> arrAux(l, arr); push(arr,v); arrAux(r, arr); } } "The number of hashing buckets to use. A larger number of buckets increases the speed of the dictionary (up to a limit) but uses more memory. A good choice is the nearest prime number to 1.5*(expected number of entries), with the default being 157. The hashing function to use. This function must take a key, and return an integer. A good hashing function will return different values for similar keys (but must of course always return the same value for the same key!). A default built-in hashing function is provided, though if the keys are of type String, the Builtins::strHash function should be used instead, and if the keys are of type Int you may use Builtins::identity (though an array may provide faster insertion and lookup if the keys are positive and either small or largely sequential). If the keys are an especially complex data type, it may again be best to write your own hashing function. This argument may be omitted and defaults to Builtins::hash. Create a new empty HashSet. Create a new empty HashSet. HashSet add array delete elem empty" public HashSet newHashSet(Int buckets = 157, Int(a) hashfn = hash) = HashSet(createArray(buckets),buckets,hashfn); "The block of code to execute for each set element. The HashSet to traverse Iteration over HashSets Used by for loops to traverse HashSet data structure. It is unlikely that you will need to call this function directly. The order in which a HashSet is traversed is undefined." public Void traverse(Bool(a, Int) block, HashSet set) { i = 0; for ps in set.entries { if (isInitialised(ps)) { for p in ps { if (!block(p,i)) { return; } i++; } } } } "The set to add to The value to add Add an element into a HashSet. Add a new element to a HashSet. If the value is already in the set, does nothing. HashSet array delete elem empty newHashSet" public Void add(var HashSet set, a key) { // Find the right bucket bucket = abs(set.hashfn(key)) % set.buckets; if (!isInitialised(set.entries[bucket])) { // shouldn't need to be very large set.entries[bucket] = createArray(5); } // If a is already a key, no-op. for p in set.entries[bucket] { if (p==key) { return; } } push(set.entries[bucket],key); } "The value to check for The set to check Check for an element in a HashSet. Returns true if the value exists in the HashSet, and false otherwise. HashSet add array delete empty newHashSet" public Bool elem(a val, HashSet set) { // Find the right bucket bucket = abs(set.hashfn(val)) % set.buckets; d = set.entries[bucket]; if (!isInitialised(d)) { // can't be here return false; } for p in d { if (p==val) { return true; } } return false; } "The set to delete from The value to delete Remove an element from a HashSet. Remove an element from a HashSet. If the value is not in the set, does nothing. HashSet add array elem empty newHashSet" public Void delete(HashSet set, a key) { // Find the right bucket bucket = abs(set.hashfn(key)) % set.buckets; if (!isInitialised(set.entries[bucket])) { return; //can't be in here } ps = set.entries[bucket]; // If a is a key in ps, remove it. for z in [0..(size(ps)-1)] { if (ps[z]==key) { removeAt(ps,z); return; } } } "The set to check Check whether a HashSet is empty Returns true if the HashSet is empty, false otherwise. HashSet add array delete elem newHashSet" public Bool empty(HashSet set) { for ps in set.entries { for p in ps { return false; } } return true; } "The set to coerce Return all elements of a HashSet Return all the elements of a HashSet as an array. The elements will be returned in an arbitrary order. HashSet add delete elem empty newHashSet" public [a] array(HashSet set) { keys = []; for ps in set.entries { if (isInitialised(ps)) { for p in ps { push(keys,p); } } } return keys; } kaya-0.4.4/stdlib/Prelude.k0000644000175100017510000005614511170340770013620 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "The standard Prelude The standard Prelude will be imported by all Kaya programs and modules unless the -noprelude compiler option is used. It provides many essential and useful functions and data types used by the Kaya standard library and applications. Generally, only the standard library itself should not automatically import this module." module Prelude; import public Builtins; import public Maths; // Should this be here or not? import public Array; import public Tuples; import public Coercions; %include "math.h"; %include "ctype.h"; /** Some generally useful types and functions. All programs import this implicitly. */ /// Linked lists "Linked list type. nil creates an empty list, cons creates a non empty list. Linked lists may be iterated over using a for loop. list = cons(2,cons(5,cons(3,nil))); array reverse" public data List = nil | cons(a head,List tail); "The block of code to execute for each list element. The list to traverse Iteration over linked lists Used by for loops to traverse List data structure. It is unlikely that you will need to call this function directly." public Void traverse(Bool(a, Int) block, List list) { i = 0; repeat case list of { nil() -> break; | cons(x,list) -> if (!block(x, i)) { return; } i++; } } "The list to convert Coerce a linked list to an array. Converts a linked list to an array. list = cons(2,cons(5,cons(3,nil))); arr = array(list); // arr = [2,3,5] List" public [a] array(List xs) { acc = []; repeat case xs of { nil -> return acc; | cons(x,xs) -> push(acc,x); } return acc; } "The list to reverse Reverse a linked list in place. Reverse a linked list in place. List Arrays can be reversed in place with Array::reverse" public Void reverse(var List xs) { acc = nil; repeat case xs of { nil -> break; | cons(x,xs) -> acc = cons(x,acc); } xs = acc; } "Optional values. A value is either of type a, represented as just(a), or empty. Maybe is often useful for computations which can possibly fail, for example looking up values in a dictionary. Because the nothing value can be stored, this is often more useful than Exceptions on failure. deref Dict::lookup" public data Maybe = nothing | just(a val); "Tried to dereference an empty Maybe If deref is called on a Maybe equal to nothing this Exception will be thrown. Generally it is better to use a case statement if this is likely. deref" Exception CantDerefNothing; "Negative string length specified If substr is called in a way that would require the generation of a string with negative length (either because the length asked for is negative, or because the starting index is after the end of the string), this Exception will be thrown. substr" Exception NegativeLengthString(Int len); "Position out of range This Exception is thrown if the substr function is called with an index that is outside the string. substr" Exception PositionOutOfRange(Int pos); "The value to dereference Dereference a Maybe. Extract the value from a Maybe. An Exception is thrown if v is nothing. A case statemement is generally more appropriate unless it is known that the dereferencing should succeed (for example, using Dict::lookup on a key known to have been added). deref(x) is equivalent to x.val. Maybe CantDerefNothing" public a deref(Maybe v) { case v of { nothing -> throw(CantDerefNothing); | just(a) -> return a; } } // The foreign bits we use. foreign "stdfuns.o" { "The string to convert The base the string is in (2-36 inclusive) Convert a string, in the given base, to an integer Convert a string, in the given base, to an integer. str = \"101\"; bin = intBase(str,2); // 5 oct = intBase(str,8); // 65 dec = intBase(str,10); // 101 hex = intBase(str,16); // 257 stringBase" public Int intBase(String str, Int base) = strtoint; "The number to convert The base the number is in Convert an integer in the given base to a string. Convert an integer in the given base to a string. Currently the base may only be decimal (10), hex (16), or octal (8). intBase" public String stringBase(Int num, Int base) = inttostr; // "Change standard error stream" -- doesn't work portably // public Void setstderr(File f) = setStdErr; "Force a garbage collection Normally the Kaya garbage collector (libgc) runs in the background at appropriate times. Occasionally, it may be appropriate to garbage-collect immediately. Heavy use of this function carries a high cost in program execution time." public Void gc() = GC_gcollect; "Debugging function Get the heap size used by the garbage collector. This is generally only useful when debugging" public Int gcHeapSize() = GC_get_heap_size; "Debugging function Get a lower bound on the number of free bytes on the heap. This is generally only useful when debugging" public Int gcFreeBytes() = GC_get_free_bytes; "Debugging function Get the total number of bytes allocated by the garbage collector. This is generally only useful when debugging" public Int gcTotalBytes() = GC_get_total_bytes; "Debugging function Set the maximum heap size used by the garbage collector. This puts an upper limit on the memory usage of the program (a segfault will occur if it is exceeded)" public Void gcSetMaxHeapSize(Int size) = GC_set_max_heap_size; "Enable incremental garbage collection. Performs a small amount of garbage collection more often. Most likely will lead to slower (though smoother) performance, but with less overall memory usage. This function does nothing unless the -nortchecks compiler option was used, as it makes debugging much harder. This is generally recommended for interactive programs. This function is automatically used for CGI programs and webapps." public Void gcIncremental() = do_GC_enable_incremental; "The garbage collection parameter Debugging function Adjust garbage collector - higher values use less memory but run slower (the default value is 4, and a value of 1 disables garbage collection entirely). The default is almost always acceptable." public Int gcSetFSD(Int fsd) = GC_set_free_space_divisor; "Switch off garbage collector. You may want this, for example, before executing some time-critical code which should not be interrupted by a garbage collection. Even explicit calls to gc() are ineffective while collection is disabled. gcEnable gc" public Void gcDisable() = GC_disable; "Switch on garbage collector. Calls to gcDisable and gcEnable nest; collection is enabled if there have been an equal number of calls to each. gcDisable gc" public Void gcEnable() = GC_enable; // Removed (temporarily?) since VM no longer does needed instructions. // Int do_max_heapsize(Ptr vm) = maxMemUsage; "Register a function to call when object is garbage collected If additional cleanup is needed when an object is destroyed, this function registers a finalisation procedure. e.g. a record containing a file handle should make sure the file is closed when the object is deallocated. The object being watched The function to call when the object is destroyed. Takes the object as its argument" public Void onDestroy(a object, Void(a) destroyFn) = do_GC_finalizer; "The character Checks if the character is a digit Returns true if the character is a digit. isAlpha isAlnum isLineEnding isLower isPunct isUpper isGraph isSpace" public Bool isDigit(Char c) = iswdigit; "The character Checks if the character is alphabetical Returns true if the character is alphabetical. isAlnum isDigit isLineEnding isLower isPunct isUpper isGraph isSpace" public Bool isAlpha(Char c) = iswalpha; "The character Checks if the character is a digit or alphabetical Returns true if the character is a digit or alphabetical. isAlpha isDigit isLineEnding isLower isPunct isUpper isGraph isSpace" public Bool isAlnum(Char c) = iswalnum; "The character Checks if the character is punctuation Returns true if the character is punctuation. isAlpha isAlnum isDigit isLineEnding isLower isUpper isGraph isSpace" public Bool isPunct(Char c) = iswpunct; "The character Checks if the character is printable and not whitespace Returns true if the character is printable and not whitespace. isAlpha isAlnum isDigit isLineEnding isLower isPunct isUpper isSpace" public Bool isGraph(Char c) = iswgraph; "The character Checks if the character is whitespace Returns true if the character is whitespace. isAlpha isAlnum isDigit isLineEnding isLower isPunct isUpper isGraph" public Bool isSpace(Char c) = iswspace; "The character Checks if the character is a lower-case letter Returns true if the character is a lower-case letter. isAlpha isAlnum isDigit isLineEnding isPunct isUpper isGraph isSpace" public Bool isLower(Char c) = iswlower; "The character Checks if the character is an upper-case letter Returns true if the character is an upper-case letter. isAlpha isAlnum isDigit isLineEnding isLower isPunct isGraph isSpace" public Bool isUpper(Char c) = iswupper; "The character Converts the character to a lower-case letter Converts the character to a lower-case letter. Non-alphabetical characters are returned unchanged. This function may give unusual results with non-ASCII characters. toLower toUpper" public Char toLower(Char c) = towlower; "The character Converts the character to an upper-case letter Converts the character to an upper-case letter. Non-alphabetical characters are returned unchanged. This function may give unusual results with non-ASCII characters. toLower toUpper" public Char toUpper(Char c) = towupper; String dosubstr(Ptr vm, String x, Int i, Int len) = getsubstr; String do_strend(Ptr vm, String x, Int i) = getstrend; Void doPutStr(String text, Int len) = putStr; } "The string to print Send a string to standard output Print a String on standard output. Equivalent to put(stdout(),text);. putStrLn IO::put IO::stdout" public Void putStr(String text) { doPutStr(text,length(text)); } "The character Checks if the character is (part of) a line ending Returns true if the character is (part of) a line ending (i.e. '\\r' or '\\n'). isAlpha isAlnum isDigit isLower isPunct isUpper isGraph isSpace" public Bool isLineEnding(Char c) { return (c=='\n' || c=='\r'); } "The string to lower-case Returns a copy of the string with all letters lower-cased Returns a copy of the string with all letters lower-cased s = toLower(\"Hello World!\"); // s = \"hello world!\" This function may give unusual results with non-ASCII characters. toLower toUpper" public String toLower(String s) { c = copy(s); translate(c,toLower); return c; } "The string to upper-case Returns a copy of the string with all letters upper-cased Returns a copy of the string with all letters upper-cased s = toUpper(\"Hello World!\"); // s = \"HELLO WORLD!\" This function may give unusual results with non-ASCII characters. toLower toUpper" public String toUpper(String s) { c = copy(s); translate(c,toUpper); return c; } "The string to examine The index to start from Return the end of a String. Return the end of a string starting at character index i. strEnd(x,0) will return the entire string. If a negative i is given, then it will be counted backwards from the end of the string. x = \"abcdef\"; putStr(strEnd(x,2)); // \"cdef\" putStr(strEnd(x,5)); // \"f\" putStr(strEnd(x,6)); // \"\" putStr(strEnd(x,7)); // OutOfBounds Exception thrown putStr(strEnd(x,-3)); // \"def\" putStr(strEnd(x,-8)); // OutOfBounds Exception thrown substr" public String strEnd(String x, Int i) { strlen = length(x); if (i < -strlen || i > strlen) { throw(OutOfBounds); } else if (i < 0) { i += strlen; } return do_strend(getVM,x,i); } "The string to print Send a string and a newline to standard output. Print a string and a newline on standard output. putStr" public Void putStrLn(String text) { putStr(text+"\n"); } "File not found This function will be called if an attempt to access a non-existent file is made." Exception FileNotFound(); /// Functional programming features a runcompose(a(b) f, b(c) g, c arg) { return f(g(arg)); } "The first function to compose The second function to compose Compose two functions. Compose two functions: compose(f,g)(x) == f(g(x)). Float double(Float x) { return x*2.0; } Int roundDown(Float y) { return Int(floor(y)); } Void main() { combined = compose(roundDown,double); a = combined(3.6); // a = 7 } " public a(c) compose(a(b) f, b(c) g) { return runcompose@(f,g); } "The function to apply The argument Apply a function to an argument. Apply a function to an argument - useful for functional programming. apply(f,arg) is equivalent to f(arg). " public a apply(a(b) f, b arg) { return f(arg); } "The suspended function Evaluate a suspended function. Evaluate a suspended function. force(f) is equivalent to f(). The inverse of thunk" public a force(a() f) { return f(); } "The value to convert Turn a value into a function. For a given value, create a function that returns that value. The inverse of force" public a() thunk(a val) { return \() -> val; } //// Useful string functions "The string to repeat The number of times to repeat it Repeat a string Return the string str repeated x times. str = \"Abc\"; r = rep(str,4); // \"AbcAbcAbcAbc\" r = rep(str,1); // \"Abc\" r = rep(str,0); // \"\"" public String rep(String str, Int x) { s = createString(length(str)*x); for i in [1..x] { s+=str; } return s; } "The original string The starting index The substring length Return a substring. Starting at character i, return the len characters long substring. Throws an Exception if len is negative, or if i is out-of-bounds. In Kaya 0.2.4 and earlier, an Exception was also thrown if len was zero. The empty string is now returned in this case. If the starting index is negative, then it will be counted in characters from the end of the string. x = \"abcdef\"; s = substr(x,0,2); // \"ab\" s = substr(x,4,1); // \"e\" s = substr(x,3,10); // \"def\" (len truncated) s = substr(x,-4,2); // \"cd\"" public String substr(String x, Int i, Int len) { if (len < 0) { throw(NegativeLengthString(len)); } else { strlen = length(x); if (i < -strlen || i > strlen) { throw(PositionOutOfRange(i)); } else if (i < 0) { i += strlen; } if (i+len > strlen) { len = strlen-i; if (len <= 0) { // CIM: this should never happen now, but I'll // leave the check in just in case. throw(NegativeLengthString(len)); } } return dosubstr(getVM,x,i,len); } } kaya-0.4.4/stdlib/Mime.k0000644000175100017510000001757211170340770013110 0ustar cimcim/** -*-C-*-ish Mime.k Copyright (C) 2006 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Mime utilities for file uploads This module contains Mime utility functions for handling file uploads in CGI and webapps via WebCommon::initWebApp. It does not currently contain a complete Mime parser, and is very restricted in how it can handle Mime-encoded data in general." module Mime; /* This is not (yet) a complete MIME module. It is currently only designed * to handle multipart/form-data
    submissions in CGI. * It is also *experimental* only. Please do not rely on it to be bugfree yet! */ import Builtins; import Array; import Prelude; import Binary; import public IO; import Strings; import Regex; "A Mime object The name field contains the original name of the Mime object in the encoded input. The ctype field contains the content-type (e.g. text/plain) of the Mime object. The mdata field describes the content of the object MimeData" public data Mime(String name, String ctype, MimeData mdata); "Mime-encoded data Mime-encoded data. Depending on the nature of the data, it may either be stored in memory as a String, or on the filesystem with the original name and the current filesystem path recorded. Mime" public data MimeData = MimeString(String text) | MimeFile(String origname, String path); data MimeProcessState = DecodeHeaders | DecodeBody | DecodeBoundary; [Char] getBinaryLine(Char() nextchar, Bool() finalchar) { state = 0; chars = createArray(4096); sz = 0; // limit at 4096 unless the last character was a \r, in which case // read the next one in case it's a \n while (state != 2 && !finalchar() && (sz < 4096 || state == 1)) { sz++; char = nextchar(); push(chars,char); if (char == Char(13) && state == 0) { state = 1; } else if (char == Char(10) && state == 1) { state = 2; } else { state = 0; } } return chars; } "A function to return the next binary character from the data source The maximum amount of data to read from the file handle The MIME boundary string The path to store MimeFile temporary files. Defaults to the current directory if unspecified. Decode a Mime-encoded file Decodes a Mime-encoded file. This function is mainly a utility function for WebCommon::initWebApp and has little general use." public [Mime] mimeDecode(Char() nextchar, Bool() finalchar, Int maxlen, String boundary, String tmppath="") { csregex = compile(":\\s*"); // scregex = compile(";\\s*"); // coregex = compile(",\\s*"); eqregex = compile("="); blockname = ""; mimeobjs = createArray(100); bstack = [boundary]; state = DecodeBoundary; while (maxlen > 0 && !finalchar() && size(bstack) > 0) { chars = getBinaryLine(@nextchar,@finalchar); maxlen -= size(chars); // this will need some tweaking for chars 128-255 in non-file data line = string(chars); case state of { DecodeBoundary -> if (line == "--"+bstack[size(bstack)-1]+"\r\n") { state = DecodeHeaders; ctype = "text/plain"; fname = ""; fenc = ""; content = ""; anywritten = false; leavestate = DecodeBody; } | DecodeHeaders -> if (line == "\r\n") { state = leavestate; } else { trim(line); header = split(csregex,line,1,true); hkey = toLower(header[0]); if (hkey == "content-disposition") { hvals = fields(header[1],[';'],['"']); for hval in hvals { trim(hval); if (quickMatch(eqregex,hval)) { hitem = split(eqregex,hval,1); if (hitem[0] == "name") { blockname = unQuote(hitem[1]); } else if (hitem[0] == "filename") { fname = unQuote(hitem[1]); if (fname == "") { /* Gecko-based browsers treat an empty upload field as a zero-sized file with no filename. Other browsers seem to just not submit the field with the form at all. This makes Gecko-based browsers act roughly the same */ state = DecodeBoundary; } else { do { tmpname = tmppath+"/"+tmpMimeName(); } while (fileExists(tmpname)); mfh = open(tmpname,[Write]); anywritten = false; } // this shouldn't be an exploitable race, should it? } } } } else if (hkey == "content-type") { if (substr(header[1],0,10) == "multipart/") { leavestate = DecodeBoundary; bound = findMimeBoundary(header[1]); push(bstack,bound); } else { ctype = header[1]; } } else if (hkey == "content-transfer-encoding") { fenc = header[1]; } } | DecodeBody -> if (line == "--"+bstack[size(bstack)-1]+"\r\n" || line == "--"+bstack[size(bstack)-1]+"--\r\n") { if (line == "--"+bstack[size(bstack)-1]+"--\r\n") { pop(bstack); } if (fname == "") { if (substr(content,-2,2) == "\r\n") { push(mimeobjs,Mime(copy(blockname),copy(ctype),MimeString(substr(content,0,length(content)-2)))); } else if (substr(content,-1,1) == "\n" || substr(content,-1,1) == "\r") { push(mimeobjs,Mime(copy(blockname),copy(ctype),MimeString(substr(content,0,length(content)-1)))); } else { push(mimeobjs,Mime(copy(blockname),copy(ctype),MimeString(copy(content)))); } } else { push(mimeobjs,Mime(copy(blockname),copy(ctype),MimeFile(copy(fname),copy(tmpname)))); close(mfh); } state = DecodeHeaders; ctype = "text/plain"; fname = ""; fenc = ""; content = ""; leavestate = DecodeBody; } else { if (fname == "") { // trim(line); content += line; } else { // binary safe (last \r\n is a delimiter, not content... complicated) csz = size(chars); if (csz >= 4096 && (chars[csz-2] != '\r' || chars[csz-1] != '\n')) { mkanywritten = false; } else { mkanywritten = true; pop(chars);pop(chars); } if (anywritten) { putChar(mfh,'\r'); putChar(mfh,'\n'); } for char in chars { putChar(mfh,char); } anywritten = mkanywritten; } } } } return mimeobjs; } "A HTTP or SMTP header line Find the Mime boundary Parse a HTTP or SMTP header line to find the Mime boundary. Note that this function does not check that the string passed actually is an appropriate header, so this must be checked at the call site." public String findMimeBoundary(String header) { eqregex = compile("="); getbs = split(":\\s*",header,1); for getb in getbs { if (quickMatch(eqregex,getb)) { bound = split(eqregex,getb,1); } } return bound[1]; } "Name a temporary file Name a temporary file for storing MimeFile data. This function merely gives a random filename - it does not check whether the file exists first, which must be done by the function calling this. For the greatest safety, this function should be used only on paths that only the current process' user may write to." public String tmpMimeName() { chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_."; sc = length(chars); slength = 7+(abs(rand())%4); str = ""; for i in [1..slength] { str += substr(chars,abs(rand())%sc,1); } return "ktmp"+str; } "The input Unquote mime fields Some parts of Mime data may be quoted, but are not always. This helper function removes the quotes if they exist." public String unQuote(String input) { if (input == "\"\"") { return ""; } else if (quickMatch("^\".*\"$",input)) { return substr(input,1,length(input)-2); } else { return input; } } kaya-0.4.4/stdlib/Crypto.k0000644000175100017510000002345011170340770013471 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "High level cryptography/hashing functions This module contains the encryption and decryption wrappers for Kaya's built-in encryption used to secure web applications. Currently this encryption uses AES 256 encryption via the Gcrypt module and libgcrypt The encryption key used in the built-in encryption is normally contained within the application binary. If you are using this internal key, you must therefore keep the application binary safe from unauthorised reading (just as you would protect a config file containing database passwords). For convenience of administration, application may choose to use an externally provided key with the built-in encryption functions." module Crypto; import Builtins; import Strings; import Gcrypt; import Binary; import Prelude; import Regex; %include "crypto_glue.h"; %include "unistd.h"; %imported "crypto_glue"; foreign "crypto_glue.o" { [Int] getInternalKey() = getKey; // the Ivec isn't secret, but it might have good reason to be constant! [Int] getInternalIvec() = getIVec; } data KeyType = InternalKey | ExternalKey([Int] key); globals { KeyType appkey = InternalKey; KeyType appivec = InternalKey; } [Int] getKey() { case appkey of { InternalKey -> key = getInternalKey(); appkey = ExternalKey(copy(key)); // so can't set key after use! | ExternalKey(key) -> ; } return key; } [Int] getIVec() { case appivec of { InternalKey -> key = getInternalIvec(); appivec = ExternalKey(copy(key)); // so can't set key after use! | ExternalKey(key) -> ; } return key; } "The new encryption key. This must be an array of integers, containing exactly 32 integers between 0 and 255. An Exception will be thrown if the parameter is unsuitable. For security, encryption keys should be generated from a good-quality random number source. Set application secret key Sets the application secret key used by encode and decode to a new value for the remainder of program execution. You can obtain the key from a variety of sources (e.g. a flat file, or a database entry) - the easiest way is probably to read 32 bytes from a file with IO::getChar. Using an external application key removes the requirement that the application binary be strongly protected (by moving the requirement to whatever the key source is, of course). This may be useful for installing common web application binaries to a shared folder. Web applications should call this function from within their webconfig function to avoid unpredictable results. Also to avoid unpredictable results, this function may only be called once per program run, and must be called before any other function that uses the key. An Exception will be thrown if this is called for a second time or too late. Note: While an unscrupulous application writer could use this function to ensure that the effective application key could not be changed by kaya-rekey, they could find far easier and less easily detectable ways to put a backdoor into any application that users were unable to recompile or verify." public Void setEncryptionKey([Int] key) { case appkey of { ExternalKey(ek) -> throw(InvalidExternalKey("External key already set")); | InternalKey -> if (size(key) != 32) { throw(InvalidExternalKey("Key must have a length of 32")); } for k@i in key { if (k < 0 || k > 255) { throw(InvalidExternalKey("Each key digit must be in the range 0..255 (error at digit "+i+")")); } } // copy to make especially sure that there's no problem with references. appkey = ExternalKey(copy(key)); } } "The new ivec. This must be an array of integers, containing exactly 16 integers between 0 and 255. An Exception will be thrown if the parameter is unsuitable. The ivec is not secret and does not need to be generated in any particular way. Set application Ivec Sets the application Ivec used by encode and decode to a new value for the remainder of program execution. You can obtain the key from a variety of sources (e.g. a flat file, or a database entry) - the easiest way is probably to read 16 bytes from a file with IO::getChar. The Ivec is not secret, but in some cases you may need it to be consistent. Web applications should call this function from within their webconfig function to avoid unpredictable results. Also to avoid unpredictable results, this function may only be called once per program run, and must be called before any other function that uses the key. An Exception will be thrown if this is called for a second time or too late." public Void setEncryptionIvec([Int] ivec) { case appivec of { ExternalKey(ek) -> throw(InvalidExternalKey("External Ivec already set")); | InternalKey -> if (size(ivec) != 16) { throw(InvalidExternalKey("Ivec must have a length of 16")); } for k@i in ivec { if (k < 0 || k > 255) { throw(InvalidExternalKey("Each Ivec digit must be in the range 0..255 (error at digit "+i+")")); } } // copy to make especially sure that there's no problem with references. appivec = ExternalKey(copy(ivec)); } } "Invalid external key or Ivec This Exception is thrown when the key or Ivec supplied to setEncryptionKey or setEncryptionIvec is invalid. The parameter describes the reason." Exception InvalidExternalKey(String reason); "Invalid hash This Exception is thrown when the hash supplied with the data to decrypt doesn't match the decrypted data. In webapps and CGI programs this guards against data corruption." Exception InvalidDecryptionHash(); "Invalid encrypted data This Exception is thrown when the data to decrypt isn't valid data generated with encode." Exception InvalidEncryptedData(); "The String to encode Encode a String using the AES256 algorithm. Encode a String using the AES256 algorithm. The value is encoded with the application's secret key, which is compiled in automatically (unless overridden with setEncryptionKey). The return value is base64 encoded and also includes a hash which will be verified when the String is decoded. The value will only be decodable by the Kaya application that encoded it, provided that the application secret key is not revealed. You must therefore ensure no-one has read access to the application key (whether this is in the Kaya binary or an external source) if you need to rely on the integrity of the data (for example, in CGI or webapps). Should you suspect the key is compromised, you can change an internal key by recompiling the binary, or using the kaya-rekey utility. decode" public String encode(String msg) { h = openCipher(AES256, CBC, createArray(1)); setCipherKey(h,getKey); setCipherIVec(h,getIVec); // putStrLn(msg); enc = encryptString(h,msg); // putStrLn("Encoded: "+enc); closeCipher(h); hh = openHash(SHA1, createArray(1)); hashString(hh,msg); msghash = Binary::base64Encode(getHash(hh)); // putStrLn("Hash: "+msghash); closeHash(hh); encoded = enc+","+msghash; //marshal((enc,msghash),9); // putStrLn(encoded); return encoded; //Strings::base64encode(encoded); } // old version: // public String encode(String str) = doencode(getVM(),str); "The String to decode Decode a String using the AES256 algorithm. Decode a String using the AES256 algorithm. The value to decode must have been generated by the encode function in an application with the same secret key (which usually requires it to be the same application). If decoding fails (due to bad input) an Exception is thrown. encode" public String decode(String msgin) { strs = split(",",msgin); if (size(strs) != 2) { throw(InvalidEncryptedData); } msg = strs[0]; hash = strs[1]; // (String,String) todecode = unmarshal(Strings::base64decode(msgin),9); // msg = todecode.fst; // hash = todecode.snd; h = openCipher(AES256, CBC, createArray(1)); setCipherKey(h,getKey); setCipherIVec(h,getIVec); dec = decryptString(h,msg); // putStrLn("Decoded: "+dec); closeCipher(h); hh = openHash(SHA1,createArray(1)); hashString(hh,dec); dechash = base64Encode(getHash(hh)); // putStrLn("Hash: "+dechash+" ("+(dechash==hash)+")"); if (dechash!=hash) { // putStrLn(dechash+" "+hash); // putStrLn(dec); throw(InvalidDecryptionHash); } closeHash(hh); return dec; } "The String to hash Generate a secure hash from a String. Use the SHA256 algorithm to generate a secure hash from a String, for example for encrypting passwords. Unlike the other Crypto functions, this function is not application-dependent." public String secureHash(String pwd) { h = openHash(SHA256,createArray(1)); hashString(h,pwd); return base64Encode(getHash(h)); } // old version // public String decode(String str) = dodecode(getVM(),str); kaya-0.4.4/stdlib/Coercions.k0000644000175100017510000001056211170340767014143 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Function versions of coercions This modules defines function versions of the coercions between built-in types. string(x) is equivalent in function to the explicit coercion String(x) but as it may be applied as a function, it may be partially applied, used as a function parameter, etc. Additionally, the coercion to Void is defined for discarding the output of a function with side-effects. It is automatically imported (via the Prelude module) unless the -noprelude compiler option is used." module Coercions; import Builtins; import Array; // Function versions of built-in coercions. These give first-class versions // of coercions which may be useful for higher order functions, or for // further overloading for built-in data-types. "The Int to coerce Built-in coercion Built-in coercion from Int to String in function form." public String string(Int x) = String(x); "The Float to coerce Built-in coercion Built-in coercion from Float to String in function form." public String string(Float x) = String(x); "The Char to coerce Built-in coercion Built-in coercion from Char to String in function form." public String string(Char x) = String(x); "The Bool to coerce Built-in coercion Built-in coercion from Bool to String in function form." public String string(Bool x) = String(x); "The String to coerce Built-in coercion Built-in coercion from String to Int in function form." public Int int(String x) = Int(x); "The Float to coerce Built-in coercion Built-in coercion from Float to Int in function form." public Int int(Float x) = Int(x); "The Char to coerce Built-in coercion Built-in coercion from Char to Int in function form. Coercion uses the Unicode Character Set." public Int int(Char x) = Int(x); "The String to coerce Built-in coercion Built-in coercion from String to Float in function form." public Float float(String x) = Float(x); "The Int to coerce Built-in coercion Built-in coercion from Int to Float in function form." public Float float(Int x) = Float(x); "The Int to coerce Built-in coercion Built-in coercion from Int to Char in function form. Coercion uses the Unicode Character Set" public Char char(Int x) = Char(x); "The value to discard Coercion to Void. Coerces any value to Void (i.e. discards it), usually used for discarding the result of a function. For example, the HTMLDocument functions for adding elements to the tree return the element just added, which is often not necessary. p = addParagraph(doc.body,\"Hello \"); void(appendInlineElement(p,StrongEmphasis,\"World!\")); Another use is in discarding the return value from database update queries" public Void void(a x) {} "The String to unpack Unpack a string to characters. Unpack a string to characters. s = \"abcde\"; cs = array(s); // cs = ['a,'b','c','d','e']" public [Char] array(String x) { l = length(x); xs = createArray(l); for(i=0;iThe list of Chars to pack Pack an array of characters into a string. Pack an array of characters into a string. cs = ['a','b','c','d','e']; s = string(cs); // s = \"abcde\"" public String string([Char] x) { str = createString(size(x)); for c in x { str=str+String(c); } return str; } kaya-0.4.4/stdlib/Builtins.k0000644000175100017510000007045011170340770014004 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Built-in functions This module contains built-in functions that are used by the Kaya run-time, functions required by the rest of the Prelude, and other fundamental functions. It is automatically imported (via the Prelude module) unless the -noprelude compiler option is used. All programs must import this module, and most modules will need to." module Builtins; /* The only global we use in this module is to seed the random number generator. */ globals { Int randseed; } // Exception thrown by foreign code "An internal code for the Exception is contained in the Int Thrown by the run-time system and foreign functions. This Exception may be thrown by run-time system calls or foreign functions." Exception InternalError(Int code); // Now for some built in exceptions in the run-time system // (CONVENTION NOTE, ECB 1/3/07: I put underscores in these because they are // meant to be read as error messages rather than caught by user programs. If // this is considered ugly or offends anyone's sense of style, sorry :). // I don't think it's important enough to worry about though...) "Tried to read a field incorrectly This Exception is thrown when a field is projected from a data type that does not have fields, for example: a = \"Hello\".world; In the example, the compiler would catch the error - in practice this error can occur when accessing an uninitialised value, or a value with inconsistent type information due to foreign function calls." Exception Project_From_Non_Union(); "Tried to lookup in an array This Exception is thrown when an array lookup is performed on something other than an array: a = \"Hello\"[1]; In the example, the compiler would catch the error - in practice this error can occur when accessing an uninitialised value, or a value with inconsistent type information due to foreign function calls." Exception Lookup_From_Non_Array(); "Array index must be non-negative Array indexes vary from 0 to (2**31)-1. Negative array indexes are not allowed and will return this Exception." Exception Negative_Array_Index(); "Tried to get a field from the wrong constructor This exception is thrown when direct projection of a field is used on a value constructed with a different constructor. It can always be avoided by the use of case statements. data Example = A(Int a) | B(String b); Void main() { val = A(3); putStrLn(val.b); }" Exception Wrong_Constructor(); "Tried to do a constructor case statement wrongly This Exception is thrown when a case statement is used on something other than an ADT, for example: i = 5; case i of { A(a) -> putStrLn(a); | B(b) -> putStrLn(b); } In the example, the compiler would catch the error - in practice this error can occur when accessing an uninitialised value, or a value with inconsistent type information due to foreign function calls." Exception Getting_Tag_From_Non_Union(); /* // call stack now expands properly "Too many recursive function calls If there are too many function calls inside each other, the call stack will overflow and cause this Exception. Call stack overflow can often be avoided using \"tail recursion\" and adding an accumulating parameter. Int triangle(Int a) { if (a <= 1) { r = 1; } else { r = a+triangle(a+1); } return r; } Int triangleTR(Int a, Int acc = 1) { if (a <= 1) { return acc; } else { return triangleTR(a+1, a+acc); } } The triangleTR function calls itself as its last action before returning, and so a tail recursion optimisation can be made to avoid inflating the call stack." Exception Call_Stack_Overflow(); */ "The unmarshal ID was invalid The unmarshal was passed a marshalling ID that was not the same as the one used to marshal the data. marshal unmarshal" Exception Invalid_Marshalling_ID(); "The function table has changed The unmarshal was passed a marshalled String where the program function table is different to the one used to marshal the data. Marshalling and unmarshalling may only be done reliably within one instance of a program binary (though may be done across multiple invocations). marshal unmarshal" Exception Invalid_Function_Table_Hash(); "Invalid or uninitialised value This Exception is usually thrown when operations are carried out on an uninitialised value, for example: xs = []; xs[0] = \"Hello\"; if (xs[0] == xs[300]) { // Invalid_Value thrown } It may also be thrown by unmarshal if the marshalled String is corrupt." Exception Invalid_Value(); "Not implemented yet This exception is thrown if a function is called that is not implemented yet, or is not applicable in the current situation." Exception Not_Implemented(); "Marshal string describes an impossible structure This Exception is thrown by unmarshal where the marshalled String describes an impossible circular structure." Exception Invalid_Circular_Structure(); "Exceptions may not be marshalled This Exception will be thrown if you attempt to marshal an Exception." Exception Cant_Marshal_Exceptions(); "Exceptions may not be reflected This Exception will be thrown if you attempt to Reflect an Exception." Exception Cant_Reflect_Exceptions(); /*"DEPRECATED This Exception is only thrown by a run-time system function that should never be called." // stdfuns.cc::callFnID doesn't appear to be used anywhere Exception Unknown_Function_ID(); */ "Unexpected constructor in case statement This Exception is thrown when a constructor with no explicitly defined behaviour was used in a case statement, and there was no default case. data Example = A(Int a) | B(String b) | C(Float c); Void string(Example e) { case e of { A(a) -> return String(a); | B(b) -> return b; } } // if e = C(1.0) then a Missing_Case exception will be thrown." Exception Missing_Case(); "Pattern matching assignment failed This Exception is thrown in a pattern matching assignment if the right hand side of the assignment does not match the pattern given on the left hand side. testlist = nil; let cons(x,xs) = testlist; // testlist is nil, not cons " Exception Pattern_Matching_Assignment_Failure(); "Unexpected case in shorthand This Exception is thrown when a shorthand syntax is used and an unexpected case occurs. Int mag(Int x) | x<0 = -x; | x>0 = x; //Calling this function with x==0 throws this exception" Exception Unguarded_Guard(); "Tried to divide by zero. This Exception is thrown when an attempt to divide by zero is made." // RTS defined. Exception Divide_By_Zero(); // Inserted to calls to traverse. Not sure I want to document these since // they are an implementation detail. Is there a way we can hide them from // the output? Exception Loop_Return(a val); Exception Loop_VoidReturn(); foreign "stdfuns.o" { "An array Length of an array Return the length of an array. The empty array has length 0, and uninitialised elements are considered to exist for the purposes of determining length. arr = []; arr[5] = 26; l = length(arr); // 6" pure public Int size([a] xs) = arraySize; "The string to check Check whether a string contains UTF8 characters Scans a string looking for non-ASCII characters; returns True if any are present." pure public Bool UTF8(String s) = checkUTF8; pure Int doByteLength(String s, Int i) = binary_length; "Any variable Debugging function Debugging function for Kaya development: Returns the number of heap bytes used to store val." public Int memUsage(a val) = funtable_memusage; pure Int doHash(a x) = funtable_hash; pure String doMarshal(Ptr vm, a x, Int id) = funtable_marshal; pure any doUnmarshal(Ptr vm, String x, Int id) = unmarshal; pure Int doCompare(Ptr vm, a x, a y) = funtable_compare; pure Bool doEqual(Ptr vm, a x, a y) = funtable_eq; pure Char doGetIndex(String s, Int i) = getIndex; Void doSetIndex(String s, Char c, Int i) = setIndex; any doCopy(Ptr vm, any x) = funtable_copy; pure a unsafe_id(b x) = unsafe_id; "A possibly initialised variable Checks if a value is initialised Returns true if the value is initialised, or false if not (for example, an uninitialised array element) arr = []; arr[2] = 55; b = isInitialised(arr); // true b = isInitialised(arr[2]); // true b = isInitialised(arr[1]); // false" public Bool isInitialised(a x) = is_initialised; "The item to get the address of Debugging function Debugging function for developer use." public pure String getAddr(a x) = getAddr; pure Bool isNull(Ptr p) = isNull; pure Bool isIdentical(a x, a y) = isIdentical; pure Int doGetFnID(fn f) = doGetFnID; "Return hash of function table. Internal function." public Int funtableHash() = getFnHash; pure Int except_code(exc e) = except_code; pure String except_msg(exc e) = except_msg; Void except_dump(exc e) = except_dumpbt; Int doStrAlloc(str e) = strAlloc; str doCreateString(Ptr vm,Int len) = createString; Int doStrHash(String s, Int i) = strHash; "Is run-time checking enabled? Return whether the executable was compiled with run-time checking. True, unless -nortchecks was used for the main program. Should be used with some care, since if abused this can mean the program exhibits very different behaviour depending on whether checking is on or off." public Bool runTimeChecking() = rtchecks; "The exit code End the application immediatelyEnd the application and exit immediately with the given exit code. An exit code of zero is traditionally used for successful completion. It is generally a bad idea to use this function in web applications. System::_exit" public Void exit(Int code) = exit; } "The String to hashGet a numeric hash of a string.Returns a numeric hash of a String. This is most useful for hashing efficiency when working with Dicts with String keys, and similar." public Int strHash(String s) = doStrHash(s,length(s)); "The string to measure Length of a String Get the length of a String. This gives the length in Chars. Compare with Builtins::byteLength." public Int length(String s) = %length(s); "The string to measure Length in bytes of a string Get the length in bytes of a String (allowing for multi-byte characters in a UTF-8 encoding). str = \"Hello multibyte: \"+Char(192); l = length(str); // 18 ml = byteLength(str); // 19 length" public Int byteLength(String s) = doByteLength(s,length(s)); "Index is out-of-bounds or otherwise illegal This Exception is thrown when an index is out-of-bounds. It is used by getIndex if the index is negative or higher than the length of the string." Exception IllegalIndex(); "Strings may not contain null bytes This Exception is thrown if you try to set a character in a String to a null byte with setIndex" Exception NoNullsInStrings; "The string The position in the string Get a character from a String Get a character from a String. Gets the ith character of the given String. The index starts at zero. str = \"abcdefg\"; c = getIndex(str,0); // 'a' c = getIndex(str,5); // 'f' An IllegalIndex exception is thrown if i is out of bounds. setIndex" public Char getIndex(String s, Int i) { if (i<0 || i >= length(s)) { throw(IllegalIndex); } return doGetIndex(s,i); } "The string The character to set (may not be a NULL) The position in the string Change a character in a String in-place Sets the ith character of the given String to the given character. The index starts at zero. str = \"abcdefg\"; setIndex(str,'-',4); // str = \"abcd-fg\" An IllegalIndex exception is thrown if i is out of bounds. getIndex" public Void setIndex(String s, Char c, Int i) { if (i<0 || i >= length(s)) { throw(IllegalIndex); } else if (Int(c) == 0) { throw(NoNullsInStrings); } doSetIndex(s,c,i); } "The string to translate The rule to apply Translate characters in a String Replace characters in a String in place, applying the translation function to each character in turn. Char rot13(Char c) { if ((c >= 'A' && c <= 'M') || (c >= 'a' && c <= 'm')) { return Char(c+13); } else if ((c >= 'N' && c <= 'Z') || (c >= 'n' && c <= 'z')) { return Char(c-13); } else { return c; } } Void main() { str = \"Hello World\"; translate(str, rot13); // str = \"Uryyb Jbeyq\"; }" public Void translate(var String s, Char(Char) rule) { l = length(s); // can't use [..] range as it's not defined yet! // so use a while() loop instead i = 0; while (iThe value to marshal The unmarshalling ID Marshal any value to a string Return a machine readable String representation of a variable of any type. The id given must be identical when unmarshalling to provide some protection against accidentally unmarshalling the wrong value. Marshalling is intended for passing complex data between two separate instances of the same program. The format is not guaranteed to be the same between versions of the standard library. Also note that if you are marshalling closures, the representation may change when you recompile (as the marshalled form of a closure is based on its function id, generated at compile time). Therefore, Kaya will not unmarshal a representation generated by a program with a different function table. To pass data other than closures between two programs, in a way that will continue to work in different library versions, consider the Pickle module. Note that a==b does not necessarily imply marshal(a,i)==marshal(b,i) as the marshalling format includes some internal representation details for the virtual machine that do not affect equality. This is unlikely to be a problem in most cases (and unmarshal(marshal(a,i),i)==unmarshal(marshal(b,i),i) is always true if a==b!). Pickle::pickle unmarshal" public String marshal(any x,Int id) { return doMarshal(getVM(),x,id); } "The String to unmarshal The unmarshalling ID Unmarshal a string Convert a String generated with marshal into a variable of the appropriate type. This must be done with care, since the type you get depends on the String, so make sure you know what you are doing! The id given must match the id given when marshalling or an Exception is generated. An Exception will also be generated if the function table of the current program does not match the function table of the marshal()ing program. marshal Pickle::unpickle" public any unmarshal(String x, Int id) { return doUnmarshal(getVM(),x,id); } "The first value to compare The second value to compare Compare two values for \"size\" Compare any two values of the same type. Returns 0 if they are equal, less than zero if x is smaller, or greater than zero if x is bigger." public Int compare(any x, any y) { return doCompare(getVM(),x,y); } "Equality check Check any two values for equality. Returns true if they are equal, false otherwise. equal(a,b) is equivalent to a == b. Compare with identical." public Bool equal(any x, any y) { return doEqual(getVM(),x,y); } "The value to hash Hash a value Return an integer hash of any value. Because hash uses marshal, the hash is not guaranteed to be the same except within the same program binary. strHash" public Int hash(any x) { return doHash(x); } "The value to copy Copy a value Create a deep copy of any value. Contrasting with assignment, which creates another reference, this function traverses the entire structure and creates a clone. Note that this function is not pure, as even called with the same input, it returns a different copy each time. a = [5,6,7]; myFunction(a); // pass by shallow copy myFunction(copy(a)); // pass by deep copy Copying a structure containing a foreign pointer (for example a database or file handle, or a piece of binary data) will copy the pointer but will not copy the contents of that pointer." public any copy(any x) { return doCopy(getVM(),x); } "The variable to change the type of Subvert the type system. Somebody is bound to want to do an unsafe cast, so I guess I'll let them. I wanted to call this \"EnoughRopeToHangYourselfWith\" but I think it might turn out to be too useful in creating bindings to external libraries to have a name like that..." public anything subvert(something x) { return unsafe_id(x); } "Get a pointer to the Kaya VM Return a pointer to the virtual machine state. Used by some foreign functions which need access to the virtual machine for such things as throwing exceptions." public Ptr getVM() { return %VM; } "The caught Exception Get a human-readable error message Return the error message in an Exception. This is useful for determining the exception caught by a catch-all clause, but it is preferable to catch Exceptions by name. try { functionThatMayGoWrong(a,b,c); } catch(e) { putStrLn(\"Something went wrong: \"+exceptionMessage(e)); } exceptionBacktrace exceptionCode" public String exceptionMessage(Exception e) { return except_msg(e); } "The caught Exception Print the backtrace of an Exception. This is used to deal with uncaught exceptions in programs and prints the backtrace on standard output. It is generally not appropriate for use within a program except for debugging purposes, and should never be called within a CGI program or webapp. If the program is compiled with the -nortchecks compiler option then the backtrace will be of limited use. Similarly, the standard library must be compiled with the --enable-debug configure option to get useful backtraces there. exceptionCode exceptionMessage" public Void exceptionBacktrace(Exception e) { except_dump(e); } "Debugging function Return the amount of memory allocated for a string, for debugging purposes." public Int strAlloc(String x) { return doStrAlloc(x); } "Internal standard library function Return the function id of fn. Used by CGI (not webapp) event handlers, to know which function to call on entry to the web application, and by other parts of the standard library. Generally this function should not be used outside standard library development." public Int fnid(Void(a) fn) { return doGetFnID(fn); } "The foreign Ptr to check. Checks if a foreign pointer is NULL Returns true if the foreign pointer is NULL. This is useful in testing whether a foreign function returns something valid, before throwing an exception. This is the only way, in general, that Ptr should be queried in Kaya; usually it is better to manipulate pointers C side." public Bool null(Ptr p) { return isNull(p); } "First value Second value Return whether two values are identical. Check if two values are identical. This is stronger than equality - this tests whether two values are stored at the same memory location. In other words, it tests whether modifying the contents of x would also modify the contents of y. a = (5,6); b = (3,a.snd); c = a; d = (5,6); test = identical(b,a); // false test2 = identical(b.snd,a.snd); //true test3 = identical(c,a); // true test4 = identical(d,a); // false Of course, equal(a,d) would be true. equal" public Bool identical(a x, a y) { return isIdentical(x,y); } // Some functions which are so primitive that the rest of the prelude needs // them... "First variable Second variable Swap the contents of two variables Swap the contents of two variables of the same type. a = 5; b = 6; swap(a,b); // a = 6, b = 5" public Void swap(var a x, var a y) { tmp = x; x = y; y = tmp; } // Removed temporarily since VM instructions are commented out. // "Return maximum memory usage over the whole program" // public Int maxHeapSize = do_max_heapsize(getVM); // added by CIM 11/9/2005 "The initial seed Seeds the random number generator Seeds the random number generator. This must be called before any calls to rand are made. Seeding with the same integer will give the same sequence of pseudo-random numbers. Where unpredictability is not crucial, the Time::time function can be used to give a different sequence each time the program is run. rand" public Void srand(Int seed) { randseed = seed; } "Pseudo-random signed integer generator rand() returns a pseudo-random signed integer in the range +/- (2**31)-1 You must call srand before the first call to this function in a program. srand(12345); for i in [1..5] { putStr(rand()+\" \"); } Gives: 1995772607 -612336503 -885735441 457910745 1875493919 The rand() function is a low-quality but fast generator - for better quality numbers, use the optional Lfrand module or for cryptographic purposes, your computer's hardware RNG. The Builtins::srand function The Lfrand module" public Int rand() { return dorand()|(dorand()<<16); } // the low bits of an LCG have appalling properties, so take two sets of // high bits instead. It's still not brilliant, but at least things like // rand()%2==0 now have a ~50% instead of 100% or 0% chance! Int dorand() { randseed = ((62089911*randseed));//%((2**31)-1)); return ((randseed>>16)&((1<<16)-1)); } "The integer to find the magnitude of Return the magnitude of an integer. Return the magnitude of an integer. a = abs(5); // 5 a = abs(-3); // 3" public Int abs(Int x) | x<0 = (-x) | default = x; "The floating-point variable to find the magnitude of Return the magnitude of a floating-point number. Return the magnitude of a floating-point number. a = abs(5.7); // 5.7 a = abs(-11.2); // 11.2" public Float abs(Float x) | x<0 = (-x) | default = x; "Creates a string with particular memory allocation The number of characters to allocate space for Create an empty string, with initial space for len characters. Use this to avoid unnecessary reallocation if you know or can compute the length of a string in advance. Using this function can save time and memory in Kaya programs, but generally the default memory allocation will be adequate - save this for the optimisation stage. Array::createArray" public String createString(Int len) { return doCreateString(getVM,len); } "Returns a new reference to the original value. Returns a new reference to the original value - i.e. the 'identity transformation'. a = (1,2,3); b = identity(a); // identical(a,b) == true Sometimes useful where a function is needed as a parameter." public a identity(a val) { return val; } "Boolean NOT The boolean NOT operator in function form. a = true; b = inverse(a); // false" public Bool inverse(Bool val) { return !val; } kaya-0.4.4/stdlib/zlib_glue.h0000644000175100017510000000036311170340767014166 0ustar cimcim#ifndef _ZLIB_GLUE_H #define _ZLIB_GLUE_H #include extern "C" { void* compressBuffer(void* vmptr, void* in, int len, KayaValue buflen); void* uncompressBuffer(void* vmptr, void* in, int len, KayaValue outlen); }; #endif kaya-0.4.4/stdlib/binary_glue.cc0000644000175100017510000000433711170340770014647 0ustar cimcim#include #include "binary_glue.h" #include "stdfuns.h" #include void* newBlock(int size) { return (void*)GC_MALLOC_ATOMIC(size); } void poke(void* block,int offset,int val) { BYTE* data = (BYTE*)block; *(data+offset)=val; } int peek(void* block,int offset) { BYTE* data = (BYTE*)block; return (int)(*(data+offset)); } void pokestring(void* block, int offset, wchar_t* str) { BYTE* point = ((BYTE*)block)+offset; memcpy(point,wctostr(str),strlen(wctostr(str))+1); } wchar_t* peekstring(void* block, kint offset, kint bsize) { char *str = (char *)(((BYTE *) block) + offset); kint maxlen = (bsize-offset); // make sure there's no overrun and null termination occurs char buf[maxlen+1]; strncpy(buf,str,maxlen); buf[maxlen] = '\0'; return strtowc(buf); } void* copyBlock(void* block, int size) { void* newblock = (void*)KayaAlloc(size); memcpy(newblock,block,size); return newblock; } void* copyChunk(void* block,int offset,int size) { void* newblock = (void*)GC_MALLOC_ATOMIC(size); void* blockstart = (void*)((BYTE*)block+offset); memcpy(newblock,blockstart,size); return newblock; } KayaArray getBlockData(void* block, int offset,int size) { BYTE* blockloc = (BYTE*)block+offset; KayaArray data = newKayaArray(size); for(int i=0;i #include "regex_glue.h" #include "Heap.h" #include "VM.h" #include "stdfuns.h" #include "KayaAPI.h" #include void* re_compile(void* vm, wchar_t* pattern, kint len, kint flagcode) { VMState* vmptr = (VMState*)vm; const char* error; int erroffset; // set by ./configure #ifndef NOUTF8 int regexflags = PCRE_UTF8; #else int regexflags = 0; if (checkUTF8(pattern)) { vmptr->kaya_internalError(1); } #endif if (flagcode & 1) { regexflags = regexflags | PCRE_CASELESS; } if (flagcode & 2) { regexflags = regexflags | PCRE_EXTENDED; } if (flagcode & 4) { regexflags = regexflags | PCRE_MULTILINE; } if (flagcode & 8) { regexflags = regexflags | PCRE_UNGREEDY; } CNPSTRING(patt,pattern,len); char* cpatt = patt; pcre* re = pcre_compile(patt,regexflags,&error, &erroffset, NULL); if (re == NULL) { vmptr->kaya_internalError(0); } CompiledRegex* reobj = new CompiledRegex(re); return (void*)reobj; } kint re_quickmatch(void* vm, void* pc, wchar_t* wstr, kint inlen) { VMState* vmptr = (VMState*)vm; CNPSTRING(stra,wstr,inlen); char* str = stra; #ifdef NOUTF8 if (topSet(str)) { vmptr->kaya_internalError(1); } #endif int ovector[255]; pcre* re = ((CompiledRegex*)pc)->regex; int rc = pcre_exec(re, NULL, str, strlen(str), 0, 0, ovector, 255); return (rc>=0); } void* re_match(void* vm, void* pc, wchar_t* wstr, kint inlen) { VMState* vmptr = (VMState*)vm; CNPSTRING(stra,wstr,inlen); char* str = stra; #ifdef NOUTF8 if (topSet(str)) { vmptr->kaya_internalError(1); } #endif int ovector[255]; Match* m = new Match(); pcre* re = ((CompiledRegex*)pc)->regex; int rc = pcre_exec(re, NULL, str, strlen(str), 0, 0, ovector, 255); int len = strlen(str); // cout << rc << endl; //cout << str << endl; if (rc>=0) { m->matched = true; m->matches = new Array(); char beforetmp[ovector[0]+1]; strncpy(beforetmp,str,ovector[0]); beforetmp[ovector[0]] = '\0'; m->before = KSTRING(beforetmp); /* m->before = (wchar_t*)GC_MALLOC_ATOMIC((ovector[0]+1)*sizeof(wchar_t)); wcsncpy(m->before, strtowc(str),ovector[0]); m->before[ovector[0]]='\0'; cout << ovector[0] << endl; */ int afterlen = len-ovector[1]; char aftertmp[afterlen+1]; strncpy(aftertmp,str+ovector[1],afterlen); aftertmp[afterlen] = '\0'; m->after = KSTRING(aftertmp); /* m->after = (wchar_t*)GC_MALLOC_ATOMIC((afterlen+1)*sizeof(wchar_t)); wcsncpy(m->after, strtowc(str+ovector[1]),afterlen); m->after[afterlen]='\0'; */ for(int i=0;imatches->push_back(KayaString2(vmptr)); //new Value(new String(strtowc(sub)),KVT_STRING)); } } else { m->matched = false; m->matches = new Array(); } return (void*)m; } Array* getmatches(void* mo) { return ((Match*)mo)->matches; } bool matched(void* mo) { return ((Match*)mo)->matched; } wchar_t* getBefore(void* mo) { return ((Match*)mo)->before; } wchar_t* getAfter(void* mo) { return ((Match*)mo)->after; } kaya-0.4.4/stdlib/CGI.k0000644000175100017510000007205511170340770012620 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Simple CGI application interface This module provides a simple low-level CGI application interface, for development of small web applications and prototypes. For larger web applications, the Webapp module may be more suitable due to tighter integration with HTMLDocument. This module now includes experimental support for AJAX programming. These functions are likely to change in future releases." module CGI; import Prelude; import System; import Strings; import Crypto; import Regex; import IO; import public WebCommon; type HTML = String; globals { [HTML] pagecontent = []; [String] headers = []; Bool headersdone = false; // list of pairs rather than a dict because we look up both ways [(String, String)] shortURLs = []; [(Char,String)] esctable; } "Unrecognised variable This Exception is thrown by httpGetVar and others when the variable requested was not submitted by the browser." Exception UnrecognisedVariable(String err); "Illegal handler This exception is thrown when an illegal handler is used." Exception IllegalHandler(); "Unexpected type This exception is thrown when an incoming variable is not of the expected type." Exception UnexpectedType(String err, String ty, String variable); "Variable outside expected range This exception is thrown when an incoming variable is outside the expected range." Exception ValueOutOfRange(); "The bad header Malformed HTTP header The HTTP header is not valid. Only a limited set of characters are permitted." Exception BadHeader(String h); "Events to be handled by Ajax actions Events which may be handled by an XMLHttpRequest" public data AjaxEvent = OnAbort | OnBlur | OnChange | OnClick | OnDblClick | OnError | OnFocus | OnKeyDown | OnKeyPress | OnKeyUp | OnLoad | OnMouseDown | OnMouseMove | OnMouseOut | OnMouseOver | OnMouseUp | OnReset | OnResize | OnSelect | OnSubmit | OnUnload; "Ajax data requests Methods for requesting additional data for ajax commands, e.g. retrieving the value of an element in the DOM or event data. " public data AjaxData = JSValue(String js) | ThisValue | Data(String val) | InputValue(String id) | InnerHTML(String htmlId); "Ajax action to take when an event occurs Either run a kaya function on the server, run some generic javascript, or update a form value" public data AjaxAction = KayaFunction(Void() fn) | JSAction(String js) | Update(String, AjaxData jsvalue) | UpdateValue(String, String value) | Actions([AjaxAction] acts); String jsAjaxData(AjaxData d) { case d of { JSValue(s) -> return s; | ThisValue -> return "this.value"; | Data(s) -> return "'"+s+"'"; | InputValue(id) -> return "document.getElementById('"+id+"').value"; | InnerHTML(id) -> return "document.getElementById('"+id+"').innerHTML"; }; } String jsAjaxEvent(AjaxEvent h) = case h of { OnAbort -> "onabort"; | OnBlur -> "onblur"; | OnChange -> "onchange"; | OnClick -> "onclick"; | OnDblClick -> "ondblclick"; | OnError -> "onerror"; | OnFocus -> "onfocus"; | OnKeyDown -> "onkeydown"; | OnKeyPress -> "onkeyup"; | OnKeyUp -> "onkeyup"; | OnLoad -> "onload"; | OnMouseDown -> "onmousedown"; | OnMouseMove -> "onmousemove"; | OnMouseOut -> "onmouseout"; | OnMouseOver -> "onmouseover"; | OnMouseUp -> "onmouseup"; | OnReset -> "onreset"; | OnResize -> "onresize"; | OnSelect -> "onselect"; | OnSubmit -> "onselect"; | OnUnload -> "onunload"; }; "Get additional data sent to an Ajax request Get additional data sent to an Ajax request" public [String] getAjaxData() { dat = incomingValue("kaya_jsdata", DataRequest); vals = split(",", dat, 0, true); return vals; } "Some basic javascript for handling Ajax calls This needs to be added as content by any application intending to use Ajax features." public HTML ajaxHeader = ""; "Add a HTTP header Add a new HTTP header to the output. header(\"Content-type: text/html; charset=UTF-8\") flushHeaders" public Void header(String h) { push(headers, h); } "Get tag information for linking an ajax call to an event on a tag When the event h occurs on the tag, apply the action and if applicable updates the contents of the tag with id resultID with the result of the handler. content(\"

    Title

    \");
    " public String ajaxTag(AjaxEvent h, AjaxAction act, String resultID = "", [AjaxData] extras = []) { return jsAjaxEvent(h)+"=\"" + ajaxTagData(act, resultID, extras) + "\""; } public String ajaxTagData(AjaxAction act, String resultID = "", [AjaxData] extras = []) { case act of { KayaFunction(fn) -> ext = "var ext = ''; "; for extra@i in extras { ext += "ext = ext.concat(encodeURIComponent(" + jsAjaxData(extra) +")); "; if (i return jsact+";"; | UpdateValue(fld,val) -> return "document.getElementById('"+fld+"').value='"+val+"';"; | Update(fld, js) -> return "document.getElementById('"+fld+"').value="+jsAjaxData(js)+";"; | Actions(acts) -> action = ""; for act in acts { action+=ajaxTagData(act,resultID,extras); } action += "\""; return action; } } Void kHandler(Void() fn, Int dummy) { fn(); } "Add new content Add some content to the page. Because of the nature of the CGI interface, this must be used instead of Prelude::putStr. flushContent" public Void content(HTML c) { push(pagecontent, c); } String encodeChar(Char x) { if (x==' ') { return "+"; } if (Int(x)>127 || isPunct(x)) /* (x `elem` ['!','&','$','+',',','/',':',';','=','?','@', '"','<','>','#','%','{','}','|','\\','^', '~','[',']','`']))*/ { return "%"+stringBase(Int(x),16); } return String(x); } "Output headers. Output the HTTP headers. Outputs a Content-type:text/html header if none has been given. This only works once; after outputting the headers, only content can be added. flushAll header" public Void flushHeaders() { contenttype = false; if (!headersdone) { for h in headers { validheader = compile("^[^()<>@,;:\\\"/[\\]?={}[:cntrl:]\r\n]+:[^[:cntrl:]\r\n]+$"); if (quickMatch(validheader,h)) { putStrLn(h); if (substr(h,0,12)=="Content-type") { contenttype=true; } } else { throw(BadHeader(h)); } } // If we haven't had a Content-type header, output the default one. if (!contenttype) { putStrLn("Content-type: text/html;charset=UTF-8"); } putStrLn(""); headersdone = true; } // print "Flushing headers"; } "Output the content. Output the content. If flushHeaders has not been called, it will be called before the first use of this function. The web server (and indeed any intermediate proxies) are under no obligation to send this content to the browser immediately. content flushAll" public Void flushContent() { flushHeaders(); // print "Flushing content "+String(size(pagecontent)); for c in pagecontent { putStrLn(c); } pagecontent = []; } "The string (a regular expression) to replace The replacement Replace a string in the current output. Replaces str with new wherever it occurs in the headers or content. This only affects content that has not yet been flushed to the user." public Void replaceContent(HTML str, HTML new) { for h in headers { replace(str,new,h,[Global]); } newc = []; for c in pagecontent { replace(str,new,c,[Global]); push(newc,c); } pagecontent = newc; } "Output all headers and content. Output all headers and content. This need not be called by the user, as it is done automatically at the end of a CGI's execution. It may be useful for debugging purposes, however." public Void flushAll() { flushContent(); // print "Flushing "; } "The cookie name The cookie value Set a cookie Set a cookie. This must be called before flushHeaders to have any effect. Remember that cookies are not available to the script that sets them. For more flexible setting of cookies, use WebCommon::setCookie instead." public Void setCookie(String name,String value) { header("Set-Cookie: "+name+"="+urlEncode(value)); } "The variable name Return the integer in a GET/POST variable. Return the integer value of a GET or POST variable. An exception is thrown if the variable is not a valid integer. httpFloat" public Int httpInt(String v) { x = incomingValue(v,DataRequest); if (quickMatch("^[+-]?[0-9]*$", x)) { return Int(x); } else { throw(UnexpectedType(x, "Integer", v)); } } "The variable name Return the floating-point number in a GET/POST variable. Return the floating-point value of a GET or POST variable. An exception is thrown if the variable is not a valid Float. httpInt" public Float httpFloat(String v) { x = incomingValue(v,DataRequest); // FIXME: This isn't quite right, but it'll do for now. if (quickMatch("[0-9]*\.?[0-9]*e?[+-][0-9]*", x)) { return Float(x); } else { throw(UnexpectedType(x,"Float",v)); } } "The button's label Create a submit button. Returns a string of HTML to create a submit button for a form. extra contains any extra attributes needed. content(submit(\"Submit\"));" public HTML submit(String text, String id ="", String extra = "") { submitname = "kaya_submit"; if (id!="") { idtext = "id=\""+id+"\" "; } return ""; } "The button's label Create a reset button. Returns a string of HTML to create a reset button for a form. content(reset(\"Reset form\"));" public HTML reset(String text, String id = "", String extra="") { if (id!="") { idtext = "id=\""+id+"\" "; } return ""; } "Get the last submit button Returns the label of the submit button used to submit the form currently being processed (or throws an Exception if no form is being processed)." public String submitUsed = incomingValue("kaya_submit",DataRequest); String scriptName() { nms = Regex::split("\/",progName()); return nms[size(nms)-1]; } "The handler function Data to pass to the handler function Whether to run the PreContent and PostContent functions after submitting the form. This defaults to true, but may be useful to disable if the form results are not HTML. Set up a form. Set up a form, which when submitted calls fn(dat)." public HTML formHandler(Void(a) fn, a dat, Bool prepost = true) { str = "\n"; str += "\n"; str += ""; if (!prepost) { str += ""; } return str; } "The handler function Data to pass to the handler function Whether to run the PreContent and PostContent functions after submitting the form. This defaults to true, but may be useful to disable if the form results are not HTML. Set up a file upload form. Set up a form capable of uploading files, which when submitted calls fn(dat). You will need to call WebCommon::allowFileUploads in your webconfig function to allow file uploads to be processed. uploadButton" public HTML fileFormHandler(Void(a) fn, a dat, Bool prepost = true) { str = "\n"; // str += ""; str += "\n"; str += ""; if (!prepost) { str += ""; } return str; } "The file upload's name Create a file upload field. Returns a string of HTML to create a file upload field for a form. content(uploadButton(\"image\"));" public HTML uploadButton(String name, String id = "", String extra = "") { if (id!="") { idtext = "id=\""+id+"\" "; } return ""; } // Helper for linkHandler. String handlerQuery(Void(a) fn, a dat, Bool prepost) { str = "kaya_function="+urlEncode(encode(marshal(fn,888))); str += ";kaya_arg="+urlEncode(encode(marshal(dat,fnid(fn)))); if (!prepost) { str += ";kaya_prepost="+urlEncode(encode(marshal(prepost,0))); } return str; } public HTML linkURL(Void(a) fn, a dat, [(String,String)] others = [], Bool prepost = true) { hq = handlerQuery(fn,dat,prepost); for x in shortURLs { if (x.snd == hq) { hq = x.fst; } } url = "?"+hq; for o in others { url = url + ";" + o.fst + "=" + o.snd; } return url; } "The handler function Data to pass to the handler function The link text A list of name-value pairs of additional variables to add in the link, defaulting to the empty list. Whether to run the PreContent and PostContent functions after submitting the form. This defaults to true, but may be useful to disable if the form results are not HTML. Create a hyperlink. Return the HTML for a hyperlink, which when followed calls fn(dat)." public HTML linkHandler(Void(a) fn, a dat, String inf, [(String,String)] others = [], Bool prepost = true) { return "
    "+inf+""; } "The short handler name The handler function Data to pass to the handler function Whether to run the PreContent and PostContent functions after submitting the form. This defaults to true, but may be useful to disable if the form results are not HTML. Register a handler to get a short URL Register a handler to get a short URL. If the same fn, dat and prepost settings are later used by linkHandler, the long string of encrypted state information will be replaced by a short handler string." public Void addHandler(String shortName, Void(a) fn, a dat, Bool prepost = true) { push(shortURLs, (shortName, handlerQuery(fn, dat, prepost))); } "The short name to look up Look up a short name to get a fully expanded query string. This function looks up a short name to get the fully expanded query string, returning the full string, or an empty string if no expansion is available." public String expandQuery(String shortName) { re = compile(r"\&"); case match(re, shortName) of { noMatch -> rest = ""; | matches(m,before,after) -> shortName = before; rest = "&"+after; } for x in shortURLs { if (x.fst == shortName) { return x.snd + rest; } } return ""; // Not expandable } "The image generating function A parameter for the image generating function The alternative text for the image The width of the image in pixels (optional) The height of the image in pixels (optional, but must be specified if width is specified) Additional image attributes (e.g. \"title='Graph 1' id='gr1'\") (this value is not filtered in any way, and so user-supplied data should not be used here). Embed an image. Return the HTML to add an image to a page, where the image is generated by one of the functions in the CGI application. Image" public HTML imageHandler(Void(a) fn, a dat, String alt, Int width = -1, Int height =-1, String attribs="") { url = scriptName()+"?"+handlerQuery(fn,dat,false); if (width!=-1) { size = "width="+width+" height="+height; } else { size = ""; } return "\""+alt+"\""; } "Link text Link to the default function. Return the HTML for a hyperlink that when followed calls the default function." public HTML goDefault(String inf) { url = scriptName(); return ""+inf+""; } "The variable name The variable value Pass a variable to a form. Pass a variable to a form. This returns the HTML for a hidden input field. Note that neither parameter is escaped by this function, so you must ensure that neither contains a '\"' character yourself." public HTML passVar(String httpvar, String value) { return ""; } "The variable name The variable value The suggested size of the input field Create a text input field. Returns the HTML for a text input field. Note that neither the name nor the value parameter is escaped by this function, so you must ensure that neither contains a '\"' character yourself." public HTML textBox(String name, String value="", Int len = 20, String id = "", String extra = "") { if (id!="") { idtext = "id=\""+id+"\" "; } return ""; } "The variable name The variable value The suggested size of the input field Create a text area input field. Returns the HTML for a text area input field. Note that neither the name nor the value parameter is escaped by this function, so you must ensure that neither contains a '\"' character yourself." public HTML textArea(String name, Int width, Int height, String value="", String id = "", String extra = "") { if (id!="") { idtext = "id=\""+id+"\" "; } return ""; } "The variable name The suggested size of the input field Create a password input field. Returns the HTML for a password input field. Note that the name parameter is not escaped by this function, so you must ensure that it contains no '\"' characters yourself." public HTML passwordBox(String name, Int len = 20, String id = "", String extra = "") { if (id!="") { idtext = "id=\""+id+"\" "; } return ""; } "The name of the selector The size of the selector (use 0 for a drop-down selection box) The options for the selector The default option Create a selection box. Returns the HTML for a selection box. Note that none of the input values are escaped, so you must ensure that name contains no '\"' characters, and opts contains no values containing '<' characters." public HTML selBox(String name, Int len, [String] opts, String def = "", String id = "", String extra = "") { if (id!="") { idtext = "id=\""+id+"\" "; } str = ""; return str; } "The name of the checkbox If this is true, the checkbox will start checked. Make a checkbox. Returns the HTML for a checkbox. checked" public HTML checkBox(String name,Bool def = false, String id = "", String extra = "") { if (id!="") { idtext = "id=\""+id+"\" "; } str = "The checkbox name Return whether a checkbox was checked. Return whether a checkbox was checked in the previous form submission. checkBox" public Bool checked(String name) { return incomingExists(name,DataRequest); } "The name of the radio button. Only one radio button with a given name may be selected at once The value of the radio button. If this is true, the radio button will start checked. Browser behaviour is undefined unless exactly one radio button out of each set begins checked. Make a radio button. Returns the HTML for a radio button. Note that neither the name nor the value parameter is escaped by this function, so you must ensure that neither contains a '\"' character yourself." public HTML radio(String name, String val, Bool set = false, String id = "", String extra = "") { if (id!="") { idtext = "id=\""+id+"\" "; } str = "End a form Returns the HTML to close the currently open form." public HTML closeForm() { return "
    "; } "A list of strings, corresponding to the column headers from left to right A list of rows, each row being a list of strings. Rows are added to the table top to bottom, with each row being added left to right. The attributes for the table as a whole, for example \"class='numericdata' title='Table 1.2'\" Any attributes to apply to all table header cells. Any attributes to apply to all table data cells. Output a table. Returns the HTML for a table" public HTML table([String] titles, [[String]] rows, String tableattribs="", String headattribs="", String dataattribs="") { str = ""; if (titles!=[]) { str+=tablerow("th",headattribs, titles)+"\n"; } for row in rows { str+=tablerow("td",dataattribs, row)+"\n"; } return str+"
    "; } String tablerow(String tag,String attribs,[String] stuff) { str = ""; str += ""; for t in stuff { str+="<"+tag+" "+attribs+">"+t+""; } str += ""; return str; } /* Void webappMain(Void() headerfn, Void() defaultfn, Void() footerfn) { foreign Void storeHTTPargs(); try { dfun = httparg("kaya_function"); darg = httparg("kaya_arg"); id = Int(decode(dfun)); ... } catch(e) { defaultfn(); } }*/ String htmlEncodeChar(Char x) { if (size(esctable)==0) { esctable = [('&',"&"), ('<',"<"), ('>',">"), (Char(163),"£")]; } for p in esctable { if (x==p.fst) return p.snd; } return String(x); } "The un-encoded string Encodes HTML special chars. Converts '&', '<' and '>' to '&amp;', '&lt;' and '&gt;'. It does not convert '\"' to '&quot;', which you will need to do manually for function attribute values." public String htmlEscape(String x) { str = x; current = ""; while(str!="") { c = head(str); str = tail(str); current += htmlEncodeChar(c); } return current; } /// Safe cast functions "The string to convert The minimum value The maximum value Convert a string to an Int. Convert a string to an Int, throwing an Exception if the resulting Int is out of the specified range. safeFloat" public Int safeInt(String x, Int min, Int max) { num = Int(x); if (nummax) { throw(ValueOutOfRange); } return num; } "The string to convert The minimum value The maximum value Convert a string to a Float. Convert a string to a Float, throwing an Exception if the resulting Float is out of the specified range (note that due to floating-point inaccuracies, values very close to the minimum or maximum value may be incorrectly rejected or accepted). safeInt" public Float safeFloat(String x, Float min, Float max) { num = Float(x); if (nummax) { throw(ValueOutOfRange); } return num; } kaya-0.4.4/stdlib/KayaDoc.k0000644000175100017510000011330511170340770013523 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2007 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Kaya API documentation generator This module contains functions to convert documentation files created with kayac's -xmldocs option into HTML or man page format. The source of the kayadoc2man program in the tools directory of the Kaya distribution may be useful for examples of use. It also provides an API to examine the documentation for writing other formats - see the ElementTree module for details of processing the XML representation. HTML documentation produced with this module may be seen on the Kaya website, and man pages are installed in prefix/man/man3/*.3kaya.gz by the Kaya installation process. // generate HTML document for a particular function doc = readDoc(\"MyModule.xml\"); entry = findEntry(doc,EntryLocation(\"myFunction\",0,EntryFunction)); appendExisting(html.body,describeFunctionHTML(entry)); // get a list of all the data types in a module // and summarise them in HTML doc = readDoc(\"MyModule.xml\"); ds = listDataTypes(doc); for d in ds { htmliseContents(d.summary,html.body,linkFn); } // get the short summary for a module in man page format doc = readDoc(\"MyModule.xml\"); summ = extractSummary(moduleSummary(doc)); manstr = manSummary(summ) A specification for the -xmldocs format can be found in the XMLDOCS file." module KayaDoc; import Time; import Regex; import Strings; import IO; import Prelude; import Dict; import ElementTree; import HTMLDocument; type APIDoc = ElementTree; "The filename of the documentation Read an -xmldocs .xml file Reads a file generated with -xmldocs into an ElementTreeData::ElementTree. This is then used by the other functions in this module. readString" public APIDoc readDoc(String filename) { xmlstr = readFile(filename); return readString(xmlstr); } "A String containing the contents of a -xmldocs file Read a String from an -xmldocs file Reads a String generated from an -xmldocs file into an ElementTreeData::ElementTree. This is then used by the other functions in this module. readDoc" public APIDoc readString(String xmlstr) { wl = Dict::new(157,strHash); for tag in ["module","modsummary","param","data","name","location","file","line","con","conname","argname","type","fun","comment","return","summary","prose","example","list","item","related","functionref","moduleref","dataref","code","input","output","emphasis","variable","except","exceptref","defval","deprecated","tysyn","syn"] { add(wl,tag,["*"]); } add(wl,"arg",["passby"]); add(wl,"argument",["name"]); add(wl,"link",["url"]); el = elementTree(xmlstr,"root",wl,Dict::new(2,strHash),["deprecated"],Dict::new(2,strHash),true); // this assumes no leading whitespace, but it'll do for now. return el.elements[0].nested; } "A type synonym A type synonym. For example, type MyDB = DBHandle; will be represented using this type as: TypeSynonym(\"MyDB\",\"DBHandle\");" public data TypeSynonym(String alias, String meaning); "A function A function. The fields have the following meanings: rntype: The return type of the function fname: The name of the function args: A list of the function's arguments summary: The summary documentation of the function deprecated: True if the function is deprecated " public data FunctionSummary(String rntype, String fname, [String] args, ElementTree summary, Bool deprecated); "A data type A function. The fields have the following meanings: dname: The name of the type params: A list of the type's parameters. For example, Dict<a,b> would have [\"a\",\"b\"] here. cons: A list of the constructor functions for this type summary: Summary documentation for the type Constructor" public data DataSummary(String dname, [String] params, [Constructor] cons, ElementTree summary); "An Exception An Exception. The fields have the following meanings: ename: The name of the Exception args: A list of the arguments of the Exception. summary: Summary documentation for the Exception." public data ExceptionSummary(String ename, [String] args, ElementTree summary); "A constructor function A constructor function for a data type. cname is the name of the constructor, and args is a list of function arguments. DataSummary" public data Constructor(String cname, [String] args); "An entry within the document An entry within the document, for use with findEntry. The parameters give the name and EntryType of the entry, with the count parameter used to disambiguate multiple functions with the same name within a module. EntryType" public data EntryLocation(String name, EntryType etype, Int count); "Types of documentation entry This data type describes types of documentation entry, for the findEntry function, and also for constructing references to these entries from other entries. Note that EntryModule may not be used with the findEntry function. EntryLocation" public data EntryType = EntryFunction | EntryData | EntryModule | EntryException; "No such entry This Exception is thrown if the entry searched for with findEntry did not exist." Exception NoSuchEntry(String ref); "EntryModule not allowed This Exception is thrown if the EntryLocation passed to findEntry had an EntryType of EntryModule." Exception ModuleContext(); "API documentation Lists type synonyms in a module Return a list of the type synonyms in the module. TypeSynonym listDataTypes listExceptions listFunctions" public [TypeSynonym] listTypes(APIDoc doc) { tys = createArray(100); for xitem in getSubtrees(doc) { if (xitem.name == "tysyn") { push(tys,summariseType(xitem)); } } return tys; } TypeSynonym summariseType(ElementTree ty) { alias = ""; meaning = ""; for part in getSubtrees(ty) { if (part.name == "name") { alias = getText(part); } else if (part.name == "syn") { meaning = getText(part); } } // best copy the summary or there could be some oddities later return TypeSynonym(alias,meaning); } "API documentation Lists functions in a module Return a list of the functions in the module. FunctionSummary listDataTypes listExceptions listTypes" public [FunctionSummary] listFunctions(APIDoc doc) { fns = createArray(100); for xitem in getSubtrees(doc) { if (xitem.name == "fun") { push(fns,summariseFunction(xitem)); } } return fns; } "API documentation Get the summary of a module Get the summary documentation block for a module. This block will contain a summary element, and then some combination of prose, example and list elements as described in the XMLDOCS specification file." public ElementTree moduleSummary(APIDoc doc) { for xitem in getSubtrees(doc) { // likely to be the first item, of course if (xitem.name == "modsummary") { return xitem; } } throw(NoSuchEntry("summary")); } "API documentation Lists data types in a module Return a list of the data types in the module. DataSummary listExceptions listFunctions listTypes" public [DataSummary] listDataTypes(APIDoc doc) { fns = createArray(100); for xitem in getSubtrees(doc) { if (xitem.name == "data") { push(fns,summariseData(xitem)); } } return fns; } "API documentation Lists Exceptions in a module Return a list of the exceptions in the module. ExceptionSummary listDataTypes listFunctions listTypes" public [ExceptionSummary] listExceptions(APIDoc doc) { fns = createArray(100); for xitem in getSubtrees(doc) { if (xitem.name == "except") { push(fns,summariseException(xitem)); } } return fns; } FunctionSummary summariseFunction(ElementTree fun) { rntype = ""; fname = ""; args = createArray(10); summary = newElement("summary",1); deprecated = false; for part in getSubtrees(fun) { if (part.name == "name") { fname = getText(part); } else if (part.name == "return") { rntype = getText(part); } else if (part.name == "deprecated") { deprecated = true; } else if (part.name == "arg") { push(args,parseArg(part)); } else if (part.name == "comment") { issummary = extractSummary(part); case issummary of { just(summary) -> ; | nothing -> ; } } } // best copy the summary or there could be some oddities later return FunctionSummary(rntype,fname,args,copy(summary),deprecated); } String parseArg(ElementTree part) { passby = ElementTree::getAttribute(part,"passby"); desc = ""; case passby of { nothing -> ; | just(x) -> if (x == "var") { desc += "var "; } } argname = ""; argtype = ""; argdef = ""; for argpart in getSubtrees(part) { if (argpart.name == "argname") { argname = getText(argpart); } else if (argpart.name == "type") { argtype = getText(argpart); } else if (argpart.name == "defval") { argdef = getText(argpart); replace(",",", ",argdef,[Global]); } } desc += argtype+" "+argname; if (argdef != "") { desc += "="+argdef; } trim(desc); return desc; } "A documentation block extracted from API documentation Find the summary component of a documentation block Find the summary component of a documentation block, if possible. findEntry moduleSummary" public Maybe extractSummary(ElementTree part) { subs = getSubtrees(part); if (size(subs) > 0) { for compart in getSubtrees(part) { if (compart.name == "summary") { return just(compart); } } return nothing; } else { // old documentation format el = newElement("summary"); addString(el, split("\n",getText(part))[0]); return just(el); } } DataSummary summariseData(ElementTree dat) { params = createArray(10); dname = ""; cons = createArray(30); summary = newElement("summary",1); for part in getSubtrees(dat) { if (part.name == "name") { dname = getText(part); } else if (part.name == "param") { push(params,getText(part)); } else if (part.name == "con") { push(cons,summariseConstructor(part)); } else if (part.name == "comment") { issummary = extractSummary(part); case issummary of { just(summary) -> ; | nothing -> ; } } } // best copy the summary or there could be some oddities later return DataSummary(dname,params,cons,copy(summary)); } ExceptionSummary summariseException(ElementTree exc) { ename = ""; args = createArray(10); summary = newElement("summary",1); for part in getSubtrees(exc) { if (part.name == "name") { ename = getText(part); } else if (part.name == "arg") { push(args,parseArg(part)); } else if (part.name == "comment") { issummary = extractSummary(part); case issummary of { just(summary) -> ; | nothing -> ; } } } // best copy the summary or there could be some oddities later return ExceptionSummary(ename,args,copy(summary)); } Constructor summariseConstructor(ElementTree con) { cname = ""; args = createArray(10); for part in getSubtrees(con) { if (part.name == "conname") { cname = getText(part); } else if (part.name == "arg") { push(args,parseArg(part)); } } return Constructor(cname,args); } "API documentation An EntryLocation describing the API component to be retrieved. Find a documentation entry Finds a documentation entry for a function, data type or exception in a module. An Exception will be thrown if the entry does not exist. EntryLocation extractSummary" public ElementTree findEntry(APIDoc doc, EntryLocation entry) { case entry.etype of { EntryFunction -> el = "fun"; | EntryData -> el = "data"; | EntryException -> el = "except"; | _ -> throw(ModuleContext); } count = entry.count; // putStrLn(entry.name); for xitem in getSubtrees(doc) { if (xitem.name == el) { if (checkEntry(xitem,entry.name)) { if (count <= 0) { return copy(xitem); } else { count--; } } } } throw(NoSuchEntry(el+": "+entry.name)); } Bool checkEntry(ElementTree item, String name) { for part in getSubtrees(item) { if (part.name == "name") { return (name == getText(part)); } } return false; // shouldn't happen with a proper -xmldocs file } ElementTree getComment(ElementTree item) { for part in getSubtrees(item) { if (part.name == "comment") { return part; } } return noDoc; // shouldn't happen with a proper -xmldocs file } ElementTree noDoc() { doc = newElement("comment"); addString(doc,"No documentation available"); return doc; } "A function description retrieved with findEntry A function that given a name, an index number (for disambiguation of overloaded functions), and an EntryType returns the URL at which documentation for that function / type / module may be found. The name of a function may include the module it is in (e.g. KayaDoc::readDoc) or may not, in which case the current module should be assumed. Describe a function in HTML Return a block of HTML that describes the function. describeDataHTML describeExceptionHTML describeFunctionMan findEntry HTMLDocument::appendExisting" public ElementTree describeFunctionHTML(ElementTree fun, String(String,Int,EntryType) linkto) { summary = summariseFunction(fun); fdesc = summary.rntype+" "+summary.fname+"("+join(summary.args,", ")+")"; div = anonymousBlock; void(addHeading(div,2,fdesc)); if (summary.deprecated) { p = addParagraph(div,""); void(appendInlineElement(p,StrongEmphasis,"This function has been deprecated and will be removed from the module in a future release. See the documentation below for the replacements.")); } toHTML(div,getComment(fun),linkto); return div; } "An Exception description retrieved with findEntry A function that given a name, an index number (for disambiguation of overloaded functions), and an EntryType returns the URL at which documentation for that function / type / module may be found. The name of a function may include the module it is in (e.g. KayaDoc::readDoc) or may not, in which case the current module should be assumed. Describe an Exception in HTML Return a block of HTML that describes the Exception. describeDataHTML describeExceptionMan describeFunctionHTML findEntry HTMLDocument::appendExisting" public ElementTree describeExceptionHTML(ElementTree exc, String(String,Int,EntryType) linkto) { summary = summariseException(exc); edesc = summary.ename+"("+join(summary.args,", ")+")"; div = anonymousBlock; void(addHeading(div,2,edesc)); toHTML(div,getComment(exc),linkto); return div; } "A data type description retrieved with findEntry A function that given a name, an index number (for disambiguation of overloaded functions), and an EntryType returns the URL at which documentation for that function / type / module may be found. The name of a function may include the module it is in (e.g. KayaDoc::readDoc) or may not, in which case the current module should be assumed. Describe a data type in HTML Return a block of HTML that describes the data type. describeDataMan describeExceptionHTML describeFunctionHTML findEntry HTMLDocument::appendExisting" public ElementTree describeDataHTML(ElementTree dat, String(String,Int,EntryType) linkto) { summary = summariseData(dat); if (size(summary.params) > 0) { ddesc = summary.dname+"<"+join(summary.params,", ")+">"; } else { ddesc = summary.dname; } div = anonymousBlock; void(addHeading(div,2,ddesc)); void(addHeading(div,3,"Constructors")); cul = addList(div,Unordered,0); for con in summary.cons { void(pushListItem(cul,con.cname+"("+join(con.args,",")+")")); } toHTML(div,getComment(dat),linkto); return div; } //"argument","summary","prose","example","related","functionref","moduleref","dataref","code","input","output","emphasis","variable","link" "The HTML element to insert documentation into The API documentation for a function, data type or exception A URL generation function that given a name, an index number (for disambiguation of overloaded functions), and an EntryType returns the URL at which documentation for that function / type / module may be found. The name of a function may include the module it is in (e.g. KayaDoc::readDoc) or may not, in which case the current module should be assumed. Convert API documentation to HTML Converts API documentation to HTML. This function rarely needs to be called directly except when using moduleSummary. describeDataHTML describeExceptionHTML describeFunctionHTML" public Void toHTML(ElementTree div, ElementTree comment, String(String,Int,EntryType) linkto) { useargs = false; useusage = false; userelated = false; parseargs = createArray(10); parseusage = createArray(20); parserelated = createArray(10); subs = getSubtrees(comment); if (size(subs) == 0) { // old documentation format void(addParagraph(div,getText(comment))); return; } for item in subs { if (item.name == "argument") { useargs = true; push(parseargs,htmliseArgumentDoc@(item)); } else if (item.name == "related") { userelated = true; push(parserelated,htmliseRelatedDoc@(item)); } else if (item.name == "prose") { useusage = true; push(parseusage,htmliseProse@(item)); } else if (item.name == "example") { useusage = true; push(parseusage,htmliseExample@(item)); } else if (item.name == "list") { useusage = true; push(parseusage,htmliseList@(item)); } } if (useargs) { void(addHeading(div,3,"Arguments")); argul = addList(div,Unordered,0); for pa in parseargs { argli = pushListItem(argul,""); pa(argli,linkto); } } if (useusage) { void(addHeading(div,3,"Usage")); for pu in parseusage { appendExisting(div,pu(linkto)); } } if (userelated) { void(addHeading(div,3,"Related")); relul = addList(div,Unordered,0); for pr in parserelated { relli = pushListItem(relul,""); pr(relli,linkto); } } } Void htmliseArgumentDoc(ElementTree argdoc, ElementTree addto, String(String,Int,EntryType) linkto) { argname = ElementTree::getAttribute(argdoc,"name"); case argname of { nothing -> addString(addto,"Anonymous argument: "); // shouldn't happen | just(argn) -> void(appendInlineElement(addto,ComputerCode,argn)); addString(addto,": "); } htmliseContents(argdoc,addto,linkto); } Void htmliseRelatedDoc(ElementTree argdoc, ElementTree addto, String(String,Int,EntryType) linkto) = htmliseContents(argdoc,addto,linkto); ElementTree htmliseProse(ElementTree prose, String(String,Int,EntryType) linkto) { new = newElement("p"); htmliseContents(prose,new,linkto); return new; } ElementTree htmliseExample(ElementTree ex, String(String,Int,EntryType) linkto) { new = newElement("pre"); code = appendInlineElement(new,ComputerCode,""); htmliseContents(ex,code,linkto); return new; } ElementTree htmliseList(ElementTree ex, String(String,Int,EntryType) linkto) { new = newElement("ul"); for item in getSubtrees(ex) { if (item.name == "item") { li = pushListItem(new,""); htmliseContents(item,li,linkto); } } return new; } // functionref, moduleref, dataref, code, input, output, emphasis, variable, link url= "A section of API documentation, most usually either a prose, item or example element. A HTML element to add the documentation to A URL generation function that given a name, an index number (for disambiguation of overloaded functions), and an EntryType returns the URL at which documentation for that function / type / module may be found. The name of a function may include the module it is in (e.g. KayaDoc::readDoc) or may not, in which case the current module should be assumed. Convert the contents of a (e.g.) <prose> section to HTML Convert a section of API documentation to HTML. This may be useful for working with summary documentation. describeDataHTML describeExceptionHTML describeFunctionHTML" public Void htmliseContents(ElementTree tree, ElementTree addto, String(String,Int,EntryType) linkto) { for item in tree.elements { case item of { CData(cdata) -> addString(addto,cdata); | SubElement(sub) -> if (sub.name == "code") { hsub = appendInlineElement(addto,ComputerCode,""); htmliseContents(sub,hsub,linkto); } else if (sub.name == "input") { hsub = appendInlineElement(addto,SampleInput,""); htmliseContents(sub,hsub,linkto); } else if (sub.name == "output") { hsub = appendInlineElement(addto,SampleOutput,""); htmliseContents(sub,hsub,linkto); } else if (sub.name == "emphasis") { hsub = appendInlineElement(addto,Emphasis,""); htmliseContents(sub,hsub,linkto); } else if (sub.name == "variable") { hsub = appendInlineElement(addto,Variable,""); htmliseContents(sub,hsub,linkto); } else if (sub.name == "link") { hsub = appendInlineElement(addto,Hyperlink(deref(ElementTree::getAttribute(sub,"url"))),""); htmliseContents(sub,hsub,linkto); } else if (sub.name == "moduleref") { modname = getText(sub); hsub = appendInlineElement(addto,Hyperlink(linkto(modname,0,EntryModule)),modname); } else if (sub.name == "functionref") { funname = getText(sub); if (!quickMatch("::",funname)) { lfunname = "module::"+funname; } else { lfunname = funname; } case ElementTree::getAttribute(sub,"index") of { nothing -> idx = 0; | just(idxstr) -> idx = Int(idxstr); } hsub = appendInlineElement(addto,Hyperlink(linkto(lfunname,idx,EntryFunction)),funname); } else if (sub.name == "dataref") { datname = getText(sub); if (!quickMatch("::",datname)) { ldatname = "module::"+datname; } else { ldatname = datname; } hsub = appendInlineElement(addto,Hyperlink(linkto(ldatname,0,EntryData)),datname); } else if (sub.name == "exceptref") { excname = getText(sub); if (!quickMatch("::",excname)) { lexcname = "module::"+excname; } else { lexcname = excname; } hsub = appendInlineElement(addto,Hyperlink(linkto(lexcname,0,EntryException)),excname); } | _ -> ; // shouldn't contain any lazy components } } } "Return a time for a man page Return a time for a man page, in the usual \"month year\" format." public String manTime() { current = gmTime(); return string(current.mon)+" "+current.year; } "A summary returned from extractSummary Convert a summary to man page format Convert a summary to man page format" public String manSummary(ElementTree summary) { return getAllText(summary); } "A function description retrieved with findEntry The current module A string in man page format describing the authorship of the function Describe a function in man page format Return a man page that describes the function. describeDataMan describeExceptionMan describeFunctionHTML findEntry" public String describeFunctionMan(ElementTree fundata, String modname, String authors="") { summary = summariseFunction(fundata); // fdesc = summary.rntype+" "+summary.fname+"("+join(summary.args,",")+")"; manpage = ".TH \""+modname+"."+summary.fname+"\" \"3kaya\" \""+manTime+"\" \"Kaya\" \"Kaya module reference\"\n"; manpage += ".SH \"NAME\"\n"+modname+"::"+summary.fname+" \\- "+manSummary(summary.summary)+"\n"; manpage += ".SH \"SYNOPSIS\"\n"; manpage += ".B "+summary.rntype+" "+summary.fname+"(\n"; manpage += "\\fI"+join(summary.args,", ")+"\\fP\n"; manpage += ".B )\n"; if (summary.deprecated) { manpage += ".SH \"DEPRECATION\"\n"; manpage += ".B This function has been deprecated and will be removed from the module in a future release. See the documentation below for the replacements.\n"; } manpage += toMan(getComment(fundata),modname,authors); return manpage; } "An Exception description retrieved with findEntry The current module A string in man page format describing the authorship of the Exception Describe an Exception in man page format Return a man page that describes the Exception. describeDataMan describeExceptionHTML describeFunctionMan findEntry" public String describeExceptionMan(ElementTree excdata, String modname, String authors="") { summary = summariseException(excdata); // fdesc = summary.rntype+" "+summary.fname+"("+join(summary.args,",")+")"; manpage = ".TH \""+manFilename(summary.ename)+"\" \"3kaya\" \""+manTime+"\" \"Kaya\" \"Kaya module reference\"\n"; manpage += ".SH \"NAME\"\n"+summary.ename+" \\- "+manSummary(summary.summary)+"\n"; manpage += ".SH \"SYNOPSIS\"\n"; manpage += ".B "+summary.ename+"(\n"; manpage += "\\fI"+manQuoteOnly(join(summary.args,", "))+"\\fP\n"; manpage += ".B)\n"; manpage += toMan(getComment(excdata),modname,authors); return manpage; } "A data type description retrieved with findEntry The current module A string in man page format describing the authorship of the data type Describe a data type in man page format Return a man page that describes the data type. describeDataHTML describeExceptionMan describeFunctionMan findEntry" public String describeDataMan(ElementTree ddata, String modname, String authors="") { summary = summariseData(ddata); // fdesc = summary.rntype+" "+summary.fname+"("+join(summary.args,",")+")"; manpage = ".TH \""+manFilename(summary.dname)+"\" \"3kaya\" \""+manTime+"\" \"Kaya\" \"Kaya module reference\"\n"; manpage += ".SH \"NAME\"\n"+summary.dname+" \\- "+manSummary(summary.summary)+"\n"; manpage += ".SH \"SYNOPSIS\"\n"; manpage += ".B "+summary.dname+"<\n"; manpage += "\\fI"+manQuoteOnly(join(summary.params,", "))+"\\fP\n"; manpage += ".B >\n"; for con@idx in summary.cons { if (idx == 0) { manpage += ".IP \"\" -2\n= \n"; } else { manpage += ".IP \"\" -2\n| \n"; } manpage += ".BI \""+con.cname+"(\" \""+join(con.args,",")+"\" \")\"\n"; } manpage += toMan(getComment(ddata),modname,authors); return manpage; } "The API documentation for a function, data type or exception The current module A string in man page format describing the authorship of the data type Convert API documentation to man page format Converts API documentation to man page format. This function rarely needs to be called directly except when using moduleSummary. describeDataMan describeExceptionMan describeFunctionMan" public String toMan(ElementTree div, String modname, String authors) { useargs = false; useusage = false; userelated = false; parseargs = createArray(10); parseusage = createArray(20); parserelated = createArray(10); subs = getSubtrees(div); if (size(subs) == 0) { // old documentation format return ".SH \"DESCRIPTION\"\nDetailed documentation unavailable.\n"; } manstr = ""; for item in subs { if (item.name == "argument") { useargs = true; argname = ElementTree::getAttribute(item,"name"); case argname of { nothing -> ; argn = "";// shouldn't happen | just(argn) -> ; } push(parseargs,maniseContents@(item,false,".PP\n.B \""+argn+"\"\n")); } else if (item.name == "related") { userelated = true; push(parserelated,maniseContents@(item,false,".PP\n")); } else if (item.name == "prose") { useusage = true; push(parseusage,maniseContents@(item,false,".PP\n")); } else if (item.name == "example") { useusage = true; push(parseusage,maniseContents@(item,true,".IP \"\" -4\n")); } else if (item.name == "list") { useusage = true; push(parseusage,maniseList@(item,false,".IP \"\" -2\n- \n")); } } if (useargs) { manstr += ".SH \"ARGUMENTS\"\n"; for pa in parseargs { manstr += pa(modname); } } if (useusage) { manstr += ".SH \"DESCRIPTION\"\n"; for pu in parseusage { manstr += pu(modname); } } if (authors != "") { manstr += ".SH \"AUTHORS\"\n"+authors+"\n"; } if (userelated) { manstr += ".SH \"RELATED\"\n"; manstr += ".PD 0\n"; for pr in parserelated { manstr += pr(modname); } manstr += ".PD 0.4v\n"; } return manstr; } String manQuoteOnly(String unq) { replace("\""," \" ",unq,[Global]); return unq; } String manQuote(String unq) { // replace("\"","\\\"",unq,[Global]); return manEscape(unq); } String manEscape(String esc) { replace("\\\\","\\\\",esc,[Global]); return esc; } String maniseList(ElementTree summary, Bool preformatted, String manstr, String modname) { str = ""; for item in getSubtrees(summary) { if (item.name == "item") { str += maniseContents(item,preformatted,copy(manstr),modname); } } return str; } "A section of API documentation, most usually either a prose, item or example element. Is the text in this section preformatted? This should generally be set to true for processing example elements, and false otherwise. This String will be prepended to the output The name of the current module Convert the contents of a (e.g.) <prose> section to man page format Convert a section of API documentation to man page format. This may be useful for working with summary documentation. describeDataMan describeExceptionMan describeFunctionMan" public String maniseContents(ElementTree summary, Bool preformatted, String manstr, String modname) { for item in summary.elements { case item of { CData(cdata) -> text = copy(cdata); trim(text); if (preformatted) { replace("\n","\n ",text,[Global]); replace("^"," ",text); // not Global!!! } replace("^\\.","",text,[Global]); replace("\n\\.","\n",text,[Global]); manstr += manEscape(text)+"\n"; | SubElement(sub) -> if (sub.name == "code") { manstr += "\\fB"+manQuote(getAllText(sub))+" \\fP\n"; } else if (sub.name == "input") { manstr += "\\fI"+manQuote(getAllText(sub))+"\\fP\n"; } else if (sub.name == "output") { manstr += "\\fI"+manQuote(getAllText(sub))+"\\fP\n"; } else if (sub.name == "emphasis") { manstr += "\\fB"+manQuote(getAllText(sub))+"\\fP\n"; } else if (sub.name == "variable") { manstr += "\\fI"+manQuote(getAllText(sub))+"\\fP\n"; } else if (sub.name == "link") { url = deref(ElementTree::getAttribute(sub,"url")); manstr += ".UR \""+url+"\"\n"+manQuote(getAllText(sub))+"\n.UE\n"; } else if (sub.name == "moduleref") { modname = getText(sub); manstr += ".BR \""+modname+"(3kaya)\"\n"; } else if (sub.name == "functionref") { funname = getText(sub); if (!quickMatch("::",funname)) { lfunname = modname+"."+funname; } else { lfunname = manFilename(funname); } case ElementTree::getAttribute(sub,"index") of { nothing -> idx = 0; | just(idxstr) -> idx = Int(idxstr); } if (idx > 0) { lfunname += "_"+idx; } manstr += ".B \""+lfunname+"\"(3kaya)\n"; } else if (sub.name == "dataref") { datname = getText(sub); if (!quickMatch("::",datname)) { ldatname = modname+"."+datname; } else { ldatname = manFilename(datname); } manstr += ".B \""+ldatname+"\"(3kaya)\n"; } else if (sub.name == "exceptref") { excname = getText(sub); if (!quickMatch("::",excname)) { lexcname = modname+"."+excname; } else { lexcname = manFilename(excname); } manstr += ".B \""+lexcname+"\"(3kaya)\n"; } | _ -> ; // shouldn't contain any lazy components } } return manstr; } "The name of a fucntion or data type Return the man page name for a function or data type Return the man page name for a function or data type. For example, KayaDoc::manFilename becomes KayaDoc.manFilename (you will have to append the section name in the appropriate format yourself)" public String manFilename(String name) { replace("::",".",name); return name; } kaya-0.4.4/stdlib/ElementTree.k0000644000175100017510000013576411170340770014436 0ustar cimcim/** -*-C-*-ish ElementTree.k Copyright (C) 2005 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Manipulation of ElementTrees This module contains functions for manipulating HTML or XML element trees described by ElementTreeData::ElementTree, including conversion to and from Strings, and a basic templating system." module ElementTree; import Prelude; import Regex; import Strings; import Dict; import Set; import public ElementTreeData; import XMLentities; data StartTagType = BlackListed | Empty(ElementTree e) | ImplicitCloser | NormalOpen(ElementTree o) | TemplateFn(ElementTree() fn); "The String contains error details Input error parsing XML An error occurred while importing an XML string. elementTree" Exception InputError(String s); "The String contains the position of the error Unexpected end of data parsing XML The XML string unexpectedly ended while trying to import. elementTree" Exception UnexpectedEnd(String p); "The Char contains the character expected, and the String contains the position of the error Expected character missing parsing XML An expected character was not present when parsing XML. elementTree" Exception ExpectedChar(Char c, String p); "The Char contains the unexpected character, and the String contains the position of the error Unexpected character found parsing XML An unexpected character was found when parsing XML. elementTree" Exception UnexpectedChar(Char c, String p); "The item to evaluate is not a generator This Exception is thrown if the item being evaluated is not a generator (so instead is a normal sub-element or text block). evaluateGenerator" Exception NotLazy(); foreign "stdfuns.o" { // PRIVATE utility function for doing string operations when we // already know we're in bounds pure Char unsafeIndex(String s, Int i) = getIndex; String do_unsafeSubstr(Ptr vm, String x, Int i, Int len) = getsubstr; Int offsetFirstOccurs(Char c, String str, Int i) = offset_wcscspn; } String unsafeSubstr(String x, Int i, Int len) = do_unsafeSubstr(getVM,x,i,len); "The ElementTree to convert to a String How to print empty tags (see ElementTreeData::EmptyTagMode). Optional, defaulting to OpenAndClose. The initial indentation level to use. Optional, defaulting to zero. The method of printing non-ASCII characters (see ElementTreeData::UnicodeFormat). Optional, defaulting to LiteralUTF8. A dictionary of elements that start a new line in the output code. Optional, defaulting to an empty dictionary A dictionary of elements that are empty. Optional, defaulting to an empty dictionary Convert an ElementTree to a String Convert an ElementTree to a String, using the selected conversion options. If the String will be printed immediately, use lazyPrint instead. lazyPrint" public String string(ElementTree etree, EmptyTagMode mode = OpenAndClose, Int indentlevel = 0, UnicodeFormat uform = LiteralUTF8, HashSet breakers=newHashSet(1,strHash), HashSet emptyels=newHashSet(1,strHash)) { output = ""; indents = makeIndents(); void(doToString(output,etree,mode,indentlevel,uform,breakers,emptyels,indents)); return output; } // false for nobreak, true otherwise Bool format(HashSet formats, String name) = elem(name,formats); // recursively does things with the string Bool doToString(var String output, ElementTree etree, EmptyTagMode mode = OpenAndClose, Int indentlevel = 0, UnicodeFormat uform = LiteralUTF8, HashSet breakers=newHashSet(1,strHash), HashSet emptyels=newHashSet(1,strHash), var [String] indents) { elformat = format(breakers,etree.name); if (elformat) { output += getIndent(indents,indentlevel); } if (size(etree.elements) > 0 || mode == OpenAndClose) { output += startTag(etree,uform); lastse = false; for element in etree.elements { case element of { // either it's a sub-element SubElement(nested) -> lastse = doToString(output,nested,mode,indentlevel+1,uform,breakers,emptyels,indents); // or it's text (which can't contain tags...) | CData(cdata) -> lastse = false; // don't need to encode quotes here. output += simpleEncode(cdata,true,uform); // or it's for lazy evaluation and will be a sub-element | SubTree(generator) -> lastse = lazyString(output,@generator,mode,indentlevel,uform,breakers,emptyels,indents); } } if (elformat && lastse) { output += getIndent(indents,indentlevel); } output += endTag(etree); } else { // if it contains nothing, and the parse mode is appropriate, // assume it's an empty tag. if (elem(etree.name,emptyels)) { output += singletonTag(etree,mode,uform); } else { // then we need to explicitly open and close it output += startTag(etree,uform)+endTag(etree); } } // gc(); return elformat; } Bool lazyString(var String output, ElementTree() generator, EmptyTagMode mode = OpenAndClose, Int indentlevel = 0, UnicodeFormat uform = LiteralUTF8, HashSet breakers=newHashSet(1,strHash), HashSet emptyels=newHashSet(1,strHash), var [String] indents) { return doToString(output,generator(),mode,indentlevel+1,uform,breakers,emptyels,indents); } "The ElementTree to print How to print empty tags (see ElementTreeData::EmptyTagMode). Optional, defaulting to OpenAndClose. The initial indentation level to use. Optional, defaulting to zero. The method of printing non-ASCII characters (see ElementTreeData::UnicodeFormat). Optional, defaulting to LiteralUTF8. A dictionary of elements that start a new line in the output code. Optional, defaulting to an empty dictionary A dictionary of elements that are empty. Optional, defaulting to an empty dictionary A function to output strings Print an ElementTree to a user-defined target Print an ElementTree to the target of outfn, using the selected conversion options. lazyPrint string" public Void lazyOutput(ElementTree etree, EmptyTagMode mode = OpenAndClose, Int indentlevel = 0, UnicodeFormat uform = LiteralUTF8, HashSet breakers=newHashSet(1,strHash), HashSet emptyels=newHashSet(1,strHash), Void(String) outfn) { indents = makeIndents(); void(doLazyOutput(etree,mode,indentlevel,uform,breakers,emptyels,indents,outfn)); } "The ElementTree to print How to print empty tags (see ElementTreeData::EmptyTagMode). Optional, defaulting to OpenAndClose. The initial indentation level to use. Optional, defaulting to zero. The method of printing non-ASCII characters (see ElementTreeData::UnicodeFormat). Optional, defaulting to LiteralUTF8. A dictionary of elements that start a new line in the output code. Optional, defaulting to an empty dictionary A dictionary of elements that are empty. Optional, defaulting to an empty dictionary Print an ElementTree Print an ElementTree to standard output, using the selected conversion options. lazyOutput string" public Void lazyPrint(ElementTree etree, EmptyTagMode mode = OpenAndClose, Int indentlevel = 0, UnicodeFormat uform = LiteralUTF8, HashSet breakers=newHashSet(1,strHash), HashSet emptyels=newHashSet(1,strHash)) { indents = makeIndents(); void(doLazyPrint(etree,mode,indentlevel,uform,breakers,emptyels,indents)); } Bool doLazyPrint(ElementTree etree, EmptyTagMode mode = OpenAndClose, Int indentlevel = 0, UnicodeFormat uform = LiteralUTF8, HashSet breakers=newHashSet(1,strHash), HashSet emptyels=newHashSet(1,strHash), [String] indents) { elformat = format(breakers,etree.name); if (elformat) { putStr(getIndent(indents,indentlevel)); } if (size(etree.elements) > 0) { putStr(startTag(etree,uform)); lastse = false; if (elformat) { ninlevel = indentlevel+1; } else { ninlevel = indentlevel; } for element in etree.elements { case element of { SubElement(nested) -> lastse = doLazyPrint(nested,mode,ninlevel,uform,breakers,emptyels,indents); | CData(cdata) -> lastse = false; putStr(simpleEncode(cdata,true,uform)); | SubTree(generator) -> lastse = doLazyPrint(generator(),mode,ninlevel,uform,breakers,emptyels,indents); //gc(); } } if (elformat && lastse) { putStr(getIndent(indents,indentlevel)); } putStr(endTag(etree)); } else { if (elem(etree.name,emptyels) && mode != OpenAndClose) { putStr(singletonTag(etree,mode,uform)); } else { putStr(startTag(etree,uform)); putStr(endTag(etree)); } } return elformat; } Bool doLazyOutput(ElementTree etree, EmptyTagMode mode = OpenAndClose, Int indentlevel = 0, UnicodeFormat uform = LiteralUTF8, HashSet breakers=newHashSet(1,strHash), HashSet emptyels=newHashSet(1,strHash), [String] indents, Void(String) outfn) { elformat = format(breakers,etree.name); if (elformat) { outfn(getIndent(indents,indentlevel)); } if (size(etree.elements) > 0) { outfn(startTag(etree,uform)); lastse = false; if (elformat) { ninlevel = indentlevel+1; } else { ninlevel = indentlevel; } for element in etree.elements { case element of { SubElement(nested) -> lastse = doLazyOutput(nested,mode,ninlevel,uform,breakers,emptyels,indents,outfn); | CData(cdata) -> lastse = false; outfn(simpleEncode(cdata,true,uform)); | SubTree(generator) -> lastse = doLazyOutput(generator(),mode,ninlevel,uform,breakers,emptyels,indents,outfn); //gc(); } } if (elformat && lastse) { outfn(getIndent(indents,indentlevel)); } outfn(endTag(etree)); } else { if (elem(etree.name,emptyels) && mode != OpenAndClose) { outfn(singletonTag(etree,mode,uform)); } else { outfn(startTag(etree,uform)); outfn(endTag(etree)); } } return elformat; } // this looks a bit silly, but it's more efficient than calling rep() // every time. [String] makeIndents() = ["\n", "\n ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n ", "\n "]; // have some in to start with String getIndent(var [String] indents, Int level) { i = indents[level]; if (isInitialised(i)) { return i; } // because it can only increase one at a time i = indents[level-1]+" "; return i; } private String startTag(ElementTree etree, UnicodeFormat uform) = openTag(etree,uform)+">"; private String endTag(ElementTree etree) = ""; private String singletonTag(ElementTree etree, EmptyTagMode mode, UnicodeFormat uform) { output = openTag(etree,uform); case mode of { ImpliedSingleton -> output += ">"; | _ -> output += " />"; } return output; } private String openTag(ElementTree etree, UnicodeFormat uform) { // this will need modification if we ever start on XML namespaces output = "<"+etree.name; // only more efficient for tinyDict names = keys(etree.attributes); values = vals(etree.attributes); for i in [0..size(names)-1] { /* if (quickMatch("[^A-Za-z]",key) || key == "") { // throw(ElementParseError); } */ output += " " + names[i] + "=\"" + simpleEncode(values[i],false,uform) + "\""; } return output; } "The String to escape Whether to leave quotes unescaped. This is optional and defaults to false (i.e. quotes will be escaped) If this is set to NumericReference (not the default) then non-ASCII characters will be replaced by numeric references. HTML-escape a string HTML-escape a string, so that <, >, & and possibly " are converted to their entity equivalents (&lt;, &gt;, &amp; and &quot; respectively). This is automatically done to all element text content and attribute values when converting ElementTree to String - this function is provided for use in other contexts." public String simpleEncode(String invalue, Bool leavequotes=false, UnicodeFormat uform=LiteralUTF8) { if (invalue == "" || (!elem('&',invalue) && (leavequotes || !elem('"',invalue)) && !elem('<',invalue))) { return invalue; } value = copy(invalue); // here we rely on the incoming code being literal UTF8. It should be. replace("&","&",value,[Global]); replace("<","<",value,[Global]); // replace(">",">",value,[Global]); // unnecessary if (!leavequotes) { replace("\"",""",value,[Global]); } // don't need to escape ' because we always use " to quote values case uform of { LiteralUTF8 -> return value; | NumericReference -> return literalToEntity(value); } } "The name of the new element This argument is used for optimising internal functions but may be useful to end users in some circumstances - it gives the expected number of child elements (including text data blocks). It is optional and defaults to 10. Create a new element Creates a new Element with the specified name." public ElementTree newElement(String name, Int expectedchildren=0) { // use Dict::newTiny because most elements have few attributes. if (expectedchildren > 0) { return ElementTree(createArray(expectedchildren),name,Dict::newTiny); } else { // 10 is probably a reasonable guess for most elements. return ElementTree(createArray(10),name,Dict::newTiny); } } public Int attrHash(String tohash) = Int(head(tohash)); "The parent element The child element Add a new child element to the end Adds a new child element to the end of the parent element. addElementAt pushData pushGenerator unshiftElement" public Void pushElement(ElementTree parent, ElementTree child) { push(parent.elements,SubElement(child)); } "The parent element The child element Add a new child element to the start Adds a new child element to the start of the parent element. addElementAt unshiftData unshiftGenerator pushElement" public Void unshiftElement(ElementTree parent, ElementTree child) { unshift(SubElement(child),parent.elements); } "The parent element The child element The index starting from zero Add a new child element Adds a new child element to the parent element at the specified index. addDataAt addGeneratorAt pushElement unshiftElement" public Void addElementAt(ElementTree parent, ElementTree child, Int index) { addAt(parent.elements,SubElement(child),index); } "The parent element The child generator Add a new child generator to the end Adds a new child generator to the end of the parent element. This allows the element tree to be built up lazily saving memory. addGeneratorAt pushData pushElement unshiftGenerator" public Void pushGenerator(ElementTree parent, ElementTree() child) { push(parent.elements,SubTree(@child)); } "The parent element The child generator Add a new child generator to the start Adds a new child generator to the start of the parent element. This allows the element tree to be built up lazily saving memory. addGeneratorAt pushGenerator unshiftData unshiftElement" public Void unshiftGenerator(ElementTree parent, ElementTree() child) { unshift(SubTree(@child),parent.elements); } "The parent element The child element The index starting from zero Add a new child generator Adds a new child generator to the parent element at the specified index. This allows the element tree to be built up lazily saving memory. addDataAt addElementAt pushGenerator unshiftGenerator" public Void addGeneratorAt(ElementTree parent, ElementTree() child, Int index) { addAt(parent.elements,SubTree(@child),index); } "The parent element The text to add Add text to the end of an element Adds the text to the end of the parent element. Adjacent text blocks will be merged. addDataAt pushElement pushGenerator unshiftData" public Void pushData(ElementTree parent, String cdata) { if (size(parent.elements) == 0) { push(parent.elements,CData(cdata)); } else { case parent.elements[size(parent.elements)-1] of { CData(text) -> parent.elements[size(parent.elements)-1].cdata += cdata; | _ -> push(parent.elements,CData(cdata)); } } } "The parent element The text to add Add text to the start of an element Adds the text to the start of the parent element. Adjacent text blocks will be merged. addDataAt pushData unshiftElement unshiftGenerator" public Void unshiftData(ElementTree parent, String cdata) { if (size(parent.elements) == 0) { unshift(CData(cdata),parent.elements); } else { case parent.elements[0] of { CData(text) -> parent.elements[0].cdata = cdata + parent.elements[0].cdata; | _ -> unshift(CData(cdata),parent.elements); } } } "The parent element The text to add The index to add at Add text to an element Adds the text to the specified position in the parent element. If the preceding block is also a text block, they will be merged. addElementAt addGeneratorAt pushData unshiftData" public Void addDataAt(ElementTree parent, String cdata, Int index) { if (index == 0) { unshiftData(parent,cdata); } else { case parent.elements[index-1] of { CData(text) -> parent.elements[index-1].cdata += cdata; | _ -> addAt(parent.elements,CData(cdata),index); } } } "The parent element The index to evaluate Evaluate a lazy element generator Evaluate a lazy element generator and replace it with its result. This can be useful if you need to further process the results before printing the element tree, or if you want to Pickle the element tree." public Void evaluateGenerator(ElementTree element, Int idx) { case element.elements[idx] of { SubTree(gen) -> element.elements[idx] = SubElement(gen()); | _ -> throw(NotLazy); } } "The element The attribute to set The attribute value Set an attribute Set an element attribute, overwriting any existing value. getAttribute getAttributes unsetAttribute" public Void setAttribute(ElementTree element, String name, String value) { add(element.attributes,name,value); } "The element The attribute to unset Unset an attribute Unset an element attribute. getAttribute getAttributes setAttribute" public Void unsetAttribute(ElementTree element, String name) { delete(element.attributes,name); } "The element Get the text length of an element Get the text length of an element's contents, including any text in sub-elements, but not the tags that delimit those elements. Items such as < are shown in their unescaped form. Note that any element generators inside the element will be evaluated as a result of this function, which may be very inefficient." public Int textSizeOfBlock(Element element) { case element of { CData(text) -> return length(text); | SubElement(el) -> len = 0; for elem in el.elements { len += textSizeOfBlock(elem); } return len; | SubTree(gen) -> el = gen(); // this can be really inefficient. for elem in el.elements { len += textSizeOfBlock(elem); } return len; } } "The parent element Get all child elements Get all child elements, whether they are sub trees, generators, or text blocks. getAttribute getAttributes getName getSubtrees" public [Element] getElements(ElementTree block) { return block.elements; } "The element Get an element name Get the name of the element getAttribute getAttributes getElements" public String getName(ElementTree block) { return block.name; } "The element Get an element's attributes Gets the element's attributes getAttribute getElements getName setAttribute unsetAttribute" public TinyDict getAttributes(ElementTree block) { return block.attributes; } "The element The attribute Get an attribute value from an element Gets an attribute value from the element, or nothing if the element does not have that attribute. getAttributes getElements getName setAttribute unsetAttribute" public Maybe getAttribute(ElementTree block, String attribute) { return lookup(block.attributes,attribute); } "The element The child element's name Get the index of a named sub-element from an element Gets the index of the first named sub-element within the parent element, or nothing if the element does not have a sub-element with that name. Generators will be evaluated to see if their root element is the right element." public Maybe findElement(ElementTree block, String subname) { i=0; for e in block.elements { case e of { SubElement(el) -> if (el.name == subname) { return just(i); } | SubTree(gen) -> el = gen(); if (el.name == subname) { return just(i); } | _ -> ; } i++; } return nothing; } "The parent element Get all child element trees Get all child element trees, excluding generators and text blocks. getElements" public [ElementTree] getSubtrees(ElementTree outer) { inner = []; for el in getElements(outer) { case el of { SubElement(etree) -> push(inner,etree); | _ -> ; } } return inner; } "The element Returns the text content of the element Returns the text content of the element (excluding text in sub-elements) getAllText textSizeOfBlock" public String getText(ElementTree outer) { inner = ""; for el in getElements(outer) { case el of { CData(cd) -> inner += cd; | _ -> ; } } return inner; } "The element Returns the text content of the element and children Returns the text content of the element (including text in sub-elements). Generators will be evaluated to calculate their text content. getText textSizeOfBlock" public String getAllText(ElementTree outer) { inner = ""; for el in getElements(outer) { case el of { CData(cd) -> inner += cd; | SubElement(tree) -> inner += getAllText(tree); | SubTree(gen) -> inner += getAllText(gen()); } } return inner; } "The element tree to be processed A list of the names of elements exempted from being processed (for example, in HTML, the <img> element is empty, but may not be appropriate for removal. If an exempt element contains empty elements, these elements will not be removed either. Recursively remove empty elements Recursively removes empty elements (i.e. elements that only contain other empty elements and whitespace) from an ElementTree. This function returns true if once this is done the current element is itself empty, false otherwise. Generators are not evaluated but are assumed to be non-empty." Bool stripEmpty(ElementTree tree, [String] exempt=createArray(1)) { rms = []; isempty = true; for el@i in getElements(tree) { case el of { SubElement(n) -> if (!elem(n.name,exempt) && stripEmpty(n)) { unshift(i,rms); } else { isempty = false; } | CData(c) -> if (quickMatch("\\S",c)) { isempty = false; } else { unshift(i,rms); } | _ -> isempty = false; } } for rm in rms { removeAt(tree.elements,rm); } return isempty; } /* Start of String->ElementTree conversion functions */ // private data type for caching data Original (String str, Int len); data ConvertOpts(Dict whitelist, Dict implicitend, [String] emptyels, Dict templates, Bool wlempty, Bool ieempty, Bool tmempty, Bool casesen, Bool sloppy); "The String to convert The name of the root element to use as a parent. Optional, defaulting to \"tree\". A whitelist dictionary of allowed elements. The key is the element name, the value is a list of allowed attribute names for that element. If the key is \"*\" then all elements are allowed (though you may wish to explicitly specify others to override the attributes specified for \"*\"). If the value list contains \"*\" then all attributes are allowed. Optional, defaulting to the empty dictionary, which makes this function strip all tags from the string as it imports it. A dictionary of tags that close elements other than their own. In XML, this should be an empty dictionary - it is used to parse HTML and other SGML dialects that allow implicit closing. The key is the element to close, and the value is a list of tags that will close that element, represented as \"tagname\" for an opening tag, and \"/tagname\" for a closing tag. For example, the implicit ending list for the \"li\" element in HTML is [\"li\",\"/ul\",\"/ol\"]. This is optional and defaults to the empty dictionary, which is correct for XML strings. A list of elements that are allowed to be empty (i.e. a singleton tag such as <br> is allowed). This is very important when importing HTML or other SGML dialects where a singleton tag might not differ in appearance from a normal opening tag. This is optional and defaults to the empty list. When processing XML, this list should always be empty, as it is never ambiguous. A dictionary of elements that are really calls to templating functions. The key is the element name, and the value is a function that takes a list of pairs of attributes and returns an ElementTree. This can be used for templating, or for converting one form of XML into another. This is optional and defaults to the empty dictionary. Should conversion be case-sensitive? If this is false, all whitelist, implicitend, emptyels and templates keys and values will be treated as case-insensitive, and all elements will be converted to lowercase. In XML, this should be set to true, which will give some increase in processing speed. This parameter is optional and the default value is false. Use 'sloppy' processing, which attempts to make a reasonable guess at the meaning of broken input. It may guess entirely wrongly, of course, and in some circumstances it may still throw an Exception. Optional, defaulting to false (where it should be left if possible!). This argument is ignored if the templates dictionary has any contents. Converts a String to an ElementTree. Converts a String to an ElementTree. Several additional parameters may be passed to control various aspects of the conversion. string" // case sensitive is twice as fast sometimes! public ElementTree elementTree(String original, String rootelement="tree", Dict whitelist=Dict::new(2,strHash), Dict implicitend=Dict::new(2,strHash), [String] emptyels=createArray(1), Dict templates=Dict::new(2,strHash), Bool casesensitive=false, Bool sloppy=false) { tree = newElement(rootelement); pos = 0; len = length(original); if (!empty(templates)) { sloppy = false; } if (casesensitive) { opts = ConvertOpts(whitelist,implicitend,emptyels,templates,empty(whitelist),empty(implicitend),empty(templates),true,sloppy); } else { opts = ConvertOpts(lowerDict(whitelist),lowerDict(implicitend),emptyels,lowerDict(templates),empty(whitelist),empty(implicitend),empty(templates),false,sloppy); } parseString(Original(original,len),tree,pos,opts); if (pos < len && !sloppy) { throw(InputError("Unexpectedly reached end at "+pos+" before actual end of string.")); } return tree; } Dict lowerDict(Dict indict) { outdict = Dict::new(numBuckets(indict),strHash); for entry in entries(indict) { add(outdict,toLower(entry.fst),entry.snd); } return outdict; } // go along collecting until we get to a tag start // then parse the tag and recursively call on that tag // or if it's an end tag, check it matches // or check it's in implicitend // return if it's a matching end tag // if end of string reached, quit // throw exceptions if something goes wrong Void parseString(Original original, ElementTree tree, var Int pos, ConvertOpts opts) { // tschar = compile("[A-Za-z_]"); len = original.len; str = ""; while (pos < len) { skip = offsetFirstOccurs('<',original.str,pos); if (skip > 0) { str += unsafeSubstr(original.str,pos,skip); pos += skip; } if (pos < len) { // c=='<' if we've not reached the end of the string if (pos+1 < len) { fchar = unsafeIndex(original.str,pos+1); if (fchar == '/') { if (parseEndTag(original,tree.name,pos,opts)) { if (str != "") { pushData(tree,entityToLiteral(str)); } return; } } else if (isAlpha(fchar) || fchar == '_') { if (str != "") { pushData(tree,entityToLiteral(str)); str = ""; } case analyseStartTag(original,tree.name,pos,opts) of { BlackListed -> skipTag(original,pos,opts); | Empty(newel) -> pushElement(tree,newel); pos--; | ImplicitCloser -> pos--; return; // don't move on by pos in this case | NormalOpen(newel) -> pushElement(tree,newel); parseString(original,newel,pos,opts); | TemplateFn(fn) -> pushGenerator(tree,@fn); } } else if (fchar == '!') { if (pos+3 < len) { if ((unsafeIndex(original.str,pos+2) == '-') && (unsafeIndex(original.str,pos+3) == '-')) { pos += 4; skipComment(original,pos,opts); } else { skipTag(original,pos,opts); } } else { if (opts.sloppy) { return; } throw(UnexpectedEnd(getLP(original,pos+1))); } // } else if (quickMatchWith(tschar,String(fchar))) { } else { // literal character str += "<"; } } else { // literal character str += "<"; } } pos++; } if (str != "") { pushData(tree,entityToLiteral(str)); //only happens on root of stack } } // find out what sort of end tag this is. // if it matches the current element, return. // if it matches an implicit end for the current element, RESET pos // and return // otherwise exception. Bool parseEndTag(Original original, String currentname, var Int pos, ConvertOpts opts) { // pos currently points at the '<' ipos = pos+2; // now points just after = len) { throw(UnexpectedEnd(getLP(original,ipos))); } else if (unsafeIndex(original.str,ipos) != '/') { throw(ExpectedChar('/',getLP(original,ipos))); } ipos++; // now points just after ',opts); if (tagname == "") { if (opts.sloppy) { return false; // pos is possibly somewhere reasonably sensible now } throw(UnexpectedChar(unsafeIndex(original.str,ipos),getLP(original,ipos))); } while(isSpace(unsafeIndex(original.str,ipos))) { ipos++; if (ipos >= len) { if (opts.sloppy) { return true; // well, it probably meant to close it } throw(UnexpectedEnd(getLP(original,ipos))); } } if (unsafeIndex(original.str,ipos) != '>') { if (!opts.sloppy) { throw(UnexpectedChar(unsafeIndex(original.str,ipos),getLP(original,ipos))); } } // ipos++; // ipos now points just past the end of the close tag. if (tagname == currentname) { // simplest case, tag is closing the current element pos = ipos; // update pos return true; } else { if (!opts.ieempty) { iclosers = lookup(opts.implicitend,currentname); case iclosers of { nothing -> ; | just(icloser) -> ctag = "/"+tagname; if (elem(ctag,icloser)) { // implicit closing. Don't update pos from ipos pos--; // but do decrement it return true; } } } if (opts.wlempty || exists(opts.whitelist,tagname) || exists(opts.whitelist,"*")) { if (opts.sloppy) { pos = ipos; // we're probably correcting for a previous error here return false; } throw(InputError("Unexpected closing tag "+tagname+" at "+getLP(original,pos))); } else { // it's a blacklisted tag, so assume we skipped an earlier start tag. pos = ipos; // we do update pos here. return false; // but don't drop a level } } } // Perhaps there needs to be a better way to deal with namespaces here? String getTagName(Original original, var Int ipos, Char closer= '>', ConvertOpts opts) { tagname = createString(10); len = original.len; // closer defaults to > as a safe character, but when it's set to = above // still need to check for > for shortattrs. str = original.str; c = unsafeIndex(str,ipos); if (!(isAlpha(c) || c == '_' || c == ':')) { if (opts.sloppy) { return ""; } throw(UnexpectedChar(c,getLP(original,ipos))); } while (ipos < len) { if (isAlnum(c) || c == '.' || c == '-' || c == '_' || c == ':') { tagname += c; ipos++; c = unsafeIndex(str,ipos); // worst case sets 'c' == '\0', so safe } else if (c == '>' || isSpace(c) || c == closer || c == '/') { if (opts.casesen) { return tagname; } else { return toLower(tagname); } } else { if (opts.sloppy) { return ""; } throw(UnexpectedChar(c,getLP(original,ipos))); } } // tag/attr names can't be at the end of the file! if (opts.sloppy) { ipos--; return ""; } throw(UnexpectedEnd(getLP(original,ipos))); } StartTagType analyseStartTag(Original original, String currentname, var Int pos, ConvertOpts opts) { // pos currently points at the '<' ipos = pos+1; // in case we get an implicit closer or a blacklist tagname = getTagName(original,ipos,'>',opts); if (tagname == "") { if (opts.sloppy) { return BlackListed; // mangled tag } throw(UnexpectedChar(unsafeIndex(original.str,ipos),getLP(original,ipos))); } if (!opts.wlempty && !exists(opts.whitelist,tagname) && !exists(opts.whitelist,"*")) { if (opts.tmempty || !exists(opts.templates,tagname)) { return BlackListed; } } if (!opts.ieempty) { case lookup(opts.implicitend,currentname) of { nothing -> ; | just(enders) -> if (elem(tagname,enders)) { // implicit ending of current element, so need to end it before we start a new one return ImplicitCloser; } } } if (!opts.tmempty) { case lookup(opts.templates,tagname) of { nothing -> ; | just(fn) -> tfn = copy(fn); newel = newElement(tagname); if(parseAttributes(original,ipos,newel,opts)) { ipos++; skipToTagEnd(original,ipos,opts); } pos = ipos; return TemplateFn(tfn@(entries(newel.attributes))); } } // now ipos is just after the ipos++; // skip it, we know // and now skip any whitespace after the '/' skipToTagEnd(original,ipos,opts); | NormalOpen(n) -> ipos++; // if it's an actual '/' closing, could // be a "happens to be empty" element in XML. skipToTagEnd(original,ipos,opts); rv = Empty(n); | _ -> if (opts.sloppy) { pos = ipos+1; // might be in about the right place? return Empty(n); // treat as empty even though it shouldn't be? } throw(InputError("Unexpected closing of non-empty element.")); } } // ipos++; // ipos now points just past the end of the close tag. pos = ipos+1; return rv; } Void skipToTagEnd(Original original, var Int ipos, ConvertOpts opts) { len = original.len; if (ipos >= len) { if (opts.sloppy) { return; } throw(UnexpectedEnd(getLP(original,ipos))); } while(isSpace(unsafeIndex(original.str,ipos))) { ipos++; if (ipos >= len) { if (opts.sloppy) { return; } throw(UnexpectedEnd(getLP(original,ipos))); } } if (unsafeIndex(original.str,ipos) != '>') { // if parseAtt false already know this if (!opts.sloppy) { throw(UnexpectedChar(unsafeIndex(original.str,ipos),getLP(original,ipos))); } } } // true for XML empty closer, false for end of tag, to optimise analyseS.T. Bool parseAttributes(Original original, var Int ipos, ElementTree el, ConvertOpts opts) { len = original.len; while (ipos < len) { c = unsafeIndex(original.str,ipos); if (c == '>') { return false; } else if (c == '/') { return true; } else { // get through any whitespace separating attribs if (!isSpace(c)) { parseAttribute(original,ipos,el,opts); } ipos++; } } if (opts.sloppy) { ipos = len-3; // back off a bit to try again later return false; } throw(UnexpectedEnd(getLP(original,ipos))); } Void parseAttribute(Original original, var Int ipos, ElementTree el, ConvertOpts opts) { // ipos is just after the whitespace attrname = getTagName(original,ipos,'=',opts); // ipos is on '=', in theory c = unsafeIndex(original.str,ipos); if (isSpace(c)) { // unless it's a minimised attribute (which can be the end of the tag, of course) attrval = attrname; //actually, name = val, here. } else if (c == '>') { attrval = attrname; //actually, name = val, here. ipos--; /* } else if (c != '=') { throw(UnexpectedChar(c,getLP(original,ipos))); */ // it must be '=' because of getTagName } else { ipos++; // now on start of attribute value, skip the '=' len = original.len; if (ipos >= len) { if (opts.sloppy) { return; } throw(UnexpectedEnd(getLP(original,ipos))); } c = unsafeIndex(original.str,ipos); if (c == '"') { ipos++; attrval = getAttVal(original,ipos,'"',opts); } else if (c == '\'') { ipos++; attrval = getAttVal(original,ipos,'\'',opts); } else { attrval = getAttVal(original,ipos,Char(0),opts); } } if (!opts.tmempty && exists(opts.templates,el.name)) { setAttribute(el,attrname,entityToLiteral(attrval)); return; } if (!opts.wlempty) { getallowed = lookup(opts.whitelist,el.name); case getallowed of { just(allowed) -> ; | nothing -> allowed = deref(lookup(opts.whitelist,"*")); // let it throw if this assumption's wrong } if (!elem(attrname,allowed) && !elem("*",allowed)) { return; } } setAttribute(el,attrname,entityToLiteral(attrval)); } String getAttVal(Original original, var Int ipos, Char ender, ConvertOpts opts) { len = original.len; if (ipos >= len) { if (opts.sloppy) { ipos = len-2; return ""; } throw(UnexpectedEnd(getLP(original,ipos))); } attrval = createString(40); if (ender == Char(0)) { while (ipos < len && (isAlnum(unsafeIndex(original.str,ipos)))) { attrval += String(unsafeIndex(original.str,ipos)); ipos++; } } else { sz = offsetFirstOccurs(ender,original.str,ipos); if (sz > 0) { attrval = unsafeSubstr(original.str,ipos,sz); } ipos+=sz; } if (ipos >= len) { if (opts.sloppy) { ipos = len-2; return ""; } throw(UnexpectedEnd(getLP(original,ipos))); } if (ender == Char(0)) { c = unsafeIndex(original.str,ipos); if (!isSpace(c) && c != '>') { if (!opts.sloppy) { throw(UnexpectedChar(c,getLP(original,ipos))); } } ipos--; // we reincrement later } return attrval; } Void skipTag(Original original, var Int pos, ConvertOpts opts) { // currently at start of tag to skip, need to move to just after end of this tag. sq = false; dq = false; ended = false; len = original.len; while (pos < len && !ended) { c = unsafeIndex(original.str,pos); if (sq) { if (c == '\'') { sq = false; } } else if (dq) { if (c == '"') { dq = false; } } else { if (c == '>') { ended = true; } } if (!ended) { pos++; } } if (!ended) { if (!opts.sloppy) { throw(UnexpectedEnd(getLP(original,pos))); } } // now pos points just after end tag } Void skipComment(Original original, var Int pos, ConvertOpts opts) { cdash1 = false; cdash2 = false; len = original.len; while (pos < len) { if (cdash2) { if (unsafeIndex(original.str,pos) == '>') { return; } } else if (!cdash1) { if (unsafeIndex(original.str,pos) == '-') { cdash1 = true; } } else { if (unsafeIndex(original.str,pos) == '-') { cdash2 = true; } else { cdash1 = false; } } pos++; } if (!opts.sloppy) { throw(UnexpectedEnd(getLP(original,pos))); } } String getLP(Original original, Int pos) { line = 1; col = 1; for i in [0..pos-1] { if (unsafeIndex(original.str,i) == '\n') { line++; col = 1; } else if (unsafeIndex(original.str,i) == '\r' && (i+1 == pos || unsafeIndex(original.str,i) != '\n')) { line++; col = 1; } else { col++; } } return "Line "+line+", Column "+col; } kaya-0.4.4/stdlib/COPYING0000644000175100017510000006346311170340764013103 0ustar cimcim GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 library 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 Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! kaya-0.4.4/stdlib/Pickle.k0000644000175100017510000001220211170340770013411 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005, 2006 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "String/any value conversion The Pickle module allows any value (other than closures) that can be marshalled to be converted to a String. Unlike Builtins::marshal, however, pickled data may be transferred between any two Kaya applications (although for meaningful transfer naturally both applications must be aware of all data types contained in the pickled data)." module Pickle; import Prelude; import Binary; import Reflect; import Strings; import Parse; "Closures may not be pickled. This Exception will be thrown if the value being pickled contains any closures." Exception CantPickleClosures(); "Format incompatibility This Exception will be thrown if the pickled data is in a format not supported by the unpickler." Exception PickleFormatError(); "Parse error This Exception will be thrown when unpickling if the input string is not a valid pickled string." Exception PickleParseError(); Int PICKLE_FORMAT = 1; // Increment this if any incompatible changes are made. "Convert a value to a string Convert a value to a string, for persistence. Builtins::marshal unpickle" public String pickle(a val) { str = ""; dtoString(str, [], reflect(val)); return "P(" + PICKLE_FORMAT + ")" + str; } "Convert a pickled string to a value Convert a pickled string back to a value. Builtins::unmarshal pickle" public val unpickle(String dat) { d = stoData(dat); return reify(d); } Void dtoString(var String dat, var [Data] done, Data val) { for xs@idx in done { if (identical(val,xs)) { dat += "C(" + idx +")"; return; } } case val of { DInt(i) -> pushInt(dat,i); | DString(str) -> pushString(dat, str); | DFloat(f) -> pushFloat(dat, f); | DArray(arr) -> push(done, val); pushArray(dat, done, arr); | DUnion(tag,arr) -> push(done, val); pushUnion(dat, done, tag, arr); | DClosure(_,_) -> throw(CantPickleClosures); } } Void pushInt(var String dat, Int i) { dat += "I(" + i +")"; } Void pushString(var String dat, String str) { dat += "S(" + base64Encode(str) +")"; } Void pushFloat(var String dat, Float f) { dat += "F(" + f +")"; } Void pushArray(var String dat, var [Data] done, [Data] arr) { dat += "A(" ; dat += (size(done)-1) +"," ; // Print the id, which is position in dat += "["; for el@idx in arr { dtoString(dat, done, el); if (idx!=size(arr)-1) { dat += ","; } } dat += "])"; } Void pushUnion(var String dat, var [Data] done, Int tag, [Data] arr) { dat += "U("; dat += (size(done)-1) +"," ; // Print the id, which is position in dat += tag + ","; dat += "["; for el@idx in arr { dtoString(dat, done, el); if (idx!=size(arr)-1) { dat += ","; } } dat += "])"; } Data stoData(String dat) { st = initial(dat); c = char('P',st); c = char('(',st); i = integer(st); c = char(')',st); if (i!=PICKLE_FORMAT) { // Might also do some backwards compatibility magic here later. throw(PickleFormatError); } try { return pData([], st); } catch(e) { throw(PickleParseError); } } Data pData([Data] done, var ParseState st) { d = (pInt `or` pString `or` pFloat `or` (pCycle@(done)) `or` (pArray@(done)) `or` (pUnion@(done))) (st); return d; } Data pInt(var ParseState st) { c = char('I', st); c = char('(', st); i = integer(st); c = char(')', st); return DInt(i); } Data pString(var ParseState st) { c = char('S', st); c = char('(', st); s = regex("[^)]*", st); c = char(')', st); return DString(Strings::base64Decode(s)); } Data pFloat(var ParseState st) { c = char('F', st); c = char('(', st); s = regex("[^)]*", st); c = char(')', st); return DFloat(Float(s)); } Data pArray([Data] done, var ParseState st) { c = char('A', st); c = char('(', st); id = integer(st); arr = DArray([]); done[id] = arr; c = char(',', st); c = char('[', st); arr.array = delimList(pData@(done), st, char@(',')); c = char(']', st); c = char(')', st); return arr; } Data pUnion([Data] done, var ParseState st) { c = char('U', st); c = char('(', st); id = integer(st); c = char(',', st); tag = integer(st); unr = DUnion(tag, []); done[id] = unr; c = char(',', st); c = char('[', st); unr.fields = delimList(pData@(done), st, char@(',')); c = char(']', st); c = char(')', st); return unr; } Data pCycle([Data] done, var ParseState st) { c = char('C', st); c = char('(', st); id = integer(st); c = char(')', st); return done[id]; } kaya-0.4.4/stdlib/binary_glue.h0000644000175100017510000000151111170340770014500 0ustar cimcim#ifndef _BINARY_H // -*-C++-*- #define _BINARY_H #include #include #include typedef unsigned char BYTE; extern "C" { void* newBlock(int size); void poke(void* block,int offset,int val); int peek(void* block,int offset); void pokestring(void* block, int offset, wchar_t* str); wchar_t* peekstring(void* block, kint offset, kint bsize); void* copyBlock(void* block,int size); void* copyChunk(void* block,int offset,int size); KayaArray getBlockData(void* block, int offset,int size); void setBlockData(void* block, int offset, int size, KayaArray data); int writeBlock(void* fptr,void* block, int size); void* readBlock(void* fptr, KayaValue size); wchar_t* b64binary(void* block, int len); void* b64binarydec(wchar_t* block, KayaValue len); } #endif kaya-0.4.4/stdlib/TLS.k0000644000175100017510000002314611170340770012655 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2006 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "TLS network connection encryption This module provides TLS network encryption. The functions in this module are called by the Net module and cannot usefully be used directly. TLS encryption is only useful if the identity of the server connected to can be verified. The various networking functions in the Net and HTTP modules allow a list of certificate files to be specified. On POSIX systems, Certification Authority certificates are often stored in the /etc/ssl/certs directory, and if the signer of the server certificate is not known in advance, you may wish to specify many or all of the .pem files in this directory that correspond to CAs that you trust." module TLS; import Prelude; import Binary; %include "tls_glue.h"; %include "gnutls/gnutls.h"; %imported "tls_glue"; %link "gnutls"; %link "gcrypt"; // needed for minGW, harmless on POSIX "A TLS connection session A TLS connection session" abstract data TLSsession(Ptr sess, Ptr conn, Ptr cred); "The argument is an error code from GNU TLS TLS handshake failed This Exception will be thrown if the TLS connection cannot be established." Exception TLSFailed(Int err); "TLS timeout This Exception will be thrown if the TLS connection times out." Exception TLSTimeout; "The argument is a description of the error TLS peer verification failed This Exception will be thrown if verification of the TLS connection in verifyCertificate fails." Exception VerifyFailed(String err); "TLS certificate acceptance failed This Exception will be thrown if a TLS certificate file was invalid." Exception AcceptCertificateFailed; foreign "tls_glue.o" { Void global_init_TLS() = gnutls_global_init; Ptr init_TLS(Ptr cred) = do_gnutls_init; Ptr initcred_TLS() = do_gnutls_makecred; Int assign_TLS(Ptr tls, Ptr conn) = do_gnutls_transport; Void put_TLS(Ptr tls, String toput) = do_gnutls_put; Void put_TLSbin(Ptr tls, Ptr toput, Int len) = do_gnutls_putbin; Void put_TLSbyte(Ptr tls, Int toput) = do_gnutls_putbyte; String get_TLS(Ptr tls, Ptr vm, Int len) = do_gnutls_get; Int get_TLSByte(Ptr tls, Ptr vm) = do_gnutls_getbyte; Ptr get_TLSBytes(Ptr tls, Ptr vm, a len) = do_gnutls_getbin; Void close_TLS(Ptr tls, Ptr cred) = do_gnutls_close; Void do_addcert(Ptr vm, Ptr cred, String fn) = do_addcert; Void do_verifycert(Ptr vm, Ptr sess, String host) = do_verifycert; } "A pointer to the network connection resource Initialise a TLS connection Initialise a TLS connection. Called by Net::connect when the usetls parameter is true. acceptCertificate verifyCertificate" public TLSsession makeTLS(Ptr conn) { global_init_TLS(); cred = initcred_TLS(); tls = init_TLS(cred); err = assign_TLS(tls,conn); if (err < 0) { throw(TLSFailed(err)); } return TLSsession(tls,conn,cred); } "An open TLS Session A file containing one or more PEM-encoded Certification Authority certificates. Accept certificates. Accept the certificates in the given file as signing certificates for the current connection. verifyCertificate" public Void acceptCertificate(TLSsession session, String certfile) { try { do_addcert(getVM(),session.cred,certfile); } catch(e) { throw(AcceptCertificateFailed); } } "An open TLS session The hostname of the server connected to. This may be left blank, in which case only the validity of the certificate will be checked. It is much more secure to specify a hostname, so that it can be confirmed that the host connected to is the expected one. Verify a server's certificate Verify that the server connected to has a valid server certificate. This should be called before sending or receiving confidential data on the connection. acceptCertificate" public Void verifyCertificate(TLSsession session, String hostname="") { try { do_verifycert(getVM(),session.sess,hostname); } catch(InternalError(code)) { case code of { 1 -> throw(VerifyFailed("Unexpected verification error")); | 2 -> throw(VerifyFailed("Signature was invalid")); | 3 -> throw(VerifyFailed("Certificate was revoked")); | 4 -> throw(VerifyFailed("Certificate signer untrusted")); | 5 -> throw(VerifyFailed("Hostname mismatch")); | 6 -> throw(VerifyFailed("Unexpected hostname verification error")); } } } "A TLS session The unencrypted data to send Send encrypted data Send encrypted data. This function is called by Net::send as necessary." public Void putTLS(TLSsession tls, String toput) { put_TLS(tls.sess,toput); } "A TLS session The unencrypted data to send (as a Binary::Binary set of bytes) Send encrypted binary data Send encrypted binary data. This function is called by Net::sendBytes as necessary." public Void putTLSBytes(TLSsession tls, Binary toput) { put_TLSbin(tls.sess,blockData(toput),blockSize(toput)); } "A TLS session The unencrypted byte to send Send a single encrypted byte Send a single encrypted byte. This function is called by Net::sendByte as necessary." public Void putTLSByte(TLSsession tls, Int toput) { put_TLSbyte(tls.sess,toput); } "A TLS session Whether to compensate for bugs in the HTTPS handling in Microsoft IIS servers (optional, defaults to false) Receive encrypted data Receive encrypted data. This function is called by Net::recv as necessary." public String getTLS(TLSsession tls, Bool iiscompensation=false, Int maxlen=-1, Int timeout=0, Bool(Int) checktimeout) { output = ""; if (maxlen==-1) { do { if (timeout==0 || checktimeout(timeout)) { temp = doTLSrecv(tls,iiscompensation,4096); output += temp; } else { if (output == "") { throw(TLSTimeout); } temp = ""; } } while (temp != ""); } else { if (timeout==0 || checktimeout(timeout)) { output += doTLSrecv(tls,iiscompensation,4096); } else { throw(TLSTimeout); } } return output; } String doTLSrecv(TLSsession tls, Bool iiscompensation, Int maxlen) { vm = getVM(); if (!iiscompensation) { temp = get_TLS(tls.sess,vm,maxlen); } else { try { temp = get_TLS(tls.sess,vm,maxlen); } catch(InternalError(code)) { if (code == -9) { temp = ""; } else { throw(TLSFailed(code)); // re-throw, it's not the expected error } } } return temp; } "A TLS session Whether to compensate for bugs in the HTTPS handling in Microsoft IIS servers (optional, defaults to false) Receive encrypted binary data Receive encrypted binary data. This function is called by Net::recvBytes as necessary." public Binary getTLSBytes(TLSsession tls, Bool iiscompensation=false) { vm = getVM(); maxlen = 0; if (!iiscompensation) { ptr = get_TLSBytes(tls.sess,vm,maxlen); } else { try { ptr = get_TLSBytes(tls.sess,vm,maxlen); } catch(InternalError(code)) { if (code == -9) { return createBlock(0); } else { throw(TLSFailed(code)); // re-throw, it's not the expected error } } } return createInitialisedBlock(ptr,maxlen); } "A TLS session Whether to compensate for bugs in the HTTPS handling in Microsoft IIS servers (optional, defaults to false) Receive encrypted byte Receive encrypted byte. This function is called by Net::recvByte as necessary. This function may return -1 if IIS bug compensation is on and the connection has been closed (if called via recvByte this will lead to a Net::NothingToReceive exception." public Int getTLSByte(TLSsession tls, Bool iiscompensation=false) { vm = getVM(); if (!iiscompensation) { byte = get_TLSByte(tls.sess,vm); } else { try { byte = get_TLSByte(tls.sess,vm); } catch(InternalError(code)) { if (code == -9) { return -1; } else { throw(TLSFailed(code)); // re-throw, it's not the expected error } } } return byte; } "A TLS session Close TLS connection Close a TLS connection. This function is called by Net::closeConnection as necessary." public Void closeTLS(TLSsession tls) { close_TLS(tls.sess,tls.cred); } kaya-0.4.4/stdlib/HTTP.k0000644000175100017510000002362111170340770012770 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "HTTP requests This module contains low-level functions for constructing and sending HTTP and HTTPS requests. If you are using HTTPS, then you should read the documentation for the TLS module about SSL certificates." module HTTP; import WebCommon; import Array; import Net; import Regex; import Tuples; import Strings; import Builtins; "The HTTP version The HTTP version to use in communication. HTTP 1.1 (HTTP11) has advantages but may be harder to parse the responses of." public data HTTPversion = HTTP10 | HTTP11; "Bad username for HTTP authentication Usernames for HTTP authentication may not contain a ':'" Exception BadUsername(); "Not a URL The String for conversion did not appear to be a valid URL" Exception NotAURL(); "URL information This data type stores URL information. server is the host to be contacted. Generally this should be the host name although for some sites the IP address may be used instead. port is the TCP port to use. Normally, 80 is used for HTTP and 443 for HTTPS localpart is the remainder of the URL (which must include the initial '/') secure is false for HTTP and true for HTTPS (note that it is possible for a HTTP server to run on port 443, so no assumptions will be made about this setting based on the port number) getURL parseURL postURL" public data HTTPURL(String server, Int port, String localpart, Bool secure); "The String representing the URL Convert a String to a HTTP URL Parse a String solely containing an absolute URL into a HTTPURL. The String must begin with the protocol http:// or https:// getURL postURL" public HTTPURL parseURL(String url) { re = compile("^https?://([^/]+)(/.*|$)",createArray(1)); result = match(re,url); case result of { noMatch -> throw(NotAURL); | matches([_,server,local],_,_) -> secure = quickMatch("^https://",url); if (quickMatch(":",server)) { hdata = split(":",server); server = hdata[0]; port = Int(hdata[1]); } else { if (secure) { port = 443; } else { port = 80; } } if (quickMatch("#",local)) { ldata = split("#",local); local = ldata[0]; } return HTTPURL(server,port,local,secure); | _ -> throw(NotAURL); // shouldn't happen } } "A HTTPURL. A list of key/value pairs of extra HTTP headers (optional, defaulting to the empty list) The HTTP version A list of SSL certificate files, each containing one or more PEM encoded certificates of trusted Certification Authorities, used for HTTPS connections. This list may be empty (the default), but this is much less secure. For HTTP connections, this parameter is ignored. Retrieve a URL by HTTP. Retrieve a URL by HTTP. The String returned will contain the HTTP response headers and response body exactly as sent by the server. Because Strings may not contain null bytes, this function is not suitable for retrieving binary data. basicAuthHeader parseURL postURL" public String getURL(HTTPURL url, [(String,String)] headers = createArray(1), HTTPversion version = HTTP10, [String] certfiles=[]) { server = url.server; dir = url.localpart; port = url.port; secure = url.secure; h = connect(TCP, server, port, secure, certfiles); getURL(h,url,headers,version); urldata = recv(h); try { closeConnection(h); } catch(CloseError) { // ignore this error } return urldata; } "An established network connection. A HTTPURL. A list of key/value pairs of extra HTTP headers (optional, defaulting to the empty list) The HTTP version Retrieve a URL by HTTP using an existing connection. Retrieve a URL by HTTP using an existing connection. The connection will then be ready to receive response data. basicAuthHeader parseURL getURL postURL" public Void getURL(NetHandle h, HTTPURL url, [(String,String)] headers = createArray(1), HTTPversion version = HTTP10) { server = url.server; dir = url.localpart; port = url.port; case version of { HTTP10 -> hver = "HTTP/1.0"; | HTTP11 -> hver = "HTTP/1.1"; } send(h,"GET "+dir+" "+hver+"\nConnection: close\n"); for x in headers { hd = x.fst; hv = x.snd; send(h,hd+": "+hv+"\n"); } send(h,"Host:"+server+":"+port+"\n\n"); } "The data to post, encoded as application/x-www-form-urlencoded data A HTTPURL. A list of key/value pairs of extra HTTP headers (optional, defaulting to the empty list) The HTTP version A list of SSL certificate files, each containing one or more PEM encoded certificates of trusted Certification Authorities, used for HTTPS connections. This list may be empty (the default), but this is much less secure. For HTTP connections, this parameter is ignored. Post data to a URL by HTTP. Post data to a URL by HTTP. The String returned will contain the HTTP response headers and response body exactly as sent by the server. Because Strings may not contain null bytes, this function is not suitable for requests that may return binary data. basicAuthHeader getURL parseURL" public String postURL(String post, HTTPURL url, [(String,String)] headers = createArray(1), HTTPversion version = HTTP10, [String] certfiles = []) { server = url.server; dir = url.localpart; port = url.port; secure = url.secure; h = connect(TCP, server, port, secure, certfiles); postURL(h,post,url,headers,version); urldata = recv(h); try { closeConnection(h); } catch(CloseError) { // ignore this error } return urldata; } "An established network connection. The data to post, encoded as application/x-www-form-urlencoded data A HTTPURL. A list of key/value pairs of extra HTTP headers (optional, defaulting to the empty list) The HTTP version Post data to a URL by HTTP using an existing connection. Post data to a URL by HTTP. The connection will then be ready to receive response data. basicAuthHeader getURL parseURL" public Void postURL(NetHandle h, String post, HTTPURL url, [(String,String)] headers = createArray(1), HTTPversion version = HTTP10) { server = url.server; dir = url.localpart; port = url.port; case version of { HTTP10 -> hver = "HTTP/1.0"; | HTTP11 -> hver = "HTTP/1.1"; } send(h,"POST "+dir+" "+hver+"\nConnection: close\n"); for x in headers { hd = x.fst; hv = x.snd; send(h,hd+": "+hv+"\n"); } len = length(post); send(h,"Content-length: "+len+"\n"); send(h,"Content-type: application/x-www-form-urlencoded\n"); send(h,"Host:"+server+":"+port+"\n\n"); send(h,post+"\n"); } "The username The password Create a Basic authentication header Creates an authentication header suitable for HTTP Basic Auth. The username may not contain a ':' character. Remember that this form of authentication is very insecure, and so should only be used over secure connections. getURL postURL" public (String,String) basicAuthHeader(String user, String pwd) { if (quickMatch(":",user)) { throw(BadUsername); } userpass = user+":"+pwd; upenc = base64Encode(userpass); return ("Authorization","Basic "+upenc); } "A list of pairs (in name,value order) of the cookies to send to the server with this request Generate a cookie header Generates a HTTP header for sending cookies. getURL postURL" public (String,String) cookieHeader([(String,String)] cookies) { vals = []; for cookie in cookies { push(vals,urlEncode(cookie.fst)+"="+urlEncode(cookie.snd)); } return ("Cookie",join(vals,";")); } kaya-0.4.4/stdlib/LazyArray.k0000644000175100017510000000542611170340766014137 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ module LazyArray; import Prelude; "Lazy Arrays of element type val." // init is the initial state, used for a reset. abstract data LazyArray(state init, state current, (state,val)(state) next, Bool(state) end, Void(state) cleanup, Void(state) reset); Exception EndOfArray = Exception("Reached the end of the Array",140); "Default Array cleanup function." public Void defaultCleanup(state s) { // Do nothing } "Default Array reset function." public Void defaultReset(state s) { // Do nothing } "Create a lazy Array. state is the type holding the state which is used to generate the next item. next returns the next item and modifies state. end is the termination test; use Infinite for no termination." public LazyArray lazyArray(state st, (state,val)(state) next, Bool(state) end = Infinite, Void(state) cleanup = defaultCleanup, Void(state) reset = defaultReset) { return LazyArray(st,st,next,end,cleanup,reset); } "Reset the state of a lazy Array to the initial state." public Void reset(var LazyArray list) { f = list.reset; f(list.current); list.current = list.init; } "Get the next element in a lazy list." public val getNext(var LazyArray gen) { if (end(gen)) { throw(EndOfArray); } p = gen.next(gen.current); gen.current = p.fst; return p.snd; } "Termination test for infinite lazy Arrays." public Bool Infinite(a foo) = false; "Check whether we have reached the end of a Array." public Bool end(LazyArray gen) { if (gen.end(gen.current)) { f = gen.cleanup; f(gen.current); return true; } return false; } "Turn a lazy Array into a real Array." public [val] makeArray(LazyArray gen) { list = []; reset(gen); while(!end(gen)) { push(list,getNext(gen)); } return list; } "Generate a list of numbers lazily." public LazyArray lazyRange(Int start, Int end, Int step) { return lazyArray(start-step, lambda(x) { return (x+step, x+step); }, lambda(x) { if (step>0) { return (x+step)>end; } else { return (x+step) mapLazily(b(a) f, [a] xs) { return lazyArray(0, lambda(x) { x++; return (x,f(xs[x-1])); }, lambda(x) -> { x==size(xs) }); } "Map across a lazy array lazily." public LazyArray,b> lazyMap(b(a) f, LazyArray xs) { reset(xs); return lazyArray(xs, lambda(x) -> { f(getNext(x)) }, end); } kaya-0.4.4/stdlib/Lazy.k0000644000175100017510000000665211170340770013135 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Lazy linked lists This module allows the creation and reading of lazy linked lists. Unlike Prelude::List, these lists can be of infinite size." module Lazy; import Prelude; "Lazy linked list type. As Prelude::List, but using a function for the tail. The tail of the list will be generated only when required." public data List = nil | cons(a head, Lazy::List() tail); "The initial number The step to increase by Create an infinite list of numbers. Create an infinite list of numbers, starting with x and increasing by step each time. List" public module::List countFrom(Int x, Int step = 1) { return cons(x,countFrom@(x+step,step)); } "The number of values to take The list to take values from Take the first n values from a lazy list Take the first n values from a lazy list, returning a new lazy list only containing those values. List" public module::List take(Int n, module::List xs) { if (n==0) { return module::nil; } else { case xs of { module::nil -> return module::nil; | module::cons(x,rest) -> return cons(x,module::take@(n-1,rest())); } } } "A lazy list The action to perform Iterate across a lazy list. Iterate across a lazy list, performing action on each element. Note that if the list is infinite in size, and action never throws an Exception, this function will never return. List" public Void iterate(module::List xs, Void(a) action) { repeat case xs of { module::nil -> break; | module::cons(x,rest) -> xs = rest(); action(x); } } "The block of code to execute for each list element. The Lazy list to traverse Iteration over lazy lists Used by for loops to traverse lazy List data structure. It is unlikely that you will need to call this function directly. If the List is infinite in size, this function will not exit unless the block function throws an exception or otherwise breaks out of the loop." public Void traverse(Bool(a,Int) block, module::List xs) { i = 0; repeat case xs of { module::nil -> break; | module::cons(x,rest) -> xs = rest(); if (!block(x,i)) { return; } i++; } } "A lazy list Convert a lazy list into an array. Create an array containing all the elements of a lazy list. If the list is infinite, this function will not return! List" public [a] array(module::List xs) { arr = []; iterate(xs, \(x) { push(arr,x); }); return arr; } kaya-0.4.4/stdlib/Logger.k0000644000175100017510000001025011170340770013422 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Message Logging This module allows messages to be logged to a file or an in-memory String. On platforms other than Windows, the Syslog module may also be of use." module Logger; import Prelude; import public IO; import Time; import Strings; "Logging method. LogFile is for sending logs directly to a file; it is less efficient because it opens and closes the file each time logging is done; use LogHandle for heavy logging. LogString is for logging to a string in memory. The given string is modified when it is logged to." public data Logger = LogFile(String fname) | LogHandle(File handle) | LogString(String log); // CIM: shouldn't this be 'abstract' rather than 'public'? "The filename Create a log file Create a log file and return the logging method. The file will not actually be created, if it doesn't already exist, until it is logged to. Logger makeLogHandle makeLogString" public Logger makeLogFile(String fname) { return LogFile(fname); } "The file handle Create a logging method from a file handle Creates a logging method from a file handle. If the file handle is not opened for either writing or appending then this will silently fail. Logger makeLogFile makeLogString" public Logger makeLogHandle(File handle) { return LogHandle(handle); } "Create an in-memory string logging method Create a string logging method, initialised to the empty string. Logger makeLogFile makeLogHandle" public Logger makeLogString() { return LogString(""); } "The logging method Finish logging. Finish logging. This has no effect for files or strings, but closes the file handle." public Void endLog(Logger l) { case l of { LogFile(fn) -> ; | LogString(s) -> ; | LogHandle(f) -> close(f); } } String leadzero(Int x) | x<10 = "0"+x | default = String(x); "A Logger The message to log If true (the default) a timestamp will be prepended to the message before it is logged. Add to a log. Add a message to a log. logAll" public Void log(var Logger l, String msg, Bool timestamp = true) { logmsg = msg +"\n"; if (timestamp) { t = localTime(); stamp = "[" + substr(string(t.mon),0,3) + " " + t.mday + " " + leadzero(t.hour) + ":" + leadzero(t.minute) + ":" + leadzero(t.second) + "]"; logmsg = stamp + " " + logmsg; } case l of { LogFile(fn) -> f = open(fn,[Append]); put(f,logmsg); close(f); | LogHandle(f) -> put(f,logmsg); | LogString(s) -> l.log += logmsg; } } "A list of Loggers The message to log If true (the default) a timestamp will be prepended to the message before it is logged. Add to multiple logs at once. Add a message to multiple logs at once (useful for logging to a log file and standard error simultaneously, for example). logAll" public Void logAll(var [Logger] ls, String msg, Bool timestamp = true) { for l in ls { log(l,msg, timestamp); } } kaya-0.4.4/stdlib/Parse.k0000644000175100017510000004232211170340770013262 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Parser generator This module allows simple String parsers to be written. The aim of this module is for ease of use, not efficiency. input = \"abc def ghi. \"; try { st = initial(input); words = list(word,st); sentenceend = char('.',st); end(st); } catch(e) { putStrLn(\"Parse error!\"); }" module Parse; /* A library for writing simple parsers. This library is intended to make the task of writing parsers for non-trivial grammars easier; however, it never pretends to be efficient, and I don't really know how efficient such a trial-and-error based algorithm *can* be. However, it works for basic stuff. I wouldn't try parsing Kaya with it... (One important note - left recursive rules cannot work with this kind of parser combinator library!) I expect with careful grammar design you could get something quite acceptable for most purposes. -- ECB */ import Prelude; import Strings; import Regex; import IO; // A parser for things takes a string, returns a thing, and modifies // the string (or throws a parse error). "The current state of the string being parsed. This data type represents the current state of the parsing. line and pos represent the current position of the parser with respect to the original String (both starting at 1), and input contains the unparsed section of the String. The constructors are public for ease of inspection and to allow users to write their own parser functions, but should never be altered directly outside a parse function. When writing your own parser, use Strings::behead and Strings::ltruncate to efficiently remove parsed characters from the string. initial" public data ParseState(Int line, Int pos, String input); type Parser = a(ParseState); "Parse result This data type represents the results of parsing a String - either an object of the same type as the parser, or an error containing details and a location. parse" public data ParseResult = Success(a val) | ParseError(String err, Int line, Int pos); "Generic parse error A generic parsing error occurred." Exception GenericError(); "End of input The end of the input occurred too soon." Exception EndOfInput(); "No end of input The end of the input did not occur when expected." Exception NoEndOfInput(); "Word error The String to be parsed contained no words (strings of ASCII letters)" Exception WordError(); "Identifier error The String to be parsed contained no identifiers (strings of ASCII letters, numbers and underscores, not starting with a number)" Exception IdentError(); "Integer error The String to be parsed contained no integers" Exception IntError(); "Expected a character The Char given by the parameter was expected but not found." Exception ExpectedChar(Char c); "Didn't expect that character The Char given by the parameter was unexpected." Exception UnexpectedChar(Char c); "Expected a letter A letter was expected but not found." Exception ExpectedLetter(); "Expected a digit A digit was expected but not found." Exception ExpectedDigit(); "Expected an alphanumeric character An alphanumeric character was expected but not found." Exception ExpectedAlphaNum(); globals { Regex wsRE = compile(r"^([ \t\n\r]+)"); Regex intRE = compile(r"^([0-9]+)"); Regex stringRE = compile(r"^([\S]+)"); Regex wordRE = compile(r"^([a-zA-Z]+)"); Regex identRE = compile(r"^([a-zA-Z_][a-zA-Z_0-9]*)"); } "The character to parse The current parsing state Parse a specific character. This function parses for a specified character, returning it if it is found, and throwing an Exception otherwise." public Char char(Char c, var ParseState st) { if (st.input=="") { throw(ExpectedChar(c)); } else { x = head(st.input); st.pos++; if (x==c) { if (x=='\n') { st.line++; st.pos=1; } behead(st.input); return x; } else { throw(UnexpectedChar(x)); } } } "The current parsing state Parse a letter. This function parses any letter character (as defined by Prelude::isAlpha, returning it if it is found, and throwing an Exception otherwise." public Char letter(var ParseState st) { if (st.input=="") { throw(ExpectedLetter); } else { x = head(st.input); st.pos++; if (isAlpha(x)) { behead(st.input); return x; } else { throw(UnexpectedChar(x)); } } } "The current parsing state Parse a digit. This function parses any digit character (as defined by Prelude::isDigit, returning it if it is found, and throwing an Exception otherwise." public Char digit(var ParseState st) { if (st.input=="") { throw(ExpectedDigit); } else { x = head(st.input); st.pos++; if (isDigit(x)) { behead(st.input); return x; } else { throw(UnexpectedChar(x)); } } } "The current parsing state Parse an alphanumeric character. This function parses any alphanumeric character (as defined by Prelude::isAlnum, returning it if it is found, and throwing an Exception otherwise." public Char alphaNum(var ParseState st) { if (st.input=="") { throw(ExpectedAlphaNum); } else { x = head(st.input); st.pos++; if (isAlnum(x)) { behead(st.input); return x; } else { throw(UnexpectedChar(x)); } } } "The current parsing state Parse a character. This function parses any character, returning it. An Exception is thrown if the end of the input has been reached." public Char anyChar(var ParseState st) { if (st.input=="") { throw(EndOfInput); } else { x = head(st.input); st.pos++; if (x=='\n') { st.line++; st.pos=1; } behead(st.input); return x; } } "A predicate function that takes a Character and returns true for legal characters. The current parsing state Parse a character predicate. This function parses any character, returning it if it matches the predicate function, and throwing an Exception otherwise." public Char pred(Bool(Char) p, var ParseState st) { if (st.input=="") { throw(EndOfInput); } else { x = head(st.input); st.pos++; if (x=='\n') { st.line++; st.pos=1; } if (p(x)) { behead(st.input); return x; } behead(st.input); return x; } } "The current parsing state Parse a word. This function parses any sequence of ASCII letters ([A-Za-z]+) at the start of the string, and returns the sequence. An Exception will be thrown if the sequence does not exist." public String word(var ParseState st) { case match(wordRE,st.input) of { matches(xs,before,input) -> st.input = input; st.pos+=length(xs[1]); return xs[1]; | noMatch() -> throw(WordError); } } "The current parsing state Parse an identifier. This function parses any sequence representing an identifier ([_A-Za-z][_A-Za-z0-9]+) at the start of the string, and returns the sequence. An Exception will be thrown if the sequence does not exist." public String identifier(var ParseState st) { case match(identRE,st.input) of { matches(xs,before,input) -> st.input = input; st.pos+=length(xs[1]); return xs[1]; | noMatch() -> throw(IdentError); } } "The current parsing state Parse an integer. This function parses any sequence representing an integer ([0-9]+) at the start of the string, and returns the integer. An Exception will be thrown if there is no integer." public Int integer(var ParseState st) { case match(intRE,st.input) of { matches(xs,before,input) -> st.input = input; st.pos+=length(xs[1]); return Int(xs[1]); | noMatch() -> throw(IntError); } } "The regular expression to match against. A ^ at the start of the expression is implied. The current parsing state Parse for a regular expression. This function parses for the specified regular expression at the start of the String, returning the match if one is found, and throwing an Exception otherwise." public String regex(String regexp, var ParseState st) { pattre = compile("^("+regexp+")"); case match(pattre,st.input) of { matches(xs,before,input) -> st.input = input; st.pos+=length(xs[1]); return xs[1]; | noMatch() -> throw(GenericError); } } "The predicate function, which should return true if the String matches The current parsing state Parse to match a predicate. Parse a string matching a predicate. The string will be formed from the contiguous set of non-whitespace characters at the start of the String to be parsed (which may be the empty String). An Exception will be thrown if the predicate is not matched." public String string(Bool(String) strfun, var ParseState st) { case match(stringRE,st.input) of { matches(xs,before,input) -> if (strfun(xs[1])) { st.input = input; st.pos+=length(xs[1]); return xs[1]; } else { throw(GenericError); } | noMatch() -> throw(GenericError); } } "The keyword to match (as a regular expression) The value to return if there is a match The current parsing state Parse a specific keyword Parse a specific keyword, returning the meaning of the keyword if it is found." public a keyword(String keyword, a meaning, var ParseState st) { foo = regex(keyword, st); return meaning; } a orParseAux(Parser x, Parser y, var ParseState state) { ParseState orig = copy(state); try { return x(state); } catch(e) { state = orig; try { a st = y(state); // putStrLn("success at: "+state.input); return st; } catch(e) { state = orig; throw(e); } } } "The first parser The second parser Create a new parser which is the combination of the arguments. Create a new parser combining x and y. The new parser recognises a string which is recognised by either x or y. decimal = or(Parse::digit,Parse::char@('.')); // may be more clear in many situations to write this as decimal = Parse::digit `or` Parse::char@('.'); As with Kaya's || operator, this uses short-circuit evaluation: if x parses the String successfully, y will not be used." public Parser or(Parser x, Parser y) { return orParseAux@(x,y); } "The current parsing state Swallow a block of whitespace. Remove any leading whitespace ([ \\t\\r\\n]) from the start of the String to be parsed." public Void whitespace(var ParseState st) { case match(wsRE,st.input) of { matches(xs,before,input) -> st.input = input; st.pos+=length(xs[1]); return; | noMatch() -> return; } } "A list of parser functions The current parsing state Parse a string using a set of parsers. Parse a string using a set of parsers. The first one which parses is used. // Equivalent to parser = alts[0] `or` alts[1] `or` alts[2] `or` ... `or` alts[size(alts)-1]; parsed = parser(st); or" public a alternatives([Parser] alts, var ParseState st) { orig = copy(st); for parser in alts { try { return parser(st); } catch(e) { // Do nothing, just try the next one. } } st = orig; throw(GenericError); } "The parser to use The current parsing state The minimum number of items (default 0) Parse a list of items out of a String Parse a string into a list of n or more items. Items are separated by whitespace and an Exception will be thrown if fewer than n are found. delimList list1" public [a] list(Parser parser, var ParseState st, Int n = 0) { all = []; orig = copy(st); while(true) { try { x = parser(st); push(all,x); whitespace(st); } catch(e) { if (size(all)>=n) { return all; } else { st = orig; throw(GenericError); } } } return all; } "The parser to use for items The current parsing state The parser to use for delimiters The minimum number of items (default 0) Parse a list of items out of a String Parse a string into a list of n or more items. Items are separated by a string defined by the delim parser and an Exception will be thrown if fewer than n are found. list list1" public [a] delimList(Parser parser, var ParseState st, Parser delim, Int n = 0) { all = []; orig = copy(st); while(true) { try { x = parser(st); push(all,x); xdelim = delim(st); } catch(e) { if (size(all)>=n) { return all; } else { st = orig; throw(GenericError); } } } return all; } "The parser to use The current parsing state Parse a string into a list of at least 1 item. Parse a string into a list of at least 1 item, multiple items separated by whitespace. Equivalent to list(parser,st,1). delimList list" public [a] list1(Parser parser, var ParseState st) { all = []; while(true) { try { x = parser(st); push(all,x); whitespace(st); } catch(e) { if (all!=[]) { return all; } else { throw(GenericError); } } } return all; } "The parser to use The current parsing state Parse a string optionally. Parse a string optionally, returning nothing if the parser failed." public Maybe optional(Parser parse, var ParseState st) { try { x = parse(st); return just(x); } catch(e) { return nothing; } } "The current parsing state Parse the end of input. Parse the end of the input. If anything remains in the String other than whitespace, this function will throw an Exception. It is used to verify that the whole String has been parsed successfully." public Void end(var ParseState st) { whitespace(st); if (st.input!="") { throw(NoEndOfInput); } } "The parser function The input String Run a parser on an input. Run a parser on an input, and return the parse result." public ParseResult parse(Parser parser, String input) { try { st = initial(input); res = parser(st); end(st); return Success(res); } catch(e) { return ParseError(exceptionMessage(e),st.line,st.pos); } } "A string Construct an initial parse state Constructs an initial parse state from the String." public ParseState initial(String x) = ParseState(1,1,x); kaya-0.4.4/stdlib/IO.k0000644000175100017510000007450511170340770012527 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "File input/output and filesystem access This module contains functions for file input and output, and filesystem access. File names may be given as absolute file paths, or relative to the current directory (which may be changed with System::chdir). Additional functions for handling binary files may be found in the Binary module." module IO; import Prelude; %include "stdlib.h"; %include "sys/stat.h"; %include "sys/types.h"; // Chris Morris, 18/6/05 - moved data definitions above foreign{} and // added AccessMode type. "File handling error This Exception is thrown when file handling functions fail." Exception FileError; "Directory handling error This Exception is thrown when directory handling functions fail." Exception DirError; "Invalid file mode error This Exception is thrown when a file mode is invalid." Exception InvalidMode; "Closed file An attempt was made to read from or write to a closed file handle." Exception ClosedFile; "Read only file An attempt was made to write to a read-only file." Exception ReadOnlyFile; "Write only file An attempt was made to read from a write-only file." Exception WriteOnlyFile; "Modes for file opening. Selects a mode for open to use. The Binary mode is only needed for reading and writing binary files on Windows systems." public data FileMode = Read | Write | Append | Binary; // internal data type data AccessMode = FExists | FExecute | FWrite | FRead; "A file handle A file handle. This may not be directly queried." abstract data File(Ptr ptr, Bool open, Bool read, Bool write, Bool append, Bool binary); "A directory handle A directory handle. As with the File type for file handles, this type may not be directly queried in any way." abstract data Dir(Ptr ptr); "A directory entry An entry within a directory. Currently only the name of the entry is recorded." public data DirEntry(String name); "File information Information about a file. The mode field describes the file mode, nlinks is the number of links to the file, and atime, mtime and ctime are the access, modify (last change to contents) and change (last change to contents or mode) times measured in seconds since midnight Jan 1 1970. The Time::gmtime function may be useful to deal with these fields. Mode stat" public data Stat(Mode mode, Int nlinks, Int atime, Int mtime, Int ctime); "File modes This describes the mode of the file. The first three fields describe the access Permission for the file owner, the file group, and others, while the remaining fields state whether a particular file property is true. This data type mostly applies to the filesystems normally found on POSIX systems. On Windows, the file permission and type model is somewhat different, so this data type may not hold especially useful information there. Permission Stat" public data Mode([Permission] ownerperms, [Permission] groupperms, [Permission] othersperms, Bool socket, Bool symlink, Bool regular, Bool block, Bool dir, Bool chardev, Bool fifo, Bool setUID, Bool setGID, Bool sticky); "File permissions Selects whether a file is readable, writable or executable. Mode Permissions" public data Permission = ReadP | WriteP | ExecuteP; "Directory creation permissions Describes the permissions with which a directory will be created. Permission mkdir" public data Permissions([Permission] owner, [Permission] group, [Permission] others, Bool setuid, Bool setgid, Bool sticky); "Directory tree A directory tree DirInfo dirinfo" public data DirTree([DirInfo] files); "Directory entry This data type describes a directory entry, which may either be a sub-directory (which is then described recursively) or a file (or a file-equivalent such as a block device). getDirInfo" public data DirInfo = Directory(String dname, [DirInfo] children) | Filename(String fname); foreign "stdfuns.o" { Ptr do_tmpFile() = do_tmpFile; Ptr fopen(String name, String mode) = do_fopen; Ptr freopen(String name, String mode, Ptr f) = do_freopen; Bool validFile(Ptr h) = validFile; String getLine(Ptr vm,Ptr h) = getLine; String do_getString(Ptr vm, Ptr h) = getString; Char do_fgetc(Ptr h) = do_fgetc; Void doputChar(Int c,Ptr h) = do_fputc; Void doPutStr(Ptr h, String s, Int len) = putString; Void putLine(Ptr h, String s, Int len) = putLine; "A file handle The byte position to seek to (if the file contains multi-byte UTF-8 characters, and is being read as a string, be aware of the problems that positioning the pointer part way through a multi-byte character may cause) Seek to a position in a file Seek to the specified byte of the file. Files opened with the Append file mode will always have writes occur at the end of the file, though this function will affect reading. fpos" Void do_fseek(Ptr h, Int p) = do_fseek; Int do_fpos(Ptr h) = do_ftell; Bool feof(Ptr h) = do_feof; Int do_fflush(Ptr h) = do_fflush; Void fclose(Ptr h) = do_fclose; Int do_unlink(String fn) = do_unlink; Int do_mkdir(String fn, Int umask) = do_mkdir; Int do_access(String fn, AccessMode mode) = do_access; "The current file name (and path) The new file name (and path) Rename a file Rename a file, moving it to a new directory if necessary. If a file with the name new already exists, it will be replaced." public Void rename(String old, String new) = do_rename; Ptr do_opendir(String name) = do_opendir; Int do_closedir(Ptr dirh) = do_closedir; Ptr do_readdir(Ptr dirh) = do_readdir; String dir_getname(Ptr vm,Ptr ent) = dir_getname; Stat do_stat(Ptr vm, String name) = do_stat; Ptr getstdin() = getstdin; Ptr getstdout() = getstdout; Ptr getstderr() = getstderr; } /* utility functions to validate file handles */ Bool isOpen(File file) = file.open; Bool isReadable(File file) = file.read; Bool isWritable(File file) = file.write || file.append; "A file handle Check that a file handle is readable Checks that a file handle is readable, and throws either a ClosedFile or WriteOnlyFile Exception if not. openCheck writeCheck" public Void readCheck(File file) { openCheck(file); if (!isReadable(file)) { throw(WriteOnlyFile); } } "A file handle Check that a file handle is open Checks that a file handle is still open, and throws a ClosedFile Exception if not. readCheck writeCheck" public Void openCheck(File file) { if (!isOpen(file)) { throw(ClosedFile); } } "A file handle Check that a file handle is writable Checks that a file handle is writable, and throws either a ClosedFile or ReadOnlyFile Exception if not. openCheck readCheck" public Void writeCheck(File file) { openCheck(file); if (!isWritable(file)) { throw(ReadOnlyFile); } } "A file handle Current position of file pointer Get the current byte position of the file pointer. fseek" public Int fpos(File h) { openCheck(h); return do_fpos(h.ptr); } "A file handle The byte position to seek to (if the file contains multi-byte UTF-8 characters, and is being read as a string, be aware of the problems that positioning the pointer part way through a multi-byte character may cause) Seek to a position in a file Seek to the specified byte of the file. Files opened with the Append file mode will always have writes occur at the end of the file, though this function will affect reading. fpos" public Void fseek(File h, Int p) { openCheck(h); do_fseek(h.ptr,p); } "A readable file handle Read a string from a binary file Reads a string (up to NULL termination) from a binary file. If the end of the file is reached, the string read up to that point will be returned. The string is assumed to be UTF-8 encoded. get putStr" public String getString(File h) { readCheck(h); return do_getString(getVM,h.ptr); } "A readable file handle Read one byte from a file. Read one byte from a file. While the return type is Char, the meaning of values greater than Char(127) will depend on the encoding of the input file, rather than being the UCS character of that number. get putChar" public Char getChar(File h) { readCheck(h); return do_fgetc(h.ptr); } "Standard input stream Returns a file handle pointing to the standard input stream. If none of the optional Curses modules for terminal control are available, basic user input can be obtained using IO::get. input = get(stdin); stdout stderr IO::get" public File stdin() = File(getstdin,true,true,false,false,false); "Standard output stream Returns a file handle pointing to the standard output stream. This may be more appropriate in some circumstances than using putStr for output. input = get(stdin); stdin stderr putStr" public File stdout() = File(getstdout,true,false,false,true,false); "Standard error stream Returns a file handle pointing to the standard error stream. Errors can be written to standard error using IO::put. put(stderr(),\"ERROR: Antler remover jammed!\"); stdin stdout IO::put" public File stderr() = File(getstderr,true,false,false,true,false); "The pointer The file mode, if known. This should be set if possible. Create a File from a pointer This coerces a pointer to a C file handle into a File. This function is intended solely for writing interfaces to C code that returns file handles, and should not be used for other purposes. ptr" public File file(Ptr ptr, [FileMode] mode = [Read,Write,Append]) { return File(ptr,true,elem(Read,mode),elem(Write,mode),elem(Append,mode),elem(Binary,mode)); } "The file handle Create a Ptr from a file handle This retrieves a C pointer from a file handle, which may sometimes be needed for writing foreign function interfaces. This function should not be used for any other purpose. file" public Ptr ptr(File file) { openCheck(file); return file.ptr; // if anyone can think of a way to allow people to write foreign // interfaces that involve file handles without exposing this // function, that would be great! - CIM } "A writable or appendable file handle The string to write Write a string to a binary file Write a string (including NULL termination) to a binary file. The string will be written to the file in UTF-8 encoding. getString put" public Void putStr(File h, String s) { writeCheck(h); doPutStr(h.ptr,s,length(s)); } String getFileMode([FileMode] mode) { for m in mode { case m of { Read -> read = true; | Write -> write = true; | Append -> append = true; | Binary -> binary = true; } } if (read && write) { fmode = "r+"; } else if (read && append) { fmode = "a+"; } else if (read) { fmode = "r"; } else if (write) { fmode = "w"; } else if (append) { fmode = "a"; } else { throw(InvalidMode); } if (binary) { fmode+="b"; } return fmode; } "The name of the file A list of file modes Open a file. Open the named file with the specified file modes. Not all combinations of modes are legal, and an InvalidMode Exception will be thrown if an illegal mode is selected. A FileError Exception will be thrown if opening fails for any other reason. Legal mode combinations are: [Read,Write]: read and write to any point in the file [Read,Append]: read from any point in the file, write to the end only (creating the file if it does not exist) [Read]: read from any point in the file [Write]: write to any point in the file, creating the file if it does not exist, and truncating it otherwise. [Append]: write to the end of the file, creating the file if it doesn't exist. Binary can be added to any of the combinations above to open the file in binary mode on Windows (it has no effect on POSIX platforms). close reopen" public File open(String fname, [FileMode] mode) { fmode = getFileMode(mode); h = fopen(fname,fmode); // Check h is valid. if (validFile(h)) { return File(h,true,elem(Read,mode),elem(Write,mode),elem(Append,mode),elem(Binary,mode)); } else { throw(FileError); } } "The file name A list of file modes The existing file handle Re-open a file. Re-open a file. This functions exactly like open except that rather than opening a new file, it changes an existing file handle. This is mainly useful for re-opening the standard input, output and error streams on a different file. in = reopen(\"inputscript\",[Read],stdin); close open stdin stdout stderr" public File reopen(String fname,[FileMode] mode, File f) { openCheck(f); fmode = getFileMode(mode); h = freopen(fname,fmode,f.ptr); // Check h is valid. if (validFile(h)) { read = elem(Read,mode); write = elem(Write,mode); append = elem(Append,mode); binary = elem(Binary,mode); // f.mode = mode; f.ptr = h; f.read = read; f.write = write; f.append = append; f.binary = binary; return File(h,true,read,write,append,binary); } else { throw(FileError); } } "A file handle opened for reading Read a line from a file Read a line from a file, including the terminating newline ('\\n')." public String get(File handle) { readCheck(handle); return getLine(getVM,handle.ptr); } "A file handle opened for writing or appending The string to write Write a string to a file. Write a string to a file. Unlike putStr this will not write a NULL terminator to the file, and so should be used when dealing with non-binary files. put(stdout,str) is equivalent to Builtins::putStr(str)" public Void put(File handle, String val) { writeCheck(handle); putLine(handle.ptr,val,length(val)); } "A writable file handle The byte to write Write a character to a file. Write a binary character to a file. Char(200) will write a byte with a value of 200, not the multibyte representation of Char(200) in UTF-8. Writing a character with a value greater than 256 is undefined. getChar put putInt putStr" public Void putChar(File handle, Char c) { writeCheck(handle); doputChar(Int(c),handle.ptr); } "A writable file handle The integer to write Write an integer to a file (as binary) Write an integer to a file as a set of four binary bytes. The most significant byte is written first. getInt put putChar putStr" public Void putInt(File handle, Int i) { writeCheck(handle); putChar(handle, Char(i>>24)); putChar(handle, Char((i>>16) & 255)); putChar(handle, Char((i>>8) & 255)); putChar(handle, Char(i & 255)); } "A readable file handle Get a binary integer from a file. Retrieves the next four bytes from the file, and converts them to an integer, most significant byte first. get getChar getString putInt" public Int getInt(File handle) { readCheck(handle); c1 = Int(getChar(handle)); c2 = Int(getChar(handle)); c3 = Int(getChar(handle)); c4 = Int(getChar(handle)); return (c1<<24)+(c2<<16)+(c3<<8)+c4; } "The file handle Check for end of file. This returns true if the end of the file has been reached, and false otherwise. It is always false after fseek. lines = []; while (!eof(h)) { push(lines,get(h)); } open" public Bool eof(File handle) { openCheck(handle); return feof(handle.ptr); } "The file handle Flush all data to a file. Flush all buffered data to the file on the handle. An Exception will be thrown if the file is not writable, or if an error occurred when writing the data." public Void flush(File handle) { writeCheck(handle); // FIXME: Capture errno and strerror(errno). if (do_fflush(handle.ptr) != 0) { throw(FileError); } } "Close a file handle Close a file. Close a file handle after you no longer need it. It is strongly recommended that you do not close the three standard file handles - use reopen to open them onto /dev/null instead." public Void close(File handle) { openCheck(handle); fclose(handle.ptr); handle.open = false; } "A file name Read a text file. Reads the entire contents of fname into a String. This function assumes that the file is a text file, rather than a binary file. Binary::readBlock writeFile" public String readFile(String fname) { contents = ""; f = open(fname,[Read]); while(!eof(f)) { contents = contents+get(f); } close(f); return contents; } "A file name The content to write Write a text file. Writes content into fname, replacing the file if it exists, and creating it otherwise. Binary::writeBlock readFile" public Void writeFile(String fname, String content) { f = open(fname,[Write]); put(f,content); close(f); } "Create and open a temporary file. Create and open a temporary file (in binary read+write mode), and return a file handle. You can then apply any of the normal IO operations to this file." public File tmpFile() { return File(do_tmpFile,true,true,true,false,true); } "The file name Unlinks a file. Unlinks a file, throwing a FileError Exception on failure. If the last link to a file is removed, this file is deleted." public Void unlink(String fname) { r = do_unlink(fname); if (r != 0) { throw(FileError); } } "The directory name The permissions to set. This is optional, and if omitted will default to setting all access permissions allowed by the current process umask, but will not set the setUID, setGID, or sticky bit. On Windows, this parameter is ignored completely as the file permissions system is very different. Makes a directory. Makes a directory, throwing a FileError Exception if creation fails. The permissions set will be affected by the current process umask (see the mkdir(2) man page) on Posix systems. Permissions" public Void mkdir(String dname, Permissions mode = Permissions([ReadP,WriteP,ExecuteP],[ReadP,WriteP,ExecuteP],[ReadP,WriteP,ExecuteP],false,false,false)) { modeint = (64*permBits(mode.owner))+(8*permBits(mode.group))+permBits(mode.others); if (mode.setuid) { modeint += 2048; } if (mode.setgid) { modeint += 1024; } if (mode.sticky) { modeint += 512; } r = do_mkdir(dname,modeint); if (r != 0) { throw(FileError); } } Int permBits([Permission] mode) { p = 0; if (elem(ReadP,mode)) { p += 4; } if (elem(WriteP,mode)) { p += 2; } if (elem(ExecuteP,mode)) { p += 1; } return p; } "The file name Checks a file exists Returns true if the filename exists, false otherwise. If the file exists, but the current process is unable to determine this (for example, because the file is in an unreadable directory), false will be returned. fileExecutable fileReadable fileWritable stat" public Bool fileExists(String fname) { if (do_access(fname,FExists) == 0) { return true; } else { return false; } } "The file name Checks a file is readable Returns true if the file is readable by the current proces, false otherwise. fileExecutable fileExists fileWritable stat" public Bool fileReadable(String fname) { if (do_access(fname,FRead) == 0) { return true; } else { return false; } } "The file name Checks a file is writable Returns true if the file is writable by the current proces, false otherwise. fileExecutable fileExists fileReadable stat" public Bool fileWritable(String fname) { if (do_access(fname,FWrite) == 0) { return true; } else { return false; } } "The file name Checks a file is executable Returns true if the file is executable by the current proces, false otherwise. fileExists fileReadable fileWritable stat" public Bool fileExecutable(String fname) { if (do_access(fname,FExecute) == 0) { return true; } else { return false; } } "The directory name Open a directory Open a directory for reading, throwing a DirError Exception on error. closeDir dirinfo listDir readDir" public Dir openDir(String fname) { ptr = do_opendir(fname); if (null(ptr)) { throw(DirError); } return Dir(ptr); } "The directory handle Close a directory handle Close a directory handle, throwing a DirError Exception on error. dirinfo listDir openDir readDir" public Void closeDir(Dir h) { if (do_closedir(h.ptr)!=0) { throw(DirError); } } "The directory handle Get the next directory entry. Get the next directory entry from an open directory handle. A DirError Exception will be thrown on error, or on reaching the end of the directory. closeDir dirinfo listDir openDir" public DirEntry readDir(Dir h) { Ptr ent = do_readdir(h.ptr); if (null(ent)) { throw(DirError); } name = dir_getname(getVM,ent); return DirEntry(name); } "The name of the directory Get a list of files in a directory Returns a list of all file and sub-directory names in the directory, including \".\" and \"..\"." public [String] listDir(String dirname) { dir = openDir(dirname); fs = []; try { while(true) { ent = readDir(dir); // Throws at the end. Yeuch. push(fs,ent.name); } } catch(e) { if (e==DirError) { closeDir(dir); return fs; } else { throw(e); } } return fs; } "The file name Get file information. Get detailed information about the access permissions and type of a file. Stat" public Stat stat(String fname) { // putStrLn("statting "+fname); // FIXME: do_stat might throw, we need to get the errno and convert it to // some useful message with the C strerror function. return do_stat(getVM(),fname); } "The initial directory Return a directory tree Return the directory tree rooted at fname." public DirTree dirinfo(String fname) { return DirTree(getDirInfo(fname)); } "The initial directory Return a list of directory trees Return the directory trees and filenames in fname. dirinfo listDir" public [DirInfo] getDirInfo(String fname) { fs = listDir(fname); inf = []; for f in fs { realf = fname+"/"+f; stats = stat(realf); if (stats.mode.dir) { if (f!="." && f!="..") { children = getDirInfo(realf); push(inf, Directory(f, children)); } } else { push(inf, Filename(f)); } } return inf; } kaya-0.4.4/stdlib/Doxyfile0000644000175100017510000013101411170340764013542 0ustar cimcim# Doxyfile 1.3.6-20040222 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, # Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en # (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, # Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. It is allowed to use relative paths in the argument list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = YES # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = . # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = *.k # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. INPUT_FILTER = ../tools/docmangler.pl # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO kaya-0.4.4/stdlib/Net.k.in0000644000175100017510000005647411170340770013360 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Networking functions This module contains functions for setting up TCP network connections and sending and receiving data, and listening on TCP ports. If libgnutls was available when Kaya was configured, then TLS may be used to set up encrypted connections." module Net; import Builtins; import System; import Prelude; // TODO: TLS currently available for client only, server support needed import TLS; import Binary; %include "network_glue.h"; %include "unistd.h"; %imported "network_glue"; @NETLIB@%link "wsock32"; foreign "network_glue.o" { Void do_net_init(Ptr vm) = net_init; String net_recv(Ptr vm, Ptr handle, a len) = net_recv; Ptr net_recvchars(Ptr vm, Ptr handle, a len) = net_recvchars; Int net_recvbyte(Ptr vm, Ptr handle) = net_recvbyte; Ptr net_connect(Ptr vm, Int proto, String server, Int port) = net_connect; Bool net_connwaiting(Ptr vm, Int socket, Int timeout) = net_connwaiting; Int net_listen(Ptr vm, Int proto, Int port, Int backlog) = net_listen; Ptr net_accept(Ptr vm, Int socket) = net_accept; Void net_shutdown(Ptr h) = net_shutdown; Void net_close(Ptr vm, Ptr h) = net_close; Void close(Int x) = close; Void net_send(Ptr vm, Ptr h, String d) = net_send; Void net_sendchars(Ptr vm, Ptr h, Ptr d, Int len) = net_sendchars; Void net_sendbyte(Ptr vm, Ptr h, Int byte) = net_sendbyte; Bool net_pending(Ptr vm, Ptr h, Int timeout) = net_pending; String net_getaddr(Ptr h) = net_getaddr; } "Can't bind to port This Exception is thrown when it is not possible to listen on a TCP port." Exception CantBind(); "Can't listen on port This Exception is thrown when it is not possible to listed on a TCP port, but binding to the port was successful." Exception CantListen(); "Failed to accept connection This Exception is thrown when a listening socket fails to accept a connection." Exception AcceptFailed(); "Sending data failed This Exception is thrown when sending data to a network connection fails." Exception SendFailed(); "No data to receive This Exception is thrown when no data is receivable on a network connection." Exception NothingToReceive(); "Testing connection failed This Exception is thrown when an attempt to check if there is data waiting on a connection fails." Exception SelectError(); "Initialisation failed This Exception is thrown if initialisation of the networking libraries failed." Exception CantInit(); "Protocol not supported This Exception is thrown if the protocol chosen was not supported. Currently IPv6 is not supported." Exception ProtocolNotSupported(); "Host not known The system was unable to look up the host in DNS." Exception CantGetHost(); "Connection failed The connection to the remote host failed." Exception ConnectError(); "Close failed An error occurred when trying to close a connection." Exception CloseError(); "Negative Length A negative length was specified when receiving data." Exception NegativeLength(); Void netError(Int code) { case code of { 1 -> throw(CantBind); | 2 -> throw(CantListen); | 3 -> throw(AcceptFailed); | 4 -> throw(SendFailed); | 5 -> throw(NothingToReceive); | 6 -> throw(SelectError); | 7 -> throw(CantInit); | 8 -> throw(ProtocolNotSupported); | 9 -> throw(CantGetHost); | 10 -> throw(ConnectError); | 11 -> throw(CloseError); | default -> throw(InternalError(code)); } } "A network connection A network connection in use." abstract data NetHandle = NetH(Ptr handle, Maybe tls, String hostname); Int MAXCONN = 128; "The protocol to use The network protocol to use for connections. IPv6 is not currently supported." public data Protocol = TCP | TCP_IPv4 | TCP_IPv6; globals { Bool initRun = netInit(); } "Initialises networking libraries. Initialises the networking libraries. This is called automatically when this module is imported, but is harmless to call again. On operating systems other than Windows, this function does nothing." public Bool netInit() { if (initRun) { return true; } try { do_net_init(getVM()); } catch(InternalError(e)) { netError(e); } return true; } "The network protocol to use The hostname or IP address of the server to connect to (e.g. service.example.com, localhost or 192.168.20.25) The network port to connect to If this is true, and the TLS library is available, then the connection will be encrypted. This parameter may be omitted and defaults to false. An optional list of certificate files for TLS encrypted connections. Each file should contain one or more PEM-encoded certificates for a trusted certification authority. If this list is empty (the default), no certificate verification will be performed on encrypted connections, which is insecure. Connect to a server Connect to a server (optionally using TLS). Returns a connection handle. NetHandle Protocol closeConnection recv shutdown send" public NetHandle connect(Protocol proto, String server, Int port, Bool usetls=false, [String] certfiles=[]) { try{ h = net_connect(getVM(),protocolToInt(proto),server,port); if (usetls) { tls = makeTLS(h); if (size(certfiles) > 0) { for cf in certfiles { acceptCertificate(tls,cf); } verifyCertificate(tls,server); } return NetH(h,just(tls),server); } else { return NetH(h,nothing,server); } } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "The network protocol to use The port to listen on The maximum number of unaccepted connections. Listen on a port. Listen on a port, returning a socket id. Protocol accept closeSocket" public Int listen(Protocol proto, Int port, Int backlog) { try { return net_listen(getVM(),protocolToInt(proto),port,backlog); } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "Return the Int representation of protocol needed by the C glue library." Int protocolToInt(Protocol proto) = case proto of { TCP -> 1; | TCP_IPv4 -> 1; | TCP_IPv6 -> 2; }; "A socket number returned from listen. The number of seconds to wait for a connection attempt before timing out (defaults to zero) Check for connections waiting on a socket. Returns whether any connections are waiting on a socket opened with listen. listen accept" public Bool connWaiting(Int socket, Int timeout = 0) { try { return net_connwaiting(getVM(),socket,timeout*1000000); } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "A socket number returned from listen. Accept a connection on a socket. Accept a connection on a socket. Returns a connection handle. If no connections are currently waiting then an Exception will be thrown - you can call connWaiting first to determine if connections are available, although this may not be completely reliable in threaded applications. NetHandle closeConnection closeSocket connWaiting listen recv shutdown send" public NetHandle accept(Int socket) { try { h = net_accept(getVM(),socket); return NetH(h,nothing,""); } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "The handle to shut down Shutdown a network handle. Shutdown a network handle so that no further data can be sent or received. NetHandle closeConnection" public Void shutdown(NetHandle h) { try { net_shutdown(h.handle); } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "The handle to close Close a connection handle. Close a connection handle. You should always close connection handles once you have finished with them. NetHandle accept connect" public Void closeConnection(NetHandle h) { try { case h.tls of { nothing -> ; | just(tls) -> closeTLS(tls); } net_close(getVM,h.handle); } catch(InternalError(e)) { netError(e); } } "The socket returned by listen. Close a socket. Stop listening on a socket and accept no further connections. listen" public Void closeSocket(Int x) { close(x); } "The connection The data to send Send data across a connection. Send data across a connection. This function is not suitable for data containing null bytes, for which sendByte or sendBytes should be used. NetHandle accept closeConnection connect sendByte sendBytes recv" public Void send(NetHandle h, String d) { try { case h.tls of { nothing -> net_send(getVM(),h.handle,d); | just(tls) -> putTLS(tls,d); } } catch(InternalError(e)) { netError(e); } } "The connection The data to send Send binary data across a connection. Send binary data across a connection. This function does not yet support TLS connections. Binary::Binary NetHandle accept closeConnection connect send sendByte recv" public Void sendBytes(NetHandle h, Binary d) { try { case h.tls of { nothing -> net_sendchars(getVM(),h.handle,blockData(d),blockSize(d)); | just(tls) -> putTLSBytes(tls,d); } } catch(InternalError(e)) { netError(e); } } "The connection The byte to send Send a single byte across a connection. Send a single byte across a connection. The Int passed should be between 0 and 255, or the results are unpredictable. This function does not yet support TLS connections. NetHandle accept closeConnection connect send sendBytes recv" public Void sendByte(NetHandle h, Int byte) { try { case h.tls of { nothing -> net_sendbyte(getVM(),h.handle,byte); | just(tls) -> putTLSByte(tls,byte); } } catch(InternalError(e)) { netError(e); } } "The connection The maximum number of bytes to read (or unlimited, if negative). For TLS connections, this is always unlimited. Note that if the data to be received contains multi-byte characters, care must be taken to avoid ending receiving part-way through a multi-byte character. The number of seconds to wait without input before timing out. The default is zero. For TLS connections, this parameter is ignored. Recieve data from a connection. Reads up to maxlen bytes from the connection, and times out after timeout seconds. NetHandle accept connect microPending microRecv pending recvByte recvBytes send" public String recv(NetHandle h, Int maxlen = -1, Int timeout = 0) { try { case h.tls of { nothing -> return dorecv(h, maxlen, timeout*1000000); | just(tls) -> try { return getTLS(tls,true,maxlen,timeout*1000000,microPending@(h)); // for now, set iiscompensation here } catch(TLSTimeout) { throw(NothingToReceive); } } } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "The connection The maximum number of bytes to read. This argument must be a positive integer The number of microseconds to wait without input before timing out. The default is zero. Recieve binary data from a connection. Reads up to maxlen bytes from the connection as binary data, and times out after timeout microseconds. This function does not yet support TLS connections. Binary::Binary NetHandle accept connect microPending microRecv pending recv recvByte send" public Binary recvBytes(NetHandle h, Int maxlen = 1024, Int timeout = 0) { if (maxlen < 1) { throw(NegativeLength); } try { if (timeout <= 0 || microPending(h,timeout)) { case h.tls of { nothing -> ptr = net_recvchars(getVM,h.handle,maxlen); return createInitialisedBlock(ptr,maxlen); | just(tls) -> return getTLSBytes(tls,true); // for now, set iiscompensation here } } else { throw(NothingToReceive); } } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "The connection The number of microseconds to wait without input before timing out. The default is zero. Recieve data from a connection. Reads a single byte from the connection, and times out after timeout microseconds. This function does not yet support TLS connections. NetHandle accept connect microPending microRecv pending recv recvBytes send" public Int recvByte(NetHandle h, Int timeout = 0) { try { if (timeout <= 0 || microPending(h,timeout)) { case h.tls of { nothing -> return net_recvbyte(getVM,h.handle); | just(tls) -> r = getTLSByte(tls,true); // for now, set iiscompensation here if (r == -1) { throw(NothingToReceive); } else { return r; } } } else { throw(NothingToReceive); } } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "The connection The maximum number of bytes to read (or unlimited, if negative). For TLS connections, this is always unlimited. The number of microseconds to wait without input before timing out. The default is zero. For TLS connections, this parameter is ignored. Recieve data from a connection. Reads up to maxlen bytes from the connection, and times out after timeout microseconds. Apart from the units the timeout is measured in, this is otherwise identical to recv NetHandle accept connect microPending pending recv send" public String microRecv(NetHandle h, Int maxlen = -1, Int microtimeout = 0) { try { case h.tls of { nothing -> return dorecv(h, maxlen, microtimeout); | just(tls) -> return getTLS(tls,true,maxlen,microtimeout,microPending@(h)); } } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } // timeout in microseconds String dorecv(NetHandle h, Int maxlen = -1, Int timeout = 0) { try { len = maxlen; rpt = false; if (maxlen==-1) { len = 65535; // Repeatedly read in 64k chunks. rpt = true; } str=""; do { if (timeout<=0) { str += net_recv(getVM(),h.handle,len); // putStrLn(str); } else { if (microPending(h,timeout)) { str += net_recv(getVM(),h.handle,len); } else { throw(NothingToReceive()); } } if (len==0) { rpt=false; } } while (rpt); return str; } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "The connection The number of seconds to wait for data before timing out (defaults to five) Return whether data is waiting at a socket. Return whether data is waiting at a socket, returning true if so, and returning false if there is still no data after the timeout period. NetHandle microPending microRecv recv" public Bool pending(NetHandle h, Int timeout = 5) { try { return net_pending(getVM(),h.handle,timeout*1000000); } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "The connection The number of microseconds to wait for data before timing out (defaults to 100) Return whether data is waiting at a socket. Return whether data is waiting at a socket, returning true if so, and returning false if there is still no data after the timeout period. NetHandle microRecv pending recv" public Bool microPending(NetHandle h, Int timeout = 100) { try { return net_pending(getVM(),h.handle,timeout); } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "The connection handle Get the host name from a connection handle. Get the host name from a connection handle. This is most useful with connections created with accept. NetHandle accept connect" public String getHost(NetHandle h) { try { return net_getaddr(h.handle); } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); } "The connection handle An optional list of certificate files for TLS encrypted connections. Each file should contain one or more PEM-encoded certificates for a trusted certification authority. If this list is empty (the default), no certificate verification will be performed on encrypted connections, which is insecure. Convert an existing connection to use TLS. Begins TLS encryption on an existing connection equivilant to having set usetls to true when creating it. Useful for secure SMTP connections. This function will fail silently if TLS encryption is already in use on the connection. Note that this function is only designed for client connections started with connect rather than server connections from accept. NetHandle connect" public Void startTLS(NetHandle h, [String] certfiles=[]) { case h.tls of { nothing -> try{ tls = makeTLS(h.handle); if (size(certfiles) > 0) { for cf in certfiles { acceptCertificate(tls,cf); } verifyCertificate(tls,h.hostname); } h.tls = just(tls); return; } catch(InternalError(e)) { netError(e); } throw(InternalError(e)); | just(t) -> return; // don't start twice. } } kaya-0.4.4/stdlib/Gcrypt.k0000644000175100017510000004377511170340770013475 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "libgcrypt interface This module implements an interface to the libgcrypt cryptographic library. It is used by the Crypto library to provide Kaya's application secret key encryption and decryption. As well as cryptographic algorithms, this library also provides several hash algorithms." module Gcrypt; import Prelude; import Binary; %include "gcrypt.h"; %include "gcrypt_glue.h"; %link "gcrypt"; %imported "gcrypt_glue"; "Available symmetric ciphers The available symmetric ciphers. Crypto uses AES256. openCipher" public data Cipher = Idea | TripleDES | Cast5 | Blowfish | AES128 | AES192 | AES256 | Twofish | Twofish128 | Arcfour | DES; "Cipher modes Cipher modes, Crypto uses CBC. openCipher" public data CipherMode = ECB | CFB | CBC | Stream | OFB | CTR; "Hash algorithms Hash algorithms openHash" public data Hash = SHA1 | RMD160 | MD5 | MD4 | Tiger | SHA256 | CRC32; "A cipher handle A cipher handle. Encryption and decryption operations use these. openCipher" abstract data CipherHandle(Ptr ptr); "A hash handle A hash handle for hashing operations. openHash" abstract data HashHandle(Ptr ptr); type Key = [Int]; type IVec = [Int]; foreign "libgcrypt" { Int algo(Cipher c) = cipheralgo; Int mode(CipherMode c) = ciphermode; Int hashalgo(Hash c) = hashalgo; Ptr do_cipherOpen(Cipher algo, CipherMode mode, Int flags) = cipherOpen; Void do_cipherClose(Ptr h) = cipherClose; Void do_setkey(Ptr h, Key key) = do_setkey; Void do_setivec(Ptr h, IVec key) = do_setivec; Ptr do_encrypt(Ptr h, Ptr dat, Int size, intval outsize) = do_encrypt; Ptr do_decrypt(Ptr h, Ptr dat, Int size, intval outsize) = do_decrypt; Int do_cipherKeySize(Int c) = cipherKeySize; Int do_cipherBlockLength(Int c) = cipherBlockLength; Ptr do_hashOpen(Hash algo, Int flags) = hashOpen; Void do_hashClose(Ptr h) = hashClose; Void do_hashReset(Ptr h) = hashReset; Void do_hashWrite(Ptr h, Ptr dat, Int size) = hashWrite; Void do_hashFinal(Ptr h) = hashFinal; Ptr do_hashGet(Ptr h, intval size) = hashGet; [Int] do_appKey() = appKey; [Int] do_appIVec() = appIVec; } "Cipher opening flags Flags for opening ciphers. CipherCTS and CipherMAC may not be used simultaneously. CipherSecure: Allocate cipher operations in secure memory if possible. CipherSync: Enable the CFB sync mode. CipherCTS: Enable cipher text stealing (CTS) for the CBC mode CipherMAC: Compute CBC-MAC checksums. openCipher" public data CipherFlags = CipherSecure | CipherSync | CipherCTS | CipherMAC; "Hash opening flags Flags for opening hashes. HashSecure: Allocate hash operations in secure memory if possible. openHash" //public data HashFlags = HashSecure | HashHMAC; // we don't currently have a way to make use of HMAC public data HashFlags = HashSecure; "The cipher algorithm to use The cipher mode to use The flags to use Open a cipher handle Open a cipher handle to be used in cipher operations. CipherFlags CipherHandle closeCipher decrypt decryptString encrypt encryptString setCipherIVec setCipherKey" public CipherHandle openCipher(Cipher algo, CipherMode mode, [CipherFlags] flags = createArray(1)) { cflags = 0; if (elem(CipherSecure,flags)) { cflags += 1; } if (elem(CipherSync,flags)) { cflags += 2; } if (elem(CipherCTS,flags)) { cflags += 4; } if (elem(CipherMAC,flags)) { cflags += 8; } return CipherHandle(do_cipherOpen(algo,mode,cflags)); } "The cipher handle Close a cipher handle Close a cipher handle. You should always close cipher handles once you have finished using them. CipherHandle decrypt decryptString encrypt encryptString openCipher setCipherIVec setCipherKey" public Void closeCipher(CipherHandle h) { do_cipherClose(h.ptr); } "The cipher handle The secret key Set the cipher secret key Sets the cipher secret key. The length of the key depends on the cipher algorithm, and can be found with cipherKeySize. CipherHandle cipherKeySize closeCipher decrypt decryptString encrypt encryptString openCipher setCipherIVec" public Void setCipherKey(CipherHandle h, Key key) { // TODO: Check that key length is right. If not, pad/chop do_setkey(h.ptr,key); } "The cipher handle The initialisation vector Set the cipher initialisation vector Sets the cipher initialisation vector. The length of the vector depends on the cipher algorithm, and can be found with cipherBlockLength. Unlike the key, the initialisation vector does not need to be secret. CipherHandle cipherBlockLength closeCipher decrypt decryptString encrypt encryptString openCipher setCipherKey" public Void setCipherIVec(CipherHandle h, IVec key) { // TODO: Check that ivec length is right. If not, pad/chop do_setivec(h.ptr,key); } "Get the application secret key Get the application secret key. This is mainly provided for the benefit of Crypto::encode, but may be useful for other functions. appIVec" public [Int] appKey() { return do_appKey(); } "Get the application initialisation vector Get the application initialisation vector. This is mainly provided for the benefit of Crypto::encode, but may be useful for other functions. appKey" public [Int] appIVec() { return do_appIVec(); } "A cipher algorithm Get the required key size. Get the required key size for a given cipher. Cipher cipherBlockLength" public Int cipherKeySize(Cipher c) { return do_cipherKeySize(algo(c)); } "A cipher algorithm Get the required block length. Get the required block length for a given cipher. Cipher cipherBlockLength" public Int cipherBlockLength(Cipher c) { return do_cipherBlockLength(algo(c)); } "A cipher handle A block of Binary data Encrypt binary data Encrypts binary data with the given cipher handle, returning a binary block containing the encrypted data. CipherHandle closeCipher decrypt decryptString encryptString openCipher setCipherIVec setCipherKey" public Binary encrypt(CipherHandle h, Binary dat) { // putStrLn("Encrypting block of length "+blockSize(dat)); outlen = 0; ptr = do_encrypt(h.ptr, blockData(dat), blockSize(dat), outlen); // putStrLn("Got block of length "+outlen); return createInitialisedBlock(ptr, outlen); } "A cipher handle A block of encrypted Binary data Decrypt binary data Decrypts binary data with the given cipher handle, returning a binary block containing the decrypted data. CipherHandle closeCipher decryptString encrypt encryptString openCipher setCipherIVec setCipherKey" public Binary decrypt(CipherHandle h, Binary dat) { outlen = 0; ptr = do_decrypt(h.ptr, blockData(dat), blockSize(dat), outlen); return createInitialisedBlock(ptr, outlen); } "A cipher handle A string Encrypt a string Encrypts a string with the given cipher handle, returning a base64-encoded string containing the encrypted data. CipherHandle closeCipher decrypt decryptString encrypt openCipher setCipherIVec setCipherKey" public String encryptString(CipherHandle h, String x) { block = createBlock(byteLength(x)+1); // putStrLn("Encrypting "+x); pokeString(block,0,x); cryptblock = encrypt(h,block); // putStrLn(String(peek(cryptblock,0))); // putStrLn(String(peek(cryptblock,1))); // putStrLn(String(peek(cryptblock,2))); return Binary::base64Encode(cryptblock); } "A cipher handle A base64-encoded encrypted string Decrypt a string Decrypts a string with the given cipher handle, returning the unencrypted string. CipherHandle closeCipher decrypt encrypt encryptString openCipher setCipherIVec setCipherKey" public String decryptString(CipherHandle h, String x) { block = Binary::base64Decode(x); decryptblock = decrypt(h,block); return peekString(decryptblock,0); } // rewrite to use sensible flags parameter! "The hash algorithm The flags to use Open a hash handle Open a hash handle with the specified algorithm HashFlags HashHandle closeHash finalHash getHash hashBinary hashString resetHash" public HashHandle openHash(Hash algo, [HashFlags] flags = createArray(1)) { hflags = 0; if (elem(HashSecure,flags)) { hflags += 1; } // if (elem(HashHMAC,flags)) { hflags += 2; } return HashHandle(do_hashOpen(algo,hflags)); } "The hash handle Close a hash handle Close a hash handle when you have finished using it. HashHandle finalHash getHash hashBinary hashString openHash resetHash" public Void closeHash(HashHandle h) { do_hashClose(h.ptr); } "The hash handle Reset a hash handle Reset a hash handle. If you are using the same hash algorithm on several pieces of data, it is more efficient to reset it after each use, rather than closing and re-opening. HashHandle closeHash finalHash getHash hashBinary hashString openHash" public Void resetHash(HashHandle h) { do_hashReset(h.ptr); } "A hash handle A block of binary data Hash binary data Hash a block of binary data. HashHandle closeHash finalHash getHash hashString openHash resetHash" public Void hashBinary(HashHandle h, Binary dat) { do_hashWrite(h.ptr, blockData(dat), blockSize(dat)); } "A hash handle A String Hash string data Hash a String. HashHandle closeHash finalHash getHash hashBinary openHash resetHash" public Void hashString(HashHandle h, String str) { block = createBlock(byteLength(str)+1); pokeString(block,0,str); do_hashWrite(h.ptr, blockData(block), blockSize(block)); } "A hash handle Finalise the hash handle Finalise the hash handle. This is not usually necessary as calling getHash implicitly finalises the handle. Once a handle is finalised, no further hashString or hashBinary operations have any effect until resetHash is used. HashHandle closeHash getHash hashBinary hashString openHash resetHash" public Void finalHash(HashHandle h) { do_hashFinal(h.ptr); } "A hash handle Get the hash result Get the hash result, as a block of binary data. HashHandle closeHash getHash hashBinary hashString openHash resetHash" public Binary getHash(HashHandle h) { size = 0; dat = do_hashGet(h.ptr, size); return createInitialisedBlock(dat,size); } kaya-0.4.4/stdlib/HTMLDocument.k0000644000175100017510000042335011170340770014457 0ustar cimcim/** -*-C-*-ish HTMLDocument.k Copyright (C) 2005 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "HTML Document creation and editing This module contains functions for creating and editing a HTML document using a tree-based approach. This ensures that documents are of a high code quality, makes maintenance easier, and provides protection against some common web security problems." module HTMLDocument; import Prelude; import System; import Crypto; import Strings; import Regex; import public ElementTreeData; // ideally import abstract, if such a thing existed import ElementTree; import HTMLnesting; import XMLentities; import WebCommon; import Compress; import Set; /** Part 1: Data type definitions **/ globals { Int uniqueid = 0; Regex::Regex classregex = compile("^[A-Za-z][A-Za-z0-9-]*$"); Regex::Regex idregex = compile("^[A-Za-z][A-Za-z0-9_:.-]*$"); } /* Development notes: * We want a special data type for URIs so we can handle encoding properly * String will do for now, though. */ "A HTML document This data type represents a HTML document. The doctype is set when an instance of this type is created. The document can be converted to a string, with each field forming a different part <DOCTYPE ...> <!-- from doctype field --> <html> <head> <!-- links, stylesheets, scripts and metadata from the head field > </head> <body> <!-- a HTML or XHTML element tree manipulated with the functions in this module --> </body> </html> The httpheaders field contains details of HTTP headers to be set if the document is served over HTTP (such as in a CGI program or Webapp) Doctype ElementTreeData::ElementTree MetaData addHTTPHeader new setDocumentTitle CGI Webapp" public data HTMLDocument(MetaData head, ElementTree body, Doctype doctype, [Pair] httpheaders); // we don't support meta HTTP-equiv here because that's better handled via // real HTTP headers, which we may add support for later in HTMLDocument // abstract because it shouldn't be poked directly "Meta data about a HTML document This data type is used to create the <head> section of a HTML document. The following things can be added using this data type. Meta data <meta name='...' value='...'> External CSS Stylesheets Document-level links (<link>) External client-side Javascript ClientScript HeadLink HTMLDocument StyleSheet addDocumentLink addDocumentMetaData addDocumentScripting addDocumentStylesheet setDocumentTitle" abstract data MetaData(String doctitle, Dict metakeys, [StyleSheet] styles, // order is significant [HeadLink] links, [ClientScript] scripts); // yes, I know, it's missing \n"; } output += " "; return output; } "The HTML document The mode for handling multibyte UTF-8 characters. LiteralUTF8 will give a smaller String, readable in Unicode-aware applications. NumericReference will give a larger String, especially if multibyte characters are very common in the text, but will work better if the String will later be edited in non-Unicode applications. This argument is optional, and defaults to the recommended LiteralUTF8, but you may wish to use NumericReference if standard output is connected to a non-Unicode terminal, for example. Print a HTML document on standard output Print the HTML document on standard output. This is considerably more efficient than putStr(string(doc)); ElementTreeData::UnicodeFormat HTMLDocument string writeTo" public Void write(HTMLDocument doc, UnicodeFormat uform = LiteralUTF8) { putStr(headString(doc,uform)); case doc.doctype of { HTML4Strict -> lazyPrint(doc.body,ImpliedSingleton,1,uform,tagFormats,getAlwaysEmpty); | XHTML1Strict -> lazyPrint(doc.body,Singleton,1,uform,tagFormats,getAlwaysEmpty); } putStr("\n\n"); } "The HTML document A function that outputs the strings given to it (using Prelude::putStr@() is equivalent to write) The mode for handling multibyte UTF-8 characters. LiteralUTF8 will give a smaller String, readable in Unicode-aware applications. NumericReference will give a larger String, especially if multibyte characters are very common in the text, but will work better if the String will later be edited in non-Unicode applications. This argument is optional, and defaults to the recommended LiteralUTF8, but you may wish to use NumericReference if the output is not Unicode-aware, for example. Print a HTML document with a specified output function Print a HTML document with a specified output function. This is considerably more efficient than output(string(doc)); ElementTreeData::UnicodeFormat HTMLDocument string write" public Void writeTo(HTMLDocument doc, Void(String) output, UnicodeFormat uform = LiteralUTF8) { output(headString(doc,uform)); case doc.doctype of { HTML4Strict -> lazyOutput(doc.body,ImpliedSingleton,1,uform,tagFormats,getAlwaysEmpty,output); | XHTML1Strict -> lazyOutput(doc.body,Singleton,1,uform,tagFormats,getAlwaysEmpty,output); } output("\n\n"); } private String mediaToString([MediaType] media) { nub(media); if (elem(MTall,media) || size(media) == 0) { return "all"; // don't need to look in this case } else { mstr = createArray(size(media)); for mt in media { case mt of { MTscreen -> mtstr = "screen"; | MTtty -> mtstr = "tty"; | MTtv -> mtstr = "tv"; | MTprojection -> mtstr = "projection"; | MThandheld -> mtstr = "handheld"; | MTprint -> mtstr = "print"; | MTbraille -> mtstr = "braille"; | MTaural -> mtstr = "aural"; } push(mstr,mtstr); } return Strings::join(mstr,','); } } /** Part 3: Header editing **/ "The HTML document The name of the header The contents of the header Adds a HTTP header to the document Adds a HTTP header to the document. If the document is then printed using Webapp::displayPage, these headers will be sent to the client. The effects of multiple HTTP headers with the same name vary. Some headers may be rewritten by the web server if they appear multiple times. You can change the HTTP status code using the special Status header. The default is 200, of course - due to a bug in older versions of Apache, explicitly setting a 200 status is not recommended. Headers with names beginning \"X-\" are non-standard and could mean anything. addHTTPHeader(doc,\"Last-Modified\",rfc2822Time(lmstamp)); addHTTPHeader(doc,\"Status\",\"404 File not found\"); addHTTPHeader(doc,\"X-Generator\",\"Kaya\"); The characters allowed in HTTP headers are relatively restricted, especially in the name field, the most obvious restriction being that they may not contain new lines. Webapp::displayPage will throw an Exception if illegal characters are found - be sure to check this if you write your own header output function. RFC 2616 describes the HTTP protocol including HTTP headers in detail You may set multiple headers with the same name, but this may not be sensible for some headers (for example, multiple Status headers make no sense, whereas multiple Set-Cookie headers are commonly used). HTMLDocument addHTTPHeader Webapp::displayPage" public Void addHTTPHeader(HTMLDocument doc, String name, String value) { // TODO: checks for headers such as Content-type that can only appear once Pair val = (name,value); push(doc.httpheaders,val); } "The HTML document A pair of Strings describing the header Adds a HTTP header to the document Adds a HTTP header to the document. If the document is then printed using Webapp::displayPage, these headers will be sent to the client. The effects of multiple HTTP headers with the same name vary. Some headers may be rewritten by the web server if they appear multiple times. You can change the HTTP status code using the special Status header. The default is 200, of course - due to a bug in older versions of Apache, explicitly setting a 200 status is not recommended. Headers with names beginning \"X-\" are non-standard and could mean anything. addHTTPHeader(doc,setCookie(\"session\",getSessionId())); The characters allowed in HTTP headers are relatively restricted, especially in the name field, the most obvious restriction being that they may not contain new lines. Webapp::displayPage will throw an Exception if illegal characters are found - be sure to check this if you write your own header output function. RFC 2616 describes the HTTP protocol including HTTP headers in detail You may set multiple headers with the same name, but this may not be sensible for some headers (for example, multiple Status headers make no sense, whereas multiple Set-Cookie headers are commonly used). HTMLDocument addHTTPHeader Webapp::displayPage WebCommon::setCookie" public Void addHTTPHeader(HTMLDocument doc, (String,String) header) { // TODO: checks for headers such as Content-type that can only appear once push(doc.httpheaders,copy(header)); } "The HTML document The key name for the meta-data value The meta-data value Adds a meta-data key/value pair to the document Adds a meta-data key/value pair to the document. This can be used to add additional information to the document useful to automated tools. The use of this data in the ranking algorithms of internet search engines has been widely debated but appears to be marginal at best. It may, however, be useful for local search engines or cataloguing software. addDocumentMetaData(doc,\"Author\",\"John Smith\"); addDocumentMetaData(doc,\"Description\",\"An example document\"); \"HTTP-equiv\" meta-data is not supported by this module - just add a real HTTP header using addHTTPHeader instead. MetaData addHTTPHeader" public Void addDocumentMetaData(HTMLDocument doc, String key, String value) { add(doc.head.metakeys,key,value); } "The HTML document A list of media types that this stylesheet applies to The location of the stylesheet. Adds a linked external stylesheet to the document Adds a linked external stylesheet to the document. See the MediaType documentation for an explanation of the various media types. Currently only CSS stylesheets are supported by this function. addDocumentStylesheet(doc,[MTall], \"/styles/base.css\"); addDocumentStylesheet(doc,[MTprint], \"/styles/print.css\"); addDocumentStylesheet(doc,[MTscreen,MTprojection,MThandheld], \"/styles/visual.css\"); If the media array is empty, [MTall] will be used. MediaType" public Void addDocumentStylesheet(HTMLDocument doc, [MediaType] media, String uri) { push(doc.head.styles,StyleSheet(media,uri)); } "The HTML document The relationship this link describes The resource linked to. The content-type of the linked document (optional) Adds a document-level link Adds a document-level link to another resource. addDocumentLink(doc,Rel(\"next\"), webappName()+\"slide=\"+(slideno+1)); addDocumentLink(doc,Rev(\"made\"),\"author@example.invalid\"); The Relationship documentation explains the semantics of forward and reverse document links." public Void addDocumentLink(HTMLDocument doc, Relationship relate, String uri, String title=createString(0), String ctype=createString(0)) { push(doc.head.links,HeadLink(relate,uri,title,ctype)); } "The HTML document The location of the Javascript file. Adds an external script to the document Adds an external script to the document. This script will define functions which may then be called using the onX event handler attributes for various elements in the document." public Void addDocumentScripting(HTMLDocument doc, String scripturi) { push(doc.head.scripts,ClientScript(scripturi)); } "The HTML document The document title, which may not be blank (an Exception is thrown if it is) Changes the document title Changes the document title, which is commonly used by browsers when bookmarking the page and in their user interface, and by search engines for indexing purposes. Ideally, all pages should have a unique title. addDocumentMetaData" public Void setDocumentTitle(HTMLDocument doc, String newtitle) { if (newtitle == "") { throw(RequiresElement("The document title may not be blank.")); } doc.head.doctitle = newtitle; } /** Part 4: Body editing - common attributes **/ "The HTML element The CSS class to set Set the CSS class Set the CSS class(es) of a HTML element. Multiple classes can be specified by separating them with a space. If a class is given which does not match the allowed characters for class names, a RequiresAttribute Exception will be thrown. setClass(paragraph,\"important\"); setClass(link,\"external recommended\"); setAttribute setID setTitle" public Void setClass(ElementTree element, String classname) { // doesn't allow for unicode or escaped character classnames // but they're very rarely used. We can add support later. classnames = words(classname); for cn in classnames { if (!quickMatch(classregex,classname)) { throw(RequiresAttribute("Class format incorrect")); } } module::setAttribute(element,"class",classname); } "The HTML element The ID to set Sets the ID of a HTML element Sets the ID of a HTML element. The ID is a unique identifier within the document for the element. Setting IDs is useful for styling, scripting, and creating anchors within a document. h = addHeading(body,2,\"Compiler options\"); setID(h,\"opts\"); // appending #opts to the URL will now jump straight to this heading setAttribute setClass setTitle" public Void setID(ElementTree element, String idname) { if (!quickMatch(idregex,idname)) { throw(RequiresAttribute("ID format incorrect")); } // Ideally we'd check for duplicate ids at this stage, but since we // don't have a way to find the root element, we can't. module::setAttribute(element,"id",idname); } private String nextUniqueID() { if (uniqueid < 1) { uniqueid = 1; } else { uniqueid++; } return "Kay"+String(uniqueid); } "The HTML element The title to set Sets the title of a HTML element Sets the title of a HTML element. The title can be used to provide optional additional information about an element. Not all browsers will display title information, and the method of display will vary - common graphical browsers tend to display it as a tooltip when someone hovers over the element. A common use is providing optional additional information about a link. url = Hyperlink(\"http://kayalang.org/library/latest/Prelude/putStr\"); link = appendInlineElement(paragraph,url,\"putStr\"); setTitle(link,\"API documentation for Prelude::putStr\"); setAttribute setClass setID" public Void setTitle(ElementTree element, String title) { module::setAttribute(element,"title",title); } "The HTML element The attribute to set The value to use Sets an attribute on a HTML element Sets an attribute on a HTML element. Required attributes will be set when you add the element by the addition function, but you may wish to add optional attributes here, or change the value of an existing attribute based on later calculations. setAttribute(quotation,\"lang\",\"fr\"); The setClass and setID functions should always be used in preference to this function for those purposes, as they do some input validation (and are shorter to type!) getAttribute setClass setID setTitle" public Void setAttribute(ElementTree element, String name, String value) { ElementTree::setAttribute(element,name,value); } "The HTML element The attribute name Gets an attribute value from a HTML element Gets an attribute value from a HTML element, or nothing if the attribute is not set. case getAttribute(el,\"class\") of { nothing -> setClass(el,\"recentchange\"); | just(c) -> setClass(el,c+\" recentchange\"); } setAttribute" public Maybe getAttribute(ElementTree element, String name) { return ElementTree::getAttribute(element,name); } // TODO: language, directionality, possibly scripting events /** Part 5: Body editing - adding blocks **/ // TODO: need a decent table editing interface here, as well // as other block-level elements.. // this should really check for proper header nesting somewhere "The parent element The level of heading (1-6) Optionally, any initial text the element should contain Add a heading Add a heading to the end of the specified element. Heading levels go from 1 to 6, and form a document outline - there should generally be one level 1 heading in the document, with level 2 headings below that, level 3 headings below the level 2 headings, and so on. In practice, headings less important than level 4 are very rarely used." public ElementTree addHeading(ElementTree parent, Int headinglevel, String initialtext=createString(0)) { if (headinglevel < 1 || headinglevel > 6) { throw(RequiresElement(headinglevel+" is not a valid heading depth")); } return addGenericBlock(parent,"h"+String(headinglevel),initialtext); } "The parent element Optionally, initial text content for the element. Add a paragraph Add a paragraph to the end of the specified element. Unlike most block-level elements, paragraphs may only contain inline elements." public ElementTree addParagraph(ElementTree parent, String initialtext=createString(0)) { return addGenericBlock(parent,"p",initialtext); } "The parent element Optionally, initial text content for the element. Add an address Add an address to the end of the specified element. The address element is intended to contain contact details for the document author (or document section author)" public ElementTree addAddress(ElementTree parent, String initialtext=createString(0)) { return addGenericBlock(parent,"address",initialtext); } // No initial text option because blockquotes can't directly contain text. "The parent element Add a quotation block Add a quotation block to the end of the specified element. Quotation blocks may not contain text directly - you must add further block-level elements to the quotation block." public ElementTree addBlockQuote(ElementTree parent) { if (!canContainBlock(parent.name)) { throw(InvalidNesting("Can't add block quotation inside "+parent.name)); } // need to check that parent can contain paragraphs (e.g. not ol) bquote = mkElement("blockquote"); pushElement(parent,bquote); return bquote; } "The parent element Optionally, initial text content for the element. Optionally, the CSS class to apply to the division Add a generic block Add a generic block to the end of the specified element. Unlike paragraphs, lists, etc. this block has no defined semantics, and so is useful for grouping and styling purposes." public ElementTree addDivision(ElementTree parent, String initialtext=createString(0), String cssclass=createString(0)) { div = addGenericBlock(parent,"div",initialtext); if (cssclass != "") { setClass(div,cssclass); } return div; } "The parent element Optionally, initial text content for the element. Add a preformatted block Add a preformatted block to the end of the specified element. This is useful for displaying program code and other text where indentation may be significant or useful to preserve. pre = addPreformatted(parent,\"\"); code = appendInlineElement(pre,\"j = 0; for i in [1..10] { j += i; }\");" public ElementTree addPreformatted(ElementTree parent, String initialtext=createString(0)) { return addGenericBlock(parent,"pre",initialtext); } private Bool canContainBlock(String ename) = containsBlock(ename); private Bool canContainException(String parent, String child) = nestingExceptions((parent,child)); // might make this public later, if people insist... private ElementTree addGenericBlock(ElementTree parent, String element, String initialtext=createString(0)) { // tweak to allow ins and del to be added in an inline context too if (canContainBlock(parent.name) || ((element == "del" || element == "ins") && canContainInline(parent.name,false))) { // need to check that parent can contain paragraphs (e.g. not ol) newelement = mkElement(element); pushElement(parent,newelement); if (initialtext != "") { // because it's only called with initial text if this is possible doAddString(newelement,initialtext); } return newelement; } else { throw(InvalidNesting("Can't add "+element+" inside "+parent.name)); } } "The parent element Is the list Unordered or Ordered The initial number of list elements to have Optionally, the initial text content for some or all of the list elements. If this list is shorter than initialsize, then only the first list items will be populated. If it is longer, then the extra list items will be ignored. Add a list Add a list to the parent element. Lists may only directly contain list items. steps = [\"Catch flamingo\",\"Place flamingo in pan\",\"Boil for 3 hours\"]; list = addList(parent,Ordered,3,steps); ListType addListItem getListItem pushListItem" public ElementTree addList(ElementTree parent, ListType ltype, Int initialsize, [String] initialcontents=createArray(1)) { if (!canContainBlock(parent.name)) { throw(InvalidNesting("Can't add lists inside "+parent.name)); } case ltype of { Ordered -> etype = "ol"; | Unordered -> etype = "ul"; } newlist = mkElement(etype); for i in [1..initialsize] { listitem = mkElement("li"); pushElement(newlist,listitem); if (initialcontents[i-1] != "") { doAddString(listitem,initialcontents[i-1]); } } pushElement(parent,newlist); return newlist; } "The list to search The index to retrieve (starting at zero) Retrieve a list item Gets the list item within a list at the specified index. If the index given is not in the list, an Array::OutOfBounds Exception will be thrown. If the list given is not actually a list, a RequiresElement Exception is thrown. list = addList(parent,Unordered,10); for i in [0..9] { item = getListItem(list,i); addString(item,\"This is item \"+(i+1)); } addList addListItem pushListItem" public ElementTree getListItem(ElementTree list, Int index) { if (list.name == "ul" || list.name == "ol") { if (index < 0 || size(list.elements) <= index) { throw(OutOfBounds); } // ol and ul should only contain li // this will throw a mildly unhelpful exception if CData has crept in return list.elements[index].nested; } else { throw(RequiresElement("Parent element is not a list")); } } "The list to add to The index to insert at (starting at zero) Optionally, the initial contents of the list item Add a list item Add a list item to a list at the specified index. If the list given is not actually a list, an InvalidNesting Exception is thrown. if (extradetails) { addListItem(instructions,5,\"Check that all leads are attached.\"); addListItem(instructions,12,\"Check that the batteries are charged.\"); } addList getListItem pushListItem" public ElementTree addListItem(ElementTree list, Int index, String initialcontents=createString(0)) { if (list.name == "ul" || list.name == "ol") { listitem = mkElement("li"); if (initialcontents != "") { doAddString(listitem,initialcontents); } addElementAt(list,listitem,index); return listitem; } else { throw(InvalidNesting("Can't add a list item here - improper nesting")); } } "The list to append to Optionally, the initial contents of the list item Append a list item Append a list item to a list. If the list given is not actually a list, an InvalidNesting Exception is thrown. This is sometimes a more convenient way to build up lists than using an initial content array on addList, especially if the final size of the list is variable. list = addList(parent,Ordered,0); while (text = getNextText(source)) { pushListItem(list,text); } addList addListItem getListItem" public ElementTree pushListItem(ElementTree list, String initialcontents=createString(0)) { if (list.name == "ul" || list.name == "ol") { listitem = mkElement("li"); if (initialcontents != "") { doAddString(listitem,initialcontents); } pushElement(list,listitem); return listitem; } else { throw(InvalidNesting("Can't add a list item here - improper nesting")); } } /** Part 6: Body editing - adding inline content **/ private Bool canContainInline(String elemname, Bool implyCdata=true) { return (containsCData(elemname) || !(isBlock(elemname) || alwaysEmpty(elemname) || pretendEmpty(elemname)) || (implyCdata && containsCDataOnly(elemname))); } // everything should call this rather than using pushData directly "The element to add text to The text to add Append text to an element Append text directly to an element. p = addParagraph(p,\"This is a \"); addString(p,\"paragraph.\"); // <p>This is a paragraph.</p> appendInlineElement is used to add text within a containing element." public Void addString(ElementTree block, String text) { if (canContainInline(block.name,true)) { doAddString(block,text); } else { throw(InvalidNesting(block.name+" can't (directly?) contain text")); } } // except that where we know strings are allowed we can use this private Void doAddString(ElementTree block, String text) { text = entityToLiteral(text); pushData(block,text); } private ElementTree makeInlineElement(InlineElement inline) { case inline of { // phrase elements Emphasis -> elem = mkElement("em"); | StrongEmphasis -> elem = mkElement("strong"); | Abbreviation(title) -> elem = mkElement("abbr"); if (title != "") { setTitle(elem,title); } | Citation -> elem = mkElement("cite"); | Definition -> elem = mkElement("dfn"); | ComputerCode -> elem = mkElement("code"); | SampleInput -> elem = mkElement("kbd"); | SampleOutput -> elem = mkElement("samp"); | Variable -> elem = mkElement("var"); | BiggerText -> elem = mkElement("big"); | SmallerText -> elem = mkElement("small"); | Bold -> elem = mkElement("b"); | Italic -> elem = mkElement("i"); | Subscript -> elem = mkElement("sub"); | Superscript -> elem = mkElement("sup"); // special elements | Hyperlink(uri) -> elem = mkElement("a"); module::setAttribute(elem,"href",uri); | InlineQuote(citeuri) -> elem = mkElement("q"); if (citeuri != "") { module::setAttribute(elem,"cite",citeuri); } | Span(class) -> elem = mkElement("span"); if (class != "") { setClass(elem,class); } | FormLabel -> elem = mkElement("label"); } return elem; } "The element to add to The inline element to add The initial text content of the inline element Append an inline element Adds a new inline element containing some text to the end of a block. p = addParagraph(parent,\"This is \"); em = appendInlineElement(p,Emphasis,\"important\"); // <p>This is <em>important</em></p> InlineElement addInlineElementAt addString" public ElementTree appendInlineElement(ElementTree block, InlineElement inline, String initialtext) { if (canContainInline(block.name,false)) { inl = makeInlineElement(inline); doAddString(inl,initialtext); pushElement(block,inl); return inl; } else { throw(InvalidNesting("Can't add an inline element here")); } } "The element to add to The inline element to add The start position for the inline element The end position for the inline element Wrap existing text in an inline element Encloses existing text within an element within an inline element. The characters from startpos to endpos inclusive (with a starting index of zero) will be included in the inline element. p = addParagraph(parent,\"abcdefghijklmnopqrstuvwxyz\"); void(addInlineElementAt(p,Emphasis,5,10)); void(addInlineElementAt(p,StrongEmphasis,6,8)); // <p>abcde<em>f<strong>ghi</strong>jk</em>lmnopqrstuvwxyz</p> An InvalidNesting Exception will be thrown if the element being added to cannot contain inline elements, or an impossible nesting situation would be created. An InvalidRange Exception will be thrown if the startpos or endpos are outside the text contents of the block. p = addParagraph(parent,\"abcdefghijklmnopqrstuvwxyz\"); void(addInlineElementAt(p,Emphasis,5,10)); void(addInlineElementAt(p,StrongEmphasis,6,15)); // exception thrown The firstOccurs function is useful for highlighting a particular word within a string. haystack = getAllText(element); npos = firstOccurs(needle,haystack); if (npos < length(haystack)) { try { added = addInlineElementAt(element,Emphasis,npos,npos+length(needle)+1); } catch(InvalidNesting(details)) { // probably overlapping elements } } InlineElement appendInlineElement Strings::firstOccurs" public ElementTree addInlineElementAt(ElementTree block, InlineElement inline, Int startpos, Int endpos) { // iterates through existing structure, places start tag at startpos // (in char) and end tag at endpos (unless this would lead to // improper nesting) if (!canContainInline(block.name,false)) { throw(InvalidNesting("Can't add an inline element here")); } if (startpos < 0) { throw(InvalidRange("Can't start before beginning of element")); } if (startpos > endpos) { throw(InvalidRange("Can't start after end")); } currentpos = 0; // if we've always been using pushData and unshiftData then there // should never be two adjacent data blocks // if we can nest properly, then the nesting level below block at // startpos and endpos must be equal, and between startpos and // endpos it must never fall below the level at startpos. totalsize = 0; for i in [0..size(block.elements)-1] { blocksizes[i] = totalsize + textSizeOfBlock(block.elements[i]); totalsize = blocksizes[i]; } if (totalsize < endpos) { throw(InvalidRange("Can't end after end of element")); } startblock = 0; while (blocksizes[startblock] <= startpos) { startblock++; } endblock = startblock; while (blocksizes[endblock] <= endpos) { endblock++; } if (startblock == 0) { substart = startpos; } else { substart = startpos - blocksizes[startblock-1]; } if (endblock == 0) { subend = endpos; } else { subend = endpos - blocksizes[endblock-1]; } if (endblock != startblock) { case block.elements[endblock] of { SubElement(el) -> throw(InvalidNesting("Improper nesting")); | CData(c) -> case block.elements[startblock] of { SubElement(el) -> throw(InvalidNesting("Improper nesting")); | CData(c) -> elem = insertInlineAroundBlocks(block,inline,startblock,substart,endblock,subend); // start in start block, end in end block, // everything in between moves down a layer } } } else { case block.elements[endblock] of { // call it again on the sub element SubElement(el) -> elem = addInlineElementAt(el,inline,substart,subend); | CData(c) -> elem = insertInlineToCData(block,inline,substart,subend,endblock); // split into three parts a, <>b, c } } return elem; } // TODO: specify start and end by word position or by providing a // substring to delimit. // this function shouldn't need error-checking inside it. private ElementTree insertInlineToCData(ElementTree block, InlineElement inline, Int startpos, Int endpos, Int blocknumber) { initial = block.elements[blocknumber].cdata; if (startpos > 0) { prefix = substr(initial,0,startpos); } else { prefix = createString(0); } if (endpos < length(initial)-1) { suffix = substr(initial,endpos+1,(length(initial)-endpos)); } else { suffix = createString(0); } len = (endpos-startpos)+1; if (len < 1) { middle = createString(0); } else { middle = substr(initial,startpos,len); } toshove = createArray(3); if (prefix != "") { push(toshove,CData(prefix)); } // this code needs making into a function elsewhere elem = makeInlineElement(inline); doAddString(elem,middle); push(toshove,SubElement(elem)); if (suffix != "") { push(toshove,CData(suffix)); } subarrayReplace(block.elements,blocknumber,toshove); return elem; } // rewrite this to use addidx private Void subarrayReplace([a] main, Int index, [a] shove) { main[index] = shove[0]; if (size(shove) > 1) { difference = size(shove)-1; // move everything in main up a few places for (i=size(main)-1;i>index;i--) { main[i+difference] = main[i]; } // and shove the replacement into the gap for (j=1;j= 2 always at this point. elem = makeInlineElement(inline); for i in [startblock+1..endblock-1] { case block.elements[i] of { SubElement(el) -> pushElement(elem,el); | CData(cd) -> doAddString(elem,cd); } } for i in [startblock+2..endblock-1] { removeAt(block.elements,startblock+2); } doAddString(elem,rightprefix); unshiftData(elem,leftsuffix); block.elements[startblock+1] = SubElement(elem); return elem; } "The block to add to Add a line break Append a line break to the block. Consecutive line breaks are not allowed - there are better ways to do this." public ElementTree addLineBreak(ElementTree block) { if (!canContainInline(block.name,false)) { throw(InvalidNesting("Can't add an line break here")); } if (size(block.elements) != 0) { lastelem = block.elements[size(block.elements)-1]; case lastelem of { SubElement(el) -> if (el.name == "br") { throw(InvalidNesting("Doesn't make sense to have two line breaks in a row.")); } | _ -> ; } } br = mkElement("br"); pushElement(block,br); return br; } "The block to add to Add a separator Append a horizontal rule to the block as a separator. Consecutive separators are not allowed." public ElementTree addHorizontalRule(ElementTree block) { if (size(block.elements) != 0) { lastelem = block.elements[size(block.elements)-1]; case lastelem of { SubElement(el) -> if (el.name == "hr") { throw(InvalidNesting("Doesn't make sense to have two horizontal rules in a row.")); } | _ -> ; } } hr = mkElement("hr"); pushElement(block,hr); return hr; } "The block to add to The image to add Add an image Append the image to the block. See the ImageData documentation for more information about image definitions. Images require both a source and alternative text, with the best way to select the alternative text being to consider the text you would use in this context if no image was available. (Many decorative images will therefore have \"\" as their alternative text) p = addParagraph(parent,\"Sponsored by \"); logo = addImage(p,ImageData(\"logo.jpg\",\"MegaCorp\",Specified(100,18))); ImageData" public ElementTree addImage(ElementTree block, ImageData image) { if (!canContainInline(block.name,false)) { throw(InvalidNesting("Can't add an image here")); } img = mkElement("img"); module::setAttribute(img,"src",image.src); module::setAttribute(img,"alt",image.alt); case image.dim of { Specified(width,height) -> module::setAttribute(img,"width",String(width)); module::setAttribute(img,"height",String(height)); // TODO: add support for AutoFromSrc and AutoFromPath | _ -> ; } pushElement(block,img); return img; } /** Part 7: Table editing - adding and editing tables **/ "The parent element Optionally, text for a table caption. Add a new empty table Add a new empty table to the document. You can then set up optional header and footer sections, and at least one body section. The rows and columns of the table are then contained within the header, footer and body sections. addTableBodySection getTableBodySections getTableFooter getTableHeader initialiseTable lazyTable setTableCaption" public ElementTree addTable(ElementTree parent, String captiontext=createString(0)) { if (!canContainBlock(parent.name)) { throw(InvalidNesting("Can't add table inside "+parent.name)); } table = mkElement("table"); pushElement(parent,table); if (captiontext != "") { caption = mkElement("caption"); doAddString(caption,captiontext); pushElement(table,caption); } return table; } "The table The new caption Sets the table caption Sets the caption of the table to the new value, replacing any existing caption. This is the only table manipulation function that will work on a lazyTable. addTable initialiseTable lazyTable" public Void setTableCaption(ElementTree table, String captiontext) { if (table.name != "table") { throw(RequiresElement("setTableCaption can only be used on table elements!")); } case table.elements[0] of { SubElement(el) -> if (el.name == "caption") { removeAt(table.elements,0); } | _ -> ; } caption = mkElement("caption"); doAddString(caption,captiontext); unshiftElement(table,caption); } "The table Get the table header section Gets the table header section. If the table header section does not yet exist, it will be created. Rows can then be added to the section. addTable addTableBodySection addTableRow getTableBodySections getTableFooter initialiseTable lazyTable" public ElementTree getTableHeader(ElementTree table) { if (table.name != "table") { throw(RequiresElement("Can't get a header from table elements!")); } for elem in table.elements { // should never be raw CData inside a table, so hit them with an // exception if they've managed to do it... if (elem.nested.name == "thead") { // return the existing thead if it's there. return elem.nested; } } // so, position it before the tfoot, the first tbody, at the end, in // that order. thead = mkElement("thead"); index = -1; case findElement(table,"tfoot") of { just(x) -> index = x; | nothing -> case findElement(table,"tbody") of { just(x) -> index = x; | nothing -> ; } } if (index == -1) { pushElement(table,thead); // on the end } else { addElementAt(table,thead,index); // in the right place } return thead; } "The table Get the table footer section Gets the table footer section. If the table footer section does not yet exist, it will be created. Rows can then be added to the section. addTable addTableBodySection addTableRow getTableBodySections getTableHeader initialiseTable lazyTable" public ElementTree getTableFooter(ElementTree table) { if (table.name != "table") { throw(RequiresElement("Can't get a footer from non-table elements!")); } for elem in table.elements { // should never be raw CData inside a table, so hit them with an // exception if they've managed to do it... if (elem.nested.name == "tfoot") { // return the existing thead if it's there. return elem.nested; } } // so, position it before the tfoot, the first tbody, at the end, in // that order. tfoot = mkElement("tfoot"); case findElement(table,"tbody") of { just(x) -> addElementAt(table,tfoot,x); | nothing -> pushElement(table,tfoot); } return tfoot; } "The table Add a new table body section Adds a new table body section to the end of the table. Rows can then be added to the section. Tables should have at least one body section, but may have an unlimited number. addTable addTableRow getTableBodySections getTableFooter getTableHeader initialiseTable lazyTable" public ElementTree addTableBodySection(ElementTree table) { if (table.name != "table") { throw(RequiresElement("Can't get a tbody from non-table elements!")); } tbody = mkElement("tbody"); pushElement(table,tbody); return tbody; } "The table Get the table body sections Get the table body sections. If no table body sections exist, one will be created. Rows can then be added to the section. addTable addTableBodySection addTableRow getTableFooter getTableHeader initialiseTable lazyTable" public [ElementTree] getTableBodySections(ElementTree table) { if (table.name != "table") { throw(RequiresElement("Can't get a tbody from non-table elements!")); } case findElement(table,"tbody") of { nothing -> return [addTableBodySection(table)]; | just(x) -> sz = size(table.elements); arr = subarray(table.elements,x,sz-x); return map(extractSubElement,arr); } } // this doesn't work with lambda, oddly private ElementTree extractSubElement(Element val) { return val.nested; } private Bool isTsect(String name) { return (name=="tbody" || name=="thead" || name=="tfoot"); } "The table Get the number of columns in a table Get the number of columns in a table addTableColumns" public Int numTableColumns(ElementTree table) { if (table.name != "table") { throw(RequiresElement("Can't get number of columns if it's not a table!")); } // whatever the first row of the table is can't be miscounted // by rowspans. for i in table.elements { // no Cdata should be here if (isTsect(i.nested.name)) { // ignore empty tsects. // any non-empty tsect will have the same number of columns if (size(i.nested.elements) != 0) { return numTsectColumns(i.nested); } } } return 0; } private Int numTsectColumns(ElementTree tsect) { cols = 0; // use the first one to avoid needing rowspan calculations for td in tsect.elements[0].nested.elements { case lookup(td.nested.attributes,"colspan") of { nothing -> cols++; | just(c) -> cols += Int(c); } } return cols; } "The table header, footer or body section Optionally, the CSS class to apply to the row Adds a table row Add a new row to the end of the selected header, body or footer section of a table. Once the table as a whole has at least one row, columns may be added. addTableBodySection addTableColumns getTableBodySections getTableCell getTableFooter getTableHeader" public ElementTree addTableRow(ElementTree tsect, String class=createString(0)) { if (!isTsect(tsect.name)) { throw(RequiresElement("Can't add a table row here!")); } tr = mkElement("tr"); pushElement(tsect,tr); if (class != "") { setClass(tr,class); } columns = numTsectColumns(tsect); if (columns > 0) { for i in [1..columns] { // can do this because we don't let rowspans extend outside the // existing tsect rows pushElement(tr,mkElement("td")); } } return tr; } "The table Optionally, the number of columns to add. If omitted, a single column is added. Add a new table column Add a new column to the table. The table must have at least one section with at least one row for this to work - a RequiresElement Exception will be thrown otherwise. Unlike most of the table functions, this function does not return the new elements created since they will be in different rows. addTable addTableRow getTableCell initialiseTable numTableColumns" public Void addTableColumns(ElementTree table, Int num=1) { if (table.name != "table") { throw(RequiresElement("Can't add columns if it's not a table!")); } for j in [1..num] { valid = false; for i in table.elements { // no Cdata should be here if (isTsect(i.nested.name)) { for tr in i.nested.elements { pushElement(tr.nested,mkElement("td")); valid = true; } } } if (!valid) { throw(RequiresElement("Can't add columns until the table has at least one row")); } } } "The table header, footer or body section The row to retrieve from (starting at 0) The column to retrieve from (starting at 0) Make a table cell a header cell Makes a table cell a header cell and returns the cell. Apart from converting the cell to a header cell if it wasn't already, this is identical to getTableCell. getTableCell makeDataCell" public ElementTree makeHeaderCell(ElementTree tsect, Int row, Int col) { cell = getTableCell(tsect,row,col); cell.name = "th"; return cell; } "The table header, footer or body section The row to retrieve from (starting at 0) The column to retrieve from (starting at 0) Make a table cell a data cell Makes a table cell a data cell and returns the cell. Apart from converting the cell to a data cell if it wasn't already, this is identical to getTableCell. All cells are data cells by default, unless created with initialiseTable (or lazyTable, though of course those cells are not retrievable with this function) in the header section. getTableCell makeHeaderCell" public ElementTree makeDataCell(ElementTree tsect, Int row, Int col) { cell = getTableCell(tsect,row,col); cell.name = "td"; return cell; } "The table header, footer or body section The row to retrieve from (starting at 0) The column to retrieve from (starting at 0) Retrieve a table cell Retrieve a table cell so that content may be added to it. An Array::OutOfBounds Exception will be thrown if the row and column are not within the table. table = addTable(parent,\"Example table\"); tbody = addTableBodySection(table); for i in [0..2] { void(addTableRow(tbody)); } addTableColumns(table,3); for i in [0..2] { for j in [0..2] { td = getTableCell(tbody,i,j); addString(td,String(i+j)); } } /* Example table +---+---+---+ | 0 | 1 | 2 | +---+---+---+ | 1 | 2 | 3 | +---+---+---+ | 2 | 3 | 4 | +---+---+---+ */ Naturally, the table in this simple example would be easier to generate using initialiseTable. addTableBodySection addTableColumns addTableRow getTableBodySections makeDataCell makeHeaderCell getTableFooter getTableHeader" public ElementTree getTableCell(ElementTree tsect, Int row, Int col) { // this does some error checking for mHC and mDC if (!isTsect(tsect.name)) { throw(RequiresElement("Can only get cells from tbody, thead or tfoot!")); } if (size(tsect.elements) <= row) { throw(OutOfBounds); } if (size(tsect.elements[row].nested.elements) <= col) { throw(OutOfBounds); } return tsect.elements[row].nested.elements[col].nested; } "The parent element The InitialTableData Optionally, a caption for the table Create a table and initialise contents Creates a table with the sections, rows, columns and cells described in the itd parameter - see the InitialTableData documentation for more details. Cells will be created as data cells by default, except for cells in the header section, which will be created as header cells. InitialTableData addTable lazyTable setTableCaption" public ElementTree initialiseTable(ElementTree parent, InitialTableData itd, String caption=createString(0)) { table = addTable(parent,caption); // create the rows if (size(itd.header) > 0 && size(itd.header[0]) > 0) { thead = getTableHeader(table); for i in [1..size(itd.header)] { tr = addTableRow(thead); } fillheader = true; cols = size(itd.header[0]); } else { fillheader = false; } if (size(itd.footer) > 0 && size(itd.footer[0]) > 0) { tfoot = getTableFooter(table); for i in [1..size(itd.footer)] { tr = addTableRow(tfoot); } cols = size(itd.footer[0]); fillfooter = true; } else { fillfooter = false; } if (size(itd.sections) > 0 && size(itd.sections[0]) > 0 && size(itd.sections[0][0]) > 0) { tbc = 0; for tbodies in itd.sections { tbody[tbc] = addTableBodySection(table); for i in [1..size(tbodies)] { tr = addTableRow(tbody[tbc]); } tbc++; } cols = size(itd.sections[0][0]); fillbody = true; } else { fillbody = false; } // create the columns addTableColumns(table,cols); // add the data if (fillheader) { fillBlockWithData(thead,itd.header,true); } if (fillfooter) { fillBlockWithData(tfoot,itd.footer); } if (fillbody) { for (k=0;kThe parent element The InitialTableData Optionally, a caption for the table Create a lazy table Creates a lazy table with the sections, rows, columns and cells described in the itd parameter - see the InitialTableData documentation for more details. Cells will be created as data cells by default, except for cells in the header section, which will be created as header cells. This function differs from initialiseTable in that the contents of the table are only partially applied. They are generated only when the table is converted to a string, which saves a considerable amount of memory for large tables, but has the disadvantage that the contents may not be edited, and so may only consist of plain text. InitialTableData addTable initialiseTable setTableCaption" public ElementTree lazyTable(ElementTree parent, InitialTableData itd, String caption=createString(0)) { table = addTable(parent,caption); // create the rows if (size(itd.header) > 0 && size(itd.header[0]) > 0) { fillheader = true; cols = size(itd.header[0]); } else { fillheader = false; } if (size(itd.footer) > 0 && size(itd.footer[0]) > 0) { cols = size(itd.footer[0]); fillfooter = true; } else { fillfooter = false; } if (size(itd.sections) > 0 && size(itd.sections[0]) > 0 && size(itd.sections[0][0]) > 0) { tbc = 0; cols = size(itd.sections[0][0]); fillbody = true; } else { fillbody = false; } if (fillheader) { appendGenerator(table,lazyTHead@(cols,itd.header)); } if (fillfooter) { appendGenerator(table,lazyTFoot@(cols,itd.footer)); } if (fillbody) { for tbody in itd.sections { appendGenerator(table,lazyTBody@(cols,tbody)); } } return table; } /* LAZY */ ElementTree lazyTHead(Int cols, [[String]] dat) = lazyTBlock("th","thead",cols,dat); ElementTree lazyTFoot(Int cols, [[String]] dat) = lazyTBlock("td","tfoot",cols,dat); ElementTree lazyTBody(Int cols, [[String]] dat) = lazyTBlock("td","tbody",cols,dat); ElementTree lazyTBlock(String cell, String block, Int cols, [[String]] dat) { tblock = mkElement(block,size(dat)); for row in dat { appendGenerator(tblock,lazyTRow@(cell,cols,row)); } return tblock; } // probably a row at a time is lazy enough. ElementTree lazyTRow(String cell, Int cols, [String] row) { tr = mkElement("tr",cols); for i in [0..cols-1] { tcell = mkElement(cell); doAddString(tcell,row[i]); pushElement(tr,tcell); } return tr; } /** Part 8: Form editing - including Kaya state maintenance magic **/ "The parent element Does this particular form allow file uploads. This argument can be omitted, for a default of disallowing them. Note that WebCommon::allowFileUploads must also be called for this to be successfully enabled. Add a form for the current application This adds a form that points to the current web application to call a named function. You then need to use addLocalControlInput to choose the function to call. If you are using mod_rewrite in Apache, or other methods of rewriting URLs at the webserver level, then you may need to call setAttribute(form,\"action\",rewritten), as Kaya cannot know about this URL rewriting layer. Note that in HTML form input controls may not be placed directly inside a form - you must add block-level elements to the form and add controls to those elements. The fieldset element is especially suited to this and the addFieldset function handles this. addFieldset addLocalControlInput addRemoteForm" public ElementTree addLocalForm(ElementTree parent, Bool fileupload=false) { form = addForm(parent); module::setAttribute(form,"action",webappName()); module::setAttribute(form,"method","post"); if (fileupload) { module::setAttribute(form,"enctype","multipart/form-data"); } return form; } "The parent element The URL of the other application The method to use to send the form data Add a form to call another application This adds a form that points to a specified URL. Unless the other URL is a (byte for byte) identical copy of the current application, you will not be able to use Kaya's special state handling, and must construct another way of passing the information. If the security of the information is not critical, and the other application is also a Kaya application, then the Pickle module may be of use. form = addRemoteForm(doc.body, \"http://www.example.com/email.cgi\", FormPost); Note that in HTML form input controls may not be placed directly inside a form - you must add block-level elements to the form and add controls to those elements. The fieldset element is especially suited to this and the addFieldset function handles this. FormType addFieldset addLocalForm" public ElementTree addRemoteForm(ElementTree parent, String action, FormType method) { form = addForm(parent); module::setAttribute(form,"action",action); case method of { FormGet -> module::setAttribute(form,"method","get"); | FormPost -> module::setAttribute(form,"method","post"); | FormPostUpload -> module::setAttribute(form,"method","post"); module::setAttribute(form,"enctype","multipart/form-data"); } return form; } // called by local and remote form private ElementTree addForm(ElementTree parent) { if (!canContainBlock(parent.name)) { throw(InvalidNesting("Can't add a form inside "+parent.name)); } form = mkElement("form"); pushElement(parent,form); return form; } "The parent element The type of text input to add The name of the input. Remember that names starting with \"kaya_\" may be used by the Kaya standard library and should not be used directly by applications. The initial value of the input. For text and password fields, this may be changed by the user in their web browser (someone attacking your application may of course change any value, regardless of the input type). This value is generally ignored by web browsers for file upload inputs. This value is optional, and defaults to the empty String. Optionally, the display size of the input element. Browser rules for determining this size vary - it is an approximate number of characters, but only approximate. Obviously browsers ignore this field for hidden fields and checkbox and radio inputs, and usually for file upload inputs too. Adds a text input Adds a text input to a form. In HTML, controls may not be added directly to a form, so you must add them to a block-level element such as fieldset within the form. TextInputType addFieldset addLabelledInput addOption addSelectElement addTextarea" public ElementTree addTextInput(ElementTree parent, TextInputType itype, String iname, String ivalue=createString(0), Int isize=0) { if (!canContainInline(parent.name)) { throw(InvalidNesting("Can't add a form input inside "+parent.name)); } if (iname == "") { throw(RequiresAttribute("Input name can't be empty.")); } input = mkElement("input"); pushElement(parent,input); module::setAttribute(input,"name",iname); module::setAttribute(input,"value",ivalue); case itype of { InputHidden -> module::setAttribute(input,"type","hidden"); | InputPassword -> module::setAttribute(input,"type","password"); module::setAttribute(input,"size",String(isize)); | InputText -> module::setAttribute(input,"type","text"); module::setAttribute(input,"size",String(isize)); | InputCheck -> module::setAttribute(input,"type","checkbox"); | InputRadio -> module::setAttribute(input,"type","radio"); | InputFile -> module::setAttribute(input,"type","file"); } return input; } "The parent element The function to call The state to pass to the function Call a CGI function Adds the state and processing function variables to a block-level element within a form created with addLocalForm. This function only works with the CGI state handling model, and is equivalent to using CGI::formHandler for non-HTMLDocument CGI programs. CGI" public Void addStateFields(ElementTree parent, Void(a) fn, a state) { discard = addTextInput(parent,InputHidden,"kaya_function",encode(String(fnid(fn)))); discard = addTextInput(parent,InputHidden,"kaya_arg",encode(marshal(state,fnid(fn)))); } "The parent element (often the form, but in many cases nested fieldsets make sense) The 'legend' of the fieldset. This text is generally displayed at the top of the fieldset as a descriptive heading. Add a new fieldset Add a new fieldset to a form. Fieldsets are very useful for containing form controls which may not be directly contained within a form." public ElementTree addFieldset(ElementTree parent, String legendtext) { if (!canContainBlock(parent.name)) { throw(InvalidNesting("Can't add a fieldset inside "+parent.name)); } fset = mkElement("fieldset"); pushElement(parent,fset); legend = mkElement("legend"); doAddString(legend,legendtext); pushElement(fset,legend); return fset; } "The element containing the text The character position of the first character The character position of the last character The form control Associates some text with a form control Associates text with a form control. In some common graphical browsers, clicking on the text will then focus or activate the form control, which is especially useful for checkboxes and radio buttons. The related functions below all add form controls which are already associated with their label texts, and so this function is not needed for these. addLabelledInput addLabelledSelect addLabelledTextarea addOptionList" public Void associateTextAndInput(ElementTree block, Int startpos, Int endpos, ElementTree control) { label = addInlineElementAt(block,FormLabel,startpos,endpos); doAssociateTandI(label,control); } private Void doAssociateTandI(ElementTree label, ElementTree control) { // private function so don't need to do this checking /* if (label.name != "label") { throw(RequiresElement("The first parameter must be a label element")); } if (control.name == "input" || control.name == "select" || control.name == "textarea") { */ uid = nextUniqueID(); module::setAttribute(label,"for",uid); setID(control,uid); /* } else { throw(RequiresElement("The second parameter must be a form field element")); }*/ } Void normaliseOpt([SelectOption] opts, Bool ismult) { for opt in opts { if (opt.chosen) { if (ismult) { opt.chosen = false; } else { ismult = true; } } } } Int normaliseOptgroups([(String,[SelectOption])] optgroups, Bool allowmult) { isize = 0; ismult = false; for optgroup in optgroups { if (optgroup.fst != "") { isize++; } else { isize += size(optgroup.snd); } if (allowmult==false) { normaliseOpt(optgroup.snd,ismult); } } return isize; } "The parent element The name of the input. Remember that names starting with \"kaya_\" may be used by the Kaya standard library and should not be used directly by applications. The size of the select element. If this is zero, the select element will only allow one option to be selected at any one time. If this is one or more, the select element will allow multiple options to be selected, and suggest to the browser that this many options be displayed simultaneously. The options to select from Adds a selection box Adds a selection box to a form. The optgroups parameter is a list of pairs. The first element of the pair is the 'heading' for the option group, and the second element is a list of options in that group. For most simple selectors, a single option group with no heading (the empty string) is sufficient. options = [ SelectOption(\"Express delivery\",\"1\",true), SelectOption(\"Standard delivery\",\"2\",false), SelectOption(\"Slow delivery\",\"3\",false) ]; sel = addSelectElement(fieldset,\"choice\",0,[(\"\",options)]); /* // produces <select> <option value='1' selected='selected'>Express delivery</option> <option value='2'>Standard delivery</option> <option value='3'>Slow delivery</option> </select> */ Using multiple groups of options is useful for larger select elements, where it can make the form clearer. singles = [\"A1\",\"A2\",\"B5\"]; twins = [\"A4\",\"C2\"]; doubles = [\"A7\",\"C1\",\"C3\"]; sopts = []; topts = []; dopts = []; for s in singles { push(sopts,SelectOption(s,s,false); } for t in twins { push(topts,SelectOption(s,s,false); } for d in doubles { push(dopts,SelectOption(s,s,false); } options = [ (\"Single rooms\",sopts), (\"Twin rooms\",topts), (\"Double rooms\",dopts) ]; sel = addSelectElement(roombooker,\"room\",0,options); Select elements allowing multiple options to be selected have very bad usability in most browsers - it is often better to use addOptionList to generate a set of checkboxes instead. Whichever method you use for multiple selection, remember that you need to use WebCommon::incomingData to correctly retrieve the selections from the user's form submission. SelectOption addFieldset addLabelledSelect addLazySelect addOptionList addTextarea addTextInput" public ElementTree addSelectElement(ElementTree block, String name, Int ssize, [(String,[SelectOption])] optgroups) { if (!canContainInline(block.name)) { throw(InvalidNesting("Can't add a form input inside "+block.name)); } isize = normaliseOptgroups(optgroups,(ssize>0)); select = mkElement("select",isize); module::setAttribute(select,"name",name); if (ssize > 0) { module::setAttribute(select,"size",String(ssize)); module::setAttribute(select,"multiple","multiple"); } for optgroup in optgroups { if (optgroup.fst != "") { og = mkElement("optgroup"); module::setAttribute(og,"label",optgroup.fst); for option in optgroup.snd { if (option.value == "") { option.value = option.label; } opt = mkElement("option"); module::setAttribute(opt,"value",option.value); module::setAttribute(opt,"label",option.label); if (option.chosen) { module::setAttribute(opt,"selected","selected"); } doAddString(opt,optgroup.fst+": "+option.label); pushElement(og,opt); } pushElement(select,og); } else { for option in optgroup.snd { if (option.value == "") { option.value = option.label; } opt = mkElement("option"); module::setAttribute(opt,"value",option.value); if (option.chosen) { module::setAttribute(opt,"selected","selected"); } doAddString(opt,option.label); pushElement(select,opt); } } } pushElement(block,select); return select; } "The parent element The name of the input. Remember that names starting with \"kaya_\" may be used by the Kaya standard library and should not be used directly by applications. The size of the select element. If this is zero, the select element will only allow one option to be selected at any one time. If this is one or more, the select element will allow multiple options to be selected, and suggest to the browser that this many options be displayed simultaneously. The options to select from Lazily adds a selection box Adds a lazy selection box to a form. The end result after conversion to a String is identical to that produced by addSelectElement, but the memory usage is lower. The disadvantage, however, is that Webapp::autoFill cannot be used to automatically complete forms containing lazy elements such as this one. SelectOption addLabelledSelect addSelectElement" public ElementTree addLazySelect(ElementTree block, String name, Int ssize, [(String,[SelectOption])] optgroups) { if (!canContainInline(block.name)) { throw(InvalidNesting("Can't add a form input inside "+block.name)); } isize = normaliseOptgroups(optgroups,(ssize>0)); select = mkElement("select",isize); module::setAttribute(select,"name",name); if (ssize > 0) { module::setAttribute(select,"size",String(ssize)); module::setAttribute(select,"multiple","multiple"); } for optgroup in optgroups { if (optgroup.fst != "") { appendGenerator(select,lazyOptgroup@(optgroup)); } else { for option in optgroup.snd { appendGenerator(select,lazyOption@(option,createString(0))); } } } pushElement(block,select); return select; } ElementTree lazyOptgroup((String,[SelectOption]) optgroup) { og = mkElement("optgroup"); module::setAttribute(og,"label",optgroup.fst); for option in optgroup.snd { appendGenerator(og,lazyOption@(option,optgroup.fst)); } return og; } ElementTree lazyOption(SelectOption option, String group) { opt = mkElement("option"); if (option.value == "") { option.value = option.label; } else { module::setAttribute(opt,"value",option.value); } module::setAttribute(opt,"label",option.label); if (option.chosen) { module::setAttribute(opt,"selected","selected"); } if (group != "") { doAddString(opt,group+": "+option.label); } else { doAddString(opt,option.label); } return opt; } "The parent element The label for the selector The name of the input. Remember that names starting with \"kaya_\" may be used by the Kaya standard library and should not be used directly by applications. The size of the select element. If this is zero, the select element will only allow one option to be selected at any one time. If this is one or more, the select element will allow multiple options to be selected, and suggest to the browser that this many options be displayed simultaneously. The options to select from This parameter is optional and defaults to false. If it is explicitly set to true then the selector will be generated lazily. Adds a labelled selection box Adds a labelled selection box to a form. The selector itself is identical to that produced by addSelectElement or addLazySelect, depending on the value of the lazy parameter. Generally, it is more convenient to use this function to label selectors, than to create them individally. SelectOption addLazySelect addOptionList addSelectElement" public ElementTree addLabelledSelect(ElementTree block, String labeltext, String name, Int ssize, [(String,[SelectOption])] optgroups, Bool lazy=false) { div = addDivision(block); label = appendInlineElement(div,FormLabel,labeltext); if (!lazy) { control = addSelectElement(div,name,ssize,optgroups); } else { control = addLazySelect(div,name,ssize,optgroups); } doAssociateTandI(label,control); return div; } "The function to call The state to pass An optional prefix to the control variables. Different components may use different prefixes, allowing multiple Webapp::runHandler functions. Create a URL that calls a local function Create a URL that calls a local function for use in hyperlinks. You may pass additional parameters by appending them to the URL, of course. url = localControlURL(browseData,logindata); url += \";datasource=12\"; CGI::imageHandler CGI::linkURL encodeControlState addLocalControlInput" public String localControlURL(b(a) fn, a state, String prefix="") { name = prefix+"kaya_control"; val = urlEncode(encodeControlState(@fn,state,prefix)); return webappName() + "?" + name + "=" + val; } "The function to call The state to pass An optional prefix to the control variables. Different components may use different prefixes, allowing multiple Webapp::runHandler functions. In this context it performs the same role as the marshalling ID - if you are calling this function directly you almost certainly don't need it. Encode application state for later retrieval Encode an application state into a string. This is useful with Webapp::storeFunction for constructing shorter URLs, or allowing someone to resume a process at a much later date. Webapp::storeFunction" public String encodeControlState(b(a) fn, a state, String prefix="") { return encode(compressString(marshal((@fn,state,prefix),228))); } "The element to add the button to The text for the button The function to call The state to pass An optional prefix to the control variables. Different components may use different prefixes, allowing multiple Webapp::runHandler functions. Add a form submit button Create a submit button that calls a local function. This only works if added to a form created with addLocalForm. addLocalForm addRemoteControlInput" public ElementTree addLocalControlInput(ElementTree parent, String label, b(a) fn, a state, String prefix="") { if (!canContainInline(parent.name)) { throw(InvalidNesting("Can't add a form input inside "+parent.name)); } input = mkElement("input"); pushElement(parent,input); module::setAttribute(input,"type","submit"); module::setAttribute(input,"value",label); submitid = nextUniqueID(); module::setAttribute(input,"name",prefix+"kaya_submit_"+submitid); stateinfo = encode(compressString(marshal((fn,state,prefix),Int(substr(submitid,3,length(submitid)-3))))); hinput = addTextInput(parent,InputHidden,prefix+"kaya_control_"+submitid,stateinfo); return input; } "The element to add the button to The type of the button The name of the button The label of the button Add a form submit button Create a submit button for a form created with addRemoteForm. The button will be submitted when pressed as iname=ivalue. If iname is the empty string, then the value will not be submitted with the rest of the form. ControlInputType addLocalControlInput addRemoteForm" public ElementTree addRemoteControlInput(ElementTree parent, ControlInputType itype, String iname=createString(0), String ivalue=createString(0)) { if (!canContainInline(parent.name)) { throw(InvalidNesting("Can't add a form input inside "+parent.name)); } input = mkElement("input"); pushElement(parent,input); case itype of { InputSubmit -> module::setAttribute(input,"type","submit"); if (iname != "") { module::setAttribute(input,"name",iname); } | InputReset -> module::setAttribute(input,"type","reset"); } if (ivalue != "") { module::setAttribute(input,"value",ivalue); } return input; } "The parent element The legend for the fieldset grouping the options The name of the option controls. Remember that names starting with \"kaya_\" may be used by the Kaya standard library and should not be used directly by applications. The options to select from This parameter is optional and defaults to true, which generates the option list as a set of checkboxes. If it is explicitly set to false then radio buttons are used instead. Adds a set of checkboxes or radio buttons Adds a set of checkboxes or radio buttons to a form. The meaning of the parameters is very similar or identical to the similar parameters for addLabelledSelect, but the appearance is very different. If the number of options is not large, this is generally considerably easier to use than a selection drop-down, although it does take up much more screen space. When using this function to generate radio buttons, you should ensure that one of the options is initially selected, as browser behaviour when no option is selected is variable and often causes problems. You may need to add a \"no option selected\" radio button for initial selection in some circumstances. options = [ SelectOption(\"Express delivery\",\"1\",true), SelectOption(\"Standard delivery\",\"2\",false), SelectOption(\"Slow delivery\",\"3\",false) ]; sel = addLabelledSelect(fieldset,\"Select a delivery speed\",\"choice\", options,false); /* // produces <fieldset><legend>Select a delivery speed</legend> <div><input type='checkbox' name='choice' value='1' id='Kay1' checked='checked'> <label for='Kay1'>Express delivery</label></div> <div><input type='checkbox' name='choice' value='2' id='Kay2'> <label for='Kay2'>Standard delivery</label></div> <div><input type='checkbox' name='choice' value='3' id='Kay3'> <label for='Kay3'>Slow delivery</label></div> </fieldset> */ // exact markup may vary slightly to keep IDs unique in the document SelectOption addLabelledSelect addOption" // gives them all the same name for symmetry with (\"ul\",\"li\") returns true). Nesting exceptions are not made for the table elements, as editing these via addition of elements would be very error-prone - the specialised table editing functions in HTMLDocument should be used instead." public Bool nestingExceptions((String,String) ex) = elem(ex,ne); // table elements not listed because editing tables that way could get messy. "List all empty elements Return a list of the names of all empty elements. This is used by HTMLDocument::readFromString." public [String] isAlwaysEmpty = array(ae); "Retrieve dictionary of all empty elements Return a HashSet of the names of all empty elements. This is used by ElementTree::string and ElementTree::lazyPrint" public HashSet getAlwaysEmpty = ae; kaya-0.4.4/stdlib/crypto_glue.cc0000644000175100017510000000116011170340770014672 0ustar cimcim#include #include //#include #include #include #include #include #include "crypto_glue.h" extern char* kaya_secret; extern char* kaya_ivec; KayaArray getKey() { KayaArray a = newKayaArray(32); // has a 3-char padding on each end for easy binary rekeying int x = 3; for(;x<35;++x) { KayaArrayPush(a,KayaInt((int)(kaya_secret[x]))); } return a; } KayaArray getIVec() { KayaArray a = newKayaArray(16); int x = 3; for(;x<19;++x) { KayaArrayPush(a,KayaInt((int)(kaya_ivec[x]))); } return a; } kaya-0.4.4/stdlib/Binary.k0000644000175100017510000003513711170340770013442 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Manipulate binary data This module contains low-level functions and data types for handling binary data. These functions may then be used by other modules and programs to handle specific types of binary data (for example, images, compressed files, or strings containing null bytes)" module Binary; import public IO; import Builtins; %include "binary_glue.h"; %imported "binary_glue"; "Block of binary data. This is a block of raw data. When storing or retrieving bytes, they are treated in Kaya as Ints, but really they are 8 bit values. If you try to store an Int greater than 256, only the low 8 bits will be used. Created with createBlock. Created and initialised with createInitialisedBlock." abstract data Binary = Bin(Ptr bindata,Int blocksize); "Attempt to access an offset outside a block This Exception is thrown if you attempt to read or write past the bounds of a Binary block. Binary" Exception OffsetOutOfRange; foreign "binary_glue.o" { Ptr newBlock(Int size) = newBlock; Void dopoke(Ptr block, Int offset, Int val) = poke; Int dopeek(Ptr block, Int offset) = peek; Void dopokeString(Ptr block, Int offset, String val) = pokestring; String dopeekString(Ptr block, Int offset, Int bsize) = peekstring; Ptr docopyBlock(Ptr block, Int size) = copyBlock; Ptr docopyChunk(Ptr block, Int offset, Int size) = copyChunk; [Int] dogetBlockData(Ptr block, Int offset, Int size) = getBlockData; Void dosetBlockData(Ptr block, Int offset, Int size, [Int] dat) = setBlockData; Int dowriteBlock(Ptr f, Ptr block, Int size) = writeBlock; Ptr doreadBlock(Ptr f, a size) = readBlock; String b64binary(Ptr block, Int len) = b64binary; Ptr b64binarydec(String block, intval len) = b64binarydec; } "The size of the block. Block sizes cannot be changed once the block is created. Create a new, uninitialised block for binary data. Create a new, uninitialised block for binary data. Remember to use Builtins::byteLength instead of Builtins::length if you want to store Strings in these, as you may have problems with multi-byte characters otherwise. The uninitialised contents of this block are not guaranteed to be zeroes. Binary" public Binary createBlock(Int bsize) { return Bin(newBlock(bsize),bsize); } "A pointer to a foreign structure. The size of the structure in bytes. Create a new and initialised block for binary data. Create a new and initialised block for binary data. Note that the contents of the block are the structure, not a copy of it, so any writes made here will affect the foreign structure. Binary" public Binary createInitialisedBlock(Ptr ptr,Int bsize) { return Bin(ptr,bsize); } "The Binary block Get the size of a block Get the size of a binary block in bytes. Binary" public Int blockSize(Binary b) { return b.blocksize; } "The Binary block Get a foreign pointer to Binary data Get a foreign pointer to Binary data to pass to a foreign function call. Binary" public Ptr blockData(Binary b) { return b.bindata; } "The binary block The location to write to (starting from zero) The byte value to write. Modify binary data. Poke the value val into the offset offset. An OffsetOutOfRange exception will be thrown if it attempts to access a value outside the block. Binary peek pokeString setBlockData" public Void poke(var Binary block, Int offset, Int val) { if (offset<0 || offset>=block.blocksize) { throw(OffsetOutOfRange); } dopoke(block.bindata,offset,abs(val%256)); } "The binary block The location to read from (starting from zero) Query binary data. Retrieve the byte at offset offset. An OffsetOutOfRange exception will be thrown if it attempts to access a value outside the block. Binary array getBlockChunk peekString poke" public Int peek(Binary block,Int offset) { if (offset<0 || offset>=block.blocksize) { throw(OffsetOutOfRange); } return dopeek(block.bindata,offset); } "The binary block The location to write to (starting from zero) The String to write. Write a String of binary data. Poke the string val into the block, starting at offset offset. An OffsetOutOfRange exception will be thrown if it attempts to access a value outside the block. Note that the String will be stored in the block in UTF-8 encoding, not as raw Kaya chars, so you need to use Builtins::byteLength to determine how much space you need (and then add one for a terminating null byte). Binary Builtins::byteLength peekString poke setBlockData" public Void pokeString(var Binary block, Int offset, String val) { if (offset<0 || offset>=(block.blocksize-byteLength(val))) { throw(OffsetOutOfRange); } dopokeString(block.bindata,offset,val); } "The binary block The location to read from (starting from zero) Read a String from binary data. Peek at the string val starting at offset offset. An OffsetOutOfRange exception will be thrown if it attempts to access a value outside the block. Note that Kaya assumes the String is stored in the block in UTF-8 encoding, with null-termination. Binary array getBlockChunk peek pokeString" public String peekString(Binary block,Int offset) { if (offset<0 || offset>=block.blocksize) { throw(OffsetOutOfRange); } return dopeekString(block.bindata,offset,block.blocksize); } "The block of data Copy a block of data. Creates a new block with identical size and contents to block. This can be used to allow editing of data from a block created with createInitialisedBlock, without altering the foreign structure itself. cblock = createInitialisedBlock(ptr,len); kblock = copyBlock(cblock); Binary copyChunk createInitialisedBlock" public Binary copyBlock(Binary block) { return Bin(docopyBlock(block.bindata,block.blocksize), block.blocksize); } "The block of data The initial offset The size of new block to create. Copy a sub-block. Creates a new block from the contents of the original starting at offset with a length of bsize bytes. An OffsetOutOfRange exception will be thrown if it attempts to access a value outside the block. Binary copyBlock getBlockChunk" public Binary copyChunk(Binary block, Int offset, Int bsize) { if (offset<0 || (offset+bsize)>=block.blocksize) { throw(OffsetOutOfRange); } return Bin(docopyChunk(block.bindata,offset,bsize),bsize); } "The binary block The offset to start at (zero-indexed) The length of chunk to read Return a chunk from a block as an array. Return a chunk from a block as an array. Throws an OffsetOutOfRange Exception if it attempts to access a value outside the block. Binary array copyChunk peek peekString setBlockData" public [Int] getBlockChunk(Binary block, Int offset, Int bsize) { if (offset<0 || (offset+bsize)>block.blocksize) { throw(OffsetOutOfRange); } return dogetBlockData(block.bindata,offset,bsize); } "The binary block Return a block as an array. Return a block as an array of Ints. Binary copyBlock getBlockChunk peek peekString setBlockData" public [Int] array(Binary block) { return dogetBlockData(block.bindata,0,block.blocksize); } "The binary block The offset to start at (zero-indexed) The data to write, as an array of Ints Set the contents of a block. Set the contents of (part of) a block from an array. An OffsetOutOfRange Exception will be thrown if this would cause a write outside the bounds of the block. The following bits of code are equivalent: setBlockData(block,offset,bdata); // is equivalent to for byte@idx in bdata { poke(block,offset+idx,byte); } However, setBlockData is more efficient and checks bounds before any data is written - the above for loop could write partial data if offset+idx was greater than blockSize(block). Binary array copyBlock getBlockChunk poke pokeString" public Void setBlockData(var Binary block, Int offset, [Int] bdata) { bsize = size(bdata); if (offset<0 || (offset+bsize)>block.blocksize) { throw(OffsetOutOfRange); } dosetBlockData(block.bindata,offset,bsize,bdata); } "A file handle to write to The binary data Write a block to a file. Write the contents of a Binary block to a file. The file must already be open and writable, of course. A IO::FileError Exception will be thrown if the block was not written in its entirety. Binary IO readBlock" public Void writeBlock(File h,Binary block) { writeCheck(h); written = dowriteBlock(ptr(h),block.bindata,block.blocksize); if (writtenA file handle to read from The maximum number of bytes to read Read a block from a file. Creates a block of size bsize and reads data into it. If there is less data to read than bsize, the block will contain as much data as could be read, and the blockSize function will return the size of the data that was read. Naturally, the file handle must be valid and readable. Binary IO writeBlock" public Binary readBlock(File h,Int bsize) { val = subvert(bsize); readCheck(h); bdata = doreadBlock(ptr(h),val); return Bin(bdata,subvert(val)); } "The block to encode base64 encode a block Returns a String containing the base64-encoded contents of the Binary block. Binary base64Decode Strings::base64Encode" public String base64Encode(Binary block) { return b64binary(block.bindata, block.blocksize); } "The String to decode base64 decode a String Returns a binary Block from base64-decoding of the String. Binary base64Encode Strings::base64Decode" public Binary base64Decode(String block) { len = 0; dec = b64binarydec(block,len); newptr = docopyBlock(dec, len); return Bin(newptr,len); } kaya-0.4.4/stdlib/Tuples.k0000644000175100017510000000524011170340767013470 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Tuple data types This module contains the definitions for the Tuple data types. While tuples up to 6-tuples are defined by this module, it is better in most situations to use a more meaningful user-defined data type than the larger tuples. It is automatically imported (via the Prelude module) unless the -noprelude compiler option is used. Almost all programs and modules will need to import this module." module Tuples; "Sugared as (a,b) This represents an arbitrary pair of values. Pair(a,b) can be written as (a,b) for compactness." public data Pair = Pair(a fst, b snd); "Sugared as (a,b,c) This represents an arbitrary triple of values. Triple(a,b,c) can be written as (a,b,c) for compactness. Tuples larger than Pairs are generally better represented as user-defined data types, to help code readability." public data Triple = Triple(a fst, b snd, c third); "Sugared as (a,b,c,d) This represents an arbitrary set of four values. Tuple4(a,b,c,d) can be written as (a,b,c,d) for compactness. Consider using a more meaningful data type instead of large Tuples, to make your code more readable." public data Tuple4 = Tuple4(a fst, b snd, c third, d fourth); "Sugared as (a,b,c,d,e) This represents an arbitrary set of five values. Tuple5(a,b,c,d,e) can be written as (a,b,c,d,e) for compactness. Consider using a more meaningful data type instead of large Tuples, to make your code more readable." public data Tuple5 = Tuple5(a fst, b snd, c third, d fourth, e fifth); "Sugared as (a,b,c,d,e,f) This represents an arbitrary set of six values. Tuple6(a,b,c,d,e,f) can be written as (a,b,c,d,e,f) for compactness. This is the largest Tuple size available in the standard library. Strongly consider using a more meaningful data type instead of large Tuples, to make your code more readable." public data Tuple6 = Tuple6(a fst, b snd, c third, d fourth, e fifth, f sixth); /* Do we need more than 6-tuples? To be honest, I think anything more than a pair is unlikely to have a use that isn't done better by an ADT. */ kaya-0.4.4/stdlib/Dict.k0000644000175100017510000005154311170340770013100 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ // changed by CIM 17/7/05 to add hashfn to allow custom hash functions "Dictionaries Dictionaries to map keys of one type to values of another type. The Dict type is generally most useful, but TinyDict can be used when the number of keys is very small (10 or fewer). The Set module may also be useful, and its Set::HashSet replaces the ExistDict in this module in previous Kaya versions. Looking up and adding values to a dictionary will usually take a constant amount of time regardless of the size of the dictionary, and so these are often more efficient than usings lists." module Dict; import Prelude; "Dictionary/Hash Table. A Dictionary maps values of type a to values of type b. new" abstract data Dict([[(a,b)]] entries, Int buckets, Int(a) hashfn); "Tiny Dictionary/Hash Table. A tiny Dictionary maps a small number of values of type a to values of type b. Generally Dict is more efficient for dictionaries expected to have 10 or more keys. newTiny" abstract data TinyDict([a] keys, [b] vals); "The number of hashing buckets to use. A larger number of buckets increases the speed of the dictionary (up to a limit) but uses more memory. A good choice is the nearest prime number to 1.5*(expected number of entries), with the default being 157. The function to hash the keys. This function must take a key, and return an integer. A good hashing function will return different values for similar keys (but must of course always return the same value for the same key!). A default built-in hashing function is provided, though if the keys are of type String, the Builtins::strHash function should be used instead, and if the keys are of type Int you may use Builtins::identity (though an array may provide faster insertion and lookup if the keys are positive and either small or largely sequential). If the keys are an especially complex data type, it may again be best to write your own hashing function. Create a new dictionary. Create a new dictionary. d = Dict::new(); // 157 buckets, default hashing function d = Dict::new(31,strHash); // 31 buckets, String hashing function // - suitable for holding about 20 values. Dict add delete empty entries exists keys lookup vals" public Dict new(Int buckets = 157, Int(a) hashfn = hash) = Dict(createArray(buckets),buckets,hashfn); "Create a new tiny dictionary. Create a new tiny dictionary. There are no parameters for tiny dictionaries. d = Dict::newTiny(); TinyDict add delete empty entries exists keys lookup vals" public TinyDict newTiny() = TinyDict(createArray(10),createArray(10)); "A Dict Get the number of buckets used in a dictionary Get the number of buckets used in a dictionary. This function is not generally useful - it is implemented solely to make Dict to Dict mappings easier to implement (for example, the ElementTree makes use of it to apply Prelude::toLower to every key in a dictionary)" public Int numBuckets(Dict d) { return d.buckets; } "A dictionary The key The value Add an entry to a dictionary. Add an entry key = value to the dictionary. If an entry with the same key already exists it will be replaced. Dict delete empty entries exists keys lookup new vals" public Void add(Dict dict, a key, b val) { // Find the right bucket bucket = abs(dict.hashfn(key)) % dict.buckets; // If a is already a key, replace it. if (!isInitialised(dict.entries[bucket])) { // shouldn't need to be very large dict.entries[bucket] = createArray(5); } for p in dict.entries[bucket] { if (p.fst==key) { p.snd = val; return; } } push(dict.entries[bucket],(key,val)); } "A tiny dictionary The key The value Add an entry to a tiny dictionary. Add an entry key = value to the dictionary. If an entry with the same key already exists it will be replaced. TinyDict delete empty entries exists keys lookup newTiny vals" public Void add(TinyDict dict, a key, b val) { // If a is already a key, replace it. for p@i in dict.keys { if (p==key) { dict.vals[i] = val; return; } } push(dict.keys,key); push(dict.vals,val); } "A dictionary The key to lookup Look up a value in a dictionary. Look up a value in a dictionary. Returns nothing if the key does not exist, or just(x) if it maps to x. Dict add delete empty entries exists keys new vals" public Maybe lookup(Dict dict, a key) { // Find the right bucket bucket = abs(dict.hashfn(key)) % dict.buckets; if (!isInitialised(dict.entries[bucket])) { return nothing; // then it can't be here! } for p in dict.entries[bucket] { if (p.fst==key) { return just(p.snd); } } return nothing; } "A tiny dictionary The key to lookup Look up a value in a tiny dictionary. Look up a value in a tiny dictionary. Returns nothing if the key does not exist, or just(x) if it maps to x. TinyDict add delete empty entries exists keys newTiny vals" public Maybe lookup(TinyDict dict, a key) { // Find the right bucket for p@i in dict.keys { if (p==key) { return just(dict.vals[i]); } } return nothing; } "A dictionary The key to lookup Check if a key exists in a dictionary. Check if a key exists in a dictionary and returns true if it does. Dict add delete empty entries keys lookup new vals" public Bool exists(Dict dict, a key) { // Find the right bucket bucket = abs(dict.hashfn(key)) % dict.buckets; if (!isInitialised(dict.entries[bucket])) { return false; // can't be here } for p in dict.entries[bucket] { if (p.fst==key) { return true; } } return false; } "A tiny dictionary The key to lookup Check if a key exists in a tiny dictionary. Check if a key exists in a tiny dictionary and returns true if it does. TinyDict add delete empty entries keys lookup newTiny vals" public Bool exists(TinyDict dict, a key) { // Find the right bucket for p in dict.keys { if (p==key) { return true; } } return false; } "A dictionary Check if a dictionary is empty Returns true if the dictionary has no contents, either because none were added, or because all added entries have been deleted. Dict add delete entries exists keys lookup new vals" public Bool empty(Dict dict) { for ps in dict.entries { if (size(ps) > 0) { return false; } } return true; } "A tiny dictionary Check if a tiny dictionary is empty Returns true if the dictionary has no contents, either because none were added, or because all added entries have been deleted. TinyDict add delete entries exists keys lookup newTiny vals" public Bool empty(TinyDict dict) { return size(dict.keys)==0; } "A dictionary List all keys in a dictionary List all keys in a dictionary. There is no guarantee of any order, although at least within a single program run, identical dictionaries will return identical lists. Dict add delete empty entries exists lookup new vals" public [a] keys(Dict dict) { keys = []; for ps in dict.entries { if (isInitialised(ps)) { for p in ps { push(keys,p.fst); } } } return keys; } "A dictionary The key of the entry to remove. Remove an entry from a dictionary Remove the entry with the given key from the dictionary. Dict add empty entries exists keys lookup new vals" public Void delete(Dict dict, a key) { // Find the right bucket bucket = abs(dict.hashfn(key)) % dict.buckets; if (!isInitialised(dict.entries[bucket])) { return; //can't be in here } ps = dict.entries[bucket]; // If a is a key in ps, remove it. for z in [0..(size(ps)-1)] { if (ps[z].fst==key) { removeAt(ps,z); return; } } } "A tiny dictionary The key of the entry to remove. Remove an entry from a tiny dictionary Remove the entry with the given key from the tiny dictionary. TinyDict add empty entries exists keys lookup newTiny vals" public Void delete(TinyDict dict, a key) { // If a is a key in ps, remove it. for k@z in dict.keys { if (k==key) { removeAt(dict.keys,z); removeAt(dict.vals,z); return; } } } "A tiny dictionary List all keys in a tiny dictionary List all keys in a dictionary. There is no guarantee of any order, although at least within a single program run, identical dictionaries will return identical lists. TinyDict add delete empty entries exists lookup newTiny vals" public [a] keys(TinyDict dict) { return dict.keys; } "A dictionary List all values in a dictionary List all values in a dictionary. There is no guarantee of any order, although at least within a single program run, identical dictionaries will return identical lists. Dict add delete empty entries exists keys lookup new" public [b] vals(Dict dict) { keys = []; for ps in dict.entries { if (isInitialised(ps)) { for p in ps { push(keys,p.snd); } } } return keys; } "A tiny dictionary List all values in a tiny dictionary List all values in a tiny dictionary. There is no guarantee of any order, although at least within a single program run, identical dictionaries will return identical lists. TinyDict add delete empty entries exists keys lookup newTiny" public [b] vals(TinyDict dict) { return dict.vals; } "A dictionary List all entries in a dictionary List all entries in a dictionary (as a list of Tuples::Pair in key-value order). There is no guarantee of any order, although at least within a single program run, identical dictionaries will return identical lists. Dict add delete empty exists keys lookup new vals" public [Pair] entries(Dict dict) { entries = []; for ps in dict.entries { if (isInitialised(ps)) { for p in ps { push(entries,p); } } } return entries; } "A tiny dictionary List all entries in a tiny dictionary List all entries in a tiny dictionary (as a list of Tuples::Pair in key-value order). There is no guarantee of any order, although at least within a single program run, identical dictionaries will return identical lists. TinyDict add delete empty exists keys lookup newTiny vals" public [Pair] entries(TinyDict dict) { entries = createArray(size(dict.keys)); v = dict.vals; for p@i in dict.keys { push(entries,(p,v[i])); } return entries; } "Create a dictionary from a list of pairs A list of pairs. The first element is the key, the second element is the value. Creates a dictionary from an association list (list of key/value pairs). If any keys are repeated, the later value is preferred. " public Dict dict([(a,b)] entries) { d = new(); for e in entries { add(d, e.fst, e.snd); } return d; } kaya-0.4.4/stdlib/zlib_glue.cc0000644000175100017510000000203111170340767014316 0ustar cimcim#include #include #include #include "zlib_glue.h" void* compressBuffer(void* vmptr, void* in, int len, KayaValue buflen) { VMState* vm = (VMState*)vmptr; uLong outlen = compressBound(len); uLong inlen = len; Byte* out = (Byte*)KayaAlloc(outlen); int err = compress(out, &outlen, (Byte*)in, inlen); if (err == Z_BUF_ERROR || err == Z_MEM_ERROR) { vm->kaya_internalError(241); } // printf("compressed %d to %d (%d)\n",len, outlen, err); KayaSetInt(buflen,outlen); return (void*)out; } void* uncompressBuffer(void* vmptr, void* in, int len, KayaValue outlen) { VMState* vm = (VMState*)vmptr; uLong blen = KayaGetInt(outlen); Byte* out = (Byte*)KayaAlloc(blen); int err = uncompress(out, &blen, (Byte*)in, len); if (err == Z_BUF_ERROR || err == Z_MEM_ERROR || err == Z_DATA_ERROR) { vm->kaya_internalError(240); } // printf("uncompressed %d to %d (%d)\n",len,blen, err); KayaSetInt(outlen,blen); return (void*)out; } kaya-0.4.4/stdlib/Time.k0000644000175100017510000004152311170340770013110 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005, 2006, 2007 Edwin Brady, Chris Morris, Boris Jakubith This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Time and date functions This module contains functions to store date/time data, and to format dates and times in ways suitable for interaction with other systems such as email, HTTP or databases." module Time; import Prelude; import Array; import Builtins; import Strings; import Regex; %include "time.h"; "Months of the year. This data type represents the months of the year Time" public data Month = Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec; "Days of the week. This data type represents the days of the week Time" public data Day = Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday; "Representation of time. This data type represents a time. wday is the day of the week, yday is the day of the year, and dst is true if daylight savings time applies." public data Time = Time(Int second, Int minute, Int hour, Int mday, Month mon, Int year, Day wday, Int yday, Bool dst); "Invalid month number This Exception is thrown if month is passed an invalid month number (must be 1-12)." Exception NoSuchMonthNumber(Int m); "Invalid month name This Exception is thrown if month is passed an invalid month name." Exception NoSuchMonthName(String s); "Invalid day name This Exception is thrown if day is passed an invalid day name." Exception NoSuchDay(String s); "Can't parse string to time This Exception is thrown if a string cannot be parsed to a Time. parseISO8601 parseRFC2822" Exception CantParseTime; foreign "stdfuns.o" { "Get the current time. Get the current time in seconds since Jan 1st 1970. localTime gmTime microTime mkTime" public Int now() = gettime; "Get microsecond time Get the current number of microseconds so far this second. On windows, this is rounded to a millisecond resolution. time" public Int microTime() = dogettimeofday; Time dogmtime(Int secs) = dogmtime; Time dolocaltime(Int secs) = dolocaltime; Int domktime(Time t) = domktime; } "The number of seconds since Jan 1 1970. This argument is optional and defaults to the current time. Convert a time to GMT. Converts a time expressed in seconds since Jan 1 1970 to a Time, using the GMT timezone. Time localTime mkTime time" public Time gmTime(Int secs = now()) = dogmtime(secs); "The number of seconds since Jan 1 1970. This argument is optional and defaults to the current time. Convert a time to local time. Converts a time expressed in seconds since Jan 1 1970 to a Time, using the current local timezone. Time gmTime mkTime time" public Time localTime(Int secs = now()) = dolocaltime(secs); "The Time. Convert a Time to seconds. Converts a Time to a number of seconds since Jan 1 1970. Time gmTime localTime time" public Int mkTime(Time t) = domktime(t); "The Time The number of days to add (if negative, subtracts) Add some days to a date. Add some days to a date. Time" public Time addDays(Time t, Int days) = gmTime(mkTime(t)+(24*60*60*days)); "The Month to convert Convert a Month to a string Convert a Month to a string. Month int month" public String string(Month m) { return case m of { Jan -> "January"; | Feb -> "February"; | Mar -> "March"; | Apr -> "April"; | May -> "May"; | Jun -> "June"; | Jul -> "July"; | Aug -> "August"; | Sep -> "September"; | Oct -> "October"; | Nov -> "November"; | Dec -> "December"; }; } "The String to convert Convert a String to a Month Convert a String to a Month. Month month string" public Month month(String s) { ms = substr(s,0,3); if (ms == "Jan") { return Jan; } else if (ms == "Feb") { return Feb; } else if (ms == "Mar") { return Mar; } else if (ms == "Apr") { return Apr; } else if (ms == "May") { return May; } else if (ms == "Jun") { return Jun; } else if (ms == "Jul") { return Jul; } else if (ms == "Aug") { return Aug; } else if (ms == "Sep") { return Sep; } else if (ms == "Oct") { return Oct; } else if (ms == "Nov") { return Nov; } else if (ms == "Dec") { return Dec; } else { throw(NoSuchMonthName(s)); } } "The Month to convert Convert a Month to an Int Convert a Month to an Int. Month month string" public Int int(Month m) { return case m of { Jan -> 1; | Feb -> 2; | Mar -> 3; | Apr -> 4; | May -> 5; | Jun -> 6; | Jul -> 7; | Aug -> 8; | Sep -> 9; | Oct -> 10; | Nov -> 11; | Dec -> 12; }; } "The Int to convert Convert an Int to a Month Convert an Int to a Month. Month int month" public Month month(Int m) { if (m==1) return Jan; if (m==2) return Feb; if (m==3) return Mar; if (m==4) return Apr; if (m==5) return May; if (m==6) return Jun; if (m==7) return Jul; if (m==8) return Aug; if (m==9) return Sep; if (m==10) return Oct; if (m==11) return Nov; if (m==12) return Dec; throw(NoSuchMonthNumber(m)); } "The Day to convert Convert a Day to a string Convert a Day to a string. Day day" public String string(Day d) { return case d of { Sunday -> "Sunday"; | Monday -> "Monday"; | Tuesday -> "Tuesday"; | Wednesday -> "Wednesday"; | Thursday -> "Thursday"; | Friday -> "Friday"; | Saturday -> "Saturday"; }; } "The String to convert Convert a String to a Day Convert a String to a Day. Day string" public Day day(String s) { ms = substr(s,0,3); if (ms == "Sun") { return Sunday; } else if (ms == "Mon") { return Monday; } else if (ms == "Tue") { return Tuesday; } else if (ms == "Wed") { return Wednesday; } else if (ms == "Thu") { return Thursday; } else if (ms == "Fri") { return Friday; } else if (ms == "Sat") { return Saturday; } else { throw(NoSuchDay(s)); } } "The Time The timezone (optional, defaults to \"+0000\") Return an RFC 2822 time Format a Time according to RFC 2822 for use in email or HTTP. Time parseRFC2822" public String rfc2822Time(Time t, String tz="+0000") { return substr(string(t.wday),0,3)+", "+twodigits(t.mday)+" "+substr(string(t.mon),0,3)+" "+t.year+" "+twodigits(t.hour)+":"+twodigits(t.minute)+":"+twodigits(t.second)+" "+tz; } "The Time, which must be in the UTC (+0000) timezone. Return a HTTP Cookie expiry time This function returns a String representing a time in the format used by HTTP Cookies, which is almost the same as RFC2822 but differs from it in a few ways for no apparent reason. This format should only be used for HTTP cookies, and not for any other purpose. rfc2822Time WebCommon::setCookie" public String cookieTime(Time t) { // because they couldn't just use RFC(2)822, could they. Had to be different. return substr(string(t.wday),0,3)+", "+twodigits(t.mday)+"-"+substr(string(t.mon),0,3)+"-"+t.year+" "+twodigits(t.hour)+":"+twodigits(t.minute)+":"+twodigits(t.second)+" GMT"; } "A String containing only an RFC 2822 time string Convert an RFC 2822 string to a Time Convert a string formatted in accordance with RFC 2822 to a Time. Time rfc2822Time" public Time parseRFC2822(String t) { bits = split(r"\s+",t); timebits = split(":",bits[4]); if (size(bits) < 5 || size(bits) > 6 || size(timebits) != 3) { throw(CantParseTime); } ts = Time(Int(timebits[2]),Int(timebits[1]),Int(timebits[0]),Int(bits[1]),month(bits[2]),Int(bits[3]),day(bits[0]),0,false); if (bits[5] == "+0000" || bits[5] == "GMT") { // known bug: dates prior to 1971 appear to have a problem due to // permanent BST from 1968-1971 return ts; } else { hdiff = substr(bits[5],0,2); ts.hour += Int(hdiff); return ts; } } // TODO: generalise this function since the separators can change "A String containing only an ISO8601 time string Convert an ISO 8601 time string to a Time Convert a string formatted in accordance with ISO 8601 to a Time. Time isoTime" public Time parseISO8601(String t) { tsp = split(" ",t); if (size(tsp) != 2) { tsp = split("T",t); // might be a slightly different isoTime format if (size(tsp) != 2) { throw(CantParseTime); } } td = split("-",tsp[0]); if (size(td) != 3) { throw(CantParseTime); } tt = split(":",tsp[1]); if (size(tt) != 3) { throw(CantParseTime); } return Time(Int(tt[2]),Int(tt[1]),Int(tt[0]), Int(td[2]),month(Int(td[1])),Int(td[0]), Sunday,0,false); } String twodigits(Int i) { if (i > 9) { return String(i); } return "0"+i; } /* Start of Boris Jakubith's isoTime() code */ // Flags required for modifying the output of `isoTime()': // - DateOnly --> return only the date "Flags for the isoTime function Flags for modifying the output of the isoTime functions. DateOnly: Return only the date portion of the date and time TimeOnly: Return only the time portion of the date and time (ignored if DateOnly is also specified) WithTimeZone: Include a timezone specification. ShortForm: Compact output by removing date and time delimiters (the delimiter between the date and time parts is kept) TwoFields: Use ' ' rather than 'T' as the delimiter between the date and time portions UTC: When converting from a Unix timestamp, return the time in the UTC timezone (normally it is returned in the local timezone). When using a Time this flag has no effect. " public data IsoTimeOpts = DateOnly | TimeOnly | WithTimeZone | ShortForm | TwoFields | UTC; "The Time A list of IsoTimeOpts options. This argument may be omitted and defaults to the empty list. The offset of the timezone from UTC in seconds. This argument is usually only used internally by isoTime for conversion from Unix timestamps Convert a Time-value into ISO-8601 format Returns a String containing the ISO-8601 representation of a Time. This can then be used in interoperation with various other systems. Time isoTime" public String isoTime (Time t, [IsoTimeOpts] opts = [], Int tzOffs = 0) { dateDelim = "-"; timeDelim = ":"; tz = ""; // In it's short form, the ISO-date has no delimiters (with the exception of // the delimiter between the date-part and the `time of day'-part ... if (ShortForm `elem` opts) { dateDelim = ""; timeDelim = ""; } // Set the delimiter used between the date- and the `time of day'-part ... dateTimeDelim = "T"; if (TwoFields `elem` opts) { dateTimeDelim = " "; } // Calculate the date-part and the `time of day'-part of the output ... dateRes = t.year + dateDelim + twodigits (int (t.mon)) + dateDelim + twodigits (t.mday); timeRes = twodigits (t.hour) + timeDelim + twodigits (t.minute) + timeDelim + twodigits (t.second); // If the output of the timezone is requested, generate it ... if (WithTimeZone `elem` opts) { if (tzOffs == 0) { tz = "Z"; } else { tz = "+"; if (tzOffs < 0) { tz = "-"; tzOffs = -tzOffs; } tz += twodigits (tzOffs / 3600) + timeDelim + twodigits ((tzOffs / 60) % 60); } } // return either the date-part ... if (DateOnly `elem` opts) { return dateRes; } // ... or the `time of day'-part ... if (TimeOnly `elem` opts) { return timeRes + tz; } // Return the full ISO-8601 compatible date/time string ... return join ([dateRes, timeRes + tz], dateTimeDelim); } "The Unix timestamp (seconds since 1970-01-01 00:00:00). A list of IsoTimeOpts options. This argument may be omitted and defaults to the empty list. Convert a Unix timestamp into ISO-8601 format Return an ISO-8601 format String representing the time from the Unix timestamp. The local timezone will be assumed (though not necessarily displayed) unless the UTC flag is in the opts array. Time isoTime" // CIM: removed default value for first parameter. now() makes sense // but because of the way function overloading works it's not possible as // isoTime() could refer to this or to the other. public String isoTime (Int secs, [IsoTimeOpts] opts = []) { // return the UTC if requested ... if (UTC `elem` opts) { return isoTime (gmTime (secs), opts); } // otherwise, calculate the cwlocal time, ... t = localTime (secs); // the timezone offset ... tzOffs = 0; if (WithTimeZone `elem` opts) { tzOffs = tzDist (secs); } // and generate the ISO-date/time format ... return isoTime (t, opts, tzOffs); } // return the distance between the current timezone and UTC ... // I chose this algorithm, because it seems quite independent from the // underlying OS ... Int tzDist (Int secs) { lt = localTime (secs); ut = gmTime (secs); dist = (lt.second - ut.second) + (lt.minute - ut.minute)*60 + (lt.hour - ut.hour)*3600; dayOffs = 0; if (lt.year != ut.year) { dayOffs = (if (lt.year > ut.year) 1 else -1); } else if (lt.mon != ut.mon) { dayOffs = (if (int (lt.mon) > int (ut.mon)) 1 else -1); } else if (lt.mday != ut.mday) { dayOffs = (if (lt.mday > ut.mday) 1 else -1); } return dist + dayOffs*86400; } kaya-0.4.4/stdlib/Mail.k0000644000175100017510000001224211170340770013070 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Sending mail via SMTP This module allows the sending of electronic mail to an SMTP server." module Mail; // Module for talking to an SMTP server // Maybe add IMAP/POP3 support later? import Prelude; import Net; import Strings; import Regex; import Time; "SMTP Connection handle." data SMTPConnection = SMTP(NetHandle h, String host); "Could not connect to SMTP server This Exception is thrown if the connection to the SMTP server failed." Exception CantConnect(); "Error description Error talking to SMTP server This Exception is thrown if the SMTP server returns an error." Exception SMTPError(String err); "Error description Badly-formed SMTP header This Exception is thrown if the mail headers are not correctly formed (for example, if they contain a newline)." Exception HeaderError(String err); "The email address to send the message from The email address to send the message to A list of name-value pairs for additional mail headers to send: consult RFC 2822 for further details. The body of the message. The hostname or IP address of the SMTP server (this is optional, and localhost will be used if it is not specified). The TCP port on the server to connect to (this is optional and the standard SMTP port of 25 will be used if it is not specified). Send a mail via SMTP Sends an email via SMTP as specified in the email. body = \"...\"; // text of message goes here headers = [(\"X-Mailer\",\"Kaya\"), (\"Subject\",\"Example Message\"), (\"Cc\",\"example2@kayalang.org\")]; sendmail(\"kaya@kayalang.org\",\"example1@kayalang.org\",headers,body); The To, From and Date headers are set automatically and do not need adding to the headers array. Only the body parameter may contain newlines. An Exception will be thrown if the header values are invalid, the SMTP server is unavailable, or the SMTP server rejects the message." public Void sendmail(String from, String whoto, [(String,String)] headers, String body, String server="localhost", Int port=25) { // check data and construct message blacklist = compile("[\r\n]",[IgnoreCase,Multiline]); if (quickMatch(blacklist,from)) { throw(HeaderError("From is "+from)); } if (quickMatch(blacklist,whoto)) { throw(HeaderError("To is "+whoto)); } msg = ""; for header in headers { if (quickMatch(blacklist,header.fst) || quickMatch(blacklist,header.snd)) { throw(HeaderError(header.fst+" is "+header.snd)); } msg += header.fst+": "+header.snd+"\n"; } msg += "From: "+from+"\n"; msg += "To: "+whoto+"\n"; msg += "Date: "+rfc2822Time(gmTime())+"\n\n"; // end headers msg += body; c = smtpConnect(server,port); smtpFrom(c,from); smtpRcpt(c,whoto); smtpData(c,msg); smtpClose(c); } // CIM: removed public status - the data type it returned was private, so // no-one could actually have used it as public anyway! "Create an SMTP connection" SMTPConnection smtpConnect(String host, Int port=25) { h = connect(TCP,host,port); rcvok = recv(h,255,30); if ((words(rcvok)[0])!="220") { throw(CantConnect); } send(h,"HELO "+host+"\n"); rcvok = recv(h,255,30); if ((words(rcvok)[0])!="250") { throw(CantConnect); } return SMTP(h,host); } Void smtpFrom(SMTPConnection c, String from) { send(c.h,"MAIL FROM:"+from+"\n"); rcvok = recv(c.h,255,30); if ((words(rcvok)[0])!="250") { throw(SMTPError(rcvok)); } } Void smtpRcpt(SMTPConnection c, String whoto) { addresses = split(",",whoto); for address in addresses { trim(address); send(c.h,"RCPT TO:"+address+"\n"); rcvok = recv(c.h,255,30); if ((words(rcvok)[0])!="250") { throw(SMTPError(rcvok)); } } } Void manglePeriod(var String stuff) { slines = lines(stuff); newstuff = ""; for x in slines { if (length(x) > 0 && head(x)=='.') { x = "."+x; } newstuff += x +"\n"; } stuff = newstuff; } // Send data. Returns message id. Void smtpData(SMTPConnection c, String stuff) { send(c.h,"DATA\n"); rcvok = recv(c.h,255,30); if ((words(rcvok)[0])!="354") { throw(SMTPError(rcvok)); } // Mangle stuff in case any lines start with a . manglePeriod(stuff); send(c.h,stuff+"\n"); send(c.h,".\n"); rcvok = recv(c.h,255,30); if ((words(rcvok)[0])!="250") { throw(SMTPError(rcvok)); } } Void smtpClose(SMTPConnection c) { send(c.h,"QUIT\n"); rcvok = recv(c.h,255,30); if ((words(rcvok)[0])!="221") { throw(SMTPError(rcvok)); } closeConnection(c.h); } kaya-0.4.4/stdlib/tls_glue.cc0000644000175100017510000001123311170340770014156 0ustar cimcim#include #include #include #include #include #include "tls_glue.h" #include "network_glue.h" #if LIBGNUTLS_VERSION_MINOR >= 2 #define GSESSTYPE gnutls_session_t #define GCERTTYPE gnutls_certificate_credentials_t #define GTRANTYPE gnutls_transport_ptr_t #define GDATTYPE gnutls_datum_t #define GX509TYPE gnutls_x509_crt_t #else #define GSESSTYPE gnutls_session #define GCERTTYPE gnutls_certificate_credentials #define GTRANTYPE gnutls_transport_ptr #define GDATTYPE gnutls_datum #define GX509TYPE gnutls_x509_crt #endif void* do_gnutls_makecred() { GCERTTYPE cred; gnutls_certificate_allocate_credentials (&cred); gnutls_certificate_set_verify_flags(cred,GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); return (void*)cred; } void do_addcert(void* vmptr, void* credptr, wchar_t* fn) { VMState* vm = (VMState*) vmptr; GCERTTYPE cred = (GCERTTYPE)credptr; int res = gnutls_certificate_set_x509_trust_file(cred,CSTRING(fn),GNUTLS_X509_FMT_PEM); if (res < 0) { vm->kaya_internalError(1); } } void do_verifycert(void* vmptr, void* sessptr, wchar_t* host) { VMState* vm = (VMState*) vmptr; GSESSTYPE sess = (GSESSTYPE) sessptr; unsigned int status; int ver = gnutls_certificate_verify_peers2(sess,&status); if (ver < 0) { vm->kaya_internalError(1); } else if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { vm->kaya_internalError(4); /* } else if (status & GNUTLS_CERT_SIGNER_NOT_CA) { vm->kaya_internalError(4); */ } else if (status & GNUTLS_CERT_INVALID) { vm->kaya_internalError(2); } else if (status & GNUTLS_CERT_REVOKED) { vm->kaya_internalError(3); } else { if (host != L"") { // verify the hostname unsigned int numcerts; const GDATTYPE* certs; GX509TYPE cert; if (gnutls_x509_crt_init(&cert) < 0) { vm->kaya_internalError(6); return; } certs = gnutls_certificate_get_peers(sess,&numcerts); if (numcerts == 0) { vm->kaya_internalError(6); return; } gnutls_x509_crt_import(cert,&certs[0],GNUTLS_X509_FMT_DER); if (!gnutls_x509_crt_check_hostname(cert,CSTRING(host))) { vm->kaya_internalError(5); } gnutls_x509_crt_deinit(cert); } } } void* do_gnutls_init(void* cred) { GSESSTYPE session; const int cert_type_priority[3] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 }; gnutls_init (&session, GNUTLS_CLIENT); gnutls_set_default_priority(session); gnutls_certificate_type_set_priority(session,cert_type_priority); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, (GCERTTYPE) cred); return (void*)session; } int do_gnutls_transport(void* rawtls, void* rawconn) { GSESSTYPE tls = (GSESSTYPE) rawtls; ConnInfo* c = (ConnInfo*) rawconn; gnutls_transport_set_ptr(tls, (GTRANTYPE) c->cid); return gnutls_handshake(tls); } // http://www.gnu.org/software/gnutls/manual/gnutls.html // gnutls_certificate_set_x509_trust_file // gnutls_certificate_verify_peers2() // /etc/ssl/certs/*.pem // takes a void*, length(void*) as does g._r._recv // so easy enough to make the binary versions void do_gnutls_put(void* rawtls, wchar_t* rawdat) { GSESSTYPE tls = (GSESSTYPE) rawtls; char* dat = CSTRING(rawdat); gnutls_record_send(tls,dat,strlen(dat)); } void do_gnutls_putbin(void* rawtls, void* rawdat, kint len) { GSESSTYPE tls = (GSESSTYPE) rawtls; gnutls_record_send(tls,(char*)rawdat,len); } void do_gnutls_putbyte(void* rawtls, kint byte) { GSESSTYPE tls = (GSESSTYPE) rawtls; char data = (char)byte; gnutls_record_send(tls,&data,1); } wchar_t* do_gnutls_get(void* rawtls, void* vmptr, kint rlen) { GSESSTYPE tls = (GSESSTYPE) rawtls; char buffer[rlen+1]; int ret = gnutls_record_recv(tls, buffer, rlen); if (ret < 0) { VMState* vm = (VMState*)vmptr; vm->kaya_internalError(ret); } buffer[ret] = '\0'; return KSTRING(buffer); } void* do_gnutls_getbin(void* rawtls, void* vmptr, KValue len) { GSESSTYPE tls = (GSESSTYPE) rawtls; char* buffer = (char*)GC_MALLOC_ATOMIC(sizeof(char)*4097); int ret = gnutls_record_recv(tls, buffer, 4096); if (ret < 0) { VMState* vm = (VMState*)vmptr; vm->kaya_internalError(ret); } KayaSetInt(len,ret); return (void*)buffer; } kint do_gnutls_getbyte(void* rawtls, void* vmptr) { GSESSTYPE tls = (GSESSTYPE) rawtls; char buffer[2]; int ret = gnutls_record_recv(tls, buffer, 1); if (ret < 0) { VMState* vm = (VMState*)vmptr; vm->kaya_internalError(ret); } return (kint)buffer[0]; } void do_gnutls_close(void* rawtls, void* rawcred) { GSESSTYPE tls = (GSESSTYPE) rawtls; GCERTTYPE cred = (GCERTTYPE) rawcred; gnutls_bye(tls, GNUTLS_SHUT_RDWR); gnutls_deinit(tls); gnutls_certificate_free_credentials(cred); } kaya-0.4.4/stdlib/Webapp.k0000644000175100017510000004461511170340770013435 0ustar cimcim/** -*-C-*-ish Webapp.k based on CGI.k from the Kaya standard library CGI.k Copyright (C) 2004, 2005 Edwin Brady Webapp.k Copyright (C) 2005 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Web application development The Webapp module allows the development of web applications with tight integration with the HTMLDocument module for high-quality HTML output (including auto-filling of forms), and secure state management." module Webapp; import public WebCommon; import Prelude; import Dict; import HTMLDocument; import ElementTree; import System; import Strings; import Crypto; import Regex; import IO; import Compress; import Binary; import Mime; import Time; // have we missed any of the standard library here? globals { Bool headersent = false; Bool debugmode = false; } "Bad handler function The Handler function was not properly specified in runHandler." Exception IllegalHandler(); "The key of the bad header The key of the bad value Malformed HTTP header key The HTTP header key is not valid. Only a limited set of characters are permitted." Exception BadHeadersKey(String key, String val); "Malformed HTTP header value The HTTP header value is not valid. New lines and control characters are not allowed." Exception BadHeadersVal(String key,String val); "Returns true if headers have been sent This function checks if the headers have been sent. It is only needed in the webapp template to correctly handle application errors." public Bool headersSent = headersent; "Check debugging mode Return whether the webprog is currently in debugging mode. You can use this check to display your own custom error messages. disableDebugging enableDebugging" public Bool debugMode = debugmode; "Enable debugging mode Enable debugging mode for the webapp. Note that this can potentially expose security-relevant information about your application and/or web server, so it's off by default and should remain that way for any production application. However, when testing a program as you write it you may find it useful to enable as it will give (among other features) better backtraces for uncaught Exceptions. debugMode enableDebugging" public Void enableDebugging() { debugmode = true; } "Disable debugging mode Disable debugging mode for the webapp. This is the default setting, so you should only need to call this if you have previously enabled debugging but only require it for one section of the webapp." public Void disableDebugging() { debugmode = false; } "The default function to run if none was specified. An optional prefix to allow multiple runHandler calls to coexist. Run the current state handler This runs the function called by the previous page of the application, or runs the provided default function if none was called. All functions called in this way must have the same return type. The default function takes no parameters, and all other functions take a single parameter representing the application state. The optional prefix allows handlers to have different namespaces, which allows multiple handler functions to safely coexist at various parts of the web application. Note that it is not possible for a single form submission or link to call more than one handler (though they will call the default function). HTMLDocument::addLocalControlInput" public b runHandler(b() defn, String prefix="") { // try POST first for svkey in incomingKeys(DataPost) { if (quickMatch("^"+prefix+"kaya_submit_",svkey)) { action = Int(substr(svkey,15+length(prefix),length(svkey)-(15+length(prefix)))); datavar = prefix+"kaya_control_Kay"+String(action); return doCalledFunction(incomingValue(datavar,DataPost),action,prefix); } } // then GET if (incomingExists(prefix+"kaya_control",DataGet)) { return doCalledFunction(incomingValue(prefix+"kaya_control",DataGet),228,prefix); } return defn(); // throw(IllegalHandler); // you should catch this and do a default function } "The default function to call if the state key does not exist. A function that returns the encoded state when given the key The key to find the state Retrieve saved state In some circumstances you may need to store application state in an external source, so that a user may save their session and return to it later. This function lets you retrieve a saved state from an external source based on a key. The function represented by the saved state is then executed. The retrieval function should throw an Exception if it can't find the key, which will cause the default function defn to be executed instead. Otherwise, it should, given the key, return the state string that was stored using storeFunction. One use of this is to generate links to be sent via email, where the links generated by Kaya containing the state data itself are too long to be practical. You should consider when writing the retrieval function whether the action of retrieving the state should delete it from the persistent storage. runHandler storeFunction" public b retrieveFunction(b() defn, String(String) retriever, String key) { try { state = retriever(key); return doCalledFunction(state,228); } catch(e) { return defn(); } } "A function that stores the state (which will be encoded as a String) and returns a key that can be used to retrieve it. The function to call when the state is retrieved. The state to pass to fn Save application state persistently. This lets you save application state and a handler function to an external source, and get a key to retrieve it later. The storage function should throw an exception if it is unable to store the state. Otherwise it should return a key that can be used with retrieveFunction to execute the state later. This lets you make URLs much shorter than is possibly by passing the state directly. You may need to consider expiring old and unused states from your persistent storage if they have not been retrieved for some time. runHandler retrieveFunction" public String storeFunction(String(String) storer, b(a) fn, a state) { enstate = encodeControlState(@fn,state); return storer(enstate); } private b doCalledFunction(String x, Int action, String prefix="") { dat = uncompressString(decode(x)); Triple fn = unmarshal(dat,action); if (prefix != fn.third) { // prefix doesn't match, so someone's trying something on. // types probably won't match either. throw(IllegalHandler); } return fn.fst(fn.snd); } "A HTMLDocument page Displays a HTML page Displays a HTML page. The displayPage functions are called automatically by a webapp based on the return value of webmain and should only be called directly for debugging purposes and when constructing custom displayPage functions. HTMLDocument::HTMLDocument displayPage (string data) displayPage (binary data) displayPage (void functions)" public Void displayPage(HTMLDocument page) { sendHeaders(page.httpheaders); putStr("\n"); // end headers write(page); if (debugmode) { putStrLn(""); } } // we have the generic String and Binary output methods here. Other modules // should have their own displayPage() functions for appropriate output. // HTMLDocument is above as an exception to this. "The string to output as the content A list of key-value pairs of HTTP headers Displays String content Displays String content. The displayPage functions are called automatically by a webapp based on the return value of webmain and should only be called directly for debugging purposes and when constructing custom displayPage functions. displayPage (HTML documents) displayPage (binary data) displayPage (void functions)" public Void displayPage(String sdata, [(String,String)] headers) { sendHeaders(headers); // last header Prelude::putStr("Content-length: "+length(sdata)+"\n\n"); Prelude::putStr(sdata); } "The binary block containing the content A list of key-value pairs of HTTP headers Displays binary data Displays binary data (for example an Image). The displayPage functions are called automatically by a webapp based on the return value of webmain and should only be called directly for debugging purposes and when constructing custom displayPage functions. The Image module contains its own displayPage function for image data, so you do not need to use this function. Binary::Binary Image displayPage (HTML documents) displayPage (string data) displayPage (void functions)" public Void displayPage(Binary bdata, [(String,String)] headers) { sendHeaders(headers); // last header Prelude::putStr("Content-length: "+blockSize(bdata)+"\n\n"); for i in [0..(blockSize(bdata)-1)] { ch = peek(bdata,i); putChar(stdout,Char(ch)); } } "A Void function taking no parameters that prints the content to standard output. A list of key-value pairs of HTTP headers Displays a function result Displays a function result. The displayPage functions are called automatically by a webapp based on the return value of webmain and should only be called directly for debugging purposes and when constructing custom displayPage functions. This function may be useful for output of very large amounts of content where reading the entire content into a string or binary block before printing it is not practical. displayPage (HTML documents) displayPage (string data) displayPage (binary data)" public Void displayPage(Void() fn, [(String,String)] headers) { sendHeaders(headers); putStr("\n"); // end headers fn(); } // check that headers are in reasonable format // let's not let people stick a response body in the headers, for example private Void sendHeaders([(String,String)] headers) { if (headersent) { return; } hkey = compile("[()<>@,;:\\\"/[\\]?={}[:cntrl:]\r\n]"); hval = compile("[[:cntrl:]\r\n]"); for header in headers { if (quickMatch(hkey,header.fst)) { throw(BadHeadersKey(header.fst,header.snd)); } if (quickMatch(hval,header.snd)) { throw(BadHeadersVal(header.fst,header.snd)); } Prelude::putStr(header.fst+": "+header.snd+"\n"); } headersent = true; } /* Begin auto-fill function set */ "The form element (or a subset of that if you only wish to automatically fill a part of the form. The data source to use (e.g. DataPost) An optional dictionary mapping keys to lists of values, to allow a form to be automatically filled from a database. You may or may not need to use DataNone as your main data source in this case. Automatically fill a HTML form Automatically fill a HTML form based on data from a particular data source. This makes it easy to construct web forms with error handling - see the webapp tutorial for more information. ElementTree OnHello(Int dummy) { div = anonymousBlock; // we create this temporarily. fname = incomingValue(\"fname\",DataPost); lname = incomingValue(\"lname\",DataPost); if (fname != \"\" && lname != \"\") { p = addParagraph(div,\"Hello \"+fname+\" \"+lname); return p; } else { form = HelloForm(); // if they entered one of first and last name, make sure it's still in the form autoFill(form,DataPost); return form; } } ElementTree helloForm() { parent = anonymousBlock; form = addLocalForm(parent); f1 = addFieldset(form,\"Who are you?\"); input = addLabelledInput(f1,\"Your First Name\",InputText,\"fname\",\"\",0); input = addLabelledInput(f1,\"Your Last Name\",InputText,\"lname\",\"\",0); submit = addLocalControlInput(f1,\"Say hello\",OnHello,1); return form; } WebCommon::DataSource" public Void autoFill (ElementTree form, DataSource mainvars, Dict extravars=Dict::new()) { if (elem(form.name,["input","select","textarea"])) { // fill each (text/check/radio/select/textarea) input found based on vars autoFillElement(form,mainvars,extravars); } else { // iterate (recursively?) through form for inputs for s in getChildren(form) { autoFill(s,mainvars,extravars); } } } Void autoFillElement(ElementTree input, DataSource mainvars, Dict extravars) { if (input.name == "input") { itype = HTMLDocument::getAttribute(input,"type"); case itype of { nothing -> autoFillTextInput(input, mainvars, extravars); | just(x) -> if (x == "text") { autoFillTextInput(input, mainvars, extravars); } else if (x == "checkbox" || x == "radio") { autoFillChoiceInput(input, mainvars, extravars); } } } else if (input.name == "select") { autoFillSelectInput(input, mainvars, extravars); } else if (input.name == "textarea") { autoFillArea(input,mainvars,extravars); } } [String] getVariables(String vname, DataSource mainvars, Dict extravars) { fromextra = lookup(extravars,vname); try { frommain = incomingData(vname,mainvars); case fromextra of { just(x) -> Array::concat(frommain,x); | nothing -> ; } return frommain; } catch(e) { case fromextra of { just(x) -> return x; | nothing -> throw(NotIncoming(vname)); } } } Void autoFillTextInput(ElementTree input, DataSource mainvars, Dict extravars) { name = HTMLDocument::getAttribute(input,"name"); case name of { nothing -> return; // strange... | just(x) -> try { vars = getVariables(x,mainvars,extravars); HTMLDocument::setAttribute(input,"value",vars[0]); // no sensible way to deal with text inputs with non-unique names } catch(e) { // HTMLDocument::setAttribute(input,"value",""); } } } Void autoFillChoiceInput(ElementTree input, DataSource mainvars, Dict extravars) { selname = "checked"; name = HTMLDocument::getAttribute(input,"name"); case name of { nothing -> return; // strange... | just(x) -> try { vars = getVariables(x,mainvars,extravars); val = HTMLDocument::getAttribute(input,"value"); case val of { nothing -> return; //strange... | just(x) -> if (elem(x,vars)) { HTMLDocument::setAttribute(input,selname,selname); // no sensible way to deal with text inputs with non-unique names } else { unsetAttribute(input,selname); } } } catch(e) { unsetAttribute(input,selname); } } } Void autoFillArea(ElementTree input, DataSource mainvars, Dict extravars) { name = HTMLDocument::getAttribute(input,"name"); input.elements = createArray(2); // clear the textarea. case name of { nothing -> return; // strange... | just(x) -> try { vars = getVariables(x,mainvars,extravars); addString(input,Strings::join(vars,'\n')); } catch(e) { return; } } } Void autoFillSelectInput(ElementTree input, DataSource mainvars, Dict extravars) { name = HTMLDocument::getAttribute(input,"name"); case name of { nothing -> return; // strange... | just(x) -> try { vars = getVariables(x,mainvars,extravars); setSelectsOptions(input,vars); } catch(e) { // unsetSelectsOptions(input); } } } Void unsetSelectsOptions(ElementTree input) { for s in getChildren(input) { if (s.name == "option") { unsetAttribute(s,"selected"); } else { // optgroup for opt in getChildren(s) { unsetAttribute(opt,"selected"); } } } } Void setSelectsOptions(ElementTree input, [String] vals) { for s in getChildren(input) { if (s.name == "option" ) { getval = HTMLDocument::getAttribute(s,"value"); case getval of { just(val) -> if (elem(val,vals)) { HTMLDocument::setAttribute(s,"selected","selected"); } else { unsetAttribute(s,"selected"); } | nothing -> ; // shouldn't happen in a KayHTML page } } else { // optgroup setSelectsOptions(s,vals); } } } /* End auto-fill functions */ kaya-0.4.4/stdlib/HTMLentities.k0000644000175100017510000002121711170340767014527 0ustar cimcim/** -*-C-*-ish HTMLentities.k Copyright (C) 2005 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "HTML named entity lookup A lookup table for the named HTML entities such as &amp;lsquo;" module HTMLentities; import Prelude; import Dict; globals { Dict::Dict namedents = makeNamedEnts(); } /* This module defines the HTML named entities. Separate module to make auto-generation easier */ "The entity name (for example pound or nbsp) Look up the character number for a named HTML entity Return the character number for a named HTML entity, or nothing if the name is not that of a HTML entity. This is mainly a helper function for the XMLentities module, though may occasionally be useful to call separately. XMLentities::entityToLiteral" public Maybe lookupEntity(String name) { return lookup(namedents,name); } private Dict makeNamedEnts() { entdict = Dict::new(379,strHash); // 250 named entities add(entdict,"nbsp",160); add(entdict,"iexcl",161); add(entdict,"cent",162); add(entdict,"pound",163); add(entdict,"curren",164); add(entdict,"yen",165); add(entdict,"brvbar",166); add(entdict,"sect",167); add(entdict,"uml",168); add(entdict,"copy",169); add(entdict,"ordf",170); add(entdict,"laquo",171); add(entdict,"not",172); add(entdict,"shy",173); add(entdict,"reg",174); add(entdict,"macr",175); add(entdict,"deg",176); add(entdict,"plusmn",177); add(entdict,"sup2",178); add(entdict,"sup3",179); add(entdict,"acute",180); add(entdict,"micro",181); add(entdict,"para",182); add(entdict,"middot",183); add(entdict,"cedil",184); add(entdict,"sup1",185); add(entdict,"ordm",186); add(entdict,"raquo",187); add(entdict,"frac14",188); add(entdict,"frac12",189); add(entdict,"frac34",190); add(entdict,"iquest",191); add(entdict,"Agrave",192); add(entdict,"Aacute",193); add(entdict,"Acirc",194); add(entdict,"Atilde",195); add(entdict,"Auml",196); add(entdict,"Aring",197); add(entdict,"AElig",198); add(entdict,"Ccedil",199); add(entdict,"Egrave",200); add(entdict,"Eacute",201); add(entdict,"Ecirc",202); add(entdict,"Euml",203); add(entdict,"Igrave",204); add(entdict,"Iacute",205); add(entdict,"Icirc",206); add(entdict,"Iuml",207); add(entdict,"ETH",208); add(entdict,"Ntilde",209); add(entdict,"Ograve",210); add(entdict,"Oacute",211); add(entdict,"Ocirc",212); add(entdict,"Otilde",213); add(entdict,"Ouml",214); add(entdict,"times",215); add(entdict,"Oslash",216); add(entdict,"Ugrave",217); add(entdict,"Uacute",218); add(entdict,"Ucirc",219); add(entdict,"Uuml",220); add(entdict,"Yacute",221); add(entdict,"THORN",222); add(entdict,"szlig",223); add(entdict,"agrave",224); add(entdict,"aacute",225); add(entdict,"acirc",226); add(entdict,"atilde",227); add(entdict,"auml",228); add(entdict,"aring",229); add(entdict,"aelig",230); add(entdict,"ccedil",231); add(entdict,"egrave",232); add(entdict,"eacute",233); add(entdict,"ecirc",234); add(entdict,"euml",235); add(entdict,"igrave",236); add(entdict,"iacute",237); add(entdict,"icirc",238); add(entdict,"iuml",239); add(entdict,"eth",240); add(entdict,"ntilde",241); add(entdict,"ograve",242); add(entdict,"oacute",243); add(entdict,"ocirc",244); add(entdict,"otilde",245); add(entdict,"ouml",246); add(entdict,"divide",247); add(entdict,"oslash",248); add(entdict,"ugrave",249); add(entdict,"uacute",250); add(entdict,"ucirc",251); add(entdict,"uuml",252); add(entdict,"yacute",253); add(entdict,"thorn",254); add(entdict,"yuml",255); add(entdict,"quot",34); add(entdict,"amp",38); add(entdict,"apos",39); add(entdict,"lt",60); add(entdict,"gt",62); add(entdict,"OElig",338); add(entdict,"oelig",339); add(entdict,"Scaron",352); add(entdict,"scaron",353); add(entdict,"Yuml",376); add(entdict,"circ",710); add(entdict,"tilde",732); add(entdict,"ensp",8194); add(entdict,"emsp",8195); add(entdict,"thinsp",8201); add(entdict,"zwnj",8204); add(entdict,"zwj",8205); add(entdict,"lrm",8206); add(entdict,"rlm",8207); add(entdict,"ndash",8211); add(entdict,"mdash",8212); add(entdict,"lsquo",8216); add(entdict,"rsquo",8217); add(entdict,"sbquo",8218); add(entdict,"ldquo",8220); add(entdict,"rdquo",8221); add(entdict,"bdquo",8222); add(entdict,"dagger",8224); add(entdict,"Dagger",8225); add(entdict,"permil",8240); add(entdict,"lsaquo",8249); add(entdict,"rsaquo",8250); add(entdict,"euro",8364); add(entdict,"fnof",402); add(entdict,"Alpha",913); add(entdict,"Beta",914); add(entdict,"Gamma",915); add(entdict,"Delta",916); add(entdict,"Epsilon",917); add(entdict,"Zeta",918); add(entdict,"Eta",919); add(entdict,"Theta",920); add(entdict,"Iota",921); add(entdict,"Kappa",922); add(entdict,"Lambda",923); add(entdict,"Mu",924); add(entdict,"Nu",925); add(entdict,"Xi",926); add(entdict,"Omicron",927); add(entdict,"Pi",928); add(entdict,"Rho",929); add(entdict,"Sigma",931); add(entdict,"Tau",932); add(entdict,"Upsilon",933); add(entdict,"Phi",934); add(entdict,"Chi",935); add(entdict,"Psi",936); add(entdict,"Omega",937); add(entdict,"alpha",945); add(entdict,"beta",946); add(entdict,"gamma",947); add(entdict,"delta",948); add(entdict,"epsilon",949); add(entdict,"zeta",950); add(entdict,"eta",951); add(entdict,"theta",952); add(entdict,"iota",953); add(entdict,"kappa",954); add(entdict,"lambda",955); add(entdict,"mu",956); add(entdict,"nu",957); add(entdict,"xi",958); add(entdict,"omicron",959); add(entdict,"pi",960); add(entdict,"rho",961); add(entdict,"sigmaf",962); add(entdict,"sigma",963); add(entdict,"tau",964); add(entdict,"upsilon",965); add(entdict,"phi",966); add(entdict,"chi",967); add(entdict,"psi",968); add(entdict,"omega",969); add(entdict,"thetasym",977); add(entdict,"upsih",978); add(entdict,"piv",982); add(entdict,"bull",8226); add(entdict,"hellip",8230); add(entdict,"prime",8242); add(entdict,"Prime",8243); add(entdict,"oline",8254); add(entdict,"frasl",8260); add(entdict,"weierp",8472); add(entdict,"image",8465); add(entdict,"real",8476); add(entdict,"trade",8482); add(entdict,"alefsym",8501); add(entdict,"larr",8592); add(entdict,"uarr",8593); add(entdict,"rarr",8594); add(entdict,"darr",8595); add(entdict,"harr",8596); add(entdict,"crarr",8629); add(entdict,"lArr",8656); add(entdict,"uArr",8657); add(entdict,"rArr",8658); add(entdict,"dArr",8659); add(entdict,"hArr",8660); add(entdict,"forall",8704); add(entdict,"part",8706); add(entdict,"exist",8707); add(entdict,"empty",8709); add(entdict,"nabla",8711); add(entdict,"isin",8712); add(entdict,"notin",8713); add(entdict,"ni",8715); add(entdict,"prod",8719); add(entdict,"sum",8721); add(entdict,"minus",8722); add(entdict,"lowast",8727); add(entdict,"radic",8730); add(entdict,"prop",8733); add(entdict,"infin",8734); add(entdict,"ang",8736); add(entdict,"and",8743); add(entdict,"or",8744); add(entdict,"cap",8745); add(entdict,"cup",8746); add(entdict,"int",8747); add(entdict,"there4",8756); add(entdict,"sim",8764); add(entdict,"cong",8773); add(entdict,"asymp",8776); add(entdict,"ne",8800); add(entdict,"equiv",8801); add(entdict,"le",8804); add(entdict,"ge",8805); add(entdict,"sub",8834); add(entdict,"sup",8835); add(entdict,"nsub",8836); add(entdict,"sube",8838); add(entdict,"supe",8839); add(entdict,"oplus",8853); add(entdict,"otimes",8855); add(entdict,"perp",8869); add(entdict,"sdot",8901); add(entdict,"lceil",8968); add(entdict,"rceil",8969); add(entdict,"lfloor",8970); add(entdict,"rfloor",8971); add(entdict,"lang",9001); add(entdict,"rang",9002); add(entdict,"loz",9674); add(entdict,"spades",9824); add(entdict,"clubs",9827); add(entdict,"hearts",9829); add(entdict,"diams",9830); return entdict; } kaya-0.4.4/stdlib/CONVENTIONS0000644000175100017510000000660011170340770013563 0ustar cimcimLibrary conventions ------------------- ECB, 17/03/06 Exported standard library function names should conform to the following conventions, for a consistent interface. These are vague and informal in some cases, as it is quite hard to give hard and fast guidelines for every function which hasn't been written yet - if in doubt, ask the mailing list (kaya-devel@lists.kayalang.org). I've derived these from the way the library has been implemented up to 0.2.0pre. If you'd like to make any changes or additions, please ask the mailing list first. * Function names with more than one word should be written likeThis, rather than like_this, and *definitely* not likethis. i.e. first word has no capital, subsequent words are capitalised. * Further to the above, keep function names as short as possible without abusing abbreviations. Keep typing to a minimum! * Do not use the module name in a function name; that's what namespaces are for. e.g. use Dict::new rather than newDict. * Constants (i.e. zero argument functions, including exceptions) should begin with a capital letter. * Coercions should have the same name as the data type, but should begin with a lowercase letter as normal. In certain cases, this convention may be stretched slightly. (so string rather than toString, but xyType is probably better than xYType or xytype for coercions to XYType) - use common sense when deciding where the word boundaries are. * verbNoun rather than nounVerb. (e.g. packString rather than stringPack) * Overload names provided that the names are used in a consistent way. Use caution when overloading common function names when the function type is not unique. * Use suffix 'At' for operations on a specific point in a data structure, (e.g. removeAt, addElementAt, etc). * If two functions are inverses, try to make this clear in the name (e.g. shift and unshift). * 'get' and 'set' prefixes are often just noise. Avoid, unless they are definitely a pair of functions. * Direct calls to standard C library functions might as well have C names (e.g. srand, mkdir). Data type names should conform to the following conventions * Data types with more than one word should be written LikeThis, rather than Like_This. * Where possible, a module written around one primary data structure (e.g. Dict or Binary) should have the same name as the data structure. Function behaviour ------------------ * Usually, it is better to use default arguments when a function has default behaviour which can be altered (e.g. sort's comparison operator). In cases where this is awkward (e.g. argument ordering, or slightly complicated default behaviour), use the suffix 'With', e.g. zipWith. * Throw an exception rather than returning a code on error. * Try to make it as clear as possible from the name whether a function modifies its argument in-place, or returns a new value. e.g. 'remove' should modify an array by removing elements, not return a copy of the array. * traverse functions in stdlib should not modify the original data Further coding conventions, being invisible to the kaya programmer, need not be strict. However, it would be good for each library module to be self-consistent, so try to conform to the convention of the module's original author. Miscreants ---------- Functions we've identified which break the above conventions (last updated 25/03/06): - feel free to add some if you find them! kaya-0.4.4/stdlib/Strings.k0000644000175100017510000003336611170340770013651 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "String processing functions This module contains string processing functions." module Strings; import Regex; import Prelude; %include "string.h"; %include "stdlib.h"; foreign "stdfuns.o" { String b64enc(String block, Int len) = b64enc; String b64dec(String str, intval len) = b64dec; "The character to check for The string to check Check if a character appears in a string Returns true if the character appears in the String, false otherwsie. Array::elem firstOccurs" public Bool elem(Char c, String str) = do_wcschr; "The character to check for The string to check Return the position of the first occurence of a character Returns the position of the first occurence of the character in the string (or the length of the string if the character is not in the string). str = \"abcdefgabcde\"; i = firstOccurs('a',str); // i = 0 i = firstOccurs('d',str); // i = 3 i = firstOccurs('h',str); // i = 12 elem firstOccurs" public Int firstOccurs(Char c, String str) = do_wcscspn; Int do_firstOccurs(String needle, String haystack) = do_wcsstr; Void str_offset(str x, Int inc) = str_offset; Void str_chop(str x, Int inc) = str_chop; } "The string to check for The string to check Return the position of the first occurence of a substring Returns the position of the first occurence of the needle substring in the haystack string (or the length of the string if the substring is not in the string). str = \"abcdefgabcde\"; i = firstOccurs(\"ab\",str); // i = 0 i = firstOccurs(\"de\",str); // i = 3 i = firstOccurs(\"efa\",str); // i = 12 firstOccurs" public Int firstOccurs(String needle, String haystack) { i = do_firstOccurs(needle,haystack); if (i == -1) { return length(haystack); } return i; } // Is this used/useful? (ECB 14/1/07) // not any more - only head() ever used it and that doesn't now // Exception EmptyString(); // is there any reason not to use Regex::split(R"\s+") instead? R"The string to split Split a String into words. Splits a String into whitespace separated words. x = \"The quick brown fox jumps\n\tover the lazy dog\"; ws = words(x); // [\"The\",\"quick\",\"brown\",\"fox\",\"jumps\", // \"over\",\"the\",\"lazy\",\"dog\"]; lines Regex::split unwords" public [String] words(String x) { [String] all = []; str = x; current = ""; while (str!="") { c = head(str); str = tail(str); if (isSpace(c)) { if (current!="") { all[size(all)]=current; current = ""; } } else { current = current + String(c); } } if (current!="") { all[size(all)]=current; } return all; } r"The string to split A function to select characters to split on, that returns true if it should split at this point, and false otherwise. Defaults to Prelude::isLineEnding if omitted (though in this case the lines function should probably be used). Split a String into substrings Split a String into substrings by a given delimiter predicate or newline if none is given. Consecutive delimiters will give empty substrings. x = \"abc\n\ndef\"; xs = splitBy(x,isLineEnding); // [\"abc\",\"\",\"def\"] join lines words" [String] splitBy(String x, Bool(Char) d=isLineEnding) { [String] all = []; str = x; current = ""; while (str!="") { c = head(str); str = tail(str); if (d(c)) { all[size(all)]=current; current = ""; } else { current = current + String(c); } } if (current!="") { all[size(all)]=current; } return all; } "The String to split Splits a string into lines Split a String into lines. This function correctly processes Windows, Unix and Mac line-ending conventions. join" public [String] lines(String x) { // otherwise windows line endings get split wrongly replace("\r\n","\n",x,[Global]); return splitBy(x,isLineEnding); } "A list of Strings Join a list of words into a String. Join a list of words into a String. xs = [\"Hello\",\"World!\"]; x = unwords(xs); // \"Hello World!\" join words" public String unwords([String] xs) = Strings::join(xs,' '); "A list of words The separator to use. This may be omitted and defaults to a newline. Join a list of words into a String with the specified separator Join a list of words into a String with the given separator or newline if none is given. join unwords" public String join([String] xs, Char c='\n') { if (size(xs) == 0) { return ""; } // needed to avoid substr exception acc=""; for x in xs { acc += x + String(c); } // since the separator is a single character, this trims the unwanted trailing separator return substr(acc,0,length(acc)-1); } "A list of words The separator to use. This may be omitted and defaults to a newline. Join a list of words into a String with the specified separator Join a list of words into a String with the given separator or newline if none is given. join unwords" public String join([String] xs, String s) { if (size(xs) == 0) { return ""; } // needed to avoid substr exception acc=""; for x in xs { acc += x + s; } // trims the unwanted trailing separator return substr(acc,0,length(acc)-length(s)); } "The String Get the first character in a String Get the first character in a String tail" public Char head(String s) { /* if (length(s) == 0) { // getIndex does this check throw(StringEmpty); }*/ return getIndex(s,0); } "The String Get the first character in a String Get all but the first character in a String. Useful with head for iteration over strings. str = \"abcdef\"; i = 0; do { i += Int(head(str)); str = tail(str); } while (length(str) > 0); head ltruncate" public String tail(String str) = strEnd(str,1); "The predicate function. The String to filter Filter a string according to a predicate. Each character in str is tested against the predicate p. The returned string contains those characters in str for which the predicate is true." public String filter(Bool(Char) p, String str) { newstr = ""; for x in [0..length(str)-1] { c = getIndex(str,x); if (p(c)) newstr+=c; } return newstr; } "The number of characters to remove The String to remove from Remove characters from the left of a string, in-place. Remove the first i characters from a string, in-place. behead rtruncate" public Void ltruncate(Int i, String x) { if (i<0 || i > length(x)) { throw(OutOfBounds); } str_offset(x,i); } "The number of characters to remove The String to remove from Remove characters from the right of a string, in-place. Remove the last i characters from a string, in-place. ltruncate" public Void rtruncate(Int i, String x) { if (i<0 || i > length(x)) { throw(OutOfBounds); } str_chop(x,i); } "The String to remove from Remove the first character of a string, in-place. Remove the first character of a string, in-place. ltruncate" public Void behead(String x) { ltruncate(1,x); } "The string to trim The trimming function. Returns true if characters should be trimmed, false otherwise. The default function is Prelude::isSpace which trims whitespace. Trim selected characters from the end of a String Remove characters in-place from the end of a String as determined by the trimming function. ltrim trim" public Void rtrim(var String x, Bool(Char) fn=isSpace) { while (length(x) > 0 && fn(getIndex(x,length(x)-1))) { x=substr(x,0,length(x)-1); } } "The string to trim The trimming function. Returns true if characters should be trimmed, false otherwise. The default function is Prelude::isSpace which trims whitespace. Trim selected characters from the start of a String Remove characters in-place from the start of a String as determined by the trimming function. rtrim trim" public Void ltrim(var String x, Bool(Char) fn=isSpace) { while (length(x) > 0 && fn(head(x))) { behead(x); } } "The string to trim The trimming function. Returns true if characters should be trimmed, false otherwise. The default function is Prelude::isSpace which trims whitespace. Trim selected characters from both ends of a String Remove characters in-place from both ends of a String as determined by the trimming function. str = \" this string needs trimming \"; trim(str); // str = \"this string needs trimming\"; ltrim rtrim" public Void trim(var String x, Bool(Char) fn=isSpace) { ltrim(x,fn); rtrim(x,fn); } "The string to encode Base64 encode a string Encodes the input string in base64 encoding, and returns the encoded string. base64Decode Binary::base64Encode" public String base64Encode(String str) { return b64enc(str,length(str)); } "The string to decode Base64 decode a string Decodes the input string, which must be in base64 encoding, and returns the original data. base64Encode Binary::base64Decode" public String base64Decode(String str) { len=0; return b64dec(str,len); } "The input string A list of characters that are treated as delimiters Characters that escape the string - i.e. delimiters between two escape characters are treated as literal characters. Split a string into fields This function splits a string into fields. For example, to split a CSV file, you could use fields(input,[',','\\n'],['\"']);. This will treat commas and newlines as field separators, except within quoted strings. Regex::split" public [String] fields(String input, [Char] delimiters, [Char] escape) { escstate = false; chars = array(input); strings = []; idx = 0; inited = false; for char in chars { if (elem(char,escape)) { escstate = !escstate; } else if (!escstate && elem(char,delimiters)) { if (!inited) { // initialise it here strings[idx] = createString(1); } idx++; inited = false; } else { if (!inited) { inited = true; strings[idx] = ""; } strings[idx] += String(char); } } return strings; } kaya-0.4.4/stdlib/ElementTreeData.k0000644000175100017510000000716211170340770015216 0ustar cimcim/** -*-C-*-ish ElementTreeData.k Copyright (C) 2005 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Data types for representation of XML and XML-like trees This module contains data types for the representation of XML and XML-like tree structures. The HTMLDocument and KayaDoc modules both use this package." module ElementTreeData; import public Dict; // isempty is true for things like
    (or
    if it's an XML // representation) "An element and its descendants This data type represents a node in the tree and its descendants (in XML, an element and its contents). The elements field is a list of the descendant Elements, the name field is the name of the element, and the attributes field is a dictionary of attribute names and values. attrs = newTiny(); add(attrs,\"title\",\"Hello\"); el = ElementTree(subs,\"example\",attrs); // converts to a string as // <example title=\"Hello\">...contents of subs here...</example>" public data ElementTree([Element] elements, String name, TinyDict attributes); "Types of element This data type represents the three different types of descendant elements that an ElementTree may contain: SubElement: a descendant ElementTree CData: an anonymous string of text SubTree: a function that returns an ElementTree, for lazy generation of trees." public data Element = SubElement(ElementTree nested) | CData(String cdata) | SubTree(ElementTree() generator); // we use CData a little sloppily here - it's just string data, not // necessarily the XML CData type. // no longer used // Exception ElementParseError(); "Controls printing of empty elements This data type is used by ElementTree::string and ElementTree::lazyPrint to control the printing of empty elements (i.e. elements that are defined as empty, not merely elements that happen to have no content). Singleton or OpenAndClose are both usable in XML (Singleton is usually more readable). If you are using this module to generate HTML (or other non-XML-based markup languages) then ImpliedSingleton should be used. The following list shows how each displays an empty br element. Singleton: <br /> ImpliedSingleton: <br> OpenAndClose: <br></br> " public data EmptyTagMode = Singleton | ImpliedSingleton | OpenAndClose; //"Controls code formatting." //public data PrettyFormat = NoBreak | OuterBreak | FullBreak; // replaced with Bool breaks "Controls the output format of non-ASCII characters Characters in Unicode that are not in ASCII can either be output as literal characters (LiteralUTF8) or as a numeric entity reference (NumericReference). Entity references give a larger file but will continue if the output will be used in an environment where the character encoding is not UTF-8 (for example, if the output is inserted into a HTML document in a different encoding)" public data UnicodeFormat = LiteralUTF8 | NumericReference; kaya-0.4.4/stdlib/Compress.k0000644000175100017510000001066711170340767014020 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Data compression and uncompression This module provides an interface to zlib to allow the compression and uncompression of Strings or Binary data." module Compress; import Regex; import Prelude; import Strings; import Binary; %include "zlib_glue.h"; %imported "zlib_glue"; %link "z"; foreign "zlib_glue.o" { Ptr compressBuffer(Ptr vm, Ptr ind, Int len, outint buflen) = compressBuffer; Ptr uncompressBuffer(Ptr vm, Ptr ind, Int len, outint buflen) = uncompressBuffer; } "Error uncompressing data Thrown if there is an error uncompressing the data uncompressBinary uncompressString" Exception UncompressionFailed(); "Error compressing data Thrown if there is an error compressing the data compressBinary compressString" Exception CompressionFailed(); "The block to compress Compress a block of binary data. Compress a block of binary data using zlib. The compressed block will be returned. If compression fails, a CompressionFailed Exception will be thrown. uncompressBinary compressString" public Binary compressBinary(Binary b) { initlen = blockSize(b); buflen = 0; dat = compressBuffer(getVM(), blockData(b), initlen, buflen); return createInitialisedBlock(dat, buflen); } "The block to uncompress The expected uncompressed length Uncompress a block of binary data. Uncompress a block of binary data that has been compressed with compressBinary. The uncompressed block will be returned. If uncompression fails, a UncompressionFailed Exception will be thrown. If the real uncompressed length is larger than the expected length, uncompression will fail. If it is smaller, this is wasted memory. compressBinary uncompressString" public Binary uncompressBinary(Binary b, var Int outlen) { newdat = uncompressBuffer(getVM(), blockData(b), blockSize(b), outlen); return createInitialisedBlock(newdat, outlen); } "The String to compress Compress a string. Compress a string using zlib and returned a base64-encoded compressed string. If compression fails, a CompressionFailed Exception will be thrown. Note that because base64-encoding increases the space required, if the compression factor is small, the compressed string may be larger than the original! In this case converting the string to Binary form and using compressBinary may be better. compressBinary uncompressString" public String compressString(String instr) { initlen = byteLength(instr)+1; b = createBlock(initlen); pokeString(b,0,instr); bin = compressBinary(b); outstr = String(initlen)+"\n"+Binary::base64Encode(bin); return outstr; } "The String to uncompress Uncompress a string. Uncompress a string generated with compressString. If uncompression fails, a UncompressionFailed Exception will be thrown. Unlike uncompressBinary you do not have to guess or record an uncompressed size, as compressed strings store this information internally (if the string is corrupted, then this information may be wrong, so uncompression will fail with an Exception) uncompressBinary compressString" public String uncompressString(String instr) { odata = split("\n",instr); bin = Binary::base64Decode(odata[1]); raw = uncompressBinary(bin,Int(odata[0])); return peekString(raw,0); } kaya-0.4.4/stdlib/Makefile.in0000644000175100017510000001302111170340770014073 0ustar cimcimRVPATH=@srcdir@ VPATH=${RVPATH} LANGNAME = @LANGNAME@ KAYAC = ../compiler/@TARGET@ prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@/${LANGNAME} LIBDIR = ${libdir} IMPORTDIR = ${libdir}/imports CXXFLAGS = @FPIC@ @EXTRAGCCOPTS@ -I../rts @INTERPROF@ @HASUTF8@ -I${VPATH}/../rts KAYAINC = @KAYAPROF@ -noenvlibs -I../rts -I${VPATH}/../rts KAYAFLAGS = -noprelude -nochase ${KAYAINC} -nortchecks -L ../rts_opt -L ../rts -xmldocs -L ${VPATH} -L ${VPATH}/../rts INSTALLFLAGS = -m 644 LIBTARGET = lib@LANGNAME@std.so lib@LANGNAME@web.so lib@LANGNAME@re.so LIBSTATIC = lib@LANGNAME@std.a lib@LANGNAME@web.a lib@LANGNAME@re.a LIBINFO = @LANGNAME@std.ddl @LANGNAME@web.ddl @LANGNAME@re.ddl SRCS = Array.@EXT@ Strings.@EXT@ IO.@EXT@ System.@EXT@ Regex.@EXT@ \ Prelude.@EXT@ CGI.@EXT@ Builtins.@EXT@ Dict.@EXT@ Maths.@EXT@ \ Coercions.@EXT@ Crypto.@EXT@ Time.@EXT@ Logger.@EXT@ \ DB.@EXT@ Binary.@EXT@ Tuples.@EXT@ Set.@EXT@ \ Lazy.@EXT@ Parse.@EXT@ WebCommon.@EXT@ \ HTMLDocument.@EXT@ ElementTree.@EXT@ ElementTreeData.@EXT@ \ HTMLnesting.@EXT@ XMLentities.@EXT@ HTMLentities.@EXT@ \ Webapp.@EXT@ Net.@EXT@ HTTP.@EXT@ Mail.@EXT@ TLS.@EXT@ \ Compress.@EXT@ Testing.@EXT@ Queue.@EXT@ Mime.@EXT@ Reflect.@EXT@ \ Pickle.@EXT@ KayaDoc.@EXT@ IFACE = Array.ki Strings.ki IO.ki System.ki Regex.ki Prelude.ki \ CGI.ki Builtins.ki Dict.ki Maths.ki Crypto.ki \ Coercions.ki DB.ki Time.ki Logger.ki Binary.ki Tuples.ki \ Lazy.ki Parse.ki Gcrypt.ki Set.ki \ HTMLDocument.ki ElementTree.ki ElementTreeData.ki \ HTMLnesting.ki XMLentities.ki HTMLentities.ki \ Webapp.ki WebCommon.ki Net.ki HTTP.ki Mail.ki TLS.ki \ Compress.ki Testing.ki Queue.ki Mime.ki Reflect.ki \ Pickle.ki KayaDoc.ki STDOBJS = Array.o Strings.o IO.o System.o Prelude.o \ Builtins.o Dict.o Maths.o Coercions.o \ DB.o Time.o Logger.o Binary.o Tuples.o Set.o \ Lazy.o Parse.o Testing.o tls_glue.o \ binary_glue.o Net.o HTTP.o Mail.o network_glue.o TLS.o \ Compress.o Queue.o zlib_glue.o Mime.o Reflect.o Pickle.o WEBOBJS = CGI.o Crypto.o Gcrypt.o gcrypt_glue.o crypto_glue.o \ HTMLDocument.o ElementTree.o ElementTreeData.o \ HTMLnesting.o XMLentities.o HTMLentities.o \ Webapp.o WebCommon.o KayaDoc.o REOBJS = Regex.o regex_glue.o OBJS = ${STDOBJS} ${WEBOBJS} ${REOBJS} #${TARGET}: ${LIBTARGET} # ${CXX} -fpic ${CXXFLAGS} -shared ${OBJS} -o ${TARGET} all: ${OBJS} dynlink: ${LIBTARGET} #${LIBTARGET}: ${OBJS} # ../tools/dynlink @LANGNAME@std ${STDOBJS} # ../tools/dynlink @LANGNAME@web -lssl -lcrypt -lcgi ${WEBOBJS} # ../tools/dynlink @LANGNAME@re -lpcre ${REOBJS} install: mkdir -p ${DESTDIR}${libdir} mkdir -p ${DESTDIR}${IMPORTDIR} # install ${TARGET} ${LIBDIR} # install ${LIBTARGET} ${LIBSTATIC} ${LIBINFO} ${LIBDIR} install ${INSTALLFLAGS} ${IFACE} ${DESTDIR}${IMPORTDIR} install ${INSTALLFLAGS} ${OBJS} ${DESTDIR}${IMPORTDIR} clean: rm -f ${OBJS} ${IFACE} ${LIBTARGET} ${TARGET} rm -f *.html *.xml rm -rf docs distclean: clean rm -f *~ Makefile Net.k rm -rf autom4te.cache Mime.o: Binary.ki Strings.ki IO.ki Regex.ki Compress.o: Binary.ki zlib_glue.h Strings.ki Regex.ki Reflect.o: Builtins.ki Prelude.ki Pickle.o: Prelude.ki Binary.ki Reflect.ki Strings.ki Parse.ki KayaDoc.o: ElementTree.ki Strings.ki HTMLDocument.ki Time.ki Regex.ki ElementTreeData.o: Dict.ki ElementTree.o: XMLentities.ki ElementTreeData.ki Regex.ki XMLentities.o: HTMLentities.ki Dict.ki Strings.ki Prelude.ki HTMLentities.o: Dict.ki HTMLnesting.o: Set.ki HTMLDocument.o: Prelude.ki System.ki Crypto.ki Regex.ki \ WebCommon.ki Strings.ki Dict.ki XMLentities.ki ElementTree.ki \ HTMLnesting.ki Compress.ki Webapp.o: Prelude.ki System.ki Crypto.ki Regex.ki \ WebCommon.ki Strings.ki Dict.ki HTMLDocument.ki Mime.ki WebCommon.o: Time.ki Dict.ki Regex.ki System.ki IO.ki Mime.ki Dict.o: Prelude.ki CGI.o: Prelude.ki System.ki Crypto.ki Regex.ki WebCommon.ki Strings.o: Prelude.ki Regex.ki Array.o: Builtins.ki Tuples.ki Coercions.o: Builtins.ki Array.ki Crypto.o: crypto_glue.h Gcrypt.ki Regex.ki Gcrypt.o : gcrypt_glue.h Binary.ki Prelude.ki Regex.o: regex_glue.h Prelude.ki Time.o: Builtins.ki Strings.ki Regex.ki Mail.o: Time.ki Binary.o: binary_glue.h IO.ki Logger.o: Prelude.ki IO.ki Regex.ki Time.ki Lazy.o: Prelude.ki Parse.o: Prelude.ki Regex.ki Strings.ki Signal.o: signal_glue.h Net.o: TLS.ki Regex.ki network_glue.h TLS.o: tls_glue.h Binary.ki HTTP.o: Net.ki WebCommon.ki Mail.o: Net.ki Testing.o: Prelude.o IO.o Regex.ki Time.ki Queue.o: Prelude.o Set.o: Prelude.o DB.o: Prelude.ki Time.ki Regex.ki IO.o: Prelude.ki System.o: Array.ki network_glue.o: network_glue.h zlib_glue.o: zlib_glue.h tls_glue.o: tls_glue.h network_glue.h crypto_glue.o: crypto_glue.h gcrypt_glue.o: gcrypt_glue.h regex_glue.o: regex_glue.h webapp_glue.o: webapp_glue.h binary_glue.o: binary_glue.h signal_glue.o: signal_glue.h #Prelude.o: Prelude.ki Builtins.ki Maths.ki Array.ki Prelude.o : Prelude.@EXT@ Builtins.ki Maths.ki Array.ki Coercions.ki # This is quite a conservative dependency # (ECB 23/6/06) I think it's too conservative. It's a pain during # development of the compiler, and in the cases where a rebuild of the # library is needed, due to changes in the compiler, it doesn't catch # them all. I'm happy to make klibclean instead where necessary, and # it shouldn't be an issue for users. # Builtins.o: ../compiler/kayac ../rts/libkayavm.a # ${KAYAC} Prelude.k -noprelude -nochase -o Prelude.o -nortchecks -L ../rts_opt -L ../rts -htmldocs %.o : %.@EXT@ ${KAYAC} $< ${KAYAFLAGS} -deprfail %.ki : %.o @: kaya-0.4.4/stdlib/network_glue.cc0000644000175100017510000001600611170340770015050 0ustar cimcim using namespace std; #include #include #include "network_glue.h" #include #include #include #include #ifdef WIN32 #define SHUT_RDWR SD_BOTH #endif // this function does nothing on Unix but should be called anyway // for compatibility. void net_init(void* vmptr) { #ifdef WIN32 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { VMState* vm = (VMState*)vmptr; vm->kaya_internalError(7); } #endif } /// Create a socket and connect to the server. Returns connection info. void* net_connect(void* vmptr, int proto,wchar_t* rawserver, int port) { char* server = CSTRING(rawserver); VMState* vm = (VMState*)vmptr; int sock; struct sockaddr_in addr; switch(proto) { case 1: sock=socket(PF_INET,SOCK_STREAM,0); addr.sin_family=AF_INET; break; // case 2: // sock=socket(PF_INET6,SOCK_STREAM,0); // addr.sin_family=AF_INET6; // break; default: vm->kaya_internalError(8); } struct hostent * hostinfo; hostinfo=gethostbyname(server); if (hostinfo==NULL) { #ifdef WIN32 vm->kaya_internalError(9); // ,WSAGetLastError()); #else vm->kaya_internalError(9); #endif } addr.sin_addr=*(struct in_addr *)hostinfo->h_addr; addr.sin_port=htons(port); if (connect(sock,(struct sockaddr *)(&addr),sizeof(struct sockaddr_in))==-1) { vm->kaya_internalError(10); } ConnInfo *c = new ConnInfo(); c->cid = sock; c->addr = addr; c->addrlen = sizeof(struct sockaddr_in); // Make it non blocking // fcntl(sock,F_SETFL,O_NONBLOCK); return (void*)c; } /// Create a socket and start listening. Returns socket id. int net_listen(void* vmptr,int proto, int port, int backlog) { VMState* vm = (VMState*)vmptr; int sock; struct sockaddr_in name; switch(proto) { case 1: sock=socket(PF_INET,SOCK_STREAM,getprotobyname("tcp")->p_proto); name.sin_family = AF_INET; break; // case 2: // sock=socket(PF_INET6,SOCK_STREAM,getprotobyname("tcp")->p_proto); // name.sin_family = AF_INET6; // break; default: vm->kaya_internalError(8); } #ifdef WIN32 BOOL val=TRUE; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&val,sizeof(int)); #else int val=1; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(int)); setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(int)); fcntl(sock,F_SETFL,O_NONBLOCK); #endif name.sin_port = htons(port); name.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sock,(struct sockaddr *)(&name),sizeof(struct sockaddr_in))) { vm->kaya_internalError(1); } if (listen(sock,backlog)) { vm->kaya_internalError(2); } return sock; } bool net_connwaiting(void* vmptr, int socket, kint timeout) { VMState* vm = (VMState*)vmptr; fd_set rfds; struct timeval tv; FD_ZERO(&rfds); FD_SET(socket,&rfds); tv.tv_sec = timeout/1000000; tv.tv_usec = timeout%1000000; int rv; do { rv = select(socket+1,&rfds,NULL,NULL,&tv); } while ((rv == -1) && (errno == EINTR)); if (rv==-1) { vm->kaya_internalError(6); } else { return rv; } } /// Accept a connection. Returns connection info. void* net_accept(void* vmptr,int socket) { VMState* vm = (VMState*)vmptr; struct sockaddr_in addr; socklen_t len = sizeof(struct sockaddr_in); int client = accept(socket,(struct sockaddr *)&addr,&len); if (client==-1) { vm->kaya_internalError(3); } ConnInfo *c = new ConnInfo(); c->cid = client; c->addr = addr; c->addrlen = len; return (void*)c; } /// Shutdown a connection. void net_shutdown(void* conn) { ConnInfo* c = (ConnInfo*)conn; shutdown(c->cid, SHUT_RDWR); } /// Close a socket. void net_close(void* vmptr, void* conn) { ConnInfo* c = (ConnInfo*)conn; VMState* vm = (VMState*)vmptr; int r; do { r = close(c->cid); } while ((r == -1) && (errno == EINTR)); if (r < 0) { vm->kaya_internalError(11); } } void net_send(void* vmptr,void* conn, wchar_t* rawdata) { char* data = CSTRING(rawdata); VMState* vm = (VMState*)vmptr; ConnInfo* c = (ConnInfo*)conn; int rlen; do { rlen = send(c->cid, data,strlen(data),0); } while ((rlen == -1) && (errno == EINTR)); if (rlen<0) { vm->kaya_internalError(4); } } void net_sendchars(void* vmptr,void* conn, void* data, kint len) { VMState* vm = (VMState*)vmptr; ConnInfo* c = (ConnInfo*)conn; int rlen; do { rlen = send(c->cid, (char*)data,len,0); } while ((rlen == -1) && (errno == EINTR)); if (rlen<0) { vm->kaya_internalError(4); } } void net_sendbyte(void* vmptr,void* conn, kint byte) { VMState* vm = (VMState*)vmptr; ConnInfo* c = (ConnInfo*)conn; int rlen; char data = (char)byte; do { rlen = send(c->cid, &data,1,0); } while ((rlen == -1) && (errno == EINTR)); if (rlen<0) { vm->kaya_internalError(4); } } wchar_t* net_recv(void* vmptr,void* conn, KayaValue len) { VMState* vm = (VMState*)vmptr; ConnInfo* c = (ConnInfo*)conn; int lenval = KayaGetInt(len); char buf[lenval+1]; memset((void*)buf,0,(lenval+1)*sizeof(char)); int rlen; do { rlen = recv(c->cid, buf,lenval,0); } while ((rlen == -1) && (errno == EINTR)); KayaSetInt(len,rlen); if (rlen<0) { // cout << rlen << endl; // buf[0]='\0'; vm->kaya_internalError(5); } return KSTRING(buf); } void* net_recvchars(void* vmptr,void* conn, KayaValue len) { VMState* vm = (VMState*)vmptr; ConnInfo* c = (ConnInfo*)conn; int lenval = KayaGetInt(len); char* buf = (char*)GC_MALLOC_ATOMIC((lenval+1)*sizeof(char)); memset((void*)buf,0,(lenval+1)*sizeof(char)); int rlen; do { rlen = recv(c->cid, buf,lenval,0); } while ((rlen == -1) && (errno == EINTR)); KayaSetInt(len,rlen); if (rlen<0) { // cout << rlen << endl; // buf[0]='\0'; vm->kaya_internalError(5); } return (void*)buf; } kint net_recvbyte(void* vmptr,void* conn) { VMState* vm = (VMState*)vmptr; ConnInfo* c = (ConnInfo*)conn; char buf[2]; int rlen; do { rlen = recv(c->cid, &buf[0],1,0); } while ((rlen == -1) && (errno == EINTR)); if (rlen<0) { // cout << rlen << endl; // buf[0]='\0'; vm->kaya_internalError(5); } return (kint)buf[0]; } wchar_t* net_getaddr(void* conn) { ConnInfo* c = (ConnInfo*)conn; struct in_addr addr = c->addr.sin_addr; char* h = inet_ntoa(addr); return KSTRING(h); } bool net_pending(void* vmptr,void* conn, int timeout) { VMState* vm = (VMState*)vmptr; ConnInfo* c = (ConnInfo*)conn; fd_set rfds; struct timeval tv; FD_ZERO(&rfds); FD_SET(c->cid,&rfds); tv.tv_sec = timeout/1000000; tv.tv_usec = timeout%1000000; int rv; do { rv = select(c->cid+1,&rfds,NULL,NULL,&tv); } while ((rv == -1) && (errno == EINTR)); if (rv==-1) { vm->kaya_internalError(6); } else { return rv; } } kaya-0.4.4/stdlib/Testing.k0000644000175100017510000003323111170340770013624 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004-2006 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ /// Support for unit test creation. "Unit testing support library This module contains functions for development of unit testing libraries. Tests are defined with add, and then the test set is run with run program test; Bool predicate(Int a) = (a%2 == 0); Void() test1() { xs = randomIntArray(10,1000); ys = filter(predicate,xs); assert(all(predicate,ys)); } Void main() { init(); add(@test1,10,\"Filtering\"); run(); } Note that random values in this module are generated using Builtins::rand, a generator with high speed but poor quality. For higher quality random values, consider using Lfrand or another generator. For most testing, this will not be important." module Testing; import Prelude; import IO; import Time; globals { [(Void(), Int, String)] tests = []; } "The error message An assertion failed This Exception is thrown when an assertion fails." Exception AssertionFailure(String message); "The test result The failure message, if any. Check the result of a test. Check the result of a test. On failure, throw an exception with the given message. add run" public Void assert(Bool test, String msg = "Unspecified Assertion Failure") { if (!test) { throw(AssertionFailure(msg)); } } // Functions for generating a variety of random test cases. "An arbitrary union type. This data type is used to create completely random union values for testing polymorphic functions." public data Arbitrary = AnInt(Int num) | AString(String str) | AChar(Char ch) | AFloat(Float float) | AnArray([Arbitrary] array) | Recursive(Arbitrary value) | RecPair(Arbitrary value1, Arbitrary value2); "This parameter gives the maximum depth of recursion to guarantee that the value has finite size. The default value is 10 and can usually be omitted. Return a random value Return a random value of arbitrary type. randomArray randomChar randomFloat randomInt randomString" public Arbitrary randomValue(Int depth = 10) { depth--; if (depth <= 0) { opts = 4; } else { opts = 7; } case rand()%opts of { 0 -> return AnInt(randomInt); | 1 -> return AString(randomString()); | 2 -> return AChar(randomChar); | 3 -> return AFloat(randomFloat); // keep it quite small, don't want to spend ages generating a value! | 4 -> return AnArray(randomArray(randomValue@(depth),0,10)); | 5 -> return Recursive(randomValue(depth)); | 6 -> return RecPair(randomValue(depth), randomValue(depth)); } } "Return a random integer Return a random integer in the range -2**31 to 2**31. randomChar randomFloat randomIntArray randomNegativeInt randomPositiveInt randomSignOfInt randomString randomValue" public Int randomInt() { if (rand()%2 == 0) { return randomPositiveInt(); } else { return randomNegativeInt(); } } "Return a random positive integer Return a random integer in the range 0 to 2**31. randomInt randomNegativeInt randomSignOfInt" public Int randomPositiveInt() { return abs(rand()); } "Return a random negative integer Return a random integer in the range -2**31 to 0. randomInt randomPositiveInt randomSignOfInt" public Int randomNegativeInt() { return -abs(rand()); } "Return a distribution of integers Return an even distribution of negative, positive and zero integers randomInt randomNegativeInt randomPositiveInt" public Int randomSignOfInt() { case rand()%3 of { 0 -> return randomPositiveInt(); | 1 -> return randomNegativeInt(); | 2 -> return 0; } } "Return a random floating point number Return a random floating point number randomChar randomFloatArray randomInt randomNegativeFloat randomPositiveFloat randomString randomValue" public Float randomFloat() { if (rand()%2 == 0) { return randomPositiveFloat(); } else { return randomNegativeFloat(); } } "Return a random positive floating point number Return a random positive floating point number randomFloat randomNegativeFloat" public Float randomPositiveFloat() { return abs(Float(rand)/Float(rand+1)); // No, I'm not convinced either. It'll do. } "Return a random negative floating point number Return a random negative floating point number randomFloat randomPositiveFloat" public Float randomNegativeFloat() { return -abs(Float(rand)/Float(rand+1)); // No, I'm not convinced either. It'll do. } "Return a random character Return a random character (half of returned characters will be ASCII, the other half will be multibyte unicode). randomCharArray randomFloat randomInt randomString randomValue" public Char randomChar() { return Char(1+(rand()%256)); } "The minimum length of the string (may be omitted for a default of zero) The maximum length of the string (may be omitted for a default of 160) Return a random string Return a random string including multibyte characters. randomChar randomFloat randomInt randomStringArray randomValue" public String randomString(Int minsize = 0, Int maxsize = 160) { num = (rand()%(maxsize-minsize))+minsize; str = ""; for x in [1..num] { str += randomChar(); } return str; } "A function that returns random elements of the given type. The minimum size of the array (optional, defaults to zero) The minimum size of the array (optional, defaults to 1000) Return a random array Return a random array, with elements given by the generator function. randomCharArray randomFloatArray randomIntArray randomStringArray randomValue" public [a] randomArray(a() generator, Int minsize = 0, Int maxsize = 1000) { num = (rand()%(maxsize-minsize))+minsize; arr = []; for x in [1..num] { push(arr,generator()); } return arr; } "The minimum size of the array (optional, defaults to zero) The minimum size of the array (optional, defaults to 1000) Return a random list of integers Return a random list of integers. randomArray randomCharArray randomFloatArray randomInt randomStringArray" public [Int] randomIntArray(Int minsize = 0, Int maxsize = 1000) = randomArray(@randomInt, minsize, maxsize); "The minimum size of the array (optional, defaults to zero) The minimum size of the array (optional, defaults to 1000) Return a random list of floating-point numbers Return a random list of floating-point numbers. randomArray randomCharArray randomFloat randomIntArray randomStringArray" public [Float] randomFloatArray(Int minsize = 0, Int maxsize = 1000) = randomArray(@randomFloat, minsize, maxsize); "The minimum size of the array (optional, defaults to zero) The minimum size of the array (optional, defaults to 1000) Return a random list of characters Return a random list of characters. randomArray randomChar randomFloatArray randomIntArray randomStringArray" public [Char] randomCharArray(Int minsize = 0, Int maxsize = 1000) = randomArray(@randomChar, minsize, maxsize); "The minimum size of the array (optional, defaults to zero) The minimum size of the array (optional, defaults to 1000) Return a random list of strings Return a random list of strings. randomArray randomCharArray randomFloatArray randomIntArray randomString" public [String] randomStringArray(Int minsize = 0, Int maxsize = 10000) = randomArray(randomString@(minsize,maxsize), minsize, maxsize); "Re-initialise the test framework. Re-initialise the test framework, clearing any existing tests. add run" public Void init() { tests = []; } "A test function. Test functions must return nothing and take no parameters. They should finish with a call to assert for the test conditions. The number of times to run the test (useful if random values are being used). Defaults to 1. A descriptive name for the test, which defaults to the empty string. Add a test function. Add a test function that runs a test case, finishing with a call to 'assert' init run" public Void add(Void() test, Int num = 1, String name = "") { push(tests, (@test, num, name)); } "Run the tests. Run the tests. Returns true if all tests pass, or false otherwise. add init" public Bool run() { srand(now); failure = 0; success = 0; for t@testnum in tests { (test, num, name) = t; Prelude::putStr("Test "+(testnum+1)+" "); if (name!="") { Prelude::putStr("("+name+") "); } try { for x in [1..num] { test(); } putStrLn("success"); success++; } catch(AssertionFailure(msg)) { putStrLn("FAILURE: "+msg); failure++; } catch(e) { putStrLn("FAILURE: Uncaught exception "+exceptionMessage(e)); failure++; } } if (failure==0) { putStrLn("\nAll tests pass"); return true; } else { putStrLn("\n"+failure+" test failure"+(if (failure!=1) "s" else "")); } return false; } kaya-0.4.4/stdlib/Queue.k0000644000175100017510000001160111170340770013270 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005, 2006 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Queue implementation This module implements a first-in, first-out queue." // I suspect this representation (two stacks rather than an array), // is both faster for lookup and insertion (constant time mostly) // and uses less memory for small structures (due to arrays allocating a // largeish block). Experimentation is probably neeed. // CIM: might be worth checking this now that operations on the left // of an array are almost as fast as operations on the right. module Queue; import Prelude; "FIFO queue. This data type represents a first-in, first-out queue." abstract data Queue
    (List inq, List out, Int length); "Queue was empty This Exception is thrown if the Queue was empty" Exception EmptyQueue(); "Create an empty queue. Create a new empty queue. array dequeue enqueue length" public Queue empty = Queue(nil,nil,0); "The queue Get the length of a queue. Returns the number of items currently in the queue. array dequeue empty enqueue" public Int length(Queue q) = q.length; "The queue The item to add Add an item to a queue. Adds an item to the queue. array dequeue empty length" public Void enqueue(Queue q, a item) { q.inq = cons(item,q.inq); q.length++; } "The queue Remove an item from a queue. Removes the front item from the queue, and returns the removed item. If the queue is empty, then the EmptyQueue exception will be thrown. array empty enqueue length" public a dequeue(Queue q) { if (q.length==0) throw(EmptyQueue); case q.out of { nil -> reverse(q.inq); q.out = q.inq; q.inq = nil; return dequeue(q); | cons(x,xs) -> q.out = xs; q.length--; return x; } } "The block of code to execute for each queue element. The queue to traverse Iteration over queues Used by for loops to traverse Queue data structure. It is unlikely that you will need to call this function directly. Iteration over a queue does not dequeue elements in the queue." public Void traverse(Bool(a,Int) block, Queue q) { for x@i in array(q) { if (!block(x, i)) { return; } } } "The queue Coercion to array. Return a list of the elements in the queue (front item in index 0), without modifying the queue. dequeue empty enqueue length" // Needs to work on the actual data, not using dequeue, since coercions // shouldn't modify the original data. public [a] array(Queue q) { ina = array(q.inq); outa = array(q.out); reverse(ina); concat(outa,ina); return outa; } // Enqueue a list of ordered numbers. // Every so often, dequeue some and maintain a list of the dequeued numbers. // They should be strictly in sequence. /* Void testQueue(Int num) { srand(time()); xs = [1..num]; dequeued = []; q = empty; for x@i in xs { enqueue(q,x); // Every 50, on average, dequeue up to 20. if ((i+(rand()%5))%50 == 1) { for x in [0..(rand()%100)] { if (length(q)>0) { y = dequeue(q); push(dequeued,y); } } } } // Dequeue the rest. while (length(q)>0) { y = dequeue(q); push(dequeued,y); } // for y in dequeued { // putStr(y+","); // } // putStrLn("END"); if (xs == dequeued) { putStrLn("Queues are identical"); } else { putStrLn("QUEUES ARE BROKEN!"); } } */ kaya-0.4.4/stdlib/XMLentities.k0000644000175100017510000001110111170340767014412 0ustar cimcim/** -*-C-*-ish XMLentities.k Copyright (C) 2005 Chris Morris This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "XML entity handling Functions to convert between literal characters and numeric entities in XML" module XMLentities; import Prelude; import Strings; import Dict; import HTMLentities; /* This module will convert XML numeric entity references to literal characters and back. It will also handle the named entities in (X)HTML */ Exception InvalidChar(Int num); "The text to convert Whether to use the named entities defined in HTML (e.g. &pound;). This argument may be omitted, for a default of using them. Convert XML entities to literal characters Return a String with all the XML entities in the original string converted to literal characters (for example &amp;#170; or &#xAA; would become Char(170)). Optionally, the HTML named entities may also be converted (so &amp;ordf; would also become Char(170)). literalToEntity" // need to double escape ampersands due to conversion public String entityToLiteral(String text, Bool html=true) { if (!elem('&',text)) { return text; } len = length(text); out = createString(len+1); //it can't be longer than the original pos = 0; inentity = false; while (pos < len) { skip = firstOccurs('&',substr(text,pos,len-pos)); if (skip > 0) { out += substr(text,pos,skip); pos += skip; } if (pos < len) { // now we want to look ahead to see what we have. if (pos+1= len || !(isDigit(getIndex(text,numpos)) || (base == 16 && elem(getIndex(text,numpos),['a','b','c','d','e','f','A','B','C','D','E','F'])))) { // not actually a reference out += "&"; pos++; } else { pos += 2; // skips &,# if (base == 16) { pos++; } // skip x/X while (pos < len && (isDigit(getIndex(text,numpos)) || (base == 16 && elem(getIndex(text,numpos),['a','b','c','d','e','f','A','B','C','D','E','F'])))) { numref += substr(text,numpos,1); numpos++; pos++; } if (pos if (enpos+1 >= len || substr(text,enpos+1,1) == ";") { refnum = i; reffound = true; } // must require a terminator for these. | nothing -> ; } // look it up enpos++; } if (reffound) { out += Char(refnum); pos = enpos; if (pos < len && substr(text,pos,1) == ";") { pos++; // skip the terminator if it exists } } else { out += "&"; pos++; } } else { out += "&"; pos++; } } } return out; } "The text to convert Convert literal characters to XML entities Return a String with all of the literal characters outside the strict 7-bit ASCII subset converted to XML entities. For example Char(220) would be replaced with &amp;#220;. An Exception is thrown if the input string contains any literal characters not legal in XML documents (or are in the range 128-159, for which the behaviour is undefined). entityToLiteral" public String literalToEntity(String text) { chars = array(text); result = ""; for char in chars { num = Int(char); if ((num >= 127 && num <= 159) || (num <= 31 && num != 9 && num != 10 && num != 13)) { throw(InvalidChar(num)); // strictly 128-159 are undefined, not invalid, but it's still a bad idea. } else if (num < 127) { result += char; } else { result += "&#"+String(num)+";"; } } return result; } kaya-0.4.4/stdlib/network_glue.h0000644000175100017510000000340311170340770014707 0ustar cimcim#ifndef _NETWORK_H // -*-C++-*- #define _NETWORK_H #ifdef WIN32 #include #include #else #include #include #include #include #include #endif #ifdef WIN32 #define FILE_SEPARATOR '' #define MSG_WAITALL 0 #else #define FILE_SEPARATOR '/' #endif #include #include #include #include class ConnInfo : public gc { public: int cid; struct sockaddr_in addr; socklen_t addrlen; }; extern "C" { /// Initialise network library (only needed on Windows at the moment) void net_init(void* vm_ptr); /// Create a socket and connect to the server. Returns connection info. void* net_connect(void* vmptr,int proto,wchar_t* server, int port); /// Create a socket and start listening. Returns socket id. int net_listen(void* vmptr,int proto, int port, int backlog); bool net_connwaiting(void* vmptr, int socket, kint timeout); /// Accept a connection. Returns connection info. void* net_accept(void* vmptr,int socket); /// Shutdown a connection. void net_shutdown(void* conn); /// Close a socket. void net_close(void* vmptr, void* conn); void net_send(void* vmptr,void* conn, wchar_t* data); void net_sendchars(void* vmptr,void* conn, void* data, kint len); void net_sendbyte(void* vmptr,void* conn, kint byte); /* need byte, chars forms */ wchar_t* net_recv(void* vmptr,void* conn, KayaValue len); void* net_recvchars(void* vmptr,void* conn, KayaValue len); kint net_recvbyte(void* vmptr,void* conn); /// Get the address of the host in the connection. wchar_t* net_getaddr(void* conn); /// Return whether data is available on a socket bool net_pending(void* vm, void* conn, int timeout); } #endif kaya-0.4.4/stdlib/Array.k0000644000175100017510000005311211170340770013265 0ustar cimcim/** -*-C-*-ish Kaya standard library Copyright (C) 2004, 2005 Edwin Brady This file is distributed under the terms of the GNU Lesser General Public Licence. See COPYING for licence. */ "Array manipulation This module contains functions for manipulating and inspecting arrays. All of the functions will work on arrays of any type. It is automatically imported (via the Prelude module) unless the -noprelude compiler option is used. Almost all programs and modules will need to import this module." module Array; import Builtins; import Tuples; foreign "stdfuns.o" { [a] doReverse([a] xs) = reverseArray; "The array to resize The new length Resize an array. Change the size of the array to i. If the array is longer than i, later items are dropped. If it is shorter, uninitialised values are pushed onto the array." public Void resize([a] xs, Int i) = resizeArray; Void quicksort(Ptr vm, [a] xs, Int(a,a) sortfn) = quicksort; Void shortenArray([a] array) = shortenArray; a shiftArray([a] array) = shiftArray; Void unshiftArray(a val, [a] array) = unshiftArray; [a] docreateArray(Ptr vm, Int size) = createArray; } "The initial size of the array Create an array Create an array with an initial size of size. While arrays are automatically resized as necessary, it is more memory-efficient to only make arrays as large as necessary, if the final size of the array is known. [] is equivalent to createArray(1024). Generally this is adequate - save the use of this function for the optimisation stage. Builtins::createString" public [a] createArray(Int size) { return docreateArray(getVM,size); } "Attempt to access an out-of-bounds element. This Exception is thrown by various array functions when an attempt is made to read an illegal array index." Exception OutOfBounds(); "The step in a range may not be zero If the step in a range is zero, as in the following examples, the range would have infinite size, and so this Exception is thrown. r = range(1,5,0); r = [1,1..5];" Exception ZeroStep(); "The array to reverse Reverse an array in-place. This function reverses an array in-place. xs = [1,2,3,4,5]; reverse(xs); // xs = [5,4,3,2,1]" public Void reverse(var [a] xs) { xs = doReverse(xs); } "The first value in the returned array The limit of the last value in the returned array The difference between adjacent values (cannot be zero!). This argument is optional and defaults to 1. Get a range of integers Return an array of values from [first..last], incrementing by step. xs = range(1,5); // [1,2,3,4,5] xs = range(1,5,2); // [1,3,5] xs = range(1,5,3); // [1,4] xs = range(8,4,-1); // [8,7,6,5,4] The usual way of calling the range function is using the [first..last] or [first,second..last] syntax. xs = [1..5]; // [1,2,3,4,5] xs = [1,3..5]; // [1,3,5] xs = [1,4..5]; // [1,4] xs = [8,7..4]; // [8,7,6,5,4]" public [Int] range(Int first, Int last, Int step = 1) { // print "Running range\n"; if (step == 0) { throw(ZeroStep); } size = (last+1-first)/step; if (size<0) { size=-size; } xs = createArray(size); j=0; val = first; if (step>0) { while (val<=last) { xs[j]=val; j=j+1; val = val + step; } } else if (step<0) { while (val>=last) { xs[j]=val; j=j+1; val = val + step; } } return xs; } "The array to sort Optionally, a user-defined comparison function. Sort an array. Sort an array in-place using the quicksort algorithm. By default this uses the Builtins::compare function and sorts in ascending order, but it can instead use a user supplied compare function. xs = [3,5,1,2,6,1]; sort(xs); // [1,1,2,3,5,6] Comparison functions should return 0 if the values are identical, less than zero if the first value passed to the function is 'smaller', and more than zero if the second value is 'bigger'. In this context, 'smaller' values are moved to the start of the array, and 'bigger' values to the end. The following example has a simple function to sort an array of Ints into descending order. Int rsort(Int a, Int b) { return b-a; } Void main() { xs = [3,5,1,2,6,1]; sort(xs,rsort); // [6,5,3,2,1,1] } Values that are identical for the purposes of the sorting function will be placed in an undefined order relative to each other. The sorted function returns a sorted copy of the array, rather than sorting in place." public Void sort(var [a] xs, Int(a,a) sortfn = compare) { quicksort(getVM(),xs,sortfn); // quicksort(xs, 0, size(xs)-1, sortfn); } "The array to sort Optionally, a user-defined comparison function. Return a sorted array. Sorts an array, but unlike sort returns a new array and leaves the original unmodified. See the sort function documentation for usage examples." public [a] sorted([a] xs, Int(a,a) sortfn = compare) { newxs = createArray(size(xs)); // Do a shallow copy. for x in xs { push(newxs,x); } sort(newxs,sortfn); return newxs; } "The array to shuffle Randomly reorder an array. Randomly reorder an array in-place. Because this function uses Builtins::rand to determine the order, you must have called Builtins::srand before you use it." public Void shuffle(var [a] xs) { // Swap each element with a random other element xsize = size(xs); for i in [0..xsize-1] { swap(xs[i],xs[abs(rand()%xsize)]); } } "The first array The second array Concatenate two arrays. Append the elements of the second array onto the first array. xs = [1,2,3]; ys = [4,5]; concat(xs,ys); // xs = [1,2,3,4,5] // ys = [4,5]" public Void concat(var [a] xs, [a] ys) { for y in ys { push(xs,y); } } "A list of lists Concatentate a list of lists Concatentate a list of lists into a single list. lists = [[1,2,3],[4,5],[6,7,8,9,10]]; joined = join(lists); // joined = [1,2,3,4,5,6,7,8,9,10]" public [a] join ([[a]] lists) { new = []; for xs in lists { for x in xs { push(new,x); } } return new; } "The separator The elements Place a separator between each element of an array Place the separator sep between each element of xs and return the resulting array. xs = [1,2,3,4]; ys = intersperse(0,xs); // ys = [1,0,2,0,3,0,4]" public [a] intersperse(a sep, [a] xs) { new = createArray(size(xs)*2); for x@i in xs { push(new,x); if (i+1!=size(xs)) push(new,sep); } return new; } "The predicate to test with The array to test Check if any elements satisfy a predicate Return true if any of the elements of xs satsify the predicate p. all" public Bool any(Bool(a) pred, [a] xs) { for x in xs { if (pred(x)) { return true; } } return false; } "The predicate to test with The array to test Check if all elements satisfy a predicate Return true if all of the elements of xs satsify the predicate p. any" public Bool all(Bool(a) pred, [a] xs) { for x in xs { if (!pred(x)) { return false; } } return true; } "The function to apply The array Map a function across an array. Returns the array created by applying function f to every element of xs. xs = [\"abc\",\"d\",\"efghij\"]; ys = map(length,xs); // ys = [3,1,6] or xs = [1,-5,2,-7,-4]; ys = map(abs,xs); // ys = [1,5,2,7,4] zipWith fold" public [b] map (b(a) f, [a] xs) { newxs = createArray(size(xs)); for x in xs { push(newxs, f(x)); } return newxs; } // If we have map, we might as well have zipWith! "The function to use The first array The second array Map a function across two arrays. Returns the array created by applying function f to every pairwise elements of xs and ys. If the arrays are of different lengths, then the resulting array will be the same size as the shorter of the two input arrays. The function must take xs[0] and ys[0] to give zs[0] and so on. Int sum(Int a, Int b) { return a+b; } Void main() { xs = [1,2,3,4,5]; ys = [7,8,9]; zs = zipWith(sum,xs,ys); // zs = [8,10,12]; } map zip" public [c] zipWith(c(a,b) f, [a] xs, [b] ys) { if (size(xs)The first list The second list Turn a pair of lists into a list of pairs. Turn a pair of lists into a list of pairs. This is equivalent to using zipWith with this function: (a,b) zipfn(a fst, b snd) { return (a,b); } zipWith" public [(a,b)] zip([a] xs, [b] ys) { return zipWith(\(a,b) -> (a,b), xs, ys); } "The function to use The array The initial value for folding. Fold an array. Applies a function across an array. For example, given a function sum which adds two integers: total = fold(sum,[1,2,3,4,5],0); putStrLn(String(total)); This prints the sum of the values in the array [1,2,3,4,5]. The following example uses fold to calculate the final direction. data Direction = North | East | South | West; data Turn = Left | Right; Direction doTurn(Turn turn, Direction current) { case turn of { Left -> case current of { North -> new = West; | West -> new = South; | South -> new = East; | East -> new = North; } | Right -> case current of { North -> new = East; | West -> new = North; | South -> new = West; | East -> new = South; } } return new; } Void main() { turns = [Left,Left,Left,Right,Right,Left,Right,Left,Left]; original = West; final = fold(doTurn,turns,original); // final = North } map" public b fold (b(a,b) f, [a] xs, b acc) { for x in xs { acc = f(x,acc); } return acc; } "The predicate to test against The array to filter Filter a list according to a predicate. Each element of xs is tested against the predicate p. The returned list contains those elements of xs for which the predicate is true. The predicate function may of course be partially applied for ease of programming. Bool isDiv(Int d,Int a) { return (a%d==0); } Void main() { ints = [1,2,3,4,5,6,7,8]; odds = filter(isDiv@(3),ints); // odds = [3,6]; } Naturally, all(p,filter(p,xs)) == any(p,xs). any all" public [a] filter(Bool(a) p, [a] xs) { newxs = createArray(size(xs)); for x in xs { if (p(x)) push(newxs,x); } return newxs; } "The array The value to push Push a value onto the end of an array. Push a value onto the end of an array. array = [1,2,3]; push(array,4); // array = [1,2,3,4] addAt pop shift unshift" public Void push(var [a] array, a v) { array[size(array)]=v; } "The array Return the last value in an array Return the last value in an array pop" public a top([a] array) { if (size(array)<=0) { throw(OutOfBounds); } return array[size(array)-1]; } "The array Remove a value from the end of an array Remove a value from the end of an array array = [1,2,3]; pop(array); // array = [1,2] push removeAt shift top unshift" public Void pop(var [a] array) { if (size(array)<=0) { throw(OutOfBounds); } shortenArray(array); } "The array Get the first item off an array, and remove it from the array. Get the first item off an array, and remove it from the array. array = [1,2,3]; v = shift(array); // array = [2,3]; v = 1; push pop removeAt unshift" public a shift(var [a] array) { if (size(array)==0) { throw(OutOfBounds); } return shiftArray(array); } "The value to unshift The array Add a value onto the start of an array. Add a value onto the start of an array. array = [1,2,3]; unshift(array,4); // array = [4,1,2,3] addAt push pop shift" public Void unshift(a val, var [a] array) { /* for(i=size(array)-1;i>=0;i=i-1) { array[i+1]=array[i]; } array[0]=val; */ unshiftArray(val,array); } "The array to act on The starting index The number of elements to retrieve Return a subarray Return the subarray starting at position pos, n elements long. An Exception is thrown if the subarray will not fit entirely within the array. array = [1,2,3,4,5,6,7]; sub = subarray(array,3,2); // sub = [4,5] remove Prelude::substr" public [a] subarray([a] array, Int pos, Int n) { if (pos < 0 || n < 1 || pos+n > size(array)) { throw(OutOfBounds); } sub = createArray(n); for i in [pos..(pos+n-1)] { push(sub,array[i]); } return sub; } "The array to act on The starting index The number of elements to remove Return the array created by removing a subarray. Return the array created by removing a subarray starting at position pos, n elements long. array = [1,2,3,4,5,6,7]; rem = remove(array,3,2); // array = [1,2,3,6,7]; rem = [4,5] subarray removeAt" public [a] remove([a] array, Int pos, Int n) { // subarray() does the bounds checking for us here. sub = subarray(array,pos,n); for i in [pos..(size(array)-n-1)] { array[i] = array[i+n]; } for i in [1..n] { pop(array); } return sub; } "The array to act on The index of the element to remove Remove an element from an array Remove (in-place) the element at position idx. array = [1,2,3,4,5,6,7]; removeAt(array,2); // array = [1,2,4,5,6,7]; remove addAt" public Void removeAt(var [a] array, Int idx) { if (size(array)<=idx || idx < 0) { throw(OutOfBounds); } for(i=idx;i<(size(array)-1);i=i+1) { array[i]=array[i+1]; } shortenArray(array); } // idx = 0 is equivalent to unshift, idx = size(array) is equivalent to push "The array to act on The new element The index of the element to add before Add an element to an array Add (in-place) an element before position idx. array = [1,2,3,4,5,6,7]; addAt(array,5,2); // array = [1,2,5,3,4,5,6,7]; push is equivalent to idx = size(array) removeAt unshift is equivalent to idx = 0" public Void addAt(var [a] array, a elem, Int idx) { if (size(array)idx;i--) { array[i]=array[i-1]; } array[idx] = elem; } } "The value to search for (\"needle\") The list to search (\"haystack\") Optionally, the function used to check for presence (the default is Builtins::equal, obviously, but Builtins::identical might be used) Check whether a value is in a list. Check whether the \"needle\" occurs at least once in the \"haystack\". This function can be thought of as a specialised version of any any Builtins::equal Builtins::identical" public Bool elem(a val, [a] list, Bool(a,a) eq = equal) { for x in list { if (eq(x,val)) { return true; } } return false; } "The list Optionally, the equality test. Defaults to Builtins::equal. Remove repeated elements from a list. Remove repeated elements from a list in-place. Repeated elements will be removed whether adjacent or not. xs = [1,2,3,3,1,2,4,5,2,2,1]; nub(xs); // xs = [1,2,3,4,5] The name 'nub', incidentally, is borrowed from the Haskell prelude function of the same name, and suggests 'essence'." public Void nub(var [a] xs, Bool(a,a) eq = equal) { pos = 1; while (pos < size(xs)) { if (elem(xs[pos],take(pos,xs),@eq)) { removeAt(xs,pos); } else { pos++; } } } "The number of elements to take The array of elements Take the first x elements from an array. Take the first x elements from an array, and return a new array, leaving the original unmodified. This is equivalent to subarray(xs,0,x). subarray" public [a] take(Int x, [a] xs) = subarray(xs,0,x); kaya-0.4.4/examples/0000755000175100017510000000000011170340772012370 5ustar cimcimkaya-0.4.4/examples/display/0000755000175100017510000000000011170340772014035 5ustar cimcimkaya-0.4.4/examples/display/cursestest.k0000644000175100017510000000135211170340772016416 0ustar cimcimprogram cursestest; import Curses; Void main() { try { initScreen(); cbreakMode(true); echoMode(false); newlineMode(false); intrFlush(stdscr, false); startColour(); setCursor(Invisible); if (hasColours()) { initPair(1,Red,Black); initPair(2,Green,Yellow); } box(stdscr); refresh(); win = newWin(10,60,5,5); wAttributes(win,[Bold,ColourPair(1)],true); intrFlush(win,false); box(win); wRefresh(win); wMove(win,2,5); waddStr(win,"Hello world!"); wAttributes(win,[Bold],false); wAttributes(win,[Normal, ColourPair(2)],true); wMove(win,7,35); waddStr(win,"Foo!"); wRefresh(win); refresh(); x = wgetChar(win); endWin(); putStrLn("You pressed '"+x+"'"); } catch(e) { endWin(); throw(e); } } kaya-0.4.4/examples/display/sdltest.k0000644000175100017510000000270011170340772015672 0ustar cimcimprogram sdltest; import SDL; Exception QuitNow; Void main() { try { sdlInit(); setWMTitle("SDL Test in Kaya","Kaya SDL"); screen = newSurface(640,480,BPP32,false); pic = loadSurface("url-large.bmp"); px = 88; py = 31; /*pic = loadSurface("kaya_64.bmp"); px = 64; py = 72; setTransparency(pic,SDLColour(192,192,192,255));*/ x = 0; y = 0; while(true) { case nextEvent() of { KeyDown(k,_) -> if (k == NormalKey('q')) { throw(QuitNow); } else if (k == NormalKey('b')) { blitSurface(pic,Rect(0,0,px,py),screen,Rect(0,0,px,py)); updateScreen(screen); } else if (k == FunctionKey(3)) { blitSurface(pic,Rect(0,0,px,py),screen,Rect(300,300,px,py)); updateScreen(screen); } else if (k == ArrowRightKey) { blitSurface(pic,Rect(0,0,px,py),screen,Rect(x+50,y,px,py)); updateScreen(screen); } else if (k == NormalKey('')) { drawRectangle(screen,Rect(x,y,20,20),SDLColour(x%256,y%256,(x+y)%256,0)); updateScreen(screen); } else if (k == NormalKey('P')) { drawRectangle(screen,Rect(x-20,y-20,20,20),SDLColour(x%256,y%256,(x+y)%256,0)); updateScreen(screen); } else { blitSurface(pic,Rect(0,0,px,py),screen,Rect(x,y,px,py)); updateScreen(screen); } | MouseButton(b,x,y) -> blitSurface(pic,Rect(0,0,px,py),screen,Rect(x,y,px,py)); updateScreen(screen); | MouseMove(x,y) -> ; | default -> ; } } } catch(e) { putStrLn(sdlError()); exceptionBacktrace(e); sdlQuit(); } } kaya-0.4.4/examples/display/url-large.bmp0000644000175100017510000002016211170340772016430 0ustar cimcimBMr zlXø  ÿÿÿÿp€fÔäÈÀÕ¬åñÞq€fª¿”ª¿”ª¿”ª¿”qfñ÷êñ÷ê¯Âñ÷êñ÷êæòßn|eª¿”«¿”ª¿”«¿”«À•Ž }Ž }ñ÷ên|e­Â—®Â˜®Ã™¯Ãš¯Äš°Ä›±Å›±Åœ³Æ³Æž´ÇŸµÈŸµÈ ¶É¡·É¢·Ê¢¸Ê¤¸Ë¤¹Ì¦ºÌ¦»Í§¼Í¨½Ï©¾Ïª¿Ð«ÀѬÀÑ­ÁÒ®ÂÓ¯ÃÓ°ÄÔ±ÅÕ²ÅÖ³Æ×´ÇصÈÙ¶ÉÙ·ÊÚ¸ËÛ¹ÌÛºÌÜ»ÍܼÎݾÏÞ¾Ðß¿ÑßÀÑàÁÒáÂÓâÃÔãÄÕãÅÖäÅ×åÆ×åÈØæÈÙæÉÙçÊÚèËÛèËÛéÌzŒlÉÛ½±¿¤ÉÛ½ w“Yw“Yw“Yl‹TÿÿÿÉÛ½ÿÿÿÿÿÿÿÿÿ w“Yw“Yw“Yw“Yw“Zy”[z•\ ééÓ‘¦}3 ~™ašc€›c‚œeƒžg… iˆ¡lŠ£oŒ¥q¨t¨v”«y•¬{˜¯~™±€³…£¹Œ§½¨½’¬Á•¯Äš±ÅœµÈ ·Ê¢½Ï©ÀÒ­ÂÔ¯Æ×´ÈÙ¶ËܹÍÝ»Ïß¾ÑàÀÜé̦“3 ÿÿÿÉÛ½ÉÛ½@X-w“Yw“Y™jÿÿÿÿÿÿ ÿÿÿÿÿÿ w“Yw“Yw“Yw“Yw“Yx“Zy”[z•\z–]ÿÿÿ3 ~™ašb€›cœe„žh† kˆ¡l¨t©v”«y•¬{´… ·ˆ¢¸‹¤ºŒ¬Á–¯Ãš²ÅœµÈ ¸Ë¤ºÌ¦½Ï©¿Ñ«ÁÒ­ÃÕ±ÄÖ²ÉÙ¶ËܹÌݼÏß¾ÒáÁÓãÃÛéÍzŒl±¿¤ÿÿÿ@X-ÿÿÿ@X-w“Y3 ÿÿÿÿÿÿ3 ÿÿÿÿÿÿ w“Yw“Yw“Yw“Yw“Yw“Yw“Zx”[z•\z–]{—] ÿÿéšb›dœe…Ÿi‡ jˆ¢lФoŒ¥p¨u©v”«z•­{˜°~š±´…¡·‰¢¸Š¤¹§½©¾’¬Á–°ÃšµÈ ·Ë¤½Ï©¿Ñ«ÀÒ­ÃÕ°ÅÖ³ÈÙ¶ÎÞ½Ðß¾ÒâÁÛéÌ©¾“@X-ÿÿÿ@X-ÉÛ½_eYw“Y ÿÿÿÉÛ½±¿¤ÿÿÿ@X-w“Yw“Yw“Yw“Yw“Yw“Yw“Yx“Zx”[y•\z•\{–^|—_éô逛cœd„žh‡ k‡¡l‰£n¦r¨tÿÿÿ•¬{–®}›²ƒ´…¡¶ˆ¡¸‹£¹Œ¥»Žª¿”­Á–±ÆœµÈ ¸Ë¤¹Í¥»Î¨½Ð©¾Ñ«ÀÒ­ÃÔ±ÅÖ²ÈÙ¶ËܹÍÝ»Ïà¾ÒáÂÓâÃÕäÄÛé̪¿“ ÿÿÿ@X-‘¦} w“Y3 ÿÿÿ3 ÿÿÿÿÿÿ_eYw“Yw“Yw“Yw“Yw“Yw“Yw“Yx“Yy”[z•\z–]{–^|—__eYÿÿÿl‹T3 œe„žh…Ÿi‡¢l‰£m¦rާtÿÿÿ”­|—¯}›²ƒ´„ ¶ˆ¢¸Š¤¹Œ¦»Žª¿”¬Á–¯Äš±Åœ´È ¶É¢¼Ï©¿Ñ«ÁÒ­ÂÓ¯ÇØ´ÈÙ¶ÎÞ½Ïà¾ÐáÀÛé̪¿“™jéôéÿÿÿ w“Y3 ‘¦}±¿¤ÿÿÿ@X-w“Yw“Yw“Yw“Yw“Yw“Yw“Yw“Yx”Zx”Zy•[z•\{—^|—_}˜`ÿÿÿ _eYƒfƒžg…Ÿi† kˆ¡m‰¢nŠ£pŒ¥qާs¨t‘©v‘ªw“«z•­{–®}˜¯™±›²‚´„Ÿµ‡ ·‰¢¸‹¤ºŒ¥»Ž§½¨¾’ª¿”¬Á–­Ã˜°Ãš±Åœ³Ç´È ·Ê¢¸Ë¤ºÍ¦»Î§½Ïª¾Ñ«ÀÒ­ÂÔ¯ÄÕ±ÅÖ³Ç×´ÈÙ¶ÉÚ·ËܺÌÝ»ÎÞ½Ðà¾ÑáÀÒáÂÔâÃÕäÄÛé̪¿“ ÿÿÿÿÿÿÿÿÿ ™j3 ééÓ _eYw“Yw“Yw“Yw“Yw“Yw“Yw“Yw“Y_eYx”[y”[z•\{—^|˜_}˜`@X-3 ÿÿÿ‚f„žg…Ÿi‡ kˆ¢l‰£m‹¤o‹¥p_eYލt¨v’ªw”«y”­{—®}˜°š°_eY´…žµ† ¶‰¢¸Š¤ºŒ¥ºŽ§¼¨¾’«¿”¬Á–®Ã—°Ä™±Åœ³Æž´È ¶Ê¡¸Ë¤ºÍ¦»Î¨½Ï©¿Ñ«ÀÒ­ÁÓ¯ÃÕ°Å×³ÇØµÈÙ¶ÊÚ¸ËÛºÍÝ»ÎÞ½Ïß¿ÐáÀÓáÁÔãÃÕäÄÛé̪¿“w“Y3 ÿÿÿÿÿÿ3 ÉÛ½@X-ÿÿÿ±¿¤3 @X-w“Yw“Yw“Yw“Yw“Y3 3 {•\{–^|—^}™_~™a3 ‘¦}ÿÿÿ„žg…Ÿi‡ k‡¡l‰¢m‹¤o3 _eY’ªx”¬z•­|–®}˜¯3 @X- ¶‰¡¸‹¤ºŒ¥»Ž§½©¾’ª¿”¬Á–®Â˜°Ãš±Åœ³Çž´ÉŸ¶É¢¸Ë£¹Í¦¼Î§½Ð©¿Ñ«ÀÒ­ÂÔ¯ÃÕ±Å×²ÆØµÈÙ¶ÊÚ¸ËܺÍÝ»ÎÞ½Ïß¿ÑàÀÒâÂÔãÃÕäÅÛé̪¿”w“Y_eY@X-l‹T3 ÿÿÿÉÛ½@X-@X- ÿÿÿÿÿÿl‹T w“Yw“Yw“Yw“Y¡¿‰ÿÿÿÿÿÿÿÿÿ 3 |—^}˜`3  ééÓééÓ …Ÿi†¡kˆ¢m‰£mÿÿÿÿÿÿÿÿÿ3 ‘ªx“«y•­{—¯}ÿÿÿÿÿÿÿÿÿ3 ¢¸Š£¹¥»Ž§¼©¾’ªÀ”¬Á•®Â˜°Äš±Åœ³ÇžµÈ ·É¢¸Ë£ºÍ¥¼Î§½Ï©¾Ñ¬ÀÒ­ÂÓ¯ÃÕ±ÄÖ²Æ×µÈÙ¶ÉÚ¸ËܺÍÝ»ÎÞ¼Ïà¿ÐáÀÒáÂÓãÄÕäÄÛé̪¿”w“Yw“Yw“Y¡¿‰ÿÿÿ@X-w“Yw“Y ÿÿÿ±¿¤ _eYw“Y3 ÿÿÿ x”[@X-éôé_eYÿÿÿ±¿¤ ÿÿÿÿÿÿ‡¡jˆ¡l‰¢nÿÿÿÿÿÿl‹T3 •­{–¯}@X-ÿÿÿ_eY‘¦}3 3 ¥»Ž§½©¾’ª¿”¬Á–®Â—¯Äš±Åœ³ÇžµÈ ¶Ê¢¸Ë£ºÌ¦¼Î§½Ï©¿Ñ«ÀÓ­ÂÓ¯ÃÕ°ÅÖ²ÆØµÈÙ¶ÊÚ·ÌܹÍݼÎÞ½Ðß¿ÑàÀÒâÂÔãÃÕäÅÛé̪¿”w“Yw“Yw“Y   _eYw“Yw“Yÿÿÿw“Y ±¿¤_eY3 ÿÿÿy”[y•\z•\ÿÿÿÿÿÿœeÿÿÿ±¿¤‡ jˆ¢l‰¢n3 ÉÛ½éôé3 ©v@X-3 3 –®}™jÿÿÿ3 ´„Ÿµ‡±¿¤3 _eY§¼©¾’«À”¬Á•­Â˜¯Äš±Å›³ÇžµÈ ¶É¢·Ë¤¹Ì¥»Í§½Ðª¾Ð«ÀÒ­ÁÔ¯ÄÔ±ÅÖ²Ç×´ÉÙ¶ÉÚ¸ËÛºÌÝ»ÎÞ½Ðß¾ÑáÀÒáÂÔãÃÔäÅÛé̪¿”w“Yw“Yw“Y @X-w“Yw“Yw“Y@X-±¿¤ w“Yw“Y±¿¤3 ÿÿÿy”[y•\z–\{—^ÿÿÿÿÿÿ‚œeƒfÿÿÿˆ¡l‰£nФo3 ÿÿÿ©v3 @X-3 @X-™jÉÛ½3 ³„žµ† ¶ˆ‘¦}_eY©½’ª¿”¬À–®Ã˜¯Ã™±Æœ³Ç´È ¶Ê¢¸Ë¤ºÌ¥¼Î§½Ð©¿Ð«ÀÒ­ÂÓ®ÄÕ°ÅÖ²ÇØ´ÈÙ¶ÊÛ¸ËܹÍÝ»ÎÞ½Ïß¿ÑàÀÓáÂÓãÄÔäÄÜȩ́“w“Yw“Y_eYÿÿÿw“Yw“Yw“Yw“Y¡¿‰3 w“Yw“Yéôéÿÿÿy”[y•\{•]{–]|—_ ÿÿÿ›eƒf@X-@X-_eY@X-‰£m‹¤o ÿÿÿ3 ¨v’ªx3 ‘¦}™jÉÛ½3 œ³„Ÿµ‡ ·ˆ¢¸Šéô驾’ªÀ”¬Á–®Â˜°Äš±Æœ³Çž´È ¶É¢¸Ë£ºÌ¥»Î§½Ð©¿Ð«ÀÒ­ÂÔ®ÃÕ°ÅÖ³ÆØ´ÈÙ¶ÊÚ¸ËÛºÌÝ»ÎÞ½Ïß¿ÑàÀÓâÂÓâÃÕäÄÛéÌzŒll‹T3 l‹Tÿÿÿÿÿÿl‹T3 w“Yw“Yw“Y3 ÿÿÿw“Yw“Yw“Yÿÿÿÿÿÿy•[z•\z•\{—^|˜_@X-ééÓÿÿÿœe‚g„žg ÿÿÿ‰£nФo_eY3 ÿÿÿ ’ªx“«yéôéÿÿÿÿÿÿ3 ´„žµ† ·‰¢¸Š¤¹Œ±¿¤3 «¿”¬Á–®Â˜°Äš²Åœ³ÇµÈŸ¶Ê¡¸Ë£ºÍ¥»Î§½Ð©¿Ñ«ÁÒ­ÂÓ¯ÃÕ±ÅÖ³ÆØ´ÈÙ¶ÊÚ¸ËܺÌݼÎÞ¼Ïà¾ÑàÀÒâÂÔâÃÕäÅÛé̪¿“w“Yw“Yw“Y   w“Yw“Yw“Yw“YÉÛ½l‹T3 w“Yw“Y_eY@X-ÿÿÿy”Zy•\z•\{—]|—^}˜_ÿÿÿ‚œeƒfƒžg…ŸiééÓÿÿÿ3 ФoŒ¥qÿÿÿ3 ‘ªx“«y•­{ÿÿÿÿÿÿ ´…Ÿµ† ¶ˆ¢¸Š¤¹Œ_eY  ª¿”¬Á–®Ã˜°Äš±Æœ³ÇµÈŸ·É¢¸Ë¤¹Í¥¼Í¨½Ï©¾Ñ«ÀÒ­ÂÓ¯ÃÕ±ÅÖ³ÆØ´ÈÙ¶ÊÚ¸ËܹÍÝ»ÎÞ½Ïß¾ÐáÀÒâÂÔâÄÕäÅÛé̪¿“w“Yw“Yw“Y_eY™j3 w“Yw“Yw“Yw“Yÿÿÿw“Yw“Yw“Y ÿÿÿ y”[y•\z–]{–^|—^}˜`ÿÿÿ@X-œe‚œfƒžg… iÿÿÿ3 ‹¤o‹¥q_eY ÿÿÿ@X-“«z•­{@X-‘¦}ÿÿÿ³„žµ† ·ˆ¢¸‹¤ºŒ¥»Ž@X-«¿”¬Á•®Ã˜¯Äš±Åœ³ÇµÈ ¶É¡¸Ë£ºÌ¥»Î¨½Ï©¾Ñ«ÀÒ­ÂÓ¯ÄÕ±Å×²ÆØ´ÈÙ¶ÊÚ·ËܹÍݼÎß½Ïß¾ÑáÀÒâÂÓâÃÔãÄÛé̪¿“w“Yw“Yw“Z™jÿÿÿ3  w“Yw“Yw“Yw“Yÿÿÿ w“Yw“Yw“Y@X-ÿÿÿ y•\z–]{–^|—_}™`ÿÿÿ_eY@X-ƒfƒžh…Ÿi_eY3 ÿÿÿŒ¥q¦r_eY @X-@X-•­{—®} éôél‹T´„žµ‡ ·ˆ¢¸Š¤¹Œ¥ºŽ§¼©¾’ªÀ”¬Á–­Â˜¯Ãš±Åœ³ÆžµÈ ¶É¢¸Ë¤ºÍ¥¼Î¨½Ï©¾Ð«ÁÒ­ÂÓ¯ÄÕ±Å×²ÆØ´ÈÙ¶ÊÚ¸ËÛºÍÜ»ÎÞ½Ðß¿ÐáÀÒâÁÓãÃÕäÄÛé̪¿“w“Yw“Y3 ÿÿÿ@X-3 éôé w“Yw“Yw“Y_eY ÿÿÿw“Yw“Yÿÿÿy•\z–]{–]|—_}˜`ÿÿÿÉÛ½@X-‚fƒžg…Ÿi† kÿÿÿ™j@X-¦s¨t@X-ÿÿÿ _eY—®}˜°@X-ÿÿÿ_eYŸµ‡ ·ˆ¡¸Š¤¹¦»Ž§¼©¾’ªÀ”¬Á–®Â˜¯Ãš±Åœ³ÇžµÈ ¶Ê¡¸Ë¤ºÌ¥»Î§½Ï©¿Ð«ÀÒ­ÁÓ¯ÃÕ°ÅÖ²Æ×´ÈÙ¶ÊÚ¸ËÛ¹ÍݼÎÞ½Ïß¾ÐàÀÒâÁÔãÃÕäÅÛé̪¾“w“Y@X-±¿¤ÿÿÿÿÿÿ ÿÿÿÿÿÿ_eYw“Yw“Y@X-@X-ÉÛ½w“Yÿÿÿ_eY_eYz–\{–^|—^}˜`ÿÿÿÉÛ½3 ƒf„žh…Ÿi† j ÿÿÿÿÿÿ¦s§t©v ÿÿÿ_eY˜° ÿÿÿ3 Ÿµ†¡·ˆ¢¸Š£ºŒ¥»Ž§½¨¾’ª¿”¬Á–®Ã˜¯Ãš±Å›³ÆžµÈ ¶Ê¡¸Ë£¹Ì¥¼Î§½Ðª¾Ñ«ÀÒ­ÂÓ¯ÄÕ±ÅÖ³Ç×´ÈÙ¶ÉÚ¸ËܺÍݼÎÞ½Ïà¿ÑàÀÒáÂÓãÃÕäÄÛé̪¾“w“Y@X- ÿÿÿ3 @X-™j3 ÿÿÿw“Yw“Yw“Y@X-@X-ÉÛ½@X-ÿÿÿÿÿÿ{–]{—]|—^}˜`ÿÿÿÉÛ½3 ‚f„žh…Ÿi† j3 ÉÛ½ÿÿÿ3 §rލt©v_eY ÿÿÿ ±¿¤ÿÿÿŸµ‡ ¶‰¢¸‹¤¹Œ¦»Ž§¼¨¾’ª¿”¬Á–®Â˜°Äš²Åœ³ÇžµÈ ¶Ê¡¸Ë£¹Ì¥¼Î§½Ï©¾Ð«ÀÒ¬ÁÓ¯ÃÕ°ÅײÇ×´ÈÙ¶ÊÚ¸ËÛºÌÝ»ÎÞ½Ðà¿ÑáÀÓâÂÓãÃÕãÄÛéͪ¾“w“Y3 ÿÿÿ_eYÿÿÿ3 _eY3 ÿÿÿÿÿÿ3 w“Yw“Yw“Y@X- ÿÿÿÿÿÿéôéééÓz•]{–]|—_}˜`@X-™jÉÛ½@X-ƒf„žh…Ÿi† kˆ¡lÿÿÿl‹T¦r¨t©v’ªx“¬zéôéÿÿÿÿÿÿ‘¦} žµ† ¶‰¢¸‹£ºŒ¦»Ž§½©¾’ª¿”¬À–®Â—¯Äš±Åœ³ÇžµÈŸ¶É¢¸Ë£ºÍ¥»Î§½Ï©¿Ñ¬ÀÒ­ÂÔ¯ÃÕ±ÅÖ³Æ×´ÈضÊÚ¸ËÛºÌÝ»ÎÞ½Ðß¾ÑáÀÓáÂÔãÄÕäÄÜé̪¾“w“Y@X-ÿÿÿÿÿÿ@X-@X-w“Y ÿÿÿl‹Tÿÿÿw“Yw“Yw“Yw“Y_eYl‹T@X-_eYz–]{–^|—_}˜`~™a3 _eY‚f„žh…Ÿi‡ kˆ¢l@X-‘¦}ާr§t‘©v’ªx“«z•­{ 3 l‹T@X-Ÿµ‡¡¶‰¡¸Š¤ºŒ¥»Ž§¼©¾’«¿”¬Á–®Â˜°Äš²Åœ³ÆµÈŸ·Ê¡¸Ë£ºÌ¥»Î§½Ðª¾Ð«ÀÒ­ÂÓ¯ÃÕ±ÅÖ²ÇØ´ÈÙ¶ÊÛ¸ËÛºÍÜ»ÎÞ½Ðß¾ÐàÀÒáÁÓâÄÕäÅÛé̪¾“ ééÓÿÿÿÿÿÿ3 w“Yw“Y3 ÿÿÿÿÿÿÿÿÿw“Yw“Yw“Yw“Yw“Yw“Yw”Zy”[z•\z–]{–^|—_}˜`~™ašb€›d‚œeƒfƒžg… i‡ jˆ¢l‰¢n3 _eY¦rާt©v‘ªx“«z•­{—®}˜°š±€›²‚´…Ÿ¶† ·ˆ¢¸Š¤¹Œ¥»Ž¦½©¾’ª¿”¬Á–®Â˜°Äš±Åœ³ÆžµÈ ¶É¢¸Ë£ºÍ¥»Î¨½Ð©¿Ñ«ÀÒ­ÁÓ¯ÄÕ±Å×²ÇØ´ÈÙ¶ÊÚ·ËÛ¹ÍÜ»ÎÞ¼Ðß¿ÑàÀÒâÁÔãÃÕäÅÜé̪¾“3 ééÓéôéÿÿÿ3 _eYw“Y3 ÿÿÿ™jééÓÿÿÿ™j3 w“Yw“Yw“Yw“Yw“Yx”Zx”Zz•[z–\{—^|—_}˜`~™ašb€›d‚œeƒf„žh…Ÿj† jˆ¡l‰£nФoŒ¥q¦r§t©v’«x“«y•­{—®}˜°™°€›²ƒ´…Ÿµ† ¶ˆ¢¸Š¤¹Œ¥»Ž§¼©½’ª¿“¬À–®Â˜¯Äš²Åœ³ÇµÈŸ¶Ê¡¸Ë¤¹Í¦¼Î§½Ð©¾Ñ«ÀÒ­ÂÔ¯ÃÕ±ÅÖ²Æ×´ÈÙ¶ÊÚ¸ËܺÌݼÎÞ½Ðß¾ÑàÀÒáÂÔãÃÔäÄÛé̪¾“ÿÿÿ ÿÿÿw“Yw“Yw“Y3 ÿÿÿ ÿÿÿÿÿÿÿÿÿ w“Yw“Yw“Yw“Yx”Zy”[y•\z•]{—^|˜_}˜`~™ašb€šdœeƒf„žh…Ÿi† jˆ¡m‰¢nФpŒ¥qަr§t©v’ªw“«y•­{–®}˜¯™±€œ²ƒ´„Ÿµ† ·ˆ¢¸Š£º¥»Ž§½©¾’ª¿“¬Á–®Ã˜¯Äš±Åœ³ÆžµÈŸ¶Ê¡¸Ë£ºÍ¥»Î¨¼Ï©¿Ñ«ÀÒ­ÁÔ¯ÃÔ±ÅÖ³ÇØ´ÈÙ¶ÊÚ¸ËÛ¹ÌÝ»ÎÞ¼Ðß¿ÐáÀÒáÂÔâÃÕäÄÛé̪¾“@X-ÿÿÿ ÿÿÿ@X-w“Yw“Yw“Y ÿÿÿl‹Tÿÿÿÿÿÿÿÿÿ3 w“Yw“Yw“Yw“Zx”Zx”[y•[z–\{–^|—^}˜`~™ašb€›d‚œe‚f„žh…Ÿi‡ k‡¡l‰¢nФoŒ¥q¦s§t©v’ªx“«z•­{–®}˜°™±›²ƒœ´„Ÿµ‡ ¶ˆ¢¸‹¤¹Œ¥»Ž§½¨½’«À”¬Á–®Â˜°Äš±Åœ³Çž´È ·Ê¢¸Ë£ºÌ¦»Î§½Ð©¿Ð«ÁÒ­ÂÓ¯ÄÕ±ÅÖ³ÇØ´ÈÙ¶ÉÚ¸ËÛºÍÝ»ÎÞ½Ïß¿ÑàÀÒâÂÓãÄÕäÅÛé̦“ ÿÿÿ@X-ÿÿÿ@X-w“Yw“Yw“Y ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÛ½ w“Yw“Yw“Yx”Zx”Zy•[z–]{—]|˜_}˜`~™ašc›dœe‚fƒžh… i‡¡kˆ¡m‰£n‹¤oŒ¥q§rާu‘©v‘ªx“«y•­{–®}˜°™±›²ƒ³…žµ†¡·ˆ¢¸Š¤¹Œ¥»Ž§¼©½’ªÀ”¬À–®Â˜°Äš±Åœ³ÆžµÈ ·É¢¸Ë£ºÍ¥¼Î§½Ï©¿Ñ«ÀÒ­ÂÓ¯ÃÕ°ÅÖ³Ç×´ÈÙ¶ÉÛ·ËܹÍÝ»ÎÞ½Ðß¿ÐàÀÓâÁÔãÄÕäÅÛé̪¾“q€fñöêñöêq€fª¾“ª¾“ª¿“ª¿”Ž }{lñ÷ê{lñ÷êñ÷êñ÷êñ÷êqfª¿”ª¿”«¿”«À”«À•¬Á•¬Á–­Á—­Â—®Â˜®Â™¯Ãš°Äš°Ä›±Å›±Æœ²Æ³Æž³ÆŸ´ÇŸµÈ µÈ¡¶É¡·Ê¢¸Ê£¹Ë¤¹Ì¥ºÌ¦»Í§¼Î¨¼Î©¾Ïª¿Ð«¿Ñ¬ÀÑ­ÁÒ®ÂÓ°ÃÓ°ÄÔ±ÄÖ²ÆÖ³Æ×´ÇØµÈØ¶ÈÙ·ÊÚ¸ËÛ¹ÌÛºÌܼÎݼÎݾÏÞ¾Ðß¿ÑßÀÑàÁÒáÂÓâÃÔãÄÔãÅÖäÆ×äÇ×åÇØæÈÙæÉÙçÊÚèËÛèËÛéÌkaya-0.4.4/examples/shape/0000755000175100017510000000000011170340772013470 5ustar cimcimkaya-0.4.4/examples/shape/shape.k0000644000175100017510000000666011170340772014754 0ustar cimcimcgi shape; // -*-C-*-ish import CGI; import primitives; import Image; Void PreContent() { content("Shape Thingy"); content("

    Shape Thingy

    "); } Void Default() { // prim = Primitive(Rectangle(DrawColour(255,0,0),50,50),80,80); drawing = Drawing(480,320,DrawColour(0,0,0),[]); showDrawing(drawing); addShapeForm(drawing); } Void showDrawing(Drawing d) { content("
    "); content(imageHandler(draw,d,"[Pretty picture]",d.x,d.y)); content(""); idx = 0; for p in d.ps { case p.shape of { Rectangle(col,rx,ry) -> shape = "Rectangle"; | Ellipse(col,ex,ey) -> shape = "Ellipse"; | Triangle(col,tb,th) -> shape = "Triangle"; } content(shape+" at ("+p.x+","+p.y+") "); content(linkHandler(deleteShape,(d,idx),"Delete")+"
    "); idx++; } content("
    "); } Void deleteShape((Drawing,Int) didx) { d = didx.fst; idx = didx.snd; removeAt(d.ps,idx); showDrawing(d); addShapeForm(d); } HTML colourBox(String name) = selBox(name,3,["Red","Green","Yellow","Blue","White","Random"]); Void addShapeForm(Drawing d) { content("

    Add a shape

    "); content(formHandler(OnAddShape,d)); content(""+ ""+ ""+ ""+ ""+ ""+ ""+ ""); content(""+ ""+ ""+ ""+ ""+ ""+ ""+ ""); content(""+ ""+ ""+ ""+ ""+ ""+ ""+ ""); content("
    RectangleX"+textBox("rx","",5)+"Y"+textBox("ry","",5)+"Width"+textBox("rw","",5)+"Height"+textBox("rh","",5)+"Colour"+colourBox("rcol")+""+submit("Add Rectangle")+"
    EllipseX"+textBox("ex","",5)+"Y"+textBox("ey","",5)+"Width"+textBox("ew","",5)+"Height"+textBox("eh","",5)+"Colour"+colourBox("ecol")+""+submit("Add Ellipse")+"
    TriangleX"+textBox("tx","",5)+"Y"+textBox("ty","",5)+"Base"+textBox("tb","",5)+"Height"+textBox("th","",5)+"Colour"+colourBox("tcol")+""+submit("Add Triangle")+"
    "); content(closeForm); } Void OnAddShape(Drawing d) { try { if (submitUsed=="Add Rectangle") { x = httpInt("rx"); y = httpInt("ry"); w = httpInt("rw"); h = httpInt("rh"); c = mkColour(incomingValue("rcol",DataPost)); shape = Primitive(Rectangle(c,w,h),x,y); } else if (submitUsed=="Add Ellipse") { x = httpInt("ex"); y = httpInt("ey"); w = httpInt("ew"); h = httpInt("eh"); c = mkColour(incomingValue("ecol",DataPost)); shape = Primitive(Ellipse(c,w,h),x,y); } else if (submitUsed=="Add Triangle") { x = httpInt("tx"); y = httpInt("ty"); b = httpInt("tb"); h = httpInt("th"); c = mkColour(incomingValue("tcol",DataPost)); shape = Primitive(Triangle(c,b,h),x,y); } push(d.ps,shape); } catch(e) { content("

    Invalid input!

    "); } showDrawing(d); addShapeForm(d); } Void PostContent() { content("
    shape.k
    "); content("primitives.k
    "); content("Memory usage: "+gcHeapSize); content(""); } kaya-0.4.4/examples/shape/primitives.k0000644000175100017510000000301611170340772016037 0ustar cimcimmodule primitives; // -*-C-*-ish import Image; import CGI; import Time; import Logger; public data DrawColour(Int r, Int g, Int b); public data Shape = Rectangle(DrawColour rcol, Int rx, Int ry) | Ellipse(DrawColour ecol, Int ex, Int ey) | Triangle(DrawColour tcol, Int base, Int height); public data Primitive(Shape shape, Int x, Int y); public data Drawing(Int x, Int y, DrawColour bg,[Primitive] ps); public DrawColour mkColour(String s) { if (s=="Red") { return DrawColour(255,0,0); } else if (s=="Green") { return DrawColour(0,255,0); } else if (s=="Blue") { return DrawColour(0,0,255); } else if (s=="Yellow") { return DrawColour(255,255,0); } else if (s=="White") { return DrawColour(255,255,255); } else { srand(now); return DrawColour(rand()%255,rand()%255,rand()%255); } } public Void draw(Drawing d) { header("Content-type: image/png"); i = create(d.x,d.y); bg = makeColour(i,d.bg.r,d.bg.g,d.bg.b); // DrawColour col = DrawColour(0,0,0); for p in d.ps { case p.shape of { Rectangle(col,x,y) -> c = makeColour(i,col.r,col.g,col.b); rectangle(i, p.x, p.y, p.shape.rx+p.x, p.shape.ry+p.y, c, true); | Ellipse(col,x,y) -> c = makeColour(i,col.r,col.g,col.b); ellipse(i, p.x, p.y, p.shape.ex, p.shape.ey, c, true); | Triangle(col,base,height) -> c = makeColour(i,col.r,col.g,col.b); poly(i,[(p.x,p.y),(p.x+base/2,p.y-height),(p.x+base,p.y)],c,true); } } CGI::flushAll(); makePNG(i); } kaya-0.4.4/examples/parser/0000755000175100017510000000000011170340772013664 5ustar cimcimkaya-0.4.4/examples/parser/calclang.k0000644000175100017510000000465711170340772015620 0ustar cimcimmodule calclang; // -*-C-*-ish import IO; import Parse; import Dict; abstract data Expr = Var(String name) | Assign(String varname, Expr val) | Num(Int num) | Infix(Op op,Expr l, Expr r); data Op = Plus | Minus | Times | Divide; Expr parseExpr(var ParseState st) = (parseAssign `or` parsePlusMinus `or` parseMultDiv `or` parseBrackets `or` parseVar `or` parseNum)(st); Expr parseVar(var ParseState st) = Var(identifier(st)); Expr parseNum(var ParseState st) { num = Num(integer(st)); return num; } Expr parseBrackets(var ParseState st) { c = char('(',st); exp = parseExpr(st); c = char(')',st); return exp; } Expr parsePlusMinus(var ParseState st) { left = (parseMultDiv `or` parseBrackets `or` parseNum `or` parseVar)(st); // putStrLn(st.input); whitespace(st); opch = ((char@('+')) `or` (char@('-')))(st); whitespace(st); if (opch=='+') { op = Plus; } else if (opch=='-') { op = Minus; } right = parseExpr(st); return Infix(op,left,right); } Expr parseAssign(var ParseState st) { name = identifier(st); whitespace(st); opch = char('=',st); whitespace(st); exp = parseExpr(st); return Assign(name, exp); } Expr parseMultDiv(var ParseState st) { left = (parseBrackets `or` parseNum `or` parseVar)(st); whitespace(st); opch = ((char@('*')) `or` (char@('/')))(st); whitespace(st); if (opch=='*') { op = Times; } else if (opch=='/') { op = Divide; } right = (parseBrackets `or` parseMultDiv `or` parseNum `or` parseVar)(st); return Infix(op,left,right); } type Context = Dict; Exception NoSuchVariable(String v); Int eval(Context ctxt, Expr e) { case e of { Num(x) -> return x; | Var(v) -> case lookup(ctxt,v) of { nothing -> throw(NoSuchVariable(v)); | just(val) -> return val; } | Assign(v,expr) -> ev = eval(ctxt,expr); add(ctxt, v, ev); return ev; | Infix(op,l,r) -> case op of { Plus -> return eval(ctxt,l)+eval(ctxt,r); | Minus -> return eval(ctxt,l)-eval(ctxt,r); | Times -> return eval(ctxt,l)*eval(ctxt,r); | Divide -> return eval(ctxt,l)/eval(ctxt,r); } } } Exception CalcParseError(String err, Int p); public Int calcExpr(Context ctxt, String strexp) { case parse(parseExpr, strexp) of { Success(expr) -> return eval(ctxt, expr); | ParseError(err,l,p) -> throw(CalcParseError(err,p)); } } kaya-0.4.4/examples/parser/webcalc.k0000644000175100017510000000231011170340772015434 0ustar cimcimcgi webcalc; // -*-C-*-ish import CGI; import calclang; import Dict; Void PreContent() { content("Web Calculator"); content(""); content("

    Web Calculator

    "); } Void Default() { runCalc(Dict::new()); } Void runCalc(Context ctxt) { content("

    Defined variables

    "); displayVars(ctxt); content("
    "); content(formHandler(OnCalc,ctxt)+ "Sum "+textBox("sum","",40)+ submit("Calculate")+ closeForm()); } Void displayVars(Context ctxt) { for p in entries(ctxt) { content(p.fst+" = "+p.snd+"
    "); } } Void OnCalc(Context ctxt) { sum = incomingValue("sum",DataPost); content("

    "); try { res = calcExpr(ctxt, sum); content("


    "+sum+ " = "+res+"
    "); } catch(CalcParseError(err,p)) { content("Error: "+err+" at position "+p+""); } catch(e) { content("Error: "+exceptionMessage(e)+""); } content("

    "); runCalc(ctxt); } String sc(String f) = "
  • "+f+""; Void PostContent() { content("