sourcedata.c 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include "pocketpy/objects/sourcedata.h"
  2. #include "pocketpy/common/sstream.h"
  3. #include <ctype.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. static void SourceData__ctor(struct SourceData* self,
  7. const char* source,
  8. const char* filename,
  9. enum py_CompileMode mode,
  10. bool is_dynamic) {
  11. self->filename = c11_string__new(filename);
  12. self->mode = mode;
  13. c11_vector__ctor(&self->line_starts, sizeof(const char*));
  14. // Skip utf8 BOM if there is any.
  15. if(strncmp(source, "\xEF\xBB\xBF", 3) == 0) source += 3;
  16. // Drop all '\r'
  17. c11_sbuf ss;
  18. c11_sbuf__ctor(&ss);
  19. while(true) {
  20. char c = *source;
  21. if(c == '\0') break;
  22. if(c != '\r') c11_sbuf__write_char(&ss, c);
  23. source++;
  24. }
  25. self->source = c11_sbuf__submit(&ss);
  26. self->is_dynamic = is_dynamic;
  27. c11_vector__push(const char*, &self->line_starts, self->source->data);
  28. }
  29. static void SourceData__dtor(struct SourceData* self) {
  30. c11_string__delete(self->filename);
  31. c11_string__delete(self->source);
  32. c11_vector__dtor(&self->line_starts);
  33. }
  34. SourceData_ SourceData__rcnew(const char* source,
  35. const char* filename,
  36. enum py_CompileMode mode,
  37. bool is_dynamic) {
  38. SourceData_ self = malloc(sizeof(struct SourceData));
  39. SourceData__ctor(self, source, filename, mode, is_dynamic);
  40. self->rc.count = 1;
  41. self->rc.dtor = (void (*)(void*))SourceData__dtor;
  42. return self;
  43. }
  44. bool SourceData__get_line(const struct SourceData* self,
  45. int lineno,
  46. const char** st,
  47. const char** ed) {
  48. if(lineno < 0) return false;
  49. lineno -= 1;
  50. if(lineno < 0) lineno = 0;
  51. const char* _start = c11__getitem(const char*, &self->line_starts, lineno);
  52. const char* i = _start;
  53. // max 300 chars
  54. while(*i != '\n' && *i != '\0' && i - _start < 300)
  55. i++;
  56. *st = _start;
  57. *ed = i;
  58. return true;
  59. }
  60. void SourceData__snapshot(const struct SourceData* self,
  61. c11_sbuf* ss,
  62. int lineno,
  63. const char* cursor,
  64. const char* name) {
  65. pk_sprintf(ss, " File \"%s\", line %d", self->filename->data, lineno);
  66. if(name && *name) {
  67. c11_sbuf__write_cstr(ss, ", in ");
  68. c11_sbuf__write_cstr(ss, name);
  69. }
  70. c11_sbuf__write_char(ss, '\n');
  71. const char *st = NULL, *ed;
  72. if(SourceData__get_line(self, lineno, &st, &ed)) {
  73. while(st < ed && isblank(*st))
  74. ++st;
  75. if(st < ed) {
  76. c11_sbuf__write_cstr(ss, " ");
  77. c11_sbuf__write_cstrn(ss, st, ed - st);
  78. if(cursor && st <= cursor && cursor <= ed) {
  79. c11_sbuf__write_cstr(ss, "\n ");
  80. for(int i = 0; i < (cursor - st); ++i)
  81. c11_sbuf__write_char(ss, ' ');
  82. c11_sbuf__write_cstr(ss, "^");
  83. }
  84. } else {
  85. st = NULL;
  86. }
  87. }
  88. if(!st) { c11_sbuf__write_cstr(ss, " <?>"); }
  89. }