/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- trim
- word
- ll_word
- wordlen
- ll_wordlen
- indxword
- ll_indxword
- words
- ll_words
- command_words
- command_word
- command_indxword
- command_wordlen
- sub_string
- getyn
- command_worddel
- worddel
- ll_worddel
- ll_wordput
- num
- ucase
- parse_extend
- initstring
- inittstring
- initqstring
- delbytes
- qatoi
- qatol
- stricmp
- strnicmp
- logic_string_2_flag
- flag_2_logic_string
- pmatch
- lpad
- rpad
- strip_space
/* General parse/string module.
Rick Smereka, Copyright (C) 1992-2005.
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 2 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, get a copy via the Internet at
http://gnu.org/copyleft/gpl.html or write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
You can contact the author via email at rsmereka@future-lab.com
Original version for DOS, Jan/92, Rick Smereka
Added 'command' functions. Jan/97, Rick Smereka
Ported to QNX V4.23a and added 'initstring' and
'inittstring'. Jan/97, Rick Smereka
Modified function 'll_word' to remove a possible
uncontrolled memory access when ANY word in the
string exceeds the allocated length of the output
word. Added functions 'command_indxword' and
'command_wordlen'. Re-wrote function 'command_word'
to use new functions. Re-wrote function 'll_wordput'
to remove slow speed. Nov/97, Rick Smereka
Added function 'sub_string' from old C library. Feb/98,
Rick Smereka
Ported to 32bit Windows under CodeWarrior. Added
functions 'stricmp' and 'strnicmp' as these were
missing from the CodeWarrior library. Dec/98,
Rick Smereka
Changed 'getyn' function to use the function 'gets' instead
of 'getche' since some platforms do not have this function.
Ported to HP-UX under GNU C 2.8.1. Jan/99, Rick Smereka
Added function 'is_valid_logic_flag'. Mar/99, Rick Smereka
Ported to Red Hat Linux 5.2, Jul/99, Rick Smereka
Added function 'isip'. Oct/99, Rick Smereka
Fixed bug in 'command_indxword' which returned the wrong value
if the first character in any word (except the first) was a
quote. Nov/99, Rick Smereka
Added function 'initqstring'. Mar/2000, Rick Smereka
Changed function 'getyn' to use 'scanf' instead of 'gets'
May/2000, Rick Smereka
Removed the function 'isip' and placed it into the new
TCP/IP utility library 'ip.c'. Jul/2000, Rick Smereka
Changed functions 'll_indxword' and 'll_wordlen' to call
'inittstring' only if the word delimiter is a space. Added
function 'pmatch'. Feb/2001, Rick Smereka
Added function 'get_time'. Oct/2001, Rick Smereka
Fixed bug in 'll_wordput' which sometimes returned an
empty string. Dec/2001, Rick Smereka
Added functions 'lpad' and 'rpad'. Apr/2002,
Rick Smereka
Moved function 'get_time' to the module 'datime.c'.
May/2002, Rick Smereka
Added function 'strip_space'. Jul/2002, Rick Smereka
Ported to Debian Linux. Nov/2002, Rick Smereka
Fixed bug in functions 'lpad' and 'rpad' that returned
an empty string if no padding was necessary. Re-wrote
function 'll_worddel' to use function 'delbytes' to
delete a portion of the string. Mar/2003, Rick Smereka
Changed function 'getyn' to use 'fgets' instead of 'scanf'.
May/2004, Rick Smereka
Fixed logic error in the function 'rpad'. Dec/2004,
Rick Smereka
Plugged memory leak in 'll_worddel' (old 'malloc' call).
Feb/2005, Rick Smereka */
#include "stdhead.h"
void trim(char *instr, char *outstr)
{
/* Trim a string by removing all spaces from the beginning
and the end plus remove all extra spaces between words.
'Outstr' must be a statically allocated string large
enough to hold the output string. */
int i, len, pos, done, outpos;
char *tmp, *tmp2;
len = strlen(instr);
outstr[0] = EOS;
if (!len)
return;
if ((tmp = initstring(instr)) == NULL)
return;
if ((tmp2 = (char *)malloc(len + 1)) == NULL)
{
free(tmp);
return;
}
/* get position of first non-blank character */
for(i = 0, pos = -1, done = FALSE; i < len && !done; i++)
if (tmp[i] != ' ')
{
pos = i;
done = TRUE;
}
/* check for all blank string */
if (pos == -1)
{
free(tmp);
free(tmp2);
return;
}
i = pos;
outpos = 0;
tmp2[0] = EOS;
while(i < len)
{
while(tmp[i] != ' ' && i < len)
{
tmp2[outpos++] = tmp[i];
i++;
}
tmp2[outpos++] = ' ';
if (i < len)
while(instr[i] == ' ' && i < len)
i++;
}
tmp2[outpos - 1] = EOS;
strcpy(outstr, tmp2);
free(tmp);
free(tmp2);
}
int word(char *instr, char *outstr, int which)
{
/* Extract the 'which' space delimited word from 'instr'. */
return(ll_word(instr, outstr, which, ' '));
}
int ll_word(char *instr, char *outstr, int which, char delim)
{
/* Extract the 'which' word of 'instr' and return it in 'outstr'.
Each word is delimited by 'delim'
'Outstr' must be a statically allocated string with enough
length to accomidate the word. Function returns TRUE on
success, FALSE otherwise. */
int len;
int pos;
len = strlen(instr);
outstr[0] = EOS;
if (!len)
return(FALSE);
if (which <= 0 || which > ll_words(instr, delim))
return(FALSE);
pos = ll_indxword(instr, which, delim);
len = ll_wordlen(instr, which, delim);
strncpy(outstr, &instr[pos], len);
outstr[len] = EOS;
return(TRUE);
}
int wordlen(char *instr, int which)
{
/* Get the length of space delimited word 'which' in
'instr'. Function returns length upon success,
-1 otherwise. */
return(ll_wordlen(instr, which, ' '));
}
int ll_wordlen(char *instr, int which, char delim)
{
/* Get the length of 'delim' delimited word 'which'
in 'instr'. Functions returns length upon sucess,
-1 otherwise. */
char *tmpstr;
int nwords;
int len;
int wrdlen;
if ((len = strlen(instr)) == 0)
return(-1);
if (delim == ' ')
{
if ((tmpstr = inittstring(instr)) == NULL)
return(-1);
}
else
if ((tmpstr = initstring(instr)) == NULL)
return(-1);
len = strlen(tmpstr);
nwords = ll_words(tmpstr, delim);
if (!nwords)
{
free(tmpstr);
return(-1);
}
if (which <= 0 || which > nwords)
{
free(tmpstr);
return(-1);
}
if (which == nwords)
wrdlen = len - ll_indxword(tmpstr, which, delim);
else
wrdlen = ll_indxword(tmpstr, which + 1, delim) -
(ll_indxword(tmpstr, which, delim) + 1);
free(tmpstr);
return(wrdlen);
}
int indxword(char *instr, int which)
{
/* Return the index of word 'which' within 'instr'. */
return(ll_indxword(instr, which, ' '));
}
int ll_indxword(char *instr, int which, char delim)
{
/* Return the index of word 'which' within 'instr'
delimited by 'delim'. Function returns the index
on success, -1 otherwise. */
int i, len, nwords, index;
char *tmp;
len = strlen(instr);
if (!len)
return(-1);
if (delim == ' ')
{
if ((tmp = inittstring(instr)) == NULL)
return(-1);
}
else
if ((tmp = initstring(instr)) == NULL)
return(-1);
if (which <= 0 || which > ll_words(tmp, delim))
{
free(tmp);
return(-1);
}
len = strlen(tmp);
if (!len)
{
free(tmp);
return(-1);
}
i = 0;
nwords = 1;
while(i <= len)
{
index = i;
if (nwords == which)
{
free(tmp);
return(index);
}
while(tmp[i] != delim && i <= len)
i++;
nwords++;
i++;
}
free(tmp);
return(-1);
}
int words(char *str)
{
/* Count the number of space delimited words in a string. */
return(ll_words(str, ' '));
}
int ll_words(char *str, char delim)
{
/* Count the number of 'delim' delimited words in a string. */
int i, len, nwords;
char *tmp;
len = strlen(str);
if (!len)
return(0);
if ((tmp = initstring(str)) == NULL)
return(0);
/* trim string if delimiter is a space */
if (delim == ' ')
{
trim(str, tmp);
len = strlen(tmp);
if (!len)
{
free(tmp);
return(FALSE);
}
}
/* count instances */
for(i = 0, nwords = 0; i < len; i++)
if (tmp[i] == delim)
nwords++;
free(tmp);
return(nwords + 1);
}
int command_words(char *p_string)
{
/* Count the number of 'command' words in a string. A
command word can be either a space delimited word or
an entire paragraph delimited by matching quotes. Function
returns the number of command words found. */
char *t_string;
char ch;
char prev_ch;
char delim;
int len;
int nwords;
int pos;
int found;
if (!strlen(p_string))
return(FALSE);
if ((t_string = initstring(p_string)) == NULL)
return(FALSE);
len = strlen(t_string);
nwords = 0;
pos = 0;
/* loop through all characters in string looking for delimiters */
do
{
ch = t_string[pos];
switch(ch)
{
case ' ':
/* a space is an unconditional word */
nwords++;
pos++;
break;
case '\'':
case '\"':
if (pos > 0)
{
prev_ch = t_string[pos - 1];
if (prev_ch != ' ' && prev_ch != '\"' && prev_ch != '\'')
nwords++;
}
delim = ch;
found = FALSE;
pos++;
/* find matching quote */
do
{
ch = t_string[pos];
if (delim == ch)
{
if (t_string[pos + 1] == ' ')
pos += 2;
else
pos++;
/* add another word as long as the quote is
not the last character */
if (pos < len)
nwords++;
found = TRUE;
}
else
pos++;
}
while(!found && pos <= len);
break;
default:
pos++;
};
}
while(pos <= len);
free(t_string);
return(nwords + 1);
}
int command_word(char *instr, char *o_string, int which)
{
/* Parse a string and extract the which command word of
'instr'. Output word will be placed into the
string 'o_string' which already must have been
allocated. Function returns 'TRUE' upon success,
'FALSE' otherwise. */
int len, pos;
o_string[0] = EOS;
if (which <= 0 || which > command_words(instr))
return(FALSE);
pos = command_indxword(instr, which);
len = command_wordlen(instr, which);
strncpy(o_string, &instr[pos], len);
o_string[len] = EOS;
return(TRUE);
}
int command_indxword(char *instr, int which)
{
/* Return the index of word 'which' within 'instr'
command delimited. Function returns the index
on success, -1 otherwise. */
int pos, len, nword, done;
int found;
char ch, delim, prev_ch;
len = strlen(instr);
if (!len)
return(-1);
if (which <= 0 || which > command_words(instr))
return(-1);
pos = 0;
nword = 1;
done = FALSE;
/* loop through all characters in string looking for delimiters */
do
{
/* handle first word requested */
if (nword == which)
{
if (instr[pos] == '\'' || instr[pos] == '\"')
pos++;
done = TRUE;
continue;
}
ch = instr[pos];
switch(ch)
{
case ' ':
/* a space is an unconditional word */
/* printf("ll_word:found space pos=%d,nword=%d\n", pos,
nword + 1); */
nword++;
pos++;
if (nword == which)
done = TRUE;
/* move position if the next character is a quote */
if (done && pos < len)
if (instr[pos] == '\'' || instr[pos] == '\"')
pos++;
break;
case '\'':
case '\"':
/* printf("ll_word:found %c pos=%d\n", ch, pos); */
/* if quote is to the right of a non-delimiter, add one word */
if (pos > 0)
{
prev_ch = instr[pos - 1];
if (prev_ch != ' ' && prev_ch != '\"' && prev_ch != '\'')
{
nword++;
/* printf("ll_word:quote1, nword=%d\n", nword); */
if (nword == which)
{
done = TRUE;
/* printf("ll_word:quote1,done=TRUE\n"); */
break;
}
}
}
delim = ch;
found = FALSE;
pos++;
/* find matching quote */
do
{
ch = instr[pos];
if (delim == ch)
{
if (instr[pos + 1] == ' ')
pos += 2;
else
pos++;
if (pos < len)
{
nword++;
if (nword == which)
{
done = TRUE;
if (instr[pos] == '\'' || instr[pos] == '"')
pos++;
}
}
/* printf("ll_word:match quote,pos=%d,nword=%d,done=%d\n",
pos, nword,done); */
found = TRUE;
}
else
pos++;
}
while(!found && pos <= len);
break;
default:
pos++;
break;
}
}
while(pos <= len && !done);
if (done)
return(pos);
return(-1);
}
int command_wordlen(char *instr, int which)
{
/* Get and return the length of the 'which' command word
in the string 'instr'. Function returns the word length
upon success (which may be zero), -1 otherwise. */
int indx, i, len, outlen;
char delim;
if (which <= 0 || which > command_words(instr))
return(-1);
indx = command_indxword(instr, which);
len = strlen(instr);
/* set delimiter */
if (indx == 0)
delim = ' ';
else
delim = instr[indx - 1];
/* loop looking for the next delimiter or end of the string */
for(i = indx, outlen = 0; i < len; i++, outlen++)
if (instr[i] == delim)
break;
return(outlen);
}
int sub_string(char *string, char *sub)
{
/* Find the occurrance of 'sub' within 'string.' Returns
a numeric index if found, -1 otherwise. */
int i, j, k;
for(i = 0; string[i] != EOS; i++)
{
for(j = i, k = 0; sub[k] == string[j] && sub[k] != EOS; j++, k++)
;
if (sub[k] == EOS)
return(i);
}
return(EOF);
}
int getyn(char *prompt)
{
/* Get a 'y'es or 'n'o answer from the user. Function
returns 'TRUE' for 'y' and 'FALSE' for 'n'. */
char ch[10];
int ret;
int done = FALSE;
while(!done)
{
ch[0] = EOS;
printf("%s?(y/n)", prompt);
fgets(ch, 9, stdin);
if (ch[0] != 'y' && ch[0] != 'Y' && ch[0] != 'n' && ch[0] != 'N')
printf("please respond with 'y' or 'n'\n");
else
if (ch[0] == 'y' || ch[0] == 'Y')
{
ret = TRUE;
done = TRUE;
}
else
{
ret = FALSE;
done = TRUE;
}
}
return(ret);
}
int command_worddel(char *instr, char *outstr, int which)
{
/* Delete the 'which' command word of 'instr'.
Upon success, 'outstr' will be loaded with the new string.
Function returns 'TRUE' upon success, 'FALSE' otherwise. */
char *tmpout;
char *tmpwrd;
char quote;
int nwords, nwords_out;
int len;
int pos;
int i;
outstr[0] = EOS;
if (instr == NULL || outstr == NULL || which <= 0)
return(FALSE);
len = strlen(instr);
if (!len)
return(FALSE);
if ((tmpout = (char *)malloc(len + 1)) == NULL)
return(FALSE);
if ((tmpwrd = (char *)malloc(len + 1)) == NULL)
{
free(tmpout);
return(FALSE);
}
nwords = command_words(instr);
nwords_out = 0;
tmpwrd[0] = tmpout[0] = EOS;
if (which > nwords)
{
free(tmpout);
free(tmpwrd);
return(FALSE);
}
/* loop to copy all words except the one to delete */
for(i = 1; i <= nwords; i++)
{
if (i != which)
{
if (!command_word(instr, tmpwrd, i))
{
free(tmpout);
free(tmpwrd);
return(FALSE);
}
len = strlen(tmpout);
pos = len + strlen(tmpwrd); /* calc new end of string */
/* if word contains multiple space delimited words,
put the quotes back */
if (words(tmpwrd) > 1)
{
/* decide which quotes to use based on if there
are any existing quotes */
if (strchr(tmpwrd, '\''))
quote = '\"';
else
quote = '\'';
tmpout[len++] = quote;
tmpout[len] = EOS;
strcat(tmpout, tmpwrd);
pos = len + strlen(tmpwrd);
tmpout[pos++] = quote;
tmpout[pos] = EOS;
}
else
strcat(tmpout, tmpwrd);
nwords_out++;
/* concatenate the output string with a delimiter
unless we are on the last word to be output */
if (nwords_out < (nwords - 1))
{
strcat(tmpout, " ");
tmpout[pos + 1] = EOS;
}
else
tmpout[pos] = EOS;
/* special logic to break if we are done before
the natual end of the loop, this should occurr
only if the last word is being deleted */
if (nwords_out == (nwords - 1))
break;
}
}
strcpy(outstr, tmpout);
free(tmpout);
free(tmpwrd);
return(TRUE);
}
int worddel(char *instr, char *outstr, int which)
{
/* Delete the 'which' space delimited word of 'instr'
and place new string in 'outstr' which must be
already allocated. Function returns 'TRUE' upon
success, 'FALSE' otherwise. */
return(ll_worddel(instr, outstr, which, ' '));
}
int ll_worddel(char *instr, char *outstr, int which, char delim)
{
/* Delete the 'which' word of 'instr' delimited by 'delim'.
Upon success, 'outstr' will be loaded with the new string.
Function returns 'TRUE' upon success, 'FALSE' otherwise. */
int nwords, pos, num_bytes;
if (instr == (char *)NULL || !strlen(instr) || outstr == (char *)NULL ||
which <= 0)
return(FALSE);
outstr[0] = EOS;
nwords = ll_words(instr, delim);
if (which > nwords)
return(FALSE);
pos = ll_indxword(instr, which, delim);
if (nwords == which)
{
// 'delbytes' uses zero len to indicate the rest of the string
num_bytes = 0;
/* if there is more than one word and we are deleting the last,
back up one byte to remove the delimiter */
if (nwords > 1)
pos--;
}
else
num_bytes = ll_indxword(instr, which + 1, delim) - pos;
if (!delbytes(instr, outstr, pos, num_bytes))
return(FALSE);
return(TRUE);
}
int ll_wordput(char *instr, char *outstr, char *wdata, int which, char delim)
{
/* Place the word 'wdata' into 'instr' as the 'which' word. If the
word already exists, it will be replaced, if it does not exist, the
string will be extended out to the required word before copying.
Each word is delimited by 'delim'. The new string will be returned in
'outstr' upon success. 'outstr' must be already allocated large
enough to hold the result string. Function returns 'TRUE' upon
success, 'FALSE' otherwise. */
char *new_str, *before, *after, *tmp;
int existing_rec_len;
int new_rec_len;
int new_field_len;
int existing_field_len;
int nwords;
int len;
int indx;
int process;
if (instr == NULL || outstr == NULL || which <= 0)
return(FALSE);
outstr[0] = EOS;
if (wdata == NULL)
return(FALSE);
len = strlen(instr);
nwords = ll_words(instr, delim);
/* create a copy of input (if present) or a new string
large enough for the word plus the number of word
delimiters plus a little extra */
if (!len)
{
if ((new_str = (char *)malloc(strlen(wdata) + which + 200)) == NULL)
return(FALSE);
new_str[0] = EOS;
}
else
if ((new_str = initstring(instr)) == NULL)
return(FALSE);
/* extend string out if required */
if (which > nwords)
{
if ((tmp = (char *)malloc(len + strlen(wdata) + which + 200)) == NULL)
{
free(new_str);
return(FALSE);
}
tmp[0] = EOS;
if (!parse_extend(new_str, tmp, which, delim))
{
free(new_str);
free(tmp);
return(FALSE);
}
free(new_str);
new_str = initstring(tmp);
len = strlen(new_str);
free(tmp);
nwords = which;
}
if (!len)
existing_field_len = existing_rec_len = 0;
else
{
existing_field_len = ll_wordlen(new_str, which, delim);
existing_rec_len = len;
}
new_field_len = strlen(wdata);
/* if existing and new words are length zero, nothing more to do */
if (new_field_len == 0 && existing_field_len == 0)
{
strcpy(outstr, new_str);
free(new_str);
return(TRUE);
}
/* if strings are equal, place new data over top of old */
if (existing_field_len == new_field_len)
{
indx = ll_indxword(new_str, which, delim);
memcpy(&new_str[indx], wdata, existing_field_len);
strcpy(outstr, new_str);
free(new_str);
return(TRUE);
}
/* compute new length */
if (new_field_len > existing_field_len)
new_rec_len = existing_rec_len + (new_field_len -
existing_field_len);
else
new_rec_len = existing_rec_len - (existing_field_len -
new_field_len);
/* 'tmp' will contain the result string */
if ((tmp = (char *)malloc(new_rec_len + 1)) == NULL)
{
free(new_str);
return(FALSE);
}
/* 'before' is all the data before the target word */
if ((before = (char *)malloc(new_rec_len + 1)) == NULL)
{
free(tmp);
free(new_str);
return(FALSE);
}
/* 'after' is all the data after the target word */
if ((after = (char *)malloc(new_rec_len + 1)) == NULL)
{
free(tmp);
free(before);
free(new_str);
return(FALSE);
}
process = TRUE;
/* figure out and copy before and after data */
/* handle first word in string */
if (which == 1)
{
before[0] = EOS;
if (nwords == which)
after[0] = EOS;
else
{
/* load 'after' from start of second word to end (no delimiters) */
indx = ll_indxword(new_str, 2, delim);
strncpy(after, &new_str[indx], len - indx + 1);
after[len - indx + 1] = EOS;
}
process = FALSE;
}
/* handle last word in string */
if (process && which == nwords)
{
/* load 'before' from start to delimiter just before 'which' */
indx = ll_indxword(new_str, which, delim);
strncpy(before, new_str, indx);
before[indx] = EOS;
after[0] = EOS;
process = FALSE;
}
/* handle 'which' in the middle of the string */
if (process)
{
/* load 'before' from start to delimiter just before 'which' */
indx = ll_indxword(new_str, which, delim);
strncpy(before, new_str, indx);
before[indx] = EOS;
/* load 'after' from start of word after 'which' to the end
(no delimiters) */
indx = ll_indxword(new_str, which + 1, delim);
strncpy(after, &new_str[indx], len - indx + 1);
after[len - indx + 1] = EOS;
}
/* build final string from three parts */
tmp[0] = EOS;
len = 0;
/* part one, 'before' string */
if (strlen(before))
{
strcpy(tmp, before);
len = strlen(tmp);
}
/* part two, new word data */
strcat(tmp, wdata);
tmp[len + new_field_len] = EOS;
len = strlen(tmp);
/* part three, 'after' string */
if (strlen(after))
{
tmp[len] = delim;
tmp[len + 1] = EOS;
len++;
strcat(tmp, after);
tmp[len + strlen(after)] = EOS;
}
strcpy(outstr, tmp);
free(new_str);
free(tmp);
free(before);
free(after);
return(TRUE);
}
int num(char *numstr)
{
/* Evaluate a string to determine whether it is a valid number.
Numbers are the digits 0-9. A minus sign is allowed in the
first character. Function returns 'TRUE' if the string is
a valid number, 'FALSE' otherwise. */
int len, i;
if (numstr == NULL)
return(FALSE);
len = strlen(numstr);
if (!len)
return(FALSE);
for(i = 0; i < len; i++)
{
if (numstr[i] == '-')
{
if (i > 0)
return(FALSE);
}
else
if (!isdigit(numstr[i]))
return(FALSE);
}
return(TRUE);
}
void ucase(char *src, char *dest)
{
/* Copy a string to its uppercase version. Output string
is copied into 'dest' which must be allocated to
sufficient size. */
int i, len;
dest[0] = EOS;
len = strlen(src);
if (!len)
return;
for(i = 0; i < len; i++)
dest[i] = toupper(src[i]);
dest[len] = EOS;
}
int parse_extend(char *instr, char *outstr, int which, char delim)
{
/* Extend string data out to 'which' 'delim' delimited word.
You may not extend using the space delimiter because of the
nature of the space and the 'trim' function. Function returns
'TRUE' upon success, 'FALSE' otherwise. Upon success, 'outstr'
will be loaded with the extended string. */
char *new_rec;
int nwords;
int i;
int pos;
int rec_len;
int total_len;
if (instr == NULL || outstr == NULL)
return(FALSE);
outstr[0] = EOS;
nwords = ll_words(instr, delim);
/* if the existing string is empty and we are adding the
first word, do not extend */
if (!nwords && which == 1)
return(TRUE);
if (which <= 0 || delim == ' ')
return(FALSE);
/* if word is already present, extend not necessary */
if (nwords >= which)
{
strcpy(outstr, instr);
return(TRUE);
}
if (!nwords)
rec_len = 0;
else
rec_len = strlen(instr);
total_len = rec_len + (which - nwords) + 200;
if ((new_rec = (char *)malloc(total_len)) == NULL)
return(FALSE);
if (rec_len)
strcpy(new_rec, instr);
else
new_rec[0] = EOS;
/* extend string */
for(pos = strlen(new_rec), i = nwords; i < which; i++, pos++)
new_rec[pos] = delim;
new_rec[pos] = EOS;
strcpy(outstr, new_rec);
free(new_rec);
return(TRUE);
}
char *initstring(char *src)
{
/* Initialize and copy a string. Dynamic memory is used for
the string and it is the responsibility of the caller
to 'free' the string memory after use. Function returns
a pointer to the beginning of the new string upon
success, a 'NULL' pointer otherwise. */
char *dest;
int len;
len = strlen(src);
if (!src)
return(NULL);
if ((dest = (char *)malloc(len + 1)) == NULL)
return(NULL);
strcpy(dest, src);
return(dest);
}
char *inittstring(char *src)
{
/* Initialize, copy and 'trim' a string. Dynamic memory is used for
the string and it is the responsibility of the caller
to 'free' the string memory after use. Function returns
a pointer to the beginning of the new string upon
success, a 'NULL' pointer otherwise. */
char *dest;
int len;
len = strlen(src);
if (!src)
return(NULL);
if ((dest = (char *)malloc(len + 1)) == NULL)
return(NULL);
trim(src, dest);
return(dest);
}
char *initqstring(char *src)
{
/* Initialize, copy and quote a string. The destination string is
only quoted if the source string contains more than one space
delimited word. Dynamic memory is used for the string and it
is the responsibility of the caller to 'free' the string
memory after use. Function returns a pointer to the beginning
of the new string upon success, a 'NULL' pointer otherwise. */
char *dest;
int len;
if (src == (char *)NULL)
return((char *)NULL);
len = strlen(src);
if (!len)
return((char *)NULL);
if ((dest = (char *)malloc(len + 3)) == (char *)NULL)
return((char *)NULL);
if (words(src) > 1)
sprintf(dest, "'%s'", src);
else
strcpy(dest, src);
return(dest);
}
int delbytes(char *instr, char *outstr, int pos, int numbytes)
{
/* Delete the 'numbytes' of 'instr' starting from byte 'pos'
and place the result string into 'outstr' which must already
be allocated to a sufficient size. Function returns 'TRUE'
upon success with the result string in 'outstr', 'FALSE'
otherwise. 'numbytes' may be zero which indicates the
remainder of the string. */
char *beg;
char *end;
int instrlen;
int i, j;
int slen;
outstr[0] = EOS;
instrlen = strlen(instr);
if (instr == NULL || !instrlen || outstr == NULL || pos < 0 ||
numbytes < 0 || (pos + numbytes) > instrlen)
return(FALSE);
if ((beg = (char *)malloc(instrlen + 1)) == (char *)NULL)
return(FALSE);
if ((end = (char *)malloc(instrlen + 1)) == (char *)NULL)
{
free(beg);
return(FALSE);
}
beg[0] = EOS;
end[0] = EOS;
/* loop to copy all data before the start position 'pos' */
for(i = 0; i < pos; i++)
beg[i] = instr[i];
beg[pos] = EOS;
/* calc the number of bytes to delete */
slen = (numbytes) ? numbytes : instrlen - pos;
/* loop to copy all data after the removed section */
for(i = pos + slen, j = 0; i < instrlen; i++, j++)
if (i < (instrlen - 1))
end[j] = instr[i];
else
{
end[j] = instr[i];
end[j + 1] = EOS;
}
sprintf(outstr, "%s%s", beg, end);
free(beg);
free(end);
return(TRUE);
}
int qatoi(char *numstr, int *numval)
{
/* Convert a number in a string to an integer. This function
differs from 'atoi' in the sense that non-numeric characters
(other than the minus sign) are not allowed. Function returns
'TRUE' if 'numstr' is a number and 'numval' will be loaded with
the value. Upon failure, 'FALSE' will be returned and 'numval'
will be zero. */
*numval = 0;
if (!num(numstr))
return(FALSE);
*numval = atoi(numstr);
return(TRUE);
}
int qatol(char *numstr, long *numval)
{
/* Convert a number in a string to a long. This function
differs from 'atol' in the sense that non-numeric characters
(other than the minus sign) are not allowed. Function returns
'TRUE' if 'numstr' is a number and 'numval' will be loaded with
the value. Upon failure, 'FALSE' will be returned and 'numval'
will be zero. */
*numval = 0L;
if (!num(numstr))
return(FALSE);
*numval = atol(numstr);
return(TRUE);
}
/* functions missing from some C libraries including
Codewarrior and Unix */
#ifndef HAS_STRICMP
int stricmp(char *s1, char *s2)
{
/* Case insensitive string comparison. Function
returns the result from 'strcmp' after the
two strings have been forced to upper case.
Dec/98, Rick Smereka */
char *us1, *us2;
int ret;
if (s1 == (char *)NULL || s2 == (char *)NULL)
return(4); // return positive number on failure
if (!strlen(s1) || !strlen(s2))
return(5);
if ((us1 = (char *)malloc(strlen(s1) + 1)) == (char *)NULL)
return(6);
if ((us2 = (char *)malloc(strlen(s2) + 1)) == (char *)NULL)
{
free(us1);
return(7);
}
// covert both strings to upper case
ucase(s1, us1);
ucase(s2, us2);
// normal compare
ret = strcmp(us1, us2);
free(us1);
free(us2);
return(ret);
}
int strnicmp(char *s1, char *s2, int len)
{
/* Case insensitive string comparison for a
specific number of bytes. Function
returns the result from 'strncmp' after the
two strings have been forced to upper case.
Dec/98, Rick Smereka */
char *us1, *us2;
int ret;
if (s1 == (char *)NULL || s2 == (char *)NULL)
return(4); // return positive number on failure
if (!strlen(s1) || !strlen(s2))
return(5);
if ((us1 = (char *)malloc(strlen(s1) + 1)) == (char *)NULL)
return(6);
if ((us2 = (char *)malloc(strlen(s2) + 1)) == (char *)NULL)
{
free(us1);
return(7);
}
// covert both strings to upper case
ucase(s1, us1);
ucase(s2, us2);
// normal compare
ret = strncmp(us1, us2, len);
free(us1);
free(us2);
return(ret);
}
#endif
int logic_string_2_flag(char *lstring, int *flag)
{
/* Convert a string to a boolean value.
Acceptable values of 'lstring' are:
yes, no, true, false, on, off, 0, 1
String comparison is case insensitive.
Function returns 'TRUE' upon success
with the flag value loaded into 'flag'.
Function returns false otherwise. */
char *tmp;
int ret = -1;
if (lstring == (char *)NULL || !strlen(lstring))
return(FALSE);
if (flag == (int *)NULL)
return(FALSE);
*flag = 0;
if ((tmp = initstring(lstring)) == (char *)NULL)
return(-1);
trim(lstring, tmp);
if (!stricmp(tmp, "YES"))
ret = TRUE;
if (ret == -1 && !stricmp(tmp, "NO"))
ret = FALSE;
if (ret == -1 && !stricmp(tmp, "TRUE"))
ret = TRUE;
if (ret == -1 && !stricmp(tmp, "FALSE"))
ret = FALSE;
if (ret == -1 && !stricmp(tmp, "ON"))
ret = TRUE;
if (ret == -1 && !stricmp(tmp, "OFF"))
ret = FALSE;
if (ret == -1 && !strcmp(tmp, "1"))
ret = TRUE;
if (ret == -1 && !strcmp(tmp, "0"))
ret = FALSE;
free(tmp);
*flag = (ret != -1) ? ret : 0;
return(ret != -1 ? TRUE : FALSE);
}
int flag_2_logic_string(int flag, char *str)
{
/* Convert a integer flag to a string. 'ON' is used
to represent 1 and 'OFF' is used to represent
0. The 'flag' must be zero or one. Function
returns 'TRUE' upon success with the string
loaded into 'str', 'FALSE' is returned
otherwise. */
if (flag != TRUE && flag != FALSE)
return(FALSE);
if (flag)
strcpy(str, "on");
else
strcpy(str, "off");
return(TRUE);
}
int pmatch(char *pattern, char *fname)
{
/* Match a (file)name to a pattern. Two wildcards are
allowed in the 'pattern'. An asterisk ('*') will
match all characters up to the next non-wildcard
and the question mark ('?') will match any
single character. Function returns 'TRUE' if a
match is found, 'FALSE' otherwise. */
char pat_ch, fname_ch;
int pat_len, fname_len, pat_pos, fname_pos;
int done = FALSE, found;
if (pattern == NULL || fname == NULL)
return(FALSE);
pat_len = strlen(pattern);
fname_len = strlen(fname);
pat_pos = fname_pos = 0;
if (!pat_len || !fname_len)
return(FALSE);
while(!done)
{
pat_ch = pattern[pat_pos];
switch(pat_ch)
{
case '?':
pat_pos++;
fname_pos++;
if (pat_pos >= pat_len && fname_pos >= fname_len)
return(TRUE);
if (pat_pos >= pat_len || fname_pos >= fname_len)
return(FALSE);
break;
case '*':
pat_pos++;
if (pat_pos >= pat_len)
return(TRUE);
pat_ch = pattern[pat_pos];
found = FALSE;
while(!found)
{
fname_ch = fname[fname_pos];
if (fname_ch == pat_ch)
{
found = TRUE;
fname_pos++;
pat_pos++;
}
else
{
fname_pos++;
if (fname_pos >= fname_len)
if (pat_pos >= pat_len)
return(TRUE);
else
return(FALSE);
}
}
break;
default:
if (pattern[pat_pos] != fname[fname_pos])
return(FALSE);
pat_pos++;
fname_pos++;
if (pat_pos >= pat_len && fname_pos >= fname_len)
return(TRUE);
if (pat_pos >= pat_len || fname_pos >= fname_len)
return(FALSE);
};
}
return(FALSE);
}
void lpad(char *istr, char *ostr, int padlen, char padch)
{
/* Pad a string on the left with the character 'padch'
to the length 'padlen'. Function returns the padded
string in 'ostr' which must already be allocated to
sufficient size by the caller. */
int i, ch2pad, outpos, len;
if (istr == (char *)NULL)
return;
if (ostr == (char *)NULL)
return;
if (padlen <= 0)
return;
ostr[0] = EOS;
len = strlen(istr);
ch2pad = padlen - len;
/* if chars to pad is zero or less, just copy input to output */
if (ch2pad <= 0)
{
strcpy(ostr, istr);
return;
}
for(i = 1, outpos = 0; i <= ch2pad; i++, outpos++)
{
ostr[outpos] = padch;
ostr[outpos + 1] = EOS;
}
for(i = 0; i < len; i++, outpos++)
{
ostr[outpos] = istr[i];
ostr[outpos + 1] = EOS;
}
}
void rpad(char *istr, char *ostr, int padlen, char padch)
{
/* Pad a string on the right with the character 'padch'
to the length 'padlen'. Function returns the padded
string in 'ostr' which must already be allocated to
sufficient size by the caller. */
int i, ch2pad, outpos, len;
if (istr == (char *)NULL)
return;
if (ostr == (char *)NULL)
return;
if (padlen <= 0)
return;
ostr[0] = EOS;
len = strlen(istr);
ch2pad = padlen - len;
/* if chars to pad is zero or less, just copy input to output */
if (ch2pad <= 0)
{
strcpy(ostr, istr);
return;
}
strcpy(ostr, istr);
for(i = 0, outpos = len; i < ch2pad; i++, outpos++)
{
ostr[outpos] = padch;
ostr[outpos + 1] = EOS;
}
}
void strip_space(char *instr, char *outstr)
{
/* Strip all spaces from 'instr' and place the result
into 'outstr' which must already be allocated to
sufficient size by the caller. */
char ch;
int i, len, out_pos;
if (instr == (char *)NULL || !strlen(instr))
return;
len = strlen(instr);
for(i = 0, out_pos = 0; i < len; i++)
{
ch = instr[i];
if (ch != ' ')
{
outstr[out_pos++] = ch;
outstr[out_pos] = EOS;
}
}
}