enscript.st - enscript - GNU Enscript
 (HTM) git clone git://thinkerwim.org/enscript.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       enscript.st (14227B)
       ---
            1 /*
            2  * States definitions file for GNU Enscript.
            3  * Copyright (c) 1997-2003 Markku Rossi.
            4  * Author: Markku Rossi <mtr@iki.fi>
            5  *
            6  * The latest version of this file can be downloaded from URL:
            7  *
            8  *     http://www.iki.fi/~mtr/genscript/enscript.st
            9  */
           10 
           11 /*
           12  * This file is part of GNU Enscript.
           13  *
           14  * Enscript is free software: you can redistribute it and/or modify
           15  * it under the terms of the GNU General Public License as published by
           16  * the Free Software Foundation, either version 3 of the License, or
           17  * (at your option) any later version.
           18  *
           19  * Enscript is distributed in the hope that it will be useful,
           20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
           21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
           22  * GNU General Public License for more details.
           23  *
           24  * You should have received a copy of the GNU General Public License
           25  * along with Enscript.  If not, see <http://www.gnu.org/licenses/>.
           26  */
           27 
           28 /*
           29  * $Id: enscript.st,v 1.3 2003/03/05 08:31:31 mtr Exp $
           30  */
           31 
           32 /*
           33  * Guildelines for writing new highlighting rules for the GNU Enscript.
           34  *
           35  * - all highlighting states should have a document comment like this:
           36  *
           37  *   /**
           38  *    * Name: c
           39  *    * Description: C programming language.
           40  *    * Author: Author Name <author@email.address>
           41  *    * ...
           42  *
           43  *   It is used by enscript's --help-pretty-print option to print
           44  *   description about supported highlighting modes.
           45  *
           46  * - the main entry state (for example, for the C, the state `c') must
           47  *   be inherited from state `HighlightEntry':
           48  *
           49  *   state c extends HighlightEntry
           50  *   {
           51  *     ...
           52  *
           53  * - all help-states smust be inherited from state `Highlight':
           54  *
           55  *   state c_string extends Highlight
           56  *   {
           57  *     ...
           58  *
           59  * - all printing should be done with the language_print() procedure
           60  *   instead of the print() primitive.
           61  *
           62  * - using enscript.el to build regular expressions:
           63  *
           64  *      M-x load-file RET enscript.el RET
           65  *
           66  *   Move in the buffer to the point where the (build-re '()) ends,
           67  *   that is, after the last closing parenthesis ')'.  Then, type:
           68  *
           69  *      C-x C-e
           70  *
           71  *   Magic should happen.
           72  *
           73  * These rules ensures that enscript's --help-pretty-print option and
           74  * the different output languages (HTML, RTF, etc.) work.
           75  */
           76 
           77 /* This script needs at least this version of the States program. */
           78 prereq ("1.6.2");
           79 
           80 /*
           81  * Constants, fonts, etc.
           82  */
           83 
           84 debug = "0";
           85 
           86 /* Boolean values. */
           87 true = 1;
           88 false = 0;
           89 
           90 font_spec = "Courier@10";
           91 
           92 /* These components are resolved from <font_spec>. */
           93 font = "";
           94 ptsize = "";
           95 
           96 /*
           97  * Generatel table of contents?  This is not supported by all output
           98  * languages.
           99  */
          100 toc = "0";
          101 
          102 /*
          103  * The Highlight style.  The default style is `emacs' to imitate
          104  * Emacs' font lock mode.
          105  */
          106 style = "emacs";
          107 
          108 /*
          109  * Create color outputs?
          110  */
          111 color = "1";
          112 
          113 /*
          114  * Use verbose highlighting rules?
          115  */
          116 verbose_highlighting = false;
          117 
          118 /*
          119  * Target language.  Possible values are:
          120  * - enscript                generate enscript special escapes
          121  * - html                generate HTML
          122  * - overstrike                generate overstrike (line printers, less)
          123  * - texinfo                generate Texinfo
          124  * - rtf                generate Rich Text Format (rtf - MS Word, WordPerfect)
          125  *                      This code can be souched into MS Word or PowerPoint
          126  *                      for a pretty version of the code
          127  */
          128 language = "enscript";
          129 
          130 /*
          131  * How many input files we have.
          132  */
          133 num_input_files = "1";
          134 current_input_file = 0;
          135 
          136 /*
          137  * Document title.
          138  */
          139 document_title = "Enscript Output";
          140 
          141 /*
          142  * Global variables for nested highlighting `nested.st'.
          143  */
          144 nested_start = "^-+(([ \t]*)([a-zA-Z_0-9]*)([ \t]*))-+$";
          145 nested_start_re = 0;
          146 nested_end = "^-+$";
          147 nested_end_re_cached = 0;
          148 nested_end_re = 0;
          149 nested_default = "passthrough";
          150 
          151 /*
          152  * Color definitions.
          153  */
          154 
          155 cindex = 0;
          156 rgb_values = list ();
          157 
          158 sub define_color (name, r, g, b)
          159 {
          160   rgb_values[cindex] = list (name, r, g, b);
          161   cindex = cindex + 1;
          162 }
          163 
          164 sub color_index (name)
          165 {
          166   local i;
          167 
          168   for (i = 0; i < length (rgb_values); i = i + 1)
          169     if (strcmp (rgb_values[i][0], name) == 0)
          170       return i;
          171 
          172   return -1;
          173 }
          174 
          175 sub language_color (name)
          176 {
          177   local idx;
          178 
          179   idx = color_index (name);
          180   if (idx < 0)
          181     panic ("unknown color `", name, "'");
          182 
          183   /*
          184    * The map_color() subroutine is language specific and defined in
          185    * *_faces() subroutine.
          186    */
          187   map_color (rgb_values[idx][1], rgb_values[idx][2], rgb_values[idx][3]);
          188 }
          189 
          190 /* RGB definitions for colors.        These are borrowed from X's rgb.txt file. */
          191 
          192 define_color ("black",                        0, 0, 0);
          193 define_color ("gray25",                        64, 64, 64);
          194 define_color ("gray50",                        127, 127, 127);
          195 define_color ("gray75",                        191, 191, 191);
          196 define_color ("gray85",                        217, 217, 217);
          197 define_color ("gray90",                        229, 229, 229);
          198 define_color ("gray95",                        242, 242, 242);
          199 define_color ("blue",                        0, 0, 255);
          200 define_color ("cadet blue",                95, 158, 160);
          201 define_color ("dark goldenrod",                184, 134, 11);
          202 define_color ("dark olive green",        85, 107, 47);
          203 define_color ("firebrick",                178, 34, 34);
          204 define_color ("forest green",                34, 139, 34);
          205 define_color ("green",                        0, 255, 0);
          206 define_color ("orchid",                        218, 112, 214);
          207 define_color ("purple",                        160, 32, 240);
          208 define_color ("red",                        255, 0, 0);
          209 define_color ("rosy brown",                188, 143, 143);
          210 
          211 define_color ("DarkSeaGreen",                143, 188, 143);
          212 define_color ("DarkSeaGreen1",                193, 255, 193);
          213 define_color ("DarkSeaGreen2",                180, 238, 180);
          214 define_color ("DarkSeaGreen3",                155, 205, 155);
          215 define_color ("DarkSeaGreen4",                105, 139, 105);
          216 define_color ("Goldenrod",                237, 218, 116);
          217 define_color ("Aquamarine",                67, 183, 186);
          218 define_color ("SeaGreen2",                100, 233, 134);
          219 define_color ("Coral",                        247, 101,  65);
          220 define_color ("DarkSlateGray1",                154, 254, 255);
          221 define_color ("LightGrey",                211, 211, 211);
          222 
          223 
          224 /*
          225  * General helpers.
          226  */
          227 
          228 sub debug (msg)
          229 {
          230   if (debug_level)
          231     print ("DEBUG: ", msg, "\n");
          232 }
          233 
          234 sub is_prefix (prefix, string)
          235 {
          236   return strncmp (prefix, string, length (prefix)) == 0;
          237 }
          238 
          239 sub strchr (string, ch)
          240 {
          241   local len = length (string), i;
          242 
          243   for (i = 0; i < len; i = i + 1)
          244     if (string[i] == ch)
          245       return i;
          246 
          247   return -1;
          248 }
          249 
          250 sub need_version (major, minor, beta)
          251 {
          252   local r, v, i;
          253 
          254   regmatch (version, (/([0-9]+)\.([0-9]+)\.([0-9]+)/));
          255   v = list (int ($1), int ($2), int ($3));
          256   r = list (major, minor, beta);
          257 
          258   for (i = 0; i < 3; i = i + 1)
          259     if (v[i] > r[i])
          260       return 1;
          261     else if (v[i] < r[i])
          262       return 0;
          263 
          264   /* Exact match. */
          265   return 1;
          266 }
          267 
          268 /* Highlight types which match expression <re> from string <data>. */
          269 sub highlight_types (data, re)
          270 {
          271   local match_len;
          272 
          273   while (regmatch (data, re))
          274     {
          275       language_print ($B);
          276       type_face (true);
          277       language_print ($0);
          278       type_face (false);
          279 
          280       match_len = length ($B, $0);
          281 
          282       data = substring (data, match_len, length (data));
          283     }
          284 
          285   language_print (data);
          286 }
          287 
          288 
          289 /*
          290  * The supported faces.  These functions are used in the highlighting
          291  * rules to mark different logical elements of the code.  The
          292  * different faces and their properties (face_*) are defined in the
          293  * style definition files.  The face_on() and face_off() functions are
          294  * defined in the output language definition files.
          295  */
          296 
          297 sub bold (on)
          298 {
          299   if (on)
          300     face_on (face_bold);
          301   else
          302     face_off (face_bold);
          303 }
          304 
          305 sub italic (on)
          306 {
          307   if (on)
          308     face_on (face_italic);
          309   else
          310     face_off (face_italic);
          311 }
          312 
          313 sub bold_italic (on)
          314 {
          315   if (on)
          316     face_on (face_bold_italic);
          317   else
          318     face_off (face_bold_italic);
          319 }
          320 
          321 sub comment_face (on)
          322 {
          323   if (on)
          324     face_on (face_comment);
          325   else
          326     face_off (face_comment);
          327 }
          328 
          329 sub function_name_face (on)
          330 {
          331   if (on)
          332     face_on (face_function_name);
          333   else
          334     face_off (face_function_name);
          335 }
          336 
          337 sub variable_name_face (on)
          338 {
          339   if (on)
          340     face_on (face_variable_name);
          341   else
          342     face_off (face_variable_name);
          343 }
          344 
          345 sub keyword_face (on)
          346 {
          347   if (on)
          348     face_on (face_keyword);
          349   else
          350     face_off (face_keyword);
          351 }
          352 
          353 sub reference_face (on)
          354 {
          355   if (on)
          356     face_on (face_reference);
          357   else
          358     face_off (face_reference);
          359 }
          360 
          361 sub string_face (on)
          362 {
          363   if (on)
          364     face_on (face_string);
          365   else
          366     face_off (face_string);
          367 }
          368 
          369 sub builtin_face (on)
          370 {
          371   if (on)
          372     face_on (face_builtin);
          373   else
          374     face_off (face_builtin);
          375 }
          376 
          377 sub type_face (on)
          378 {
          379   if (on)
          380     face_on (face_type);
          381   else
          382     face_off (face_type);
          383 }
          384 
          385 sub highlight_face (on)
          386 {
          387   if (on)
          388     face_on (face_highlight);
          389   else
          390     face_off (face_highlight);
          391 }
          392 
          393 
          394 /*
          395  * Initializations.
          396  */
          397 
          398 start
          399 {
          400   /* Set debug level. */
          401   debug_level = int (debug);
          402 
          403   /* Use colors? */
          404   color = int (color);
          405 
          406   /* Increment input file count. */
          407   current_input_file = current_input_file + 1;
          408 
          409   /* Resolve fonts. */
          410   idx = strchr (font_spec, '@');
          411   if (idx < 0)
          412     panic ("malformed font spec: `", font_spec, "'");
          413 
          414   font = substring (font_spec, 0, idx);
          415   ptsize = substring (font_spec, idx + 1, length (font_spec));
          416 
          417   debug (concat ("start: ", font, "@", ptsize));
          418 
          419   /* Construct bold, italic, etc. fonts for our current body font. */
          420   if (is_prefix ("AvantGarde", font))
          421     {
          422       bold_font = "AvantGarde-Demi";
          423       italic_font = "AvantGarde-BookOblique";
          424       bold_italic_font = "AvantGarde-DemiOblique";
          425     }
          426   else if (regmatch (font, /^Bookman|Souvenir/))
          427     {
          428       bold_font = concat ($0, "-Demi");
          429       italic_font = concat ($0, "-LightItalic");
          430       bold_italic_font = concat ($0, "-DemiItalic");
          431     }
          432   else if (regmatch (font, /^Lucida(Sans-)?Typewriter/))
          433     {
          434       bold_font = concat ($0, "Bold");
          435       italic_font = concat ($0, "Oblique");
          436       bold_italic_font = concat ($0, "BoldOblique");
          437     }
          438   else if (regmatch (font, /^(.*)-Roman$/))
          439     {
          440       bold_font = concat ($1, "-Bold");
          441       italic_font = concat ($1, "-Italic");
          442       bold_italic_font = concat ($1, "-BoldItalic");
          443     }
          444   else
          445     {
          446       bold_font = concat (font, "-Bold");
          447       italic_font = concat (font, "-Oblique");
          448       bold_italic_font = concat (font, "-BoldOblique");
          449     }
          450 
          451   /* Create regular expressions for nested highlighting. */
          452   nested_start_re = regexp (nested_start);
          453   nested_end_re_cached = regexp (nested_end);
          454 
          455   /* Define output faces. */
          456   calln (concat ("lang_", language));
          457 
          458   /* Define our highlight style. */
          459   calln (concat ("style_", style));
          460 
          461   /* Resolve start state. */
          462   if (check_startrules ())
          463     debug ("startstate from startrules");
          464   if (check_namerules ())
          465     debug ("startstate from namerules");
          466 }
          467 
          468 namerules
          469 {
          470   /\.(c|h)$/                                        c;
          471   /\.(c++|C|H|cpp|cc|cxx|hpp)$/                        cpp;
          472   /\.m$/                                        matlab;
          473   /\.(mpl|mp|maple)$/                                maple;
          474   /\.(scm|scheme)$/                                scheme;
          475   /\b\.emacs$|\.el$/                                elisp;
          476   /\.ad(s|b|a)$/                                ada;
          477   /\.[Ss]$/                                        asm;
          478   /\.st$/                                        states;
          479   /(M|m)akefile.*/                                makefile;
          480   /\.(MOD|DEF|mi|md)$/                                modula_2;
          481   /\.tcl$/                                        tcl;
          482   /\.(v|vh)$/                                        verilog;
          483   /\.html?$/                                        html;
          484   /\bChangeLog$/                                changelog;
          485   /\.(vhd|vhdl)$/                                vhdl;
          486   /\.(scr|.syn|.synth)$/                        synopsys;
          487   /\.idl$/                                        idl;
          488   /\.(hs|lhs|gs|lgs)$/                                haskell;
          489   /\.(pm|pl)$/                                        perl;
          490   /\.(eps|EPS|ps|PS)$/                                postscript;
          491   /\.py$/                                        python;
          492   /\.pyx$/                                        pyrex;
          493   /\.js$/                                        javascript;
          494   /\.java$/                                        java;
          495   /\.([Pp][Aa][Ss]|[Pp][Pp]|[Pp])$/                pascal;
          496   /\.[fF]$/                                        fortran;
          497   /\.f90$/                                        f90;
          498   /\.awk$/                                        awk;
          499   /\.sh$/                                        sh;
          500   /\.vba$/                                        vba;
          501   /\.(cshrc|login|logout|history|csh)$/                csh;
          502   /\.tcshrc$/                                        tcsh;
          503   /\.(zshenv|zprofile|zshrc|zlogin|zlogout)$/        zsh;
          504   /\.(bash_profile|bashrc|inputrc)$/                bash;
          505   /\.m4$/                                        m4;
          506   /\.il$/                                        skill;
          507   /\.wrl$/                                        vrml;
          508   /\b(rfc.*\.txt|draft-.*\.txt)$/                rfc;
          509   /\.inf$/i                                        inf;
          510   /\.tex$/                                        tex;
          511   /\.wmlscript$/                                wmlscript;
          512   /\.wmls$/                                        wmlscript;
          513   /^.*$/                                        passthrough;
          514 }
          515 
          516 startrules
          517 {
          518   /.\010.\010.\010./                                        nroff;
          519   /-\*- [Cc] -\*-/                                        c;
          520   /-\*- [Cc]\+\+ -\*-/                                        cpp;
          521   /-\*- [Aa][Dd][Aa] -\*-/                                ada;
          522   /-\*- [Aa][Ss][Mm] -\*-/                                asm;
          523   /-\*- [Oo][Bb][Jj][Cc] -\*-/                                objc;
          524   /-\*- [Ss][Cc][Hh][Ee][Mm][Ee] -\*-/                        scheme;
          525   /-\*- [Ee][Mm][Aa][Cc][Ss] [Ll][Ii][Ss][Pp] -\*-/        elisp;
          526   /-\*- [Tt][Cc][Ll] -\*-/                                tcl;
          527   /-\*- [Vv][Hh][Dd][Ll] -\*-/                                vhdl;
          528   /-\*- [Hh][Aa][Ss][Kk][Ee][Ll][Ll] -\*-/                haskell;
          529   /-\*- [Ii][Dd][Ll] -\*-/                                idl;
          530   /-\*- [Pp][Ee][Rr][Ll] -\*-/                                perl;
          531   /^#![ \t]*\/.*\/perl/                                        perl;
          532   /^From:/                                                mail;
          533   /^#![ \t]*(\/usr)?\/bin\/[ngmt]?awk/                        awk;
          534   /^#![ \t]*(\/usr)?\/bin\/sh/                                sh;
          535   /^#![ \t]*(\/usr)?\/bin\/csh/                                csh;
          536   /^#![ \t]*(\/usr)?(\/local)?\/bin\/tcsh/                tcsh;
          537   /^#![ \t]*(\/usr)?(\/local)?\/bin\/zsh/                zsh;
          538   /^#![ \t]*(\/usr)?(\/local)?\/bin\/bash/                bash;
          539   /^#![ \t]*(\/usr)?(\/ccs)?\/bin\/m4/                        m4;
          540   /^#VRML/                                                vrml;
          541   /^\04?%!/                                                postscript;
          542 }
          543 
          544 
          545 /*
          546  * The global super states.
          547  */
          548 
          549 state Highlight
          550 {
          551   /* If you want to preserve enscript's escape sequences in the state
          552      highlighting, uncomment the following rule.  It passes all
          553      enscript's escape sequences to the output.
          554 
          555        /^\0[^{]+{[^}]+}/ {
          556         language_print ($0);
          557        }
          558   */
          559 
          560   /* If we are doing nested highlighting (same document can contain
          561      multiple highlighting styles), the variable `nested_end_re'
          562      specifies the end of the nesting highlight state. */
          563   nested_end_re {
          564     language_print($0);
          565     return;
          566   }
          567 
          568   /* Skip output language's special characters. */
          569   LANGUAGE_SPECIALS {
          570     language_print ($0);
          571   }
          572 }
          573 
          574 /* How many nesting HighlightEntry states are currently active.  The
          575    header and trailer will be printed at the nesting level 0. */
          576 highlight_entry_nesting = 0;
          577 
          578 state HighlightEntry extends Highlight
          579 {
          580   BEGIN {
          581     if (highlight_entry_nesting++ == 0)
          582       header();
          583   }
          584   END {
          585     if (--highlight_entry_nesting == 0)
          586       trailer();
          587   }
          588 }
          589 
          590 
          591 
          592 /*
          593  * Helper subroutines and states.
          594  */
          595 
          596 state match_balanced_block extends Highlight
          597 {
          598   match_balanced_block_start {
          599     language_print ($0);
          600     match_balanced_block_count = match_balanced_block_count + 1;
          601   }
          602 
          603   match_balanced_block_end {
          604     match_balanced_block_count = match_balanced_block_count - 1;
          605     if (match_balanced_block_count == 0)
          606       return $0;
          607 
          608     language_print ($0);
          609   }
          610 }
          611 
          612 sub match_balanced_block (starter, ender)
          613 {
          614   match_balanced_block_count = 1;
          615   match_balanced_block_start = starter;
          616   match_balanced_block_end = ender;
          617   return call (match_balanced_block);
          618 }
          619 
          620 state eat_one_line
          621 {
          622   /.*\n/ {
          623     language_print ($0);
          624     return;
          625   }
          626 }
          627 
          628 
          629 /*
          630 Local variables:
          631 mode: c
          632 End:
          633 */