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. "include directive", // ET_INCLUDE
  13. "preprocessor", // ET_PREPROC
  14. "memory layout", // ET_LAYOUT
  15. "symbol table", // ET_SYMBOL
  16. "instruction parser" // ET_PARSER
  17. };
  18. static const char *asm_error_descs[] = {
  19. "missing or invalid argument", // ED_INC_BAD_ARG
  20. "infinite recursion detected", // ED_INC_RECURSION
  21. "couldn't read included file", // ED_INC_FILE_READ
  22. "unknown directive", // ED_PP_UNKNOWN
  23. "multiple values for directive", // ED_PP_DUPLICATE
  24. "missing argument for directive", // ED_PP_NO_ARG
  25. "invalid argument for directive", // ED_PP_BAD_ARG
  26. "directive argument out of range", // ED_PP_ARG_RANGE
  27. "header offset exceeds given ROM size", // ED_LYT_HEADER_RANGE
  28. "declared ROM size in header exceeds actual size", // ED_LYT_DECLARE_RANGE
  29. "location is out of bounds for the ROM size", // ED_LYT_BOUNDS
  30. "block zero cannot be mapped into a nonzero slot", // ED_LYT_BLOCK0
  31. "multiple slot declarations for block directive", // ED_LYT_SLOTS
  32. "location overlaps with instruction or data", // ED_LYT_OVERLAP
  33. "location overlaps with ROM header", // ED_LYT_OVERLAP_HEAD
  34. "duplicate definitions for label", // ED_SYM_DUPE_LABELS
  35. "undefined reference to label", // ED_SYM_NO_LABEL
  36. "syntax error" // ED_PARSE_SYNTAX
  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. }