module.c 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Module search function
  2. // Copyright (C) 2015 Legimet
  3. //
  4. // This file is part of Duktape-nspire.
  5. //
  6. // Duktape-nspire is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU Lesser General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // Duktape-nspire is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU Lesser General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU Lesser General Public License
  17. // along with Duktape-nspire. If not, see <http://www.gnu.org/licenses/>.
  18. #include "duktape.h"
  19. #include "module.h"
  20. #include <stdbool.h>
  21. #include <stdio.h>
  22. #include <errno.h>
  23. // Duktape.modSearch function, needed for loading modules with require()
  24. duk_ret_t module_search(duk_context *ctx) {
  25. const char *id = duk_require_string(ctx, 0);
  26. // C modules: add functions to exports variable (3rd argument) and return undefined
  27. for (int i = 0; i < c_module_count; i++) {
  28. if (!strcmp(c_module_list[i].name, id)) {
  29. duk_push_c_function(ctx, c_module_list[i].init_func, 0);
  30. duk_call(ctx, 0);
  31. duk_enum(ctx, -1, 0);
  32. while(duk_next(ctx, -1, 1)) {
  33. duk_put_prop(ctx, 2);
  34. }
  35. duk_pop_2(ctx);
  36. return 0;
  37. }
  38. }
  39. // JS modules: return source code as a string
  40. // Read from file "modname.js.tns"
  41. int module_filename_len = strlen(id) + strlen(".js.tns") + 1;
  42. char *module_filename = malloc(module_filename_len);
  43. if (!module_filename) goto error;
  44. snprintf(module_filename, module_filename_len, "%s.js.tns", id);
  45. FILE *module_file = fopen(module_filename, "r");
  46. free(module_filename);
  47. if (!module_file) goto error;
  48. if (fseek(module_file, 0, SEEK_END) != 0) goto error;
  49. long module_file_size = ftell(module_file);
  50. if (module_file_size == -1) goto error;
  51. rewind(module_file);
  52. char *src = malloc(module_file_size);
  53. if (!src) goto error;
  54. fread(src, 1, module_file_size, module_file);
  55. if (ferror(module_file)) goto error;
  56. fclose(module_file);
  57. duk_push_lstring(ctx, src, module_file_size);
  58. free(src);
  59. return 1;
  60. error:
  61. duk_push_error_object(ctx, DUK_ERR_ERROR, "module %s not found: %s", id, strerror(errno));
  62. duk_throw(ctx);
  63. }