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.
 
 
 
 
 

163 lignes
5.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 "../util.h"
  8. /* Error strings */
  9. static const char *error_types[] = {
  10. [ET_INCLUDE] = "include directive",
  11. [ET_PREPROC] = "preprocessor",
  12. [ET_LAYOUT] = "memory layout",
  13. [ET_SYMBOL] = "symbol table",
  14. [ET_PARSER] = "instruction parser"
  15. };
  16. static const char *error_descs[] = {
  17. [ED_NONE] = "undefined error",
  18. [ED_INC_BAD_ARG] = "missing or invalid argument",
  19. [ED_INC_DEPTH] = "maximum include depth exceeded",
  20. [ED_INC_FILE_READ] = "couldn't read included file",
  21. [ED_PP_UNKNOWN] = "unknown directive",
  22. [ED_PP_DUPLICATE] = "multiple values for directive",
  23. [ED_PP_NO_ARG] = "missing argument for directive",
  24. [ED_PP_BAD_ARG] = "invalid argument for directive",
  25. [ED_PP_ARG_RANGE] = "directive argument out of range",
  26. [ED_LYT_HEADER_RANGE] = "header offset exceeds given ROM size",
  27. [ED_LYT_DECL_RANGE] = "declared ROM size in header exceeds actual size",
  28. [ED_LYT_BOUNDS] = "location is out of bounds for the ROM size",
  29. [ED_LYT_BLOCK0] = "block zero cannot be mapped into a nonzero slot",
  30. [ED_LYT_SLOTS] = "multiple slot declarations for block directive",
  31. [ED_LYT_BLOCK_CROSS] = "instruction or data extends past block boundary",
  32. [ED_LYT_OVERLAP] = "multiple instructions/data occupy same location",
  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_SYM_TOO_LONG] = "label name is too long",
  37. [ED_SYM_IS_REGISTER] = "labels cannot share names with registers",
  38. [ED_SYM_IS_CONDITION] = "labels cannot share names with condition codes",
  39. [ED_PS_OP_TOO_LONG] = "opcode mnemonic is too long (2-4 characters)",
  40. [ED_PS_OP_TOO_SHORT] = "opcode mnemonic is too short (2-4 characters)",
  41. [ED_PS_OP_INVALID] = "invalid characters in opcode mnemonic",
  42. [ED_PS_OP_UNKNOWN] = "unknown opcode mnemonic",
  43. [ED_PS_TOO_FEW_ARGS] = "too few arguments for opcode",
  44. [ED_PS_TOO_MANY_ARGS] = "too many arguments for opcode",
  45. [ED_PS_ARG_SYNTAX] = "invalid syntax in argument(s)",
  46. [ED_PS_ARG_TYPE] = "invalid argument type",
  47. [ED_PS_ARG_VALUE] = "invalid value for argument"
  48. };
  49. /* Internal structs */
  50. struct ASMErrorLine {
  51. char *data;
  52. size_t length;
  53. size_t lineno;
  54. char *filename;
  55. struct ASMErrorLine *next;
  56. };
  57. typedef struct ASMErrorLine ASMErrorLine;
  58. struct ErrorInfo {
  59. ASMErrorType type;
  60. ASMErrorDesc desc;
  61. ASMErrorLine *line;
  62. };
  63. /*
  64. Create an ASMErrorLine object from an ASMLine.
  65. */
  66. static ASMErrorLine* create_error_line(const ASMLine *line)
  67. {
  68. ASMErrorLine *el = cr_malloc(sizeof(ASMErrorLine));
  69. const char *source = line->original->data;
  70. size_t length = line->original->length;
  71. // Ignore spaces at beginning:
  72. while (length > 0 && (*source == ' ' || *source == '\t'))
  73. source++, length--;
  74. el->data = cr_malloc(sizeof(char) * length);
  75. memcpy(el->data, source, length);
  76. el->length = length;
  77. el->lineno = line->original->lineno;
  78. el->filename = cr_strdup(line->filename);
  79. el->next = NULL;
  80. return el;
  81. }
  82. /*
  83. Create an ErrorInfo object describing a particular error.
  84. The ErrorInfo object can be printed with error_info_print(), and must be
  85. freed when done with error_info_destroy().
  86. This function never fails (OOM triggers an exit()); the caller can be
  87. confident the returned object is valid.
  88. */
  89. ErrorInfo* error_info_create(
  90. const ASMLine *line, ASMErrorType err_type, ASMErrorDesc err_desc)
  91. {
  92. ErrorInfo *einfo = cr_malloc(sizeof(ErrorInfo));
  93. einfo->type = err_type;
  94. einfo->desc = err_desc;
  95. einfo->line = line ? create_error_line(line) : NULL;
  96. return einfo;
  97. }
  98. /*
  99. Add an ASMLine to an ErrorInfo object, as part of a file trace.
  100. */
  101. void error_info_append(ErrorInfo *einfo, const ASMLine *line)
  102. {
  103. ASMErrorLine* el = create_error_line(line);
  104. el->next = einfo->line;
  105. einfo->line = el;
  106. }
  107. /*
  108. Print an ErrorInfo object returned by assemble() to the given stream.
  109. */
  110. void error_info_print(const ErrorInfo *einfo, FILE *file)
  111. {
  112. ASMErrorLine *line = einfo->line;
  113. fprintf(file, "error: %s: %s\n", error_types[einfo->type],
  114. error_descs[einfo->desc]);
  115. while (line) {
  116. fprintf(file, "%s:%zu:\n", line->filename, line->lineno);
  117. fprintf(file, " %.*s\n", (int) line->length, line->data);
  118. line = line->next;
  119. }
  120. }
  121. /*
  122. Destroy an ErrorInfo object created by assemble().
  123. */
  124. void error_info_destroy(ErrorInfo *error_info)
  125. {
  126. if (!error_info)
  127. return;
  128. ASMErrorLine *line = error_info->line, *temp;
  129. while (line) {
  130. temp = line->next;
  131. free(line->data);
  132. free(line->filename);
  133. free(line);
  134. line = temp;
  135. }
  136. free(error_info);
  137. }