xenocara/app/fvwm/libs/ModParse.c

317 lines
6.7 KiB
C

/*
File: ModParse.c
Modifications:
Changed 08/30/98 by Dan Espen:
- Copied from FvwmEvent/Parse.c. Set up for general use by modules.
Still to be done, try to integrate with Parse.c which is used by fvwm
itself for parsing.
*/
#include "fvwmlib.h"
#include "ModParse.h"
/*
** PeekArgument: returns next token from string, leaving string intact
** (you should free returned string later)
**
** notes - quotes and brakets deonte blocks, which are returned MINUS
** the start & end delimiters. Delims within block may be escaped
** with a backslash \ (which is removed when returned). Backslash
** must be escaped too, if you want one... (\\). Arguments may be up
** to MAX_TOKEN_LENGTH in size.
*/
char *DoPeekArgument(const char *pstr, char **pret)
{
char *tok=NULL;
const char *p;
char bc=0,be=0,tmptok[MAX_TOKEN_LENGTH];
int len=0;
if (!pstr)
return NULL;
p=pstr;
EatWS(p); /* skip leading space */
if (*p)
{
if (IsQuote(*p) || IsBlockStart(*p)) /* quoted string or block start? */
{
bc = *p; /* save block start char */
p++;
}
/* find end of token */
while (*p && len < MAX_TOKEN_LENGTH)
{
/* first, check stop conditions based on block or normal token */
if (bc)
{
if ((IsQuote(*p) && bc == *p) || IsBlockEnd(*p,bc))
{
be = *p;
break;
}
}
else /* normal token */
{
if (isspace(*p) || *p == ',')
break;
}
if (*p == '\\' && *(p+1)) /* if \, copy next char verbatim */
p++;
tmptok[len] = *p;
len++;
p++;
}
/* sanity checks: */
if (bc && !be) /* did we have block start, but not end? */
{
/* should yell about this */
return NULL;
}
if (len)
{
tok = (char *)safemalloc(len+1);
strncpy(tok,tmptok,len);
tok[len]='\0';
}
}
if (!isspace(*p)) p++;
if (pret) *pret = p;
return tok;
}
char *PeekArgument(const char *pstr)
{
return DoPeekArgument(pstr, NULL);
}
/*
** GetArgument: destructively rips next token from string, returning it
** (you should free returned string later)
*/
char *GetArgument(char **pstr)
{
char *tok ;
if (!pstr || !*pstr || !(tok=DoPeekArgument(*pstr, pstr)))
return NULL; /* *pstr=NULL; ???? */
/* skip tok and following whitespace/separators in pstr & DON'T realloc */
EatWS(*pstr);
if (!**pstr)
*pstr=NULL; /* change \0 to NULL */
return tok;
}
/*
** CmpArgument: does case-insensitive compare on next token in string, leaving
** string intact (return code like strcmp)
*/
int CmpArgument(const char *pstr,char *tok)
{
int rc=0;
char *ntok=PeekArgument(pstr);
if (ntok)
{
rc = strcasecmp(tok,ntok);
free(ntok);
}
return rc;
}
/*
** MatchArgument: does case-insensitive compare on next token in string, leaving
** string intact (returns true if matches, false otherwise)
*/
int MatchArgument(const char *pstr,char *tok)
{
int rc=0;
char *ntok=PeekArgument(pstr);
if (ntok)
{
rc = (strcasecmp(tok,ntok)==0);
free(ntok);
}
return rc;
}
#if 0
/*
** GetNextArgument: equiv interface of old parsing routine, for ease of transition
*/
char *GetNextArgument(char *indata,char **token)
{
char *nindata=indata;
*token = PeekArgument(indata);
if (*token)
nindata+=strlen(*token);
EatWS(nindata);
return nindata;
}
#else
/****************************************************************************
*
* Gets the next "word" of input from char string indata.
* "word" is a string with no spaces, or a qouted string.
* Return value is ptr to indata,updated to point to text after the word
* which is extracted.
* token is the extracted word, which is copied into a malloced
* space, and must be freed after use.
*
**************************************************************************/
char *GetNextArgument(char *indata,char **token)
{
char *t,*start, *end, *text;
t = indata;
if(t == NULL)
{
*token = NULL;
return NULL;
}
while(isspace(*t)&&(*t != 0))t++;
start = t;
while(!isspace(*t)&&(*t != 0))
{
/* Check for qouted text */
if(*t == '"')
{
t++;
while((*t != '"')&&(*t != 0))
{
/* Skip over escaped text, ie \" or \space " */
if((*t == '\\')&&(*(t+1) != 0))
t++;
t++;
}
if(*t == '"')
t++;
}
else
{
/* Skip over escaped text, ie \" or \space " */
if((*t == '\\')&&(*(t+1) != 0))
t++;
t++;
}
}
end = t;
text = safemalloc(end-start+1);
*token = text;
while(start < end)
{
/* Check for qouted text */
if(*start == '"')
{
start++;
while((*start != '"')&&(*start != 0))
{
/* Skip over escaped text, ie \" or \space " */
if((*start == '\\')&&(*(start+1) != 0))
start++;
*text++ = *start++;
}
if(*start == '"')
start++;
}
else
{
/* Skip over escaped text, ie \" or \space " */
if((*start == '\\')&&(*(start+1) != 0))
start++;
*text++ = *start++;
}
}
*text = 0;
if(*end != 0)
end++;
return end;
}
#endif /* 0 */
/*
function: MatchToken
description: matches one word
returns: pointer to delimiter character
NULL if no match
*/
#if 0 /* supported in 2.0.47b */
const char *MatchToken(register const char *s, register const char *w)
{
if (s==NULL) return NULL;
assert(w!=NULL); /* the token may not be NULL -> design flaw */
while (*w && (*s==*w ||
#ifdef WORD_IS_UPPERCASE
isupper(*s) && _toupper(*s)==*w
#else
toupper(*s)==toupper(*w)
#endif
))
s++,w++;
if (*w=='\0' && /* end of word and */
(*s=='\0' || ispunct(*s) || isspace(*s))) /* same in string */
return s; /* return endptr */
else
return NULL; /* no match */
}
#endif
/*
function: CmpToken
description: compare 1st word of s to 1st word of w
returns: < 0 if s < t
= 0 if s = t
> 0 if s > t
Note arguments are not declares register, so the function can be
used with the bsearch() <search.h> function of the c library.
*/
int XCmpToken(char *s, char **t)
{
register char *w=*t;
if (w==NULL) return 1; /* non existant word */
if (s==NULL) return -1; /* non existant string */
while (*w && (*s==*w ||
#ifdef WORD_IS_UPPERCASE
isupper(*s) && _toupper(*s)==*w
#else
toupper(*s)==toupper(*w)
#endif
))
s++,w++;
if ((*s=='\0' && (ispunct(*w) || isspace(*w)))||
(*w=='\0' && (ispunct(*s) || isspace(*s))) )
return 0; /* 1st word equal */
else
return toupper(*s)-toupper(*w); /* smaller/greater */
}