···11+// MIT License
22+33+// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
44+55+// Permission is hereby granted, free of charge, to any person obtaining a copy
66+// of this software and associated documentation files (the "Software"), to deal
77+// in the Software without restriction, including without limitation the rights
88+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99+// copies of the Software, and to permit persons to whom the Software is
1010+// furnished to do so, subject to the following conditions:
1111+1212+// The above copyright notice and this permission notice shall be included in all
1313+// copies or substantial portions of the Software.
1414+1515+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+// SOFTWARE.
2222+2323+#include "json.h"
2424+2525+#define JSMN_STATIC
2626+#define JSMN_PARENT_LINKS
2727+#include <jsmn.h>
2828+2929+#include <stdio.h>
3030+3131+static struct
3232+{
3333+ jsmn_parser p;
3434+ jsmntok_t* t;
3535+ s32 tcount, count;
3636+ const char* json;
3737+} state = {.tcount = 128};
3838+3939+bool json_parse(const char *json, s32 size)
4040+{
4141+ if(state.t == NULL)
4242+ state.t = malloc(state.tcount * sizeof *state.t);
4343+4444+ jsmn_init(&state.p);
4545+4646+ state.json = json;
4747+4848+ while((state.count = jsmn_parse(&state.p, state.json, size, state.t, state.tcount)) == JSMN_ERROR_NOMEM)
4949+ state.t = realloc(state.t, (state.tcount *= 2) * sizeof *state.t);
5050+5151+ return state.count >= 0 && state.t[0].type == JSMN_OBJECT;
5252+}
5353+5454+static s32 jsoneq(const char *json, const jsmntok_t *tok, const char *s)
5555+{
5656+ if (tok->type & JSMN_STRING
5757+ && strlen(s) == tok->end - tok->start
5858+ && strncmp(json + tok->start, s, tok->end - tok->start) == 0)
5959+ return 0;
6060+6161+ return -1;
6262+}
6363+6464+static s32 getJsonItem(const char *var, s32 parent, jsmntype_t type)
6565+{
6666+ for(s32 i = parent; i < state.count; i++)
6767+ if(jsoneq(state.json, &state.t[i], var) == 0 && state.t[i + 1].type & type)
6868+ return i + 1;
6969+7070+ return 0;
7171+}
7272+7373+bool json_bool(const char *var, s32 parent)
7474+{
7575+ const jsmntok_t *t = &state.t[getJsonItem(var, parent, JSMN_PRIMITIVE)];
7676+ return strncmp(state.json + t->start, "true", t->end - t->start) == 0;
7777+}
7878+7979+s32 json_int(const char *var, s32 parent)
8080+{
8181+ return atoi(state.json + state.t[getJsonItem(var, parent, JSMN_PRIMITIVE)].start);
8282+}
8383+8484+bool json_string(const char *var, s32 parent, char* value, s32 size)
8585+{
8686+ const jsmntok_t* t = &state.t[getJsonItem(var, parent, JSMN_STRING)];
8787+ return snprintf(value, size, "%.*s", t->end - t->start, state.json + t->start) > 0;
8888+}
8989+9090+s32 json_array(const char *var, s32 parent)
9191+{
9292+ return getJsonItem(var, parent, JSMN_ARRAY);
9393+}
9494+9595+s32 json_array_size(s32 array)
9696+{
9797+ s32 count = 0;
9898+9999+ for(s32 i = state.t[array].parent; i < state.count; i++)
100100+ if(state.t[i].parent == array)
101101+ count++;
102102+103103+ return count;
104104+}
105105+106106+s32 json_array_item(s32 array, s32 index)
107107+{
108108+ for(s32 i = state.t[array].parent, count = 0; i < state.count; i++)
109109+ if(state.t[i].parent == array && index == count++)
110110+ return i;
111111+112112+ return 0;
113113+}
114114+115115+s32 json_object(const char *var, s32 parent)
116116+{
117117+ return getJsonItem(var, parent, JSMN_OBJECT);
118118+}
+35
src/ext/json.h
···11+// MIT License
22+33+// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
44+55+// Permission is hereby granted, free of charge, to any person obtaining a copy
66+// of this software and associated documentation files (the "Software"), to deal
77+// in the Software without restriction, including without limitation the rights
88+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99+// copies of the Software, and to permit persons to whom the Software is
1010+// furnished to do so, subject to the following conditions:
1111+1212+// The above copyright notice and this permission notice shall be included in all
1313+// copies or substantial portions of the Software.
1414+1515+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+// SOFTWARE.
2222+2323+#pragma once
2424+2525+#include "tic.h"
2626+2727+bool json_parse(const char *json, s32 size);
2828+2929+s32 json_int(const char *var, s32 parent);
3030+bool json_bool(const char *var, s32 parent);
3131+bool json_string(const char *var, s32 parent, char* value, s32 size);
3232+s32 json_array(const char *var, s32 parent);
3333+s32 json_array_size(s32 array);
3434+s32 json_array_item(s32 array, s32 index);
3535+s32 json_object(const char *var, s32 parent);
+176
src/script.c
···11+// MIT License
22+33+// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
44+55+// Permission is hereby granted, free of charge, to any person obtaining a copy
66+// of this software and associated documentation files (the "Software"), to deal
77+// in the Software without restriction, including without limitation the rights
88+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99+// copies of the Software, and to permit persons to whom the Software is
1010+// furnished to do so, subject to the following conditions:
1111+1212+// The above copyright notice and this permission notice shall be included in all
1313+// copies or substantial portions of the Software.
1414+1515+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+// SOFTWARE.
2222+2323+#include "script.h"
2424+#include "tools.h"
2525+2626+#include <stdio.h>
2727+2828+#define MAX_SUPPORTED_LANGS (16)
2929+3030+#if defined(TIC_RUNTIME_STATIC)
3131+3232+#if defined (TIC_BUILD_WITH_LUA)
3333+extern tic_script EXPORT_SCRIPT(Lua);
3434+#endif
3535+3636+#if defined(TIC_BUILD_WITH_MRUBY)
3737+extern tic_script EXPORT_SCRIPT(Ruby);
3838+#endif
3939+4040+#if defined(TIC_BUILD_WITH_JS)
4141+extern tic_script EXPORT_SCRIPT(Js);
4242+#endif
4343+4444+#if defined(TIC_BUILD_WITH_MOON)
4545+extern tic_script EXPORT_SCRIPT(Moon);
4646+#endif
4747+4848+#if defined(TIC_BUILD_WITH_FENNEL)
4949+extern tic_script EXPORT_SCRIPT(Fennel);
5050+#endif
5151+5252+#if defined(TIC_BUILD_WITH_SQUIRREL)
5353+extern tic_script EXPORT_SCRIPT(Squirrel);
5454+#endif
5555+5656+#if defined(TIC_BUILD_WITH_SCHEME)
5757+extern tic_script EXPORT_SCRIPT(Scheme);
5858+#endif
5959+6060+#if defined(TIC_BUILD_WITH_WREN)
6161+extern tic_script EXPORT_SCRIPT(Wren);
6262+#endif
6363+6464+#if defined(TIC_BUILD_WITH_WASM)
6565+extern tic_script EXPORT_SCRIPT(Wasm);
6666+#endif
6767+6868+#if defined(TIC_BUILD_WITH_JANET)
6969+extern tic_script EXPORT_SCRIPT(Janet);
7070+#endif
7171+7272+#if defined(TIC_BUILD_WITH_PYTHON)
7373+extern tic_script EXPORT_SCRIPT(Python);
7474+#endif
7575+7676+#endif
7777+7878+static const tic_script *Scripts[MAX_SUPPORTED_LANGS + 1] =
7979+{
8080+#if defined(TIC_RUNTIME_STATIC)
8181+ #if defined (TIC_BUILD_WITH_LUA)
8282+ &EXPORT_SCRIPT(Lua),
8383+ #endif
8484+8585+ #if defined(TIC_BUILD_WITH_MRUBY)
8686+ &EXPORT_SCRIPT(Ruby),
8787+ #endif
8888+8989+ #if defined(TIC_BUILD_WITH_JS)
9090+ &EXPORT_SCRIPT(Js),
9191+ #endif
9292+9393+ #if defined(TIC_BUILD_WITH_MOON)
9494+ &EXPORT_SCRIPT(Moon),
9595+ #endif
9696+9797+ #if defined(TIC_BUILD_WITH_FENNEL)
9898+ &EXPORT_SCRIPT(Fennel),
9999+ #endif
100100+101101+ #if defined(TIC_BUILD_WITH_SCHEME)
102102+ &EXPORT_SCRIPT(Scheme),
103103+ #endif
104104+105105+ #if defined(TIC_BUILD_WITH_SQUIRREL)
106106+ &EXPORT_SCRIPT(Squirrel),
107107+ #endif
108108+109109+ #if defined(TIC_BUILD_WITH_WREN)
110110+ &EXPORT_SCRIPT(Wren),
111111+ #endif
112112+113113+ #if defined(TIC_BUILD_WITH_WASM)
114114+ &EXPORT_SCRIPT(Wasm),
115115+ #endif
116116+117117+ #if defined(TIC_BUILD_WITH_JANET)
118118+ &EXPORT_SCRIPT(Janet),
119119+ #endif
120120+121121+ #if defined(TIC_BUILD_WITH_PYTHON)
122122+ &EXPORT_SCRIPT(Python),
123123+ #endif
124124+125125+#endif
126126+127127+ NULL,
128128+};
129129+130130+static s32 compareScripts(const void* a, const void* b)
131131+{
132132+ const tic_script* script1 = *(const tic_script**)a;
133133+ const tic_script* script2 = *(const tic_script**)b;
134134+135135+ if (script1->id < script2->id) return -1;
136136+ if (script1->id > script2->id) return 1;
137137+ return 0;
138138+}
139139+140140+void tic_add_script(const tic_script* script)
141141+{
142142+ s32 index = 0;
143143+ FOREACH_LANG(it)
144144+ {
145145+ if(it->id == script->id || strcmp(it->name, script->name) == 0)
146146+ {
147147+ // script already exists
148148+ return;
149149+ }
150150+151151+ index++;
152152+ }
153153+154154+ if(index < MAX_SUPPORTED_LANGS)
155155+ {
156156+ Scripts[index] = script;
157157+ qsort(Scripts, index + 1, sizeof Scripts[0], compareScripts);
158158+ }
159159+}
160160+161161+const tic_script** tic_scripts()
162162+{
163163+ return Scripts;
164164+}
165165+166166+const tic_script* tic_get_script(tic_mem* memory)
167167+{
168168+ FOREACH_LANG(script)
169169+ {
170170+ if(script->id == memory->cart.lang
171171+ || strcmp(tic_tool_metatag(memory->cart.code.data, "script", script->singleComment), script->name) == 0)
172172+ return script;
173173+ }
174174+175175+ return NULL;
176176+}
+89
src/script.h
···11+// MIT License
22+33+// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
44+55+// Permission is hereby granted, free of charge, to any person obtaining a copy
66+// of this software and associated documentation files (the "Software"), to deal
77+// in the Software without restriction, including without limitation the rights
88+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99+// copies of the Software, and to permit persons to whom the Software is
1010+// furnished to do so, subject to the following conditions:
1111+1212+// The above copyright notice and this permission notice shall be included in all
1313+// copies or substantial portions of the Software.
1414+1515+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+// SOFTWARE.
2222+2323+#pragma once
2424+2525+#include "api.h"
2626+2727+struct tic_script
2828+{
2929+ u8 id;
3030+ const char* name;
3131+ const char* fileExtension;
3232+ const char* projectComment;
3333+ struct
3434+ {
3535+ bool(*init)(tic_mem* memory, const char* code);
3636+ void(*close)(tic_mem* memory);
3737+3838+ tic_tick tick;
3939+ tic_boot boot;
4040+ tic_blit_callback callback;
4141+ };
4242+4343+ const tic_outline_item* (*getOutline)(const char* code, s32* size);
4444+ void (*eval)(tic_mem* tic, const char* code);
4545+4646+ const char* blockCommentStart;
4747+ const char* blockCommentEnd;
4848+ const char* blockCommentStart2;
4949+ const char* blockCommentEnd2;
5050+ const char* blockStringStart;
5151+ const char* blockStringEnd;
5252+ const char* stdStringStartEnd;
5353+ const char* singleComment;
5454+ const char* blockEnd;
5555+5656+ const char* const * keywords;
5757+ s32 keywordsCount;
5858+5959+ tic_lang_isalnum lang_isalnum;
6060+ bool useStructuredEdition;
6161+6262+ s32 api_keywordsCount;
6363+ const char** api_keywords;
6464+6565+ struct tic_demo
6666+ {
6767+ const u8* data;
6868+ s32 size;
6969+ const char* name;
7070+ } demo, mark, *demos;
7171+7272+};
7373+7474+typedef struct tic_script tic_script;
7575+7676+const tic_script* tic_get_script(tic_mem* memory);
7777+void tic_add_script(const tic_script* script);
7878+const tic_script** tic_scripts();
7979+8080+#define FOREACH_LANG(script) \
8181+ for(const tic_script **MACROVAR(it) = tic_scripts(), *script = *MACROVAR(it); *MACROVAR(it); script = *++MACROVAR(it))
8282+8383+#define SCRIPT_CONFIG ScriptConfig
8484+8585+#if defined(TIC_RUNTIME_STATIC)
8686+#define EXPORT_SCRIPT(X) CONCAT(X, SCRIPT_CONFIG)
8787+#else
8888+#define EXPORT_SCRIPT(X) SCRIPT_CONFIG
8989+#endif