;;;; -*-Mode:LISP; Package:LISP; Base:10; Syntax:ISLISP -*-
;;;; Title:     testext.lsp
;;;; Author:    C. Jullien
;;;; License:   New BSD license
;;;; SVN:       "$Id: testext.lsp 4720 2022-01-18 16:49:12Z jullien $"

;;; Test external definitions using some C standard functions.

(require "extern")

(defconstant size_t '(<integer>  . "size_t"))
(defconstant file_t '(<external> . "FILE *"))

(defun test-external ()
   (external-module external external
      (:includes "<stdio.h>"
                 "<signal.h>"
                 "<stdlib.h>")
      (:in-package :stdc)
      (constant    <integer>  |OLMAXIOBUFLEN|)
      (constant    <integer>  |SEEK_SET|)
      (constant    <integer>  |SEEK_END|)
      (constant    <integer>  |SEEK_CUR|)
      ;; ANSI-C Signals
      (constant    <integer> |SIGABRT|) ;; Abort signal from abort(3)
      (constant    <integer> |SIGFPE|)  ;; Floating point exception
      (constant    <integer> |SIGILL|)  ;; Illegal Instruction
      (constant    <integer> |SIGINT|)  ;; Interrupt from keyboard
      (constant    <integer> |SIGSEGV|) ;; Invalid memory reference
      (constant    <integer> |SIGTERM|) ;; Termination signal
      ;; Non ANSI-C Signals very often defined.
      (constant    <integer> |SIGUSR1|  :if-defined)
      (constant    <integer> |SIGUSR2|  :if-defined)
      (constant    <integer> |SIGBREAK| :if-defined)
      (constant    <integer> |SIGABRT|  :if-defined)
      ;; Standard IO
      (constant    <external> (stdout *stdout*))
      (constant    <external> (stdin  *stdin*))
      (constant    <external> (stderr *stderr*))
      (<external>  |fopen|
                   (<string> <string>))
      (<integer>   |fread|
                   (<rstring> #.size_t #.size_t #.file_t))
      (<string>    |fgets|
                   (<string> <integer> #.file_t))
      (<character> |fgetc|
                   (#.file_t))
      (<character> |fputc|
                   (<character> #.file_t))
      (<integer>   |fwrite|
                   (<string> #.size_t #.size_t #.file_t))
      (<integer>   |fflush|
                   (#.file_t))
      (<integer>   |fseek|
                   (#.file_t (<integer> . "long") <integer>))
      (<integer>   |ftell|
                   (#.file_t))
      (<integer>   |fclose|
                   (#.file_t))
      (<null>      |perror|
                   (<string>))
      (<external>  |malloc|
                   (#.size_t))
      (<external>  |calloc|
                   (#.size_t #.size_t))
      (<null>      |free|
                   (<external>))
      (<external>  |memcpy|
                   (<heap> <heap> #.size_t))
   )
)

(test-external)

#|
;; usage sample:

(defun file-content (file)
   (let ((fd   (stdc:fopen file "rb"))
         (buf  (create-string stdc:|OLMAXIOBUFLEN|))
         (res  "")
         (sum  0)
         (len  0))
        (unwind-protect
                (while (> (setf len (fstdc:fread buf 1 (length buf) fd)) 0)
                       (setf sum (+ sum len))
                       (when (< len (length buf))
                             (setf buf (subseq buf 0 len)))
                       (setf res (string-append res buf)))
                (stdc:fclose fd))
        res))
|#