#!/bin/sh
: ; exec klone $0 "$@"
; The above line allows not to embed the exact path of the klone executable
;;Skeleton of a typical klone script
(setq args (getopts "USAGE: %0 [options] files...
qc-check tries to check QuakeC files for correctness
"
("-v" () verbose "verbose operation")
("-debug" () enter-debugger-on-error "enter klone debugger on error")
("-stackdump" () stackdump-on-error "verbose stack dump on error")
))
(if enter-debugger-on-error (kdb t))
(if stackdump-on-error (stack-dump-on-error t))
(setq Rident "([a-zA-Z_][a-zA-Z_0-9.]*)")
(setq Rspace "[ \t\n]*")
(setq Rexpr
"(([-+/*&|!<>=a-zA-Z_0-9. \t\n]*)|([(][-+/*&|!<>=a-zA-Z_0-9. \t\n]*[)]))")
(setq Rfuncall (+ Rident Rspace "[(]" Rexpr "[)]"))
(setq Rop "(&&|[|][|]|!|<=|<|>=|>|==|!=|[+]|[-]|&|[|]|[*]|[/])")
(setq re-combination-of-funcalls (regcomp
(+ Rspace Rfuncall Rspace Rop
"(" Rspace Rident Rspace Rop ")*"
Rspace Rfuncall)
))
(setq re-funcall-of-funcall (regcomp
(+ Rident Rspace "[(]" Rspace Rfuncall Rspace "[)]")
))
(setq re-funcall-of-funcall-ok (regcomp
(+ "[bds]print" Rspace "[(]"
"(([a-zA-Z_][a-zA-Z_0-9.]*)" Rspace "," Rspace ")?"
"[fv]tos" Rspace "[(]"
)))
(setq re-lower-case-constants (regcomp (+
"\n" Rspace "(float|string|entity|vector)" Rspace "[a-z_]" Rident Rspace
"=[^\n]*"
)))
(defun qc-check-file (filename &aux
(buffer (String (open filename
:error '(fatal-error 1 "Cannot open file: %0\n" filename)
)))
(pos 0)
)
;; check for afunc() + bfunc()
(with (pos 0 re re-combination-of-funcalls)
(while (regexec re buffer pos)
(emacs-error-message filename buffer
(get (get re 0) 0) (PF String "Operation on funcalls: %0"
(regsub re 0))
)
(setq pos (get (get re 0) 1))
))
;; check for afunc(bfunc())
(with (pos 0 re re-funcall-of-funcall)
(while (regexec re buffer pos)
(if (and
(not (regexec re-funcall-of-funcall-ok (regsub re 0)))
(/= "if" (regsub re 1))
(/= "while" (regsub re 1))
)
(emacs-error-message filename buffer
(get (get re 0) 0) (PF String "Funcall of Funcall: %0"
(regsub re 0))
))
(setq pos (get (get re 0) 1))
))
;; check for lower-case constants (disallowed!)
(with (pos 0 re re-lower-case-constants)
(while (regexec re buffer pos)
(emacs-error-message filename buffer
(get (get re 0) 0) (PF String "Lower-case constant: %0"
(subseq (regsub re 0) 1)
))
(setq pos (get (get re 0) 1))
))
)
(defun emacs-error-message (filename buffer pos text)
(PF "%0:%1:%2\n" filename (pos-to-line buffer pos) text)
)
(defun pos-to-line (buffer pos &aux
(lineno 1)
(curpos 0)
)
(catch 'Found
(while (setq curpos (seek buffer #\newline curpos))
(if (> curpos pos) (throw 'Found))
(incf lineno)
(incf curpos)
)
)
lineno
)
(defun main (&aux
)
(dolist (file args)
(qc-check-file file)
)
)
(main)
;;; EMACS MODES
;;; Local Variables: ***
;;; mode:lisp ***
;;; End: ***
syntax highlighted by Code2HTML, v. 0.9.1