An emulator, assembler, and disassembler for the Sega Game Gear
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

161 lignes
4.5 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. /* Error strings */
  11. static const char *asm_error_types[] = {
  12. [ET_INCLUDE] = "include directive",
  13. [ET_PREPROC] = "preprocessor",
  14. [ET_LAYOUT] = "memory layout",
  15. [ET_SYMBOL] = "symbol table",
  16. [ET_PARSER] = "instruction parser"
  17. };
  18. static const char *asm_error_descs[] = {
  19. [ED_INC_BAD_ARG] = "missing or invalid argument",
  20. [ED_INC_RECURSION] = "infinite recursion detected",
  21. [ED_INC_FILE_READ] = "couldn't read included file",
  22. [ED_PP_UNKNOWN] = "unknown directive",
  23. [ED_PP_DUPLICATE] = "multiple values for directive",
  24. [ED_PP_NO_ARG] = "missing argument for directive",
  25. [ED_PP_BAD_ARG] = "invalid argument for directive",
  26. [ED_PP_ARG_RANGE] = "directive argument out of range",
  27. [ED_LYT_HEADER_RANGE] = "header offset exceeds given ROM size",
  28. [ED_LYT_DECL_RANGE] = "declared ROM size in header exceeds actual size",
  29. [ED_LYT_BOUNDS] = "location is out of bounds for the ROM size",
  30. [ED_LYT_BLOCK0] = "block zero cannot be mapped into a nonzero slot",
  31. [ED_LYT_SLOTS] = "multiple slot declarations for block directive",
  32. [ED_LYT_OVERLAP] = "location overlaps with instruction or data",
  33. [ED_LYT_OVERLAP_HEAD] = "location overlaps with ROM header",
  34. [ED_SYM_DUPE_LABELS] = "duplicate definitions for label",
  35. [ED_SYM_NO_LABEL] = "undefined reference to label",
  36. [ED_PARSE_SYNTAX] = "syntax error"
  37. };
  38. /* Internal structs */
  39. struct ASMErrorLine {
  40. char *data;
  41. size_t length;
  42. size_t lineno;
  43. char *filename;
  44. struct ASMErrorLine *next;
  45. };
  46. typedef struct ASMErrorLine ASMErrorLine;
  47. struct ErrorInfo {
  48. ASMErrorType type;
  49. ASMErrorDesc desc;
  50. ASMErrorLine *line;
  51. };
  52. /*
  53. Create an ASMErrorLine object from an ASMLine.
  54. */
  55. static ASMErrorLine* create_error_line(const ASMLine *line)
  56. {
  57. ASMErrorLine *el = malloc(sizeof(ASMErrorLine));
  58. if (!el)
  59. OUT_OF_MEMORY()
  60. const char *source = line->original->data;
  61. size_t length = line->original->length;
  62. if (!(el->data = malloc(sizeof(char) * length)))
  63. OUT_OF_MEMORY()
  64. // Ignore spaces at beginning:
  65. while (length > 0 && (*source == ' ' || *source == '\t'))
  66. source++, length--;
  67. memcpy(el->data, source, length);
  68. el->length = length;
  69. el->lineno = line->original->lineno;
  70. el->filename = strdup(line->filename);
  71. if (!el->filename)
  72. OUT_OF_MEMORY()
  73. el->next = NULL;
  74. return el;
  75. }
  76. /*
  77. Create an ErrorInfo object describing a particular error.
  78. The ErrorInfo object can be printed with error_info_print(), and must be
  79. freed when done with error_info_destroy().
  80. This function never fails (OOM triggers an exit()); the caller can be
  81. confident the returned object is valid.
  82. */
  83. ErrorInfo* error_info_create(
  84. const ASMLine *line, ASMErrorType err_type, ASMErrorDesc err_desc)
  85. {
  86. ErrorInfo *einfo = malloc(sizeof(ErrorInfo));
  87. if (!einfo)
  88. OUT_OF_MEMORY()
  89. einfo->type = err_type;
  90. einfo->desc = err_desc;
  91. einfo->line = line ? create_error_line(line) : NULL;
  92. return einfo;
  93. }
  94. /*
  95. Add an ASMLine to an ErrorInfo object, as part of a file trace.
  96. */
  97. void error_info_append(ErrorInfo *einfo, const ASMLine *line)
  98. {
  99. ASMErrorLine* el = create_error_line(line);
  100. el->next = einfo->line;
  101. einfo->line = el;
  102. }
  103. /*
  104. Print an ErrorInfo object returned by assemble() to the given stream.
  105. */
  106. void error_info_print(const ErrorInfo *einfo, FILE *file)
  107. {
  108. ASMErrorLine *line = einfo->line;
  109. fprintf(file, "error: %s: %s\n", ERROR_TYPE(einfo), ERROR_DESC(einfo));
  110. while (line) {
  111. fprintf(file, "%s:%zu:\n", line->filename, line->lineno);
  112. fprintf(file, " %.*s\n", (int) line->length, line->data);
  113. line = line->next;
  114. }
  115. }
  116. /*
  117. Destroy an ErrorInfo object created by assemble().
  118. */
  119. void error_info_destroy(ErrorInfo *error_info)
  120. {
  121. if (!error_info)
  122. return;
  123. ASMErrorLine *line = error_info->line, *temp;
  124. while (line) {
  125. temp = line->next;
  126. free(line->data);
  127. free(line->filename);
  128. free(line);
  129. line = temp;
  130. }
  131. free(error_info);
  132. }