aboutsummaryrefslogtreecommitdiff
path: root/src/ctemplates.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ctemplates.c')
-rw-r--r--src/ctemplates.c241
1 files changed, 229 insertions, 12 deletions
diff --git a/src/ctemplates.c b/src/ctemplates.c
index 8138f7c..2129ec2 100644
--- a/src/ctemplates.c
+++ b/src/ctemplates.c
@@ -87,6 +87,18 @@ struct TMPL_tagnode* parse_variable(
struct TMPL_token* head,
struct TMPL_buf* errbuf
);
+struct TMPL_tagnode* parse_continue(
+ struct TMPL_token* head,
+ struct TMPL_buf* errbuf
+ );
+struct TMPL_tagnode* parse_break(
+ struct TMPL_token* head,
+ struct TMPL_buf* errbuf
+ );
+struct TMPL_tagnode* parse_end(
+ struct TMPL_token* head,
+ struct TMPL_buf* errbuf
+ );
struct TMPL_varlist* TMPL_alloc_varlist(void);
int TMPL_free_hashmapitems(any_t a, any_t b);
void TMPL_free_varlist(struct TMPL_varlist* vl);
@@ -133,6 +145,16 @@ int render_loop(
struct TMPL_tagnode* node,
struct TMPL_varlist* varlist
);
+int render_continue(
+ struct TMPL_templates* t,
+ struct TMPL_tagnode* node,
+ struct TMPL_varlist* varlist
+ );
+int render_break(
+ struct TMPL_templates* t,
+ struct TMPL_tagnode* node,
+ struct TMPL_varlist* varlist
+ );
int render_any(
struct TMPL_templates* t,
struct TMPL_tagnode* node,
@@ -233,8 +255,7 @@ starts_with_token(const char* str, size_t strlen){
&& *(str + 6) == 'R'
&& *(str + 7) == 'E'
&& *(str + 8) == 'A'
- && *(str + 9) == 'K'
- && *(str + 10) == ' '){
+ && *(str + 9) == 'K'){
return tag_break;
}else if(strlen > TAG_CONTINUE_LENGTH
&& *(str + 5) == 'C'
@@ -244,8 +265,7 @@ starts_with_token(const char* str, size_t strlen){
&& *(str + 9) == 'I'
&& *(str + 10) == 'N'
&& *(str + 11) == 'U'
- && *(str + 12) == 'E'
- && *(str + 13) == ' '){
+ && *(str + 12) == 'E'){
return tag_continue;
}else{
return tag_null;
@@ -363,10 +383,13 @@ TMPL_add_var_to_varlist(struct TMPL_varlist* t, const char* varname, const char*
void
print_ast_helper(struct TMPL_tagnode* cursor, int level){
+ /*printf("Helper called, level %d\n",level);*/
int i;
+ /*printf("Cursor is: %p\n", (void*)cursor);*/
for(i = 0; i < level; i++){
printf("|");
}
+ /*printf("type is %d\n",cursor->type);*/
printf("} %d ->",(int)cursor->type);
switch(cursor->type){
case tag_null:
@@ -411,10 +434,10 @@ print_ast_helper(struct TMPL_tagnode* cursor, int level){
print_ast_helper(cursor->TMPL_tag.loop.body,level+1);
break;
case tag_break:
- printf("TAG Break\n");
+ printf("TAG Break (%d)\n",cursor->TMPL_tag.breakcont.level);
break;
case tag_continue:
- printf("TAG Continue\n");
+ printf("TAG Continue (%d)\n",cursor->TMPL_tag.breakcont.level);
break;
}
if(cursor->next != NULL){
@@ -423,6 +446,7 @@ print_ast_helper(struct TMPL_tagnode* cursor, int level){
}
void
print_ast(struct TMPL_templates* t){
+ printf("Printing template %p\nRoottag: %p\n",(void*)t,(void*)t->roottag);
print_ast_helper(t->roottag,0);
}
@@ -497,9 +521,37 @@ is_whitespace(char c){
return (c == ' ' || c == '\t' || c == '\n') ? 1 : 0;
}
+const char* tokentype_to_str(struct TMPL_token *head){
+ switch(head->type){
+ case tag_null:
+ return "NULL";
+ case tag_text:
+ return "TEXT";
+ case tag_var:
+ return "VAR";
+ case tag_if:
+ return "IF";
+ case tag_elseif:
+ return "ELSEIF";
+ case tag_else:
+ return "ELSE";
+ case tag_end:
+ return "END";
+ case tag_loop:
+ return "LOOP";
+ case tag_break:
+ return "BREAK";
+ case tag_continue:
+ return "CONTINUE";
+ default:
+ return "UNKNOWN";
+ }
+}
+
struct TMPL_tagnode*
parse_text(struct TMPL_token* head, struct TMPL_buf* errbuf){
struct TMPL_tagnode* t = alloc_tagnode();
+ head->into = t;
t->TMPL_tag.text.start = head->start;
t->TMPL_tag.text.len = head->length;
t->type = head->type;
@@ -517,6 +569,7 @@ parse_else(struct TMPL_token* head, struct TMPL_buf* errbuf){
struct TMPL_tagnode*
parse_elseif(struct TMPL_token* head, struct TMPL_buf* errbuf){
struct TMPL_tagnode* t = alloc_tagnode();
+ head->into = t;
const char* start_of_attribs = head->start + TAG_ELSEIF_LENGTH;
int name_offset = kmp(start_of_attribs,head->length, ATTRIBUTE_VARNAME,ATTRIBUTE_VARNAME_LENGTH);
const char* start_of_name = start_of_attribs + name_offset + ATTRIBUTE_VARNAME_LENGTH;
@@ -593,7 +646,6 @@ parse_elseif(struct TMPL_token* head, struct TMPL_buf* errbuf){
t->TMPL_tag.ifelse.tbranch = parse(head->next,errbuf);
t->next = parse(cursor->next,errbuf);
-
t->type = tag_elseif;
return t;
@@ -602,6 +654,7 @@ parse_elseif(struct TMPL_token* head, struct TMPL_buf* errbuf){
struct TMPL_tagnode*
parse_if(struct TMPL_token* head, struct TMPL_buf* errbuf){
struct TMPL_tagnode* t = alloc_tagnode();
+ head->into = t;
const char* start_of_attribs = head->start + TAG_IF_LENGTH;
/*Find the name of the varialbe*/
int name_offset = kmp(start_of_attribs,head->length,ATTRIBUTE_VARNAME,ATTRIBUTE_VARNAME_LENGTH);
@@ -681,7 +734,6 @@ parse_if(struct TMPL_token* head, struct TMPL_buf* errbuf){
t->TMPL_tag.ifelse.tbranch = parse(head->next,errbuf);
/*Walk the tbranch and try to find if we have elseifs*/
t->next = parse(cursor->next,errbuf);
-
t->type = tag_if;
return t;
}
@@ -690,6 +742,7 @@ parse_if(struct TMPL_token* head, struct TMPL_buf* errbuf){
struct TMPL_tagnode*
parse_loop(struct TMPL_token* head, struct TMPL_buf* errbuf){
struct TMPL_tagnode* t = alloc_tagnode();
+ head->into = t;
const char* loop_start = head->start + TAG_LOOP_LENGTH;
int loop_length = head->length - TAG_LOOP_LENGTH;
int name_offset = kmp(loop_start,loop_length, ATTRIBUTE_VARNAME, ATTRIBUTE_VARNAME_LENGTH);
@@ -736,13 +789,27 @@ parse_loop(struct TMPL_token* head, struct TMPL_buf* errbuf){
}
cursor = cursor->next;
}
+ printf("When parsing loop, cursor for continue is %p\n",(void*)cursor);
if(cursor == NULL){
bputs(errbuf,"Parse error: Tried parsing loop and hit end of stream near\n");
bputsn(errbuf,head->start,ERRBUF_HINTLEN);
return NULL;
}
- t->TMPL_tag.loop.body = parse(head->next,errbuf);
+ printf("When parsing loop, cursor was %p and cursor->next was %p\n",(void*)cursor,(void*)cursor->next);
t->next = parse(cursor->next,errbuf);
+ printf("Setting loop %p's next to %p\n",(void*)t,(void*)t->next);
+ t->TMPL_tag.loop.body = parse(head->next,errbuf);
+ return t;
+}
+
+const char end_str[] = "";
+struct TMPL_tagnode* parse_end(struct TMPL_token* head, struct TMPL_buf* errbuf){
+ struct TMPL_tagnode* t = alloc_tagnode();
+ head->into = t;
+ t->TMPL_tag.text.start = end_str;
+ t->TMPL_tag.text.len = 0;
+ t->type = tag_text;
+ t->next = NULL;
return t;
}
@@ -750,6 +817,7 @@ parse_loop(struct TMPL_token* head, struct TMPL_buf* errbuf){
struct TMPL_tagnode*
parse_variable(struct TMPL_token* head, struct TMPL_buf* errbuf){
struct TMPL_tagnode* t = alloc_tagnode();
+ head->into =t;
/*<TMPL_VAR name="..." default="...">
^*/
const char* start_of_attribs = head->start + TAG_VAR_LENGTH;
@@ -813,6 +881,110 @@ parse_variable(struct TMPL_token* head, struct TMPL_buf* errbuf){
return t;
}
+struct TMPL_tagnode*
+parse_continue(struct TMPL_token* head, struct TMPL_buf* errbuf){
+ printf("Praseing continue\n");
+ struct TMPL_tagnode* t = alloc_tagnode();
+ head->into = t;
+ const char* start_of_attribs = head->start + TAG_CONTINUE_LENGTH;
+ unsigned int level = 1; //how many loops to continue
+ /*We might have multiple loops to continue through*/
+ int level_offset = kmp(start_of_attribs,head->length,ATTRIBUTE_LEVEL, ATTRIBUTE_LEVEL_LENGTH);
+ if(level_offset != -1){//level found
+ const char* start_of_level = start_of_attribs + level_offset + ATTRIBUTE_LEVEL_LENGTH;
+ while(is_whitespace(*start_of_level))
+ start_of_level++;
+ if(*start_of_level != '='){
+ printf("Start of level was %c\n",*start_of_level);
+ if(*start_of_level == '>'){
+ level = 1;
+ }else{
+ bputs(errbuf,"Parsing error: Expected \"=\" in <TMPL_continue ...> near ");
+ bputsn(errbuf,head->start,ERR_MSG_LEN);
+ bputs(errbuf,"\n");
+ }
+ }else{
+ start_of_level++;
+ while(is_whitespace(*start_of_level)){
+ start_of_level++;
+ }
+ sscanf(start_of_level,"%u",&level);
+ }
+ }
+ printf("Found continue %u levels\n",level);
+ int y = level;
+ struct TMPL_token* cursor = head;
+ while(y > 0){
+ //Scan backwards until we find the loop we're in
+ while(cursor != NULL && cursor->type != tag_loop){
+ cursor = cursor->last;
+ }
+ y--;
+ if(y > 0 && cursor == NULL){
+ size_t msglen = snprintf(NULL,0,"Parsing error: Continue was %d levels, but was only nested %d levels deep\n",level, level - y);
+ char errmsg[msglen];
+ sprintf(errmsg, "Parsing error: Continue was %d levels, but was only nested %d levels deep\n",level, level - y);
+ bputs(errbuf,errmsg);
+ }
+ }
+ printf("Turning continue's next into %5s's into(%p)\n",cursor->start,(void*)cursor->into->next);
+ t->TMPL_tag.breakcont.level = level;
+ t->next = parse(head->next,errbuf);
+ t->type = tag_continue;
+ return t;
+}
+
+struct TMPL_tagnode*
+parse_break(struct TMPL_token* head, struct TMPL_buf* errbuf){
+ struct TMPL_tagnode* t = alloc_tagnode();
+ head->into = t;
+ const char* start_of_attribs = head->start + TAG_CONTINUE_LENGTH;
+ unsigned int level = 1; //how many loops to continue
+ /*We might have multiple loops to continue through*/
+ int level_offset = kmp(start_of_attribs,head->length,ATTRIBUTE_LEVEL, ATTRIBUTE_LEVEL_LENGTH);
+ if(level_offset != -1){ //level found
+ const char* start_of_level = start_of_attribs + level_offset + ATTRIBUTE_LEVEL_LENGTH;
+ while(is_whitespace(*start_of_level))
+ start_of_level++;
+ if(*start_of_level != '='){
+ bputs(errbuf,"Parsing error: Expected \"=\" in <TMPL_break ...> near ");
+ bputsn(errbuf,head->start,ERR_MSG_LEN);
+ bputs(errbuf,"\n");
+ }else{
+ start_of_level++;
+ while(is_whitespace(*start_of_level)){
+ start_of_level++;
+ }
+ sscanf(start_of_level,"%u",&level);
+ }
+ }
+ t->TMPL_tag.breakcont.level = level;
+ int y = level;
+ struct TMPL_token* cursor = head;
+ while(y > 0){
+ //Scan backwards until we find the loop we're in
+ while(cursor != NULL && cursor->type != tag_loop){
+ cursor = cursor->last;
+ }
+ y--;
+ if(y > 0 && cursor == NULL){
+ printf("Failed 927\n");
+ exit(-1);
+ size_t msglen = snprintf(NULL,0,"Parsing error: Break was %d levels, but was only nested %d levels deep\n",level,level - y);
+ char errmsg[msglen];
+ sprintf(errmsg,"Parsing error: Break was %d levels, but was only nested %d levels deep\n",level,level - y);
+ bputs(errbuf,errmsg);
+ }
+ }
+ printf("Turning break's next into %5s's into (%p)\n",cursor->start,(void*)cursor->into);
+ /*t->next = cursor->into;*/
+ t->next = NULL;
+ printf("At time of prasing, cursor is %p and cursor->into is %p\n",(void*)cursor,(void*)cursor->into);
+ t->TMPL_tag.breakcont.into = cursor->into;
+ t->type = tag_break;
+ return t;
+}
+
struct TMPL_varlist*
TMPL_alloc_varlist(){
struct TMPL_varlist* ret = (struct TMPL_varlist*)malloc(sizeof(struct TMPL_varlist));
@@ -891,6 +1063,7 @@ parse(struct TMPL_token* head, struct TMPL_buf* errbuf){
if(head == NULL){
return NULL;
}
+ printf("Parse called... on type (%d:%s)\n",head->type,tokentype_to_str(head));
switch(head->type){
case tag_text:
root = parse_text(head,errbuf);
@@ -902,7 +1075,8 @@ parse(struct TMPL_token* head, struct TMPL_buf* errbuf){
root = parse_loop(head,errbuf);
break;
case tag_end:
- root = NULL;
+ //A 0-sized string to make break fall out right
+ root = parse_end(head,errbuf);
break;
case tag_if:
root = parse_if(head,errbuf);
@@ -913,13 +1087,25 @@ parse(struct TMPL_token* head, struct TMPL_buf* errbuf){
case tag_else:
root = NULL;
break;
+ case tag_continue:
+ printf("Parsing continue\n");
+ root = parse_continue(head,errbuf);
+ break;
+ case tag_break:
+ printf("Parsing break\n");
+ root = parse_break(head,errbuf);
+ break;
default:
exit(-1);
break;
}
if(errbuf->total_len > 0){
+ printf("Error parsing %p\n",(void*)head);
+ size_t dummy;
+ printf("Error: %s\n",bstringify(errbuf,&dummy));
return NULL;
}
+ printf("parse returning %p\n",(void*)root);
return root;
}
@@ -936,17 +1122,22 @@ compile(const char* tmplstr){
ret->out = alloc_tmpl_buf();
ret->errout = alloc_tmpl_buf();
struct TMPL_token* tokens = TMPL_tokenize(tmplstr,slen);
+ printf("After tokenizing, tokens are:\n");
+ print_tokens(tokens);
struct TMPL_tagnode* ast = parse(tokens,ret->errout);
+ size_t dummy;
+ printf("errbuf:%s\n",bstringify(ret->errout,&dummy));
+ printf("After parsing, syntax tree is:\n");
if(ast == NULL){
//size_t dummy;
//printf("error: %s\n",bstringify(ret->errout,&dummy));
}else{
ret->roottag = ast;
}
+ print_ast(ret);
return ret;
}
-
int
render_variable(struct TMPL_templates* t, struct TMPL_tagnode* node, struct TMPL_varlist* varlist){
struct TMPL_varitem* vi;
@@ -1021,7 +1212,6 @@ print_varlist_helper(struct TMPL_varlist* vl, int indent){
hashmap_iterate(vl->map, print_pair,&indent);
}
-
void
print_varlist(struct TMPL_varlist* vl){
print_varlist_helper(vl,0);
@@ -1080,6 +1270,28 @@ resolve_name(struct TMPL_varlist* varlist, char* name,struct TMPL_varitem** item
}
int
+render_break(struct TMPL_templates* t, struct TMPL_tagnode* node, struct TMPL_varlist* varlist){
+ printf("Rendering break\n");
+ printf("node is:%p\n",(void*)node);
+ printf("node->next:%p\n",(void*)node->TMPL_tag.breakcont.into->next);
+ printf("varlist->parent:%p\n",(void*)varlist->parent);
+ printf("varlist->parent->parent:%p\n",(void*)varlist->parent->parent);
+ printf("node into:%p\n",(void*)node->TMPL_tag.breakcont.into);
+ printf("node into->next:%p\n",(void*)node->TMPL_tag.breakcont.into->next);
+ /*struct TMPL_templates* nt = (struct TMPL_templates)malloc(sizeof(struct TMPL_templates));*/
+ /*nt->out = t->out;*/
+ /*nt->errout = t->errout;*/
+ /*nt->roottag = node->TMPL_tag.breakcont.*/
+ return render_any(t,node->TMPL_tag.breakcont.into->next,varlist->parent->parent);
+}
+
+int
+render_continue(struct TMPL_templates* t, struct TMPL_tagnode* node, struct TMPL_varlist* varlist){
+ printf("Rendering continue\n");
+ return render_any(t,node->next,varlist->parent->next->varlist);
+}
+
+int
render_loop(struct TMPL_templates* t, struct TMPL_tagnode* node, struct TMPL_varlist* varlist){
char* loopname = node->TMPL_tag.loop.loopname;
struct TMPL_varitem* loop;
@@ -1132,7 +1344,11 @@ render_any(struct TMPL_templates* t, struct TMPL_tagnode* node, struct TMPL_varl
if(err < 0){
}
break;
+ case tag_break:
+ err = render_break(t,node,varlist);
+ break;
default:
+ printf("Failed to find node type: %d\n",node->type);
exit(-1);
break;
}
@@ -1141,6 +1357,7 @@ render_any(struct TMPL_templates* t, struct TMPL_tagnode* node, struct TMPL_varl
void
TMPL_render_helper(struct TMPL_templates* t, struct TMPL_varlist* varlist){
+ printf("Render helper\n");
struct TMPL_tagnode* cursor = t->roottag;
while(cursor != NULL){
render_any(t,cursor,varlist);