diff --git a/include/libse.h b/include/libse.h index ae6538d..b9460dd 100644 --- a/include/libse.h +++ b/include/libse.h @@ -18,16 +18,28 @@ typedef struct cons { struct cons* cdr; } list_t; -#define SET_PARSE_NIL (1<<0) -#define SET_PARSE_QUOTE (1<<1) -#define SET_PARSE_ESCAPE (1<<2) -#define SET_PARSE_INSENSITIVE (1<<3) +enum _se_type { + SE_NIL=0, + SE_STRING, + SE_LIST, +}; + +#define SET_PARSE_NIL (1<<0) //Parse `NIL' as null pointer +#define SET_PARSE_QUOTE (1<<1) //Parse "string quotes" +#define SET_PARSE_ESCAPE (1<<2) //Parse "escape \" sequences \"" +#define SET_PARSE_INSENSITIVE (1<<3) //PARSE ALL AS UPPERCASE +#define SET_NO_WRAP (1<<4) //Interpret "(one two three)" as (one two three) instead of ((one two three)) #define SETP_DEFAULT (SET_PARSE_QUOTE | SET_PARSE_ESCAPE) #define SETP_LISP (SETP_DEFAULT | SET_PARSE_INSENSITIVE | SET_PARSE_NIL) +#define se_parsed(s) se_parse((s), SET_DEFAULT) list_t* se_parse(const char* sexpr, unsigned int flags); //Parse string into list. void se_free(list_t* list); //Free whole list. void se_print(FILE* fp, const list_t* list); //Print list to fp, if fp is NULL, print to stdout. +enum _se_type se_typeof(list_t* cons); //Get type of cons's car value. +list_t* se_new(char* from, int dupe); //Create new cons. +#define se_newd(f) se_new((f), 1) +list_t* se_last(list_t* list); //Get last non-nil cons. #endif /* _LIBSE_H */ diff --git a/src/exstring.c b/src/exstring.c index caef837..ded7d03 100644 --- a/src/exstring.c +++ b/src/exstring.c @@ -177,17 +177,17 @@ exString* exs_where(exString* from, exsp_where func, void* data) void exs_selectip(exString* str, exsp_select func, void* data) { exString* out = exs_select(str,func,data); - exs_reset(str); - exs_append(str, *out); - exs_free(out); + free(GETOPT(str)); + *str = *out; + free(out); } void exs_whereip(exString* str, exsp_where func, void* data) { exString* out = exs_where(str,func,data); - exs_reset(str); - exs_append(str, *out); - exs_free(out); + free(GETOPT(str)); + *str = *out; + free(out); } void exs_reset(exString *str) diff --git a/src/libse.c b/src/libse.c index 4030195..0c9eb35 100644 --- a/src/libse.c +++ b/src/libse.c @@ -132,16 +132,23 @@ int se_valid(const char* str) char *ns = EXS(s); int ret = *ns && !(*ns=='(' && memcmp(ns, ns+1, strlen(ns)-1)==0); + exs_free(s); return ret; } +list_t* se_last(list_t *list) +{ + if(list->cdr) return se_last(list->cdr); + else return list; +} + list_t* se_parse(const char* str, unsigned int flags) { if(!str) return NULL; int lp=0,tst=0; - if(*str=='(') + if(*str=='(' && !(flags & SET_NO_WRAP)) str+=1; else if( (tst=nows(str))>0) return se_parse(str+tst, flags); @@ -157,6 +164,8 @@ static int _se_add_quotes(const char* inp) case ' ': case ')': case '(': + case '\t': + case '\r': return 1; default: break; } @@ -175,6 +184,7 @@ void _se_append(exString *out, const char* thing) { switch(*thing) { + case '\n': case '\"': exs_appendc(str, '\\'); default:break; @@ -224,7 +234,73 @@ void se_print(FILE* fp, const list_t* list) void se_free(list_t* list) { if(list->cdr) se_free(list->cdr); - if(list->ptr && list->car.alloced) - free(list->ptr); + if(list->ptr) { + if(list->car.alloced) { + if(list->car.sexpr) + se_free((list_t*)list->ptr); + else + free(list->ptr); + } + } free(list); } + +enum _se_type se_typeof(list_t* list) +{ + if(!list->ptr) return SE_NIL; + else if(list->car.sexpr) return SE_LIST; + else return SE_STRING; +} + +static list_t* _se_new(void* car, enum _se_type type, int dupe) +{ + list_t* m = malloc(sizeof(list_t)); + memset(m,0,sizeof(list_t)); + void* _car = car; + if(car) { + switch(type) + { + case SE_STRING: + if(dupe) { + char* dup = strdup((char*)car); + m->ptr = dup; + m->car.size = strlen(dup); + m->car.alloced = 1; + } + else { + m->ptr = car; + m->car.size = strlen(car); + } + break; + case SE_LIST: + if(dupe) { //TODO: Clone alloced cars? + list_t* cr = malloc(sizeof(list_t)); + list_t* or = cr; + list_t* car = _car; + memcpy(cr, car, sizeof(list_t)); + while(car->cdr) { + cr->cdr = malloc(sizeof(list_t)); + memcpy(cr->cdr, car->cdr, sizeof(list_t)); + cr->cdr->car.alloced = 0; + car = car->cdr; + cr = cr->cdr; + } + m->ptr = or; + m->car.size = sizeof(list_t); + m->car.alloced = 1; + } + else { + m->ptr = car; + m->car.size = sizeof(list_t); + } + break; + default: break; + } + } + return m; +} + +list_t* se_new(char* str, int dupe) +{ + return _se_new(str, SE_STRING, dupe); //We don't need the list part. +} diff --git a/src/test/main.c b/src/test/main.c index 094fe52..9b4de4d 100644 --- a/src/test/main.c +++ b/src/test/main.c @@ -69,9 +69,26 @@ void test_parse() exs_free(buf); } +void test_make() +{ + list_t* l = se_new("Hello", 1); + l->cdr = se_new("world", 1); + + list_t* n = se_parse("(I love you)", SETP_DEFAULT | SET_NO_WRAP); + + se_last((((l->cdr->cdr = n)->cdr = se_parse("((((very)) much))", SETP_DEFAULT)) + ->cdr = se_parse("((\\\n more parsing))", SETP_DEFAULT)) + ->cdr = se_parse("((AND EVEN (M (O (R (E))))) !!!)", SETP_DEFAULT))->cdr = se_parse("(test test test!)", SETP_DEFAULT); + + se_print(NULL, l); + printf("\n"); + se_free(l); +} + int main() { // test_exs(); test_parse(); + test_make(); return 0; }