#!/bin/sh
: ; exec klone $0 "$@"
; The above line finds the klone executable in the $PATH

;(kdb t)

;; verify all files. For all files, prints usages of the get function with 3
;; arguments with the 3rd not being (), a number, a string or a keyword

(defvar curfd () "Current file descriptor")
(defvar curfd-string () "Current file contents as a string")
(defvar curdir "" "Current directory")
(defvar curfile "" "Current file")

(defun main ()
  ;; recursively treat all files in current dir
  (dolist (file (directory))
    (catch 'ERROR			;errors abort only current file
      (setq ftype (file-type file))
      (if (= 'file ftype)
	(do-file file)
	(= 'directory ftype)
	(do-dir file)
))))

(defun do-file (file &aux
    (curfd (open file))
    (c (read-char curfd))
    (curfile (+ curdir (if (/= "" curdir) "/" "") file))
    expr
  )
  ;; check that file is a klone file
  (if (or (= #\( c) (= #\; c)
      (and (= #\# c) (= #\! (read-char curfd)))
    ) (progn
      (file-position curfd 0)		;rewind
      (setq curfd-string (String curfd))
      (file-position curfd 0) 
      (trap-error 'Errors:SyntaxError
	(catch 'EOF
	  (while (setq expr (read curfd))
	    (do-expr expr)
	  )
)))))

(defun do-dir (dir &aux
    (curdir (+ curdir (if (/= "" curdir) "/" "") dir))
    (*current-directory* dir)
  )
  (print-format "entering directory %0...\n" curdir)
  (main)
))

(defun do-expr (expr &aux
  )
  (if
    (typep expr QuotedExpr)		;recurse once
    (do-expr (get expr 1))

    (typep expr List) (progn
      (if (and (or (= 'get (getn expr 0)) (= 'list-get (getn expr 0)))
	    (= (length expr) 4)
	  (get expr 3) (/= t (get expr 3))
	  (not (seek allowable-default-types (type-of (get expr 3))))
	)
	(do-message "old get syntax:"  expr)
      )
      (dolist (l expr)			;recurse in list
	(do-expr l)
      )
    )

	
    (or (typep expr Number) (typep expr String) (typep expr Keyword))
    ()					;terminal types
    ;; other types: issue a warning
    (do-message "*** unknown type" (type-of expr))
))


(defun do-message (text obj)
  (print-format "%0: %1: %2 %3\n" curfile
    (file-position-to-lineno (file-position curfd) curfd-string)
    text obj
))

(defun file-position-to-lineno (pos file-string &aux
    (upto (subseq file-string 0 pos))
    c
    (lineno 1)
  )
  (dolist (c upto)
    (if (= #\newline c) (incf lineno))
  )
  lineno
)

(defunq trap-error (trap-error:tag &rest trap-error:body)
  (setq trap-error:tag (eval trap-error:tag))
  (setq trap-error:catched ())
  (with (*error-correctors* (+ *error-correctors* (list
	  (eval `(lambda (errorcode &rest args)
	      (if (= ,trap-error:tag errorcode) (progn
		  (setq trap-error:catched t)
		  :true
		)
		:nil
    ))))))
    (catch 'trap-error (apply progn trap-error:body))
  )
)

(defvar allowable-default-types
  (list Number Int Real ProcessId FExpr Expr Subr FSubr Macro String Keyword
    Regexp Type Stream Hashtable ExObject ExClass GenericFunction Link
))

(setq files (subseq *arguments* 0))
(if files
  (dolist (file files)
    (catch 'ERROR			;errors abort only current file
      (setq ftype (file-type file))
      (if (= 'file ftype)
	(do-file file)
	(= 'directory ftype)
	(do-dir file)
  )))
  (main)
)
