main.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <stdbool.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <assert.h>
  5. #include <string.h>
  6. #include "pocketpy.h"
  7. #define py_interrupt()
  8. #ifdef _WIN32
  9. #define WIN32_LEAN_AND_MEAN
  10. #include <windows.h>
  11. static BOOL WINAPI sigint_handler(DWORD dwCtrlType) {
  12. if(dwCtrlType == CTRL_C_EVENT) {
  13. py_interrupt();
  14. return TRUE;
  15. }
  16. return FALSE;
  17. }
  18. #else
  19. // set ctrl+c handler
  20. #include <signal.h>
  21. #include <unistd.h>
  22. static void sigint_handler(int sig) { py_interrupt(); }
  23. #endif
  24. static char* read_file(const char* path) {
  25. FILE* file = fopen(path, "rb");
  26. if(file == NULL) {
  27. printf("Error: file not found\n");
  28. return NULL;
  29. }
  30. fseek(file, 0, SEEK_END);
  31. long size = ftell(file);
  32. fseek(file, 0, SEEK_SET);
  33. char* buffer = malloc(size + 1);
  34. size = fread(buffer, 1, size, file);
  35. buffer[size] = 0;
  36. return buffer;
  37. }
  38. static void tracefunc(py_Frame* frame, enum py_TraceEvent event) {
  39. int line;
  40. const char* filename = py_Frame_sourceloc(frame, &line);
  41. const char* event_str;
  42. switch(event) {
  43. case TRACE_EVENT_LINE:
  44. event_str = "line";
  45. break;
  46. case TRACE_EVENT_EXCEPTION:
  47. event_str = "exception";
  48. break;
  49. case TRACE_EVENT_PUSH:
  50. event_str = "push";
  51. break;
  52. case TRACE_EVENT_POP:
  53. event_str = "pop";
  54. break;
  55. }
  56. printf("\x1b[30m%s:%d, event=%s\x1b[0m\n", filename, line, event_str);
  57. }
  58. static char buf[2048];
  59. int main(int argc, char** argv) {
  60. #if _WIN32
  61. SetConsoleCP(CP_UTF8);
  62. SetConsoleOutputCP(CP_UTF8);
  63. // SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigint_handler, TRUE);
  64. #else
  65. // signal(SIGINT, sigint_handler);
  66. #endif
  67. bool trace = false;
  68. const char* filename = NULL;
  69. for(int i = 1; i < argc; i++) {
  70. if(strcmp(argv[i], "--trace") == 0) {
  71. trace = true;
  72. continue;
  73. }
  74. if(filename == NULL) {
  75. filename = argv[i];
  76. continue;
  77. }
  78. printf("Usage: pocketpy [--trace] filename\n");
  79. }
  80. py_initialize();
  81. py_sys_setargv(argc, argv);
  82. if(trace) py_sys_settrace(tracefunc);
  83. if(filename == NULL) {
  84. printf("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") ");
  85. printf("[%d bit] on %s", (int)(sizeof(void*) * 8), PY_SYS_PLATFORM_STRING);
  86. #ifndef NDEBUG
  87. printf(" (DEBUG)");
  88. #endif
  89. printf("\n");
  90. printf("https://github.com/pocketpy/pocketpy\n");
  91. printf("Type \"exit()\" to exit.\n");
  92. while(true) {
  93. int size = py_replinput(buf, sizeof(buf));
  94. if(size == -1) { // Ctrl-D (i.e. EOF)
  95. printf("\n");
  96. break;
  97. }
  98. assert(size < sizeof(buf));
  99. if(size >= 0) {
  100. py_StackRef p0 = py_peek(0);
  101. if(!py_exec(buf, "<stdin>", SINGLE_MODE, NULL)) {
  102. py_printexc();
  103. py_clearexc(p0);
  104. }
  105. }
  106. }
  107. } else {
  108. char* source = read_file(filename);
  109. if(source) {
  110. if(!py_exec(source, filename, EXEC_MODE, NULL)) py_printexc();
  111. free(source);
  112. }
  113. }
  114. int code = py_checkexc(false) ? 1 : 0;
  115. py_finalize();
  116. return code;
  117. }