/*
SuperCat - The Super Cat Colorizer
Copyright (C) 2007-2008 - Thomas G. Anderson
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "spc.h"
enum { BLK='0', RED, GRN, YEL, BLU, MAG, CYA, WHI };
typedef struct spc_s spc_t;
struct spc_s {
regex_t buffer; /* struct for regexp */
char *string; /* string for strchr, strstr */
char *htmrgb; /* html color codes RGB */
int number; /* 1-9, 0:all */
size_t htmlen; /* length of htmrgb string */
char aryidx; /* array index 1-255, 0=default */
char colour; /* enum */
char attrib; /* -, b, i, u */
char patype; /* c, s, r, t */
};
spc_t Spc [NREGEX+1]; /* 0 is default */
int Spn = 1;
char Att;
char Col;
int opt_debug = 0; /* multi-level */
int opt_reverse = 0; /* 0:whi on blk, 1:blk on whi */
int opt_line_number = 0;
int opt_matching = 0;
int opt_webpage = 0;
int opt_nohomerc = 0;
int opt_nocwdrc = 0;
char *opt_config = 0;
char *opt_directory = 0;
char *opt_type = 0;
char *inp_file = 0;
int inp_lineno = 0;
char *typ_suffix = 0;
void
help ()
{
puts ("usage: spc [OPTIONS] [FILE]");
puts ("");
puts (" -c <CFG>, --config=CFG specify non-standard spcrc config file");
puts (" -C <DIR>, --config-dir=DIR specify non-standard config directory");
puts (" -d, --debug turn on debug information");
puts (" -D, --no-extension don't look at ./.spcrc[-ext] for config file");
puts (" -h, --help print this help and exit");
puts (" -m, --matching print only lines that have matches");
puts (" -n, --line-numbers precede each line with a line number");
puts (" -r, --reverse reverse black and white");
puts (" -R, --nohomedir don't look in ~/.spcrc for config files");
puts (" -S, --printsysdir printf system directory and exit");
puts (" -t <TYP>, --type=TYP specify the effective file type extension");
puts (" -v, --version print version information and exit");
puts (" -w, --webpage generate web page");
puts ("");
puts ("Report bugs to <bug-spc@nosredna.net>");
exit (0);
}
void
version ()
{
printf ("spc (The SuperCat Colorizer) Version %s February 15, 2008", VERSION);
puts ("");
puts ("Copyright (C) 2007-2008 - Thomas G. Anderson");
puts ("This is free software; see the source for copying conditions. There is NO");
puts ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
exit (0);
}
void
sysdir ()
{
printf ("system directory is %s\n", SYSTEM_DIRECTORY);
exit (0);
}
void
err_doit (int errnoflag, int error, const char *fmt, va_list ap)
{
char buf [BUFSIZ];
vsnprintf (buf, BUFSIZ, fmt, ap);
if (errnoflag)
snprintf (buf + strlen(buf), BUFSIZ - strlen(buf), ": %s",
strerror (error));
strcat (buf, "\n");
fflush (stdout);
fputs (buf, stderr);
fflush (NULL);
}
void
err_quit (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
err_doit (0, 0, fmt, ap);
va_end (ap);
exit (-1);
}
void
err_sys (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
err_doit (1, errno, fmt, ap);
va_end (ap);
exit (-1);
}
#ifdef HAVE_GETOPT_H
void
options (int ac, char **av)
{
int c;
static struct option opt_tbl [] = {
{"config", 1, 0, 'c' }, /* specify spcrc config file */
{"config-dir", 1, 0, 'C' }, /* non-standard config directory */
{"debug", 0, 0, 'd' }, /* turn on debug */
{"no-extension", 0, 0, 'D' }, /* don't do extension scraping */
{"help", 0, 0, 'h' }, /* helpful information and exit */
{"matching", 0, 0, 'm' }, /* only show matching portions of a line */
{"line-numbers", 0, 0, 'n' }, /* pre-pend line numbers */
{"reverse", 0, 0, 'r' }, /* reverse black and white */
{"nohomedir", 0, 0, 'R' }, /* don't check home directory */
{"printsysdir", 0, 0, 'S' }, /* print system directory location */
{"type", 1, 0, 't' }, /* specify effective file extension */
{"version", 0, 0, 'v' }, /* show version and exit */
{"webpage", 0, 0, 'w' } /* generate html output */
};
while (1) {
int opt_idx = 0;
switch ((c = getopt_long (ac, av, "c:C:dDhmnrRSt:vw", opt_tbl, &opt_idx))) {
case -1:
goto DONE;
case 0:
printf ("option %s", opt_tbl [opt_idx].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'd': opt_debug++; break;
case 'D': opt_nocwdrc = 1; break;
case 'h': help (); break;
case 'm': opt_matching = 1; break;
case 'n': opt_line_number = 1; break;
case 'r': opt_reverse = 1; break;
case 'R': opt_nohomerc = 1; break;
case 'S': sysdir (); break;
case 'v': version (); break;
case 'w': opt_webpage = 1; break;
case 'c':
opt_config = malloc (strlen (optarg)+1);
strcpy (opt_config, optarg);
break;
case 'C':
opt_directory = malloc (strlen (optarg)+1);
strcpy (opt_directory, optarg);
break;
case 't':
opt_type = malloc (strlen (optarg)+1);
strcpy (opt_type, optarg);
break;
case '?':
break;
default:
printf ("getopt returned character code 0x%02X ??\n", (unsigned char) c);
}
}
DONE:
if (optind < ac) {
if (opt_debug) printf ("non-option ARGV-elements: %s\n", av [optind]);
inp_file = malloc (strlen (av [optind])+1);
strcpy (inp_file, av [optind]);
}
}
#else
void
options (int ac, char **av)
{
int i;
char *p;
for (i=1; i<ac; i++) {
if (!strcmp (av [i], "-h") || !strcmp (av [i], "--help")) help ();
if (!strcmp (av [i], "-v") || !strcmp (av [i], "--version")) version ();
if (!strcmp (av [i], "-S") || !strcmp (av [i], "--printsysdir")) sysdir ();
if (!strcmp (av [i], "-d") || !strcmp (av [i], "--debug")) { opt_debug++; continue; }
if (!strcmp (av [i], "-D") || !strcmp (av [i], "--no-extension")) { opt_nocwdrc = 1; continue; }
if (!strcmp (av [i], "-m") || !strcmp (av [i], "--matching")) { opt_matching = 1; continue; }
if (!strcmp (av [i], "-n") || !strcmp (av [i], "--line-numbers")) { opt_line_number = 1; continue; }
if (!strcmp (av [i], "-r") || !strcmp (av [i], "--reverse")) { opt_reverse = 1; continue; }
if (!strcmp (av [i], "-R") || !strcmp (av [i], "--nohomedir")) { opt_nohomerc = 1; continue; }
if (!strcmp (av [i], "-w") || !strcmp (av [i], "--webpage")) { opt_webpage = 1; continue; }
if (!strcmp (av [i], "-c")) {
if (!av[++i]) err_quit ("missing parameter to -c");
opt_config = malloc (strlen (av[i])+1);
strcpy (opt_config, av [i]);
continue;
}
if (!strncmp (av [i], "--config", strlen ("--config"))) {
if (*(p = av [i] + strlen ("--config")) != '=')
err_quit ("invalid character in --config");
if (!*(++p))
err_quit ("missing parameter to --config");
opt_config = malloc (strlen (p)+1);
strcpy (opt_config, p);
continue;
}
if (!strcmp (av [i], "-C")) {
if (!av[++i]) err_quit ("missing parameter to -C");
opt_directory = malloc (strlen (av[i])+1);
strcpy (opt_directory, av [i]);
continue;
}
if (!strncmp (av [i], "--config-dir", strlen ("--config-dir"))) {
if (*(p = av [i] + strlen ("--config-dir")) != '=')
err_quit ("invalid character in --config-dir");
if (!*(++p))
err_quit ("missing parameter to --config-dir");
opt_directory = malloc (strlen (p)+1);
strcpy (opt_directory, p);
continue;
}
if (!strcmp (av [i], "-t")) {
if (!av[++i]) err_quit ("missing parameter to -t");
opt_type = malloc (strlen (av[i])+1);
strcpy (opt_type, av [i]);
continue;
}
if (!strncmp (av [i], "--type", strlen ("--type"))) {
if (*(p = av [i] + strlen ("--type")) != '=')
err_quit ("invalid character in --type");
if (!*(++p))
err_quit ("missing parameter to --type");
opt_type = malloc (strlen (p)+1);
strcpy (opt_type, p);
continue;
}
if (i == (ac-1)) {
inp_file = malloc (strlen (av [i])+1);
strcpy (inp_file, av [i]);
continue;
}
err_quit ("unknown option %s", av [i]);
}
}
#endif
void
obtain_suffix ()
{
char *p;
/*
* if we are using stdin then we won't have any file.
*/
if (!inp_file) return;
typ_suffix = malloc (strlen (inp_file)+1);
strcpy (typ_suffix, inp_file);
/*
* Find the file suffix from the end of the string,
* back to either a '.' or if a '/' is found then it
* is a file name, that's ok. this means that "xx.c"
* becomes "c" and that ".../file" becomes "file".
*/
p = &typ_suffix [strlen (typ_suffix)-1];
while (*p != '.' && *p != '/' && p != typ_suffix) p--;
if (*p == '.' || *p == '/') p++;
/*
* However, if the suffix or file name is "log", we
* want to try and go back to the beginning to see if
* we can find a more definitive name. That means
* that "Xorg.0.log" becomes "Xorg".
*/
if (!strcmp (p, "log") && p != typ_suffix) {
p--;
while (*p != '/' && p != typ_suffix) {
if (*p == '.') *p = 0;
p--;
}
if (*p == '.' || *p == '/') p++;
}
strcpy (typ_suffix, p);
}
FILE *
config_check (char *file)
{
struct stat status_buffer [1];
FILE *rc;
if (opt_debug) printf ("trying config file: %s\n", file);
if (stat (file, status_buffer) == -1) return (0);
if (!S_ISREG (status_buffer->st_mode)) return (0);
if (!(rc = fopen (file, "r"))) return (0);
if (opt_debug) printf ("using config file: %s\n", file);
return (rc);
}
FILE *
config_search (char *file)
{
char string [1024];
char *home = getenv ("HOME");
FILE *rc;
if (!opt_nocwdrc) {
sprintf (string, "./.%s", file);
if ((rc = config_check (string))) return (rc);
if ((rc = config_check ("./.spcrc"))) return (rc);
}
if (home && !opt_nohomerc) {
sprintf (string, "%s/.spcrc/%s", home, file);
if ((rc = config_check (string))) return (rc);
sprintf (string, "%s/.spcrc/spcrc", home);
if ((rc = config_check (string))) return (rc);
}
if (opt_directory) {
sprintf (string, "%s/%s", opt_directory, file);
if ((rc = config_check (string))) return (rc);
sprintf (string, "%s/spcrc", opt_directory);
if ((rc = config_check (string))) return (rc);
}
sprintf (string, "%s/%s", SYSTEM_DIRECTORY, file);
if ((rc = config_check (string))) return (rc);
sprintf (string, "%s/spcrc", SYSTEM_DIRECTORY);
if ((rc = config_check (string))) return (rc);
if (opt_debug)
err_quit ("can't find a config file");
else
err_quit ("can't find a config file, try using -d to show where I'm checking");
}
FILE *
configure ()
{
FILE *rc;
char *home, *temp;
/*
* Open *conf_file, ./.spcrc, ~/.spcrc, /etc/spcrc
*/
if (opt_config) {
if (!strncmp (opt_config, "~/", 2)) {
if (!(home = getenv ("HOME")))
err_quit ("can't find home directory");
temp = malloc (strlen (home)+strlen (opt_config)+1);
strcpy (temp, home);
strcat (temp, opt_config+1);
} else
temp = opt_config;
if (!(rc = config_check (temp)))
err_quit ("can't open config file %s", temp);
free (temp);
return (rc);
}
/*
* look for spcrc-type in the standard locations
*/
if (opt_type) {
opt_config = malloc (strlen (opt_type)+7);
sprintf (opt_config, "spcrc-%s", opt_type);
return (config_search (opt_config));
}
obtain_suffix ();
/*
* look for spcrc-suffix in the standard locations
*/
if (typ_suffix) {
opt_config = malloc (strlen (typ_suffix)+7);
sprintf (opt_config, "spcrc-%s", typ_suffix);
return (config_search (opt_config));
}
err_quit ("can't find a config file");
}
char
colour_lookup (char *str)
{
if (!strcmp (str, "blk")) return (BLK);
if (!strcmp (str, "red")) return (RED);
if (!strcmp (str, "grn")) return (GRN);
if (!strcmp (str, "yel")) return (YEL);
if (!strcmp (str, "blu")) return (BLU);
if (!strcmp (str, "mag")) return (MAG);
if (!strcmp (str, "cya")) return (CYA);
if (!strcmp (str, "whi")) return (WHI);
err_quit ("unknown color %s at line number %d", str, inp_lineno);
}
int
number_lookup (char chr)
{
if (chr == ' ') return (999);
if (chr == '0') return (999);
if (chr == '1') return (1);
if (chr == '2') return (2);
if (chr == '3') return (3);
if (chr == '4') return (4);
if (chr == '5') return (5);
if (chr == '6') return (6);
if (chr == '7') return (7);
if (chr == '8') return (8);
if (chr == '9') return (9);
err_quit ("unknown number %c at line number %d", chr, inp_lineno);
}
char
attrib_lookup (char chr)
{
if (chr == '-') return ('0');
if (chr == ' ') return ('0');
if (chr == 'b') return ('1');
if (chr == 'u') return ('4');
if (chr == 'k') return ('5');
if (chr == 'r') return ('7');
err_quit ("unknown attribute %c at line number %d", chr, inp_lineno);
}
char
patype_lookup (char chr)
{
if (chr == ' ') return (PATYPE_REGEXP);
if (chr == 'c') return (PATYPE_CHARS);
if (chr == 'r') return (PATYPE_REGEXP);
if (chr == 's') return (PATYPE_STRING);
if (chr == 't') return (PATYPE_UNIXTM);
err_quit ("unknown pattern type %c at line number %d", chr, inp_lineno);
}
int
colour_str (spc_t *spc, char *string, char *aryidx, int n)
{
int i, j, rtn=0, t=spc->number;
int m = strlen (spc->string);
char *p = string;
char *q;
/*
* This function moves a pointer 'p' though a string
* using strstr() to find the specified sub-string.
* After coloring the matched substring the pointer
* is bumped past the sub-string and the search
* continues.
*/
while ((q = strstr (p, spc->string)) && t--) {
i = q - string;
rtn = 1;
for (j=0; j<m; j++, i++) {
aryidx [i] = spc->aryidx;
}
p = q + m;
}
return (rtn);
}
int
colour_chr (spc_t *spc, char *string, char *aryidx, int n)
{
int i, rtn=0, t=spc->number;
for (i=0; i<n; i++) {
if (spc->string [string [i]]) {
rtn = 1;
aryidx [i] = spc->aryidx;
if (!--t) break;
}
}
return (rtn);
}
/*
* The theory behind this function is the use of parenthesized REs
* to select the text to be colored. For example, take the RE
* h(e)l(l)o
* This would create 3 matches from regexec(), one for the entire
* string "hello", one for the first parenthsized "e" and one for
* the parenthsized "l". The code ignores the first match and
* begins with the second match.
*/
int
colour_rex (spc_t *spc, char *string, char *aryidx, int n)
{
struct tm *tm;
regmatch_t pmatch [NMATCH], *m;
int nmatch= NMATCH;
int flag = 0;
time_t unixtm;
int i, j, ini, rtn=0, t=spc->number;
char *p=string, *q;
while (t--) {
/*
* Match against supplied string. Pointer 'p' points to
* the current start of string. This pointer is moved
* through the input string, being bumped past each of
* the matches since regexec only returns the first of
* possibly multiple matches within a string. The t--
* above allows control of how many matches to allow.
*/
memset (pmatch, 0, sizeof (pmatch));
if (regexec (&spc->buffer, p, nmatch, pmatch, flag))
return (rtn);
rtn = 1;
ini = 0;
flag = REG_NOTBOL;
/*
* Set the colour array index associated with each match.
* Start at the second entry since the first one is for the
* entire match while the rest are for parenthesized REs.
*/
for (m=pmatch+1; m->rm_so != (regoff_t) -1; m++) {
j = p - string;
for (i=m->rm_so+j; i<m->rm_eo+j; i++)
aryidx [i] = spc->aryidx;
/*
* This hack converts a 10-digit Unix time-since-epoch
* into a human-readable format MMDDHHMMSS within the
* same 10 characters so the string stays the same size.
*/
if (spc->patype == PATYPE_UNIXTM) {
if ((m->rm_eo - m->rm_so) != 10) continue;
unixtm = 0;
for (i=m->rm_so+j; i<m->rm_eo+j; i++) {
unixtm *= 10;
unixtm += string [i] - '0';
}
tm = localtime (&unixtm);
i = m->rm_so;
tm->tm_mon++;
string [i++] = (tm->tm_mon / 10) + '0' ;
string [i++] = (tm->tm_mon % 10) + '0' ;
string [i++] = (tm->tm_mday / 10) + '0' ;
string [i++] = (tm->tm_mday % 10) + '0' ;
string [i++] = (tm->tm_hour / 10) + '0' ;
string [i++] = (tm->tm_hour % 10) + '0' ;
string [i++] = (tm->tm_min / 10) + '0' ;
string [i++] = (tm->tm_min % 10) + '0' ;
string [i++] = (tm->tm_sec / 10) + '0' ;
string [i++] = (tm->tm_sec % 10) + '0' ;
}
if (opt_debug > 1) {
for (q=string, i=0; *q; q++) {
if (i++ == m->rm_so) putchar ('<');
putchar (*q );
if (i == m->rm_eo) putchar ('>');
}
putchar ('\n');
}
}
p += pmatch->rm_eo;
}
return (rtn);
}
int
colour_sca (char *string, char *aryidx, int n)
{
int i, r, rtn=0;
char *p;
spc_t *spc;
memset (aryidx, 0, n);
/*
* Process each converted entry from the config file
* using the appropriate matching algorithm. The 'rtn'
* variable is used to pass back information about
* whether a match was found or not for subsequent use
* in conjunction with 'opt_matching'.
*/
for (spc=Spc, r=0; r<Spn; r++, spc++) {
if (spc->patype == PATYPE_REGEXP)
rtn |= colour_rex (spc, string, aryidx, n);
else if (spc->patype == PATYPE_STRING)
rtn |= colour_str (spc, string, aryidx, n);
else if (spc->patype == PATYPE_CHARS)
rtn |= colour_chr (spc, string, aryidx, n);
else /* PATYPE_UNIXTM */
rtn |= colour_rex (spc, string, aryidx, n);
}
if (opt_debug > 3) {
p = string; for (i=0; i<n; i++) putchar (*p++); putchar ('\n');
p = aryidx; for (i=0; i<n; i++) putchar (*p++); putchar ('\n');
}
return (rtn);
}
char *
printf_htm_entity (char *b, char *p)
{
switch (*p) {
case '<': strcpy (b, "<"); b += 4; break;
case '>': strcpy (b, ">"); b += 4; break;
case '"': strcpy (b, """); b += 6; break;
case '\'': strcpy (b, "'"); b += 6; break;
case '&': strcpy (b, "&"); b += 5; break;
default: *b++ = *p; break;
}
return (b);
}
void
printf_htm (char *string, char *aryidx, int n)
{
char output [BUFFER*4];
char *p = string;
char *q = aryidx;
char *b = output;
spc_t *spc;
int i, ini=0;
Col = -1;
*b = 0;
for (i=0; i<n; i++, p++, q++) {
spc = &Spc [*q];
if (spc->colour != Col) {
if (ini) {
strcpy (b, "</font>");
b += 7;
}
strcpy (b, "<font color=\""); b += 13;
strcpy (b, spc->htmrgb); b += spc->htmlen;
strcpy (b, "\">"); b += 2;
Col = spc->colour;
}
b = printf_htm_entity (b, p);
ini = 1;
}
if (n) {
strcpy (b, "</font>");
b += 11;
}
*b++ = 0;
if (opt_line_number) printf ("%5d: ", inp_lineno);
puts (output);
}
void
printf_con (char *string, char *aryidx, int n)
{
char output [BUFFER*2];
char *p = string;
char *q = aryidx;
char *b = output;
spc_t *spc;
int i;
*b++ = 0x1B;
*b++ = '[';
*b++ = Att = Spc->attrib;
*b++ = ';';
*b++ = '3';
*b++ = Col = Spc->colour;
*b++ = 'm';
for (i=0; i<n; i++, q++) {
spc = &Spc [*q];
if (spc->colour != Col || spc->attrib != Att) {
*b++ = 0x1B;
*b++ = '[';
if (spc->attrib != Att) {
*b++ = Att = spc->attrib ;
if (spc->colour != Col)
*b++ = ';';
}
if (spc->colour != Col) {
*b++ = '3';
*b++ = Col = spc->colour ;
}
*b++ = 'm';
}
*b++ = *p++;
}
*b++ = 0x1B;
*b++ = '[';
*b++ = Spc->attrib;
*b++ = ';';
*b++ = '3';
*b++ = Spc->colour;
*b++ = 'm';
*b++ = 0;
if (opt_line_number) printf ("%5d: ", inp_lineno);
puts (output);
}
void
create_rex (FILE *fp)
{
char buffer [BUFFER], *p;
int n;
spc_t *spc;
memset (Spc, 0, sizeof (Spc));
spc = Spc;
spc->aryidx = 0;
spc->colour = WHI;
spc->attrib = '0';
spc->htmrgb = (opt_reverse) ? "Black" : "White" ;
spc->htmlen = strlen (spc->htmrgb);
spc++;
/*
* This loop reads each line of the config file and
* processes it according to its pattern type field.
* If it is a RE ('r' or 't') it is compiled. If it
* is a simple character set ('c') or string ('s')
* the strings are just stored.
*/
while (fgets (buffer, sizeof (buffer), fp)) {
n = strlen (buffer);
if (n == BUFFER)
err_quit ("line too long: %s", buffer);
inp_lineno++;
buffer [n-1] = 0;
buffer [COLUMN_COLOUR+3] = 0;
if (*buffer == '#') continue; /* comment */
if (*buffer == 0 ) continue; /* blank line */
if (buffer [COLUMN_HTMRGB] == ' ')
strcpy (&buffer [COLUMN_HTMRGB], (opt_reverse) ? "Black" : "White");
else {
p = &buffer [COLUMN_HTMRGB];
while (*p != ' ') p++ ;
*p = 0;
}
spc->aryidx = Spn;
spc->colour = colour_lookup (&buffer [COLUMN_COLOUR]);
spc->attrib = attrib_lookup ( buffer [COLUMN_ATTRIB]);
spc->number = number_lookup ( buffer [COLUMN_NUMBER]);
spc->patype = patype_lookup ( buffer [COLUMN_PATYPE]);
spc->htmrgb = malloc (strlen (&buffer [COLUMN_HTMRGB]) + 1);
strcpy (spc->htmrgb,&buffer [COLUMN_HTMRGB]);
spc->htmlen = strlen (spc->htmrgb);
if (spc->patype == PATYPE_REGEXP ||
spc->patype == PATYPE_UNIXTM) {
/*
* Compile the regular expression
*/
if ((n = regcomp (&spc->buffer, buffer+COLUMN_CREGEX, REG_EXTENDED))) {
fprintf (stderr, "regcomp error: %s\n", buffer+COLUMN_CREGEX);
regerror (n, &spc->buffer, buffer, sizeof (buffer));
err_quit ("%s", buffer);
}
} else if (spc->patype == PATYPE_CHARS) {
/*
* Allocate a 256 byte array, one for each ASCII
* character and set each location to 1 that has
* a corresponding character in the input string.
*/
spc->string = malloc (256);
memset (spc->string, 0, 256);
n=strlen (buffer+COLUMN_CREGEX-1);
for (p=buffer+COLUMN_CREGEX; *p; p++)
spc->string [*p] = 1;
} else {
/*
* just save the string expression
*/
spc->string = malloc (strlen (buffer+COLUMN_CREGEX-1));
strcpy (spc->string, buffer+COLUMN_CREGEX);
}
Spn++;
spc++;
}
if (Spn == 1)
err_quit ("config file %s is invalid", opt_config);
}
void
initialize_con ()
{
putchar (0x1B);
putchar ('[');
putchar (Att = Spc->attrib);
putchar (';');
putchar ('3');
putchar (Col = Spc->colour);
putchar ('m');
}
void
finalize_con ()
{
putchar (0x1B);
putchar ('[');
putchar ('0');
putchar (';');
putchar ('m');
}
void
initialize_htm ()
{
puts ("<html>");
puts ("<head>");
puts ("<style type=\"text/css\">");
puts ("body { font-family: courier; white-space: nowrap }");
puts ("</style>");
printf ("<title>Colorized by supercat %s</title>\n", VERSION);
puts ("</head>");
printf ("<body bgcolor=\"%s\">\n", (opt_reverse) ? "White" : "Black" );
puts ("<pre>");
}
void
finalize_htm ()
{
puts ("</pre>");
puts ("</body>");
puts ("</html>");
}
FILE *
input_open ()
{
FILE *in = stdin;
struct stat status_buffer [1];
if (inp_file) {
if (stat (inp_file, status_buffer) == -1)
err_sys ("can't stat input file %s", inp_file);
if (!S_ISREG (status_buffer->st_mode))
err_quit ("input file %s is not a regular file", inp_file);
if (!(in = fopen (inp_file, "r")))
err_sys ("can't open input file %s", inp_file);
}
return (in);
}
int
main (int ac, char *av[])
{
char string [BUFFER];
char aryidx [BUFFER];
FILE *in;
int rtn, n;
options (ac, av);
create_rex (configure ());
in = input_open ();
if (opt_webpage)
initialize_htm ();
else
initialize_con ();
inp_lineno = 0;
while (fgets (string, sizeof (string), in)) {
string [n=strlen (string)-1] = 0;
inp_lineno++;
rtn = colour_sca (string, aryidx, n);
if (opt_webpage) {
if (!opt_matching || rtn)
printf_htm (string, aryidx, n);
} else {
if (!opt_matching || rtn)
printf_con (string, aryidx, n);
}
}
if (opt_webpage)
finalize_htm ();
else
finalize_con ();
return (0);
}