#!/bin/sh #< Convert a shell script into HTML, with syntax highlighting # # (C) 2004 Kevin Waldron # Released under the terms of the GNU General Public Licence # # Most modern Bourne Shell features are implemented here. Other # common external commands are also implemented. We can't implement # everything that may exist in everyones PATH's however!! if [ "$#" -ne "2" ]; then echo "Usage: $(basename $0) filename outputfile" && exit 1 fi O_FILE=$2 if [ -e "${O_FILE}" ]; then echo "$(basename $0): Error: ${O_FILE} already exists" && exit 1 fi I_FILE=$1 if [ ! -e "${I_FILE}" ]; then echo "$(basename $0): Error: ${I_FILE} does not exist" && exit 1 fi # Print standard header stuff to file #echo "" >> ${O_FILE} #echo "
" >> ${O_FILE} #echo "" >> ${O_FILE} #echo "" >> ${O_FILE} # main awk routine - syntax highlighting done here! awk '{ # these gsubs globally replace special chars gsub( "&", "\\&", $0 ); gsub( "<", "\\<", $0 ); gsub( ">", "\\>", $0 ); commandArray[0] = "awk"; commandArray[1] = "read"; commandArray[2] = "exit"; commandArray[3] = "ls"; commandArray[4] = "rm"; commandArray[5] = "sort"; commandArray[6] = "uniq"; commandArray[7] = "sed"; commandArray[8] = "mv"; commandArray[9] = "cp"; commandArray[10] = "join"; commandArray[11] = "grep"; commandArray[12] = "cat"; commandArray[13] = "df"; commandArray[14] = "cd"; commandArray[15] = "basename"; commandArray[16] = "id"; commandArray[17] = "tr"; commandArray[18] = "ls"; commandArray[19] = "true"; commandArray[20] = "false"; commandArray[21] = "seq"; commandArray[22] = "cut"; commandArray[23] = "getopt"; commandArray[24] = "getopts"; commandArray[25] = "gunzip"; commandArray[26] = "gzip"; commandArray[27] = "tar"; commandArray[28] = "date"; commandArray[29] = "clear"; commandArray[30] = "ps"; commandArray[31] = "ifconfig"; commandArray[32] = "ping"; commandArray[33] = "tput"; commandArray[34] = "useradd"; commandArray[35] = "passwd"; commandArray[36] = "stty"; commandArray[37] = "chown"; commandArray[38] = "chmod"; commandArray[39] = "trap"; commandArray[40] = "sleep"; commandArray[41] = "wait"; commandArray[42] = "last"; commandArray[43] = "head"; commandArray[44] = "let"; commandArray[45] = "shift"; commandArray[46] = "unalias"; commandArray[47] = "read"; commandArray[48] = "unset"; commandArray[49] = "alias"; commandArray[50] = "expr"; commandArray[51] = "printf"; commandArray[52] = "mkdir"; commandArray[53] = "declare"; commandArray[54] = "local"; commandArray[55] = "tail"; commandArray[56] = "hostname"; commandArray[57] = "xterm"; commandArray[58] = "bc"; commandArray[59] = "wc"; commandArray[60] = "more"; commandArray[61] = "find"; commandArray[62] = "mount"; commandArray[63] = "who"; commandArray[64] = "suspend"; commandArray[65] = "ulimit"; commandArray[66] = "umask"; commandArray[67] = "source"; commandArray[68] = "bind"; commandArray[69] = "builtin"; commandArray[70] = "typeset"; commandArray[71] = "export"; commandArray[72] = "fc"; commandArray[73] = "history"; commandArray[74] = "hash"; commandArray[75] = "jobs"; commandArray[76] = "kill"; commandArray[77] = "fg"; commandArray[78] = "bg"; commandArray[79] = "logout"; commandArray[80] = "popd"; commandArray[81] = "pushd"; commandArray[82] = "pwd"; commandArray[83] = "shopt"; commandArray[84] = "test"; commandArray[85] = "touch"; # update array_length manually below! array_length = 85; # deal with comments first - ignore entire line if one is found if ( $0 ~ /^[ ]*#/ ) { print ""$0""; } else { # syntax highlight on a line-by-line, element-by-element basis # dealing with echo firstly, so we can say echo "echo if else" # and only have the "echo" highlighted if ( $0 ~ /^[ ]*echo/ ) { gsub( /^[ ]*echo/, "&", $0 ); gsub( /;[ ]*echo/, "; echo", $0 ); # check for commands within ` and ( in echo for ( i = 0; i <= array_length; i++ ) { x=commandArray[i]; if ( $0 ~ x ) { reg = "[(]"x"[ ]*"; gsub( reg, "("x" ", $0 ); reg = "[(][ ]+"x"[ ]+"; gsub( reg, "( "x" ", $0 ); reg = "[`]"x"[ ]*"; gsub( reg, "`"x" ", $0 ); reg = "[`][ ]+"x"[ ]+"; gsub( reg, "` "x" ", $0 ); reg = "^[ ]*"x"[ ]*$"; gsub( reg, "&", $0 ); reg = "[ ]+"x"[ ]+"; gsub( reg, "&", $0 ); } } } else { # catch other echos - i.e. with case gsub( /[ ]*echo[ ]+/, "&", $0 ); # if - will be at start of line (usually) gsub( /if test/, "if test", $0 ); gsub( /^[ ]*if[ ]+/, "&", $0 ); gsub( /^[ ]*if[ ]*$/, "&", $0 ); # else - will be at start of line (usually) gsub( /^[ ]*else[ ]*$/, "&", $0 ); # elif - will be at start of line (usually) gsub( /^[ ]*elif[ ]+/, "&", $0 ); # fi - will also usually be at the start of a line gsub( /^[ ]*fi[ ]*$/, "&", $0 ); # for - will be at start of line (usually) gsub( /^[ ]*for[ ]+/, "&", $0 ); # select - will be at start of line (usually) gsub( /^[ ]*select[ ]+/, "&", $0 ); # while - will be at start of line (usually) gsub( /while read/, "while read", $0 ); gsub( /^[ ]*while[ ]+/, "&", $0 ); # until - will be at start of line (usually) gsub( /^[ ]*until[ ]+/, "&", $0 ); # case - will be at start of line (usually) gsub( /^[ ]*case[ ]+/, "&", $0 ); # esac - will be at start of line (usually) gsub( /^[ ]*esac[ ]*$/, "&", $0 ); # function - will be at start of line (usually) gsub( /^[ ]*function[ ]+/, "&", $0 ); # done - will be at start of line (usually) gsub( /^[ ]*done[ ]*/, "&", $0 ); # then - can be at start of line, or after a ; gsub( /^[ ]*then[ ]*$/, "&", $0 ); gsub( /;[ ]*then[ ]*$/, "; then", $0 ); # special case - then followed by comment if ( /[ ]*then[ ]*#/ ) { gsub( /[^$]#.*$/, "&", $0 ); gsub( /then/, "&", $0 ); } # special case - do followed by comment if ( /[ ]*do[ ]*#/ ) { gsub( /[^$]#.*$/, "&", $0 ); gsub( /do/, "&", $0 ); } # special case - else followed by comment if ( /[ ]*else[ ]*#/ ) { gsub( /[^$]#.*$/, "&", $0 ); gsub( /else/, "&", $0 ); } # special case - break followed by comment if ( /[ ]*break[ ]*#/ ) { gsub( /[^$]#.*$/, "&", $0 ); gsub( /break/, "&", $0 ); } # special case - continue followed by comment if ( /[ ]*continue[ ]*#/ ) { gsub( /[^$]#.*$/, "&", $0 ); gsub( /continue/, "&", $0 ); } # special case - done followed by comment if ( /[ ]*done[ ]*#/ ) { gsub( /[^$]#.*$/, "&", $0 ); gsub( /done/, "&", $0 ); } # special case - fi followed by comment if ( /[ ]*fi[ ]*#/ ) { gsub( /[^$]#.*$/, "&", $0 ); gsub( /fi/, "&", $0 ); } # special case - esac followed by comment if ( /[ ]*esac[ ]*#/ ) { gsub( /[^$]#.*$/, "&", $0 ); gsub( /esac/, "&", $0 ); } # do - can be at start of line, or after a ; gsub( /^[ ]*do[ ]*$/, "&", $0 ); gsub( /;[ ]*do[ ]*$/, "; do", $0 ); # continue - can be at start of line, or after a ; gsub( /^[ ]*continue[ ]*$/, "&", $0 ); gsub( /;[ ]*continue[ ]*$/, "; continue", $0 ); gsub( /continue;/, "continue;", $0 ); # break - can be at start of line, or after a ; or ending in ; gsub( /^[ ]*break[ ]*$/, "&", $0 ); gsub( /;[ ]*break[ ]*$/, "; break", $0 ); gsub( /break[ ]*;/, "break ;", $0 ); # return - can be at start of line, or after a ; gsub( /^[ ]*return[ ]*/, "&", $0 ); gsub( /;[ ]*return[ ]*/, "; return", $0 ); # scan for more comments - probably makes some of the code # above redundant! A bit of a "catch all" for comments that # slip through the net. if ( /[^${#]#[^#]/ ) { gsub( /[^$^]#.*$/, "&", $0 ); } # exec - special case as more commands may follow it if ( /[^#][ ]*exec[ ]*/ ) { gsub( /exec/, "&", $0 ); } if ( /^exec/ ) { gsub ( /exec/, "exec", $0 ); } # eval - special case as more commands may follow it if ( /[^#][ ]*eval[ ]*/ ) { gsub( /eval/, "&", $0 ); } # set - to allow tput reset if ( /set/ ) { gsub( /^[ ]*set/, "&", $0 ); } for ( i = 0; i <= array_length; i++ ) { x=commandArray[i]; if ( $0 ~ x ) { reg = "[(]"x"[ ]*"; gsub( reg, "("x" ", $0 ); reg = "[(][ ]+"x"[ ]+"; gsub( reg, "( "x" ", $0 ); reg = "[`]"x"[ ]*"; gsub( reg, "`"x" ", $0 ); reg = "[\047]"x"[ ]*"; gsub( reg, "\047"x" ", $0 ); reg = "[\042]"x"[ ]*"; gsub( reg, "\042"x" ", $0 ); reg = "[`][ ]+"x"[ ]+"; gsub( reg, "` "x" ", $0 ); reg = "[ ]+"x"[ ]+"; gsub( reg, "&", $0 ); reg = x";"; gsub( reg, ""x";", $0 ); reg = "^[ ]*"x"[ ]+"; gsub( reg, "&", $0 ); reg = "[ ]*"x"[`]"; gsub( reg, " "x"`", $0 ); reg = "[ ]*"x"[)]"; gsub( reg, " "x")", $0 ); reg = "[ ]*"x"[ ]+[`]"; gsub( reg, " "x" `", $0 ); reg = "[ ]*"x"[ ]+[)]"; gsub( reg, " "x" )", $0 ); reg = "^[ ]*"x"[ ]*$"; gsub( reg, "&", $0 ); reg = "[|][ ]+"x; gsub( reg, "| "x"", $0 ); } } # some comparison ops gsub( /[ ]+\-gt[ ]+/, " -gt ", $0 ); gsub( /[ ]+\-lt[ ]+/, " -lt ", $0 ); gsub( /[ ]+\-eq[ ]+/, " -eq ", $0 ); gsub( /[ ]+\-ne[ ]+/, " -ne ", $0 ); gsub( /[ ]+\-ge[ ]+/, " -ge ", $0 ); gsub( /[ ]+\-le[ ]+/, " -le ", $0 ); gsub( /[ ]+\-a[ ]+/, " -a ", $0 ); gsub( /[ ]+\-o[ ]+/, " -o ", $0 ); gsub( /[ ]+\-n[ ]+/, " -n ", $0 ); gsub( /[ ]+\![ ]+/, " ! ", $0 ); gsub( /[ ]+\-e[ ]+/, " -e ", $0 ); gsub( /[ ]+\-z[ ]+/, " -z ", $0 ); gsub( /[ ]+\-f[ ]+/, " -f ", $0 ); } # print out the line now we are all gsubbed print $0 } }' ${I_FILE} >> ${O_FILE} # print website plug - please leave in to "spread the word" echo "" >> ${O_FILE} #echo "" >> ${O_FILE} #echo "" >> ${O_FILE} exit 0
" >> ${O_FILE} echo "# Generated with sh2html - freely available from http://www.zazzybob.com/sh2html.html" >> ${O_FILE} # print standard footer stuff to file echo "