archie/archie/clients/telnet/argv.c
2024-05-27 16:13:40 +02:00

370 lines
5.9 KiB
C

#include <malloc.h>
#ifdef AIX
#include <stdlib.h>
#endif
#include <string.h>
#include "error.h"
#include "extern.h"
#include "lang.h"
#include "macros.h"
#include "misc_ansi_defs.h"
#include "rmem.h"
#include "protos.h"
typedef enum
{
AV_OUT_STR,
AV_IN_STR,
AV_IN_QUOTE,
AV_Q_IN_STR,
AV_Q_IN_QUOTE,
AV_DONE,
AV_ERROR
} State;
/*
*
* Internal routines
*
*/
#define INIT_ARGV_ELTS 16
#define INIT_STR_ELTS 32
static char **end_current_str PROTO((char *s, char **av));
static char **init_argv PROTO((void));
static char *insert_char PROTO((int c, char *s));
static char *new_str PROTO((void));
static char *insert_char(c, s)
int c;
char *s;
{
char ch = c;
char *ts = rappend(s, &ch, char);
if (ts) return ts;
else
{
rfree(s);
return (char *)0;
}
}
static char **end_current_str(s, av)
char *s;
char **av;
{
char *ts = insert_char('\0', s);
if (ts) return (char **)rappend(av, &ts, char *);
else
{
rfree(s);
return (char **)0;
}
}
static char **init_argv()
{
char **av;
if ((av = rmalloc(INIT_ARGV_ELTS, char *)))
{
av[0] = (char *)0;
return (char **)av;
}
else
{
error(A_SYSERR, curr_lang[65]);
return (char **)0;
}
}
static char *new_str()
{
char *s = rmalloc(INIT_STR_ELTS, char);
if (s) return s;
else
{
error(A_SYSERR, curr_lang[66], curr_lang[67], INIT_STR_ELTS);
return (char *)0;
}
}
/*
*
* External routines
*
*/
/*bug: generic argvFindStrCmp()*/
int argvFindStrCase(ac, av, start, end, str)
int ac;
char **av;
int start;
int end;
const char *str;
{
int i;
for (i = start; i <= end && i < ac; i++)
{
if (strcasecmp(av[i], str) == 0) return i;
}
return -1;
}
/*bug: start > ac or all args empty could cause problems */
char *argvFlattenSep(ac, av, start, end, sep)
int ac;
char **av;
int start;
int end;
const char *sep;
{
char *t = (char *)0;
int i;
int len = 0;
int seplen = strlen(sep);
ptr_check(av, char *, curr_lang[68], (char *)0);
for (i = start; i <= end && i < ac; i++)
{
len += strlen(av[i]) + seplen;
}
if ( ! (t = malloc((unsigned)(len + 1)))) /*bug? +1 for nul of final strcat */
{
error(A_SYSERR, curr_lang[68], curr_lang[69], len);
return (char *)0;
}
else
{
t[0] = '\0';
for (i = start; i <= end && i < ac; i++)
{
strcat(t, av[i]);
strcat(t, sep);
}
t[len - 1] = '\0';
return (char *)t;
}
}
int argvReplaceStr(ac, av, idx, newstr)
int ac;
char **av;
int idx;
const char *newstr;
{
char *s;
if (idx >= ac) return 0;
s = rmalloc((unsigned)strlen(newstr) + 1, char);
if ( ! s)
{
return 0;
}
else
{
strcpy(s, newstr);
rfree(av[idx]);
av[idx] = s;
return 1;
}
}
/*bug: start > ac or all args empty could cause problems */
char *argvflatten(ac, av, start)
int ac;
char **av;
int start;
{
return argvFlattenSep(ac, av, start, ac, " ");
}
void argvfree(av)
char **av;
{
int i;
for(i = 0; i <= last_index(av); i++)
{
rfree(av[i]);
av[i] = (char *)0;
}
rfree(av);
}
#define try(x, t, v, e) \
do { if ((t = (e))) { v = t; } else { error(A_ERR, curr_lang[70], curr_lang[71], x); state = ERROR; } } while (0)
int argvify(str, argc, argv)
const char *str;
int *argc;
char ***argv;
{
State state = AV_OUT_STR;
const char *p;
char *ts;
char *s = (char *)0;
char **av;
char **tav;
int done = 0;
ptr_check(str, const char, curr_lang[70], 0);
ptr_check(argc, int, curr_lang[70], 0);
ptr_check(argv, char **, curr_lang[70], 0);
*argc = 0;
*argv = (char **)0;
try(curr_lang[72], tav, av, init_argv());
p = str;
while ( ! done)
{
switch (state)
{
case AV_OUT_STR:
switch (*p)
{
case ' ':
case '\t':
break;
case '\\':
state = AV_Q_IN_STR;
try(curr_lang[73], ts, s, new_str());
break;
case '"':
state = AV_IN_QUOTE;
try(curr_lang[73], ts, s, new_str());
break;
case '\0':
state = AV_DONE;
break;
default:
state = AV_IN_STR;
try(curr_lang[73], ts, s, new_str());
try(curr_lang[74], ts, s, insert_char(*p, s));
break;
}
break;
case AV_IN_STR:
switch (*p)
{
case ' ':
case '\t':
state = AV_OUT_STR;
try(curr_lang[75], tav, av, end_current_str(s, av));
break;
case '\\':
state = AV_Q_IN_STR;
break;
case '"':
state = AV_IN_QUOTE;
break;
case '\0':
state = AV_DONE;
try(curr_lang[75], tav, av, end_current_str(s, av));
break;
default:
state = AV_IN_STR;
try(curr_lang[74], ts, s, insert_char(*p, s));
break;
}
break;
case AV_IN_QUOTE:
switch (*p)
{
case '\\':
state = AV_Q_IN_QUOTE;
break;
case '"':
state = AV_IN_STR;
break;
case '\0':
state = AV_ERROR;
break;
default:
state = AV_IN_QUOTE;
try(curr_lang[74], ts, s, insert_char(*p, s));
break;
}
break;
case AV_Q_IN_STR:
if ( ! *p) state = AV_ERROR;
else
{
state = AV_IN_STR;
try(curr_lang[74], ts, s, insert_char(*p, s));
}
break;
case AV_Q_IN_QUOTE:
if ( ! *p) state = AV_ERROR;
else
{
state = AV_IN_QUOTE;
try(curr_lang[74], ts, s, insert_char(*p, s));
}
break;
case AV_DONE:
case AV_ERROR:
default:
done = 1;
break;
}
p++;
}
switch (state)
{
case AV_DONE:
*argv = av;
*argc = last_index(av) + 1;
return 1;
case AV_ERROR:
if (s) rfree(s);
argvfree(av);
return 0;
default:
error(A_INTERR, curr_lang[70], curr_lang[76], (int)state);
return 0;
}
}