cbscanf.s 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. |*cbscanf() implementation for TIGCCLIB
  2. |WARNING: This implementation might accept broken format strings (for size
  3. | reasons). For example: "%1h2d" == "%h12d".
  4. |Copyright (C) Kevin Kofler, 2002-2003
  5. /*Prototypes:
  6. typedef CALLBACK short (*__cbscanf_get_Callback_t) (void *param);
  7. typedef CALLBACK void (*__cbscanf_unget_Callback_t) (short c, void *param);
  8. short cbscanf(register __cbscanf_get_Callback_t getfun asm("a0"),
  9. register __cbscanf_unget_Callback_t ungetfun asm("a1"),
  10. register void *param asm("a2"),
  11. register const char *format asm("a3"), ...);
  12. short vcbscanf(register __cbscanf_get_Callback_t getfun asm("a0"),
  13. register __cbscanf_unget_Callback_t ungetfun asm("a1"),
  14. register void *param asm("a2"),
  15. register const char *format asm("a3"),
  16. register va_list arglist asm("a4"));
  17. */
  18. .text
  19. .xdef vcbscanf
  20. vcbscanf:
  21. movem.l %d3-%d7/%a2-%a4/%a6,-(%a7)
  22. bra.s __vcbscanf_entry_point
  23. .xdef cbscanf
  24. cbscanf:
  25. movem.l %d3-%d7/%a2-%a4/%a6,-(%a7)
  26. lea.l 4+9*4(%a7),%a4
  27. __vcbscanf_entry_point:
  28. clr.w %d4 |number of bytes read from input
  29. clr.w %d0 |result (number of tokens read in)
  30. __cbscanf_next:
  31. move.b (%a3)+,%d1 |current format character
  32. beq.s __cbscanf_return
  33. cmp.b #'%',%d1
  34. beq __cbscanf_conversion
  35. cmp.b #32,%d1
  36. beq.s __cbscanf_whitespace
  37. cmp.b #13,%d1
  38. bhi.s 0f
  39. cmp.b #9,%d1
  40. bcc.s __cbscanf_whitespace
  41. 0:
  42. __cbscanf_literal:
  43. |literal character
  44. bsr.s __cbscanf_getc
  45. cmp.w #-1,%d2
  46. beq.s __cbscanf_return
  47. cmp.b %d1,%d2
  48. beq.s __cbscanf_next
  49. __cbscanf_return:
  50. |return EOF if EOF occured with no conversions done
  51. tst.w %d0
  52. bne.s 45f
  53. addq.w #1,%d2
  54. bne.s 45f
  55. moveq.l #-1,%d0
  56. 45:
  57. movem.l (%a7)+,%d3-%d7/%a2-%a4/%a6
  58. rts
  59. __cbscanf_getc:
  60. movem.l %d0-%d1/%a0-%a1,-(%a7)
  61. pea.l (%a2)
  62. jsr (%a0)
  63. addq.l #4,%a7
  64. move.w %d0,%d2
  65. addq.w #1,%d4
  66. movem.l (%a7)+,%d0-%d1/%a0-%a1
  67. rts
  68. __cbscanf_ungetc:
  69. cmp.w #-1,%d2 |don't unget EOF
  70. beq.s 46f
  71. movem.l %d0-%d2/%a0-%a1,-(%a7)
  72. pea.l (%a2)
  73. move.w %d2,-(%a7)
  74. jsr (%a1)
  75. addq.l #6,%a7
  76. movem.l (%a7)+,%d0-%d2/%a0-%a1
  77. 46:
  78. subq.w #1,%d4
  79. rts
  80. __cbscanf_whitespace:
  81. addq.l #1,%a3
  82. move.b (%a3),%d1
  83. cmp.b #32,%d1
  84. beq.s __cbscanf_whitespace
  85. cmp.b #13,%d1
  86. bhi.s 1f
  87. cmp.b #9,%d1
  88. bcc.s __cbscanf_whitespace
  89. 1:
  90. clr.w %d1
  91. __cbscanf_whitespace2:
  92. addq.w #1,%d1 |count whitespace chars
  93. bsr.s __cbscanf_getc
  94. cmp.b #32,%d2
  95. beq.s __cbscanf_whitespace2
  96. cmp.b #13,%d2
  97. bhi.s 2f
  98. cmp.b #9,%d2
  99. bcc.s __cbscanf_whitespace2
  100. 2:
  101. subq.w #1,%d1 |last char is not whitespace
  102. beq.s __cbscanf_return |no whitespace = error
  103. bsr.s __cbscanf_ungetc
  104. bra __cbscanf_next
  105. __cbscanf_conversion_skip_whitespace:
  106. bsr.s __cbscanf_getc
  107. cmp.b #32,%d2
  108. beq.s __cbscanf_conversion_skip_whitespace
  109. cmp.b #13,%d2
  110. bhi.s 12f
  111. cmp.b #9,%d2
  112. bcc.s __cbscanf_conversion_skip_whitespace
  113. 12:
  114. bra.s __cbscanf_ungetc |bsr+rts = bra
  115. __cbscanf_conversion:
  116. moveq.l #0,%d3 |flags
  117. clr.w %d5 |field width
  118. 3:
  119. move.b (%a3)+,%d1 |current format character
  120. cmp.b #'*',%d1
  121. bne.s 4f
  122. bset.l #0,%d3
  123. bra.s 3b
  124. 4:
  125. cmp.b #'h',%d1
  126. bne.s 5f
  127. btst.l #2,%d3
  128. bne __cbscanf_return
  129. bset.l #1,%d3
  130. bra.s 3b
  131. 5:
  132. cmp.b #'l',%d1
  133. bne.s 6f
  134. btst.l #1,%d3
  135. bne __cbscanf_return
  136. bset.l #2,%d3
  137. bra.s 3b
  138. 6:
  139. |read field width
  140. cmp.b #'0',%d1
  141. bcs.s 9f
  142. cmp.b #'9',%d1
  143. bhi.s 9f
  144. subi.b #'0',%d1
  145. ext.w %d1
  146. mulu.w #10,%d5
  147. add.w %d1,%d5
  148. bra.s 3b
  149. 9:
  150. move.w %d5,%d6
  151. cmp.b #'%',%d1
  152. beq __cbscanf_literal
  153. |now, the next char must be a conversion
  154. cmp.b #'i',%d1
  155. bne.s __cbscanf_conversion_not_i
  156. moveq.l #0,%d7
  157. btst.l #0,%d3
  158. bne.s 27f
  159. move.l (%a4)+,%a6
  160. 27:
  161. bsr __cbscanf_conversion_skip_whitespace
  162. __cbscanf_conversion_i_next:
  163. bsr __cbscanf_getc
  164. cmp.b #'-',%d2
  165. beq.s __cbscanf_conversion_i_neg
  166. cmp.b #173,%d2
  167. beq.s __cbscanf_conversion_i_neg
  168. cmp.b #'0',%d2
  169. bne.s __cbscanf_conversion_d_continue_as_u
  170. subq.w #1,%d6
  171. beq __cbscanf_conversion_u_finish
  172. bsr __cbscanf_getc
  173. cmp.b #'X',%d2
  174. beq.s 28f
  175. cmp.b #'x',%d2
  176. bne __cbscanf_conversion_i_continue_as_o
  177. 28:
  178. subq.w #1,%d6
  179. beq __cbscanf_conversion_u_finish
  180. bsr __cbscanf_getc
  181. bra __cbscanf_conversion_i_continue_as_x
  182. __cbscanf_conversion_i_neg:
  183. bchg.l #3,%d3
  184. subq.w #1,%d6
  185. beq.s __cbscanf_conversion_u_finish
  186. bra.s __cbscanf_conversion_i_next
  187. __cbscanf_conversion_not_i:
  188. cmp.b #'d',%d1
  189. bne.s __cbscanf_conversion_not_d
  190. moveq.l #0,%d7
  191. btst.l #0,%d3
  192. bne.s 20f
  193. move.l (%a4)+,%a6
  194. 20:
  195. bsr __cbscanf_conversion_skip_whitespace
  196. __cbscanf_conversion_d_next:
  197. bsr __cbscanf_getc
  198. cmp.b #'-',%d2
  199. beq.s 21f
  200. cmp.b #173,%d2
  201. bne.s __cbscanf_conversion_d_continue_as_u
  202. 21:
  203. bchg.l #3,%d3
  204. subq.w #1,%d6
  205. beq.s __cbscanf_conversion_u_finish
  206. bra.s __cbscanf_conversion_d_next
  207. __cbscanf_conversion_not_d:
  208. cmp.b #'u',%d1
  209. bne.s __cbscanf_conversion_not_u
  210. moveq.l #0,%d7
  211. btst.l #0,%d3
  212. bne.s 17f
  213. move.l (%a4)+,%a6
  214. 17:
  215. bsr __cbscanf_conversion_skip_whitespace
  216. __cbscanf_conversion_u_next:
  217. bsr __cbscanf_getc
  218. __cbscanf_conversion_d_continue_as_u:
  219. cmp.b #'0',%d2
  220. bcs.s __cbscanf_conversion_u_unget
  221. cmp.b #'9',%d2
  222. bhi.s __cbscanf_conversion_u_unget
  223. subi.b #'0',%d2
  224. ext.w %d2
  225. ext.l %d2
  226. add.l %d7,%d7
  227. move.l %d7,-(%a7)
  228. lsl.l #2,%d7
  229. add.l (%a7)+,%d7
  230. add.l %d2,%d7
  231. subq.w #1,%d6
  232. bne.s __cbscanf_conversion_u_next
  233. bra.s __cbscanf_conversion_u_finish
  234. __cbscanf_conversion_u_unget:
  235. bsr __cbscanf_ungetc
  236. __cbscanf_conversion_u_finish:
  237. btst.l #0,%d3
  238. bne __cbscanf_conversion_check
  239. btst.l #3,%d3
  240. beq.s 19f
  241. neg.l %d7
  242. 19:
  243. btst.l #2,%d3
  244. bne.s 18f
  245. move.w %d7,(%a6)
  246. bra __cbscanf_conversion_check
  247. 18:
  248. move.l %d7,(%a6)
  249. bra __cbscanf_conversion_check
  250. __cbscanf_conversion_not_u:
  251. cmp.b #'x',%d1
  252. beq.s 7f
  253. cmp.b #'X',%d1
  254. bne.s __cbscanf_conversion_not_x
  255. 7:
  256. __cbscanf_conversion_hexadecimal:
  257. moveq.l #0,%d7
  258. btst.l #0,%d3
  259. bne.s 22f
  260. move.l (%a4)+,%a6
  261. 22:
  262. bsr __cbscanf_conversion_skip_whitespace
  263. __cbscanf_conversion_x_next:
  264. bsr __cbscanf_getc
  265. __cbscanf_conversion_i_continue_as_x:
  266. cmp.b #'0',%d2
  267. bcs.s __cbscanf_conversion_u_unget
  268. cmp.b #'9',%d2
  269. bhi.s 23f
  270. subi.b #'0',%d2
  271. bra.s 25f
  272. 23:
  273. cmp.b #'A',%d2
  274. bcs.s __cbscanf_conversion_u_unget
  275. cmp.b #'F',%d2
  276. bhi.s 24f
  277. subi.b #'A'-10,%d2
  278. bra.s 25f
  279. 24:
  280. cmp.b #'a',%d2
  281. bcs.s __cbscanf_conversion_u_unget
  282. cmp.b #'f',%d2
  283. bhi.s __cbscanf_conversion_u_unget
  284. subi.b #'a'-10,%d2
  285. 25:
  286. ext.w %d2
  287. ext.l %d2
  288. lsl.l #4,%d7
  289. add.l %d2,%d7
  290. subq.w #1,%d6
  291. bne.s __cbscanf_conversion_x_next
  292. bra __cbscanf_conversion_u_finish
  293. __cbscanf_conversion_not_x:
  294. cmp.b #'p',%d1
  295. bne.s __cbscanf_conversion_not_p
  296. bclr.l #1,%d3
  297. bset.l #2,%d3 |p=lx
  298. bra.s __cbscanf_conversion_hexadecimal
  299. __cbscanf_conversion_not_p:
  300. cmp.b #'o',%d1
  301. bne.s __cbscanf_conversion_not_o
  302. bsr __cbscanf_conversion_skip_whitespace
  303. moveq.l #0,%d7
  304. btst.l #0,%d3
  305. bne.s 26f
  306. move.l (%a4)+,%a6
  307. 26:
  308. bsr __cbscanf_conversion_skip_whitespace
  309. __cbscanf_conversion_o_next:
  310. bsr __cbscanf_getc
  311. __cbscanf_conversion_i_continue_as_o:
  312. cmp.b #'0',%d2
  313. bcs __cbscanf_conversion_u_unget
  314. cmp.b #'7',%d2
  315. bhi __cbscanf_conversion_u_unget
  316. subi.b #'0',%d2
  317. ext.w %d2
  318. ext.l %d2
  319. lsl.l #3,%d7
  320. add.l %d2,%d7
  321. subq.w #1,%d6
  322. bne.s __cbscanf_conversion_o_next
  323. bra __cbscanf_conversion_u_finish
  324. __cbscanf_conversion_not_o:
  325. cmp.b #'f',%d1
  326. beq.s 8f
  327. cmp.b #'e',%d1
  328. beq.s 8f
  329. cmp.b #'g',%d1
  330. beq.s 8f
  331. cmp.b #'E',%d1
  332. bne __cbscanf_conversion_not_f
  333. 8:
  334. bsr __cbscanf_conversion_skip_whitespace
  335. tst.w %d5 |default/maximum is 29 chars (not 100% ANSI compliant, but who cares?)
  336. beq.s 30f
  337. cmp.l #29,%d5
  338. bls.s 31f
  339. 30:
  340. moveq.l #29,%d5
  341. moveq.l #29,%d6
  342. 31:
  343. lea.l -30(%a7),%a7 |buffer
  344. move.l %a7,%a6
  345. __cbscanf_conversion_f_next:
  346. bsr __cbscanf_getc
  347. cmp.w #-1,%d2
  348. beq.s __cbscanf_conversion_f_unget
  349. cmp.b #'.',%d2
  350. beq.s 32f
  351. cmp.b #'0',%d2
  352. bcs.s __cbscanf_conversion_f_unget
  353. cmp.b #'9',%d2
  354. bls.s 32f
  355. cmp.b #149,%d2
  356. beq.s 32f
  357. cmp.b #173,%d2
  358. bne.s __cbscanf_conversion_f_unget
  359. 32:
  360. move.b %d2,(%a6)+
  361. subq.w #1,%d6
  362. bne.s __cbscanf_conversion_f_next
  363. bra.s __cbscanf_conversion_f_add_nul
  364. __cbscanf_conversion_f_unget:
  365. bsr __cbscanf_ungetc
  366. __cbscanf_conversion_f_add_nul:
  367. clr.b (%a6)+
  368. movem.l %d0-%d2/%a0-%a1,-(%a7)
  369. pea.l 5*4(%a7)
  370. jsr atof
  371. addq.l #4,%a7
  372. cmp.l #0x7fffaa00,%d0
  373. bne.s 33f
  374. tst.l %d1
  375. bne.s 33f
  376. tst.w %d2
  377. beq.s __cbscanf_conversion_f_nan
  378. 33:
  379. btst.l #0,%d3
  380. bne.s 34f
  381. move.l (%a4)+,%a6
  382. move.l %d0,(%a6)+
  383. move.l %d1,(%a6)+
  384. move.w %d2,(%a6)
  385. 34:
  386. movem.l (%a7)+,%d0-%d2/%a0-%a1
  387. lea.l 30(%a7),%a7
  388. bra __cbscanf_conversion_check
  389. __cbscanf_conversion_f_nan:
  390. movem.l (%a7)+,%d0-%d2/%a0-%a1
  391. lea.l 30(%a7),%a7
  392. bra __cbscanf_return
  393. __cbscanf_conversion_not_f:
  394. cmp.b #'s',%d1
  395. bne.s __cbscanf_conversion_not_s
  396. btst.l #0,%d3
  397. bne.s 10f
  398. move.l (%a4)+,%a6
  399. 10:
  400. bsr __cbscanf_conversion_skip_whitespace
  401. __cbscanf_conversion_s_next:
  402. bsr __cbscanf_getc
  403. cmp.w #-1,%d2
  404. beq.s __cbscanf_conversion_s_unget
  405. cmp.b #32,%d2
  406. beq.s __cbscanf_conversion_s_unget
  407. cmp.b #13,%d2
  408. bhi.s 13f
  409. cmp.b #9,%d2
  410. bcc.s __cbscanf_conversion_s_unget
  411. 13:
  412. btst.l #0,%d3
  413. bne.s 14f
  414. move.b %d2,(%a6)+
  415. 14:
  416. subq.w #1,%d6
  417. bne.s __cbscanf_conversion_s_next
  418. bra.s __cbscanf_conversion_s_add_nul
  419. __cbscanf_conversion_s_unget:
  420. bsr __cbscanf_ungetc
  421. __cbscanf_conversion_s_add_nul:
  422. btst.l #0,%d3
  423. bne __cbscanf_conversion_check
  424. clr.b (%a6)+
  425. bra __cbscanf_conversion_check
  426. __cbscanf_conversion_not_s:
  427. cmp.b #'[',%d1
  428. bne __cbscanf_conversion_not_set
  429. tst.b (%a3)
  430. beq __cbscanf_return
  431. cmp.b #'^',(%a3)
  432. bne.s 38f
  433. addq.l #1,%a3
  434. tst.b (%a3)
  435. beq __cbscanf_return
  436. bset.l #3,%d3
  437. 38:
  438. btst.l #0,%d3
  439. bne.s 35f
  440. move.l (%a4)+,%a6
  441. 35:
  442. __cbscanf_conversion_set_next:
  443. bsr __cbscanf_getc
  444. cmp.w #-1,%d2
  445. beq.s __cbscanf_conversion_set_unget
  446. |check if in set
  447. pea.l (%a3)
  448. tst.b (%a3)
  449. beq.s 39f
  450. cmp.b (%a3)+,%d2
  451. beq.s 36f
  452. 43:
  453. move.b (%a3)+,%d1
  454. beq.s 39f
  455. cmp.b #']',%d1
  456. beq.s 39f
  457. cmp.b #'-',%d1
  458. bne.s 40f
  459. move.b (%a3)+,%d1
  460. beq.s 39f
  461. cmp.b #']',%d1
  462. beq.s 42f
  463. cmp.b %d1,%d2
  464. bhi.s 43b
  465. cmp.b -3(%a3),%d2
  466. bcs.s 43b
  467. bra.s 36f
  468. 40:
  469. cmp.b %d1,%d2
  470. beq.s 36f
  471. bra.s 43b
  472. 42:
  473. cmp.b #'-',%d2
  474. beq.s 36f
  475. 39: |not in set
  476. movea.l (%a7)+,%a3
  477. btst.l #3,%d3
  478. bne.s 41f
  479. bra.s __cbscanf_conversion_set_unget
  480. 36: |in set
  481. movea.l (%a7)+,%a3
  482. btst.l #3,%d3
  483. bne.s __cbscanf_conversion_set_unget
  484. 41:
  485. btst.l #0,%d3
  486. bne.s 37f
  487. move.b %d2,(%a6)+
  488. 37:
  489. subq.w #1,%d6
  490. bne.s __cbscanf_conversion_set_next
  491. bra.s __cbscanf_conversion_set_add_nul
  492. __cbscanf_conversion_set_unget:
  493. bsr __cbscanf_ungetc
  494. __cbscanf_conversion_set_add_nul:
  495. addq.l #1,%a3
  496. 47:
  497. tst.b (%a3)
  498. beq __cbscanf_return
  499. cmp.b #']',(%a3)+
  500. bne.s 47b
  501. bra __cbscanf_conversion_s_add_nul
  502. __cbscanf_conversion_not_set:
  503. cmp.b #'c',%d1
  504. bne.s __cbscanf_conversion_not_c
  505. btst.l #0,%d3
  506. bne.s 11f
  507. move.l (%a4)+,%a6
  508. 11:
  509. tst.w %d5 |default is 1 char
  510. bne.s 15f
  511. addq.w #1,%d5
  512. addq.w #1,%d6
  513. 15:
  514. __cbscanf_conversion_c_next:
  515. bsr __cbscanf_getc
  516. cmp.w #-1,%d2
  517. beq.s __cbscanf_conversion_check
  518. btst.l #0,%d3
  519. bne.s 16f
  520. move.b %d2,(%a6)+
  521. 16:
  522. subq.w #1,%d6
  523. bne.s __cbscanf_conversion_c_next
  524. bra.s __cbscanf_conversion_check
  525. __cbscanf_conversion_not_c:
  526. cmp.b #'n',%d1
  527. bne.s __cbscanf_conversion_not_n
  528. btst.l #0,%d3
  529. bne.s __cbscanf_conversion_no_check
  530. move.l (%a4)+,%a6
  531. move.w %d4,(%a6)
  532. bra.s __cbscanf_conversion_no_check
  533. __cbscanf_conversion_not_n:
  534. __cbscanf_conversion_check:
  535. cmp.w %d5,%d6
  536. beq __cbscanf_return
  537. __cbscanf_conversion_no_check:
  538. btst.l #0,%d3
  539. bne.s 44f
  540. addq.w #1,%d0 |count successful conversion
  541. 44:
  542. bra __cbscanf_next