#!/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 "# Generated with sh2html - freely available from http://www.zazzybob.com/sh2html.html" >> ${O_FILE}
# print standard footer stuff to file
echo "" >> ${O_FILE}
#echo "" >> ${O_FILE}
#echo "" >> ${O_FILE}
exit 0