misc.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Miscellaneous functions
  2. // Copyright (C) 2017 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 <errno.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. void push_file_contents(duk_context *ctx, const char *filename) {
  23. FILE *file = fopen(filename, "rb");
  24. if (!file) goto error;
  25. if (fseek(file, 0, SEEK_END)) goto error;
  26. long size = ftell(file);
  27. if (size < 0) goto error;
  28. if (size == 0) {
  29. fclose(file);
  30. duk_push_lstring(ctx, NULL, 0);
  31. return;
  32. }
  33. if (fseek(file, 0, SEEK_SET)) goto error;
  34. char *buf = duk_push_fixed_buffer(ctx, size);
  35. if (fread(buf, size, 1, file) != 1) {
  36. duk_pop(ctx);
  37. goto error;
  38. }
  39. fclose(file);
  40. duk_buffer_to_string(ctx, -1);
  41. return;
  42. error:
  43. if (file)
  44. fclose(file);
  45. (void) duk_error(ctx, DUK_ERR_TYPE_ERROR, "Unable to read '%s': %s", filename, strerror(errno));
  46. }
  47. static duk_ret_t push_file_contents_wrapper(duk_context *ctx, void *filename) {
  48. push_file_contents(ctx, filename);
  49. return 1;
  50. }
  51. duk_ret_t push_file_contents_safe(duk_context *ctx, char *filename) {
  52. return duk_safe_call(ctx, push_file_contents_wrapper, filename, 0, 1);
  53. }
  54. struct args {const char *str; duk_size_t len;};
  55. static duk_ret_t safe_push_lstring(duk_context *ctx, void *udata) {
  56. duk_push_lstring(ctx, ((struct args*)udata)->str, ((struct args*)udata)->len);
  57. return 1;
  58. }
  59. duk_ret_t console_readline(duk_context *ctx) {
  60. size_t n = 0;
  61. char *line = NULL;
  62. ssize_t len;
  63. if ((len = __getline(&line, &n, stdin)) == -1) {
  64. free(line);
  65. goto failure;
  66. }
  67. struct args udata = {line, len - 1};
  68. if (duk_safe_call(ctx, safe_push_lstring, &udata, 0, 1)) {
  69. free(line);
  70. return duk_throw(ctx);
  71. }
  72. return 1;
  73. failure:
  74. return duk_generic_error(ctx, "Unable to read line: %s", strerror(errno));
  75. }