/* Copyright (C) 2006-2007 G.P. Halkes
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3, as
published by the Free Software Foundation.
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 .
*/
#include
#include "definitions.h"
#include "optionMacros.h"
#define VERSION_STRING "1.3"
typedef struct {
const char *name;
const char *description;
const char *sequence;
} Color;
Color colors[] = {
{ "black", N_("Black"), "\033[0;30m" },
{ "red", N_("Red"), "\033[0;31m" },
{ "green", N_("Green"), "\033[0;32m" },
{ "brown", N_("Brown"), "\033[0;33m" },
{ "blue", N_("Blue"), "\033[0;34m" },
{ "magenta", N_("Magenta"), "\033[0;35m" },
{ "cyan", N_("Cyan"), "\033[0;36m" },
{ "gray", N_("Gray"), "\033[0;37m" },
{ "dgray", N_("Dark gray"), "\033[0;30;1m" },
{ "bred", N_("Bright red"), "\033[0;31;1m" },
{ "bgreen", N_("Bright green"), "\033[0;32;1m" },
{ "yellow", N_("Yellow"), "\033[0;33;1m" },
{ "bblue", N_("Bright blue"), "\033[0;34;1m" },
{ "bmagenta", N_("Bright magenta"), "\033[0;35;1m" },
{ "bcyan", N_("Bright cyan"), "\033[0;36;1m" },
{ "white", N_("White"), "\033[0;37;1m" },
{ NULL, NULL, NULL}
};
/** Compare two strings, ignoring case.
@param a The first string to compare.
@param b The first string to compare.
@retval an integer smaller, equal, or larger than zero to indicate that @a a
sorts before, the same, or after @a b.
*/
int strCaseCmp(const char *a, const char *b) {
int ca, cb;
while ((ca = tolower(*a++)) == (cb = tolower(*b++)) && ca != 0) {}
return ca == cb ? 0 : (ca < cb ? -1 : 1);
}
/** Convert a string from the input format to an internally usable string.
@param string A @a Token with the string to be converted.
@param descr A description of the string to be included in error messages.
@return The length of the resulting string.
The use of this function processes escape characters. The converted
characters are written in the original string.
*/
static size_t parseEscapes(char *string, const char *descr) {
size_t maxReadPosition = strlen(string);
size_t readPosition = 0, writePosition = 0;
size_t i;
while(readPosition < maxReadPosition) {
if (string[readPosition] == '\\') {
readPosition++;
if (readPosition == maxReadPosition) {
fatal(_("Single backslash at end of %s argument\n"), descr);
}
switch(string[readPosition++]) {
case 'n':
string[writePosition++] = '\n';
break;
case 'r':
string[writePosition++] = '\r';
break;
case '\'':
string[writePosition++] = '\'';
break;
case '\\':
string[writePosition++] = '\\';
break;
case 't':
string[writePosition++] = '\t';
break;
case 'b':
string[writePosition++] = '\b';
break;
case 'f':
string[writePosition++] = '\f';
break;
case 'a':
string[writePosition++] = '\a';
break;
case 'v':
string[writePosition++] = '\v';
break;
case '?':
string[writePosition++] = '\?';
break;
case '"':
string[writePosition++] = '"';
break;
case 'x': {
/* Hexadecimal escapes */
int value = 0;
/* Read at most two characters, or as many as are valid. */
for (i = 0; i < 2 && (readPosition + i) < maxReadPosition && isxdigit(string[readPosition + i]); i++) {
value <<= 4;
if (isdigit(string[readPosition + i]))
value += (int) (string[readPosition + i] - '0');
else
value += (int) (tolower(string[readPosition + i]) - 'a') + 10;
}
readPosition += i;
if (i == 0)
fatal(_("Invalid hexadecimal escape sequence in %s argument\n"), descr);
string[writePosition++] = (char) value;
break;
}
case '0':
case '1':
case '2': {
/* Octal escapes */
int value = (int)(string[readPosition - 1] - '0');
for (i = 0; i < 2 && readPosition + i < maxReadPosition && string[readPosition + i] >= '0' && string[readPosition + i] <= '7'; i++)
value = value * 8 + (int)(string[readPosition + i] - '0');
readPosition += i;
string[writePosition++] = (char) value;
break;
}
default:
string[writePosition++] = string[readPosition];
break;
}
} else {
string[writePosition++] = string[readPosition++];
}
}
/* Terminate string. */
string[writePosition] = 0;
return writePosition;
}
static void noDefaultMarkers(void) {
/* Note: then lenghts are 0 by default. */
if (option.addStart == NULL)
option.addStart = "";
if (option.addStop == NULL)
option.addStop = "";
if (option.delStart == NULL)
option.delStart = "";
if (option.delStop == NULL)
option.delStop = "";
}
const char *descriptions[] = {
N_("-d , --delimiters= Specifiy delimiters\n"),
N_("-W , --white-space= Specify whitespace characters\n"),
N_("-h, --help Print this help message\n"),
N_("-v, --version Print version and copyright information\n"),
N_("-1, --no-deleted Do not print deleted words\n"),
N_("-2, --no-inserted Do not print inserted words\n"),
N_("-3, --no-common Do not print common words\n"),
N_("-i, --ignore-case Ignore differences in case\n"),
N_("-s, --statistics Print statistics when done\n"),
N_("-p, --printer Use overstriking and bold text\n"),
N_("-l, --less-mode As -p but also overstrike whitespace\n"),
N_("-w , --start-delete= String to mark begin of deleted text\n"),
N_("-x , --stop-delete= String to mark end of deleted text\n"),
N_("-y , --start-insert= String to mark begin of inserted text\n"),
N_("-z , --stop-insert= String to mark end of inserted text\n"),
N_("-D