Skip to content

Commit 4e6bac4

Browse files
authored
Merge pull request #274 from skx/bases
Document octal/octal? And add more conversion routines.
2 parents 34277a0 + 3040553 commit 4e6bac4

2 files changed

Lines changed: 95 additions & 8 deletions

File tree

‎PRIMITIVES.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,12 @@ The implementation of these primitives can be found in the file [stdlib.slisp](s
215215
* Does the given string look like a binary number, with 0b-prefix?
216216
* `binary`
217217
* Parse the given string, with 0b-prefix, as a binary number and return the integer value.
218+
* `dec2binary`
219+
* Convert an integer to a string containing the binary version of that number (e.g. 7 -> 0b111)
220+
* `dec2hex`
221+
* Convert an integer to a string containing the hex version of that number. (e.g. 255 -> 0xFF).
222+
* `dec2octal`
223+
* Convert an integer to a string containing the octal version of that number. (e.g. 255 -> 0o173).
218224
* `dir?`
219225
* Does the given path exist as a directory?
220226
* `even?`
@@ -280,6 +286,10 @@ The implementation of these primitives can be found in the file [stdlib.slisp](s
280286
* Return true if the number is negative.
281287
* `now`
282288
* Get the milliseconds past the epoch.
289+
* `octal?`
290+
* Does the given string look like an octal number, with 0o prefix?
291+
* `octal`
292+
* Parse the given string, with 0o-prefix, as an octal number and return the integer value.
283293
* `odd?`
284294
* Return 1 if the given number is odd, nil otherwise.
285295
* `one?`

‎stdlib.slisp‎

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ Mode is \"r\" for read, \"w\" for write, and \"a\" for append."
488488
((= 0 (strcmp mode "r")) (set! flags 0)) ; O_RDONLY
489489
((= 0 (strcmp mode "w")) (set! flags 577)) ; O_WRONLY|O_CREAT|O_TRUNC
490490
(t (do (println "unknown mode for fopen:" mode ) (exit 1))))
491-
(set! handle (syscall SYS_open str flags 420)) ; 420 == mode, 644 in octal
491+
(set! handle (syscall SYS_open str flags (octal "0o644")))
492492
(if (> handle 0)
493493
handle
494494
nil)))
@@ -544,10 +544,7 @@ It is assumed the filehandle came from fopen, but nil is also accepted."
544544
"Make the given directory.
545545

546546
Note that this does not create parents, use (mkdirs) for that."
547-
(syscall SYS_mkdir
548-
path
549-
493 ; octal 0755 in decimal
550-
))
547+
(syscall SYS_mkdir path (octal "0o755")))
551548

552549
(defun mkdirs (path)
553550
"Make the given directory, creating parent directories as necessary"
@@ -797,27 +794,107 @@ and run BODY for side-effects. Returns nil."
797794

798795

799796
(defun binary (text)
800-
"Parse the given text as a binary number, complet with 0b prefix."
797+
"Parse the given text as a binary number, complete with an 0b prefix.
798+
799+
See-also dec2binary."
801800
(parse-integer text "b" 2))
802801

803802
(defun binary? (text)
804803
(integer-base? text "b" 2))
805804

806805
(defun hex (text)
807-
"Parse the given text as a hex number, complet with 0x prefix."
806+
"Parse the given text as a hex number, complete with an 0x prefix.
807+
808+
See-also dec2hex."
808809
(parse-integer text "x" 16))
809810

810811
(defun hex? (text)
811812
(integer-base? text "x" 16))
812813

813814
(defun octal (text)
814-
"Parse the given text as a binary number, complet with 0o prefix."
815+
"Parse the given text as a binary number, complete with an 0o prefix.
816+
817+
See-also dec2octal"
815818
(parse-integer text "o" 8))
816819

817820
(defun octal? (text)
818821
(integer-base? text "o" 8))
819822

820823

824+
;;; 5.1.1 base conversions from decimal
825+
826+
(defun base-digit (value)
827+
"Return the character representation of a digit value 0-15."
828+
(cond
829+
((= value 0) "0")
830+
((= value 1) "1")
831+
((= value 2) "2")
832+
((= value 3) "3")
833+
((= value 4) "4")
834+
((= value 5) "5")
835+
((= value 6) "6")
836+
((= value 7) "7")
837+
((= value 8) "8")
838+
((= value 9) "9")
839+
((= value 10) "A")
840+
((= value 11) "B")
841+
((= value 12) "C")
842+
((= value 13) "D")
843+
((= value 14) "E")
844+
((= value 15) "F")
845+
(t nil)))
846+
847+
(defun decimal-base (value prefix base)
848+
"Convert a decimal integer to a number in the specified base."
849+
(let ((result "")
850+
(remainder 0)
851+
(digit "")
852+
(negative nil))
853+
854+
;; Remember if our value was negative
855+
(if (< value 0)
856+
(do
857+
(set! negative t)
858+
(set! value (- 0 value))))
859+
860+
;; Zero is a special case because the loop below would not run.
861+
(if (= value 0)
862+
(set! result "0")
863+
864+
(while (> value 0)
865+
(set! remainder (% value base))
866+
(set! digit (base-digit remainder))
867+
(set! result (strcat digit result))
868+
(set! value (/ value base))))
869+
870+
;; Restore sign if we need to.
871+
(if negative (set! result (strcat "-" result)))
872+
873+
;; Minimum width is two digits; mostly for hex digits.
874+
(if (= (strlen result) 1)
875+
(set! result (strcat "0" result)))
876+
877+
(strcat prefix result)))
878+
879+
(defun dec2binary (value)
880+
"Convert a decimal integer to binary, with a 0b prefix.
881+
882+
See also binary, and binary?"
883+
(decimal-base value "0b" 2))
884+
885+
(defun dec2hex (value)
886+
"Convert a decimal integer to hexadecimal, with a 0x prefix.
887+
888+
See also hex, and hex?"
889+
(decimal-base value "0x" 16))
890+
891+
(defun dec2octal (value)
892+
"Convert a decimal integer to octal, with a 0o prefix.
893+
894+
See also octal, and octal?"
895+
(decimal-base value "0o" 8))
896+
897+
821898

822899
;;; 5.2 maths functions
823900

0 commit comments

Comments
 (0)