From: Ton v. O. <tvo...@us...> - 2006-10-04 00:39:26
|
Update of /cvsroot/easycalc/easycalc/mlib In directory sc8-pr-cvs5.sourceforge.net:/tmp/cvs-serv8755/mlib Modified Files: funcs.c konvert.c Log Message: Introduce lazy evaluation of the 'if' statement. This makes recursive function definitions possible. Introduce check against stack overflow. Increase stack from the default 4K to 8K for PalmOS >= 3.0. Index: konvert.c =================================================================== RCS file: /cvsroot/easycalc/easycalc/mlib/konvert.c,v retrieving revision 1.66 retrieving revision 1.67 diff -C2 -d -r1.66 -r1.67 *** konvert.c 1 Oct 2006 22:43:36 -0000 1.66 --- konvert.c 4 Oct 2006 00:39:17 -0000 1.67 *************** *** 562,565 **** --- 562,635 ---- } + static Int16 handleIfArguments(char *buf, Int16 priority, CError *err) PARSER; + static Int16 + handleIfArguments(char *buf, Int16 priority, CError *err) + { + Char *ptr; + Int16 prmcnt1 = 1; + Int16 level = 0; + Int16 count = 0; + Int16 i; + Char lastchar; + UInt16 len; + Tmeq item; + Char *text; + static Char sepchar[2] = { ':', ')' }; + + /* We compile the condition argument as ususal. The true and false + * false arguments are stored as strings. They are compiled and + * executed later in func_if(). This allows 'lazy evaluation' of + * the if statement and recursion. + * Now it is possible to define recursive functions, e.g. the factorial + * can be defined as: mf()="if(x>1:mf(x-1)*x:1)". + * Of course we need a check against stack overflow now. See file + * chkstack.c */ + + for (ptr = buf; *ptr && (*ptr != ':' || level > 0); ptr++, count++) { + if (*ptr == '(') level++; + if (*ptr == ')' && level > 0) level--; + } + /* Now we have the condition argument, process it as normal */ + lastchar = *ptr; *ptr = '\0'; + if (!konvert_to_meq(buf, priority, &prmcnt1, ')', err)) + return 0; + *ptr = lastchar; + if (*ptr) + ptr++; count++; + + for (i = 0; i < 2; i++) { + /* Isolate the true (i=0) or false (i=1) argument */ + for (buf = ptr; *ptr && (*ptr != sepchar[i] || level > 0); + ptr++, count++) { + if (*ptr == '(') level++; + if (*ptr == ')' && level > 0) level--; + } + /* Push the true/false argument on the meq stack as a string */ + lastchar = *ptr; *ptr = '\0'; + len = StrLen(buf); + if (!len) { + *err = c_syntax; + return 0; + } + text = MemPtrNew(len + 1); + if (!text) { + *err = c_memory; + return 0; + } + StrCopy(text, buf); + text[len] = '\0'; + item.priority = priority; + item.rpn.type = string; + item.rpn.u.stringval = text; + item.rpn.allocsize = len + 1; + meq_push(meqstack, item); + *ptr = lastchar; + if (lastchar) + ptr++; count++; + } + + return count; + } + static Int16 try_func(char *buf,Int16 priority,CError *err) *************** *** 607,611 **** prmcnt1 = item.rpn.u.funcval.paramcount; i = meq_push(meqstack,item); ! if (!(tmp=konvert_to_meq(buf,priority+1, &prmcnt1,')',err))) return 0; --- 677,685 ---- prmcnt1 = item.rpn.u.funcval.paramcount; i = meq_push(meqstack,item); ! if (StrCompare("if", fname) == 0) { ! if (!(tmp = handleIfArguments(buf, priority + 1, err))) ! return 0; ! } ! else if (!(tmp=konvert_to_meq(buf,priority+1, &prmcnt1,')',err))) return 0; *************** *** 779,783 **** Int16 tmp; Int16 length=0; ! Int16 param_encountred = 1; Int16 (*try_num)(char *,Int16,CError *); Tmeq item; --- 853,857 ---- Int16 tmp; Int16 length=0; ! Int16 param_encountered = 1; Int16 (*try_num)(char *,Int16,CError *); Tmeq item; *************** *** 865,870 **** length++; if (*param_count == 0) ! *param_count = param_encountred; ! else if (param_encountred != *param_count) return 0; /* Bad parameter count */ return length; --- 939,944 ---- length++; if (*param_count == 0) ! *param_count = param_encountered; ! else if (param_encountered != *param_count) return 0; /* Bad parameter count */ return length; *************** *** 879,883 **** /* Next parameter */ else if (*buf==':') { ! param_encountred++; buf++; length++; --- 953,957 ---- /* Next parameter */ else if (*buf==':') { ! param_encountered++; buf++; length++; Index: funcs.c =================================================================== RCS file: /cvsroot/easycalc/easycalc/mlib/funcs.c,v retrieving revision 1.50 retrieving revision 1.51 diff -C2 -d -r1.50 -r1.51 *** funcs.c 22 Sep 2006 15:06:33 -0000 1.50 --- funcs.c 4 Oct 2006 00:39:17 -0000 1.51 *************** *** 658,662 **** { CError err; ! Trpn argtrue, argfalse; UInt32 value; --- 658,662 ---- { CError err; ! Trpn arg, argtrue, argfalse; UInt32 value; *************** *** 670,679 **** } if (value) { - stack_push(stack,argtrue); rpn_delete(argfalse); } else { - stack_push(stack,argfalse); rpn_delete(argtrue); } return c_noerror; } --- 670,692 ---- } if (value) { rpn_delete(argfalse); + arg = argtrue; } else { rpn_delete(argtrue); + arg = argfalse; } + if (arg.type == string) { + CodeStack *tmp = text_to_stack(arg.u.stringval,&err); + rpn_delete(arg); + if (!err) + err = stack_compute(tmp); + if (!err) + arg=stack_pop(tmp); + if (tmp) + stack_delete(tmp); + if (err) + return err; + } + stack_push(stack,arg); return c_noerror; } |