staden-lg/src/convert/list.c

417 lines
6.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include "list.h"
static char *mystrdup(char *s)
/*
* A quick implementation of strdup()
*/
{
char *copy;
if ( (copy = (char *)malloc(strlen(s)+1)) != NULL ) strcpy(copy,s);
return copy;
}
Node *nodeList = nil;
void destroy_node_list()
{
Node *n,*m;
for(n=nodeList;!isNil(n);) {
m = cdr(n);
free(n);
n = m;
}
}
static Node *create_node (int type)
{
Node *n;
if (isNil(nodeList)) {
n = (Node *) malloc(sizeof(Node));
} else {
n = nodeList;
nodeList = cdr(nodeList);
}
if (! isNil(n)){
n->type = type;
n->val.list.head = nil;
n->val.list.tail = nil;
}
return n;
}
static void free_node (Node *n)
{
if (isNil(n))
;
else {
n->type = Node_List; /* entries on the nodeList are ALWAYS lists */
n->val.list.head = nil;
n->val.list.tail = nodeList;
nodeList = n;
}
}
#define create_node_list() create_node(Node_List)
#define create_node_atom() create_node(Node_Atom)
void destroy_list (Node *n)
{
if (isNil(n))
;
else if (isAtom(n)){
free(atomVal(n)); /* free the atom here */
free_node(n);
} else {
destroy_list(car(n));
destroy_list(cdr(n));
free_node(n);
}
}
Node *copy_list(Node *n)
{
Node *new;
if (isNil(n))
new = nil;
else if (isAtom(n)){
new = create_node_atom();
new->val.atom.ptr = mystrdup(atomVal(n));
} else {
new = create_node_list();
new->val.list.head = copy_list(car(n));
new->val.list.tail = copy_list(cdr(n));
}
return new;
}
Node *atom_str(char *s)
{
Node *new;
new = create_node_atom();
new->val.atom.ptr = mystrdup(s);
return new;
}
Node *atom_int(int i)
{
char buffer[200];
sprintf(buffer,"%d",i);
return atom_str(buffer);
}
Node *build_list(Node *n1, ...)
{
Node *root;
Node *next;
Node *ROOT;
va_list ap;
va_start(ap, n1);
root = ROOT = create_node_list();
/*
* no action if n1 is nil
* we are trying to construct '()'
*/
if (! isNil(n1)) {
root->val.list.head = n1;
next = va_arg(ap, Node *);
while (! isNil(next)) {
Node *new;
new = create_node_list();
new->val.list.head = next;
root->val.list.tail = new;
root = new;
next = va_arg(ap, Node *);
}
}
va_end(ap);
return ROOT;
}
Node *tail_list(Node *n)
{
Node *tail;
if (isNil(n))
tail = nil;
else if (isAtom(n))
tail = nil;
else {
for ( tail = n; !isNil(cdr(tail)); tail = cdr(tail)) ;
}
return tail;
}
Node *join_list(Node *n1,...)
{
Node *tail;
Node *ROOT;
Node *next;
va_list ap;
va_start(ap, n1);
ROOT = n1;
tail = tail_list(ROOT);
next = va_arg(ap, Node *);
while (! isNil(next)) {
Node *newtail;
newtail = tail_list(next);
tail->val.list.tail = next;
tail = newtail;
next = va_arg(ap, Node *);
}
va_end(ap);
return ROOT;
}
static void _print_list (Node *n)
{
if ( isNil(n) ) {
printf("nil ");
} else if (isAtom(n))
printf("%s ", atomVal(n));
else {
Node *next;
printf("( ");
for (next = n; ! isNil(next); next = cdr(next))
_print_list(car(next));
printf(") ");
}
}
void print_list (Node *n)
{
_print_list(n);
nl;
}
static void printAtom(FILE *f, Atom *n)
{
char *val = atomVal(n);
char *q;
for (q=val; *q && !(isspace(*q)) && *q!='"' && *q!='(' && *q!=')'; q++);
if (*q) putc('"',f);
for (; *val; val++) {
if (*val=='"') putc('"',f);
putc(*val,f);
}
if (*q) putc('"',f);
}
static void _print_list_f (FILE *f,Node *n,int level)
{
if ( isNil(n) ) {
fprintf(f,"nil ");
} else if (isAtom(n)) {
printAtom(f,n);
fprintf(f," ");
} else {
Node *next;
int i;
if (level) fprintf(f,"\n");
for (i=0;i<level;i++) fprintf(f," ");
fprintf(f,"( ");
for (next = n; ! isNil(next); next = cdr(next))
_print_list_f(f,car(next),level+1);
fprintf(f,") ");
}
}
void print_list_f (Node *n)
{
_print_list_f(stdout, n,0);
nl;
}
void fprint_list_f (FILE *f, Node *n)
{
_print_list_f(f, n,0);
fnl(f);
}
Node *index_list(Node *n, Atom *a)
{
Node *index;
if (! isList(n) || ! isAtom(a))
index = nil;
else {
Node *i;
int found = 0;
for (i = n; ! isNil(i) && !found; i=cdr(i)) {
index = car(i);
if (isList(index) && isAtom(car(index))) {
found = (strcmp(atomVal(car(index)),atomVal(a))==0);
}
}
if (! found) index = nil;
}
return index;
}
Node *index_list_by_str(Node *n, char *a)
{
Atom *atom;
List *node;
atom = atom_str(a);
node = index_list(n,atom);
destroy_list(atom);
return node;
}
char *assoc(Node *n, char *a)
{
return atomVal(car(cdr(index_list_by_str(n,a))));
}
int read_string(FILE *fp, char **s)
{
char buff[4096];
int c;
int len;
int ret;
/* skip over while space */
for (c = getc(fp);c != EOF && isspace(c); c= getc(fp));
len = 0;
ret = 0;
if (c == EOF)
*s = NULL;
else if (c == '"') {
int l;
for (c = getc(fp), l = getc(fp);
c != EOF && !(c=='"' && (l == EOF || l!='"') );
c=l,l = getc(fp)) {
buff[len++] = c;
if (c=='"' && l=='"') {
c = '\0';
l = getc(fp);
}
}
ret = 1;
buff[len] = '\0';
*s = (char *)mystrdup(buff);
} else {
buff[len++] = c;
for (c = getc(fp); c != EOF && !isspace(c); c = getc(fp))
buff[len++] = c;
buff[len] = '\0';
*s = (char *)mystrdup(buff);
}
return ret;
}
List *read_list(FILE *fp)
{
List *l;
char *s;
int q;
q = read_string(fp,&s);
if (s == NULL)
l = nil;
else if ( strcmp(s,")") == 0 && !q) {
free(s);
l = nil;
} else if ( strcmp(s,"(") == 0 && !q) {
List *item, *t;
free(s);
l = nil;
t = nil;
for (item = read_list(fp); ! isNil(item); item = read_list(fp)) {
List *m;
m = create_node_list();
m->val.list.head = item;
if (isNil(l)) l = m;
if (isNil(t))
t = m;
else {
t->val.list.tail = m;
t = m;
}
}
if (isNil(l)) l = create_node_list();
} else {
l = atom_str(s);
}
return l;
}