├── src ├── w32 │ └── libqtoc.def ├── makeprint.q ├── k.h ├── printq.c └── makeq.c ├── docs ├── icons │ ├── apple.png │ ├── linux.png │ └── windows.png ├── InterfacingWithC.docx └── InterfacingWithC.pdf ├── .gitignore ├── CMakeLists.txt └── README.md /src/w32/libqtoc.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | makeq 3 | printq -------------------------------------------------------------------------------- /docs/icons/apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataIntellectTech/kdb-c-interface/HEAD/docs/icons/apple.png -------------------------------------------------------------------------------- /docs/icons/linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataIntellectTech/kdb-c-interface/HEAD/docs/icons/linux.png -------------------------------------------------------------------------------- /docs/icons/windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataIntellectTech/kdb-c-interface/HEAD/docs/icons/windows.png -------------------------------------------------------------------------------- /docs/InterfacingWithC.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataIntellectTech/kdb-c-interface/HEAD/docs/InterfacingWithC.docx -------------------------------------------------------------------------------- /docs/InterfacingWithC.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataIntellectTech/kdb-c-interface/HEAD/docs/InterfacingWithC.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | -------------------------------------------------------------------------------- /src/makeprint.q: -------------------------------------------------------------------------------- 1 | make:`:./libqtoc 2:(`makeq;1) 2 | print:`:./libqtoc 2:(`printq;1) 3 | 4 | -1"##"; 5 | -1"# makeprint.q"; 6 | -1"# "; 7 | -1"# Example q script that loads in two functions from the libqtoc shared object"; 8 | -1"# and makes them available as 'make' and 'print'."; 9 | -1"#"; 10 | -1"# AquaQ Analytics"; 11 | -1"# kdb+ consultancy, training and support"; 12 | -1"#"; 13 | -1"# For questions, comments, requests or bug reports, please contact us"; 14 | -1"# w: www.aquaq.co.uk"; 15 | -1"# e: support@aquaq.co.uk"; 16 | -1"#"; 17 | -1"# examples:"; 18 | -1"# \tprint[1b] to print an atom"; 19 | -1"# \tprint[101b] to print a list"; 20 | -1"# \tprint[`a`b`c!1 2 3] to print a dictionary]"; 21 | -1"# \tprint[([] a:til 5; b:reverse `char$65+til 5)] to print a table"; 22 | -1"#"; 23 | -1"# \tmake[`b] to create a atom"; 24 | -1"# \tmake[`B] to create a list"; 25 | -1"# \tmake[`dictionary] to create a dictionary"; 26 | -1"# \tmake[`table] to create a table\n\n"; 27 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(libqtoc C) 3 | 4 | # Create the binary directory for makefile output and copy over 5 | # a test q script. 6 | file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/bin") 7 | file(COPY "src/makeprint.q" DESTINATION "${CMAKE_SOURCE_DIR}/bin") 8 | 9 | set(PROJ_SOURCES "src/makeq.c" "src/printq.c") 10 | 11 | # Set some operating system dependent flags to be passed to the 12 | # compilers. 13 | if(UNIX) 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -fpic -std=gnu99") 15 | elseif(WIN32) 16 | set(LINK_LIBS "${CMAKE_SOURCE_DIR}/src/w32/q.lib") 17 | set(PROJ_SOURCES ${PROJ_SOURCES} "src/w32/libqtoc.def") 18 | endif() 19 | 20 | # Define how the library should be linked to the other objects. 21 | add_library(libqtoc SHARED ${PROJ_SOURCES}) 22 | target_link_libraries(libqtoc ${LINK_LIBS}) 23 | set_target_properties(libqtoc PROPERTIES PREFIX "") 24 | 25 | # Move the finished binaries into the binary folder if installing. 26 | INSTALL(TARGETS libqtoc DESTINATION "${CMAKE_SOURCE_DIR}/bin") 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Interfacing KDB+ with C 2 | 3 | This project demonstrates how to marshall data between kdb+ and C using the Kx provided interface. A shared 4 | object is built as the output and a q script is provided that will show how to load the C functions into kdb+ 5 | dynamically. 6 | 7 | The PDF documentation for this resource can be found [here][gitpdfdoc] and also on the [AquaQ Analytics][aquaqresources] 8 | website. 9 | 10 | Installation & Setup 11 | -------------------- 12 | 13 | ### Extra Resources 14 | You will need to download the `q.lib` file from the code.kx.com/svn repository for Windows platforms 15 | and place it in the w32/ directory. 16 | 17 | This project uses CMake 2.6+ to build across multiple platforms. It has been tested on Linux and 18 | Windows. Execute the following commands on all platforms to create platform appropriate build 19 | files within the `build` directory. 20 | 21 | ```sh 22 | mkdir build; cd build; cmake .. 23 | ``` 24 | 25 | ### Building on Linux 26 | 27 | On Linux, you just need to run make install to complete the build process 28 | and find the binary output in the `../bin` directory. 29 | 30 | ```sh 31 | make install && cd ../bin 32 | ``` 33 | 34 | ### Building on Windows 35 | 36 | On Windows platforms you will need to have the msbuild.exe available on your path. CMake creates 37 | two Visual Studio projects that need to be built. The `INSTALL` project will not modify any of the 38 | code and will just move the binaries from the `../build` directory to the `../bin` directory. An 39 | extra `libqtoc.lib` file will be produced on Windows, which can be ignored after the build process. 40 | 41 | ```bat 42 | msbuild ./ALL_BUILD.vcxproj /p:Configuration=Release 43 | msbuild ./INSTALL.vcxproj /p:Configuration=Release 44 | cd ../bin 45 | ``` 46 | 47 | Running the Examples 48 | -------------------- 49 | 50 | The resulting directory after running a build should look like this: 51 | 52 | bin/ -- contains the libqtoc.[dll/so] library and makeprint.q 53 | build/ -- contains the makefile/visual studio projects 54 | src/ -- contains the source code 55 | CMakeLists.txt 56 | 57 | Once the build is complete, navigate to the `bin` directory and execute: 58 | 59 | q makeprint.q 60 | 61 | This will load the C shared object and bind the functions to names (*make* and *print*). Instructions 62 | and example commands should be displayed as soon as the the makeprint.q script loads. 63 | 64 | ```apl 65 | ## 66 | # makeprint.q 67 | # 68 | # Example q script that loads in two functions from the libqtoc shared object 69 | # and makes them available as 'make' and 'print'. 70 | # 71 | # AquaQ Analytics 72 | # kdb+ consultancy, training and support 73 | # 74 | # For questions, comments, requests or bug reports, please contact us 75 | # w: www.aquaq.co.uk 76 | # e: support@aquaq.co.uk 77 | # 78 | # examples: 79 | # print[1b] to print an atom 80 | # print[101b] to print a list 81 | # print[`a`b`c!1 2 3] to print a dictionary] 82 | # print[([] a:til 5; b:reverse `char$65+til 5)] to print a table 83 | # 84 | # make[`b] to create a atom 85 | # make[`B] to create a list 86 | # make[`dictionary] to create a dictionary 87 | # make[`table] to create a table 88 | q) print[`a`b`c!1 2 3] 89 | a | 1 90 | b | 2 91 | c | 3 92 | q) make[`M] 93 | 2011.12 2014.05 2019.05 2018.07 2012.09m 94 | ``` 95 | 96 | Other Resources 97 | --------------- 98 | 99 | This resource is intended to suppliment the existing Kx Wiki sections on interfacting with C 100 | and provide some concrete examples. Readers should look at the following pages on the Kx Wiki: 101 | 102 | * [Interfacing With C][kxwikiinterface] 103 | * [Extending With C][kxwikiextend] 104 | 105 | [aquaqwebsite]: http://www.aquaq.co.uk "AquaQ Analytics Website" 106 | [aquaqresources]: http://www.aquaq.co.uk/resources "AquaQ Analytics Website Resources" 107 | [gitpdfdoc]: https://github.com/markrooney/kdb-c-interface/blob/master/docs/InterfacingWithC.pdf 108 | [kxwikiinterface]: http://code.kx.com/wiki/Cookbook/InterfacingWithC "Kx Wiki Interfacing with C" 109 | [kxwikiextend]: http://code.kx.com/wiki/Cookbook/ExtendingWithC "Kx Wiki Extending with C" -------------------------------------------------------------------------------- /src/k.h: -------------------------------------------------------------------------------- 1 | #ifndef KX 2 | #define KX 3 | typedef char*S,C;typedef unsigned char G;typedef short H;typedef int I;typedef long long J;typedef float E;typedef double F;typedef void V; 4 | #ifdef __cplusplus 5 | extern"C"{ 6 | #endif 7 | #ifndef KXVER 8 | #error "Set KXVER=3 for kdb+3.0 or standalone c-api after 2011-04-20. Otherwise set KXVER=2" 9 | #endif 10 | #if KXVER>=3 11 | typedef struct k0{signed char m,a,t;C u;I r;union{G g;H h;I i;J j;E e;F f;S s;struct k0*k;struct{J n;G G0[1];};};}*K; 12 | typedef struct{G g[16];}U; 13 | #define kU(x) ((U*)kG(x)) 14 | #define xU ((U*)xG) 15 | extern K ku(U),ktn(I,J),kpn(S,J); 16 | extern I setm(I); 17 | #define DO(n,x) {J i=0,_i=(n);for(;i<_i;++i){x;}} 18 | #else 19 | typedef struct k0{I r;H t,u;union{G g;H h;I i;J j;E e;F f;S s;struct k0*k;struct{I n;G G0[1];};};}*K; 20 | extern K ktn(I,I),kpn(S,I); 21 | #define DO(n,x) {I i=0,_i=(n);for(;i<_i;++i){x;}} 22 | #endif 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | //#include 27 | // vector accessors, e.g. kF(x)[i] for float&datetime 28 | #define kG(x) ((x)->G0) 29 | #define kC(x) kG(x) 30 | #define kH(x) ((H*)kG(x)) 31 | #define kI(x) ((I*)kG(x)) 32 | #define kJ(x) ((J*)kG(x)) 33 | #define kE(x) ((E*)kG(x)) 34 | #define kF(x) ((F*)kG(x)) 35 | #define kS(x) ((S*)kG(x)) 36 | #define kK(x) ((K*)kG(x)) 37 | 38 | // type bytes qtype ctype accessor 39 | #define KB 1 // 1 boolean char kG 40 | #define UU 2 // 16 guid U kU 41 | #define KG 4 // 1 byte char kG 42 | #define KH 5 // 2 short short kH 43 | #define KI 6 // 4 int int kI 44 | #define KJ 7 // 8 long long kJ 45 | #define KE 8 // 4 real float kE 46 | #define KF 9 // 8 float double kF 47 | #define KC 10 // 1 char char kC 48 | #define KS 11 // * symbol char* kS 49 | 50 | #define KP 12 // 8 timestamp long kJ (nanoseconds from 2000.01.01) 51 | #define KM 13 // 4 month int kI (months from 2000.01.01) 52 | #define KD 14 // 4 date int kI (days from 2000.01.01) 53 | 54 | #define KN 16 // 8 timespan long kJ (nanoseconds) 55 | #define KU 17 // 4 minute int kI 56 | #define KV 18 // 4 second int kI 57 | #define KT 19 // 4 time int kI (millisecond) 58 | 59 | #define KZ 15 // 8 datetime double kF (DO NOT USE) 60 | 61 | // table,dict 62 | #define XT 98 // x->k is XD 63 | #define XD 99 // kK(x)[0] is keys. kK(x)[1] is values. 64 | 65 | #ifdef __cplusplus 66 | extern"C"{ 67 | extern V m9(); 68 | #else 69 | extern V m9(V); 70 | #endif 71 | extern I khpun(const S,I,const S,I),khpu(const S,I,const S),khp(const S,I),okx(K),ymd(I,I,I),dj(I);extern V r0(K),sd0(I),kclose(I);extern S sn(S,I),ss(S); 72 | extern K ktj(I,J),ka(I),kb(I),kg(I),kh(I),ki(I),kj(J),ke(F),kf(F),kc(I),ks(S),kd(I),kz(F),kt(I),sd1(I,K(*)(I)),dl(V*f,I), 73 | knk(I,...),kp(S),ja(K*,V*),js(K*,S),jk(K*,K),jv(K*k,K),k(I,const S,...),xT(K),xD(K,K),ktd(K),r1(K),krr(const S),orr(const S),dot(K,K),b9(I,K),d9(K); 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | 78 | // nulls(n?) and infinities(w?) 79 | #define nh ((I)0xFFFF8000) 80 | #define wh ((I)0x7FFF) 81 | #define ni ((I)0x80000000) 82 | #define wi ((I)0x7FFFFFFF) 83 | #define nj ((J)0x8000000000000000LL) 84 | #define wj 0x7FFFFFFFFFFFFFFFLL 85 | #if WIN32 || _WIN32 86 | #define nf (log(-1.0)) 87 | #define wf (-log(0.0)) 88 | #define isnan _isnan 89 | #define finite _finite 90 | extern double log(double); 91 | #else 92 | #define nf (0/0.0) 93 | #define wf (1/0.0) 94 | #define closesocket(x) close(x) 95 | #endif 96 | 97 | // remove more clutter 98 | #define O printf 99 | #define R return 100 | #define Z static 101 | #define P(x,y) {if(x)R(y);} 102 | #define U(x) P(!(x),0) 103 | #define SW switch 104 | #define CS(n,x) case n:x;break; 105 | #define CD default 106 | 107 | #define ZV Z V 108 | #define ZK Z K 109 | #define ZH Z H 110 | #define ZI Z I 111 | #define ZJ Z J 112 | #define ZE Z E 113 | #define ZF Z F 114 | #define ZC Z C 115 | #define ZS Z S 116 | 117 | #define K1(f) K f(K x) 118 | #define K2(f) K f(K x,K y) 119 | #define TX(T,x) (*(T*)((G*)(x)+8)) 120 | #define xr x->r 121 | #define xt x->t 122 | #define xu x->u 123 | #define xn x->n 124 | #define xx xK[0] 125 | #define xy xK[1] 126 | #define xg TX(G,x) 127 | #define xh TX(H,x) 128 | #define xi TX(I,x) 129 | #define xj TX(J,x) 130 | #define xe TX(E,x) 131 | #define xf TX(F,x) 132 | #define xs TX(S,x) 133 | #define xk TX(K,x) 134 | #define xG x->G0 135 | #define xH ((H*)xG) 136 | #define xI ((I*)xG) 137 | #define xJ ((J*)xG) 138 | #define xE ((E*)xG) 139 | #define xF ((F*)xG) 140 | #define xS ((S*)xG) 141 | #define xK ((K*)xG) 142 | #define xC xG 143 | #define xB ((G*)xG) 144 | 145 | #endif 146 | 147 | -------------------------------------------------------------------------------- /src/printq.c: -------------------------------------------------------------------------------- 1 | //// 2 | // printq.c 3 | // 4 | // A simple example of how to access and print the 5 | // different K object types from C. Handles atoms, lists 6 | // dictionaries and tables (enumerated types and functions 7 | // are currently unsupported). 8 | // 9 | // @updated: 17/03/2015 10 | // @authors: Kent Lee, Kevin Piar, Mark Rooney 11 | // 12 | // AquaQ Analytics 13 | // kdb+ consultancy, training and support 14 | // 15 | // For questions, comments, requests or bug reports, please contact us 16 | // w: www.aquaq.co.uk 17 | // e: info@aquaq.co.uk 18 | // p: +44 (0)28 9051 1232 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define KXVER 3 27 | #include "k.h" 28 | 29 | K printq(K x); 30 | 31 | static void fmt_time(char *str, time_t time, int adjusted) 32 | { 33 | static char buffer[4096]; 34 | 35 | struct tm *timeinfo = localtime(&time); 36 | if (adjusted) timeinfo->tm_hour -= 1; 37 | strftime(buffer, sizeof(buffer), str, timeinfo); 38 | 39 | printf("%s ", buffer); 40 | } 41 | 42 | static K printatom(K x) 43 | { 44 | switch (xt) { 45 | case -1: printf("%db", x->g); break; 46 | case -4: printf("0x%02x", x->g); break; 47 | case -5: printf("%d", x->h); break; 48 | case -6: printf("%d", x->i); break; 49 | case -7: printf("%lld", x->j); break; 50 | case -8: printf("%.2f", x->e); break; 51 | case -9: printf("%.2f", x->f); break; 52 | case -10: printf("\"%c\"", x->g); break; 53 | case -11: printf("`%s", x->s); break; 54 | case -12: fmt_time("%Y.%m.%dD%H:%M:%S.", ((x->j) / 8.64e13 + 10957)*8.64e4, 0); break; 55 | case -13: printf("%04d.%02d", (x->i)/12+2000, (x->i)%12+1); break; 56 | case -14: fmt_time("%Y.%m.%d", ((x->i) + 10957)*8.64e4, 0); break; 57 | case -15: fmt_time("%Y.%m.%dD%H:%M:%S", ((x->f) + 10957)*8.64e4, 0); break; 58 | case -16: { fmt_time("%jD%H:%M:%S", (x->j)/1000000000, 1); 59 | printf(".%09lld", (x->j)%1000000000); break; } 60 | case -17: fmt_time("%H:%M", (x->i) * 60, 1); break; 61 | case -18: fmt_time("%H:%M:%S", x->i, 1); break; 62 | case -19: { fmt_time("%H:%M:%S", (x->i) / 1000, 1); 63 | printf(".%03d", (x->i)%1000); break; } 64 | default: return krr("notimplemented"); 65 | } 66 | 67 | return (K) 0; 68 | } 69 | 70 | #define showatom(c,a,x,i) do { K r = c(a((x))[i]); printatom(r); r0(r); } while(0) 71 | 72 | static K printitem(K x, int index) 73 | { 74 | switch (xt) { 75 | case 0: printq(kK(x)[index]); break; 76 | case 1: showatom(kb, kG, x, index); break; 77 | case 4: showatom(kg, kG, x, index); break; 78 | case 5: showatom(kh, kH, x, index); break; 79 | case 6: showatom(ki, kI, x, index); break; 80 | case 7: showatom(kj, kJ, x, index); break; 81 | case 8: showatom(ke, kE, x, index); break; 82 | case 9: showatom(kf, kF, x, index); break; 83 | case 10: showatom(kc, kC, x, index); break; 84 | case 11: showatom(ks, kS, x, index); break; 85 | case 14: showatom(kd, kI, x, index); break; 86 | case 15: showatom(kz, kF, x, index); break; 87 | default: return krr("notimplemented"); 88 | } 89 | 90 | return (K) 0; 91 | } 92 | 93 | static K printlist(K x) 94 | { 95 | if (x->n == 1) printf(","); 96 | 97 | for (int i = 0; i < x->n; i++) 98 | printitem(x, i); 99 | 100 | return (K) 0; 101 | } 102 | 103 | static K printdict(K x) 104 | { 105 | K keys = kK(x)[0]; 106 | K data = kK(x)[1]; 107 | 108 | for (int row = 0; row < keys->n; row++) { 109 | printitem(keys, row); 110 | printf("| "); 111 | printitem(data, row); 112 | if (row < keys->n - 1) printf("\n"); 113 | } 114 | 115 | return (K) 0; 116 | } 117 | 118 | static K printtable(K x) 119 | { 120 | K flip = ktd(x); 121 | K columns = kK(flip->k)[0]; 122 | K rows = kK(flip->k)[1]; 123 | 124 | int colcount = columns->n; 125 | int rowcount = kK(rows)[0]->n; 126 | 127 | for (int i = 0; i < colcount; i++) 128 | printf("%s\t", kS(columns)[i]); 129 | printf("\n"); 130 | 131 | for (int i = 0; i < rowcount; i++) { 132 | for (int j = 0; j < colcount; j++) { 133 | printitem(kK(rows)[j], i); 134 | printf("\t"); 135 | } 136 | printf("\n"); 137 | } 138 | 139 | return (K) 0; 140 | } 141 | 142 | K printq(K x) 143 | { 144 | K result; 145 | 146 | if (xt < 0) result = printatom(x); 147 | else if ((xt >= 0) && (xt < 20)) result = printlist(x); 148 | else if (xt == 98) result = printtable(x); 149 | else if (xt == 99) result = printdict(x); 150 | else result = krr("notimplemented"); 151 | 152 | printf("\n"); 153 | return result; 154 | } 155 | -------------------------------------------------------------------------------- /src/makeq.c: -------------------------------------------------------------------------------- 1 | //// 2 | // makeq.c 3 | // 4 | // A simple example of how to create K objects within C. Handles 5 | // atoms, lists, dictionaries and tables. (enumerated types, functions 6 | // and nested types are currently unsupported). 7 | // 8 | // @updated: 17/03/2015 9 | // @authors: Kent Lee, Kevin Piar, Mark Rooney 10 | // 11 | // AquaQ Analytics 12 | // kdb+ consultancy, training and support 13 | // 14 | // For questions, comments, requests or bug reports, please contact us 15 | // w: www.aquaq.co.uk 16 | // e: info@aquaq.co.uk 17 | // p: +44 (0)28 9051 1232 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define KXVER 3 26 | #include "k.h" 27 | 28 | #define charfrom(x) x[rand()%(sizeof((x)-1))] 29 | #define arraylen(x) (sizeof(x)/(sizeof(*(x)))) 30 | 31 | static const char alpha[] = "abcdefghijklmnopqrstuvwxyz"; 32 | static const char types[] = "bxhijefcs"; 33 | 34 | static char* gensym(char *buffer, size_t size) 35 | { 36 | int i; 37 | for (i = 0; i < size; i++) 38 | buffer[i] = charfrom(alpha); 39 | buffer[i] = '\0'; 40 | 41 | return buffer; 42 | } 43 | 44 | static long long randtimestamp() 45 | { 46 | long long year = rand() % 10 + 2010; 47 | long long month = rand() % 12 + 1; 48 | long long day = rand() % 28 + 1; 49 | long long hour = rand() % 24; 50 | long long min = rand() % 60; 51 | long long sec = rand() % 60; 52 | long long nano = rand() % 1000000000; 53 | 54 | return (((ymd(year,month,day)*24+hour)*60+min)*60+sec)*1000000000+nano; 55 | } 56 | 57 | static long long randdate() 58 | { 59 | long long year = rand() % 10 + 2010; 60 | long long month = rand() % 12 + 1; 61 | long long day = rand() % 28 + 1; 62 | 63 | return ymd(year, month, day); 64 | } 65 | 66 | static double randdatetime() 67 | { 68 | double year = rand() % 10 + 2010; 69 | double month = rand() % 12 + 1; 70 | double day = rand() % 24; 71 | double hour = rand() % 24; 72 | double min = rand() % 60; 73 | double sec = rand() % 60; 74 | double mili = rand() % 1000; 75 | return ymd(year,month,day)+(hour+(min+(sec+mili/1000)/60)/60)/24; 76 | } 77 | 78 | static long long randtimespan() 79 | { 80 | long long day = rand() % 10; 81 | long long hour = rand() % 24; 82 | long long min = rand() % 60; 83 | long long sec = rand() % 60; 84 | long long nano = rand() % 1000000000; 85 | return (((day*24+hour)*60+min)*60+sec)*1000000000+nano; 86 | } 87 | 88 | static long long randtime() 89 | { 90 | int hour = rand() % 24; 91 | int min = rand() % 60; 92 | int sec = rand() % 60; 93 | int mili = rand() % 1000; 94 | return ((hour*60+min)*60+sec)*1000+mili; 95 | } 96 | 97 | static long long randmonth() 98 | { 99 | long long year = rand() % 10 + 2010; 100 | long long month = rand() % 12 + 1; 101 | return (year-2000)*12+month-1; 102 | } 103 | 104 | static long long randminute() 105 | { 106 | int min = rand() % 60; 107 | int sec = rand() % 60; 108 | return min*60+sec; 109 | } 110 | 111 | static long long randsecond() 112 | { 113 | int hour = rand() % 24; 114 | int min = rand() % 60; 115 | int sec = rand() % 60; 116 | return (hour*60+min)*60+sec; 117 | } 118 | 119 | static K makeatom(char ch) 120 | { 121 | static char buffer[32]; 122 | 123 | switch (ch) { 124 | case 'b': return kb(rand() % 2); 125 | case 'x': return kg(rand()); 126 | case 'h': return kh(rand() % 100); 127 | case 'i': return ki(rand() % 100); 128 | case 'j': return kj(rand() % 100); 129 | case 'e': return ke(rand() / 100.0); 130 | case 'f': return kf(rand() / 100.0); 131 | case 'c': return kc(charfrom(alpha)); 132 | case 's': return ks(gensym(buffer, rand() % 32)); 133 | case 'p': return ktj(-KP, randtimestamp()); 134 | case 'm': { K result = ka(-KM); result->i = randmonth(); return result; } 135 | case 'd': return kd(randdate()); 136 | case 'z': return kz(randdatetime()); 137 | case 'n': return ktj(-KN, randtimespan()); 138 | case 'u': { K result = ka(-KU); result->i = randminute(); return result; } 139 | case 'v': { K result = ka(-KV); result->i = randsecond(); return result; } 140 | case 't': return kt(randtime()); 141 | } 142 | 143 | return krr("notimplemented"); 144 | } 145 | 146 | #define makeatoms(t,a,v) do { result = ktn(t,5); for (int i = 0; i < 5; i++) a(result)[i] = (v); } while (0) 147 | 148 | static K makelist(char ch) 149 | { 150 | static char buffer[32]; 151 | K result; 152 | 153 | switch (ch) { 154 | case 'B': makeatoms(KB, kG, rand() % 2); break; 155 | case 'X': makeatoms(KG, kG, rand()); break; 156 | case 'H': makeatoms(KH, kH, rand() % 100); break; 157 | case 'I': makeatoms(KI, kI, rand() % 100); break; 158 | case 'J': makeatoms(KJ, kJ, rand() % 100); break; 159 | case 'E': makeatoms(KE, kE, rand() / 100.0); break; 160 | case 'F': makeatoms(KF, kF, rand() / 100.0); break; 161 | case 'C': makeatoms(KC, kC, charfrom(alpha)); break; 162 | case 'S': makeatoms(KS, kS, gensym(buffer, rand() % 32)); break; 163 | case 'P': makeatoms(KP, kJ, randtimestamp()); break; 164 | case 'M': makeatoms(KM, kI, randmonth()); break; 165 | case 'D': makeatoms(KD, kI, randdate()); break; 166 | case 'Z': makeatoms(KZ, kF, randdatetime()); break; 167 | case 'N': makeatoms(KN, kJ, randtimespan()); break; 168 | case 'U': makeatoms(KU, kI, randminute()); break; 169 | case 'V': makeatoms(KV, kI, randsecond()); break; 170 | case 'T': makeatoms(KT, kI, randtime()); break; 171 | default: return krr("notimplemented"); 172 | } 173 | 174 | return result; 175 | } 176 | 177 | static K makedict(K x) 178 | { 179 | static char buffer[] = "t_ "; 180 | 181 | int ntypes = 9; 182 | K keys = ktn(KS, ntypes); 183 | K values = ktn(0, ntypes); 184 | 185 | for (int i = 0; i < ntypes; i++) { 186 | buffer[2] = types[i]; 187 | kS(keys)[i] = ss(buffer); 188 | kK(values)[i] = makelist(toupper(types[i])); 189 | } 190 | 191 | return xD(keys, values); 192 | } 193 | 194 | K makeq(K x) 195 | { 196 | if (xt != -11) return krr("type"); 197 | 198 | if (0 == strcmp(x->s, "dictionary")) return makedict(x); 199 | else if (0 == strcmp(x->s, "table")) return xT(makedict(x)); 200 | else if (strlen(x->s) != 1) return krr("*notimplemented"); 201 | 202 | if (isupper(x->s[0])) return makelist(x->s[0]); 203 | else return makeatom(x->s[0]); 204 | } 205 | --------------------------------------------------------------------------------