1
0

stdlib.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /*
  2. * Standard library
  3. * Contains basic functions, including timer and memory functions
  4. */
  5. // uses math.c
  6. #define UART_TX_ADDR 0xC02723
  7. // Timer I/O Addresses
  8. #define TIMER1_VAL 0xC02739
  9. #define TIMER1_CTRL 0xC0273A
  10. #define TIMER2_VAL 0xC0273B
  11. #define TIMER2_CTRL 0xC0273C
  12. #define TIMER3_VAL 0xC0273D
  13. #define TIMER3_CTRL 0xC0273E
  14. word timer1Value = 0;
  15. word timer2Value = 0;
  16. word timer3Value = 0;
  17. /*
  18. * TODO:
  19. * - Convert most of these functions to assembly
  20. */
  21. /*
  22. Copies n words from src to dest
  23. */
  24. void memcpy(word* dest, word* src, word n)
  25. {
  26. word i;
  27. for (i = 0; i < n; i++)
  28. {
  29. dest[i] = src[i];
  30. }
  31. }
  32. /*
  33. Compares n words between a and b
  34. Returns 1 if similar, 0 otherwise
  35. */
  36. word memcmp(word* a, word* b, word n)
  37. {
  38. word i;
  39. for (i = 0; i < n; i++)
  40. {
  41. if (a[i] != b[i])
  42. {
  43. return 0;
  44. }
  45. }
  46. return 1;
  47. }
  48. /*
  49. Sets n words from dest to val
  50. */
  51. void memset(word* dest, word val, word n)
  52. {
  53. word i;
  54. for (i = 0; i < n; i++)
  55. {
  56. dest[i] = val;
  57. }
  58. }
  59. // Returns length of string
  60. word strlen(char* str)
  61. {
  62. word retval = 0;
  63. char chr = *str; // first character of str
  64. while (chr != 0) // continue until null value
  65. {
  66. retval += 1;
  67. str++; // go to next character address
  68. chr = *str; // get character from address
  69. }
  70. return retval;
  71. }
  72. /*
  73. Copies string from src to dest
  74. Returns number of characters copied
  75. */
  76. word strcpy(char* dest, char* src)
  77. {
  78. // write to buffer
  79. word i = 0;
  80. while (src[i] != 0)
  81. {
  82. dest[i] = src[i];
  83. i++;
  84. }
  85. // terminate
  86. dest[i] = 0;
  87. return i;
  88. }
  89. /*
  90. Appends string from src to dest
  91. Returns number of characters appended
  92. */
  93. word strcat(char* dest, char* src)
  94. {
  95. // move to end of destination
  96. word endOfDest = 0;
  97. while (dest[endOfDest] != 0)
  98. endOfDest++;
  99. // copy to end of destination
  100. return strcpy(dest+endOfDest, src);
  101. }
  102. /*
  103. Compares two strings a and b
  104. Returns 0 if similar
  105. otherwise returns the difference in the first non-matching character
  106. */
  107. word strcmp(char* s1, char* s2)
  108. {
  109. while(*s1 && (*s1 == *s2))
  110. {
  111. s1++;
  112. s2++;
  113. }
  114. return *s1 - *s2;
  115. }
  116. /*
  117. Returns a pointer to the first occurrence of the character c in the string s, or 0 if the character is not found.
  118. */
  119. char* strchr (const char *s, char c)
  120. {
  121. do {
  122. if (*s == c)
  123. {
  124. return (char*)s;
  125. }
  126. } while (*s++);
  127. return 0;
  128. }
  129. /*
  130. Returns a pointer to the last occurance of a character, or 0 if the character is not found.
  131. */
  132. char* strrchr (const char *s, int c)
  133. {
  134. char *rtnval = 0;
  135. do {
  136. if (*s == c)
  137. rtnval = (char*) s;
  138. } while (*s++);
  139. return (rtnval);
  140. }
  141. char * strtok_old_str;
  142. /*
  143. Parse str into tokens separated by characters in delim.
  144. If S is NULL, the last string strtok() was called with is used.
  145. Note that strtok() modifies the input string.
  146. For example:
  147. char s[] = "-abc-=-def";
  148. x = strtok(s, "-"); // x = "abc"
  149. x = strtok(NULL, "-="); // x = "def"
  150. x = strtok(NULL, "="); // x = NULL
  151. // s = "abc\0=-def\0"
  152. */
  153. char* strtok(char* str, const char* delim)
  154. {
  155. if (str != (word*)-1)
  156. strtok_old_str = str;
  157. if (strtok_old_str == (word*)-1)
  158. return (word*)-1;
  159. // Return reached end of string
  160. if (*strtok_old_str == 0)
  161. {
  162. return (word*)-1;
  163. }
  164. // Skip leading delimiters
  165. while (strchr(delim, *strtok_old_str) != 0)
  166. strtok_old_str++;
  167. // Find end of token
  168. char* start = strtok_old_str;
  169. while (*strtok_old_str != 0 && strchr(delim, *strtok_old_str) == 0)
  170. strtok_old_str++;
  171. if (*strtok_old_str == 0)
  172. {
  173. strtok_old_str = (word*)-1;
  174. return start;
  175. }
  176. *strtok_old_str = 0;
  177. strtok_old_str++;
  178. return start;
  179. }
  180. /*
  181. Compress a string made of one char per word, into a string made of one char per byte.
  182. */
  183. void strcompress(word* dest, char* src)
  184. {
  185. word i_src = 0;
  186. word i_dst = 0;
  187. word byte_offset = 0;
  188. word c = src[i_src];
  189. while (c != 0)
  190. {
  191. dest[i_dst] |= (c << byte_offset);
  192. if (byte_offset == 24)
  193. {
  194. byte_offset = 0;
  195. i_dst++;
  196. dest[i_dst] = 0;
  197. }
  198. else
  199. {
  200. byte_offset += 8;
  201. }
  202. i_src++;
  203. c = src[i_src];
  204. }
  205. }
  206. /*
  207. Decompress a string made of one char per byte, into a string made of one char per word.
  208. */
  209. void strdecompress(char* dest, word* src)
  210. {
  211. word i_src = 0;
  212. word i_dst = 0;
  213. word byte_offset = 0;
  214. while (1)
  215. {
  216. word c = (src[i_src] >> byte_offset) & 0xFF;
  217. if (c == 0)
  218. break;
  219. dest[i_dst] = c;
  220. i_dst++;
  221. if (byte_offset == 24)
  222. {
  223. byte_offset = 0;
  224. i_src++;
  225. }
  226. else
  227. {
  228. byte_offset += 8;
  229. }
  230. }
  231. // Terminate
  232. dest[i_dst] = 0;
  233. }
  234. /**
  235. * Return the basename of a path
  236. * path: full path
  237. */
  238. char* basename(char *path)
  239. {
  240. char *base = strrchr(path, '/');
  241. return base ? base + 1 : path;
  242. }
  243. /**
  244. * Return the dirname of a path
  245. * output: buffer to store the dirname
  246. * path: full path
  247. */
  248. char* dirname(char* output, char *path)
  249. {
  250. strcpy(output, path);
  251. char *last_slash = strrchr(output, '/');
  252. if (last_slash != 0)
  253. {
  254. *last_slash = 0;
  255. // If the last slash is the first character, return "/"
  256. if (last_slash == output)
  257. {
  258. strcpy(output, "/");
  259. }
  260. } else
  261. {
  262. // No slash found, return "."
  263. strcpy(output, ".");
  264. }
  265. return output;
  266. }
  267. /*
  268. Recursive helper function for itoa
  269. Eventually returns the number of digits in n
  270. s is the output buffer
  271. */
  272. word itoar(word n, char *s)
  273. {
  274. word digit = MATH_modU(n, 10);
  275. word i = 0;
  276. n = MATH_divU(n,10);
  277. if ((unsigned int) n > 0)
  278. i += itoar(n, s);
  279. s[i++] = digit + '0';
  280. return i;
  281. }
  282. /*
  283. Converts integer n to characters.
  284. The characters are placed in the buffer s.
  285. The buffer is terminated with a 0 value.
  286. Uses recursion, division and mod to compute.
  287. */
  288. void itoa(word n, char *s)
  289. {
  290. // compute and fill the buffer
  291. word i = itoar(n, s);
  292. // end with terminator
  293. s[i] = 0;
  294. }
  295. /*
  296. Recursive helper function for itoa
  297. Eventually returns the number of digits in n
  298. s is the output buffer
  299. */
  300. word itoahr(word n, char *s)
  301. {
  302. word digit = MATH_modU(n, 16);
  303. word i = 0;
  304. n = MATH_divU(n,16);
  305. if ((unsigned int) n > 0)
  306. i += itoahr(n, s);
  307. char c;
  308. if (digit > 9)
  309. {
  310. c = digit + 'A' - 10;
  311. }
  312. else
  313. {
  314. c = digit + '0';
  315. }
  316. s[i++] = c;
  317. return i;
  318. }
  319. /*
  320. Converts integer n to hex string characters.
  321. The characters are placed in the buffer s.
  322. A prefix of 0x is added.
  323. The buffer is terminated with a 0 value.
  324. Uses recursion, division and mod to compute.
  325. */
  326. void itoah(word n, char *s)
  327. {
  328. // add prefix
  329. s[0] = '0';
  330. s[1] = 'x';
  331. s+=2;
  332. // compute and fill the buffer
  333. word i = itoahr(n, s);
  334. // end with terminator
  335. s[i] = 0;
  336. }
  337. // isalpha
  338. word isalpha(char c)
  339. {
  340. if (c >= 'A' && c <= 'Z')
  341. return 2;
  342. if (c >= 'a' && c <= 'z')
  343. return 1;
  344. return 0;
  345. }
  346. // isdigit
  347. word isdigit(char c)
  348. {
  349. if (c >= '0' && c <= '9')
  350. return 1;
  351. return 0;
  352. }
  353. // isalnum
  354. word isalnum(char c)
  355. {
  356. if (isdigit(c) || isalpha(c))
  357. return 1;
  358. return 0;
  359. }
  360. /*
  361. Converts string into int.
  362. Assumes the string is valid.
  363. */
  364. word strToInt(char* str)
  365. {
  366. word retval = 0;
  367. word multiplier = 1;
  368. word i = 0;
  369. while (str[i] != 0)
  370. {
  371. i++;
  372. }
  373. if (i == 0)
  374. return 0;
  375. i--;
  376. while (i > 0)
  377. {
  378. // Return 0 if not a digit
  379. if (str[i] < '0' || str[i] > '9')
  380. return 0;
  381. word currentDigit = str[i] - '0';
  382. word toAdd = multiplier * currentDigit;
  383. retval += toAdd;
  384. multiplier = multiplier * 10;
  385. i--;
  386. }
  387. // Check for negative
  388. if (str[i] == '-')
  389. {
  390. retval *= -1;
  391. }
  392. else
  393. {
  394. word currentDigit = str[i] - '0';
  395. word toAdd = multiplier * currentDigit;
  396. retval += toAdd;
  397. }
  398. return retval;
  399. }
  400. /*
  401. Prints a single char c by writing it to UART_TX_ADDR
  402. */
  403. void uprintc(char c)
  404. {
  405. word *p = (word *)UART_TX_ADDR; // address of UART TX
  406. *p = (word)c; // write char over UART
  407. }
  408. /*
  409. Sends each character from str over UART
  410. by writing them to UART_TX_ADDR
  411. until a 0 value is found.
  412. Does not send a newline afterwards.
  413. */
  414. void uprint(char* str)
  415. {
  416. word *p = (word *)UART_TX_ADDR; // address of UART TX
  417. char chr = *str; // first character of str
  418. while (chr != 0) // continue until null value
  419. {
  420. *p = (word)chr; // write char over UART
  421. str++; // go to next character address
  422. chr = *str; // get character from address
  423. }
  424. }
  425. /*
  426. Same as uprint(char* str),
  427. except it sends a newline afterwards.
  428. */
  429. void uprintln(char* str)
  430. {
  431. uprint(str);
  432. uprintc('\n');
  433. }
  434. /*
  435. Prints decimal integer over UART
  436. */
  437. void uprintDec(word i)
  438. {
  439. char buffer[20];
  440. itoa(i, buffer);
  441. uprint(buffer);
  442. }
  443. /*
  444. Prints hex integer over UART
  445. */
  446. void uprintHex(word i)
  447. {
  448. char buffer[16];
  449. itoah(i, buffer);
  450. uprint(buffer);
  451. }
  452. /*
  453. Prints decimal integer over UART, with newline
  454. */
  455. void uprintlnDec(word i)
  456. {
  457. char buffer[20];
  458. itoa(i, buffer);
  459. uprint(buffer);
  460. uprintc('\n');
  461. }
  462. /*
  463. Prints hex integer over UART, with newline
  464. */
  465. void uprintlnHex(word i)
  466. {
  467. char buffer[16];
  468. itoah(i, buffer);
  469. uprint(buffer);
  470. uprintc('\n');
  471. }
  472. // sleeps ms using timer1.
  473. // blocking.
  474. // requires int1() to set timer1Value to 1:
  475. /*
  476. timer1Value = 1; // notify ending of timer1
  477. */
  478. void delay(word ms)
  479. {
  480. // clear result
  481. timer1Value = 0;
  482. // set timer
  483. word *p = (word *) TIMER1_VAL;
  484. *p = ms;
  485. // start timer
  486. word *q = (word *) TIMER1_CTRL;
  487. *q = 1;
  488. // wait until timer done
  489. while (timer1Value == 0);
  490. }
  491. // Returns interrupt ID by using the readintid asm instruction
  492. word getIntID()
  493. {
  494. word retval = 0;
  495. asm(
  496. "readintid r2 ;reads interrupt id to r2\n"
  497. "write -4 r14 r2 ;write to stack to return\n"
  498. );
  499. return retval;
  500. }
  501. // Converts char c to uppercase if possible
  502. char toUpper(char c)
  503. {
  504. if (c>96 && c<123)
  505. c = c ^ 0x20;
  506. return c;
  507. }
  508. // Converts string str to uppercase if possible
  509. void strToUpper(char* str)
  510. {
  511. char chr = *str; // first character of str
  512. while (chr != 0) // continue until null value
  513. {
  514. *str = toUpper(chr); // uppercase char
  515. str++; // go to next character address
  516. chr = *str; // get character from address
  517. }
  518. }
  519. /*
  520. For debugging
  521. Prints a hex dump of size 'len' for each word starting from 'addr'
  522. Values are printed over UART
  523. */
  524. void hexdump(char* addr, word len)
  525. {
  526. char buf[16];
  527. word i;
  528. for (i = 0; i < len; i++)
  529. {
  530. // newline every 8 words
  531. if (i != 0 && MATH_modU(i, 8) == 0)
  532. uprintc('\n');
  533. itoah(addr[i], buf);
  534. uprint(buf);
  535. uprintc(' ');
  536. }
  537. }