{"action":"created","comment":{"url":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/comments/198499235","pull_request_review_id":132438738,"id":198499235,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5ODQ5OTIzNQ==","diff_hunk":"@@ -0,0 +1,275 @@\n+/*\n+ * Copyright (C) 2018 Freie Universität Berlin\n+ *\n+ * This file is subject to the terms and conditions of the GNU Lesser\n+ * General Public License v2.1. See the file LICENSE in the top level\n+ * directory for more details.\n+ */\n+/**\n+ * @ingroup  pkg_lua\n+ * @ingroup  pkg\n+ * @ingroup  sys\n+ * @{\n+ * @file\n+ *\n+ * @brief   Convenience functions for running Lua code.\n+ * @author  Juan Carrano <j.carrano@fu-berlin.de>\n+ *\n+ */\n+\n+#define LUA_LIB\n+\n+#include \"lprefix.h\"\n+\n+#include <setjmp.h>\n+\n+#include \"kernel_defines.h\"\n+#include \"tlsf.h\"\n+\n+#include \"lua.h\"\n+#include \"lualib.h\"\n+#include \"lauxlib.h\"\n+\n+#include \"lua_run.h\"\n+#include \"lua_loadlib.h\"\n+\n+const char * luaR_str_errors[] = {\n+    \"No errors\",\n+    \"Error setting up the interpreter\",\n+    \"Error while loading a builtin library\",\n+    \"Cannot find the specified module\",\n+    \"Compilation / syntax error\",\n+    \"Unprotected error (uncaught exception)\",\n+    \"Out of memory\",\n+    \"Internal interpreter error\",\n+    \"Unknown error\"\n+};\n+\n+/* The lua docs state the behavior in these cases:\n+ *\n+ *  1.              ptr=?, size=0    -> free(ptr)\n+        therefore   ptr=NULL, size=0 -> NOP\n+ *  2.               ptr=? , size!=0  -> realloc(ptr, size)\n+ *\n+ * The  TLSF code for realloc says:\n+ *  / * Zero-size requests are treated as free. * /\n+ *  if (ptr && size == 0)\n+ *  {\n+ *      tlsf_free(tlsf, ptr);\n+ *  }\n+ *  / * Requests with NULL pointers are treated as malloc. * /\n+ *  else if (!ptr)\n+ *  {\n+ *      p = tlsf_malloc(tlsf, size);\n+ *  }\n+ *\n+ * Therefore it is safe to use tlsf_realloc here.\n+ */\n+static void *lua_tlsf_alloc(void *ud, void *ptr, size_t osize, size_t nsize)\n+{\n+    tlsf_t tlsf = ud;\n+    (void)osize;\n+\n+    return tlsf_realloc(tlsf, ptr, nsize);\n+}\n+\n+LUALIB_API lua_State *luaR_newstate(void *memory, size_t mem_size,\n+                                    lua_CFunction panicf)\n+{\n+    lua_State *L;\n+    #ifdef LUA_DEBUG\n+        Memcontrol *mc = memory;\n+    #endif\n+\n+    /* If we are using the lua debug module, let's reserve a space for the\n+     * memcontrol block directly. We don't use the allocator because we lose\n+     * the pointer, so we won't be able to free it and we will get a false\n+     * positive if we try to check for memory leaks.\n+     */\n+    #ifdef LUA_DEBUG\n+        memory = (Memcontrol *)memory + 1;\n+        mem_size -= (uint8_t*)memory - (uint8_t*)mc;\n+    #endif\n+\n+    tlsf_t tlsf = tlsf_create_with_pool(memory, mem_size);\n+\n+    #ifdef LUA_DEBUG\n+        luaB_init_memcontrol(mc, lua_tlsf_alloc, tlsf);\n+        L = luaB_newstate(mc);\n+    #else\n+        L = lua_newstate(lua_tlsf_alloc, tlsf);\n+    #endif\n+\n+    if (L != NULL) {\n+        lua_atpanic(L, panicf);\n+    }\n+\n+    return L;\n+}\n+\n+static const luaL_Reg loadedlibs[LUAR_LOAD_O_ALL] = {\n+  {\"_G\", luaopen_base},\n+  {LUA_LOADLIBNAME, luaopen_package},\n+  {LUA_COLIBNAME, luaopen_coroutine},\n+  {LUA_TABLIBNAME, luaopen_table},\n+  {LUA_IOLIBNAME, luaopen_io},\n+  {LUA_OSLIBNAME, luaopen_os},\n+  {LUA_STRLIBNAME, luaopen_string},\n+  {LUA_MATHLIBNAME, luaopen_math},\n+  {LUA_UTF8LIBNAME, luaopen_utf8},\n+  {LUA_DBLIBNAME, luaopen_debug},\n+};\n+\n+LUALIB_API int luaR_openlibs(lua_State *L, uint16_t modmask)\n+{\n+    int lib_index;\n+\n+    #ifdef LUA_DEBUG\n+        luaL_requiref(L, LUA_TESTLIBNAME, luaB_opentests, 1);\n+        lua_pop(L, 1);\n+    #endif\n+\n+    for (lib_index = 0; lib_index < LUAR_LOAD_O_ALL;\n+         lib_index++, modmask >>= 1) {\n+        const luaL_Reg *lib = loadedlibs + lib_index;\n+\n+        if (!(modmask & 1)) {\n+            continue;\n+        }\n+        /* TODO: how can the loading fail? */\n+        luaL_requiref(L, lib->name, lib->func, 1);\n+        lua_pop(L, 1);  /* remove lib from stack (it is already global) */\n+    }\n+\n+    return lib_index;\n+}\n+\n+/**\n+ * Jump back to a save point (defined with setjmp).\n+ *\n+ * @note    This function never returns!\n+ */\n+NORETURN static int _jump_back (lua_State *L)\n+{\n+    jmp_buf *jump_buffer = *(jmp_buf **)lua_getextraspace(L);\n+\n+    /* FIXME: I dont think it's OK to print a message */\n+    lua_writestringerror(\"PANIC: unprotected error in call to Lua API (%s)\\n\",\n+                        lua_tostring(L, -1));\n+\n+    /* TODO: try to return some info about the error object. */\n+\n+    longjmp(*jump_buffer, 1);\n+}\n+\n+static int luaR_do_module_or_buf(const char *buf, size_t buflen,\n+                            const char *modname, void *memory, size_t mem_size,\n+                            uint16_t modmask, int *retval)\n+{\n+    jmp_buf jump_buffer;\n+    lua_State * volatile L = NULL;\n+    volatile int tmp_retval = 0; /* we need to make it volatile because of the\n+                                    setjmp/longjmp */\n+    volatile int status = LUAR_EXIT;\n+    int compilation_result;\n+\n+    if(setjmp(jump_buffer)) { /* We'll teleport back here if something goes wrong*/\n+        status = LUAR_INTERNAL_ERR;\n+        goto luaR_do_error;\n+    }\n+\n+    L = luaR_newstate(memory, mem_size, _jump_back);\n+    if (L == NULL) {\n+        status = LUAR_STARTUP_ERR;\n+        goto luaR_do_error;\n+    }\n+\n+    /* lua_getextraspace() gives us a pointer to an are large enough to hold a\n+     * pointer.\n+     *\n+     * We store a pointer to the jump buffer in that area.\n+     *\n+     * lua_getextraspace() is therefore a pointer to a pointer to jump_buffer.\n+     */\n+    *(jmp_buf **)lua_getextraspace(L) = &jump_buffer;\n+\n+    tmp_retval = luaR_openlibs(L, modmask);\n+    if (tmp_retval != LUAR_LOAD_O_ALL) {\n+        status = LUAR_LOAD_ERR;\n+        goto luaR_do_error;\n+    }\n+\n+    if (buf == NULL) {\n+        compilation_result = luaR_getloader(L, modname);\n+    } else {\n+        compilation_result = luaL_loadbufferx(L, buf, buflen, modname, \"t\");\n+    }\n+\n+    switch (compilation_result) {\n+    case LUAR_MODULE_NOTFOUND:","path":"pkg/lua/contrib/lua_run.c","position":209,"original_position":209,"commit_id":"af3e4596229379fb9bf8bebbc26bc60a4ab0f01e","original_commit_id":"af3e4596229379fb9bf8bebbc26bc60a4ab0f01e","user":{"login":"jcarrano","id":3057851,"node_id":"MDQ6VXNlcjMwNTc4NTE=","avatar_url":"https://avatars0.githubusercontent.com/u/3057851?v=4","gravatar_id":"","url":"https://api.github.com/users/jcarrano","html_url":"https://github.com/jcarrano","followers_url":"https://api.github.com/users/jcarrano/followers","following_url":"https://api.github.com/users/jcarrano/following{/other_user}","gists_url":"https://api.github.com/users/jcarrano/gists{/gist_id}","starred_url":"https://api.github.com/users/jcarrano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jcarrano/subscriptions","organizations_url":"https://api.github.com/users/jcarrano/orgs","repos_url":"https://api.github.com/users/jcarrano/repos","events_url":"https://api.github.com/users/jcarrano/events{/privacy}","received_events_url":"https://api.github.com/users/jcarrano/received_events","type":"User","site_admin":false},"body":"It would be more like moving the dirtiness to somewhere else. I don't like to rely on specific values of enums, and I'd rather treat them as symbols.","created_at":"2018-06-27T13:41:38Z","updated_at":"2018-06-27T13:41:38Z","html_url":"https://github.com/RIOT-OS/RIOT/pull/9153#discussion_r198499235","pull_request_url":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/9153","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/comments/198499235"},"html":{"href":"https://github.com/RIOT-OS/RIOT/pull/9153#discussion_r198499235"},"pull_request":{"href":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/9153"}},"in_reply_to_id":198127774},"pull_request":{"url":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/9153","id":189066195,"node_id":"MDExOlB1bGxSZXF1ZXN0MTg5MDY2MTk1","html_url":"https://github.com/RIOT-OS/RIOT/pull/9153","diff_url":"https://github.com/RIOT-OS/RIOT/pull/9153.diff","patch_url":"https://github.com/RIOT-OS/RIOT/pull/9153.patch","issue_url":"https://api.github.com/repos/RIOT-OS/RIOT/issues/9153","number":9153,"state":"open","locked":false,"title":"pkg/lua: Better Lua-RIOT integration","user":{"login":"jcarrano","id":3057851,"node_id":"MDQ6VXNlcjMwNTc4NTE=","avatar_url":"https://avatars0.githubusercontent.com/u/3057851?v=4","gravatar_id":"","url":"https://api.github.com/users/jcarrano","html_url":"https://github.com/jcarrano","followers_url":"https://api.github.com/users/jcarrano/followers","following_url":"https://api.github.com/users/jcarrano/following{/other_user}","gists_url":"https://api.github.com/users/jcarrano/gists{/gist_id}","starred_url":"https://api.github.com/users/jcarrano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jcarrano/subscriptions","organizations_url":"https://api.github.com/users/jcarrano/orgs","repos_url":"https://api.github.com/users/jcarrano/repos","events_url":"https://api.github.com/users/jcarrano/events{/privacy}","received_events_url":"https://api.github.com/users/jcarrano/received_events","type":"User","site_admin":false},"body":"### Better integration of the Lua interpreter with RIOT\r\n\r\nThe main idea behind this PR is that interpreted code should never be allowed to crash the host application. A secondary goal is to cover the majority of use cases in a few simple API calls, to remove the required boilerplate and make it easier to use the Lua package correctly.\r\n\r\n- The lua intepreter itself, with some custom modifications:\r\n  * Patches to reduce C-stack usage.\r\n  * Modifications to the test module to enable it to work on RIOT.\r\n  * The vanilla module loader is disabled as it is too dependent on files and dynamic loading.\r\n- A new module loader intended to load source code and C-modules built-into the application.\r\n- A custom memory allocator based on TLSF. This allows to limit the memory that Lua can consume and to not have memory leaks in case of an interpreter crash.\r\n- A panic handler based on `setjmp()/longjmp()`. Thus, in case of a irrecoverable failure in the interpreter, control returns to the host application (by default, lua calls `abort()`)\r\n- An example with an interactive Lua REPL.\r\n- Procedures to easily launch Lua and handle errors.\r\n\r\n**Note that only 32 bit CPUs will be supported.**\r\n\r\n### Future work\r\n\r\nThe next PRs will focus on build system integration (i.e. being able to compile ``%.lua`` into an application).\r\n\r\n### About the Lua patches\r\n\r\nI'm patching lua, in a way that is perfectly compatible with the unmodified code. I'm running the test suite, and it passes. Patches are still patches, and they will never get merged into upstream lua, simply because the Lua people don't accept outside submissions (check the [FAQ](https://www.lua.org/faq.html#1.8) for more info). This is a reality we have to accept. Other projects do the same, they apply their own modifications.\r\n\r\n### Issues/PRs references\r\n\r\nExtends: #8847\r\nDepends on: #9090 #9006 #9244","created_at":"2018-05-18T15:48:49Z","updated_at":"2018-06-27T13:41:38Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e22b41c29e7c0a8d26339c8aca4126e4a0065e13","assignee":{"login":"jia200x","id":1260616,"node_id":"MDQ6VXNlcjEyNjA2MTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1260616?v=4","gravatar_id":"","url":"https://api.github.com/users/jia200x","html_url":"https://github.com/jia200x","followers_url":"https://api.github.com/users/jia200x/followers","following_url":"https://api.github.com/users/jia200x/following{/other_user}","gists_url":"https://api.github.com/users/jia200x/gists{/gist_id}","starred_url":"https://api.github.com/users/jia200x/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jia200x/subscriptions","organizations_url":"https://api.github.com/users/jia200x/orgs","repos_url":"https://api.github.com/users/jia200x/repos","events_url":"https://api.github.com/users/jia200x/events{/privacy}","received_events_url":"https://api.github.com/users/jia200x/received_events","type":"User","site_admin":false},"assignees":[{"login":"jia200x","id":1260616,"node_id":"MDQ6VXNlcjEyNjA2MTY=","avatar_url":"https://avatars3.githubusercontent.com/u/1260616?v=4","gravatar_id":"","url":"https://api.github.com/users/jia200x","html_url":"https://github.com/jia200x","followers_url":"https://api.github.com/users/jia200x/followers","following_url":"https://api.github.com/users/jia200x/following{/other_user}","gists_url":"https://api.github.com/users/jia200x/gists{/gist_id}","starred_url":"https://api.github.com/users/jia200x/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jia200x/subscriptions","organizations_url":"https://api.github.com/users/jia200x/orgs","repos_url":"https://api.github.com/users/jia200x/repos","events_url":"https://api.github.com/users/jia200x/events{/privacy}","received_events_url":"https://api.github.com/users/jia200x/received_events","type":"User","site_admin":false},{"login":"danpetry","id":11301549,"node_id":"MDQ6VXNlcjExMzAxNTQ5","avatar_url":"https://avatars2.githubusercontent.com/u/11301549?v=4","gravatar_id":"","url":"https://api.github.com/users/danpetry","html_url":"https://github.com/danpetry","followers_url":"https://api.github.com/users/danpetry/followers","following_url":"https://api.github.com/users/danpetry/following{/other_user}","gists_url":"https://api.github.com/users/danpetry/gists{/gist_id}","starred_url":"https://api.github.com/users/danpetry/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danpetry/subscriptions","organizations_url":"https://api.github.com/users/danpetry/orgs","repos_url":"https://api.github.com/users/danpetry/repos","events_url":"https://api.github.com/users/danpetry/events{/privacy}","received_events_url":"https://api.github.com/users/danpetry/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":214816571,"node_id":"MDU6TGFiZWwyMTQ4MTY1NzE=","url":"https://api.github.com/repos/RIOT-OS/RIOT/labels/Ready%20for%20CI%20build","name":"Ready for CI build","color":"bfdadc","default":false},{"id":23399100,"node_id":"MDU6TGFiZWwyMzM5OTEwMA==","url":"https://api.github.com/repos/RIOT-OS/RIOT/labels/enhancement","name":"enhancement","color":"f17070","default":true},{"id":114180965,"node_id":"MDU6TGFiZWwxMTQxODA5NjU=","url":"https://api.github.com/repos/RIOT-OS/RIOT/labels/pkg","name":"pkg","color":"006b75","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/9153/commits","review_comments_url":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/9153/comments","review_comment_url":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/comments{/number}","comments_url":"https://api.github.com/repos/RIOT-OS/RIOT/issues/9153/comments","statuses_url":"https://api.github.com/repos/RIOT-OS/RIOT/statuses/af3e4596229379fb9bf8bebbc26bc60a4ab0f01e","head":{"label":"jcarrano:lua-on-riot","ref":"lua-on-riot","sha":"af3e4596229379fb9bf8bebbc26bc60a4ab0f01e","user":{"login":"jcarrano","id":3057851,"node_id":"MDQ6VXNlcjMwNTc4NTE=","avatar_url":"https://avatars0.githubusercontent.com/u/3057851?v=4","gravatar_id":"","url":"https://api.github.com/users/jcarrano","html_url":"https://github.com/jcarrano","followers_url":"https://api.github.com/users/jcarrano/followers","following_url":"https://api.github.com/users/jcarrano/following{/other_user}","gists_url":"https://api.github.com/users/jcarrano/gists{/gist_id}","starred_url":"https://api.github.com/users/jcarrano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jcarrano/subscriptions","organizations_url":"https://api.github.com/users/jcarrano/orgs","repos_url":"https://api.github.com/users/jcarrano/repos","events_url":"https://api.github.com/users/jcarrano/events{/privacy}","received_events_url":"https://api.github.com/users/jcarrano/received_events","type":"User","site_admin":false},"repo":{"id":129120876,"node_id":"MDEwOlJlcG9zaXRvcnkxMjkxMjA4NzY=","name":"RIOT","full_name":"jcarrano/RIOT","owner":{"login":"jcarrano","id":3057851,"node_id":"MDQ6VXNlcjMwNTc4NTE=","avatar_url":"https://avatars0.githubusercontent.com/u/3057851?v=4","gravatar_id":"","url":"https://api.github.com/users/jcarrano","html_url":"https://github.com/jcarrano","followers_url":"https://api.github.com/users/jcarrano/followers","following_url":"https://api.github.com/users/jcarrano/following{/other_user}","gists_url":"https://api.github.com/users/jcarrano/gists{/gist_id}","starred_url":"https://api.github.com/users/jcarrano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jcarrano/subscriptions","organizations_url":"https://api.github.com/users/jcarrano/orgs","repos_url":"https://api.github.com/users/jcarrano/repos","events_url":"https://api.github.com/users/jcarrano/events{/privacy}","received_events_url":"https://api.github.com/users/jcarrano/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jcarrano/RIOT","description":"RIOT -  The friendly OS for IoT","fork":true,"url":"https://api.github.com/repos/jcarrano/RIOT","forks_url":"https://api.github.com/repos/jcarrano/RIOT/forks","keys_url":"https://api.github.com/repos/jcarrano/RIOT/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jcarrano/RIOT/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jcarrano/RIOT/teams","hooks_url":"https://api.github.com/repos/jcarrano/RIOT/hooks","issue_events_url":"https://api.github.com/repos/jcarrano/RIOT/issues/events{/number}","events_url":"https://api.github.com/repos/jcarrano/RIOT/events","assignees_url":"https://api.github.com/repos/jcarrano/RIOT/assignees{/user}","branches_url":"https://api.github.com/repos/jcarrano/RIOT/branches{/branch}","tags_url":"https://api.github.com/repos/jcarrano/RIOT/tags","blobs_url":"https://api.github.com/repos/jcarrano/RIOT/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jcarrano/RIOT/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jcarrano/RIOT/git/refs{/sha}","trees_url":"https://api.github.com/repos/jcarrano/RIOT/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jcarrano/RIOT/statuses/{sha}","languages_url":"https://api.github.com/repos/jcarrano/RIOT/languages","stargazers_url":"https://api.github.com/repos/jcarrano/RIOT/stargazers","contributors_url":"https://api.github.com/repos/jcarrano/RIOT/contributors","subscribers_url":"https://api.github.com/repos/jcarrano/RIOT/subscribers","subscription_url":"https://api.github.com/repos/jcarrano/RIOT/subscription","commits_url":"https://api.github.com/repos/jcarrano/RIOT/commits{/sha}","git_commits_url":"https://api.github.com/repos/jcarrano/RIOT/git/commits{/sha}","comments_url":"https://api.github.com/repos/jcarrano/RIOT/comments{/number}","issue_comment_url":"https://api.github.com/repos/jcarrano/RIOT/issues/comments{/number}","contents_url":"https://api.github.com/repos/jcarrano/RIOT/contents/{+path}","compare_url":"https://api.github.com/repos/jcarrano/RIOT/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jcarrano/RIOT/merges","archive_url":"https://api.github.com/repos/jcarrano/RIOT/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jcarrano/RIOT/downloads","issues_url":"https://api.github.com/repos/jcarrano/RIOT/issues{/number}","pulls_url":"https://api.github.com/repos/jcarrano/RIOT/pulls{/number}","milestones_url":"https://api.github.com/repos/jcarrano/RIOT/milestones{/number}","notifications_url":"https://api.github.com/repos/jcarrano/RIOT/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jcarrano/RIOT/labels{/name}","releases_url":"https://api.github.com/repos/jcarrano/RIOT/releases{/id}","deployments_url":"https://api.github.com/repos/jcarrano/RIOT/deployments","created_at":"2018-04-11T16:13:19Z","updated_at":"2018-05-15T12:50:24Z","pushed_at":"2018-06-22T16:41:49Z","git_url":"git://github.com/jcarrano/RIOT.git","ssh_url":"git@github.com:jcarrano/RIOT.git","clone_url":"https://github.com/jcarrano/RIOT.git","svn_url":"https://github.com/jcarrano/RIOT","homepage":"https://github.com/RIOT-OS/RIOT/wiki","size":53770,"stargazers_count":0,"watchers_count":0,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":5,"license":{"key":"lgpl-2.1","name":"GNU Lesser General Public License v2.1","spdx_id":"LGPL-2.1","url":"https://api.github.com/licenses/lgpl-2.1","node_id":"MDc6TGljZW5zZTEx"},"forks":0,"open_issues":5,"watchers":0,"default_branch":"master"}},"base":{"label":"RIOT-OS:master","ref":"master","sha":"011b80cb924d6ee499d1f37d5ad8067b85906e50","user":{"login":"RIOT-OS","id":3079480,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMwNzk0ODA=","avatar_url":"https://avatars2.githubusercontent.com/u/3079480?v=4","gravatar_id":"","url":"https://api.github.com/users/RIOT-OS","html_url":"https://github.com/RIOT-OS","followers_url":"https://api.github.com/users/RIOT-OS/followers","following_url":"https://api.github.com/users/RIOT-OS/following{/other_user}","gists_url":"https://api.github.com/users/RIOT-OS/gists{/gist_id}","starred_url":"https://api.github.com/users/RIOT-OS/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RIOT-OS/subscriptions","organizations_url":"https://api.github.com/users/RIOT-OS/orgs","repos_url":"https://api.github.com/users/RIOT-OS/repos","events_url":"https://api.github.com/users/RIOT-OS/events{/privacy}","received_events_url":"https://api.github.com/users/RIOT-OS/received_events","type":"Organization","site_admin":false},"repo":{"id":7370241,"node_id":"MDEwOlJlcG9zaXRvcnk3MzcwMjQx","name":"RIOT","full_name":"RIOT-OS/RIOT","owner":{"login":"RIOT-OS","id":3079480,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMwNzk0ODA=","avatar_url":"https://avatars2.githubusercontent.com/u/3079480?v=4","gravatar_id":"","url":"https://api.github.com/users/RIOT-OS","html_url":"https://github.com/RIOT-OS","followers_url":"https://api.github.com/users/RIOT-OS/followers","following_url":"https://api.github.com/users/RIOT-OS/following{/other_user}","gists_url":"https://api.github.com/users/RIOT-OS/gists{/gist_id}","starred_url":"https://api.github.com/users/RIOT-OS/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RIOT-OS/subscriptions","organizations_url":"https://api.github.com/users/RIOT-OS/orgs","repos_url":"https://api.github.com/users/RIOT-OS/repos","events_url":"https://api.github.com/users/RIOT-OS/events{/privacy}","received_events_url":"https://api.github.com/users/RIOT-OS/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/RIOT-OS/RIOT","description":"RIOT -  The friendly OS for IoT","fork":false,"url":"https://api.github.com/repos/RIOT-OS/RIOT","forks_url":"https://api.github.com/repos/RIOT-OS/RIOT/forks","keys_url":"https://api.github.com/repos/RIOT-OS/RIOT/keys{/key_id}","collaborators_url":"https://api.github.com/repos/RIOT-OS/RIOT/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/RIOT-OS/RIOT/teams","hooks_url":"https://api.github.com/repos/RIOT-OS/RIOT/hooks","issue_events_url":"https://api.github.com/repos/RIOT-OS/RIOT/issues/events{/number}","events_url":"https://api.github.com/repos/RIOT-OS/RIOT/events","assignees_url":"https://api.github.com/repos/RIOT-OS/RIOT/assignees{/user}","branches_url":"https://api.github.com/repos/RIOT-OS/RIOT/branches{/branch}","tags_url":"https://api.github.com/repos/RIOT-OS/RIOT/tags","blobs_url":"https://api.github.com/repos/RIOT-OS/RIOT/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/RIOT-OS/RIOT/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/RIOT-OS/RIOT/git/refs{/sha}","trees_url":"https://api.github.com/repos/RIOT-OS/RIOT/git/trees{/sha}","statuses_url":"https://api.github.com/repos/RIOT-OS/RIOT/statuses/{sha}","languages_url":"https://api.github.com/repos/RIOT-OS/RIOT/languages","stargazers_url":"https://api.github.com/repos/RIOT-OS/RIOT/stargazers","contributors_url":"https://api.github.com/repos/RIOT-OS/RIOT/contributors","subscribers_url":"https://api.github.com/repos/RIOT-OS/RIOT/subscribers","subscription_url":"https://api.github.com/repos/RIOT-OS/RIOT/subscription","commits_url":"https://api.github.com/repos/RIOT-OS/RIOT/commits{/sha}","git_commits_url":"https://api.github.com/repos/RIOT-OS/RIOT/git/commits{/sha}","comments_url":"https://api.github.com/repos/RIOT-OS/RIOT/comments{/number}","issue_comment_url":"https://api.github.com/repos/RIOT-OS/RIOT/issues/comments{/number}","contents_url":"https://api.github.com/repos/RIOT-OS/RIOT/contents/{+path}","compare_url":"https://api.github.com/repos/RIOT-OS/RIOT/compare/{base}...{head}","merges_url":"https://api.github.com/repos/RIOT-OS/RIOT/merges","archive_url":"https://api.github.com/repos/RIOT-OS/RIOT/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/RIOT-OS/RIOT/downloads","issues_url":"https://api.github.com/repos/RIOT-OS/RIOT/issues{/number}","pulls_url":"https://api.github.com/repos/RIOT-OS/RIOT/pulls{/number}","milestones_url":"https://api.github.com/repos/RIOT-OS/RIOT/milestones{/number}","notifications_url":"https://api.github.com/repos/RIOT-OS/RIOT/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/RIOT-OS/RIOT/labels{/name}","releases_url":"https://api.github.com/repos/RIOT-OS/RIOT/releases{/id}","deployments_url":"https://api.github.com/repos/RIOT-OS/RIOT/deployments","created_at":"2012-12-29T20:38:40Z","updated_at":"2018-06-27T13:07:50Z","pushed_at":"2018-06-27T13:35:41Z","git_url":"git://github.com/RIOT-OS/RIOT.git","ssh_url":"git@github.com:RIOT-OS/RIOT.git","clone_url":"https://github.com/RIOT-OS/RIOT.git","svn_url":"https://github.com/RIOT-OS/RIOT","homepage":"https://github.com/RIOT-OS/RIOT/wiki","size":54187,"stargazers_count":1843,"watchers_count":1843,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1082,"mirror_url":null,"archived":false,"open_issues_count":760,"license":{"key":"lgpl-2.1","name":"GNU Lesser General Public License v2.1","spdx_id":"LGPL-2.1","url":"https://api.github.com/licenses/lgpl-2.1","node_id":"MDc6TGljZW5zZTEx"},"forks":1082,"open_issues":760,"watchers":1843,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/9153"},"html":{"href":"https://github.com/RIOT-OS/RIOT/pull/9153"},"issue":{"href":"https://api.github.com/repos/RIOT-OS/RIOT/issues/9153"},"comments":{"href":"https://api.github.com/repos/RIOT-OS/RIOT/issues/9153/comments"},"review_comments":{"href":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/9153/comments"},"review_comment":{"href":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/RIOT-OS/RIOT/pulls/9153/commits"},"statuses":{"href":"https://api.github.com/repos/RIOT-OS/RIOT/statuses/af3e4596229379fb9bf8bebbc26bc60a4ab0f01e"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"jcarrano"}}