utils.g 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. # This file is part of asmc, a bootstrapping OS with minimal seed
  2. # Copyright (C) 2018-2019 Giovanni Mascellani <gio@debian.org>
  3. # https://gitlab.com/giomasce/asmc
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. # You should have received a copy of the GNU General Public License
  13. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. $_resolve_symbol_ext
  15. fun resolve_symbol 3 {
  16. $loc
  17. $nameptr
  18. $offptr
  19. @loc 2 param = ;
  20. @nameptr 1 param = ;
  21. @offptr 0 param = ;
  22. $res
  23. @res 0 = ;
  24. if _resolve_symbol_ext {
  25. @res loc nameptr offptr _resolve_symbol_ext \3 = ;
  26. }
  27. if res {
  28. ret ;
  29. }
  30. $i
  31. @i 0 = ;
  32. offptr 0 = ;
  33. nameptr "<unknown>" = ;
  34. while i __symbol_num < {
  35. $this_loc
  36. @this_loc __symbol_locs i 4 * + ** = ;
  37. $this_name
  38. @this_name __symbol_names i __max_symbol_name_len * + = ;
  39. if this_loc loc <= this_loc offptr ** >= && {
  40. offptr this_loc = ;
  41. nameptr this_name = ;
  42. }
  43. @i i 1 + = ;
  44. }
  45. offptr loc offptr ** - = ;
  46. }
  47. fun dump_frame 1 {
  48. $frame_ptr
  49. @frame_ptr 0 param = ;
  50. if frame_ptr 0 == {
  51. ret ;
  52. }
  53. $prev_frame_ptr
  54. $ret_addr
  55. @prev_frame_ptr frame_ptr ** = ;
  56. @ret_addr frame_ptr 4 + ** = ;
  57. $name
  58. $off
  59. ret_addr @name @off resolve_symbol ;
  60. "Frame pointer: " log ;
  61. frame_ptr itoa log ;
  62. "; previous frame pointer: " log ;
  63. prev_frame_ptr itoa log ;
  64. "; return address: " log ;
  65. ret_addr itoa log ;
  66. " (" log ;
  67. name log ;
  68. "+" log ;
  69. off itoa log ;
  70. ")\n" log ;
  71. prev_frame_ptr dump_frame ;
  72. }
  73. fun dump_stacktrace 0 {
  74. $frame_ptr
  75. @frame_ptr __frame_ptr = ;
  76. frame_ptr dump_frame ;
  77. }
  78. fun assert 1 {
  79. if 0 param ! {
  80. "\nASSERTION FAILED\n" log ;
  81. dump_stacktrace ;
  82. platform_panic ;
  83. }
  84. }
  85. fun assert_msg 2 {
  86. if 1 param ! {
  87. "\nASSERTION FAILED\n" log ;
  88. 0 param log ;
  89. "\n" log ;
  90. dump_stacktrace ;
  91. platform_panic ;
  92. }
  93. }
  94. fun assert_msg_str 3 {
  95. if 2 param ! {
  96. "\nASSERTION FAILED\n" log ;
  97. 1 param log ;
  98. "\n" log ;
  99. 0 param log ;
  100. "\n" log ;
  101. dump_stacktrace ;
  102. platform_panic ;
  103. }
  104. }
  105. fun assert_msg_int_int 4 {
  106. if 3 param ! {
  107. "\nASSERTION FAILED\n" log ;
  108. 2 param log ;
  109. "\n" log ;
  110. 1 param itoa log ;
  111. " " log ;
  112. 0 param itoa log ;
  113. "\n" log ;
  114. dump_stacktrace ;
  115. platform_panic ;
  116. }
  117. }
  118. fun min 2 {
  119. $x
  120. $y
  121. @x 0 param = ;
  122. @y 1 param = ;
  123. if x y < {
  124. x ret ;
  125. } else {
  126. y ret ;
  127. }
  128. }
  129. fun max 2 {
  130. $x
  131. $y
  132. @x 0 param = ;
  133. @y 1 param = ;
  134. if x y > {
  135. x ret ;
  136. } else {
  137. y ret ;
  138. }
  139. }
  140. fun take 2 {
  141. # The two parameters are actually perfectly interchangable...
  142. $ptr
  143. $off
  144. @ptr 1 param = ;
  145. @off 0 param = ;
  146. ptr off + ** ret ;
  147. }
  148. fun takec 2 {
  149. # The two parameters are actually perfectly interchangable...
  150. $ptr
  151. $off
  152. @ptr 1 param = ;
  153. @off 0 param = ;
  154. ptr off + **c ret ;
  155. }
  156. fun take_addr 2 {
  157. # The two parameters are actually perfectly interchangable...
  158. $ptr
  159. $off
  160. @ptr 1 param = ;
  161. @off 0 param = ;
  162. ptr off + ret ;
  163. }
  164. fun strcmp_case 2 {
  165. $s1
  166. $s2
  167. @s1 1 param = ;
  168. @s2 0 param = ;
  169. $diff
  170. @diff 'A' 'a' - = ;
  171. while 1 {
  172. $c1
  173. $c2
  174. @c1 s1 **c = ;
  175. @c2 s2 **c = ;
  176. if 'A' c1 <= c1 'Z' <= && {
  177. @c1 c1 diff - = ;
  178. }
  179. if 'A' c2 <= c2 'Z' <= && {
  180. @c2 c2 diff - = ;
  181. }
  182. if c1 c2 < {
  183. 0xffffffff ret ;
  184. }
  185. if c1 c2 > {
  186. 1 ret ;
  187. }
  188. if c1 0 == {
  189. 0 ret ;
  190. }
  191. @s1 s1 1 + = ;
  192. @s2 s2 1 + = ;
  193. }
  194. }
  195. fun isspace 1 {
  196. $c
  197. @c 0 param = ;
  198. if c '\n' == { 1 ret ; }
  199. if c '\r' == { 1 ret ; }
  200. if c '\f' == { 1 ret ; }
  201. if c '\v' == { 1 ret ; }
  202. if c '\t' == { 1 ret ; }
  203. if c ' ' == { 1 ret ; }
  204. 0 ret ;
  205. }
  206. fun strlen 1 {
  207. $ptr
  208. @ptr 0 param = ;
  209. $len
  210. @len 0 = ;
  211. while ptr **c 0 != {
  212. @len len 1 + = ;
  213. @ptr ptr 1 + = ;
  214. }
  215. len ret ;
  216. }
  217. fun strcmp 2 {
  218. $a
  219. $b
  220. @a 1 param = ;
  221. @b 0 param = ;
  222. while a **c b **c == {
  223. if a **c 0 == {
  224. 0 ret ;
  225. }
  226. @a a 1 + = ;
  227. @b b 1 + = ;
  228. }
  229. if a **c b **c < {
  230. 1 ret ;
  231. } else {
  232. 0 1 - ret ;
  233. }
  234. }
  235. fun strcpy 2 {
  236. $src
  237. $dest
  238. @src 1 param = ;
  239. @dest 0 param = ;
  240. while src **c 0 != {
  241. dest src **c =c ;
  242. @src src 1 + = ;
  243. @dest dest 1 + = ;
  244. }
  245. dest 0 =c ;
  246. }
  247. fun memcpy 3 {
  248. $n
  249. $src
  250. $dest
  251. @n 2 param = ;
  252. @src 1 param = ;
  253. @dest 0 param = ;
  254. while n 0 > {
  255. dest src **c =c ;
  256. @src src 1 + = ;
  257. @dest dest 1 + = ;
  258. @n n 1 - = ;
  259. }
  260. }
  261. fun strtol 3 {
  262. $ptr
  263. $endptr
  264. $base
  265. @ptr 2 param = ;
  266. @endptr 1 param = ;
  267. @base 0 param = ;
  268. $positive
  269. @positive 1 = ;
  270. $white
  271. @white 1 = ;
  272. $sign_found
  273. @sign_found 0 = ;
  274. $val
  275. @val 0 = ;
  276. while 1 {
  277. $c
  278. @c ptr **c = ;
  279. if c 0 == {
  280. if endptr 0 != {
  281. endptr ptr = ;
  282. }
  283. val positive * ret ;
  284. }
  285. base 0 >= base 1 != && base 36 <= && "strtol: wrong base" assert_msg ;
  286. if c isspace {
  287. white "strtol: wrong whitespace" assert_msg ;
  288. } else {
  289. @white 0 = ;
  290. if c '+' == {
  291. sign_found ! "strtol: more than one sign found" assert_msg ;
  292. @sign_found 1 = ;
  293. } else {
  294. if c '-' == {
  295. sign_found ! "strtol: more than one sign found" assert_msg ;
  296. @sign_found 1 = ;
  297. @positive 0 1 - = ;
  298. } else {
  299. @sign_found 1 = ;
  300. if base 0 == {
  301. if c '0' == {
  302. @base 8 = ;
  303. @ptr ptr 1 + = ;
  304. @c ptr **c = ;
  305. if c 'x' == c 'X' == || {
  306. @base 16 = ;
  307. @ptr ptr 1 + = ;
  308. @c ptr **c = ;
  309. }
  310. } else {
  311. @base 10 = ;
  312. }
  313. }
  314. if '0' c <= c '9' <= && {
  315. @c c '0' - = ;
  316. } else {
  317. if 'a' c <= c 'z' <= && {
  318. @c c 'a' - 10 + = ;
  319. } else {
  320. if 'A' c <= c 'Z' <= && {
  321. @c c 'A' - 10 + = ;
  322. } else {
  323. @c 0x100 = ;
  324. }
  325. }
  326. }
  327. if c base >= {
  328. if endptr 0 != {
  329. endptr ptr = ;
  330. }
  331. val positive * ret ;
  332. }
  333. @val val base * c + = ;
  334. }
  335. }
  336. }
  337. @ptr ptr 1 + = ;
  338. }
  339. }
  340. fun atoi 1 {
  341. $ptr
  342. @ptr 0 param = ;
  343. ptr 0 != "atoi: invalid null pointer" assert_msg ;
  344. ptr **c 0 != "atoi: invalid empty string" assert_msg ;
  345. $end
  346. $res
  347. @res ptr @end 0 strtol = ;
  348. # "atoi with input " log ;
  349. # ptr log ;
  350. # "\n" log ;
  351. end **c 0 == "atoi: invalid number" assert_msg ;
  352. res ret ;
  353. }
  354. fun atoi_c 1 {
  355. $ptr
  356. @ptr 0 param = ;
  357. ptr 0 != "atoi: invalid null pointer" assert_msg ;
  358. ptr **c 0 != "atoi: invalid empty string" assert_msg ;
  359. $end
  360. $res
  361. @res ptr @end 0 strtol = ;
  362. # "atoi with input " log ;
  363. # ptr log ;
  364. # "\n" log ;
  365. # Ignore L or LL suffixes
  366. if end **c 'L' == {
  367. @end end 1 + = ;
  368. }
  369. if end **c 'L' == {
  370. @end end 1 + = ;
  371. }
  372. end **c 0 == "atoi: invalid number" assert_msg ;
  373. res ret ;
  374. }
  375. fun memset 3 {
  376. $s
  377. $c
  378. $n
  379. @s 2 param = ;
  380. @c 1 param = ;
  381. @n 0 param = ;
  382. $i
  383. @i 0 = ;
  384. while i n < {
  385. s i + c =c ;
  386. @i i 1 + = ;
  387. }
  388. }
  389. fun memcheck 3 {
  390. $s
  391. $c
  392. $n
  393. @s 2 param = ;
  394. @c 1 param = ;
  395. @n 0 param = ;
  396. $i
  397. @i 0 = ;
  398. while i n < {
  399. if s i + **c c != {
  400. 0 ret ;
  401. }
  402. @i i 1 + = ;
  403. }
  404. 1 ret ;
  405. }
  406. fun dump_nibble 1 {
  407. $x
  408. @x 0 param = ;
  409. @x x 0xf & = ;
  410. if x 0 == { '0' write ; }
  411. if x 1 == { '1' write ; }
  412. if x 2 == { '2' write ; }
  413. if x 3 == { '3' write ; }
  414. if x 4 == { '4' write ; }
  415. if x 5 == { '5' write ; }
  416. if x 6 == { '6' write ; }
  417. if x 7 == { '7' write ; }
  418. if x 8 == { '8' write ; }
  419. if x 9 == { '9' write ; }
  420. if x 10 == { 'a' write ; }
  421. if x 11 == { 'b' write ; }
  422. if x 12 == { 'c' write ; }
  423. if x 13 == { 'd' write ; }
  424. if x 14 == { 'e' write ; }
  425. if x 15 == { 'f' write ; }
  426. }
  427. fun dump_byte 1 {
  428. $x
  429. @x 0 param = ;
  430. x 4 >> dump_nibble ;
  431. x dump_nibble ;
  432. ' ' write ;
  433. }
  434. fun dump_mem 2 {
  435. $ptr
  436. $size
  437. @ptr 1 param = ;
  438. @size 0 param = ;
  439. @size size ptr + = ;
  440. while ptr size < {
  441. ptr **c dump_byte ;
  442. @ptr ptr 1 + = ;
  443. }
  444. }
  445. fun get_char_type 1 {
  446. $x
  447. @x 0 param = ;
  448. if x '\n' == { 1 ret ; }
  449. if x '\t' == x ' ' == || x '\f' == || { 2 ret ; }
  450. if x '0' >= x '9' <= && x 'a' >= x 'z' <= && || x 'A' >= x 'Z' <= && || x '_' == || { 3 ret ; }
  451. 4 ret ;
  452. }