?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #ifndef included_formatstr
  2. #define included_formatstr
  3.  
  4. ; This routine for taking a base-10 exponent and a string of digits and (without
  5. ; a decimal) and inserting a decimal, any leading zeros, stripping trailing
  6. ; zeros, and appending an exponent if needed.
  7.  
  8.  
  9.  
  10. ; Define the absolute maximum number of digits in the result string.
  11. ; If FORMAT_LEN is bigger than this value, then it will be reduced.
  12. #ifndef MAX_FORMAT_LEN
  13. #define MAX_FORMAT_LEN 19
  14. #endif
  15.  
  16. ; Define this to use an external reference to get the number of digits used
  17. ;#define EXTERNAL_FORMAT_LEN <pointer>
  18. ;
  19. ; For example, TI-OS has a byte at fmtDigits:
  20. ;#define EXTERNAL_FORMAT_LEN fmtDigits
  21.  
  22. ; This is the max number of digits in the output.
  23. ; If EXTERNAL_FORMAT_LEN is used and it is 0, then this will be used.
  24. #ifndef FORMAT_LEN
  25. #define FORMAT_LEN 18
  26. #endif
  27.  
  28. ; Define this to use an external reference for the max exponent before switching
  29. ; to enginieering mode.
  30. ;#define EXTERNAL_FORMAT_MAX_ENGINEERING  <pointer>
  31.  
  32. ; Define the max exponent to use before switching to engineering format
  33. ; If none is defined, this uses FORMAT_LEN.
  34. ; If EXTERNAL_FORMAT_MAX_ENGINEERING is used and is 0 or larger than FORMAT_LEN,
  35. ; then this will be used.
  36. ;#define FORMAT_MAX_ENGINEERING
  37.  
  38.  
  39. ; Define this to use an external reference for the min exponent before switching
  40. ; to enginieering mode.
  41. ;#define EXTERNAL_FORMAT_MIN_ENGINEERING  <pointer>
  42.  
  43. ; Define the largest negative exponent to use engineering format
  44. ; If EXTERNAL_FORMAT_MIN_ENGINEERING is used and is 0 or larger than FORMAT_LEN,
  45. ; then this will be used.
  46. #ifndef FORMAT_MIN_ENGINEERING
  47. #define FORMAT_MIN_ENGINEERING  -5  ; causes exponent of -5 to be enginierring
  48. #endif
  49.  
  50. ; For formatting, we need to define these three characters
  51. ; "Enginieering e" for values like "1.23456e10"
  52. #ifndef TOK_ENG
  53. #define TOK_ENG 'e'
  54. #endif
  55.  
  56. ; Negative sign
  57. #ifndef TOK_NEG
  58. #define TOK_NEG '-'
  59. #endif
  60.  
  61. ; Decimal point
  62. #ifndef TOK_DECIMAL
  63. #define TOK_DECIMAL '.'
  64. #endif
  65.  
  66. formatstr:
  67. ;Inputs:
  68. ;   HL points to the null-terminated string of digits
  69. ;   DE is the signed exponent.
  70. ;Outputs:
  71. ;   The string has leading and trailing zeros stripped, a decimal is placed
  72. ;   (if needed), and an exponent field is appended (if needed).
  73. ;Destroys:
  74. ;   HL, DE, BC, AF
  75. ;Notes:
  76. ;   This routine operates in-place. It assumes that there is enough space
  77. ;   allocated for the string. At most MAX_FORMAT_LEN+10 bytes is needed,
  78. ;   assuming the exponent can be up to 5 digits long.
  79. ;
  80. ; Skip over the negative sign, if any
  81.   ld a,(hl)
  82.   cp TOK_NEG
  83.   jr nz,$+3
  84.   inc hl
  85.   push de ; save the exponent
  86.   push hl
  87.  
  88. ;Strip leading zeros
  89.   ld d,h
  90.   ld e,l
  91.   ld a,'0'
  92.   cp (hl)                           ;These two lines can be commented-out to save three
  93.   jr nz,formatstr_no_leading_zeros  ;bytes at the expense of redundant processing.
  94. formatstr_strip_leading_zeros:
  95.   cpi
  96.   jr z,formatstr_strip_leading_zeros
  97.   dec hl
  98.  
  99. ; HL points to the first non-'0' digit
  100. ; DE points to the first digit
  101. ; Copy bytes from HL to DE until 0x00 is reached at HL or FORMAT_LEN digits are copied
  102. #ifdef EXTERNAL_FORMAT_LEN
  103.   ld a,(EXTERNAL_FORMAT_LEN)
  104.   or a
  105.   jr nz,$+4
  106. #endif
  107.   ld a,FORMAT_LEN
  108. #ifdef EXTERNAL_FORMAT_LEN
  109.   cp MAX_FORMAT_LEN
  110.   jr c,$+4
  111.   ld a,MAX_FORMAT_LEN
  112. #endif
  113.   ld c,a
  114.  
  115.   xor a
  116.   ld b,a
  117. formatstr_copy_digits:
  118.   cp (hl)
  119.   ldi
  120.   jp po,+_
  121.   jr nz,formatstr_copy_digits
  122. _:
  123.   dec hl
  124.   ld (hl),0
  125.  
  126. formatstr_no_leading_zeros:
  127. ; there are no more leading zeros
  128. ; Truncate the number of digits if necessary based on FORMAT_LEN
  129.  
  130.   call formatstr_remove_trailing_zeros
  131.   pop hl  ; points to the first digit
  132.   pop de  ; exponent
  133.  
  134. ; Make sure the first digit isn't 0x00
  135.   ld a,(hl)
  136.   or a
  137.   jr nz,+_
  138.   ld (hl),'0'
  139.   inc hl
  140.   ld (hl),a
  141.   ret
  142. _:
  143.  
  144.   call formatstr_check_eng
  145.   jr c,formatstr_eng
  146.   inc de
  147.   bit 7,d
  148.   jr nz,formatstr_neg_exp
  149.   ; Otherwise, we need to insert a decimal after DE digits (D is 0, though)
  150.   ld b,d
  151.   ld c,e
  152.   xor a
  153.   cp e
  154.   jr z,formatstr_insert_decimal
  155.   cpir
  156.   ; If we have reached a 0x00, we may need to pad with zeros
  157.   jr z,formatstr_pad_right
  158.   ; otherwise, let's insert the decimal
  159. formatstr_insert_decimal:
  160.   ld a,(hl)
  161.   or a
  162.   ret z
  163.   ld a,TOK_DECIMAL
  164. formatstr_insert_decimal_loop:
  165.   ld c,(hl) ; back up digit
  166.   ld (hl),a
  167.   inc hl
  168.   ld a,c
  169.   or a
  170.   jr nz,formatstr_insert_decimal_loop
  171.   ld (hl),a
  172.   ret
  173.  
  174. formatstr_neg_exp:
  175. ; Need to pad -DE 0s to the left
  176.   xor a
  177.   ld c,a
  178.   cpir
  179.   ld b,a
  180.   sub c
  181.   ld c,a
  182.   ;HL-1 is where to start reading bytes
  183.   ;HL-DE is where to start writing bytes
  184.   xor a
  185.   ld d,a
  186.   sub e     ; A is the number of 0s to write
  187.   ld e,a
  188.   ex de,hl
  189.   add hl,de
  190.   ex de,hl
  191.   dec hl
  192.   ; DE points to where to write the last byte
  193.   ; HL points to where to read it from
  194.   ; BC is the number of bytes to copy (it will be non-zero)
  195.   ; A is the number of zeros to insert
  196.   lddr
  197.   ;now from DE backwards, write A '0's
  198.   ex de,hl
  199.   ld b,a
  200.   ld (hl),'0'
  201.   dec hl
  202.   djnz $-3
  203.   ; finally, write a '.'
  204.   ld (hl),TOK_DECIMAL
  205.   ret
  206.  
  207. formatstr_pad_right:
  208.   ; append BC+1 0s
  209.   dec hl
  210.   inc bc
  211. _:
  212.   ld (hl),'0'
  213.   cpi
  214.   jp pe,-_
  215.   ld (hl),0
  216.   ret
  217.  
  218. formatstr_eng:
  219. ; need to insert a decimal after the first digit
  220.   inc hl
  221.   call formatstr_insert_decimal
  222.   ld (hl),TOK_ENG
  223.   inc hl
  224.   bit 7,d
  225.   jr z,formatstr_exp_to_str
  226.   ld (hl),TOK_NEG
  227.   inc hl
  228.   xor a
  229.   sub e
  230.   ld e,a
  231.   sbc a,a
  232.   sub d
  233.   ld d,a
  234. formatstr_exp_to_str:
  235.   ex de,hl
  236.   ld a,'0'-1
  237.   ld bc,-10000
  238. _:
  239.   inc a
  240.   add hl,bc
  241.   jr c,-_
  242.   cp '0'
  243.   jr z,$+4
  244.   ld (de),a
  245.   inc de
  246.  
  247.   ld a,'9'+1
  248.   ld bc,1000
  249. _:
  250.   dec a
  251.   add hl,bc
  252.   jr nc,-_
  253.   cp '0'
  254.   jr z,$+4
  255.   ld (de),a
  256.   inc de
  257.  
  258.   ld a,'0'-1
  259.   ld bc,-100
  260. _:
  261.   inc a
  262.   add hl,bc
  263.   jr c,-_
  264.   cp '0'
  265.   jr z,$+4
  266.   ld (de),a
  267.   inc de
  268.  
  269.   ld b,10
  270.   ld a,l
  271. _:
  272.   add a,10
  273.   dec b
  274.   jr nc,-_
  275.   ex de,hl
  276.   jr z,formatstr_eng_last_digit
  277.   set 4,b
  278.   set 5,b
  279.   ld (hl),b
  280.   inc hl
  281. formatstr_eng_last_digit:
  282.   add a,'0'
  283.   ld (hl),a
  284.   inc hl
  285.   ld (hl),0
  286.   ret
  287.  
  288. formatstr_remove_trailing_zeros:
  289.   ; first, seek the end of the string
  290.   xor a
  291.   ld c,a
  292.   ld b,a
  293.   cpir
  294.   dec hl
  295.   ld a,'0'
  296. _:
  297.   dec hl
  298.   cp (hl)
  299.   jr z,-_
  300.   inc hl
  301.   ld (hl),0
  302.   ret
  303.  
  304. formatstr_check_eng:
  305. ; Return carry flag set if engineering format is required, else nc
  306. ;
  307. ; If the exponent is greater than FORMAT_MAX_ENGINEERING, then use enginieering
  308. ; notation. Note that FORMAT_MAX_ENGINEERING < 256, so check that D = -1 or 0
  309.   ld a,d
  310.   inc a
  311.   jr z,formatstr_check_eng_neg
  312.   add a,254
  313.   ret c   ;the exponent is too big in magnitude, engineering format is required.
  314. ; The exponent is positive and less than 256
  315.  
  316. #ifdef EXTERNAL_FORMAT_MAX_ENGINEERING
  317.   ld a,(EXTERNAL_FORMAT_MAX_ENGINEERING)
  318.   or a
  319.   jr nz,+_
  320. #ifdef FORMAT_MAX_ENGINEERING
  321.   ld a,FORMAT_MAX_ENGINEERING
  322. #else
  323. #ifdef EXTERNAL_FORMAT_LEN
  324.   ld a,(EXTERNAL_FORMAT_LEN)
  325.   or a
  326.   jr nz,$+4
  327. #endif
  328.   ld a,FORMAT_LEN
  329. #endif
  330.  
  331. _:
  332. #else
  333. #ifdef FORMAT_MAX_ENGINEERING
  334.   ld a,FORMAT_MAX_ENGINEERING
  335. #else
  336. #ifdef EXTERNAL_FORMAT_LEN
  337.   ld a,(EXTERNAL_FORMAT_LEN)
  338.   or a
  339.   jr nz,$+4
  340. #endif
  341.   ld a,FORMAT_LEN
  342. #endif
  343. #endif
  344.   cp e
  345.   ret
  346.  
  347. formatstr_check_eng_neg:
  348. ;The exponent is negative and greater than or equal to -256
  349.  
  350. #ifdef EXTERNAL_FORMAT_MIN_ENGINEERING
  351.   ld a,(EXTERNAL_FORMAT_MIN_ENGINEERING)
  352.   or a
  353.   jr nz,$+3
  354.   ld a,FORMAT_MIN_ENGINEERING
  355. #else
  356.   ld a,FORMAT_MIN_ENGINEERING
  357. #endif
  358.   cp e
  359.   ccf
  360.   ret
  361. #endif
  362.