/*
* Copyright 1989 by Rayan S. Zachariassen, all rights reserved.
* This will be free software, but only when it is finished.
*/
/*
* List manipulation utility functions.
*/
#include "hostenv.h"
#include "listutils.h"
#ifdef MAILER
#include "sift.h"
#endif /* MAILER */
#include "mailer.h"
#include <ctype.h>
#include "sh.h"
#include "io.h"
#include "shconfig.h"
#include "libz.h"
#include "libsh.h"
/*
* Cdr down a linked list to retrieve its last element. This is not
* quite identical to (last l), which would be s_last(car(l)) due to
* our representation of lists.
*/
conscell *
s_last(list)
register conscell *list;
{
if (list == NULL)
return NULL;
while (cdr(list) != NULL)
list = cdr(list);
return list;
}
int
s_equal1(l1, l2)
register conscell *l1, *l2;
{
if (l1 == NULL)
return (l2 == NULL);
if (l2 == NULL)
return 0;
/* assert l1 != NULL && l2 != NULL */
if (STRING(l1) && STRING(l2))
return CISTREQ(l1->string, l2->string);
return 0;
}
int
s_equal(l1, l2)
register conscell *l1, *l2;
{
if (l1 == NULL)
return l2 == NULL;
else if (l2 == NULL)
return 0;
/* assert l1 != NULL && l2 != NULL */
if (STRING(l1) && STRING(l2) && CISTREQ(l1->string, l2->string))
return s_equal(cdr(l1), cdr(l2));
else if (LIST(l1) && LIST(l2) && s_equal(car(l1), car(l2)))
return s_equal(cdr(l1), cdr(l2));
return 0;
#if 0
if (l1->next == NULL) {
if (l2->next == NULL) {
if (STRING(l1)) {
if (STRING(l2))
return CISTREQ(l1->string, l2->string);
else
return 0;
} else {
if (STRING(l2))
return 0;
else
return s_equal(car(l1), car(l2));
}
} else
return 0;
} else if (l2->next == NULL)
return 0;
else
return s_equal(cdr(l1), cdr(l2));
#endif
}
/*
* The N'th element of a list.
*/
conscell *
s_nth(list, n)
register conscell *list;
register int n;
{
if (list == NULL || STRING(list))
return NULL;
for (list = car(list); list != NULL && n-- > 0; list = cdr(list))
continue;
if (list == NULL)
return NULL;
return list;
}
/*
* Does a string contain any metacharacters that might be misinterpreted
* if the string was read in as is?
*/
STATIC int s_isname __((const char *s));
STATIC int
s_isname(s)
register const char *s;
{
while (*s != '\0') {
int c = (*s) & 0xFF;
if (!isascii(c) || !isprint(c) || c == '\\' || c == ' ' ||
c == '\'' || c == '"' || *s == '`') {
return 0;
} else
++s;
}
return 1;
}
/*
* Print a string in quoted form.
*/
STATIC void s_pname __((const char *s, FILE *fp));
STATIC void
s_pname(s, fp)
register const char *s;
FILE *fp;
{
const char *base = s;
if (*s != '\'')
putc('\'', fp);
while (*s != '\0') {
if (*s == '\'') {
if (s > base)
putc('\'', fp); /* end previous string */
putc('\\', fp); /* backslash */
putc('\'', fp); /* quote */
if (*(s+1) == '\0')
return;
/* putc('\'', fp); */ /* start new string */
}
putc(*s, fp);
++s;
}
putc('\'', fp);
}
/*
* Print a list.
*/
void
s_grind(list, fp)
conscell *list;
FILE *fp;
{
if (list == NULL) {
fputs("<0>", fp);
return;
} else if (STRING(list)) {
if (list->string != NULL) {
if (list->string[0] && s_isname(list->string))
fputs(list->string, fp);
else
s_pname(list->string, fp);
} else
fputs("\\000", fp);
} else if ((list = car(list))) {
putc('(', fp);
while (list != NULL) {
if (list == envarlist)
fputs(ENVIRONMENT, fp);
else
s_grind(list, fp);
if ((list = cdr(list)))
putc(' ', fp);
}
putc(')', fp);
} else
fputs("nil", fp);
}
/*
* Print a list to stdout.
*/
void
_grind(list)
conscell *list;
{
s_grind(list, stderr);
putc('\n', stderr);
}
/*
* Squish a linked list of buffers into a single buffer.
*/
conscell *
s_catstring(s)
conscell *s;
{
char *cp, *buf;
conscell *sp; /* No need to protect below */
int len, quoted;
if (cdr(s) == NULL)
return s;
len = 0;
for (sp = s; sp != NULL; sp = cdr(sp))
if (STRING(sp) && sp->cstring)
len += sp->slen;
quoted = 0;
cp = buf = mallocstr(len);
for (sp = s; sp != NULL; sp = cdr(sp)) {
if (STRING(sp) && sp->cstring) {
memcpy(cp, sp->cstring, sp->slen);
cp += sp->slen;
quoted += ISQUOTED(sp);
}
}
*cp++ = '\0';
sp = newstring(buf, len);
if (quoted)
sp->flags |= QUOTEDSTRING;
return sp;
}
/*
* Construct a list structure representing the data on the input file pointer.
*/
conscell *
s_read(fp)
FILE *fp;
{
register int ch;
register char *bp;
register conscell **listp;
char ech, buf[8096];
conscell *list;
GCVARS1;
memtypes oval = stickymem;
if (feof(fp))
return NULL;
while ((ch = getc(fp)) != EOF)
if (!(isascii(ch) && isspace(ch)))
break;
bp = buf;
list = NULL; /* lint */
GCPRO1(list);
switch (ch) {
case '(':
list = newcell();
list->flags = 0;
cdr(list) = NULL;
listp = &car(list);
do {
if ((*listp = s_read(fp)) == NULL)
break;
if ((cdr(*listp) = s_read(fp)))
listp = &cddr(*listp);
else
break;
} while (1);
break;
case ')':
case EOF:
UNGCPRO1;
return NULL;
case '"': /* quoted symbol */
case '\'':
ech = ch;
while ((ch = getc(fp)) != EOF && ch != ech) {
if (ch == '\\')
if ((ch = getc(fp)) == EOF)
break;
*bp++ = ch;
}
*bp = '\0';
list = newstring(dupnstr(buf, bp - buf), bp-buf);
break;
default: /* normal symbol */
*bp++ = ch;
while ((ch = getc(fp)) != EOF && isascii(ch) &&
!isspace(ch) && ch != '(' && ch != ')') {
if (ch == '\\')
if ((ch = getc(fp)) == EOF)
break;
*bp++ = ch;
}
if (ch != EOF)
ungetc(ch, fp);
*bp = '\0';
stickymem = MEM_MALLOC;
list = newstring(dupnstr(buf, bp - buf), bp-buf);
stickymem = oval;
break;
}
/* putc('>', runiofp);s_grind(list, runiofp); putc('\n', runiofp); */
UNGCPRO1;
return list;
}
/*
* Turn an argc,argv type parameter spec into a list of the argv's.
*/
conscell *
s_listify(ac, av)
register int ac;
register const char *av[];
{
register conscell **pl;
conscell *l = NIL;
GCVARS1;
GCPRO1(l);
pl = &car(l);
for ( ;ac > 0 && *av != NULL; --ac,++av) {
int slen = strlen(av[0]);
*pl = newstring(dupnstr(av[0], slen), slen);
pl = &cdr(*pl);
*pl = NULL;
}
UNGCPRO1;
return l;
}
/* push a command string onto the input stack */
conscell *
s_pushstack(l, s)
conscell *l;
const char *s;
{
conscell *d;
GCVARS1;
int slen = strlen(s);
d = newstring(dupnstr(s, slen), slen);
GCPRO1(d);
cdr(d) = conststring(" \n", 2);
cddr(d) = l;
UNGCPRO1;
return d;
}
conscell *
s_popstack(l)
conscell *l;
{
conscell *d;
d = l;
l = cdr(l);
cdr(d) = NULL;
/* s_free_tree(d); */
return l;
}
#if 0 /* New GC/newcell() will take over this */
conscell *
newcell()
{
return (conscell*)tmalloc(sizeof(conscell));
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1