#!/usr/bin/newlisp
# comment following line out when using as CGI utilty
# in this case files to convert which are local must end with .txt
#(define cgi-use true)
# syntax.cgi 2.1
#
# v.1.7 - switch for using as commandline or cgi utility
# v.1.9 - fixed highlighting problem with escaped quotes
# v.2.0 - fixed \r\n translation
# v.2.1 - more compatible CGI
#
# formats newLISP source files with syntax highlighting in HTML
#
# use on the command line or as cgi file together with a webserver
#
# EXAMPLE command line:
#
# ./syntaxi.cgi mysource.lsp > mysource.lsp.html
#
# formats mysorce.lsp and redirects output to a new file mysource.lsp.html
#
# EXAMPLE webserver CGI (tested on Apache) local files must end in txt for security
#
# http://www.mysite.com/syntax.cgi?mysource.lsp.txt
#
# returns mysorce.lsp HTML formatted to the requesting client (browser)
#
# EXAMPLE webserver CGI with other site URL
#
# http://www.mysite.com/syntax.cgi?http://othersite/afile.lsp
#
# displays afile.lsp formateed from other site
#
# the following situations are not handled correctly:
# - nested curly braces for strings like {abd{def}ghi}
# - multiline quoted strings, use [text] [/text] instead
# - multiline braced strings, use [text] [/text] instead
# - comments starting with # but not starting at beginning of line
# use ; as comment starter when comment appears after code
(if cgi-use
(print "Content-type: text/html\r\n\r\n"))
(define keyword-color "#0000AA") ; newLISP keywords
(define string-color "#008800") ; single line quoted and braced strings
(define long-string-color "#008800") ; multiline for [text], [/text] tags
(define paren-color "#AA0000") ; parenthesis
(define comment-color "#555555") ; comments
(define number-color "#665500") ; numbers
(define function-name-color "#000088") ; not implemented yet for func in (define (func x y z) ...)
(set 'keywords (map name (filter (fn (x) (primitive? (eval x))) (sort (symbols) > ))))
(push "nil" keywords)
(push "true" keywords)
(set 'keyword-regex (join keywords "|"))
(replace "?" keyword-regex "\\?")
(replace "$" keyword-regex "\\$")
(replace "!" keyword-regex "\\!")
(replace "+" keyword-regex "\\+")
(replace "*" keyword-regex "\\*")
(replace "||" keyword-regex "|\\|")
(set 'keyword-regex (append {(\s+|\(|\))(} keyword-regex {)(\s+|\(|\))}))
(set 'file (if cgi-use
(or (read-line) (env "QUERY_STRING"))
(main-args 2)))
(if cgi-use
(begin
(if (and (not (starts-with file "http://" nil)) (not (ends-with file ".txt")))
(begin
(println "
File not allowed for viewing: " file "
")
(exit)))
))
(if (starts-with file "http://" nil)
(set 'file (get-url file 10000))
(set 'file (read-file file )))
(if (not file)
(begin
(println "Cannot find file
")
(exit)))
(define (clean-comment str)
(replace {} str "" 0)
(replace {} str "")
(replace {[text]} str "[&text]")
(replace {[/text]} str "[&/text]")
)
(define (format-quoted-string str)
(replace {} str "" 0)
(replace {} str "")
(replace ";" str ";&")
(replace "{" str "{&")
(replace "}" str "}&")
(replace {\} str "\&")
(replace {[text]} str "[&text]")
(replace {[/text]} str "[&/text]")
(format {%s} string-color str)
)
(define (format-braced-string str)
(replace {} str "" 0)
(replace {} str "")
(replace ";" str ";&")
(replace {"} str ""&")
(replace {[text]} str "[&text]")
(replace {[/text]} str "[&/text]")
(format {%s} string-color str)
)
(define (format-tagged-string str)
(replace {} str "" 0)
(replace {} str "")
(replace ";" str ";&")
(format {%s} string-color str)
)
; replace special HTML characters
(replace "\r\n" file "\n")
(replace "&" file "&&")
(replace "<(\\w)" file (append "<&" $1) 0)
(replace "(\\w)>" file (append $1 ">&") 0)
(replace "/>" file "/>&" 0)
(replace "" file "<&/" 0)
(replace "%s%s} $1 keyword-color $2 $3) 0)
; color numbers
(replace {(\s+|\(|\))(0x[0-9a-fA-F]+|[+-]?\d+\.\d+|[+-]?\d+|\.\d+)} file
(format {%s%s} $1 number-color $2) 0)
; color parens
(replace "(" file (format {(} paren-color))
(replace ")" file (format {)} paren-color))
; color braced strings
(replace "{.*?}" file (format-braced-string $0) 0) ; no multiline string
; color quoted strings
(replace {".*?"} file (format-quoted-string $0) 0) ; no multiline strings
; color ; comments
(replace ";.*" file (clean-comment $0) 0)
(replace ";.*" file (format {%s} comment-color $0) 0)
; color # comments
(set 'buff "")
(dolist (lne (parse file "\n"))
(replace "^\\s*#.*" lne (clean-comment $0) 0)
(replace "^\\s*#.*" lne (format {%s} comment-color $0) 0)
(write-line lne buff))
(set 'file buff)
; color tagged strings
(replace {\[text\].*?\[/text\]} file (format-tagged-string $0) 4) ; handles multiline strings
; xlate back special characters
(replace "&&" file "&") ; ampersand
(replace "<&" file "<") ; less
(replace ">&" file ">") ; greater
(replace {"&} file """) ; quotes
(replace {;&} file ";") ; semicolon
(replace {{&} file "{") ; left curly brace
(replace {}&} file "}") ; right curly brace
(replace {[&} file "[") ; left bracket
(replace {\&} file "\") ; back slash
; add pre and post tags
(println (append "\n" file "\n
" ))
(println {}
{syntax highlighting with newLISP }
{and syntax.cgi}
{})
(println {})
(exit)
;; eof