/// Do the first for part. void tag_for(parser_status *st, list *l){ function_add_code(st, " {\n" " onion_dict *loopdict=onion_dict_get_dict(context, \"%s\");\n", tag_value_arg (l,3)); function_add_code(st, " onion_dict *tmpcontext=onion_dict_hard_dup(context);\n" " if (loopdict){\n" " dict_res dr={ .dict = tmpcontext, .res=res };\n" " onion_dict_preorder(loopdict, "); function_data *d=function_new(st, NULL); d->signature="dict_res *dr, const char *key, const void *value, int flags"; function_add_code(st, " onion_dict_add(dr->dict, \"%s\", value, OD_DUP_VALUE|OD_REPLACE|(flags&OD_TYPE_MASK));\n", tag_value_arg(l,1)); function_new(st, NULL); }
/// Include an external html. This is only the call, the programmer must compile such html too. void tag_include(parser_status* st, list* l){ function_data *d=function_new(st, "%s", tag_value_arg(l, 1)); function_pop(st); onion_block_free(d->code); // This means no impl d->code=NULL; function_add_code(st, " %s(context, res);\n", d->id); }
void tag_extends(parser_status *st, list *l){ function_data *d=function_new(st, "%s", tag_value_arg(l, 1)); function_pop(st); onion_block_free(d->code); d->code=NULL; function_add_code(st, " %s(context, res);", d->id); d=(function_data*)st->function_stack->tail->data; d->flags|=F_NO_MORE_WRITE; }
static void process_args(char *name) { struct function *func; struct symbol *arg; /*(*/ consume_token(); func = function_table_lookup(name); /* Delete an old function and make a new one */ if (func != NULL) function_table_delete_function(name); func = function_new(name); while (!match(TOKEN_RPARENTH)) { if (match(TOKEN_EOL)) { error_msg("error: new line in function definition"); return; } if (!match(TOKEN_ID)) { error_msg("error: unexpected symbol in definition"); sync_stream(); ufree(func); return; } arg = symbol_new(lex_prev.id, VALUE_TYPE_UNKNOWN); function_add_arg(func, arg); if (current_token != TOKEN_RPARENTH && !match(TOKEN_COMMA)) { error_msg("error: comma expected"); sync_stream(); return; } } switch(current_token) { case TOKEN_LBRACE: function_table_insert(func); process_function_body(name); break; default: error_msg("error: `{' expected"); sync_stream(); break; } }
static gpointer function_dup(gconstpointer data) { const function_t *org = data; function_t *stfuncrec; GSList *p; stfuncrec = function_new(org->funcdef); for (p = org->params; p; p = p->next) { const stnode_t *param = p->data; stfuncrec->params = g_slist_append(stfuncrec->params, stnode_dup(param)); } return (gpointer) stfuncrec; }
void tag_block(parser_status *st, list *l){ const char *block_name=tag_value_arg(l, 1); function_add_code(st, " {\n" " void (*f)(onion_dict *context, onion_response *res);\n" " f=(void*)onion_dict_get(context, \"__block_%s__\");\n" " if (f)\n" " f(context, res);\n" " }\n", block_name); char tmp[256]; strncpy(tmp, st->infilename, sizeof(tmp)); function_data *d=function_new(st, "%s__block_%s", basename(tmp), block_name); function_add_code_f(st->blocks_init, " if (!onion_dict_get(context, \"__block_%s__\"))\n" " onion_dict_add(context, \"__block_%s__\", %s, 0);\n", block_name, block_name, d->id); }
/// Starts an if void tag_if(parser_status *st, list *l){ int lc=list_count(l); if (lc==2){ function_add_code(st, " {\n" " const char *tmp;\n" ); variable_solve(st, tag_value_arg(l, 1), "tmp", tag_type_arg(l,1)); function_add_code(st, " if (tmp && strcmp(tmp, \"false\")!=0)\n", tag_value_arg(l,1)); } else if (lc==4){ const char *op=tag_value_arg(l, 2); const char *opcmp=NULL; if (strcmp(op,"==")==0) opcmp="==0"; else if (strcmp(op,"<=")==0) opcmp="<=0"; else if (strcmp(op,"<")==0) opcmp="<0"; else if (strcmp(op,">=")==0) opcmp=">=0"; else if (strcmp(op,">")==0) opcmp=">0"; else if (strcmp(op,"!=")==0) opcmp="!=0"; if (opcmp){ function_add_code(st, " {\n" " const char *op1, *op2;\n"); variable_solve(st, tag_value_arg(l, 1), "op1", tag_type_arg(l,1)); variable_solve(st, tag_value_arg(l, 3), "op2", tag_type_arg(l,3)); function_add_code(st, " if (op1==op2 || (op1 && op2 && strcmp(op1, op2)%s))\n",opcmp); } else{ ONION_ERROR("%s:%d Unkonwn operator for if: %s", st->infilename, st->line, op); st->status=1; } } else{ ONION_ERROR("%s:%d If only allows 1 or 3 arguments. TODO. Has %d.", st->infilename, st->line, lc-1); st->status=1; } function_new(st, NULL); }
int test_function_new_and_destroy(void) { f = function_new(DEFAULT, 0, 2); mu_check(f->type == DEFAULT); mu_check(f->function == 0); mu_check(f->arity == 2); function_destroy(f); /* default function */ f = function_new_func(0, 2); mu_check(f->type == DEFAULT); mu_check(f->function == 0); mu_check(f->arity == 2); function_destroy(f); /* classification function */ f = function_new_cfunc(0, 2); mu_check(f->type == CLASSIFICATION); mu_check(f->function == 0); mu_check(f->arity == 2); function_destroy(f); return 0; }
/// Else part void tag_else(parser_status *st, list *l){ function_data *d=function_pop(st); function_add_code(st, " %s(context, res);\n else\n", d->id); function_new(st, NULL); }
// Parses a function definition struct function *parse_function(struct lexer_state *lexer) { int error = 0; int i = 0; struct function *function = NULL; // First getting the identifier lex(lexer); if(lexer->error == UNRECOGNIZED_TOKEN) { print_error(lexer, LEX_ERROR); return NULL; } if(lexer->error == END_OF_INPUT) { print_error(lexer, UNEXPECTED_END); return NULL; } if(lexer->type != IDENT) { print_error(lexer, EXPECTED_IDENT); return NULL; } // Storing the identifier function = function_new(); function->name = strdup(lexer->value.sval); // Figuring out what type of function this is function->type = USER; // Until proven otherwise // Checking against primitive and form lists for(i = 0; *(PRIMITIVE_FUNCTION_NAMES[i]); i++) { if(!strcmp(PRIMITIVE_FUNCTION_NAMES[i], function->name)) { function->type = PRIMITIVE; function->index = i; } } for(i = 0; *(FUNCTIONAL_FORM_NAMES[i]); i++) { if(!strcmp(FUNCTIONAL_FORM_NAMES[i], function->name)) { function->type = FORM; function->index = i; } } // Now checking for possible arguments if(function->type == PRIMITIVE) { lex(lexer); if(lexer->error == UNRECOGNIZED_TOKEN) { print_error(lexer, LEX_ERROR); function_delete(function); return NULL; } // Now checking for opening paren if(lexer->error == OK && lexer->type == OPEN_SPEC) { function->args = parse_constant_args(lexer, CLOSE_SPEC); if(!function->args) { function_delete(function); return NULL; } } else { lexer_rewind(lexer); } } else if(function->type == FORM) { // A functional form requires arguments if(!require_token(lexer, OPEN_FORM)) { print_error(lexer, EXPECTED_ARGS); function_delete(function); return NULL; } function->args = parse_function_args(lexer); if(!function->args) { function_delete(function); return NULL; } } return function; }
/** * @short Compiles the infilename to outfilename. */ int work(const char *infilename, const char *outfilename, onion_assets_file *assets){ tag_init(); parser_status status; memset(&status, 0, sizeof(status)); status.mode=TEXT; status.functions=list_new((void*)function_free); status.function_stack=list_new(NULL); status.status=0; status.line=1; status.rawblock=onion_block_new(); status.infilename=infilename; char tmp2[256]; strncpy(tmp2, infilename, sizeof(tmp2)-1); const char *tname=basename(tmp2); ONION_DEBUG("Create init function on top, tname %s",tname); status.blocks_init=function_new(&status, "%s_blocks_init", tname); status.blocks_init->signature="onion_dict *context"; if (strcmp(infilename, "-")==0) status.in=stdin; else status.in=fopen(infilename,"rt"); if (!status.in){ ONION_ERROR("Could not open in file %s", infilename); goto work_end; } ONION_DEBUG("Create main function on top, tname %s",tname); function_new(&status, tname); function_add_code(&status, " int has_context=(context!=NULL);\n" " if (!has_context)\n" " context=onion_dict_new();\n" " \n" " %s(context);\n", status.blocks_init->id); parse_template(&status); ((function_data*)status.function_stack->tail->data)->flags=0; function_add_code(&status, " if (!has_context)\n" " onion_dict_free(context);\n" ); if (status.status){ ONION_ERROR("Parsing error"); goto work_end; } if (strcmp(outfilename, "-")==0) status.out=stdout; else status.out=fopen(outfilename,"wt"); if (!status.out){ ONION_ERROR("Could not open out file %s", infilename); goto work_end; } fprintf(status.out, "/** Autogenerated by otemplate v. 0.2.0 */\n" "\n" "#include <libintl.h>\n" "#include <string.h>\n\n" "#include <onion/onion.h>\n" "#include <onion/dict.h>\n" "\n" "typedef struct dict_res_t{\n" " onion_dict *dict;\n" " onion_response *res;\n" "}dict_res;\n" "\n" "\n"); functions_write_declarations_assets(&status, assets); functions_write_declarations(&status); functions_write_main_code(&status); if (use_orig_line_numbers) fprintf(status.out, "#line 1 \"%s\"\n", infilename); functions_write_code(&status); work_end: if (status.in) fclose(status.in); if (status.out) fclose(status.out); list_free(status.functions); list_free(status.function_stack); //list_free(status.blocks); onion_block_free(status.rawblock); tag_free(); return status.status; }
static int place_function (xmlDocPtr doc, xmlNodePtr node, sectlist *s) { xmlNodePtr n1, n2; function *fun, **funs = NULL; char *sname, *fname, *atype, *retval; int matrix_ok = 0; int gotargs = 0; int nc, n = -1; int i, err = 0; sname = (char *) xmlGetProp(node, (UTF) "section"); fname = (char *) xmlGetProp(node, (UTF) "name"); retval = (char *) xmlGetProp(node, (UTF) "output"); if (!function_in_gretl(fname)) { fprintf(stderr, "*** '%s': obsolete function, skipping\n", fname); goto bailout; } if (sname == NULL || fname == NULL || retval == NULL) { fprintf(stderr, "Error parsing function\n"); return 1; } if (matrix_return(retval)) { matrix_ok = 1; } else { n1 = node->xmlChildrenNode; while (n1 != NULL && !err && !gotargs) { if (!xmlStrcmp(n1->name, (UTF) "fnargs")) { gotargs = 1; n2 = n1->xmlChildrenNode; while (n2 != NULL && !err && !matrix_ok) { if (!xmlStrcmp(n2->name, (UTF) "fnarg")) { atype = (char *) xmlGetProp(n2, (UTF) "type"); if (ok_matrix_arg(atype)) { matrix_ok = 1; } free(atype); } n2 = n2->next; } } n1 = n1->next; } } if (!matrix_ok) { goto bailout; } for (i=0; i<s->nsects; i++) { if (!strcmp(sname, s->sections[i]->name)) { n = i; break; } } if (n < 0) { /* assume this function is not wanted, in context */ goto bailout; } fun = function_new(fname, matrix_ok); if (fun == NULL) { fprintf(stderr, "Out of memory\n"); return 1; } nc = s->sections[n]->nfuns + 1; funs = realloc(s->sections[n]->funs, nc * sizeof *funs); if (funs == NULL) { fprintf(stderr, "Out of memory\n"); return 1; } s->sections[n]->funs = funs; s->sections[n]->funs[nc-1] = fun; s->sections[n]->nfuns = nc; #if VERBOSE fprintf(stderr, "Added function '%s' to section '%s'\n", fname, sname); #endif bailout: free(fname); free(sname); return err; }