#!/usr/bin/perl -w
######################################################################
#                                                                    #
# Code2HTML                                                          #
# ---------                                                          #
#                                                                    #
# Code2Html, version 0.7.1, Aug 1999, ppalfrad@cosy.sbg.ac.at        #
#                                                                    #
# AUTHOR                                                             #
#        Peter  Palfrader,  computer   science   student   at   the  #
#        University  of Salzburg/Austria. Written in 1999.           #
#                                                                    #
# DESCRIPTION                                                        #
#        code2html.pl is a  perlscript  which  converts  a  program  #
#        source  code  to syntax highlighted HTML by applying a set  #
#        of   regular   expressions   depending   on  the  language  #
#        the source code is written.                                 #
#                                                                    #
# LICENSE                                                            #
#        Copyright (c) 1999 by Peter Palfrader.                      #
#        Not derived from licensed software.                         #
#                                                                    #
#        Permission is granted to anyone to use this  software  for  #
#        any purpose on any computer system, and to redistribute it  #
#        in any way, subject to the following restrictions:          #
#                                                                    #
#        1. The author is not responsible for the  consequences  of  #
#           use of this software, no matter how awful, even if they  #
#           arise from defects in it.                                #
#        2. The origin of this software must not be misrepresented,  #
#           either by explicit claim or by omission.                 #
#        3. Altered  versions  must  be plainly marked as such, and  #
#           must  not  be  misrepresented  (by  explicit  claim  or  #
#           omission) as being the original software.                #
#        3a. It would be nice if I got  a  copy  of  your  improved  #
#            version  sent to ppalfrad@cosy.sbg.ac.at. However this  #
#            is not obligatory.                                      #
#        4. This notice must not be removed or altered.              #
#                                                                    #
#        Thanks to Henry Spencer for this wonderful license :).      #
#                                                                    #
#                                                                    #
#        The regular expressions found in the default database  are  #
#        are  not subject to  this  license. They  have  been taken  #
#        from  NEdit and were then slightly modified by me.          #
#                                                                    #
#        According to Mark Edel <edel@ltx.com> who does the support  #
#        of NEdit they are public domain and so  you  may  do  with  #
#        them whatever you want.                                     #
#                                                                    #
######################################################################
#                                                                    #
# HISTORY                                                            #
#                                                                    #
# 0.7.1 - August 1999                                                #
#  * corrected (hopefully) a gotcha in the perl patterns (again...)  #
#  * added one item to the changelog of 0.7.0                        #
#  * --replace_tabs no longer replaces every tab with the given      #
#   amount of spaces but instead it now replaces it with the right   #
#   number to go to the next tabstop. the parameter given to         #
#   replace_tabs gives the width of tabstops.                        #
#   TNX to T. Jahn <tjahn@crosswinds.net> for providing an example   #
#   of how to do this in one of his programs. If I had known it      #
#   was that easy I'ld have done it earlier :)                       #
#                                                                    #
# 0.7.0 - August 1999                                                #
# * No longer need for that stupid fatal_error sub. I now use perl's #
#   handlers for __DIE__ and __WARN__                                #
# * complete rewrite of the option and parameter fetching sub. I     #
#   now use Getopt::Long. TNX to Barrie for the pointer. As a        #
#   the number for --replace_tabs / -t is no longer optional.        #
# * Added HTML patching: code2html now also allows you to have       #
#   inline source code in an html file. It can then take this html   #
#   file and insert the syntax highlighted code.                     #
#   Look in the help. It's very usefull ( at least for me )          #
# * the CGI mode got a forth way to pass the input file. If the      #
#   input_selector parameter is set to REDIRECT_URL the file is      #
#   taken from ENV{'DOCUMENT_ROOT'}.$ENV{'REDIRECT_URL'}.            #
#   Kevin Burton <burton@relativity.yi.org> suggested this so that   #
#   it is possible to configure Apache with an action directive      #
#   to automatically print java files syntax highlighted.            #
#                                                                    #
# 0.6.6 - July 1999                                                  #
# * added sql - it is still very poor since I don't know all the     #
#   keywords etc. If you know, tell me.                              #
# * Martynov Andrew <root@tn.energo.ru> pointed me to the qq, qx,    #
#   etc operators in perl. They should now no longer cause problems  #
# * Wayne Roberts <wroberts1@cx983858-b.orng1.occa.home.com>         #
#   reported a problem with C strings like "\\". It should be fixed  #
#   too.                                                             #
# * I changed the operator with which the default language base      #
#   is assigned to a variable, so there's no need for \\\\\\\\\\     #
#   quotes anymore :)                                                #
#                                                                    #
# 0.6.5 - June 1999                                                  #
# * tweaking Perl regular expressions (TNX to Barrie Slaymaker       #
#   <rbs@telerama.com>)                                              #
# * if a language mode cannot be found the error message now tells   #
#   you which lang you requested.                                    #
# * new --fallback <lang> option. This language mode is used if the  #
#   given mode by parameter #1 is not available. This feature was    #
#   requested by Barrie Slaymaker <rbs@telerama.com>                 #
# * changed 'is called as CGI' heuristics.                           #
#                                                                    #
# 0.6.4 - May 1999                                                   #
# * the name attribute in the line numbers was wrong. there should   #
#   be no # in it. TNX to <stifle33@hotmail.com>                     #
# * linking to line numbers now works from the command line too      #
#                                                                    #
# 0.6.3 - May 1999                                                   #
# * fixed C character constant regex. TNX to Jesse                   #
#   <jesse@lmscadsi.com>                                             #
# * line numbers now can link to themselves                          #
# * line numbers now have a constant width                           #
#                                                                    #
# 0.6.2 - May 1999                                                   #
# * fixed something in HTML lang                                     #
#                                                                    #
# 0.6.1 - May 1999                                                   #
# * added 'plain' language mode                                      #
# * cgi support improoved. should now also handle                    #
#   enctype="multipart/form-data" forms                              #
#                                                                    #
# 0.6.0 - May 1999                                                   #
# * fixed Substitution loop at ./code2html.pl (5.2) line 627         #
# * changed string regular expressions: \" is no longer a problem    #
# * default locations for the language files have changed:           #
#   first all the files listed in the enviroment variable            #
#   CODE2HTML_CONFIG (seperated by colons (:)) will be checked,      #
#   then, if HOME set, $HOME/.code2html.config and finally           #
#   /etc/code2html.config                                            #
#   TNX to Eric Brandwine <ebrandwi@UU.NET> for the hint.            #
# * new: --no_header does not print the <html><head>... stuff        #
# * new: --content_type prints Content-Type: text/html;              #
# * C/C++: in preprocessor lines: strings are highlighted now        #
# * -n now also names the lines with <a name="line<nr>">..</a>       #
# * script may now be run as a CGI script. see the CGI section       #
#   in the help                                                      #
# * get_config_file was rewritten because it was _ugly_              #
#                                                                    #
# 0.5.2 - May 1999                                                   #
# * fixed Makefile dependency line bug. (a * in regexp instead a +)  #
#                                                                    #
# 0.5.1 - May 1999                                                   #
# * clarified copyright questions on regular expressions             #
# * changed -dumb_default_lang to -dump_default_lang :)              #
#                                                                    #
# 0.5.0 - Apr 1999                                                   #
# * changed find_all_matches__create_taglist__insert_placeholders    #
#   so that it works around a bug in earlier perl versions, in which #
#   pos() is not set if the return value of m//g is not used.        #
# * changed a regex in get_config_file                               #
#                                                                    #
# 0.4.1 - Mar 1999                                                   #
# * changed JavaScript regexps slightly                              #
# * changed find_all_matches_.. slightly                             #
#                                                                    #
# 0.4.0 - Mar 1999                                                   #
# * script no longer needs $' and $` thus beeing faster. $& is still #
#   needed                                                           #
# * regexps for perl changed slightly                                #
# * find_all_matches has been completly rewritten. verify is no      #
#   longer needed. taglist is built while searching.                 #
#   May take a bit longer now, but otherwhise a bug could not have   #
#   been fixed.                                                      #
# * changed (fixed?) start of language_def_block pos evaluation      #
#                                                                    #
# 0.3.3 - Feb 1999                                                   #
# * fixed STDIN/STDOUT parameters when passed a - the scrpit though  #
#   options would follow and didn't tread this as a handle for STDIN #
# * added -V as shortcut to --version                                #
#                                                                    #
# 0.3.2 - Feb 1999                                                   #
# * removed -T from 1st line so activePerl will run the script       #
#   without any modifications                                        #
# * changed perl string regexps. run now faster and better           #
#   (and run at all under win)                                       #
# * added --replace_tabs                                             #
#                                                                    #
# 0.3.1 - Feb 1999                                                   #
# * fixed language files bug (<space>lang_mode<space> no longer      #
#         starts langmode)                                           #
# * fixed empty html tag bug when reading lang specs                 #
# * added languages: Makefile, Java, JavaScript, Perl                #
# * added --modes                                                    #
#                                                                    #
# 0.3.0 - Feb 1999                                                   #
# * added linenumbers                                                #
# * added <head> and <title> tag in html output                      #
# * fixed crlf switch works now                                      #
#                                                                    #
# 0.2.0 - Feb 1999                                                   #
# * first official release                                           #
#                                                                    #
######################################################################

use strict;
use Getopt::Long;

my $FILES_DISALLOWED_IN_CGI = 0;
# you may set this to true to disallow file reading from your hd in 
# cgi mode. This may be good if your httpd runs as 'root' (yes, I've
# seen this!) and so any user could with some knowledge easily read
# your /etc/shadow for example!
my $FILES_REDIRECT_DISALLOWED = 0;




my $vernr = "0.7.1";
my $monthshort = "Aug";
my $monthlong = "August";

my $pure_version_message = "Code2Html, version $vernr, $monthshort 1999, ppalfrad\@cosy.sbg.ac.at";
my $version_message = "\$pure_version_message\n\n";

my $help_message = "
$pure_version_message

NAME
       code2html.pl - Converts a program source code to HTML

SYNOPSIS
       (1) code2html.pl [options] language_mode [input_file 
           [output_file]]

       (2) code2html.pl -p [file]

       (3) code2html.pl (as a CGI script: see CGI section below)

DESCRIPTION
       code2html.pl is a  perlscript  which  converts  a  program
       source  code  to syntax highlighted HTML by applying a set
       of   regular   expressions   depending   on  the  language
       the source code is written.

EXAMPLE USAGE
       assuming code2html.pl is in the current directory, you may
       type

           code2html.pl perl code2html.pl code2html.html
     
       to convert the script into a html file.
 
 (1) OPTIONS
       language_mode
              Specify the set  of  regular  expressions  to  use.
              These  have  to  be  defined  in  a  langugage file
              (see FILES below). To find out which language modes
              are defined, issue a code2html.pl --modes.

              This input is treated case-insensitive.
  
       input_file
              Is the file which contains the program source  code
              to be formatted. If not specified or a minus (-) is
              given, the code will be read from STDIN.

       output_file
              Is the file ro write the formatted code to. If  not
              specified or a minus (-) is given, the code will be
              written to STDOUT.

       -v, --verbose
              Prints progress information to STDERR. You will not
			  need this.

       -n, --linenumbers
              Print out the source code with line numbers.

       -N, --linknumbers
              Print out the source code with line numbers.
              The linenumbers  will  link  to  themselves,  which
              makes it easy to send links to lines.

       -t, --replace_tabs  <TABSTOP WIDTH>
              Replace each occurence of a  <TAB>  character  with
              the  right  amount  of  spaces  to  get to the next
              TABSTOP.
              can be changed by an optional argument.

       -l, --language_file  <FILE>
              Specify an alternate languages  file  to  take  the
              regular expressions from (see FILES below).

       -m, --modes
              Print all defined modes currently defined to STDOUT
              and exit succesfully.  Also  prints  modes  from  a
              given language_file if applicable.

       --fallback <LANG>
              If the language mode givin with the first parameter
              (language_mode) cannot be found then use this mode.
              Usefull  when code2html is called from a script to
              ensure output is created: --fallback plain

       --dump_default_lang
              Write default language  file  to  STDOUT  and  exit
              succesfully.

       -h, -? --help
              Print this text and exit succesfully.

       -V --version
              Print the program version and exit succesfully.

       -c --content_type
              Prints \"Content-Type: text/html\\n\\n\" prior  to  the
              html file. Usefull if the script is  ivoked   as  a
              cgi script.

       -H --no_header
              do not print the  <html>,  <head>,  <body>,  <pre>
              stuff. Usefull if this script is only  a  part  in
              a  bigger program.

 (2) code2html.pl -p [file]
       code2html now also allows you to have inline source code
       in an html file. It can then  take this  html  file  and
       insert the syntax highlighted code.

       If no file is given,  code2html  reads  from  STDIN  and
       writes to STDOUT.

       To  use  this feature, just insert a like like this into
       your html file:
       <!-- code2html add [options] lang_mode <file> -->
       
       the syntax highlighted file will  be  inserted  at  this
       position enclosed in <pre> tags.
  
       All  options  that  can be given on the commandline like
       --linenumbers   etc.   work.   --help,   --version   and 
       --dump_default_lang work too  however  it  is  not  very
       intelligent to use them :). --content_type is ignored.

       You  may  also  write the program's source code directly
       in the html file with the following syntax:

       <!-- code2html add [options] lang_mode
 
       <your program source code here>

       -->
      
       This is a very new feature, so if you have  problems  or
       questions,  please  let me know. An example can be found
       at my homepage: http://www.cosy.sbg.ac.at/~ppalfrad

 (3) CGI
       If   the   the   script   is   used   as   a   CGI  script
       (GATEWAY_INTERFACE envoriment  set  and  no  command  line
       arguments given) code2html reads the arguments either from
       the query string or from stdin. (methods POST and GET).

       --content_type is switched on automatically and the output
       always goes to STDOUT.


       The following parameters/options are accepted:


       language_mode - required
         'c', 'cc', 'pas', etc.

       fallback - optional
         'plain', 'c', etc.
         if language_mode cannot be found, use this one

       input_selector - optional
         either 'file', 'cgi_input1', 'cgi_input2', or 
         'REDIRECT_URL'
         default: file

       filename
         file to read from if input_selector is 'file'

       cgi_input1
         the source code to syntax highlight
         for example from a <textarea> or from a upload.
         see input_selector

       cgi_input2
         the source code to syntax highlight
         for example from a <textarea> or from a upload.
         see input_selector

       line_numbers - optional
         'yes', 'no' or 'link'
         default: no

       replace_tabs - optional
         if 0 then tabs are not replaced, if larger then each
         tab is replaced by that many spaces.
         default: 0
       

       Why  two  cgi_inputs  you  may  ask: This is to allow your
       users to choose vie a <form> interface whether  they  want
       to  insert their file into a <textarea> or user a <browse>
       button to select their file. See the example on  my  home-
       page.

       Note that by default it is possbile for your users to read
       all the files the httpd can read (if you don't run a  cgi-
       wrapper  or  something  like  this . You may disallow file
       reading via cgi with setting FILES_DISALLOWED_IN_CGI  to 1
       at the top of the script.

       The   input   selector   REDIRECT_URL   needs   a  special
       explaination.  The  file  name  is  formed  from  the  two
       enviroment variables DOCUMENT_ROOT and REDIRECET_URL.

       Kevin Burton  <burton\@relativity.yi.org>  will  tell  you
       what you need this for:

       > So I had a problem where  I  wanted  all  my  Java files
       > automatically  converted  to  html  and displayed. But I
       > didn't  want  to  write  any  crazy  web  interface  for
       > code2html.
       > So what I did was this.
       >
       > Configured Apache with an \"Action\" directive in srm.conf
       > like this:
       >
       > Action text/java
       > /cgi-bin/code2html?language_mode=java&input_selector=REDIRECT_URL
       >
       > Works great!
       >
       > It is more powerfull if you use it in an Apache
       > <Directory> tag
       >
       > <Directory /source>
       >
       >   #with your Action tag here... this way you can 
       >   #still have regular .java files on your server.
       >
       > </Directory>
       >




BUGS
       If the input file contains  all  256  possible  characters
       then all character values of 255 will be changed to values
       of  254. I don't think this is a problem and so I will not
       try to find a other way to code  this  stuff.  If  however
       this  is a problem for you, let me know and I will rethink
       my strategy.

       Please   report   bugs  to  ppalfrad\@cosy.sbg.ac.at.  This
       program is still in beta so you might find some. Also have
       a look at my web-site, perhaps a new version is  available
       already:              http://www.cosy.sbg.ac.at/~ppalfrad/

FILES
       file specified by -l or --language_file if any
       files specified in \$CODE2HTML_CONFIG, seperated by colons
       \$HOME/.code2html.config
       /etc/code2html.config
	   built in default languages

       These databases will be searched in that order for the set
       of regular  expressions  specified  by  the  language_mode
       parameter. The first set of regular expression which is
       found will be taken.


       The files must have the following structure:

       Empty lines are ignored.

       Every line beginning with a pound sign (#) is a comment.
       Note that a line actually must start with  this  character
       (apart from tabs and spaces) in order to be a comment.

       A language starts with the name of it's section in
       brackets. Aliases may be defined withing the same brackets
       seperated by a comma (,).
         Examples:  [c]
                    [c++,cpp,cc]

       Then the default background and text colours may  be  set.
       If  not  defined  they  default to #ffffff (white) for the
       background and #000000 (black) for the text.
                    bgcolor=#ffffff
                    textcolor=#000000
       Spaces and Tabs before and after the equals-sign  (=)  are
       allowed.  The  first non whitespace after the = sign until
       the end of line will then be copied  to  the  bgcolor  and
       the text options in the HTMLs body tag.

       As a third step the regular expressions must be defined:
       A line defining this consist of three parts:
       The html tag to insert  at  the  start  of  the  pattern's
       occurance,  one  to insert  at  the  end  and  the pattern
       itself.  All  three  parts  must  be  enclosed  in  double
       quotes(\")  and  are  seperated  by  commas (,).  If one of
       those parts contains a double quote, this must be  escaped
       with a backshlash (\\).
         Example:
              \"<i>\", \"</i>\", \"\\\".*?\\\"\"
              This line prints all strings enclosed by double
              quotes italic.
       If a line starts with a minus (-) then this pattern is
       applied to the matched part of the previos line that had
       no minus in front. So you can highlight for example escape
       characters in strings.
              - \"<strong>\", \"</strong>\", \"\\\\.\"

       If you ever write languages files yourself, I'ld be  happy
       if  you  could  send be them, so I put them on my homepage
       with full credits of course.
       Before you do so you might also have a look at my site  to
       check  wheter  someone  has  written  the  file  for  your
       language already.

       web-site:             http://www.cosy.sbg.ac.at/~ppalfrad/

AUTHOR
       Peter  Palfrader,  computer   science   student   at   the
       University  of Salzburg/Austria. Written in $monthlong 1999.

LICENSE
       Copyright (c) 1999 by Peter Palfrader.
       Not derived from licensed software.

       Permission is granted to anyone to use this  software  for
       any purpose on any computer system, and to redistribute it
       in any way, subject to the following restrictions:

       1. The author is not responsible for the  consequences  of
          use of this software, no matter how awful, even if they
          arise from defects in it.
       2. The origin of this software must not be misrepresented,
          either by explicit claim or by omission.
       3. Altered  versions  must  be plainly marked as such, and
          must  not  be  misrepresented  (by  explicit  claim  or
          omission) as being the original software.
       3a. It would be nice if I got  a  copy  of  your  improved
           version  sent to ppalfrad\@cosy.sbg.ac.at. However this
           is not obligatory.
       4. This notice must not be removed or altered.

       Thanks to Henry Spencer for this wonderful license :).


       The regular expressions found in the default database  are
       are  not subject to  this  license. They  have  been taken
       from  NEdit and were then slightly modified by me.

       According to Mark Edel <edel\@ltx.com> who does the support
       of NEdit they are public domain and so  you  may  do  with
       them whatever you want.
";

my $short_help = "
$pure_version_message

NAME
       code2html.pl - Converts a program source code to HTML

SYNOPSIS
       code2html.pl language_mode [input_file [output_file]]
         [options]

DESCRIPTION
       code2html.pl is a  perlscript  which  converts  a  program
       source  code  to syntax highlighted HTML by applying a set
       of   regular   expressions   depending   on  the  language
       the source code is written.
";





my $USE_CGI_FOR_ERRORS      = 0;
$SIG{'__DIE__'} = 
  sub {
    if ($USE_CGI_FOR_ERRORS) { print "Content-Type: text/plain\n\n$_[0]\n"; }
    else                     { print STDERR $_[0];                          };
    exit 1;
  };

$SIG{'__WARN__'} = 
  sub {
    if (!$USE_CGI_FOR_ERRORS) { print STDERR $_[0]; };
  };


my %params = &parse_params;
if    ($params{'what_to_do'} eq 'patch_html') { &patch_html(\%params) }
elsif ($params{'what_to_do'} eq 'normal'    ) { &main(\%params)       }
else  { die("I don't know what to do :(\n") };










sub main
  {
      my %params = %{shift()};

      my $hidechar = "";  # a character that must not exist in the code and which is used as a placeholder will be set in $code;
      my $bgcolor   = "#ffffff"; #default value only. will be set in parse_config_part
      my $textcolor = "#000000"; #default value only. will be set in parse_config_part

      my @CONFIG_FILES = [];
      push @CONFIG_FILES, split(/:/,$params{'langfile'})      if defined($params{'langfile'});
      push @CONFIG_FILES, split(/:/,$ENV{'CODE2HTML_CONFIG'}) if ($ENV{'CODE2HTML_CONFIG'});
      push @CONFIG_FILES, $ENV{'HOME'}."/.code2html.config"   if (defined($ENV{'HOME'}));
      push @CONFIG_FILES, "/etc/code2html.config";


      print STDERR "parsing config file...\n"                                           if ($params{'verbose'});
      my @regexps = &parse_config_part( &get_config_file(\@CONFIG_FILES, \%params) , $bgcolor, $textcolor);

      print STDERR "loading input file...\n"                                            if ($params{'verbose'});
      my $code    = &get_input_file(\%params, $hidechar);

      print STDERR "finding all matches, inserting placeholders, creating taglist...\n" if ($params{'verbose'});
      my @taglist = &find_all_matches__create_taglist__insert_placeholders(\@regexps, $code, $hidechar);                          

      print STDERR "converting source code to HTML...\n"                                if ($params{'verbose'});
      $code    = &convert_code_2_html($code);                                                                                  

      print STDERR "replacing placeholders with appropriate HTML tags...\n"             if ($params{'verbose'});
      $code    = &insert_tags(\@taglist, $code, $hidechar);

      print STDERR "outputting file...\n"                                               if ($params{'verbose'});
      return &put_output(\%params, $code, $bgcolor, $textcolor);
}





sub patch_html
  {
      my %params = %{shift()};
      my $code;

      open(FILEHANDLE, $params{'infile'}) || die("Error while opening inputfile.\n");
      undef $/; $code = <FILEHANDLE>;
      close(FILEHANDLE);
      
      $code =~ s/<!-- code2html delete start -->.*?<!-- code2html delete stop -->//gs;
      my $counter=0;
      my @chunks = split ( /(<!-- code2html add.*?-->)/s , $code);

      $code = '';
      for (@chunks)
	{
	    $code .= $_;
    	    if ($_ =~ /<!-- code2html add(.*?)(\n.*?)?-->/s)
	      {
		  my $cmdline = $1; 
		  my $input   = $2;

		  $cmdline =~ s/^[ \t]*//g;
		  $cmdline =~ s/[ \t]*$//g;
		  @ARGV = split ( / / , $cmdline);
		  my %new_params = &parse_params;

		  $new_params{'input'} = $input  if ($new_params{'infile'} eq "-");
		  undef $new_params{'outfile'};
		  $new_params{'line_number_prefix'} = ++$counter;

		  $new_params{'verbose'} = $params{'verbose'};

		  my $no_header = $new_params{'noheader'};
		  $new_params{'noheader'} = 1;

		  if ($no_header)
		    {
			$code .= '<!-- code2html delete start -->'..
			  &main(\%new_params).
			    '<!-- code2html delete stop -->';
		    }
		  else
		    {
			$code .= '<!-- code2html delete start --><pre>'.
			  &main(\%new_params).
			    '</pre><!-- code2html delete stop -->';
		    };
	      };
	};


      open(FILEHANDLE, '>'.$params{'infile'}) || die("Error while opening outputfile.\n");
      print FILEHANDLE $code;
      close(FILEHANDLE);
  };







#####################################################################
################### get_input_data ##################################
#####################################################################
# Reads the input data for the cgi script.
# in : nothing
# out: a hash with the input data
sub get_input_data
  {
    my $input_data;
    my %f;
    if($ENV{'REQUEST_METHOD'} eq 'GET')  { $input_data = $ENV{'QUERY_STRING'}; }
    else {  read(STDIN, $input_data, $ENV{'CONTENT_LENGTH'}); };
    
    
    if ($ENV{'CONTENT_TYPE'} =~ m/^multipart\/form-data; boundary=(.*)$/i)
      {
        my $boundary = quotemeta($1);
        my @blocks = split(/$boundary/, $input_data);
        
        for (@blocks)
          {
            if (my $dummy = m/name="(.*?)"/i) 
              {
                my $name = $1;
                $_ =~ s/\r\n/\n/g;
                m/\n\n(.*)\n/s;
                my $value = $1;
                $f{$name}=$value;
              };
          };
      }
    elsif ($ENV{'CONTENT_TYPE'} =~ m/^multipart\/form-data;$/i) # if the boundary is not in the enviroment variable we'll guess
      {
        my $dummy = $input_data =~ m/^(.*?)(\n|\r)/;
        my $boundary = $1;

        my @blocks = split(/$boundary/, $input_data);

        for (@blocks)
          {
            if (my $dummy = m/name="(.*?)"/i)
              {
                my $name = $1;
                $_ =~ s/\r\n/\n/g;
                m/\n\n(.*)\n/s;
                my $value = $1;
                $f{$name}=$value;
              };
          };
      }
    else
      {
        my @form_fields = split(/&/, $input_data);
        
        for (@form_fields)
          {
            my ($name, $value) = split(/=/, $_);
            $value =~ tr/+/ /;
            $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
            
            $f{$name} = $value;
          }
      };

    return %f;
  };
################################################################################
####################### parse_params ###########################################
################################################################################
sub parse_params
  {
      my %RESULT;
      
      if (defined($ENV{'GATEWAY_INTERFACE'}) && (!scalar(@ARGV))) # if there is a CGI enviroment and no parameters/options given
	{
	    $USE_CGI_FOR_ERRORS = 1;
	    $RESULT{'content-type'} = 1;
	    $RESULT{'what_to_do'} = 'normal';
	    
	    my %input = &get_input_data;
	    if (!defined($input{'language_mode'})) {die('CGI parse error: language mode not given!')};
	    $RESULT{'langmode'} = $input{'language_mode'};
      
	    if ($input{'input_selector'} eq "cgi_input1")
	      {
		  if (!defined($input{'cgi_input1'})) {die('CGI parse error: cgi_input1 does not exist!')};
		  $RESULT{'input'} = $input{'cgi_input1'};
	      }
	    elsif ($input{'input_selector'} eq "cgi_input2")
	      {
		  if (!defined($input{'cgi_input2'})) {die('CGI parse error: cgi_input2 does not exist!')};
		  $RESULT{'input'} = $input{'cgi_input2'};
	      }
	    elsif ($input{'input_selector'} eq "file")
	      {
		  if ($FILES_DISALLOWED_IN_CGI) {die('CGI parse error: option not supported due to security reasons!')};
		  if (!defined($input{'filename'})) {die('CGI parse error: filename not defined!')};
		  $RESULT{'infile'} = $input{'filename'};
	      }
	    elsif ($input{'input_selector'} eq "REDIRECT_URL")
	      {
		  if ($FILES_REDIRECT_DISALLOWED) {die('CGI parse error: option not supported due to security reasons!')};
		  if (!defined($ENV{'REDIRECT_URL'})) {die('CGI parse error: ENV: REDIRECT_URL not defined!')};
		  $RESULT{'infile'} = $ENV{'DOCUMENT_ROOT'}.$ENV{'REDIRECT_URL'};
	      }
	    else
	      {
		  die('CGI parse error: input selector not given!');
	      };
	    
	    if ($input{'line_numbers'} eq "yes")  { $RESULT{'linenumbers'} = 'yes'; };
	    if ($input{'line_numbers'} eq "link") { $RESULT{'linenumbers'} = 'link'; };
	    if (defined($input{'replace_tabs'}))  { $RESULT{'replacetabs'} = $input{'replace_tabs'} };
	    if (defined($input{'fallback'}))      { $RESULT{'alt_langmode'} = $input{'fallback'} };

	    $RESULT{'content_type'} = 1;
	    $RESULT{'outfile'}      = '-';
	}
      else
	{
	    my $verbose           = 0;
	    my $linenumbers       = 0;
	    my $linknumbers       = 0;
	    my $replace_tabs      = 0;
	    my $language_file     = '';
	    my $modes             = 0;
	    my $fallback          = '';
	    my $dump_default_lang = 0;
	    my $help              = 0;
	    my $version           = 0;
	    my $content_type      = 0;
	    my $no_header         = 0;

	    my $patch_html;

	    Getopt::Long::config('bundling');
	    if (! GetOptions( "--verbose"               , \$verbose              , 
		              "-v"                      , \$verbose            ,
			      
			      "--linenumbers"           , \$linenumbers          , 
			      "-n"                      , \$linenumbers        , 
			      
			      "--linknumbers"           , \$linknumbers          , 
			      "-N"                      , \$linknumbers        , 
			      
			      "--replace_tabs=i"        , \$replace_tabs         , 
			      "-t=i"                    , \$replace_tabs       , 
			      
			      "--language_file=s"       , \$language_file        , 
			      "-l=s"                    , \$language_file        , 

			      "--modes"                 , \$modes                , 
			      "-m"                      , \$modes                , 

			      "--fallback=s"            , \$fallback             , 
			      
			      "--dump_default_lang"     , \$dump_default_lang    , 

			      "--help"                  , \$help                 , 
			      "-s"                      , \$help                 , 
			      "-h"                      , \$help                 , 

			      "--version"               , \$version              , 
			      "-V"                      , \$version              , 
			      
			      "--content_type"          , \$content_type         , 
			      "-c"                      , \$content_type         , 
			      
			      "--no_header"             , \$no_header            ,
			      "-H"                      , \$no_header            ,

			    
			      "--patch_html"            , \$patch_html           ,
			      "-p"                      , \$patch_html           )
	       )
	      {
		  print STDERR $short_help;
		  print STDERR "\n\nrun code2html --help for furhter help\n";
		  exit 1;
	      };
	    if ($help)              { print $help_message;         exit 0; };
	    if ($version)           { print $version_message;      exit 0; };
	    if ($dump_default_lang) { print &get_default_database; exit 0; };

	    if ($patch_html)
	      {
		  $RESULT{'what_to_do'} = 'patch_html';
		  $RESULT{'verbose'}    = $verbose;

		  if (!defined ($RESULT{'infile'}        = shift(@ARGV))) { $RESULT{'infile'} = '-' };
		  $RESULT{'outfile'} = $RESULT{'infile'};
	      }
	    else
	      {
		  $RESULT{'what_to_do'} = 'normal';

		  $RESULT{'verbose'}        = $verbose;
		  if    ($linknumbers) { $RESULT{'linenumbers'}    = 'link' }
		  elsif ($linenumbers) { $RESULT{'linenumbers'}    = 'yes' }
		  else                 { $RESULT{'linenumbers'}    = 'no' };
		  $RESULT{'replacetabs'}    = $replace_tabs;
		  $RESULT{'langfile'}       = $language_file;
		  $RESULT{'modes'}          = $modes;
		  $RESULT{'alt_langmode'}   = $fallback;
		  $RESULT{'content_type'}   = $content_type;
		  $RESULT{'noheader'}       = $no_header;

		  if (!defined ($RESULT{'langmode'}        = shift(@ARGV))) { print STDERR  "no language mode given!\n";
									      print STDERR $short_help;
									      print STDERR "\n\nrun code2html --help for furhter help\n";
									      exit 1;
									  };
		  if (!defined ($RESULT{'infile'}          = shift(@ARGV))) { $RESULT{'infile'} = '-'};
		  if (!defined ($RESULT{'outfile'}         = shift(@ARGV))) { $RESULT{'outfile'} = '-'};
		  if (defined (shift(@ARGV))) { print STDERR  "too many parameters!\n";
						print STDERR $short_help;
						print STDERR "\n\nrun code2html --help for furhter help\n";
						exit 1;
					    };
	      };
	};

      return %RESULT;
  };

################################################################################
####################### get_config_lines #######################################
################################################################################
sub get_config_lines
  {
    #in : \@lines
    #in : metaquoted $langmode
    #in : $modes

    #returns config file as string

    my @lines = @{shift()};
    my ($lm, $modes) = @_;
    my $result = "";


    if ($modes)
      {
	for (@lines)
	  {
	    $_ =~ s/\n|\r//g;
	    $_ =~ s/^[ \t]*(.*)[ \t]*/$1/; #remove beginning and trailing spaces / tabs
	    print "    ".$_."\n" if (substr($_,0,1) eq "[");
	  }
      } 
    else 
      {
	  my $waiting = 1;
	  for (@lines)
	    {
		if ($waiting)
		  {
		      $_ =~ s/\n|\r//g;
		      $_ =~ s/^[ \t]*(.*)[ \t]*/$1/; #remove beginning and trailing spaces / tabs
		      if ($_ =~ m/^\[(.*?[, ])?$lm([, ].*?)?\]/i)
			{$waiting = 0;};
		  }
		else
		  {
		      $_ =~ s/\n|\r//g;
		      $_ =~ s/^[ \t]*(.*)[ \t]*/$1/; #remove beginning and trailing spaces / tabs
		      last if (substr($_,0,1) eq "["); #new language mode
		      
		      if (($_ ne "")&&(substr($_, 0, 1) ne "#"))
			{
			    $_ =~ /^(.*)$/;    # untaint input
			    $result .= $1."\n";
			}
		  }
	    };
      };
    
    return $result;
};

################################################################################
####################### get_one_config_file ####################################
################################################################################
sub get_one_config_file
{
    #in: filename
    #in: langmode already meta quoted.
    #in: modes;
    #returns config file as string
    
    my ($filename, $langmode, $modes) = @_;

    open(FILEHANDLE, "<$filename") || return "";

    my @lines = <FILEHANDLE>;
    my $result = get_config_lines(\@lines, $langmode, $modes);
    close FILEHANDLE;
    
    return $result;
};

################################################################################
####################### get_config_file ########################################
################################################################################
sub get_config_file
{
    #in : @config_files
    #in : %params
    #returns config file as string
    
    my @CONFIG_FILES = @{shift()};
    my %PARAMS       = %{shift()};


    #Apply language mode
    my $result = "";

    if ($PARAMS{'modes'})
      {
	  print "\n\nDefined language modes:\n";
	  print "-----------------------\n";
	  print "(You may use any of the names seperated\n";
	  print "by commas to refer to a certain mode.)\n\n";
      };
    
    for (@CONFIG_FILES)
      {
	  print "in file $_:\n" if $PARAMS{'modes'};

	  $result = &get_one_config_file($_, quotemeta($PARAMS{'langmode'}), $PARAMS{'modes'});
	  if ($result ne "") {last;};
      };

    if ($result eq "")
      {
	  print "in default database:\n" if $PARAMS{'modes'};
	  
	  my @lines = split(/\n/,&get_default_database);
	  $result = &get_config_lines(\@lines, quotemeta($PARAMS{'langmode'}), $PARAMS{'modes'});
      }
    
    if ($PARAMS{'modes'})
      {
	  print "-----------------------\n";
	  print "That's it\n\n\n";
	  exit;
      };


    if ($result eq "")
      {
	  if ($PARAMS{'alt_langmode'} ne "")
	    {
		warn("Given language mode '".$PARAMS{'langmode'}."' was not found in config files. Falling back to '".$PARAMS{'alt_langmode'}."'.\n");
		$PARAMS{'langmode'    } = $PARAMS{'alt_langmode'};
		$PARAMS{'alt_langmode'} = "";
		$result = get_config_file(\@CONFIG_FILES, \%PARAMS);
	    }
	  else
	    {
		die("Given language mode '".$PARAMS{'langmode'}."' was not found in config files.\n");
	    };
      }

    return $result;
};


################################################################################
####################### parse_config_part ######################################
################################################################################
sub parse_config_part
{
    #in: string: config data
    #in: string: bgcolor
    #in: string: textcolor
    #returns @regexps
    
    my ($configdata, $bgcolor, $textcolor) = @_;

    my @regexps = ();
	
    while ($configdata =~ /(^[^\-].*?$)/gms) # )
	   {
	       my $us = $1;
	       my $after = substr($configdata, pos($configdata));
	       
	       if ($us =~ /^"/) #";# xemacs :)
		   {
		       my %t = ();
		       my $tmp = "";
		       my @child = ();
		       
		       $us =~ s/([ \t]*("([^"]|\\")*")[ \t]*,)//m; $tmp = $1; $tmp =~ m/("(.*[^\\])?")/; $tmp = $1; $tmp =~ s/"(.*)"/$1/g; $tmp =~ s/\\"/"/g; $t{"html1"}   = $tmp;
		       $us =~ s/([ \t]*("([^"]|\\")*")[ \t]*,)//m; $tmp = $1; $tmp =~ m/("(.*[^\\])?")/; $tmp = $1; $tmp =~ s/"(.*)"/$1/g; $tmp =~ s/\\"/"/g; $t{"html2"}   = $tmp;
             	       $us =~ s/([ \t]*("([^"]|\\")*")[ \t]*$)//m; $tmp = $1; $tmp =~ m/("(.*[^\\])?")/; $tmp = $1; $tmp =~ s/"(.*)"/$1/g; $tmp =~ s/\\"/"/g; $t{"regex"}   = $tmp;
	       
            	       if ($after =~ /(^\n\-.*?($|\n[^\-]))/s)
			 {
			     $tmp = $1;
			     $tmp =~ s/^\n//;
			     $tmp =~ s/\n.$//;
			     $tmp =~ s/^-[ \t]*//mg;

			     @child = &parse_config_part($tmp."\n");
			 };

              	       $t{"childregex"} = \@child;
	               push @regexps, \%t;
           	   }
               else
	           {
		       if ($us =~ s/^bgcolor[ \t]*=[ \t]*//i)
			 {
			     $_[1] = $us;
			 }
		       elsif ($us =~ s/^textcolor[ \t]*=[ \t]*//i)
			 {
			     $_[2] = $us;
			 }
		   };
       };

    return @regexps;
};

################################################################################
####################### checkTabulator #########################################
################################################################################
sub checkTabulator
{
    my ($line, $TABSTOP) = @_;
    
    while ((my $at = index($line, "\t")) != -1)
      {
	  my $cnt = ($TABSTOP - ($at % $TABSTOP));
	  my $replace_with = ' ' x $cnt if ($cnt);
	  $line =~ s/\t/$replace_with/;
      };

    return $line;
}

################################################################################
####################### get_input_file #########################################
################################################################################
sub get_input_file
{

    # in  : \%params
    # out : hidechar
    # returns: input file
    
    my %PARAMS       = %{$_[0]};
    my $code;
    my $hidechar = "";



    if (defined($PARAMS{'input'}) && ($PARAMS{'input'} ne ""))
      {
	  $code = $PARAMS{'input'};
	  $code =~ s/\r//g;
      }
    else
      {
	  open(FILEHANDLE, $PARAMS{'infile'}) || die("Error while opening inputfile.\n");
	  undef $/; $code = <FILEHANDLE>;
	  close(FILEHANDLE);
      };
    
    if ($PARAMS{'replacetabs'} != 0)
      {
	  my @lines = split(/\n/, $code);
	  for (@lines)
	    {
		$_ = &checkTabulator($_, $PARAMS{'replacetabs'});
	    };
	  $code = join("\n", @lines);
#	  my $replacewith = " " x $PARAMS{'replacetabs'};
#	  $code =~ s/\t/$replacewith/g;
      };


    #find a character that does not exist in $code
    foreach $a (0..255) {
	my $n = quotemeta(chr($a));
	if (!($code =~ s/$n/$n/g))
	  {
	      $_[1] = chr($a);
	      last;
	  };
    };

    if ($_[1] eq "") # if no character - which does not exist in $code - was found then be brute
      {
	  $code =~ s/\xff/\xfe/g;
	  $_[1] = "\xff";
      }

    return $code;
};


################################################################################
####################### find_all_matches__create_taglist__insert_placeholders ##
################################################################################
sub find_all_matches__create_taglist__insert_placeholders
  {
      # in: regexps
      # in/out: code
      # in : hidechar
      # returns: @taglist;
      
      my @regexps  = @{$_[0]};
      my $code     = $_[1];
      my $hidechar = $_[2];
      my @taglist;

      if (!@regexps) {return @taglist}; #if there are no regexps, then there are not hits.


      my $over_length = length($code)+1;
      my $index=0;
      my @regexps_occurence;
      
      for (@regexps)
	{
	    my %t;
	    $t{"index"} = $index;
	    $t{"regex"} = $$_{"regex"};
	    $t{"html1"} = $$_{"html1"};
	    $t{"html2"} = $$_{"html2"};
	    
	    pos($code) = 0;
	    if ($code =~ /$t{"regex"}/gms)
	      { $t{"first_occurence"} = pos($code) - length($&) }
	    else 
	      { $t{"first_occurence"} = $over_length;           };
	    push @regexps_occurence, \%t;
	    $index++;
	};
      @regexps_occurence = sort {  $$a{"first_occurence"} <=> $$b{"first_occurence"} || $$a{"index"} <=> $$b{"index"} }  @regexps_occurence;
      
      while (${$regexps_occurence[0]}{"first_occurence"} < $over_length)
        {
	    my %t;
      
	    pos($code) = ${$regexps_occurence[0]}{"first_occurence"} + scalar(@taglist);

            my $dummy = $code =~ /${$regexps_occurence[0]}{"regex"}/gms;

            my $match        = $&;
	    my $matchend     = pos($code);
	    my $matchlength  = length($match);
	    my $delta_offset = 0;

            push @taglist, ${$regexps_occurence[0]}{"html1"}; #push beginning html tag

	    my @m = @{  ${  %{$regexps[${$regexps_occurence[0]}{"index"}]}  }{"childregex"}  };
	    if (@m)
	      {
		  my @newtaglist = &find_all_matches__create_taglist__insert_placeholders(
											  \@m,
											  $match,
											  $hidechar);
		  $delta_offset = scalar(@newtaglist);
		  push @taglist, @newtaglist;
	      };

	    $code = substr($code, 0, $matchend-$matchlength) .
	      $hidechar .
	      $match .
	      $hidechar .
	      substr($code, $matchend);
	    
	    push @taglist, ${$regexps_occurence[0]}{"html2"}; #push ending html tag

            for (@regexps_occurence)
              {
		  if (${$_}{"first_occurence"} < $matchend+2+$delta_offset - scalar(@taglist))
                    {
			pos($code) = $matchend+2+$delta_offset;
			if ($code =~ /${$_}{"regex"}/gms) 
                          { ${$_}{"first_occurence"} = pos($code) - length($&) - scalar(@taglist); }
                        else 
                          { ${$_}{"first_occurence"} = $over_length;                               };
		    }
		  else 
                    {
			last;
		    }
	      }
	      @regexps_occurence = sort { $$a{"first_occurence"} <=> $$b{"first_occurence"} || $$a{"index"} <=> $$b{"index"} } @regexps_occurence;
	  };
	

	$_[1] = $code;
	return @taglist;
};

################################################################################
####################### convert_code_2_html ####################################
################################################################################
sub convert_code_2_html
{
	# in: code
	# returns: code

	my $code = $_[0];

	$code =~ s/&/&amp;/g;
	$code =~ s/>/&gt;/g;
	$code =~ s/</&lt;/g;
	$code =~ s/"/&quot;/g;     # "# just because xemacs syntax highlighting messes things up

	return $code;
};

################################################################################
####################### insert_tags ############################################
################################################################################
sub insert_tags
{
	# in: taglist
	# in: code
	# in: hidechar
	# returns: code

	my @taglist = @{$_[0]};
	my $tmp = $_[1];
	my $hidechar = $_[2];

	my $newcode = "";
	
	for (@taglist) # go for all tags
	{
		# This goes must faster than
		# $code =~ s/$hidechar/$_/;

		$tmp =~ m/(^.*?)$hidechar(.*)/s;
		$newcode .= $1.$_;
		$tmp = $2;
	};

	return $newcode.$tmp;
};

################################################################################
####################### put_output #############################################
################################################################################
sub prettyprint
{
  # don't ask me what happens if $nr does not fit into $lengthofnr chars!
  my ($nr, $lengthofnr) = @_;

  my $result = " " x $lengthofnr;

  substr($result, -length($nr)) = $nr;

  return $result;
}

sub put_output
{	
      my %PARAMS = %{shift()};
      my ($code, $bgcolor, $textcolor) = @_;

      my $text = '';
      $text .= "Content-Type: text/html;\n\n"                                                  if ($PARAMS{'content_type'});
      $text .= "<html><head><title>".
               ($PARAMS{'outfile'} eq '-' ? 'STDIN' : $PARAMS{'outfile'} eq '-').
               "</title></head><body bgcolor=\"$bgcolor\" text=\"$textcolor\"><pre>\n"         if (!$PARAMS{'noheader'});


	
      my @lines = split(/\n/,$code);
      my $nr = 1;

      my $nr_of_lines = scalar(@lines);
      my $lengthofnr = 0;
      while ($nr_of_lines>1)
	{
	    $lengthofnr++;
	    $nr_of_lines = $nr_of_lines / 10;
	};
 
      my $prefix = '';
      $prefix = $PARAMS{'line_number_prefix'}.'_' if defined $PARAMS{'line_number_prefix'};
      for (@lines)
	{
	    if ($PARAMS{'linenumbers'} eq 'link')
	      { $text .= '<a name="'.$prefix.'line'.$nr.'" href="#'.$prefix.'line'.$nr.'">'.&prettyprint($nr, $lengthofnr).'</a>  '.$_."\n"; }
	    elsif ($PARAMS{'linenumbers'} eq 'yes')
	      { $text .= '<a name="'.$prefix.'line'.$nr.'">'.&prettyprint($nr, $lengthofnr).'</a>  '.$_."\n"; }
	    else
	      { $text .= '<a name="'.$prefix.'line'.$nr.'">'.$_."</a>\n"; };
	    $nr++;
	}

      
      $text .= "</pre></body></html>\n"          if (!$PARAMS{'no_header'});



      if (defined($PARAMS{'outfile'}))
	{
	    open (FILEHANDLE, ">".$PARAMS{'outfile'}) || die("Error while opening outputfile.\n");
	    print FILEHANDLE $text;
	    close (FILEHANDLE);
	};
      return $text;
  };

################################################################################
####################### get_default_database ###################################
################################################################################
sub get_default_database
{
# last evaluated value will be returned
my $tmp = <<'EODB';
######################################################################
################################# Plain ##############################
######################################################################
[plain]
bgcolor=#ffffff
textcolor=#000000

######################################################################
################################# Ada 95 #############################
######################################################################
[ada,ada95]
bgcolor=#ffffff
textcolor=#000000

#Comments
	"<font color=\"#444444\">", "</font>", "--.*?$"
#String Literals
	"<font color=\"#008000\">", "</font>", "\".*?(\"|$)"
#Character Literals
	"<font color=\"#008000\">", "</font>", "'.'"
#Ada Attibutes
	"<strong>", "</strong>", "'[a-zA-Z][a-zA-Z_]+\b"
#Numeric Literals
	"<font color=\"#FF0000\">", "</font>", "(((2|8|10|16)#[_0-9a-fA-F]*#)|[0-9.]+)"
#Withs Pragmas Use
	"<font color=\"#0000FF\"><strong>", "</strong></font>", "\b(([wW]ith|WITH|[pP]ragma|PRAGMA|[uU]se|USE)[ \t\n\f\r]+[a-zA-Z0-9_.]+;)+\b"
#Predefined Types
	"<font color=\"#800000\"><strong>", "</strong></font>", "\b([bB]oolean|BOOLEAN|[cC]haracter|CHARACTER|[cC]ount|COUNT|[dD]uration|DURATION|[fF]loat|FLOAT|[iI]nteger|INTEGER|[lL]ong_[fF]loat|LONG_FLOAT|[lL]ong_[iI]nteger|LONG_INTEGER|[pP]riority|PRIORITY|[sS]hort_[fF]loat|SHORT_FLOAT|[sS]hort_[iI]nteger|SHORT_INTEGER|[sS]tring|STRING)\b"
#Predefined Subtypes
	"<font color=\"#800000\"><strong>", "</strong></font>", "\b([fF]ield|FIELD|[nN]atural|NATURAL|[nN]umber_[bB]ase|NUMBER_BASE|[pP]ositive|POSITIVE|[pP]riority|PRIORITY)\b"
#Reserved Words
	"<strong>", "</strong>", "\b([aA]bort|ABORT|[aA]bs|ABS|[aA]ccept|ACCEPT|[aA]ccess|ACCESS|[aA]nd|AND|[aA]rray|ARRAY|[aA][tT]|[bB]egin|BEGIN|[bB]ody|BODY|[cC]ase|CASE|[cC]onstant|CONSTANT|[dD]eclare|DECLARE|[dD]elay|DELAY|[dD]elta|DELTA|[dD]igits|DIGITS|[dD][oO]|[eE]lse|ELSE|[eE]lsif|ELSIF|[eE]nd|END|[eE]ntry|ENTRY|[eE]xception|EXCEPTION|[eE]xit|EXIT|[fF]or|FOR|[fF]unction|FUNCTION|[gG]eneric|GENERIC|[gG]oto|GOTO|[iI][fF]|[iI][nN]|[iI][sS]|[lL]imited|LIMITED|[lL]oop|LOOP|[mM]od|MOD|[nN]ew|NEW|[nN]ot|NOT|[nN]ull|NULL|[oO][fF]|[oO][rR]|[oO]thers|OTHERS|[oO]ut|OUT|[pP]ackage|PACKAGE|[pP]ragma|PRAGMA|[pP]rivate|PRIVATE|[pP]rocedure|PROCEDURE|[rR]aise|RAISE|[rR]ange|RANGE|[rR]ecord|RECORD|[rR]em|REM|[rR]enames|RENAMES|[rR]eturn|RETURN|[rR]everse|REVERSE|[sS]elect|SELECT|[sS]eparate|SEPARATE|[sS]ubtype|SUBTYPE|[tT]ask|TASK|[tT]erminate|TERMINATE|[tT]hen|THEN|[tT]ype|TYPE|[uU]se|USE|[wW]hen|WHEN|[wW]hile|WHILE|[wW]ith|WITH|[xX]or|XOR)\b"
#Ada 95 Only
	"<strong>", "</strong>", "\b([aA]bstract|ABSTRACT|[tT]agged|TAGGED|[aA]ll|ALL|[pP]rotected|PROTECTED|[aA]liased|ALIASED|[rR]equeue|REQUEUE|[uU]ntil|UNTIL)\b"
#Identifiers
	"<font color=\"#800000\">", "</font>", "\b[a-zA-Z][a-zA-Z0-9_]*\b"
#Dot All
	"<font color=\"#800000\"><strong>", "</strong></font>", "\.[aA][lL][lL]\b"


######################################################################
################################# C ##################################
######################################################################
[c]
bgcolor=#ffffff
textcolor=#000000

#comment
	"<font color=\"#444444\">", "</font>", "/\*.*?\*/"
#string
	"<font color=\"#008000\">", "</font>", "((\"\")|(\"\\\\\")|(\"[^\"\\]\")|(\"[^\"].*?[^\\]\"))"
	#esc character
	-	"<font color=\"#77dd77\">", "</font>", "\\."
#preprocessor line
	"<font color=\"#0000FF\">", "</font>", "^[ \t]*#.*?$"
	#string
	-	"<font color=\"#008000\">", "</font>", "((\"\")|(\"\\\\\")|(\"[^\"\\]\")|(\"[^\"].*?[^\\]\"))"
		#esc character
		--	"<font color=\"#77dd77\">", "</font>", "\\."
        #<files>
        -      "<font color=\"#008000\">", "</font>", "<.*?>"
	#comment
	-	"<font color=\"#444444\">", "</font>", "[^/]/\*.*?\*/"
#character constant
	"<font color=\"#008000\">", "</font>", "'(\\)?.'"
	#esc character
	-	"<font color=\"#77dd77\">", "</font>", "\\."
#numeric constant
	"<font color=\"#FF0000\">", "</font>", "\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f)?\b"
#storage keyword
	"<strong>", "</strong>", "\b(const|extern|auto|register|static|unsigned|signed|volatile|char|double|float|int|long|short|void|typedef|struct|union|enum)\b"
#keyword
	"<strong>", "</strong>", "\b(return|goto|if|else|case|default|switch|break|continue|while|do|for|sizeof)\b"
#braces
	"<font color=\"#4444FF\"><strong>", "</strong></font>", "[\{\}]"
#symbols
	"<font color=\"#4444FF\">", "</font>", "([\*\-\+=:;%&\|<>\(\)\[\]!])"
#identifiers
	"<font color=\"#993333\">", "</font>", "([a-zA-Z_][a-zA-Z_0-9]*)"



######################################################################
################################# C ++ ###############################
######################################################################
[c++,cpp,cc]
bgcolor=#ffffff
textcolor=#000000

#comment
	"<font color=\"#444444\">", "</font>", "/\*.*?\*/"
#cplus comment
	"<font color=\"#444444\">", "</font>", "//.*?$"
#string
	"<font color=\"#008000\">", "</font>", "((\"\")|(\"\\\\\")|(\"[^\"\\]\")|(\"[^\"].*?[^\\]\"))"
	#esc character
	-	"<font color=\"#77dd77\">", "</font>", "\\."
#preprocessor line
	"<font color=\"#0000FF\">", "</font>", "^[ \t]*#.*?$"
	#string
	-	"<font color=\"#008000\">", "</font>", "((\"\")|(\"[^\"\\]\")|(\"[^\"].*?[^\\]\"))"
		#esc character
		--	"<font color=\"#77dd77\">", "</font>", "\\."
        #<files>
        -      "<font color=\"#008000\">", "</font>", "<.*?>"
	#comment
	-	"<font color=\"#444444\">", "</font>", "[^/]/\*.*?\*/"
	#cplus comment
	-	"<font color=\"#444444\">", "</font>", "//.*?$"
#character constant
	"<font color=\"#008000\">", "</font>", "'(\\)?.'"
	#esc character
	-	"<font color=\"#77dd77\">", "</font>", "\\."
#numeric constant
	"<font color=\"#FF0000\">", "</font>", "\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f)?\b"
#storage keyword
	"<strong>", "</strong>", "\b(class|typename|typeid|template|friend|virtual|inline|explicit|operator|overload|public|private|protected|const|extern|auto|register|static|mutable|unsigned|signed|volatile|char|double|float|int|long|short|bool|wchar_t|void|typedef|struct|union|enum)\b"
#keyword
	"<strong>", "</strong>", "\b(new|delete|this|return|goto|if|else|case|default|switch|break|continue|while|do|for|catch|throw|sizeof|true|false|namespace|using|dynamic_cast|static_cast|reinterpret_cast)\b"
#braces
	"<font color=\"#4444FF\"><strong>", "</strong></font>", "[\{\}]"
#symbols
	"<font color=\"#4444FF\">", "</font>", "([\*\-\+=:;%&\|<>\(\)\[\]!])"
#identifiers
	"<font color=\"#993333\">", "</font>", "([a-zA-Z_][a-zA-Z_0-9]*)"


######################################################################
################################# HTML ###############################
######################################################################
[html]
bgcolor=#ffffff
textcolor=#000000

#comment
	"<font color=\"#444444\">", "</font>", "<!--.*?-->"
#special chars
	"<font color=\"#FF0000\">", "</font>", "\&[-.a-zA-Z0-9#]*;?"
#tag
	"<font color=\"#993333\">", "</font>", "<(/|!)?[-.a-zA-Z0-9]*.*?>"
	#double quote string
	-	"<font color=\"#008000\">", "</font>", "\".*?\""
	#single quote string
	-	"<font color=\"#008000\">", "</font>", "'.*?'"
	#brackets
	-	"<font color=\"#0000aa\"><strong>", "</strong></font>", "[<>]"
	#attribute
	-	"<font color=\"#0000ff\">", "</font>", "[^'\"]+?"


######################################################################
################################# Java ###############################
######################################################################
[java]
bgcolor=#ffffff
textcolor=#000000

#doc comment
	"<font color=\"#444444\"><i>", "</i></font>", "/\*\*.*?\*/"
#comment
	"<font color=\"#444444\">", "</font>", "/\*.*?\*/"
#cplus comment
	"<font color=\"#444444\">", "</font>", "//.*?$"
#string
	"<font color=\"#008000\">", "</font>", "((\"\")|(\"\\\\\")|(\"[^\"\\]\")|(\"[^\"].*?[^\\]\"))"
	#esc character
	-	"<font color=\"#77dd77\">", "</font>", "\\."
#single quoted
	"<font color=\"#008000\">", "</font>", "'([^\\]|\\[^'])*?'"
#numeric constant
	"<font color=\"#FF0000\">", "</font>", "\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f)?\b"
#include
	"<font color=\"#0000FF\">", "</font>", "\b(import|package)\b.*?$"
	#esc character
	-	"<font color=\"#3333FF\">", "</font>", "\\(.|\n)"
	#comment
	-	"<font color=\"#444444\">", "</font>", "[^/]/\*.*?\*/"
#storage keyword
	"<strong>", "</strong>", "\b(abstract|boolean|byte|char|class|double|extends|final|float|int|interface|long|native|private|protected|public|short|static|transient|synchronized|void|volatile|implements)\b"
#keyword
	"<strong>", "</strong>", "\b(break|case|catch|continue|default|do|else|false|finally|for|if|instanceof|new|null|return|super|switch|this|throw|throws|true|try|while)\b"
#braces and parens
	"<strong>", "</strong>", "[\{\}\(\)\[\]]"
#Identifiers
	"<font color=\"#800000\">", "</font>", "\b[a-zA-Z_][a-zA-Z0-9_]*\b"
#symbols
	"<font color=\"#4444FF\">", "</font>", "([\*\-\+=:;%&\|<>!])"


######################################################################
################################# JavaScript #########################
######################################################################
[js,javascipt]
bgcolor=#ffffff
textcolor=#000000

#comment
	"<font color=\"#444444\">", "</font>", "/\*.*?\*/"
#cplus comment
	"<font color=\"#444444\">", "</font>", "//.*?$"
#numeric constant
	"<font color=\"#FF0000\">", "</font>", "\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f)?\b"
#events
	"<strong>", "</strong>", "\b(onAbort|onBlur|onClick|onChange|onDblClick|onDragDrop|onError|onFocus|onKeyDown|onKeyPress|onLoad|onMouseDown|onMouseMove|onMouseOut|onMouseOver|onMouseUp|onMove|onResize|onSelect|onSubmit|onUnload)\b"
#braces
	"<font color=\"#4444FF\"><strong>", "</strong></font>", "[\{\}]"
#statements
	"<strong>", "</strong>", "\b(break|continue|else|for|if|in|new|return|this|typeof|var|while|with)\b"
#function
	"<strong>", "</strong>", "function[\t ]+([a-zA-Z0-9_]+)[\t \(]+.*?[\n{]"
	#function args
	-	"<font color=\"#2040a0\">", "</font>", "\(.*?\)"
	#function name
	-	"<font color=\"#a52a2a\">", "</font>", "[\t ][a-zA-Z0-9_]+"
#built in object type
	"<font color=\"#a52a2a\"><strong>", "</strong></font>", "\b(anchor|Applet|Area|Array|button|checkbox|Date|document|elements|FileUpload|form|frame|Function|hidden|history|Image|link|location|Math|navigator|Option|password|Plugin|radio|reset|select|string|submit|text|textarea|window)\b"
#string
	"<font color=\"#008000\">", "</font>", "\".*?(\"|$)"
	#Colors
	-	"<font color=\"#4682B4\">", "</font>", "(aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|#008000|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen|#[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9])"
#string
	"<font color=\"#008000\">", "</font>", "'.*?('|$)"
	#Colors
	-	"<font color=\"#4682B4\">", "</font>", "(aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|#008000|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen|#[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9])"
#event capturing
	"<strong>", "</strong>", "\b(captureEvents|releaseEvents|routeEvent|handleEvent)\b.*?(\)|$)"
#predefined methods
	"<strong>", "</strong>", "\b(abs|acos|alert|anchor|asin|atan|atan2|back|big|blink|blur|bold|ceil|charAt|clear|clearTimeout|click|close|confirm|cos|escape|eval|exp|fixed|floor|focus|fontcolor|fontsize|forward|getDate|getDay|getHours|getMinutes|getMonth|getSeconds|getTime|getTimezoneOffset|getYear|go|indexOf|isNaN|italics|javaEnabled|join|lastIndexOf|link|log|max|min|open|parse|parseFloat|parseInt|pow|prompt|random|reload|replace|reset|reverse|round|scroll|select|setDate|setHours|setMinutes|setMonth|setSeconds|setTimeout|setTime|setYear|sin|small|sort|split|sqrt|strike|sub|submit|substring|sup|taint|tan|toGMTString|toLocaleString|toLowerCase|toString|toUpperCase|unescape|untaint|UTC|write|writeln)\b"
#properties
	"<font color=\"#a52a2a\"><strong>", "</strong></font>", "\b(action|alinkColor|anchors|appCodeName|appName|appVersion|bgColor|border|checked|complete|cookie|defaultChecked|defaultSelected|defaultStatus|defaultValue|description|E|elements|enabledPlugin|encoding|fgColor|filename|forms|frames|hash|height|host|hostname|href|hspace|index|lastModified|length|linkColor|links|LN2|LN10|LOG2E|LOG10E|lowsrc|method|name|opener|options|parent|pathname|PI|port|protocol|prototype|referrer|search|selected|selectedIndex|self|SQRT1_2|SQRT2|src|status|target|text|title|top|type|URL|userAgent|value|vlinkColor|vspace|width|window)\b"
#operators
	"<font color=\"#4444FF\">", "</font>", "([=;->/&|])"

######################################################################
################################# Makefile ###########################
######################################################################
[make,makefile]
bgcolor=#ffffff
textcolor=#000000

#comment
	"<font color=\"#444444\">", "</font>", "#.*?$"
#Assignment
	"<font color=\"#2040a0\">", "</font>", "^( *| [ \t]*)[A-Za-z0-9_+]*[ \t]*(\+|:)?="
#Dependency Line
	"<font color=\"#8b2252\">", "</font>", "^ *([A-Za-z0-9./$(){} _%+-]|\n)*::?"
	#Dependency Target
	-	"<strong>", "</strong>", "[A-Za-z0-9./$(){} _%+-]+"
	#Dependency continuation
	-	"<font color="#000000"><strong>", "</strong></font>", "\\\n"
	#comment
	-	"<font color=\"#444444\">", "</font>", "#.*?$"
	#macro
	-	"<font color=\"#2040a0\">", "</font>", "\$([A-Za-z0-9_]|\([^)]*\)|{[^}]*})"
	#int macro
	-	"<font color=\"#4080ff\">", "</font>", "\$([<@*?%]|\$@)"
#Continuation
	"<strong>", "</strong>", "\\$"
#Macro
	"<font color=\"#2040a0\">", "</font>", "\$([A-Za-z0-9_]|\([^)]*\)|{[^}]*})"
#Internal Macro
	"<font color=\"#4080FF\">", "</font>", "\$([<@*?%]|\$@)"
#Escaped Dollar
	"<font color=\"#444444\">", "</font>", "\$\$"
#Include
	"<strong>", "</strong>", "^include[ \t]"


######################################################################
################################# Pascal #############################
######################################################################
[pas,pascal]
bgcolor=#ffffff
textcolor=#000000

#comment1 (*    *)
	"<font color=\"#444444\">", "</font>", "\(\*.*?\*\)"
#comment1 {      }
	"<font color=\"#444444\">", "</font>", "\{.*?\}"
#string
	"<font color=\"#008000\">", "</font>", "'.*?('|$)"
#preprocessor line
	"<font color=\"#0000FF\">", "</font>", "^[ \t]*#.*?$"
	#comment1 (*    *)
	-	"<font color=\"#444444\">", "</font>", "\(\*.*?\*\)"
	#comment1 {      }
	-	"<font color=\"#444444\">", "</font>", "\{.*?\}"
#character constant
	"<font color=\"#008000\">", "</font>", "'.'"
#numeric constant
	"<font color=\"#FF0000\">", "</font>", "\b((0(x|X)[0-9a-fA-F]*)|[0-9.]+((e|E)(\+|-)?)?[0-9]*)(L|l|UL|ul|u|U|F|f)?\b"
#storage and ops
	"<strong>", "</strong>", "\b(and|AND|array|const|div|export|file|function|import|in|IN|label|mod|module|nil|not|NOT|only|or|OR|packed|pow|pragma|procedure|program|protected|qualified|record|restricted|set|type|var)\b"
#keywords
	"<strong>", "</strong>", "\b(begin|case|do|downto|else|end|for|goto|if|of|otherwise|repeat|then|to|until|while|with)\b"
#symbols
	"<font color=\"#4444FF\">", "</font>", "([\*\-\+=:;<>\(\)\[\]!]|[^/]/[^/])"
#identifiers
	"<font color=\"#993333\">", "</font>", "([a-zA-Z_][a-zA-Z_0-9.^]*[a-zA-Z_0-9]|[a-zA-Z_][a-zA-Z_0-9]*)"
	#dot, carret(sp?)
	-	"<font color=\"#4444FF\">", "</font>", "(\.|\^)+"


######################################################################
################################# Perl ###############################
######################################################################
[perl]
bgcolor=#ffffff
textcolor=#000000

#comment
	"<font color=\"#444444\">", "</font>", "#.*?$"
#variables
	"<font color=\"2040a0\">", "</font>", "[$@%]\$?({[^}]*}|[^a-zA-Z0-9_/\t\n\.,\\[\\{\\(]|[0-9]+|[a-zA-Z_][a-zA-Z0-9_]*)?"
#string; so this part realy is weird, but it works!
	"<font color=\"#008000\">", "</font>", "((\"\")|(\"\\\\\")|(\"[^\"\\]\")|(\"[^\"].*?[^\\]\"))"
	#esc character
	-	"<font color=\"#77dd77\">", "</font>", "\\."
	#variables
	-	"<font color=\"2040a0\">", "</font>", "[$@%]\$?({[^}]*}|[^a-zA-Z0-9_/\t\n\.,\\[\\{\\(]|[0-9]+|[a-zA-Z_][a-zA-Z0-9_]*)?"
#string; so this part realy is weird, but it works!
	"<font color=\"#008000\">", "</font>", "(('')|('\\\\')|('[^'\\]')|('[^'].*?[^\\]'))"
	#esc character
	-	"<font color=\"#77dd77\">", "</font>", "\\."

#more strings - q// qw//
	"<font color=\"#008000\">", "</font>", "(?:\b| )(?:q|qw)(\W)(\\\1|[^\1\n])*(\1)"
	#esc character
	-	"<font color=\"#77dd77\">", "</font>", "\\."

#more strings qq// qx//
	"<font color=\"#008000\">", "</font>", "(?:\b| )(?:qq|qx)(\W)(\\\1|[^\1\n])*(\1)"
	#esc character
	-	"<font color=\"#77dd77\">", "</font>", "\\."
	#variables
	-	"<font color=\"2040a0\">", "</font>", "[$@%]\$?({[^}]*}|[^a-zA-Z0-9_/\t\n\.,\\[\\{\\(]|[0-9]+|[a-zA-Z_][a-zA-Z0-9_]*)?"

#subroutine header
	"<strong>", "</strong>", "sub[\t ]+([a-zA-Z0-9_]+)[\t \n]*(\{|\n)"
	#subr header coloring
	-	"<font color=\"#ff0000\">", "</font>", "[\t ]([a-zA-Z0-9_]+)"
#ignore escaped chars
#	"", "", "\\[#"'\$msytq]"
#regex matching
#	"<font color=\"#b000d0\">", "</font>", "(\b| )((m|q|qq)?/)(\\/|[^/\n])*(/[gimsox]*)"
	"<font color=\"#b000d0\">", "</font>", "(\b| )?(/)(\\/|[^/\n])*(/[gimsox]*)"
	"<font color=\"#b000d0\">", "</font>", "(?:\b| )(?:(?:m|q|qq)(\W))(\\\1|[^\1\n])*(\1[gimsox]*)"
#regex substitution
#	"<font color=\"#b000d0\">", "</font>", "(\b| )((s|y|tr)/)(\\/|[^/\n])*(/)[^/\n]*(/[gimsox]*)"
	"<font color=\"#b000d0\">", "</font>", "(?:\b| )?(?:s(\W))(?:\\\1|[^\1\n])*?(\1)[^(\1)\n]*?(\1[gimsox]*)"
#translate
	"<font color=\"#b000d0\">", "</font>", "(?:\b| )(?:(?:tr|y)(\W))(?:\\\1|[^\1\n])*?(\1)[^(\1)\n]*?(\1[gimsox]*)"

#keywords
	"<strong>", "</strong>", "\b(my|local|new|if|until|while|elsif|else|eval|unless|for|foreach|continue|exit|die|last|goto|next|redo|return|local|exec|do|use|require|package|eval|BEGIN|END|eq|ne|not|\|\||\&\&|and|or)\b"
#library fns
	"<font color=\"a52a2a\"><strong>", "</strong></font>", "\b(abs|accept|alarm|atan2|bind|binmode|bless|caller|chdir|chmod|chomp|chop|chr|chroot|chown|closedir|close|connect|cos|crypt|dbmclose|dbmopen|defined|delete|die|dump|each|endgrent|endhostent|endnetent|endprotoent|endpwent|endservent|eof|exec|exists|exp|fctnl|fileno|flock|fork|format|formline|getc|getgrent|getgrgid|getgrnam|gethostbyaddr|gethostbyname|gethostent|getlogin|getnetbyaddr|getnetbyname|getnetent|getpeername|getpgrp|getppid|getpriority|getprotobyname|getprotobynumber|getprotoent|getpwent|getpwnam|getpwuid|getservbyname|getservbyport|getservent|getsockname|getsockopt|glob|gmtime|grep|hex|import|index|int|ioctl|join|keys|kill|lcfirst|lc|length|link|listen|log|localtime|lstat|map|mkdir|msgctl|msgget|msgrcv|no|oct|opendir|open|ord|pack|pipe|pop|pos|printf|print|push|quotemeta|rand|readdir|read|readlink|recv|ref|rename|reset|reverse|rewinddir|rindex|rmdir|scalar|seekdir|seek|select|semctl|semget|semop|send|setgrent|sethostent|setnetent|setpgrp|setpriority|setprotoent|setpwent|setsockopt|shift|shmctl|shmget|shmread|shmwrite|shutdown|sin|sleep|socket|socketpair|sort|splice|split|sprintf|sqrt|srand|stat|study|substr|symlink|syscall|sysopen|sysread|system|syswrite|telldir|tell|tie|tied|time|times|truncate|uc|ucfirst|umask|undef|unlink|unpack|unshift|untie|utime|values|vec|wait|waitpid|wantarray|warn|write|qw|-[rwxoRWXOezsfdlpSbctugkTBMAC])\b"
#braces and parens
	"<strong>", "</strong>", "[\[\]\{\}\(\)]"
#<< stuff
	"<i>", "</i>", "<<'([^\n]*)';.*?^\1$"
	"<i>", "</i>", "<<([^\n]*).*?^\1$"


######################################################################
################################# sql ################################
######################################################################
[sql]
bgcolor=#ffffff
textcolor=#000000

#keywords
        "<font color=\"#0000FF\"><strong>", "</strong></font>", ",|%|<|>|:=|=|\(|\)|\b(SELECT|ON|FROM|ORDER BY|DESC|WHERE|AND|OR|NOT|NULL|TRUE|FALSE|select|on|from|order by|desc|where|and|or|not|null|true|false|Select|On|From|Order By|Desc|Where|And|Or|Not|Null|True|False)\b"
#comment
        "<font color=\"#444444\"><i>", "</i></font>", "--.*?$"
#comment
	"<font color=\"#444444\"><i>", "</i></font>", "/\*.*?\*/"
#string; so this part realy is weird, but it works!
	"<font color=\"#008000\">", "</font>", "(('')|('[^'\\]')|('[^'].*?[^\\]'))"
#keywords
        "<font color=\"#0000FF\"><strong>", "</strong></font>", "END IF;|End If;|end if;|\b(CREATE|REPLACE|BEGIN|END|FUNCTION|RETURN|FETCH|OPEN|CLOSE|INTO|IS|IN|WHEN|OTHERS|GRANT|ON|TO|EXCEPTION|SHOW|SET|OUT|PRAGMA|AS|PACKAGE|create|replace|begin|end|function|return|fetch|open|close|into|is|in|when|others|grant|on|to|exception|show|set|out|pragma|as|package|Create|Replace|Begin|End|Function|Return|Fetch|Open|Close|Into|Is|In|When|Others|Grant|On|To|Exception|Show|Set|Out|Pragma|As|Package)\b"
#keywords
        "<font color=\"#0000FF\"><strong>", "</strong></font>", "\b(ALTER|Alter|alter)\b"

#datatypes
        "<font color=\"#8800FF\">", "</font>", "\b(INTEGER|Integer|integer|BLOB|Blob|blobl|DATE|Date|date|NUMERIC|Numeric|numeric|CHARACTER|Character|character|VARYING|Varying|varying|VARCHAR|Varchar|varchar|CHAR|Char|char)\b"

#st
        "<font color=\"#0000FF\"><strong>", "</strong></font>", "\b(CONSTRAINT|Constraint|constraint|KEY|Key|key|CONSTRAINT|Constraint|constraint|REFERENCES|References|references|PRIMARY|Primary|primary|TABLE|Table|table|FOREIGN|Foreign|foreign|ADD|Add|add|INSERT|Insert|insert|GROUP BY|Group By|group by)\b"

######################################################################
EODB
;

};
