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.
 
 
 
 
 

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