|
|
|
@ -1,65 +1,93 @@
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <libse.h>
|
|
|
|
|
#include <internal/exstring.h>
|
|
|
|
|
|
|
|
|
|
static void _addcar(list_t* out, exString* token)
|
|
|
|
|
static void _addcar(list_t* out, exString* token, int nil, int ucase)
|
|
|
|
|
{
|
|
|
|
|
#ifdef SE_PARSE_NIL
|
|
|
|
|
if(strcmp(EXS(token), "nil")==0)
|
|
|
|
|
if(ucase)
|
|
|
|
|
for(char* t = *token; *t; t++)
|
|
|
|
|
*t = toupper((unsigned char)*t);
|
|
|
|
|
if(nil&&strcmp(EXS(token), "NIL")==0)
|
|
|
|
|
out->ptr = NULL;
|
|
|
|
|
else {
|
|
|
|
|
#endif
|
|
|
|
|
out->ptr = strdup(EXS(token));
|
|
|
|
|
out->car.size = strlen(out->ptr);
|
|
|
|
|
out->car.alloced = 1;
|
|
|
|
|
exs_reset(token);
|
|
|
|
|
#ifdef SE_PARSE_NIL
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static list_t* _parse_list(const char* sexpr, int* lp)
|
|
|
|
|
static list_t* _parse_list(const char* sexpr, int* lp, unsigned int flags)
|
|
|
|
|
{
|
|
|
|
|
list_t* out = malloc(sizeof(list_t));
|
|
|
|
|
memset(out,0,sizeof(list_t));
|
|
|
|
|
exString *token = exs_new(NULL);
|
|
|
|
|
|
|
|
|
|
int instr=0;
|
|
|
|
|
int inesc=0;
|
|
|
|
|
|
|
|
|
|
while(*sexpr) {
|
|
|
|
|
if(*sexpr==' ') {
|
|
|
|
|
if(inesc)
|
|
|
|
|
{
|
|
|
|
|
exs_nappend(token, sexpr, 1);
|
|
|
|
|
inesc=0;
|
|
|
|
|
}
|
|
|
|
|
else if(instr)
|
|
|
|
|
{
|
|
|
|
|
if(*sexpr=='\"')
|
|
|
|
|
instr=0;
|
|
|
|
|
else exs_nappend(token, sexpr, 1);
|
|
|
|
|
}
|
|
|
|
|
else if(*sexpr==' ' || *sexpr == '\r' || *sexpr == '\n' || *sexpr == '\t') {
|
|
|
|
|
if(strlen(EXS(token))>0) {
|
|
|
|
|
_addcar(out, token);
|
|
|
|
|
_addcar(out, token, flags & SET_PARSE_NIL, flags & SET_PARSE_INSENSITIVE);
|
|
|
|
|
|
|
|
|
|
if(*(sexpr+1))
|
|
|
|
|
out->cdr = _parse_list(sexpr, lp);
|
|
|
|
|
out->cdr = _parse_list(sexpr, lp, flags);
|
|
|
|
|
else out->cdr =NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(*sexpr == ')')
|
|
|
|
|
{
|
|
|
|
|
_addcar(out, token);
|
|
|
|
|
if(**token)
|
|
|
|
|
_addcar(out, token, flags & SET_PARSE_NIL, flags & SET_PARSE_INSENSITIVE);
|
|
|
|
|
out->cdr=NULL;
|
|
|
|
|
(*lp)+=1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if(*sexpr == '(')
|
|
|
|
|
{
|
|
|
|
|
int hp =0;
|
|
|
|
|
list_t* nc = _parse_list(sexpr+1, &hp);
|
|
|
|
|
out->ptr = nc;
|
|
|
|
|
out->car.alloced=1;
|
|
|
|
|
out->car.sexpr=1;
|
|
|
|
|
out->car.size = sizeof(list_t);
|
|
|
|
|
sexpr+= hp+1;
|
|
|
|
|
(*lp) += hp+1;
|
|
|
|
|
|
|
|
|
|
if(*(sexpr))
|
|
|
|
|
out->cdr = _parse_list(sexpr, lp);
|
|
|
|
|
else out->cdr =NULL;
|
|
|
|
|
break;
|
|
|
|
|
if(**token) {
|
|
|
|
|
_addcar(out, token, flags & SET_PARSE_NIL, flags&SET_PARSE_INSENSITIVE);
|
|
|
|
|
if(*(sexpr+1))
|
|
|
|
|
out->cdr = _parse_list(sexpr, lp ,flags);
|
|
|
|
|
else out->cdr = NULL; //Invalid syntax.
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
int hp =0;
|
|
|
|
|
list_t* nc = _parse_list(sexpr+1, &hp, flags);
|
|
|
|
|
out->ptr = nc;
|
|
|
|
|
out->car.alloced=1;
|
|
|
|
|
out->car.sexpr=1;
|
|
|
|
|
out->car.size = sizeof(list_t);
|
|
|
|
|
sexpr+= hp+1;
|
|
|
|
|
(*lp) += hp+1;
|
|
|
|
|
|
|
|
|
|
if(*(sexpr))
|
|
|
|
|
out->cdr = _parse_list(sexpr, lp, flags);
|
|
|
|
|
else out->cdr =NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(flags & SET_PARSE_QUOTE && *sexpr == '\"')
|
|
|
|
|
instr = 1;
|
|
|
|
|
else if(flags & SET_PARSE_ESCAPE && *sexpr == '\\')
|
|
|
|
|
inesc = 1;
|
|
|
|
|
else
|
|
|
|
|
exs_nappend(token, sexpr, 1);
|
|
|
|
|
sexpr+=1;
|
|
|
|
@ -67,7 +95,7 @@ static list_t* _parse_list(const char* sexpr, int* lp)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(strlen(EXS(token))>0)
|
|
|
|
|
_addcar(out, token);
|
|
|
|
|
_addcar(out, token, flags & SET_PARSE_NIL, flags & SET_PARSE_INSENSITIVE);
|
|
|
|
|
else if(!out->ptr && !out->cdr) {
|
|
|
|
|
free(out);
|
|
|
|
|
out=NULL;
|
|
|
|
@ -77,10 +105,89 @@ static list_t* _parse_list(const char* sexpr, int* lp)
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list_t* se_parse(const char* str)
|
|
|
|
|
static int iws(char c)
|
|
|
|
|
{
|
|
|
|
|
switch(c)
|
|
|
|
|
{
|
|
|
|
|
case ' ':
|
|
|
|
|
case '\t':
|
|
|
|
|
case '\n':
|
|
|
|
|
case '\r':
|
|
|
|
|
return 1;
|
|
|
|
|
default: return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int nows(const char* str)
|
|
|
|
|
{
|
|
|
|
|
register int i=0;
|
|
|
|
|
for(;*str&&iws(*str);str++) i++;
|
|
|
|
|
return !*str?0:i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int se_valid(const char* str)
|
|
|
|
|
{
|
|
|
|
|
exString* s = exs_new(str);
|
|
|
|
|
exs_whereip(s, &exspf_only_not, " \t\n\r");
|
|
|
|
|
|
|
|
|
|
char *ns = EXS(s);
|
|
|
|
|
int ret = *ns && !(*ns=='(' && memcmp(ns, ns+1, strlen(ns)-1)==0);
|
|
|
|
|
exs_free(s);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list_t* se_parse(const char* str, unsigned int flags)
|
|
|
|
|
{
|
|
|
|
|
if(!str) return NULL;
|
|
|
|
|
int lp=0,tst=0;
|
|
|
|
|
if(*str=='(')
|
|
|
|
|
str+=1;
|
|
|
|
|
else if( (tst=nows(str))>0)
|
|
|
|
|
return se_parse(str+tst, flags);
|
|
|
|
|
if(!se_valid(str)) return NULL;
|
|
|
|
|
return _parse_list(str,&lp, flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int _se_add_quotes(const char* inp)
|
|
|
|
|
{
|
|
|
|
|
do {
|
|
|
|
|
switch (*inp) {
|
|
|
|
|
case '\"':
|
|
|
|
|
case ' ':
|
|
|
|
|
case ')':
|
|
|
|
|
case '(':
|
|
|
|
|
return 1;
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
inp+=1;
|
|
|
|
|
}
|
|
|
|
|
while (*inp);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _se_append(exString *out, const char* thing)
|
|
|
|
|
{
|
|
|
|
|
int lp=0;
|
|
|
|
|
return _parse_list(str,&lp);
|
|
|
|
|
int q = _se_add_quotes(thing);
|
|
|
|
|
exString* str = exs_new(NULL);
|
|
|
|
|
|
|
|
|
|
for(;*thing;thing++)
|
|
|
|
|
{
|
|
|
|
|
switch(*thing)
|
|
|
|
|
{
|
|
|
|
|
case '\"':
|
|
|
|
|
exs_appendc(str, '\\');
|
|
|
|
|
default:break;
|
|
|
|
|
}
|
|
|
|
|
exs_nappend(str, thing, 1);
|
|
|
|
|
}
|
|
|
|
|
if(q)
|
|
|
|
|
{
|
|
|
|
|
exs_appendc(out, '\"');
|
|
|
|
|
exs_appendc(str, '\"');
|
|
|
|
|
}
|
|
|
|
|
exs_append(out, *str);
|
|
|
|
|
exs_free(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _list_tostring(exString *out, const list_t* list)
|
|
|
|
@ -91,7 +198,7 @@ void _list_tostring(exString *out, const list_t* list)
|
|
|
|
|
exs_append(out, "(");
|
|
|
|
|
_list_tostring(out, (list_t*)list->ptr);
|
|
|
|
|
}
|
|
|
|
|
else exs_append(out,(char*)list->ptr);
|
|
|
|
|
else _se_append(out,(char*)list->ptr);
|
|
|
|
|
|
|
|
|
|
if(list->cdr)
|
|
|
|
|
{
|
|
|
|
|