1
0

stdio.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Stdio replacement library
  3. * Contains a subset of functions to use as drop-in replacement
  4. * Originally made for porting the BCC compiler
  5. * BDOS_PrintConsole could be replaced with uprint instead
  6. */
  7. // maximum number of files to open at the same time (+1 because we skip index 0)
  8. #define FOPEN_MAX_FILES 16
  9. #define FOPEN_FILENAME_LIMIT 32
  10. #define EOF -1
  11. char fopenList[FOPEN_MAX_FILES][FOPEN_FILENAME_LIMIT]; // filenames for each opened file
  12. word fopenCurrentlyOpen[FOPEN_MAX_FILES]; // which indexes are currently opened
  13. word fopenCursors[FOPEN_MAX_FILES]; // cursors of currently opened files
  14. word CH376CurrentlyOpened = 0; // index in fopenList which is currently opened on CH376
  15. // fopen replacement
  16. // requires full paths
  17. // returns 0 on error
  18. // otherwise returns the index to the fopenList buffer
  19. // creates new file if write is 1
  20. // append is not an option for now
  21. word fopen(const char* fname, const word write)
  22. {
  23. if (strlen(fname) >= FOPEN_FILENAME_LIMIT)
  24. {
  25. BDOS_PrintConsole("E: Path too large\n");
  26. return 0;
  27. }
  28. if (fname[0] != '/')
  29. {
  30. BDOS_PrintConsole("E: Filename should be a full path\n");
  31. return 0;
  32. }
  33. // conver to uppercase
  34. strToUpper(fname);
  35. // if write, create the file
  36. if (write)
  37. {
  38. FS_close(); // to be sure
  39. CH376CurrentlyOpened = 0;
  40. // if current path is correct (can be file or directory)
  41. if (FS_sendFullPath(fname) == FS_ANSW_USB_INT_SUCCESS)
  42. {
  43. // create the file
  44. if (FS_createFile() == FS_ANSW_USB_INT_SUCCESS)
  45. {
  46. //BDOS_PrintConsole("File created\n");
  47. }
  48. else
  49. {
  50. BDOS_PrintConsole("E: Could not create file\n");
  51. return 0;
  52. }
  53. }
  54. else
  55. {
  56. BDOS_PrintConsole("E: Invalid path\n");
  57. return 0;
  58. }
  59. }
  60. word i = 1; // skip index 0
  61. while (i < FOPEN_MAX_FILES)
  62. {
  63. if (fopenCurrentlyOpen[i] == 0)
  64. {
  65. // found a free spot
  66. fopenCurrentlyOpen[i] = 1;
  67. fopenCursors[i] = 0;
  68. // write filename
  69. strcpy(fopenList[i], fname);
  70. return i; // return index
  71. }
  72. i++;
  73. }
  74. BDOS_PrintConsole("E: The maximum number of files are already opened. Forgot to close some files?\n");
  75. return 0;
  76. }
  77. // closes file at index
  78. // also closes the file on CH376 if it is currently open there as well
  79. void fclose(word i)
  80. {
  81. if (CH376CurrentlyOpened == i)
  82. {
  83. FS_close(); // to be sure
  84. CH376CurrentlyOpened = 0;
  85. }
  86. fopenCurrentlyOpen[i] = 0;
  87. fopenList[i][0] = 0; // to be sure
  88. }
  89. // returns the current char at cursor (EOF is end of file)
  90. // increments the cursor
  91. word fgetc(word i)
  92. {
  93. // check if file is open
  94. if (fopenCurrentlyOpen[i] == 0)
  95. {
  96. BDOS_PrintConsole("fgetc: File is not open\n");
  97. return EOF;
  98. }
  99. // open on CH376 if not open already
  100. if (CH376CurrentlyOpened != i)
  101. {
  102. // close last one first, unless there is no last
  103. if (CH376CurrentlyOpened != 0)
  104. {
  105. //BDOS_PrintConsole("fgetc: Closed previous file\n");
  106. FS_close();
  107. }
  108. // if the resulting path is correct (can be file or directory)
  109. if (FS_sendFullPath(fopenList[i]) == FS_ANSW_USB_INT_SUCCESS)
  110. {
  111. // if we can successfully open the file (not directory)
  112. if (FS_open() == FS_ANSW_USB_INT_SUCCESS)
  113. {
  114. CH376CurrentlyOpened = i;
  115. // set cursor to last position
  116. FS_setCursor(fopenCursors[i]);
  117. //BDOS_PrintConsole("fgetc: File opened on CH376\n");
  118. }
  119. else
  120. {
  121. BDOS_PrintConsole("E: Could not open file\n");
  122. return EOF;
  123. }
  124. }
  125. else
  126. {
  127. BDOS_PrintConsole("E: Invalid path\n");
  128. return EOF;
  129. }
  130. }
  131. // read char and increment cursor locally
  132. char gotchar = 0;
  133. word retval = FS_readFile(&gotchar, 1, 0);
  134. if (retval != FS_ANSW_USB_INT_SUCCESS)
  135. {
  136. // assume EOF
  137. return EOF;
  138. }
  139. fopenCursors[i]++;
  140. return gotchar;
  141. }
  142. // writes string s at cursor
  143. // increments the cursor
  144. // returns EOF on failure
  145. // otherwise returns 1
  146. word fputs(word i, char* s)
  147. {
  148. // check if file is open
  149. if (fopenCurrentlyOpen[i] == 0)
  150. {
  151. BDOS_PrintConsole("fputs: File is not open\n");
  152. return EOF;
  153. }
  154. // open on CH376 if not open already
  155. if (CH376CurrentlyOpened != i)
  156. {
  157. // close last one first, unless there is no last
  158. if (CH376CurrentlyOpened != 0)
  159. {
  160. //BDOS_PrintConsole("fputs: Closed previous file\n");
  161. FS_close();
  162. }
  163. // if the resulting path is correct (can be file or directory)
  164. if (FS_sendFullPath(fopenList[i]) == FS_ANSW_USB_INT_SUCCESS)
  165. {
  166. // if we can successfully open the file (not directory)
  167. if (FS_open() == FS_ANSW_USB_INT_SUCCESS)
  168. {
  169. CH376CurrentlyOpened = i;
  170. // set cursor to last position
  171. FS_setCursor(fopenCursors[i]);
  172. //BDOS_PrintConsole("fputs: File opened on CH376\n");
  173. }
  174. else
  175. {
  176. BDOS_PrintConsole("E: Could not open file\n");
  177. return EOF;
  178. }
  179. }
  180. else
  181. {
  182. BDOS_PrintConsole("E: Invalid path\n");
  183. return EOF;
  184. }
  185. }
  186. // write string and increment cursor locally
  187. word slen = strlen(s);
  188. word retval = FS_writeFile(s, slen);
  189. if (retval != FS_ANSW_USB_INT_SUCCESS)
  190. {
  191. // assume EOF
  192. return EOF;
  193. }
  194. fopenCursors[i] += slen;
  195. return 1;
  196. }
  197. // fputs, but a single char
  198. word fputc(word i, char c)
  199. {
  200. char* s = "0";
  201. s[0] = c;
  202. return fputs(i, s);
  203. }
  204. word printf(char* s)
  205. {
  206. //TODO: do escape character handling
  207. BDOS_PrintConsole(s);
  208. }
  209. word printd(word d)
  210. {
  211. if (d < 0)
  212. {
  213. BDOS_PrintcConsole('-');
  214. BDOS_PrintDecConsole(-d);
  215. }
  216. else
  217. {
  218. BDOS_PrintDecConsole(d);
  219. }
  220. }
  221. void exit(word i)
  222. {
  223. asm("jump Return_BDOS\n");
  224. }