#include "RxI.h"
#include <ctype.h>
typedef struct {
char *ptr;
int length;
} NString;
#ifdef NETSCAPE_PLUGIN
void *
_RxRealloc(void *p, size_t olds, size_t s)
{
void *np = Malloc(s);
if (np) {
memcpy(np, p, olds);
Free(p);
}
return np;
}
#endif
static char *
NextWord(char *stream, char *limit, NString *word)
{
while (isspace((int) *stream) && *stream && stream != limit)
stream++;
word->ptr = stream;
while (!isspace((int) *stream) && *stream && stream != limit)
stream++;
word->length = stream - word->ptr;
return stream;
}
static char *
NextChunk(char *stream, char *limit, NString *word)
{
while (isspace((int) *stream) && *stream && stream != limit)
stream++;
word->ptr = stream;
while (!isspace((int) *stream) && *stream && stream != limit) {
if (*stream == '"' || *stream == '\'') {
char quote = *stream;
do
stream++;
while (*stream != quote && *stream && stream != limit);
if (*stream && stream != limit)
stream++;
break;
} else
stream++;
}
word->length = stream - word->ptr;
return stream;
}
static char *
NextElement(char *stream, NString *element)
{
while (*stream != '<' && *stream)
stream++;
element->ptr = stream;
while (*stream != '>' && *stream)
stream++;
element->length = stream - element->ptr;
return *stream ? stream + 1 : stream;
}
static char *
NextParam(char *stream, NString *param)
{
NString element, word;
do {
stream = NextElement(stream, &element);
if (element.length)
(void) NextWord(element.ptr + 1, element.ptr + element.length - 1,
&word);
else {
param->ptr = 0;
param->length = 0;
return stream;
}
} while(word.length != 5 && memcmp("PARAM", word.ptr, 5) != 0 && *stream);
param->ptr = word.ptr + word.length;
param->length = element.length - word.length - 1;
return stream;
}
static char *
GetLiteralValue(NString *literal)
{
char *ptr, *limit, *value, *vptr;
char quote;
int skip;
value = vptr = (char *)Malloc(literal->length + 1);
if (!value)
return 0;
ptr = literal->ptr;
limit = ptr + literal->length;
quote = (*ptr == '"' || *ptr == '\'') ? *ptr++ : '\0';
skip = 0;
do
if (isspace((int) *ptr)) {
if (!skip) {
*vptr++ = ' ';
skip = 1;
}
ptr++;
} else {
skip = 0;
*vptr++ = *ptr++;
}
while (*ptr != quote && ptr != limit);
*vptr = '\0';
return value;
}
static int
ParseParam(NString *param, char **name_ret, char **value_ret)
{
NString word, name, value;
char *stream = param->ptr;
char *limit = param->ptr + param->length;
do
stream = NextChunk(stream, limit, &word);
while (word.length < 5 && memcmp("NAME=", word.ptr, 5 != 0) && *stream);
if (stream == limit)
return 1;
name.ptr = word.ptr + 5;
name.length = word.length - 5;
*name_ret = GetLiteralValue(&name);
do
stream = NextChunk(stream, limit, &word);
while (word.length < 6 && memcmp("VALUE=", word.ptr, 6) != 0 && *stream);
value.ptr = word.ptr + 6;
value.length = word.length - 6;
*value_ret = GetLiteralValue(&value);
return 0;
}
#define PARAMSINC 10
int
RxReadParams(char *stream,
char **argn_ret[], char **argv_ret[], int *argc_ret)
{
char **argv, **argn;
int argc, n;
NString param;
char *name, *value;
int status;
status = 0;
argc = n = 0;
argn = argv = NULL;
if (stream != NULL) {
do {
stream = NextParam(stream, ¶m);
if (param.length != 0 && ParseParam(¶m, &name, &value) == 0) {
argc++;
if (n == 0) {
n = PARAMSINC;
argn = (char **)Malloc(sizeof(char *) * n);
if (!argn)
return 1;
argv = (char **)Malloc(sizeof(char *) * n);
if (!argv) {
Free(argn);
return 1;
}
}
if (argc % PARAMSINC == 0) {
n += PARAMSINC;
argn = (char **)
Realloc(argn, sizeof(char *) * argc, sizeof(char *) * n);
argv = (char **)
Realloc(argv, sizeof(char *) * argc, sizeof(char *) * n);
if (!argn || !argv) {
argc--;
status = 1;
break;
}
}
argn[argc - 1] = name;
argv[argc - 1] = value;
}
} while (*stream);
}
*argn_ret = argn;
*argv_ret = argv;
*argc_ret = argc;
return status;
}