changeset 18:2a3055313d1e

*** empty log message ***
author ht
date Sat, 19 Apr 2008 19:10:28 +0100
parents ee87d53174b1
children cc9c7bc8194a
files generic-extras.el generic-mode.el
diffstat 2 files changed, 1717 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/generic-extras.el	Sat Apr 19 19:10:28 2008 +0100
@@ -0,0 +1,991 @@
+;;; generic-extras.el --- Extra Modes for generic-mode
+;;
+;; Author:  Peter Breton <pbreton@i-kinetics.com>
+;; Created: Tue Oct 08 1996
+;; Version: $Id$
+;; Keywords: 
+;; Time-stamp: <98/02/10 22:48:22 pbreton>
+;;
+;; Copyright (C) Peter Breton 01Nov96
+;;
+;; This is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; generic-extras.el is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;
+;; LCD Archive Entry:
+;; generic-extras|Peter Breton|pbreton@i-kinetics.com|
+;; Sample modes for 'generic-mode'|
+;; 01-Nov-1996|1.0|~/misc/generic-extras.el.gz|
+;;
+;;; Commentary:
+;;
+;; This file contains some pre-defined generic-modes.
+;; 
+;; INSTALLATION:
+;;
+;; Add this line to your .emacs file:
+;;
+;;   (require 'generic-extras)
+;;
+;; You can decide which modes to load by setting the variable
+;; 'generic-extras-enable-list'. Some platform-specific modes are
+;; affected by the variables 'generic-define-mswindows-modes' and
+;; 'generic-define-unix-modes' (which see).
+;;
+;; ALTERING THESE MODES:
+;;
+;; To alter the definition of these modes, use the 'alter-generic-mode-'
+;; convenience functions defined in generic-mode.el. Each of these functions
+;; takes an optional how-to-alter argument, which can be one of the following
+;; symbols: 'overwrite, 'append, 'prepend.
+;; 
+;; You can also send me new modes (I'll accept ones for file types which are
+;; reasonably common) or patches to these ones.
+;;
+;; PROBLEMS WHEN USED WITH FOLDING MODE:
+;;
+;; From Anders Lindgren <andersl@csd.uu.se>
+;; 
+;; Problem summary: Wayne Adams has found a problem when using folding
+;; mode in conjuction with font-lock for a mode defined in
+;; `generic-extras.el'.
+;;
+;; The problem, as Wayne described it, was that error messages of the
+;; following form appeared when both font-lock and folding are used:
+;; 
+;; >      - various msgs including "Fontifying region...(error Stack
+;; > overflow in regexp matcher)" appear
+;; 
+;; I have just tracked down the cause of the problem.  The regexp:s in
+;; `generic-extras.el' does not take into account the way that folding
+;; hides sections of the buffer.  The technique is known as
+;; `selective-display' and has been available for a very long time (I
+;; started using it back in the good old' Emacs 18 days).  Basically, a
+;; section is hidden by creating one very long line were the newline
+;; character (C-j) is replaced by a linefeed (C-m) character.
+;; 
+;; Many other hiding packages, besides folding, use the same technique,
+;; the problem should occur when using them as well.
+;; 
+;; The erroronous lines in `generic-extras' look like the following (this
+;; example is from the `ini' section):
+;; 
+;;     '(("^\\(\\[.*\\]\\)"   1 'font-lock-reference-face)
+;;       ("^\\(.*\\)="        1 'font-lock-variable-name-face)
+;; 
+;; The intention of these lines is to highlight lines of the following
+;; form:
+;; 
+;; [foo]
+;; bar = xxx
+;; 
+;; However, since the `.' regexp symbol match the linefeed character the
+;; entire folded section is searched, resulting in a regexp stack
+;; overflow.
+;; 
+;; Solution suggestion 2: Instead of using ".", use the sequence
+;; "[^\n\r]".  This will make the rules behave just as before, but they
+;; will work together with selective-display.
+;;
+;; 
+;;; Change log:
+;; $Log$
+;; Revision 1.1  2008/04/19 18:10:28  ht
+;; *** empty log message ***
+;;
+;; Revision 1.5  1998/02/11 03:44:32  pbreton
+;; About to pull out generic-indent code
+;;
+;; Revision 1.4  1996/11/01 16:51:20  peter
+;; Added GPL and LCD information.
+;;
+;; Revision 1.3  1996/10/19 12:22:07  peter
+;; Added new versions of rc and rul modes
+;; Regexp patches for generic-bat-mode
+;;
+;; Revision 1.2  1996/10/17 01:02:41  peter
+;; Improved samba and apache modes
+;; Added fvwm and x-resource modes
+;;
+
+;;; Code:
+
+(require 'generic-mode)
+(require 'font-lock)
+
+(defvar generic-extras-enable-list nil
+  "*List of generic modes to enable by default.
+Each entry in the list should be a symbol.
+The variables `generic-define-mswindows-modes' and `generic-define-unix-modes'
+also affect which generic modes are defined")
+
+(defvar generic-define-mswindows-modes 
+  (memq system-type (list 'windows-nt 'ms-dos))
+  "*If non-nil, some MS-Windows specific generic modes will be defined.")
+
+(defvar generic-define-unix-modes
+  (not generic-define-mswindows-modes)
+  "*If non-nil, some Unix specific generic modes will be defined.")
+
+(if generic-define-mswindows-modes
+    (setq generic-extras-enable-list
+	  (append (list 'bat-generic-mode 'ini-generic-mode 
+			'inf-generic-mode 'rc-generic-mode 
+			'reg-generic-mode 'rul-generic-mode)
+		  generic-extras-enable-list)))
+
+(if generic-define-unix-modes
+    (setq generic-extras-enable-list
+	  (append (list 'apache-generic-mode 'samba-generic-mode 
+			'hosts-generic-mode  'fvwm-generic-mode 
+			'x-resource-generic-mode 
+			'crontab-generic-mode)
+		  generic-extras-enable-list)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Generic-modes
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Apache
+(and 
+ (memq 'apache-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'apache-generic-mode
+   (list ?#)  
+   nil 
+   '(("^\\(<.*>\\)"       1 'font-lock-reference-face)
+     ("^\\(\\sw+\\)\\s-"  1 'font-lock-variable-name-face))    
+   (list "srm\\.conf$" "httpd\\.conf$" "access\\.conf$")
+   nil 
+   "Generic mode for Apache or HTTPD configuration files."))
+ 
+;;; Samba
+(and 
+ (memq 'samba-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'samba-generic-mode
+   (list ?\;)
+   nil
+   '(("^\\(\\[.*\\]\\)"   1 'font-lock-reference-face))
+   (list "smb\\.conf$")
+   (list 'generic-bracket-support)
+   "Generic mode for Samba configuration files."))
+
+;;; Fvwm
+;; This is pretty basic. Also, modes for other window managers could
+;; be defined as well.
+(and 
+ (memq 'fvwm-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'fvwm-generic-mode
+   (list ?#)
+   (list "Style" "Function" "EndFunction" "Popup" "EndPopup")
+   nil
+   (list "\\.fvwmrc")
+   nil
+   "Generic mode for FVWM configuration files."))
+
+;;; X Resource
+;; I'm pretty sure I've seen an actual mode to do this, but I don't
+;; think it's standard with Emacs
+(and 
+ (memq 'x-resource-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'x-resource-generic-mode
+   (list ?!)
+   nil
+   '(("^\\([^:\n]+:\\)" 1 'font-lock-variable-name-face))
+   (list "\\.Xdefaults" "\\.Xresources")
+   nil
+   "Generic mode for X Resource configuration files."))
+
+;;; Hosts
+(and 
+ (memq 'hosts-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'hosts-generic-mode
+   (list ?#)
+   (list "localhost")
+   '(("\\([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\\)" 1 'font-lock-reference-face))
+   (list "[hH][oO][sS][tT][sS]$")
+   nil
+   "Generic mode for HOSTS files."))
+
+;;; Windows INF files
+(and 
+ (memq 'inf-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'inf-generic-mode
+   (list ?\;)
+   nil 
+   '(("^\\(\\[.*\\]\\)"   1 'font-lock-reference-face))
+   (list "\\.[iI][nN][fF]")
+   (list 'generic-bracket-support)
+   "Generic mode for MS-Windows INF files."))
+
+;;; Windows INI files
+;; Should define escape character as well!
+(and 
+ (memq 'ini-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'ini-generic-mode
+   (list ?\;)
+   nil
+   '(("^\\(\\[.*\\]\\)"   1 'font-lock-reference-face)
+     ("^\\([^\n\r]*\\)=\\([^\n\r]*\\)$"        
+      (1 font-lock-function-name-face)
+      (2 font-lock-variable-name-face)))
+   (list "\\.[iI][nN][iI]$")
+    (list 
+     (function
+      (lambda ()
+	(setq imenu-generic-expression 
+	'((nil "^\\[\\(.*\\)\\]" 1)
+	  ("*Variables*" "^\\s-*\\(.*\\)\\s-*=" 1)))
+	)))
+    "Generic mode for MS-Windows INI files."))
+
+;;; Windows REG files
+;;; Unfortunately, Windows 95 and Windows NT have different REG file syntax!
+(and 
+ (memq 'reg-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'reg-generic-mode
+   '(?\;)
+   '("key" "classes_root" "REGEDIT" "REGEDIT4")
+   '(("\\(\\[.*]\\)"     1 'font-lock-reference-face)
+     ("^\\([^\n\r]*\\)\\s-*="  1 'font-lock-variable-name-face))
+   '("\\.[rR][eE][gG]$")
+    (list 
+     (function
+      (lambda ()
+	(setq imenu-generic-expression 
+	'((nil "^\\s-*\\(.*\\)\\s-*=" 1))))))
+    "Generic mode for MS-Windows Registry files."))
+
+;;; Windows BAT files
+(if (not (memq 'bat-generic-mode generic-extras-enable-list))
+    nil
+(define-generic-mode 'bat-generic-mode
+    nil
+    nil
+    (list
+     ;; Make this one first in the list, otherwise comments will
+     ;; be over-written by other variables
+     (list "^[@ \t]*\\([rR][eE][mM][^\n\r]*\\)" 1 'font-lock-comment-face t)
+     (list "^[ \t]*\\(::-.*\\)"		        1 'font-lock-comment-face t)
+     ;; These keywords appear as the first word on a line
+     (generic-make-keywords-list
+      (list
+       "[cC][aA][lL][lL]"
+       "[eE][cC][hH][oO]"
+       "[fF][oO][rR]"
+       "[iI][fF]"
+       "[pP][aA][tT][hH]"
+       "[pP][aA][uU][sS][eE]"
+       "[pP][rR][oO][mM][pP][tT]"
+       "[sS][eE][tT]"
+       "[sS][tT][aA][rR][tT]"
+       )
+      'font-lock-keyword-face "^[@ \t]*")
+     ;; These keywords can be anywhere on a line
+     (generic-make-keywords-list
+      (list
+       "[eE][xX][iI][sS][tT]"
+       "[eE][rR][rR][oO][rR][lL][eE][vV][eE][lL]"
+       "[gG][oO][tT][oO]"
+       "[nN][oO][tT]"
+       ) 'font-lock-keyword-face)
+     (list "^[ \t]*\\(:\\sw+\\)"         1 'font-lock-function-name-face t)
+     (list "\\(%\\sw+%\\)"		 1 'font-lock-reference-face)
+     (list "\\(%[0-9]\\)"		 1 'font-lock-reference-face)
+     (list "\\(/[^/ \"\t\n]+\\)"	 1 'font-lock-type-face)
+     (list "[\t ]+\\([+-][^\t\n\" ]+\\)" 1 'font-lock-type-face)
+     (list "\\<\\([gG][oO][tT][oO]\\)\\>[ \t]*\\(\\sw+\\)?" 
+	   '(1 font-lock-keyword-face)
+	   '(2 font-lock-function-name-face nil t))
+     
+     )
+    (list "\\.[bB][aA][tT]$" "CONFIG\\." "AUTOEXEC\\." )
+    (list 'generic-bat-mode-setup-function)
+    "Generic mode for MS-Windows BAT files.")
+
+  (defvar bat-generic-mode-syntax-table nil
+    "Syntax table in use in bat-generic-mode buffers.")
+  
+  ;; Make underscores count as words
+  (if bat-generic-mode-syntax-table
+      nil
+    (setq bat-generic-mode-syntax-table (make-syntax-table))
+    (modify-syntax-entry ?_  "w"  bat-generic-mode-syntax-table))
+  
+  ;; bat-generic-mode doesn't use the comment functionality of generic-mode
+  ;; because it has a three-letter comment-string, so we do it
+  ;; here manually instead
+  (defun generic-bat-mode-setup-function ()
+    (make-local-variable	     'parse-sexp-ignore-comments)
+    (make-local-variable	     'comment-start)
+    (make-local-variable	     'comment-start-skip)
+    (make-local-variable	     'comment-end)
+    (setq imenu-generic-expression  '((nil "^:\\(\\sw+\\)" 1))
+	  parse-sexp-ignore-comments t
+	  comment-end                ""
+	  comment-start		     "[Rr][Ee][Mm] "
+	  comment-start-skip	     "[Rr][Ee][Mm] *"
+	  )
+    (set-syntax-table	      bat-generic-mode-syntax-table)
+    )
+  )
+
+;;; Windows RC files
+;; Contributed by ACorreir@pervasive-sw.com (Alfred Correira)
+(and 
+ (memq 'rc-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'rc-generic-mode
+;;   (list ?\/)
+   (list "//")
+   '("ACCELERATORS"
+     "AUTO3STATE"
+     "AUTOCHECKBOX"
+     "AUTORADIOBUTTON"
+     "BITMAP"
+     "CAPTION"
+     "CHARACTERISTICS"
+     "CHECKBOX"
+     "CLASS"
+     "COMBOBOX"
+     "CONTROL"
+     "CTEXT"
+     "CURSOR"
+     "DEFPUSHBUTTON"
+     "DIALOG"
+     "EDITTEXT"
+     "EXSTYLE"
+     "FONT"
+     "GROUPBOX"
+     "ICON"
+     "LANGUAGE"
+     "LISTBOX"
+     "LTEXT"
+     "MENUITEM SEPARATOR" 
+     "MENUITEM" 
+     "MENU"
+     "POPUP"
+     "PUSHBOX"
+     "PUSHBUTTON"
+     "RADIOBUTTON"
+     "RCDATA"
+     "RTEXT"
+     "SCROLLBAR"
+     "SEPARATOR"
+     "STATE3"
+     "STRINGTABLE"
+     "STYLE"
+     "VERSIONINFO"
+     "VERSION"
+     )
+   ;; the choice of what tokens go where is somewhat arbitrary,
+   ;; as is the choice of which value tokens are included, as
+   ;; the choice of face for each token group
+   (list
+   (generic-make-keywords-list
+    (list
+     "FILEFLAGSMASK"
+     "FILEFLAGS"
+     "FILEOS"
+     "FILESUBTYPE"
+     "FILETYPE"
+     "FILEVERSION"
+     "PRODUCTVERSION"
+     ) 'font-lock-type-face)
+   (generic-make-keywords-list
+    (list
+     "BEGIN"
+     "BLOCK"
+     "END"
+     "VALUE"
+     ) 'font-lock-function-name-face)
+   '("^#[ \t]*include[ \t]+\\(<[^>\"\n]+>\\)" 1 font-lock-string-face)
+   '("^#[ \t]*define[ \t]+\\(\\sw+\\)("       1 font-lock-function-name-face)
+   '("^#[ \t]*\\(elif\\|if\\)\\>"
+     ("\\<\\(defined\\)\\>[ \t]*(?\\(\\sw+\\)?" nil nil
+      (1 font-lock-reference-face) (2 font-lock-variable-name-face nil t)))
+   '("^#[ \t]*\\(\\sw+\\)\\>[ \t]*\\(\\sw+\\)?"
+     (1 font-lock-reference-face) (2 font-lock-variable-name-face nil t)))
+    (list "\\.[rR][cC]$")
+    nil
+    "Generic mode for MS-Windows Resource files."))
+
+;;; InstallShield RUL files
+;; Contributed by ACorreir@pervasive-sw.com (Alfred Correira)
+;; Additional contributions by alex@brainstorm.fr (Alex Lemaresquier)
+(and 
+ (memq 'rul-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'rul-generic-mode 
+   ;; Using "/*" and "*/" doesn't seem to be working right
+   (list "//")
+   '("begin"
+     "call"
+     "case"
+     "declare"
+     "default"
+     "downto"
+     "elseif"
+     "else"
+     "endfor"
+     "endif"
+     "endswitch"
+     "endwhile"
+     "end"
+     "exit"
+     "external"
+     "for"
+     "function"
+     ;; "goto" -- handled elsewhere
+     "if"
+     "program"
+     "prototype"
+     "repeat"
+     "return"
+     "step"
+     "switch"
+     "then"
+     "to"
+     "typedef"
+     "until"
+     "void"
+     "while")
+  (list
+   ;; preprocessor constructs
+   '("#[ \t]*include[ \t]+\\(<[^>\"\n]+>\\)"
+     1 font-lock-string-face)
+   '("#[ \t]*\\(\\sw+\\)\\>[ \t]*\\(\\sw+\\)?"
+     (1 font-lock-reference-face)
+     (2 font-lock-variable-name-face nil t))
+   ;; gotos
+   '("[ \t]*\\(\\sw+:\\)" 1 font-lock-reference-face)
+   '("\\<\\(goto\\)\\>[ \t]*\\(\\sw+\\)?" 
+     (1 font-lock-keyword-face)
+     (2 font-lock-reference-face nil t))
+   ;; system variables
+   (generic-make-keywords-list
+    (list
+     "CMDLINE"
+     "ERRORFILENAME"
+     "INFOFILENAME"
+     "ISRES"
+     "ISUSER"
+     "ISVERSION"
+     "SRCDIR"
+     "SRCDISK"
+     "SUPPORTDIR"
+     "TARGETDIR"
+     "TARGETDISK"
+     "WINDIR"
+     "WINDISK"
+     "WINMAJOR"
+     "WINSYSDIR"
+     "WINSYSDISK"
+     )
+    'font-lock-variable-name-face)
+   ;; system functions
+   (generic-make-keywords-list
+    (list
+      "AddFolderIcon"
+      "AppCommand"
+      "AskDestPath"
+      "AskOptions"
+      "AskPath"
+      "AskText"
+      "AskYesNo"
+      "CloseFile"
+      "CmdGetHwndDlg"
+      "CompressEnum"
+      "CompressGet"
+      "CopyFile"
+      "CreateDir"
+      "CreateProgramFolder"
+      "DeinstallStart"
+      "Delay"
+      "DeleteDir"
+      "DeleteFile"
+      "Disable"
+      "DoInstall"
+      "Do"
+      "Enable"
+      "EnterDisk"
+      "ExistsDir"
+      "EzDefineDialog"
+      "FindFile"
+      "FindWindow"
+      "FileCompare"
+      "FileSetBeginDefine"
+      "FileSetEndDefine"
+      "FileSetPerformEz"
+      "FileSetPerform"
+      "GetDiskSpace"
+      "GetDisk"
+      "GetExtents"
+      "GetProfString"
+      "GetSystemInfo"
+      "GetVersion"
+      "GetWindowHandle"
+      "InstallationInfo"
+      "Is"
+      "LaunchApp"
+      "ListCreate"
+      "ListDestroy"
+      "ListGetFirstString"
+      "ListGetNextString"
+      "ListSetIndex"
+      "LongPathToQuote"
+      "LongPathToShortPath"
+      "MessageBox"
+      "NumToStr"
+      "OpenFile"
+      "ParsePath"
+      "PlaceBitmap"
+      "PlaceWindow"
+      "ProgDefGroupType"
+      "RegDBCreateKeyEx"
+      "RegDBGetItem"
+      "RegDBSetItem"
+      "RegDBGetKeyValueEx"
+      "RegDBSetKeyValueEx"
+      "RegDBSetDefaultRoot"
+      "RenameFile"
+      "SdSelectFolder"
+      "SdShowMsg"
+      "SdWelcome"
+      "SetColor"
+      "SetDialogTitle"
+      "SetFileInfo"
+      "SetForegroundWindow"
+      "SetStatusWindow"
+      "SetTitle"
+      "ShowProgramFolder"
+      "Sprintf"
+      "StatusUpdate"
+      "StrCompare"
+      "StrFind"
+      "StrGetTokens"
+      "StrLength"
+      "StrRemoveLastSlash"
+      "StrToLower"
+      "StrToUpper"
+      "StrSub"
+      "VarRestore"
+      "VarSave"
+      "WaitOnDialog"
+      "Welcome"
+      "XCopyFile"
+      )
+    'font-lock-function-name-face)
+   ;; type keywords
+   (generic-make-keywords-list
+    (list
+      "BOOL"
+      "BYREF"
+      "CHAR"
+      "HIWORD"
+      "HWND"
+      "INT"
+      "LIST"
+      "LONG"
+      "LOWORD"
+      "NUMBER"
+      "POINTER"
+      "QUAD"
+      "RGB"
+      "SHORT"
+      "STRINGLIST"
+      "STRING"
+      )
+    'font-lock-type-face)
+   ;;; system variables
+   (generic-make-keywords-list
+    (list
+     "CMDLINE"
+     "ERRORFILENAME"
+     "INFOFILENAME"
+     "ISRES"
+     "ISUSER"
+     "ISVERSION"
+     "SRCDIR"
+     "SRCDISK"
+     "SUPPORTDIR"
+     "TARGETDIR"
+     "TARGETDISK"
+     "WINDIR"
+     "WINDISK"
+     "WINSYSDIR"
+     "WINSYSDISK"
+     )
+    'font-lock-variable-name-face)
+   ;; pre-defined constants (not exhaustive -- just my favorites)
+   (generic-make-keywords-list
+    (list
+      "AFTER"
+      "APPEND"
+      "BACKGROUNDCAPTION"
+      "BACKGROUND"
+      "BACK"
+      "BEFORE"
+      "BK_BLUE"
+      "BK_GREEN"
+      "BK_RED"
+      "CANCEL"
+      "COMMANDEX"
+      "COMMAND"
+      "CONTINUE"
+      "DEFWINDOWMODE"
+      "DISABLE"
+      "DLG_ERR"
+      "ENABLE"
+      "END_OF_LIST"
+      "EXCLUSIVE"
+      "EXISTS"
+      "EXIT"
+      "FAILIFEXISTS"
+      "FALSE"
+      "FULL"
+      "INDVFILESTATUS"
+      "INFORMATION"
+      "LIST_NULL"
+      "LISTFIRST"
+      "LISTNEXT"
+      "LOGGING"
+      "NEXT"
+      "NONEXCLUSIVE"
+      "NOSET"
+      "NO"
+      "OFF"
+      "ON"
+      "PARTIAL"
+      "REPLACE_ITEM"
+      "REPLACE"
+      "RESET"
+      "RESTART"
+      "SET"
+      "SEVERE"
+      "SRCTARGETDIR"
+      "STATUS"
+      "TRUE"
+      "YES"
+      "WARNING"
+      )
+    'font-lock-variable-name-face)     ; is this face the best choice?
+   )
+  (list "\\.[rR][uU][lL]$")
+  (list
+   (function 
+    (lambda ()
+      (setq imenu-generic-expression 
+	    '((nil "^function\\s-+\\([A-Za-z0-9_]+\\)" 1)))
+      )))
+  "Generic mode for InstallShield RUL files")
+
+(define-skeleton rul-if
+   "Insert an if statement."
+   "condition: "
+   "if(" str ") then" \n
+   > _ \n
+   ( "other condition, %s: "
+     > "elseif(" str ") then" \n
+     > \n)   
+   > "else" \n
+   > \n
+   resume:
+   > "endif;"
+   )
+
+(define-skeleton rul-function
+  "Insert a function statement."
+  "function: "
+  "function " str " ()" \n
+  ( "local variables, %s: "
+  > "  " str ";" \n)
+  > "begin" \n
+  > _ \n
+  resume:
+  > "end;")
+
+)
+
+;;; Info-Mac abstracts
+;; Contributed by Jacques Duthen Prestataire (duthen@cegelec-red.fr)
+;; 
+;; For an example of such a file, you can download (the small):
+;; http://hyperarchive.lcs.mit.edu/HyperArchive/Archive/_Font/00font-abstracts.txt
+(and 
+ (memq 'info-mac-abstract-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'info-mac-abstract-generic-mode 
+   () 
+   (list "Date" "From" "Subject") 
+   '(("^#### [^\n\r]*" . font-lock-function-name-face))
+   (list "00.*-abstracts\\.txt") 
+   nil 
+   "Generic mode for info-mac abstract files."))
+
+;;; Mailagent
+;; Mailagent is a Unix mail filtering program. Anyone wanna do a generic mode
+;; for procmail?
+(and 
+ (memq 'mailagent-rules-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'mailagent-rules-generic-mode
+   (list ?#)  
+   (list "SAVE" "DELETE" "PIPE" "ANNOTATE" "REJECT")
+   '(("^\\(\\sw+\\)\\s-*="         1 'font-lock-variable-name-face)
+     ("\\s-/\\([^/]+\\)/[i, \t\n]" 1 'font-lock-reference-face))
+   (list "\\.rules$")
+   (list 'mailagent-rules-setup-function)
+   "Mode for Mailagent rules files.")
+ 
+(defun mailagent-rules-setup-function () 
+   (make-local-variable 'imenu-generic-expression)
+   (setq imenu-generic-expression 
+	 '((nil "\\s-/\\([^/]+\\)/[i, \t\n]" 1))))
+ )
+
+;;; Crontab
+;; I didn't write this, I only adapted it for generic-mode
+;; If anyone knows who wrote it originally, I'd be glad to credit them
+(and 
+ (memq 'crontab-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'crontab-generic-mode
+   (list ?#)  
+   nil
+   (list 
+    (list 
+     (concat "^\\(" 
+	     ;; Repeated 5 times for minute, hour, day of month,
+	     ;; month and day of week fields
+	     (mapconcat 'identity (make-list 5 "[*0-9,]+[ \t]+") "") 
+	     "\\)\\([^\n\r]*\\)")
+     (list 1 'font-lock-reference-face)
+     (list 2 'font-lock-function-name-face)))
+   nil
+   (list 'crontab-setup-function)
+   "Mode for Crontab files.")
+ 
+(defun crontab-setup-function () 
+   (local-set-key "\C-c\C-c" 'crontab-update)
+   (local-set-key "\C-x\C-s" 'crontab-update)
+   )
+ 
+(defun crontab ()
+   "Edit a crontab file.  
+Type \\[save-buffer] to feed the buffer to the crontab command."
+   (interactive)
+   (switch-to-buffer "*Crontab*")
+   (erase-buffer)
+   (message "Reading crontab file ... ")(sit-for 0) ; redisplay
+   (if (eq (call-process-region (point) (point) "crontab" nil t t "-l") 0)
+       (message "Reading crontab file ... done")
+     (message "No crontab file")
+     (erase-buffer)
+     (insert "#min hour dom mon dow (0=Sun) cmd\n"))
+   (set-buffer-modified-p nil)
+   (crontab-generic-mode))
+ 
+(defun crontab-update ()
+   "Use the current buffer to update the crontab file."
+   (interactive)
+   (message "Updating crontab file ... ")(sit-for 0) ; redisplay
+   (shell-command-on-region (point-min) (point-max) "crontab" nil)
+   (message "Updating crontab file ... done")
+   (set-buffer-modified-p nil))
+ )
+
+;; Contributed by Jacques Duthen Prestataire (duthen@cegelec-red.fr)
+(and 
+ (memq 'ps-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'ps-generic-mode
+   () ;; (list ?%) would not permit to differentiate DSC comments.
+   (list "def" "if" "ifelse" "forall")              ; some keywords
+   '(("^%%[^ \n]*" . font-lock-reference-face)      ; DSC comments
+     ("^/[^ \n]*"  . font-lock-function-name-face)  ; func or glob var def
+     ("%.*"        . font-lock-comment-face)        ; normal comments
+     ("(.*)"       . font-lock-string-face)         ; ps strings
+     ("/[^ \n]*"   . font-lock-variable-name-face)  ; symbols
+     )
+   (list "\\.ps") ;; extension of Postscript files
+   nil            ;; no hook
+   "Generic mode for PostScript files")
+ )
+
+;; Solaris/Sys V prototype files
+(and 
+ (memq 'prototype-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'prototype-generic-mode
+   (list ?#)
+   nil
+   '(
+     ("^\\([0-9]\\)?\\s-*\\([a-z]\\)\\s-+\\([A-Za-z_]+\\)\\s-+\\([^\n\r]*\\)$"
+      (2 font-lock-reference-face)
+      (3 font-lock-keyword-face))
+     ("^\\([a-z]\\) \\([A-Za-z_]+\\)=\\([^\n\r]*\\)$"
+      (1 font-lock-reference-face)
+	  (2 font-lock-keyword-face)
+	  (3 font-lock-variable-name-face))
+     ("^\\(!\\s-*\\(search\\|include\\|default\\)\\)\\s-*\\([^\n\r]*\\)$"
+      (1 font-lock-keyword-face)
+      (3 font-lock-variable-name-face))
+     ("^\\(!\\s-*\\sw+\\)=\\([^\n\r]*\\)$"
+      (1 font-lock-keyword-face)
+      (2 font-lock-variable-name-face))
+     )
+   (list "prototype$")
+   nil
+   "Mode for Sys V prototype files"))
+
+;; Solaris/Sys V pkginfo files
+(and 
+ (memq 'pkginfo-generic-mode generic-extras-enable-list)
+
+(define-generic-mode 'pkginfo-generic-mode
+   (list ?#)
+   nil
+   '(
+     ("^\\([A-Za-z_]+\\)=\\([^\n\r]*\\)$"
+      (1 font-lock-keyword-face)
+      (2 font-lock-variable-name-face))
+     )
+   (list "pkginfo$")
+   nil
+   "Mode for Sys V pkginfo files"))
+
+(define-generic-mode 'javascript-generic-mode
+  (list "//")
+  (list
+   "document"
+   "else"
+   "function"
+   "function"
+   "if"
+   "then"
+   "var"
+   )
+  (list
+   (list "^\\s-*function\\s-+\\([A-Za-z0-9]+\\)"
+	 '(1 font-lock-function-name-face))
+     (list "^\\s-*var\\s-+\\([A-Za-z0-9]+\\)"
+	   '(1 font-lock-variable-name-face))
+     )    
+  (list "\\.js$")
+  (list
+   (function 
+    (lambda ()
+      (setq imenu-generic-expression 
+	    '((nil "^function\\s-+\\([A-Za-z0-9_]+\\)" 1)))
+      )))
+  "Mode for JavaScript files.")
+
+(define-generic-mode 'vrml-generic-mode
+  (list ?#)
+  (list
+   "DEF"
+   "NULL"
+   "USE"
+   "Viewpoint"
+   "ambientIntensity"
+   "appearance"
+   "children"
+   "color"
+   "coord"
+   "coordIndex"
+   "creaseAngle"
+   "diffuseColor"
+   "emissiveColor"
+   "fieldOfView"
+   "geometry"
+   "info"
+   "material"
+   "normal"
+   "orientation"
+   "position"
+   "shininess"
+   "specularColor"
+   "texCoord"
+   "texture"
+   "textureTransform"
+   "title"
+   "transparency"
+   "type"
+   )
+  (list
+   (list "USE\\s-+\\([-A-Za-z0-9_]+\\)"
+	 '(1 font-lock-reference-face))
+   (list "DEF\\s-+\\([-A-Za-z0-9_]+\\)\\s-+\\([A-Za-z0-9]+\\)\\s-*{"
+	 '(1 font-lock-type-face)
+	 '(2 font-lock-reference-face))
+   (list "^\\s-*\\([-A-Za-z0-9_]+\\)\\s-*{"
+	 '(1 font-lock-function-name-face))
+   (list 
+    "^\\s-*\\(geometry\\|appearance\\|material\\)\\s-+\\([-A-Za-z0-9_]+\\)"
+    '(2 font-lock-variable-name-face))
+   )
+  (list "\\.wrl$")
+  (list
+   (function 
+    (lambda ()
+      (setq imenu-generic-expression 
+	    '((nil "^\\([A-Za-z0-9_]+\\)\\s-*{" 1)
+	      ("*Definitions*" 
+	       "DEF\\s-+\\([-A-Za-z0-9_]+\\)\\s-+\\([A-Za-z0-9]+\\)\\s-*{"
+	       1)))
+      )))
+  "Generic Mode for VRML files.")
+
+(define-generic-mode 'mailrc-generic-mode
+  (list ?#)
+  (list "alias" "group" "set")
+  '(("^\\s-*\\(alias\\|group\\)\\s-+\\([-A-Za-z0-9_]+\\)\\s-+\\([^\n\r]*\\)$"
+     (2 font-lock-reference-face) (3 font-lock-variable-name-face))
+    ("^\\s-*set\\s-+\\([-A-Za-z0-9_]+\\)=\\([^\n\r]*\\)$"
+     (1 font-lock-reference-face) (2 font-lock-variable-name-face)))
+  (list "\\.mailrc$")
+  nil
+  "Mode for mailrc files")
+
+(define-generic-mode 'java-manifest-generic-mode
+  (list ?#)
+  (list "Name" 
+	"Digest-Algorithms" 
+	"Manifest-Version" 
+	"Required-Version" 
+	"Signature-Version"
+	"Magic")
+  '(("^Name:\\s-+\\([^\n\r]*\\)$"
+     (1 font-lock-variable-name-face))
+    ("^\\(Manifest\\|Required\\|Signature\\)-Version:\\s-+\\([^\n\r]*\\)$"
+     (2 font-lock-reference-face))
+    )
+  (list "manifest\\.mf$")
+  nil
+  "Mode for Java Manifest files")
+
+(provide 'generic-extras)
+
+;;; generic-extras.el ends here
+
+;; Local Variables:
+;; autocompile: t
+;; End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/generic-mode.el	Sat Apr 19 19:10:28 2008 +0100
@@ -0,0 +1,726 @@
+;;; generic-mode.el --- A meta-mode which makes it easy to create small
+;;   modes with basic comment and font-lock support
+;;
+;; Author:  Peter Breton
+;; Created: Fri Sep 27 1996
+;; Version: $Header$
+;; Keywords: generic, comment, font-lock
+;; Time-stamp: <97/03/25 10:10:19 pbreton>
+;;
+;; Copyright (C) Peter Breton 01Nov96
+;;
+;; This is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; generic-mode.el is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;
+;; LCD Archive Entry:
+;; generic-mode|Peter Breton|pbreton@i-kinetics.com|
+;; Meta-mode to create small modes with basic comment and font-lock support|
+;; 01-Nov-1996|1.0|~/misc/generic-mode.el.gz|
+;;
+;; Purpose:
+;; 
+;; Meta-mode to create small modes with basic comment and font-lock support
+;;
+;;; Commentary:
+;;
+;; INTRODUCTION:
+;;
+;; Generic-mode is a meta-mode which can be used to define small modes
+;; which provide basic comment and font-lock support. These modes are
+;; intended for the many configuration files and such which are too small
+;; for a "real" mode, but still have a regular syntax, comment characters
+;; and the like.
+;;
+;; Each generic mode can define the following:
+;;
+;; * List of comment-characters. The entries in this list should be
+;;   either a character, a one or two character string or a cons pair.
+;;   If the entry is a character or a one-character string
+;;   LIMITATIONS:  Emacs does not support comment strings of more than
+;;   two characters in length.
+;;
+;; * List of keywords to font-lock. Each keyword should be a string.
+;;   If you have additional keywords which should be highlighted in a face
+;;   different from 'font-lock-keyword-face', you can use the convenience
+;;   function 'generic-make-keywords-list' (which see), and add the
+;;   result to the following list:
+;; 
+;; * Additional expressions to font-lock. This should be a list of
+;;   expressions, each of which should be of the same form
+;;   as those in 'font-lock-defaults-alist'.
+;;   
+;; * List of regular expressions to be placed in auto-mode-alist.
+;;
+;; * List of functions to call to do some additional setup
+;;
+;; This should pretty much cover basic functionality; if you need much
+;; more than this, or you find yourself writing extensive customizations,
+;; perhaps you should be writing a major mode instead!
+;;
+;; INSTALLATION:
+;;
+;; Place the following in your .emacs file:
+;;
+;;   (require 'generic-mode)
+;;
+;; If you want to use some pre-defined generic modes, add:
+;;
+;;   (require 'generic-extras)
+;;
+;; Loading these generic modes will cause some new entries to be placed in
+;; your auto-mode-alist. See 'generic-extras.el' for details.
+;;
+;; LOCAL VARIABLES:
+;;
+;; To put a file into generic mode using local variables, use a line
+;; like this in a Local Variables block:
+;;
+;;   mode: default-generic
+;;
+;; Do NOT use "mode: generic"!
+;; See also "AUTOMATICALLY ENTERING GENERIC MODE" below.
+;;   
+;; DEFINING NEW GENERIC MODES:
+;;
+;; Use the 'define-generic-mode' function to define new modes.
+;; For example:
+;;
+;;   (require 'generic-mode)
+;;   (define-generic-mode 'foo-generic-mode
+;;                        (list ?% )
+;;                        (list "keyword")
+;;                        nil
+;;			  (list "\.FOO")
+;;			  (list 'foo-setup-function))
+;;
+;; defines a new generic-mode 'foo-generic-mode', which has '%' as a
+;; comment character, and "keyword" as a keyword. When files which end in
+;; '.FOO' are loaded, Emacs will go into foo-generic-mode and call
+;; foo-setup-function.  You can also use the function 'foo-generic-mode'
+;; (which is interactive) to put a buffer into foo-generic-mode.
+;; 
+;; ALTERING EXISTING MODES:
+;;
+;; To alter an existing generic-mode, use the convenience functions:
+;;
+;; (alter-generic-mode-comments  MODE COMMENT-LIST   HOW-TO-ALTER)
+;; (alter-generic-mode-keywords  MODE KEYWORD-LIST   HOW-TO-ALTER)
+;; (alter-generic-mode-font-lock MODE FONT-LOCK-LIST HOW-TO-ALTER)
+;; (alter-generic-mode-auto-mode MODE AUTO-MODE-LIST HOW-TO-ALTER)
+;; (alter-generic-mode-functions MODE FUNCTION-LIST  HOW-TO-ALTER)
+;;
+;; HOW-TO-ALTER should be one of the following symbols: 'append, 'prepend,
+;; or 'overwrite. If it is omitted, 'append is assumed.
+;;
+;; AUTOMATICALLY ENTERING GENERIC MODE:
+;;
+;; Generic-mode provides a hook which automatically puts a
+;; file into default-generic-mode if the first few lines of a file in
+;; fundamental mode start with a hash comment character. To disable
+;; this functionality, set the variable 'generic-use-find-file-hook'
+;; to nil BEFORE loading generic-mode. See the variables
+;; 'generic-lines-to-scan' and 'generic-find-file-regexp' for customization
+;; options.
+;; 
+;; GOTCHAS:
+;;
+;; Be careful that your font-lock definitions are correct. Getting them
+;; wrong can cause emacs to continually attempt to fontify! This problem
+;; is not specific to generic-mode.
+;; 
+
+;; Credit for suggestions, brainstorming, patches and bug-fixes:
+;;   ACorreir@pervasive-sw.com (Alfred Correira)
+
+;;; Change log:
+;; $Log$
+;; Revision 1.1  2008/04/19 18:10:28  ht
+;; *** empty log message ***
+;;
+; Revision 1.2  1997/04/02  07:02:38  voelker
+; *** empty log message ***
+;
+;; Revision 1.6  1996/11/01 17:27:47  peter
+;; Changed the function generic-function-name to return a string instead
+;; of a symbol. Generic-mode now uses this for the mode's name
+;;
+;; Revision 1.5  1996/11/01 16:45:20  peter
+;; Added GPL and LCD information.
+;; Updated documentation
+;; Added generic-find-file-regexp variable
+;; Added generic-make-keywords-list function
+;;
+;; Revision 1.4  1996/10/19 12:16:59  peter
+;; Small bug fixes: fontlock -> font-lock
+;; New entries are added to the end of auto-mode-alist
+;; Generic-font-lock-defaults are set to nil, not (list nil)
+;; Comment-regexp in generic-mode-find-file-hook changed to allow optional
+;; blank lines
+;;
+;; Revision 1.3  1996/10/17 08:24:25  peter
+;; Added generic-mode-find-file-hook and associated variables
+;;
+;; Revision 1.2  1996/10/17 01:00:45  peter
+;; Moved from a data-centered approach (generic-mode-alist) to
+;; a function-based one (define-generic-mode)
+;;
+;; Revision 1.1  1996/10/10 11:37:36  peter
+;; Initial revision
+;;
+
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Variables
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(make-variable-buffer-local
+(defvar generic-font-lock-defaults nil
+  "Global defaults for font-lock in a generic mode."))
+
+(make-variable-buffer-local
+(defvar generic-mode-name 'default-generic-mode
+  "The name of the generic mode. 
+This is the car of one of the items in `generic-mode-alist'. 
+This variable is buffer-local."))
+
+(make-variable-buffer-local
+(defvar generic-comment-list nil
+  "List of comment characters for a generic mode."))
+
+(make-variable-buffer-local 
+(defvar generic-keywords-list nil
+  "List of keywords for a generic mode."))
+
+(make-variable-buffer-local
+(defvar generic-font-lock-expressions nil
+  "List of font-lock expressions for a generic mode."))
+
+(make-variable-buffer-local
+(defvar generic-mode-function-list nil
+  "List of customization functions to call for a generic mode."))
+
+(make-variable-buffer-local
+(defvar generic-mode-syntax-table nil
+  "Syntax table for use in a generic mode."))
+
+(defvar generic-mode-alist nil
+  "An association list for generic-mode. 
+Each entry in the list looks like this: 
+
+ NAME COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST AUTO-MODE-LIST FUNCTION-LIST.
+
+Do not add entries to this list directly; use `define-generic-mode' 
+instead (which see). 
+
+To alter an already existing generic-mode, use 
+one of the `alter-generic-mode-' convenience functions (which see)"
+)
+
+(defvar generic-use-find-file-hook t
+  "*If non-nil, add a hook to enter default-generic-mode automatically
+if the first few lines of a file in fundamental mode start with a hash 
+comment character.")
+
+(defvar generic-lines-to-scan 3
+  "*Number of lines that `generic-mode-find-file-hook' looks at 
+when deciding whether to enter generic-mode automatically. 
+This variable should be set to a small positive number.")
+
+(defvar generic-find-file-regexp "#.*\n\\(.*\n\\)?"
+  "*Regular expression used by `generic-mode-find-file-hook'
+to determine if files in fundamental mode should be put into
+`default-generic-mode' instead.")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Inline functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defsubst generic-read-type ()
+  (completing-read
+   "Generic Type: "
+   (mapcar
+    '(lambda (elt) (list (symbol-name (car elt))))
+    generic-mode-alist) nil t))
+
+;; Basic sanity checks. It does *not* check whether the elements of the lists
+;; are of the correct type.
+(defsubst generic-mode-sanity-check (name comment-list   keyword-list   
+					  font-lock-list auto-mode-list  
+					  function-list  &optional description)
+  (if (not (symbolp name))
+      (error "%s is not a symbol" (princ name)))
+
+  (mapcar '(lambda (elt) 
+	     (if (not (listp elt))
+		 (error "%s is not a list" (princ elt))))
+	  (list comment-list   keyword-list font-lock-list 
+		auto-mode-list function-list))
+
+  (if (not (or (null description) (stringp description)))
+      (error "Description must be a string or nil"))
+)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;### autoload
+(defun define-generic-mode (name comment-list    keyword-list   font-lock-list 
+				 auto-mode-list  function-list  
+				 &optional description)
+  "Create a new generic mode with NAME.
+NAME should be a symbol; its string representation is used as the function 
+name. If DESCRIPTION is provided, it is used as the docstring for the new 
+function.
+
+COMMENT-LIST is a list, whose entries are either a single character, 
+a one or two character string or a cons pair. If the entry is a character 
+or a one-character string, it is added to the mode's syntax table with
+comment-start syntax. If the entry is a cons pair, the elements of the
+pair are considered to be comment-start and comment-end respectively. 
+Note that Emacs has limitations regarding comment characters.
+
+KEYWORD-LIST is a list of keywords to highlight with `font-lock-keyword-face'.
+Each keyword should be a string.
+
+FONT-LOCK-LIST is a list of additional expressions to highlight. Each entry
+in the list should have the same form as an entry in `font-lock-defaults-alist'
+
+AUTO-MODE-LIST is a list of regular expressions to add to auto-mode-alist.
+These regexps are added to auto-mode-alist as soon as `define-generic-mode' 
+is called; any old regexps with the same name are removed. To modify the 
+auto-mode-alist expressions, use `alter-generic-mode-auto-mode' (which see).
+
+FUNCTION-LIST is a list of functions to call to do some additional setup.
+
+See the file generic-extras.el for some examples of `define-generic-mode'."
+
+  ;; Basic sanity check
+  (generic-mode-sanity-check name 
+			     comment-list    keyword-list   font-lock-list 
+			     auto-mode-list  function-list  description)
+
+  ;; Remove any old entry
+  (setq generic-mode-alist
+	(delq (assq name generic-mode-alist) 
+	      generic-mode-alist))
+  
+  ;; Add a new entry
+  (setq generic-mode-alist
+	(append
+	 (list
+	  (list
+	   name comment-list keyword-list font-lock-list 
+	   auto-mode-list    function-list
+	   ))
+	 generic-mode-alist))
+
+  ;; Add it to auto-mode-alist
+  (generic-add-to-auto-mode name auto-mode-list t)
+  
+  ;; Define a function for it
+  (generic-create-generic-function name description)
+  )
+
+(defun generic-add-to-auto-mode (mode auto-mode-list 
+				      &optional remove-old prepend)
+  "Add the entries for mode to `auto-mode-alist'. 
+If remove-old is non-nil, removes old entries first. If prepend is
+non-nil, prepends entries to auto-mode-alist; otherwise, appends them."
+
+  (if (not (listp auto-mode-list))
+      (error "%s is not a list" (princ auto-mode-list)))
+
+  (let ((new-mode (intern (symbol-name mode))))
+    (if remove-old
+	(let ((auto-mode-entry))
+	  (while (setq auto-mode-entry (rassq new-mode auto-mode-alist))
+	    (setq auto-mode-alist
+		  (delq auto-mode-entry
+			auto-mode-alist)))))
+
+    (mapcar '(lambda (entry) 
+	       (generic-add-auto-mode-entry new-mode entry prepend))
+	    auto-mode-list)))
+
+(defun generic-add-auto-mode-entry (name entry &optional prepend)
+  "Add a new entry to the end of auto-mode-alist.
+If prepend is non-nil, add the entry to the front of the list."
+  (let ((new-entry (list (cons entry name))))
+    (setq auto-mode-alist
+	  (if prepend
+	      (append new-entry auto-mode-alist)
+	    (append auto-mode-alist new-entry)))))
+   
+(defun generic-create-generic-function (name &optional description)
+  "Create a generic mode function with NAME.
+If DESCRIPTION is provided, it is used as the docstring."
+  (let ((symname (symbol-name name)))
+    (fset (intern symname)
+	  (list 'lambda nil
+		(or description 
+		    (concat "Generic mode for type " symname))
+		(list 'interactive)
+		(list 'generic-mode-with-type (list 'quote name))))))
+
+(defun generic-mode-with-type (&optional mode)
+  "Go into the generic-mode MODE."
+  (let* ((type (or mode generic-mode-name))
+	 (generic-mode-list  (assoc type generic-mode-alist))
+	 )
+
+    (if (not generic-mode-list)
+	(error "Can't find generic-mode information for type %s"
+	       (princ generic-mode-name)))
+
+    ;; Put this after the point where we read generic-mode-name!
+    (kill-all-local-variables)
+
+    (setq 
+     generic-mode-name             type
+     generic-comment-list          (nth 1 generic-mode-list)
+     generic-keywords-list	   (nth 2 generic-mode-list)
+     generic-font-lock-expressions (nth 3 generic-mode-list)
+     generic-mode-function-list	   (nth 5 generic-mode-list)
+     major-mode			   'generic-mode
+     mode-name			   (symbol-name type)
+     )
+
+    (generic-mode-set-comments     generic-comment-list)
+
+    ;; Font-lock functionality
+    ;; Font-lock-defaults are always set even if there are no keywords
+    ;; or font-lock expressions, so comments can be highlighted.
+    (setq generic-font-lock-defaults nil)
+    (generic-mode-set-font-lock      generic-keywords-list
+				     generic-font-lock-expressions)
+    (make-local-variable	    'font-lock-defaults)
+    (setq font-lock-defaults (list 'generic-font-lock-defaults nil))
+
+    ;; Call a list of functions
+    (if generic-mode-function-list
+	(mapcar 'funcall generic-mode-function-list))
+    )
+  )
+
+;;;###autoload
+(defun generic-mode (type)
+  "A mode to do basic comment and font-lock functionality 
+for files which are too small to warrant their own mode, but have
+comment characters, keywords, and the like.
+
+To define a generic-mode, use the function `define-generic-mode'.
+To alter an existing generic-mode, use the `alter-generic-mode-'
+convenience functions. 
+Some generic modes are defined in generic-extras.el" 
+  (interactive
+   (list (generic-read-type)))
+  (generic-mode-with-type (intern type)))
+
+;;; Comment Functionality
+(defun generic-mode-set-comments (comment-list)
+  "Set up comment functionality for generic mode."
+  (if (null comment-list)
+      nil
+    (let ((generic-mode-syntax-table (make-syntax-table)))
+      (make-local-variable	     'comment-start)
+      (make-local-variable	     'comment-start-skip)
+      (make-local-variable	     'comment-end)
+      (mapcar 'generic-mode-set-a-comment comment-list)
+      (set-syntax-table    generic-mode-syntax-table))))
+
+(defun generic-mode-set-a-comment (comment)
+  (and (char-or-string-p comment)
+       (if (stringp comment)
+	   (cond 
+	    ((eq (length comment) 1)
+	     (generic-mode-set-comment-char 
+	      (string-to-char comment)))
+	    ((eq (length comment) 2)
+	     (generic-mode-set-comment-string comment))
+	    (t
+	     (error "Character string %s must be one or two characters long"
+		    comment))
+	    )
+	 (generic-mode-set-comment-char comment)))
+  (if (consp comment)
+      (generic-mode-set-comment-pair comment)))
+
+(defun generic-mode-set-comment-char (comment-char)
+  "Set the given character as a comment character for generic mode."
+  (if (not comment-char)
+      nil
+    (setq 
+     comment-end         ""
+     comment-start       (char-to-string comment-char)
+     comment-start-skip  (concat comment-start "+ *")
+     )
+      
+    (modify-syntax-entry comment-char "<"
+			 generic-mode-syntax-table)
+    (modify-syntax-entry ?\n ">"
+			 generic-mode-syntax-table)))
+
+(defun generic-mode-set-comment-string (comment-string)
+  "Set the given string as a comment string for generic mode."
+  (if (not comment-string)
+      nil
+    (setq 
+     comment-end         ""
+     comment-start       comment-string
+     comment-start-skip  (concat comment-start " *")
+     )
+      
+    (let ((first  (elt comment-string 0))
+	  (second (elt comment-string 1)))
+      ;; C++ style comments
+      (if (char-equal first second)
+	  (progn
+	    (modify-syntax-entry first "<12b"
+				 generic-mode-syntax-table)
+	    (modify-syntax-entry ?\n ">b"
+				 generic-mode-syntax-table)))
+      ;; Some other two character string
+      (modify-syntax-entry first  "<1"
+			   generic-mode-syntax-table)
+      (modify-syntax-entry second "<2"
+			   generic-mode-syntax-table)
+      (modify-syntax-entry ?\n ">"
+			   generic-mode-syntax-table))))
+
+(defun generic-mode-set-comment-pair (comment-pair)
+  "Set the given comment pair as a comment start and end for generic mode."
+  (let ((generic-comment-start (car comment-pair))
+	(generic-comment-end   (cdr comment-pair))
+	)
+    (setq 
+     comment-end         generic-comment-end
+     comment-start       generic-comment-start
+     comment-start-skip  (concat generic-comment-start " *")
+     )
+
+    ;; Sanity checks
+    (if (not (and (stringp generic-comment-start)
+		  (stringp generic-comment-end)))
+	(error "Elements of cons pair must be strings"))
+    (if (not (and (equal (length generic-comment-start) 2)
+		  (equal (length generic-comment-end) 2)))
+	(error "Start and end must be exactly two characters long"))
+
+    (let ((first   (elt generic-comment-start 0))
+	  (second  (elt generic-comment-start 1))
+	  (third   (elt generic-comment-end   0))
+	  (fourth  (elt generic-comment-end   1))
+	  )
+
+      (modify-syntax-entry first   ". 1" generic-mode-syntax-table)
+      (modify-syntax-entry second  ". 2" generic-mode-syntax-table)
+
+      (modify-syntax-entry 
+       third  
+       (concat 
+	"."
+	(cond 
+	 ((char-equal first   third) " 13")
+	 ((char-equal second  third) " 23")
+	 (t			     " 3"))
+	)
+       generic-mode-syntax-table)
+
+      (modify-syntax-entry 
+       fourth  
+       (concat 
+	"."
+	(cond 
+	 ((char-equal first   fourth) " 14")
+	 ((char-equal second  fourth) " 24")
+	 (t			      " 4"))
+	)
+       generic-mode-syntax-table)
+      ))) 
+
+(defun generic-mode-set-font-lock (keywords font-lock-expressions)
+  "Set up font-lock functionality for generic mode."
+  (let ((generic-font-lock-expressions))
+    ;; Keywords
+    (if keywords
+	(setq
+	 generic-font-lock-expressions
+	 (append
+	  (list
+	   (list
+	    (concat 
+	     "\\(\\<"
+	     (mapconcat 'identity keywords "\\>\\|\\<")
+	     "\\>\\)") 
+	    1 'font-lock-keyword-face))
+	  generic-font-lock-expressions)))
+    ;; Other font-lock expressions
+    (if font-lock-expressions
+	(setq generic-font-lock-expressions
+	      (append
+	       font-lock-expressions
+	       generic-font-lock-expressions)))
+    (if (not (or font-lock-expressions keywords))
+	nil
+      (setq generic-font-lock-defaults generic-font-lock-expressions))
+    ))
+
+(defun alter-generic-mode (mode alter-list &optional how-to-alter)
+  "Alter the specified generic mode.
+How-to-alter, if specified, should be one of the following symbols:
+`append', `prepend', `overwrite'. The default is `append'."
+  (let ((generic-mode-list  (assoc mode generic-mode-alist))
+	(item-number 0)
+	(current-elt) 
+	(current-list)
+	(alter-elt)
+	(alter-method (or how-to-alter 'append))
+	)
+    (if (not generic-mode-list)
+	(error "Can't find generic-mode information for type %s"
+	       (princ mode)))
+    ;; Ignore the name
+    (setq generic-mode-list (cdr generic-mode-list))
+    (while (< item-number (length alter-list)) 
+      (setq current-list (nthcdr item-number generic-mode-list)
+	    current-elt  (nth    item-number generic-mode-list)
+	    alter-elt    (nth    item-number alter-list))
+      (cond 
+       ;; Ignore items with value t
+       ((eq alter-elt 't)
+	     nil)
+       ((eq alter-method 'overwrite)
+	(setcar current-list alter-elt))
+       ((eq alter-method 'prepend)
+	(setcar current-list (append alter-elt current-elt)))
+       ((eq alter-method 'append)
+	(setcar current-list (append current-elt alter-elt)))
+       (t
+	(error "Optional argument %s not understood" (princ alter-method))))
+      (setq item-number (1+ item-number))
+      )
+    )
+  )
+
+;; Convenience functions
+(defun alter-generic-mode-comments (mode comment-list &optional how-to-alter)
+  "Alter comments in the specified generic mode.
+How-to-alter, if specified, should be one of the following symbols:
+`append', `prepend', `overwrite'. The default is `append'."
+  (alter-generic-mode mode (list comment-list t t t t) how-to-alter))
+
+(defun alter-generic-mode-keywords (mode keyword-list &optional how-to-alter)
+  "Alter keywords in the specified generic mode.
+How-to-alter, if specified, should be one of the following symbols:
+`append', `prepend', `overwrite'. The default is `append'."
+  (alter-generic-mode mode (list t keyword-list t t t) how-to-alter))
+
+(defun alter-generic-mode-font-lock (mode font-lock-list &optional how-to-alter)
+  "Alter font-lock expressions in the specified generic mode.
+How-to-alter, if specified, should be one of the following symbols:
+`append', `prepend', `overwrite'. The default is `append'."
+  (alter-generic-mode mode (list t t font-lock-list t t) how-to-alter))
+
+(defun alter-generic-mode-functions (mode function-list &optional how-to-alter)
+  "Alter functions in the specified generic mode.
+How-to-alter, if specified, should be one of the following symbols:
+`append', `prepend', `overwrite'. The default is `append'."
+  (alter-generic-mode mode (list t t t t function-list) how-to-alter))
+
+;; This one is different because it takes effect immediately
+;; Appending or Prepending to auto-mode-alist is ignored,
+;; since the effect is the same either way
+(defun alter-generic-mode-auto-mode 
+  (mode auto-mode-list &optional how-to-alter)
+  "Alter auto-mode-alist regular expressions in the specified generic mode.
+How-to-alter, if specified, should be one of the following symbols:
+`append', `prepend', `overwrite'. The default is `append'."
+  (alter-generic-mode mode (list t t t auto-mode-list  t) how-to-alter)
+  (let ((alter-method (or how-to-alter 'append)))
+    (cond ((eq alter-method 'overwrite)
+	   (generic-add-to-auto-mode mode auto-mode-list t))
+	  ((eq alter-method 'append)
+	   (generic-add-to-auto-mode mode auto-mode-list nil))
+	  ((eq alter-method 'prepend)
+	   (generic-add-to-auto-mode mode auto-mode-list nil t))
+	  (t
+	   (error "Optional argument %s not understood" (princ alter-method))))
+    ))
+
+;; Support for [KEYWORD] constructs found in INF, INI and Samba files
+(defun generic-bracket-support ()
+  (setq imenu-generic-expression 
+	'((nil "^\\[\\(.*\\)\\]" 1))))
+
+;; This generic mode is always defined
+(define-generic-mode 'default-generic-mode (list ?#)  nil nil nil nil)
+
+;; A more general solution would allow us to enter generic-mode for
+;; *any* comment character, but would require us to synthesize a new
+;; generic-mode on the fly. I think this gives us most of what we
+;; want.
+(defun generic-mode-find-file-hook ()
+  "Hook to enter default-generic-mode automatically 
+if the first few lines of a file in fundamental-mode start with a hash 
+comment character. This hook will be installed if the variable 
+`generic-use-find-file-hook' is non-nil. The variable `generic-lines-to-scan'
+determines the number of lines to look at."
+  (if (not (eq major-mode 'fundamental-mode))
+      nil
+    (if (or (> 1  generic-lines-to-scan)
+	    (< 50 generic-lines-to-scan))
+	(error "Variable `generic-lines-to-scan' should be set to a small"
+	       " positive number"))
+    (let ((comment-regexp "")
+	  (count 0)
+	  )
+      (while (< count generic-lines-to-scan)
+	(setq comment-regexp (concat comment-regexp 
+				     generic-find-file-regexp))
+	(setq count (1+ count)))
+      (save-excursion
+	(goto-char (point-min))
+	(if (looking-at comment-regexp)
+	    (generic-mode-with-type 'default-generic-mode))))))
+
+(if generic-use-find-file-hook
+    (add-hook 'find-file-hooks 'generic-mode-find-file-hook))
+
+(defun generic-make-keywords-list (keywords-list face &optional prefix suffix)
+  "Return a regular expression matching the specified keywords.
+The regexp is highlighted with FACE."
+  ;; Sanity checks
+  ;; Don't check here; face may not be defined yet
+  ;;   (if (not (facep face))
+  ;;       (error "Face %s is not defined" (princ face)))
+  (if (not (listp keywords-list))
+      (error "Keywords argument must be a list of strings"))
+  (list
+   (concat 
+    (or prefix "")
+    "\\(\\<"
+    (mapconcat 'identity keywords-list "\\>\\|\\<")
+    "\\>\\)"
+    (or suffix "")
+    ) 1 face))
+
+(provide 'generic-mode)
+
+;;; generic-mode.el ends here
+
+;; Local Variables:
+;; autocompile: t
+;; End: