├── 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 |
--------------------------------------------------------------------------------