home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / pas-filt.c < prev    next >
C/C++ Source or Header  |  1998-05-19  |  10KB  |  455 lines

  1. /*
  2.  * Program: A simple comment and keyword attributer for vile
  3.  * Author : Jukka Keto, jketo@cs.joensuu.fi
  4.  * Date   : 30.12.1994
  5.  * Modifications:  kevin buettner and paul fox  2/95
  6.  *         string literal ("Literal") support --  ben stoltz
  7.  *
  8.  * $Header: /usr/build/vile/vile/RCS/pas-filt.c,v 1.2 1998/05/19 19:24:11 tom Exp $
  9.  *
  10.  * Features:
  11.  *     - Reads the keyword file ".vile.keywords" from the home directory.
  12.  *      Keyword file consists lines "keyword:attribute" where
  13.  *      keyword is any alphanumeric string [#a-zA-Z0-9_] followed
  14.  *      by colon ":" and attribute character; "I" for italic,
  15.  *      "U" for underline, "B" for bold, "R" for reverse or
  16.  *      "C#" for color (where # is a single hexadecimal digit representing
  17.  *      one of 16 colors).
  18.  *    - Attributes the file read from stdin using vile attribute sequences
  19.  *      and outputs the file to stdout with keywords and comments
  20.  *      attributed.
  21.  *    - Comments are handled by the pseudo-keyword "Comments".
  22.  *    - "String literals" are handled by the pseudo-keyword "Literals".
  23.  *    - Here is a macro one might use to invoke the colorizer:
  24.  *        30 store-macro
  25.  *            write-message "[Attaching Pascal attributes...]"
  26.  *            set-variable %savcol $curcol
  27.  *            set-variable %savline $curline
  28.  *            set-variable %modified $modified
  29.  *            goto-beginning-of-file
  30.  *            filter-til end-of-file "pas-filt"
  31.  *            goto-beginning-of-file
  32.  *            attribute-cntl_a-sequences-til end-of-file
  33.  *            ~if ¬ %modified
  34.  *                unmark-buffer
  35.  *            ~endif
  36.  *            %savline goto-line
  37.  *            %savcol goto-column
  38.  *            write-message "[Attaching Pascal attributes...done ]"
  39.  *        ~endm
  40.  *        bind-key execute-macro-30 ^X-q
  41.  *
  42.  * Here's the .vile.keywords file which I used to test:
  43. Comments:C2
  44. Literal:U
  45. goto:C2
  46. and:B
  47. begin:B
  48. case:B
  49. case:B
  50. constructor:B
  51. do:B
  52. else:B
  53. end:B
  54. function:B
  55. if:B
  56. not:B
  57. of:B
  58. or:B
  59. procedure:B
  60. program:B
  61. record:B
  62. repeat:B
  63. then:B
  64. type:B
  65. unit:B
  66. until:B
  67. uses:B
  68. while:B
  69. with:B
  70. array:C4
  71. array:C4
  72. boolean:C4
  73. byte:C4
  74. char:C4
  75. const:C4
  76. const:C4
  77. file:C4
  78. integer:C4
  79. packed:C4
  80. pointer:C4
  81. real:C4
  82. set:C4
  83. var:C4
  84. word:C4
  85.  */
  86.  
  87. #ifdef HAVE_CONFIG_H
  88. #include "config.h"
  89. #else
  90. /* assume ANSI C */
  91. # define HAVE_STDLIB_H 1
  92. # define HAVE_STRING_H 1
  93. #endif
  94.  
  95. #include <sys/types.h>        /* sometimes needed to get size_t */
  96.  
  97. #if HAVE_STDLIB_H
  98. #include <stdlib.h>
  99. #else
  100. # if !defined(HAVE_CONFIG_H) || MISSING_EXTERN_MALLOC
  101. extern    char *    malloc    ( size_t len );
  102. # endif
  103. #endif
  104.  
  105. #ifdef HAVE_UNISTD_H
  106. #include <unistd.h>
  107. #endif
  108.  
  109. #include <stdio.h>
  110.  
  111. #ifdef HAVE_STRING_H
  112. #include <string.h>
  113. #endif
  114.  
  115. #if MISSING_EXTERN__FILBUF
  116. extern    int    _filbuf    ( FILE *fp );
  117. #endif
  118.  
  119. #if MISSING_EXTERN__FLSBUF
  120. extern    int    _flsbuf    ( int len, FILE *fp );
  121. #endif
  122.  
  123. #if MISSING_EXTERN_FCLOSE
  124. extern    int    fclose    ( FILE *fp );
  125. #endif
  126.  
  127. #if MISSING_EXTERN_FPRINTF
  128. extern    int    fprintf    ( FILE *fp, const char *fmt, ... );
  129. #endif
  130.  
  131. #if MISSING_EXTERN_PRINTF
  132. extern    int    printf    ( const char *fmt, ... );
  133. #endif
  134.  
  135. #if MISSING_EXTERN_SSCANF
  136. extern    int    sscanf    ( const char *src, const char *fmt, ... );
  137. #endif
  138.  
  139. #if OPT_LOCALE
  140. #include <locale.h>
  141. #endif
  142. #include <ctype.h>
  143.  
  144. #define MAX_KEYWORD_LENGTH 80
  145. #define HASH_LENGTH 256
  146. #define MAX_LINELENGTH 256
  147. #define MAX_ATTR_LENGTH 3
  148.  
  149. #ifdef _WIN32
  150. static char *keyword_file="vile.keywords";
  151. #define PATHSEP '\\'
  152. #else
  153. # if __GO32__
  154. #define PATHSEP '\\'
  155. static char *keyword_file="vile.key";
  156. # else
  157. #define PATHSEP '/'
  158. static char *keyword_file=".vile.keywords";
  159. # endif
  160. #endif
  161.  
  162. #define isNameBegin(c)   (isalpha(c) || (c) == '_')
  163. #define isNameExtra(c)   (isalnum(c) || (c) == '_')
  164. #define isBlank(c)  ((c) == ' ' || (c) == '\t')
  165.  
  166. #define L_CURL '{'
  167. #define R_CURL '}'
  168. #define QUOTE  '\''
  169.  
  170. typedef struct _keyword KEYWORD;
  171.  
  172. struct _keyword {
  173.     char kw[MAX_KEYWORD_LENGTH+1];    /* stores lowercase keyword */
  174.     char ow[MAX_KEYWORD_LENGTH+1];    /* stores original keyword */
  175.     char attribute[MAX_ATTR_LENGTH+1];
  176.     int  length;
  177.     KEYWORD *next;
  178. };
  179.  
  180. static KEYWORD *hashtable[HASH_LENGTH];
  181. static KEYWORD identifier;
  182. static char comment_attr[MAX_ATTR_LENGTH+1] = "C1"; /* color 1 */
  183. static char literal_attr[MAX_ATTR_LENGTH+1] = "C2"; /* color 1 */
  184.  
  185. static void
  186. inithash(void)
  187. {
  188.     int i;
  189.     for (i=0;i<HASH_LENGTH;i++) hashtable[i] = NULL;
  190. }
  191.  
  192. static void
  193. removelist(KEYWORD *k)
  194. {
  195.     if (k != NULL) {
  196.     if (k->next != NULL) removelist(k->next);
  197.     free((char *)k);
  198.     }
  199. }
  200.  
  201. static void
  202. closehash(void)
  203. {
  204.     int i;
  205.     for (i=0;i<HASH_LENGTH;i++) {
  206.     removelist(hashtable[i]);
  207.     hashtable[i] = NULL; /* For unseen future i do this */
  208.     }
  209. }
  210.  
  211. static int
  212. hash_function(char *id)
  213. {
  214.     /*
  215.      * Build more elaborate hashing scheme. If you want one.
  216.      */
  217.     return ( (int) *id );
  218. }
  219.  
  220. static void
  221. insert_keyword(
  222.     char *ident,
  223.     char *attribute)
  224. {
  225.     KEYWORD *first;
  226.     KEYWORD *nxt;
  227.     int Index;
  228.     if (!strcmp(ident,"Comments")) {
  229.     (void)strcpy(comment_attr,attribute);
  230.     return;
  231.     }
  232.     if (!strcmp(ident,"Literal")) {
  233.     strcpy(literal_attr,attribute);
  234.     return;
  235.     }
  236.     nxt = first = NULL;
  237.     Index = hash_function(ident);
  238.     first = hashtable[Index];
  239.     if ((nxt = (KEYWORD *)malloc(sizeof(struct _keyword))) != NULL) {
  240.     (void)strcpy(nxt->kw,ident);
  241.     nxt->length = strlen(nxt->kw);
  242.     (void)strcpy(nxt->attribute,attribute);
  243.     nxt->next = first;
  244.     hashtable[Index] = nxt;
  245. #ifdef DEBUG
  246.     fprintf(stderr,"insert_keyword: new %li, new->kw %s, new->length %i, new->attribute %c, new->next %li\n", new,
  247.                         nxt->kw, nxt->length, nxt->attribute,nxt->next);
  248. #endif
  249.     }
  250. }
  251.  
  252.  
  253. static void
  254. match_identifier(void)
  255. {
  256.     KEYWORD *hash_id;
  257.     int Index, match = 0;
  258.  
  259.     Index = hash_function(identifier.kw);
  260.     hash_id = hashtable[Index];
  261.  
  262.     while (hash_id != NULL) {
  263.     if (hash_id->length == identifier.length) { /* Possible match */
  264.         if (strcmp(hash_id->kw,identifier.kw) == 0) {
  265.         match = 1;
  266.         break;
  267.         }
  268.     }
  269.     hash_id = hash_id->next;
  270.     }
  271.     if (match)
  272.     printf("\001%i%s:", identifier.length, hash_id->attribute);
  273.     printf("%s",identifier.ow);
  274. }
  275.  
  276.  
  277. static char *
  278. extract_identifier(char *s)
  279. {
  280.     register char *kwp = identifier.kw;
  281.     register char *owp = identifier.ow;
  282.  
  283.     identifier.length = 0;
  284.  
  285.     while ((isNameExtra(*s)) &&
  286.            identifier.length < MAX_KEYWORD_LENGTH) {
  287.     identifier.length += 1;
  288.     if (isalpha(*s) && isupper(*s))
  289.         *kwp++ = tolower(*s);
  290.     else
  291.         *kwp++ = *s;
  292.     *owp++ = *s++;
  293.     }
  294.     *kwp = '\0';
  295.     *owp = '\0';
  296.     return(s);
  297. }
  298.  
  299. static FILE *
  300. open_keywords(char *filename)
  301. {
  302.     char *home = getenv("HOME");
  303.     char fullname[1024];
  304.  
  305.     if (home == 0)
  306.         home = "";
  307.     sprintf(fullname, "%s%c%s", home, PATHSEP, filename);
  308.     return fopen(fullname, "r");
  309. }
  310.  
  311. static void
  312. read_keywords(char *filename)
  313. {
  314.     char ident[MAX_KEYWORD_LENGTH+1];
  315.     char line[MAX_LINELENGTH+1];
  316.     char attribute[MAX_ATTR_LENGTH+1];
  317.     int  items;
  318.     FILE *kwfile;
  319.  
  320.     if ((kwfile = open_keywords(filename)) != NULL) {
  321.     fgets(line,MAX_LINELENGTH,kwfile);
  322.     items = sscanf(line,"%[#a-zA-Z0-9_]:%[IUBR]",ident,attribute);
  323.     if (items != 2)
  324.         items = sscanf(line,"%[#a-zA-Z0-9_]:%[C0-9ABCDEF]",ident,attribute);
  325.     while (! feof(kwfile) ) {
  326. #ifdef DEBUG
  327.         fprintf(stderr,"read_keywords: Items %i, kw = %s, attr = %s\n",items,ident,attribute);
  328. #endif
  329.         if (items == 2)
  330.         insert_keyword(ident,attribute);
  331.         fgets(line,MAX_LINELENGTH,kwfile);
  332.         items = sscanf(line,"%[#a-zA-Z0-9_]:%[IUBR]",ident,attribute);
  333.         if (items != 2)
  334.         items = sscanf(line,"%[#a-zA-Z0-9_]:%[C0-9ABCDEF]",ident,attribute);
  335.     }
  336.     fclose(kwfile);
  337.     }
  338. }
  339.  
  340. static int
  341. has_endofcomment(char *s)
  342. {
  343.     int i=0;
  344.     while (*s) {
  345.     if (*s == R_CURL) {
  346.         return(i+1);
  347.     }
  348.     i += 1;
  349.     s += 1;
  350.     }
  351.     return(0);
  352. }
  353.  
  354. static int
  355. has_endofliteral(char *s)    /* points past beginning QUOTE */
  356. {
  357.     int i = 0;
  358.  
  359.     while (s[i]) {
  360.     if (s[i] == QUOTE) {
  361.         if (s[i+1] == QUOTE) {
  362.         i += 2;
  363.         } else {
  364.             return (i);    /* points before ending QUOTE */
  365.         }
  366.     }
  367.     ++i;
  368.     }
  369.     return(0);
  370. }
  371.  
  372. static char *
  373. skip_white(char *s)
  374. {
  375.     while(*s && isBlank(*s))
  376.         putchar(*s++);
  377.     return s;
  378. }
  379.  
  380. static char *
  381. write_literal(char *s)
  382. {
  383.     int c_length = has_endofliteral(s);
  384.     if (c_length == 0)
  385.     c_length = strlen(s);
  386.     printf("\001%i%s:%.*s", c_length, literal_attr, c_length, s);
  387.     s += c_length;
  388.     if (*s == QUOTE)
  389.         putchar(*s++);
  390.     return s;
  391. }
  392.  
  393. int
  394. main(int argc, char **argv)
  395. {
  396.     char line[MAX_LINELENGTH+1];
  397.     char *s;
  398.     int comment,c_length;
  399.  
  400. #if OPT_LOCALE
  401.     setlocale(LC_CTYPE, "");
  402. #endif
  403.  
  404.     comment = 0;
  405.     inithash();
  406.  
  407.     if (argc > 1) {
  408.     int n;
  409.     for (n = 1; n < argc; n++)
  410.         read_keywords(argv[n]);
  411.     } else {
  412.     read_keywords(keyword_file);
  413.     }
  414.  
  415.     while (fgets(line,MAX_LINELENGTH,stdin) != NULL) {
  416.     s = line;
  417.     s = skip_white(s);
  418.     while (*s) {
  419.         if (!comment && *s == L_CURL) {
  420.         c_length = has_endofcomment(s);
  421.         if (c_length == 0) { /* Comment continues to the next line */
  422.             c_length = strlen(s);
  423.             comment = 1;
  424.         }
  425.         printf("\001%i%s:%.*s",c_length,comment_attr,c_length,s);
  426.         s = s + c_length ;
  427.         }
  428.         if (comment && *s) {
  429.         if ((c_length = has_endofcomment(s)) > 0) {
  430.             printf("\001%i%s:%.*s",c_length,comment_attr,c_length,s);
  431.             s = s + c_length ;
  432.             comment = 0;
  433.         } else { /* Whole line belongs to comment */
  434.             c_length = strlen(s);
  435.             printf("\001%i%s:%.*s",c_length,comment_attr,c_length,s);
  436.             s = s + c_length;
  437.         }
  438.         } else if (*s == QUOTE)  {
  439.         putchar(*s++);
  440.         s = write_literal(s);
  441.         } else if (*s) {
  442.         if ( isNameBegin(*s) ) {
  443.             s = extract_identifier(s);
  444.             match_identifier();
  445.         } else {
  446.             putchar(*s++);
  447.         }
  448.         }
  449.     }
  450.     }
  451.     closehash();
  452.  
  453.     exit(0);
  454. }
  455.