An emulator, assembler, and disassembler for the Sega Game Gear
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

126 lines
3.0 KiB

  1. /* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. Released under the terms of the MIT License. See LICENSE for details. */
  3. #include <stdlib.h>
  4. #include "errors.h"
  5. #include "state.h"
  6. #include "../assembler.h"
  7. #include "../logging.h"
  8. #define ERROR_TYPE(err_info) (asm_error_types[err_info->type])
  9. #define ERROR_DESC(err_info) (asm_error_descs[err_info->desc])
  10. /* Internal structs */
  11. struct ASMErrorLine {
  12. char *data;
  13. size_t length;
  14. size_t lineno;
  15. char *filename;
  16. struct ASMErrorLine *next;
  17. };
  18. typedef struct ASMErrorLine ASMErrorLine;
  19. struct ErrorInfo {
  20. ASMErrorType type;
  21. ASMErrorDesc desc;
  22. ASMErrorLine *line;
  23. };
  24. /*
  25. Create an ASMErrorLine object from an ASMLine.
  26. */
  27. static ASMErrorLine* create_error_line(const ASMLine *line)
  28. {
  29. ASMErrorLine *el = malloc(sizeof(ASMErrorLine));
  30. if (!el)
  31. OUT_OF_MEMORY()
  32. const char *source = line->original->data;
  33. size_t length = line->original->length;
  34. if (!(el->data = malloc(sizeof(char) * length)))
  35. OUT_OF_MEMORY()
  36. // Ignore spaces at beginning:
  37. while (length > 0 && (*source == ' ' || *source == '\t'))
  38. source++, length--;
  39. memcpy(el->data, source, length);
  40. el->length = length;
  41. el->lineno = line->original->lineno;
  42. el->filename = strdup(line->filename);
  43. if (!el->filename)
  44. OUT_OF_MEMORY()
  45. el->next = NULL;
  46. return el;
  47. }
  48. /*
  49. Create an ErrorInfo object describing a particular error.
  50. The ErrorInfo object can be printed with error_info_print(), and must be
  51. freed when done with error_info_destroy().
  52. This function never fails (OOM triggers an exit()); the caller can be
  53. confident the returned object is valid.
  54. */
  55. ErrorInfo* error_info_create(
  56. const ASMLine *line, ASMErrorType err_type, ASMErrorDesc err_desc)
  57. {
  58. ErrorInfo *einfo = malloc(sizeof(ErrorInfo));
  59. if (!einfo)
  60. OUT_OF_MEMORY()
  61. einfo->type = err_type;
  62. einfo->desc = err_desc;
  63. einfo->line = create_error_line(line);
  64. return einfo;
  65. }
  66. /*
  67. Add an ASMLine to an ErrorInfo object, as part of a file trace.
  68. */
  69. void error_info_append(ErrorInfo *einfo, const ASMLine *line)
  70. {
  71. ASMErrorLine* el = create_error_line(line);
  72. el->next = einfo->line;
  73. einfo->line = el;
  74. }
  75. /*
  76. Print an ErrorInfo object returned by assemble() to the given stream.
  77. */
  78. void error_info_print(const ErrorInfo *einfo, FILE *file)
  79. {
  80. ASMErrorLine *line = einfo->line;
  81. fprintf(file, "error: %s: %s\n", ERROR_TYPE(einfo), ERROR_DESC(einfo));
  82. while (line) {
  83. fprintf(file, "%s:%zu:\n", line->filename, line->lineno);
  84. fprintf(file, " %.*s\n", (int) line->length, line->data);
  85. line = line->next;
  86. }
  87. }
  88. /*
  89. Destroy an ErrorInfo object created by assemble().
  90. */
  91. void error_info_destroy(ErrorInfo *error_info)
  92. {
  93. if (!error_info)
  94. return;
  95. ASMErrorLine *line = error_info->line, *temp;
  96. while (line) {
  97. temp = line->next;
  98. free(line->data);
  99. free(line->filename);
  100. free(line);
  101. line = temp;
  102. }
  103. free(error_info);
  104. }