diff --git a/PRIMITIVES.md b/PRIMITIVES.md index 06c18b2..fece281 100644 --- a/PRIMITIVES.md +++ b/PRIMITIVES.md @@ -118,11 +118,6 @@ added to them too. * Terminate execution. * `explode` * Convert the supplied string to a list of characters. - * `fclose` - * Close the given file-handle, and always return nil. - * To simplify usage `fclose` will accept a nil-filehandle. - * `fopen` - * Open the given filename, for read/write, and return a handle. * `fread` * Read ALL available data from the given handle. * To simplify usage `fread` will accept a nil-filehandle, and return nil. @@ -242,6 +237,11 @@ The implementation of these primitives can be found in the file [stdlib.slisp](s * Return the offset of matching items inside the given list. * `flatten` * Flatten the given list of lists into a single list +* `fclose` + * Close the given file-handle, and always return nil. + * To simplify usage `fclose` will accept a nil-filehandle. +* `fopen` + * Open the given filename, for read/write, and return a handle. * `getc` * Read a single character from STDIN, return NIL on failure. * `getenv` diff --git a/compiler/template.tmpl b/compiler/template.tmpl index 9ca66ed..7c5cb8b 100644 --- a/compiler/template.tmpl +++ b/compiler/template.tmpl @@ -1578,84 +1578,6 @@ FUNC fn_sys_explode -;; Close a file handle -;; -;; As a special case closing a nil-filehandle is valid. -;; -FUNC fn_sys_fclose - mov rbx, rdi ; type-check arg1 (path) - GET_TAG_BITS rbx - cmp rbx, TAG_ID_NIL - je .fclose_return_nil - cmp rbx, TAG_ID_INTEGER - jne type_error - - UNTAG_REG rdi - mov rax, SYS_close - syscall - xor rax, rax ; return nil -.fclose_return_nil: - STORE_NIL_REG rax - ret - - - - -;; Open a file handle, modes are "r", "w", or "a" -FUNC fn_sys_fopen - mov rbx, rdi ; type-check arg1 (path) - GET_TAG_BITS rbx - cmp rbx, TAG_ID_STRING - jne type_error - - mov rbx, rsi ; type-check arg2 (mode) - GET_TAG_BITS rbx - cmp rbx, TAG_ID_STRING - jne type_error - - UNTAG_REG rdi - UNTAG_REG rsi - - mov al, [rsi] ; We only look at the first character.. - cmp al, 'a' - je .fopen_append - cmp al, 'r' - je .fopen_read - cmp al, 'w' - je .fopen_write - - ; fall through to bad mode - STORE_NIL_REG rax - ret - -.fopen_append: - mov rax, SYS_open - mov rsi, 1089 ; O_WRONLY|O_CREAT|O_APPEND - mov rdx, 0o644 - syscall - jmp .fopen_done -.fopen_read: - mov rax, SYS_open - mov rsi, 0 ; O_RDONLY - xor rdx, rdx - syscall - jmp .fopen_done -.fopen_write: - mov rax, SYS_open - mov rsi, 577 ; O_WRONLY|O_CREAT|O_TRUNC - mov rdx, 0o644 - syscall -.fopen_done: - test rax, rax - js .fopen_syscall_fail - TAG_INTEGER_REG rax - ret -.fopen_syscall_fail: - STORE_NIL_REG rax - ret - - - ;; Read ALL data from the given file handle. ;; ;; As a special case reading from a nil-filehandle diff --git a/inception.lisp b/inception.lisp index a50ea81..2ee104f 100644 --- a/inception.lisp +++ b/inception.lisp @@ -309,8 +309,6 @@ (register-builtin "sys_environment" (lambda (args) (sys_environment))) (register-builtin "sys_exit" (lambda (args) (sys_exit (car args)))) (register-builtin "sys_explode" (lambda (args) (sys_explode (car args)))) - (register-builtin "sys_fclose" (lambda (args) (sys_fclose (car args)))) - (register-builtin "sys_fopen" (lambda (args) (sys_fopen (car args) (cadr args)))) (register-builtin "sys_fread" (lambda (args) (sys_fread (car args)))) (register-builtin "sys_fwrite" (lambda (args) (sys_fwrite (car args) (cadr args) (caddr args)))) (register-builtin "sys_implode" (lambda (args) (sys_implode (car args)))) diff --git a/stdlib.slisp b/stdlib.slisp index a5aba16..fe9beac 100644 --- a/stdlib.slisp +++ b/stdlib.slisp @@ -98,18 +98,6 @@ "Convert a string to a list of characters." (sys_explode str)) -(defun fclose (n) - "Close the given file-handle. - -It is assumed the filehandle came from fopen, but nil is also accepted." - (sys_fclose n)) - -(defun fopen (str mode) - "Open a file with the given mode. - -Mode is \"r\" for read, \"w\" for write, and \"a\" for append." - (sys_fopen str mode)) - (defun fread (handle) "Read all available data from the given file-handle. @@ -409,6 +397,40 @@ do the right thing for each entry in the given list." "Does the named path exist?" (cons? (stat path))) +(defconst SYS_close 3) + +(defun fclose (handle) + "Close the given handle. + +As a special case closing a NIL file-handle is valid" + (cond + ((nil? handle) nil) + ((int? handle) + (let ((res 0)) + (set! res (syscall SYS_close handle)) + (if (> res 0) + res + nil))) + (t (do (println "Calling fclose with an invalid handle-type") (exit 1))))) + +(defconst SYS_open 2) + +(defun fopen (str mode) + "Open a file with the given mode. + +Mode is \"r\" for read, \"w\" for write, and \"a\" for append." + (let ((flags 0) + (handle 0)) + (cond + ((= 0 (strcmp mode "a")) (set! flags 1089)) ; O_WRONLY|O_CREAT|O_APPEND + ((= 0 (strcmp mode "r")) (set! flags 0)) ; O_RDONLY + ((= 0 (strcmp mode "w")) (set! flags 577)) ; O_WRONLY|O_CREAT|O_TRUNC + (t (do (println "unknown mode for fopen:" mode ) (exit 1)))) + (set! handle (syscall SYS_open str flags 420)) ; 420 == mode, 644 in octal + (if (> handle 0) + handle + nil))) + (defun file? (path) "Is the given path a file?" (let ((res (stat path)))