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.

io.c 3.1 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 <errno.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/stat.h>
  8. #include "io.h"
  9. #include "../logging.h"
  10. #include "../util.h"
  11. /*
  12. Deallocate a LineBuffer previously created with read_source_file().
  13. */
  14. void line_buffer_free(LineBuffer *buffer)
  15. {
  16. Line *line = buffer->lines, *temp;
  17. while (line) {
  18. temp = line->next;
  19. free(line->data);
  20. free(line);
  21. line = temp;
  22. }
  23. free(buffer->filename);
  24. free(buffer);
  25. }
  26. /*
  27. Read the contents of the source file at the given path into a line buffer.
  28. Return the buffer if reading was successful; it must be freed with
  29. line_buffer_free() when done. Return NULL if an error occurred while
  30. reading. If print_errors is true, a message will also be printed to stderr.
  31. */
  32. LineBuffer* read_source_file(const char *path, bool print_errors)
  33. {
  34. FILE *fp;
  35. struct stat st;
  36. if (!(fp = fopen(path, "r"))) {
  37. if (print_errors)
  38. ERROR_ERRNO("couldn't open source file")
  39. return NULL;
  40. }
  41. if (fstat(fileno(fp), &st)) {
  42. fclose(fp);
  43. if (print_errors)
  44. ERROR_ERRNO("couldn't open source file")
  45. return NULL;
  46. }
  47. if (!(st.st_mode & S_IFREG)) {
  48. fclose(fp);
  49. if (print_errors)
  50. ERROR("couldn't open source file: %s", st.st_mode & S_IFDIR ?
  51. "Is a directory" : "Is not a regular file")
  52. return NULL;
  53. }
  54. LineBuffer *source = cr_malloc(sizeof(LineBuffer));
  55. source->lines = NULL;
  56. source->filename = cr_strdup(path);
  57. Line dummy = {.next = NULL};
  58. Line *line, *prev = &dummy;
  59. size_t lineno = 1;
  60. while (1) {
  61. char *data = NULL;
  62. size_t cap = 0;
  63. ssize_t len;
  64. if ((len = getline(&data, &cap, fp)) < 0) {
  65. if (feof(fp))
  66. break;
  67. if (errno == ENOMEM)
  68. OUT_OF_MEMORY()
  69. if (print_errors)
  70. ERROR_ERRNO("couldn't read source file")
  71. fclose(fp);
  72. source->lines = dummy.next;
  73. line_buffer_free(source);
  74. return NULL;
  75. }
  76. line = cr_malloc(sizeof(Line));
  77. line->data = data;
  78. line->length = feof(fp) ? len : (len - 1);
  79. line->lineno = lineno++;
  80. line->next = NULL;
  81. prev->next = line;
  82. prev = line;
  83. }
  84. fclose(fp);
  85. source->lines = dummy.next;
  86. return source;
  87. }
  88. /*
  89. Write an assembled binary file to the given path.
  90. Return whether the file was written successfully. On error, a message is
  91. printed to stderr.
  92. */
  93. bool write_binary_file(const char *path, const uint8_t *data, size_t size)
  94. {
  95. FILE *fp;
  96. if (!(fp = fopen(path, "wb"))) {
  97. ERROR_ERRNO("couldn't open destination file")
  98. return false;
  99. }
  100. if (!fwrite(data, size, 1, fp)) {
  101. fclose(fp);
  102. ERROR_ERRNO("couldn't write to destination file")
  103. return false;
  104. }
  105. fclose(fp);
  106. return true;
  107. }