"Fossies" - the Fresh Open Source Software Archive

Member "teapot-2.3.0/func.c" (6 Feb 2012, 34212 Bytes) of package /linux/privat/old/teapot-2.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "func.c" see the Fossies "Dox" file reference documentation.

A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.


    1 /* #includes */ /*{{{C}}}*//*{{{*/
    2 #ifndef NO_POSIX_SOURCE
    3 #undef _POSIX_SOURCE
    4 #define _POSIX_SOURCE   1
    5 #undef _POSIX_C_SOURCE
    6 #define _POSIX_C_SOURCE 2
    7 #endif
    8 
    9 #define _XOPEN_SOURCE /* glibc2 needs this */
   10 
   11 #ifdef DMALLOC
   12 #include "dmalloc.h"
   13 #endif
   14 
   15 #include <assert.h>
   16 #include <errno.h>
   17 #include <limits.h>
   18 #include <math.h>
   19 #include <stdlib.h>
   20 extern double strtod(const char *nptr, char **endptr); /* SunOS 4 hack */
   21 #include <stdio.h>
   22 #include <string.h>
   23 #include <time.h>
   24 
   25 
   26 #include "default.h"
   27 #include "eval.h"
   28 #include "func.h"
   29 #include "main.h"
   30 #include "misc.h"
   31 #include "parser.h"
   32 #include "scanner.h"
   33 #include "sheet.h"
   34 /*}}}*/
   35 /* #defines */ /*{{{*/
   36 /* There is a BSD extensions, but they are possibly more exact. */
   37 #ifdef M_E
   38 #define CONST_E M_E
   39 #else
   40 #define CONST_E ((double)2.7182818284590452354)
   41 #endif
   42 #ifdef M_PI
   43 #define CONST_PI M_PI
   44 #else
   45 #define CONST_PI ((double)3.14159265358979323846)
   46 #endif
   47 /*}}}*/
   48 
   49 #ifdef WIN32
   50 // This strptime implementation Copyright 2009 Google Inc.
   51 //
   52 // Licensed under the Apache License, Version 2.0 (the "License");
   53 // you may not use this file except in compliance with the License.
   54 // You may obtain a copy of the License at
   55 //
   56 //      http://www.apache.org/licenses/LICENSE-2.0
   57 //
   58 // Unless required by applicable law or agreed to in writing, software
   59 // distributed under the License is distributed on an "AS IS" BASIS,
   60 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   61 // See the License for the specific language governing permissions and
   62 // limitations under the License.
   63 
   64 // Implement strptime under windows
   65 static const char* kWeekFull[] = {
   66     "Sunday", "Monday", "Tuesday", "Wednesday",
   67     "Thursday", "Friday", "Saturday"
   68 };
   69 
   70 static const char* kWeekAbbr[] = {
   71     "Sun", "Mon", "Tue", "Wed",
   72     "Thu", "Fri", "Sat"
   73 };
   74 
   75 static const char* kMonthFull[] = {
   76     "January", "February", "March", "April", "May", "June",
   77     "July", "August", "September", "October", "November", "December"
   78 };
   79 
   80 static const char* kMonthAbbr[] = {
   81     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
   82     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
   83 };
   84 
   85 static const char* _parse_num(const char* s, int low, int high, int* value) {
   86     const char* p = s;
   87     for (*value = 0; *p && isdigit(*p); ++p) {
   88         *value = (*value) * 10 + *p - '0';
   89     }
   90 
   91     if (p == s || *value < low || *value > high) return NULL;
   92     return p;
   93 }
   94 
   95 static char* _strptime(const char *s, const char *format, struct tm *tm) {
   96     int i, len;
   97     while (*format && *s) {
   98         if (*format != '%') {
   99             if (*s != *format) return NULL;
  100 
  101             ++format;
  102             ++s;
  103             continue;
  104         }
  105 
  106         ++format;
  107         len = 0;
  108         switch (*format) {
  109         // weekday name.
  110         case 'a':
  111         case 'A':
  112             tm->tm_wday = -1;
  113             for (i = 0; i < 7; ++i) {
  114                 len = strlen(kWeekAbbr[i]);
  115                 if (strnicmp(kWeekAbbr[i], s, len) == 0) {
  116                     tm->tm_wday = i;
  117                     break;
  118                 }
  119 
  120                 len = strlen(kWeekFull[i]);
  121                 if (strnicmp(kWeekFull[i], s, len) == 0) {
  122                     tm->tm_wday = i;
  123                     break;
  124                 }
  125             }
  126             if (tm->tm_wday == -1) return NULL;
  127             s += len;
  128             break;
  129 
  130         // month name.
  131         case 'b':
  132         case 'B':
  133         case 'h':
  134             tm->tm_mon = -1;
  135             for (i = 0; i < 12; ++i) {
  136                 len = strlen(kMonthAbbr[i]);
  137                 if (strnicmp(kMonthAbbr[i], s, len) == 0) {
  138                     tm->tm_mon = i;
  139                     break;
  140                 }
  141 
  142                 len = strlen(kMonthFull[i]);
  143                 if (strnicmp(kMonthFull[i], s, len) == 0) {
  144                     tm->tm_mon = i;
  145                     break;
  146                 }
  147             }
  148             if (tm->tm_mon == -1) return NULL;
  149             s += len;
  150             break;
  151 
  152         // month [1, 12].
  153         case 'm':
  154             s = _parse_num(s, 1, 12, &tm->tm_mon);
  155             if (s == NULL) return NULL;
  156             --tm->tm_mon;
  157             break;
  158 
  159         // day [1, 31].
  160         case 'd':
  161         case 'e':
  162             s = _parse_num(s, 1, 31, &tm->tm_mday);
  163             if (s == NULL) return NULL;
  164             break;
  165 
  166         // hour [0, 23].
  167         case 'H':
  168             s = _parse_num(s, 0, 23, &tm->tm_hour);
  169             if (s == NULL) return NULL;
  170             break;
  171 
  172         // minute [0, 59]
  173         case 'M':
  174             s = _parse_num(s, 0, 59, &tm->tm_min);
  175             if (s == NULL) return NULL;
  176             break;
  177 
  178         // seconds [0, 60]. 60 is for leap year.
  179         case 'S':
  180             s = _parse_num(s, 0, 60, &tm->tm_sec);
  181             if (s == NULL) return NULL;
  182             break;
  183 
  184         // year [1900, 9999].
  185         case 'Y':
  186             s = _parse_num(s, 1900, 9999, &tm->tm_year);
  187             if (s == NULL) return NULL;
  188             tm->tm_year -= 1900;
  189             break;
  190 
  191         // year [0, 99].
  192         case 'y':
  193             s = _parse_num(s, 0, 99, &tm->tm_year);
  194             if (s == NULL) return NULL;
  195             if (tm->tm_year <= 68) {
  196                 tm->tm_year += 100;
  197             }
  198             break;
  199 
  200         // arbitray whitespace.
  201         case 't':
  202         case 'n':
  203             while (isspace(*s)) ++s;
  204             break;
  205 
  206         // '%'.
  207         case '%':
  208             if (*s != '%') return NULL;
  209             ++s;
  210             break;
  211 
  212         // All the other format are not supported.
  213         default:
  214             return NULL;
  215         }
  216         ++format;
  217     }
  218 
  219     if (*format) {
  220         return NULL;
  221     } else {
  222         return (char *)s;
  223     }
  224 }
  225 
  226 char* strptime(const char *buf, const char *fmt, struct tm *tm) {
  227     return _strptime(buf, fmt, tm);
  228 }
  229 #endif
  230 
  231 /* sci_func -- map a double to a double */ /*{{{*/
  232 static Token sci_func(int argc, const Token argv[], double (*func)(double), const char *func_name)
  233 {
  234   Token result;
  235 
  236   if (argc==1 && argv[0].type==FLOAT)
  237   {
  238     result.type=FLOAT;
  239     errno=0;
  240     result.u.flt=(func)(argv[0].u.flt);
  241     if (errno)
  242     {
  243       result.type=EEK;
  244       result.u.err=malloc(strlen(func_name)+2+strlen(strerror(errno))+1);
  245       sprintf(result.u.err,"%s: %s",func_name,strerror(errno));
  246     }
  247   }
  248   else
  249   {
  250     if (argc==1 && argv[0].type==INT)
  251     {
  252       result.type=FLOAT;
  253       errno=0;
  254       result.u.flt=(func)((double)argv[0].u.integer);
  255       if (errno)
  256       {
  257         result.type=EEK;
  258         result.u.err=malloc(strlen(func_name)+2+strlen(strerror(errno))+1);
  259         sprintf(result.u.err,"%s: %s",func_name,strerror(errno));
  260       }
  261     }
  262     else    
  263     {
  264       result.type=EEK;
  265       /* This is actually too much, but always enough for %s formats. */
  266       result.u.err=malloc(strlen(_("Usage: %s(float)"))+strlen(func_name)+1);
  267       sprintf(result.u.err,_("Usage: %s(float)"),func_name);
  268     }
  269   }
  270   return result;
  271 }
  272 /*}}}*/
  273 /* arsinh */ /*{{{*/
  274 static double arsinh(double x)
  275 {
  276   return log(x+sqrt(x*x+1.0));
  277 }
  278 /*}}}*/
  279 /* arcosh */ /*{{{*/
  280 static double arcosh(double x)
  281 {
  282   if (x>=1.0) return log(x+sqrt(x*x-1.0));
  283   else { errno=EDOM; return 0.0; }
  284 }
  285 /*}}}*/
  286 /* artanh */ /*{{{*/
  287 static double artanh(double x)
  288 {
  289   if (x>-1.0 && x<1.0) return 0.5*log((1.0+x)/(1.0-x));
  290   else { errno=EDOM; return 0.0; }
  291 }
  292 /*}}}*/
  293 /* rad2deg */ /*{{{*/
  294 static double rad2deg(double x)
  295 {
  296   return (360.0/(2.0*CONST_PI))*x;
  297 }
  298 /*}}}*/
  299 /* deg2rad */ /*{{{*/
  300 static double deg2rad(double x)
  301 {
  302   return (2.0*CONST_PI/360.0)*x;
  303 }
  304 /*}}}*/
  305 
  306 /* @ */ /*{{{*/
  307 static Token at_func(int argc, const Token argv[])
  308 {
  309   /* variables */ /*{{{*/
  310   Token result;
  311   /*}}}*/
  312 
  313   /* asserts */ /*{{{*/
  314   assert(argv!=(Token*)0);
  315   /*}}}*/
  316   if (argc==0)
  317   /* return value at current location */ /*{{{*/
  318   return (getvalue(upd_sheet,upd_x,upd_y,upd_z));
  319   /*}}}*/
  320   if (argc==1 && argv[0].type==LOCATION)
  321   /* return value at location pointed to by argument */ /*{{{*/
  322   return (getvalue(upd_sheet,argv[0].u.location[0],argv[0].u.location[1],argv[0].u.location[2]));
  323   /*}}}*/
  324   else if (argc==1 && (argv[0].type==INT || argv[0].type==EMPTY))
  325   /* return value at x on current y,z */ /*{{{*/
  326   return (getvalue(upd_sheet,argv[0].type==INT ? argv[0].u.integer : upd_x,upd_y,upd_z));
  327   /*}}}*/
  328   else if (argc==2 && (argv[0].type==INT || argv[0].type==EMPTY) && (argv[1].type==INT || argv[1].type==EMPTY))
  329   /* return value at x,y on current z */ /*{{{*/
  330   return (getvalue(upd_sheet,argv[0].type==INT ? argv[0].u.integer : upd_x,argv[1].type==INT ? argv[1].u.integer : upd_y,upd_z));
  331   /*}}}*/
  332   else if (argc==3 && (argv[0].type==INT || argv[0].type==EMPTY) && (argv[1].type==INT || argv[1].type==EMPTY) && (argv[2].type==INT || argv[2].type==EMPTY))
  333   /* return value at x,y,z */ /*{{{*/
  334   return (getvalue(upd_sheet,argv[0].type==INT ? argv[0].u.integer : upd_x,argv[1].type==INT ? argv[1].u.integer : upd_y,argv[2].type==INT ? argv[2].u.integer : upd_z));  
  335   /*}}}*/
  336   else
  337   /* return error */ /*{{{*/
  338   {
  339     result.type=EEK;
  340     result.u.err=strcpy(malloc(strlen(_("Usage: @([integer x][,[integer y][,[integer z]]]) or @(location)"))+1),_("Usage: @([integer x][,[integer y][,[integer z]]]) or @(location)"));
  341     return result;
  342   }
  343   /*}}}*/
  344 }
  345 /*}}}*/
  346 /* & */ /*{{{*/
  347 static Token adr_func(int argc, const Token argv[])
  348 {
  349   /* variables */ /*{{{*/
  350   Token result;
  351   /*}}}*/
  352 
  353   /* asserts */ /*{{{*/
  354   assert(argv!=(Token*)0);
  355   /*}}}*/
  356   if (argc==3 && (argv[0].type==INT || argv[0].type==EMPTY) && (argv[1].type==INT || argv[1].type==EMPTY) && (argv[2].type==INT || argv[2].type==EMPTY))
  357   /* result is location of the given position */ /*{{{*/
  358   {
  359     result.type=LOCATION;
  360     result.u.location[0]=(argv[0].type==INT ? argv[0].u.integer : upd_x);
  361     result.u.location[1]=(argv[1].type==INT ? argv[1].u.integer : upd_y);
  362     result.u.location[2]=(argv[2].type==INT ? argv[2].u.integer : upd_z);
  363   }
  364   /*}}}*/
  365   else if (argc==2 && (argv[0].type==INT || argv[0].type==EMPTY) && (argv[1].type==INT || argv[1].type==EMPTY))
  366   /* result is location of the given position in the current z layer */ /*{{{*/
  367   {
  368     result.type=LOCATION;
  369     result.u.location[0]=(argv[0].type==INT ? argv[0].u.integer : upd_x);
  370     result.u.location[1]=(argv[1].type==INT ? argv[1].u.integer : upd_y);
  371     result.u.location[2]=upd_z;
  372   }
  373   /*}}}*/
  374   else if (argc==1 && (argv[0].type==INT || argv[0].type==EMPTY))
  375   /* result is location of the given position in the current y,z layer */ /*{{{*/
  376   {
  377     result.type=LOCATION;
  378     result.u.location[0]=(argv[0].type==INT ? argv[0].u.integer : upd_x);
  379     result.u.location[1]=upd_y;
  380     result.u.location[2]=upd_z;
  381   }
  382   /*}}}*/
  383   else if (argc==0)
  384   /* result is location of the current position */ /*{{{*/
  385   {
  386     result.type=LOCATION;
  387     result.u.location[0]=upd_x;
  388     result.u.location[1]=upd_y;
  389     result.u.location[2]=upd_z;
  390   }
  391   /*}}}*/
  392   else
  393   /* result is type error */ /*{{{*/
  394   {
  395     result.type=EEK;
  396     result.u.err=strcpy(malloc(strlen(_("Usage: &([integer x][,[integer y][,[integer z]]])"))+1),_("Usage: &([integer x][,[integer y][,[integer z]]])"));
  397   }
  398   /*}}}*/
  399   return result;
  400 }
  401 /*}}}*/
  402 /* x */ /*{{{*/
  403 static Token x_func(int argc, const Token argv[])
  404 {
  405   /* variables */ /*{{{*/
  406   Token result;
  407   /*}}}*/
  408 
  409   if (argc==0)
  410   /* result is currently updated x position */ /*{{{*/
  411   {
  412     result.type=INT;
  413     result.u.integer=upd_x;
  414   }
  415   /*}}}*/
  416   else if (argc==1 && argv[0].type==LOCATION)
  417   /* return x component of location */ /*{{{*/
  418   {
  419     result.type=INT;
  420     result.u.integer=argv[0].u.location[0];
  421   }
  422   /*}}}*/
  423   else
  424   /* x type error */ /*{{{*/
  425   {
  426     result.type=EEK;
  427     result.u.err=strcpy(malloc(strlen(_("Usage: x([location])"))+1),_("Usage: x([location])"));
  428   }
  429   /*}}}*/
  430   return result;
  431 }
  432 /*}}}*/
  433 /* y */ /*{{{*/
  434 static Token y_func(int argc, const Token argv[])
  435 {
  436   /* variables */ /*{{{*/
  437   Token result;
  438   /*}}}*/
  439 
  440   if (argc==0)
  441   /* result is currently updated y position */ /*{{{*/
  442   {
  443     result.type=INT;
  444     result.u.integer=upd_y;
  445   }
  446   /*}}}*/
  447   else if (argc==1 && argv[0].type==LOCATION)
  448   /* return y component of location */ /*{{{*/
  449   {
  450     result.type=INT;
  451     result.u.integer=argv[0].u.location[1];
  452   }
  453   /*}}}*/
  454   else
  455   /* y type error */ /*{{{*/
  456   {
  457     result.type=EEK;
  458     result.u.err=strcpy(malloc(strlen(_("Usage: y([location])"))+1),_("Usage: y([location])"));
  459   }
  460   /*}}}*/
  461   return result;
  462 }
  463 /*}}}*/
  464 /* z */ /*{{{*/
  465 static Token z_func(int argc, const Token argv[])
  466 {
  467   /* variables */ /*{{{*/
  468   Token result;
  469   /*}}}*/
  470 
  471   if (argc==0)
  472   /* result is currently updated z position */ /*{{{*/
  473   {
  474     result.type=INT;
  475     result.u.integer=upd_z;
  476   }
  477   /*}}}*/
  478   else if (argc==1 && argv[0].type==LOCATION)
  479   /* return z component of location */ /*{{{*/
  480   {
  481     result.type=INT;
  482     result.u.integer=argv[0].u.location[2];
  483   }
  484   /*}}}*/
  485   else
  486   /* result is z type error */ /*{{{*/
  487   {
  488     result.type=EEK;
  489     result.u.err=mystrmalloc(_("Usage: z([location])"));
  490   }
  491   /*}}}*/
  492   return result;
  493 }
  494 /*}}}*/
  495 /* e */ /*{{{*/
  496 static Token e_func(int argc, const Token argv[])
  497 {
  498   /* variables */ /*{{{*/
  499   Token result;
  500   /*}}}*/
  501 
  502   if (argc==0) /* result is constant e */ /*{{{*/
  503   {
  504     result.type=FLOAT;
  505     result.u.flt=CONST_E;
  506   }
  507   /*}}}*/
  508   else /* result is e type error */ /*{{{*/
  509   {
  510     result.type=EEK;
  511     result.u.err=mystrmalloc(_("Usage: e()"));
  512   }
  513   /*}}}*/
  514   return result;
  515 }
  516 /*}}}*/
  517 /* eval */ /*{{{*/
  518 static Token eval_func(int argc, const Token argv[])
  519 {
  520   /* variables */ /*{{{*/
  521   Token result;
  522   /*}}}*/
  523 
  524   --max_eval;
  525   if (max_eval<0)
  526   /* nesting error */ /*{{{*/
  527   {
  528     result.type=EEK;
  529     result.u.err=mystrmalloc(_("nested eval()"));
  530   }
  531   /*}}}*/
  532   else if (argc==1 && argv[0].type==LOCATION)
  533   /* evaluate expression in cell at given position */ /*{{{*/
  534   {
  535     Token **contents;
  536 
  537     contents=getcont(upd_sheet,argv[0].u.location[0],argv[0].u.location[1],argv[0].u.location[2],2);
  538     if (contents==(Token**)0) result.type=EMPTY;
  539     else result=eval(contents);
  540   }
  541   /*}}}*/
  542   else
  543   /* eval type error */ /*{{{*/
  544   {
  545     result.type=EEK;
  546     result.u.err=strcpy(malloc(strlen(_("Usage: eval(location)"))+1),_("Usage: eval(location)"));
  547   }
  548   /*}}}*/
  549   ++max_eval;
  550   return result;
  551 }
  552 /*}}}*/
  553 /* error */ /*{{{*/
  554 static Token error_func(int argc, const Token argv[])
  555 {
  556   /* variables */ /*{{{*/
  557   Token result;
  558   /*}}}*/
  559 
  560   /* asserts */ /*{{{*/
  561   assert(argv!=(Token*)0);
  562   /*}}}*/
  563   result.type=EEK;
  564   if (argc!=1 || argv[0].type!=STRING)
  565   /* result is type error */ /*{{{*/
  566   result.u.err=strcpy(malloc(strlen(_("Usage: error(string message)"))+1),_("Usage: error(string message)"));
  567   /*}}}*/
  568   else
  569   /* result is user defined error */ /*{{{*/
  570   result.u.err=strcpy(malloc(strlen(argv[0].u.string)+1),argv[0].u.string);
  571   /*}}}*/
  572   return result;
  573 }
  574 /*}}}*/
  575 /* string */ /*{{{*/
  576 static Token string_func(int argc, const Token argv[])
  577 {
  578   /* variables */ /*{{{*/
  579   Token result;
  580   char *buf;
  581   size_t size;
  582   /*}}}*/
  583 
  584   if (argc==1 && argv[0].type==LOCATION) /* cell to string */ /*{{{*/
  585   {
  586     buf=(char*)0;
  587     size=0;
  588     do
  589     {
  590       if (buf!=(char*)0) free(buf);
  591       size+=16;
  592       buf=malloc(size);
  593       printvalue(buf,size,0,0,getscientific(upd_sheet,argv[0].u.location[0],argv[0].u.location[1],argv[0].u.location[2]),getprecision(upd_sheet,argv[0].u.location[0],argv[0].u.location[1],argv[0].u.location[2]),upd_sheet,argv[0].u.location[0],argv[0].u.location[1],argv[0].u.location[2]);
  594     } while (strlen(buf)==size-1);
  595     result.type=STRING;
  596     result.u.string=buf;
  597   }
  598   /*}}}*/
  599   else if (argc==1 && argv[0].type==FLOAT) /* float to string */ /*{{{*/
  600   {
  601     result.u.string=malloc(def_precision+10);
  602     sprintf(result.u.string,DEF_SCIENTIFIC ? "%.*e" : "%.*f", def_precision,argv[0].u.flt);
  603     result.type=STRING;
  604   }
  605   /*}}}*/
  606   else if (argc==1 && argv[0].type==INT) /* int to string */ /*{{{*/
  607   {
  608     int length=2;
  609     int n=argv[0].u.integer;
  610 
  611     while (n!=0) n/=10;
  612     result.u.string=malloc(length);
  613     sprintf(result.u.string,"%ld",argv[0].u.integer);
  614     result.type=STRING;
  615   }
  616   /*}}}*/
  617   else if (argc==2 && argv[0].type==FLOAT && argv[1].type==INT) /* float to string */ /*{{{*/
  618   {
  619     result.u.string=malloc(argv[1].u.integer==-1 ? def_precision+10 : argv[1].u.integer+10);
  620     sprintf(result.u.string,DEF_SCIENTIFIC ? "%.*e" : "%.*f",argv[1].u.integer==-1 ? def_precision : (int)(argv[1].u.integer), argv[0].u.flt);
  621     result.type=STRING;
  622   }
  623   /*}}}*/
  624   else if (argc==3 && argv[0].type==FLOAT && (argv[1].type==INT || argv[1].type==EMPTY) && argv[2].type==INT) /* float to string */ /*{{{*/
  625   {
  626     result.u.string=malloc((argv[1].type==INT ? argv[1].u.integer : def_precision)+10);
  627     sprintf(result.u.string,argv[2].u.integer ? "%.*e" : "%.*f",argv[1].type==INT && argv[1].u.integer>=0 ? (int)argv[1].u.integer : def_precision, argv[0].u.flt);
  628     result.type=STRING;
  629   }
  630   /*}}}*/
  631   else /* return string type error  */ /*{{{*/
  632   {
  633     result.type=EEK;
  634     result.u.err=strcpy(malloc(strlen(_("Usage: string(location) or string(float[,[integer][,integer]])"))+1),_("Usage: string(location) or string(float[,[integer][,integer]])"));
  635     return result;
  636   }
  637   /*}}}*/
  638   return result;
  639 }
  640 /*}}}*/
  641 /* sum */ /*{{{*/
  642 static Token sum_func(int argc, const Token argv[])
  643 {
  644   /* variables */ /*{{{*/
  645   Token result;
  646   /*}}}*/
  647 
  648   if (argc==2 && argv[0].type==LOCATION && argv[1].type==LOCATION) /* result is sum */ /*{{{*/
  649   {
  650     /* variables */ /*{{{*/
  651     int x,y,z;
  652     int x1,y1,z1;
  653     int x2,y2,z2;
  654     Token tmp;
  655     /*}}}*/
  656 
  657     x1=argv[0].u.location[0]; x2=argv[1].u.location[0]; posorder(&x1,&x2);
  658     y1=argv[0].u.location[1]; y2=argv[1].u.location[1]; posorder(&y1,&y2);
  659     z1=argv[0].u.location[2]; z2=argv[1].u.location[2]; posorder(&z1,&z2);
  660     result.type=EMPTY;
  661     for (x=x1; x<=x2; ++x)
  662     for (y=y1; y<=y2; ++y)
  663     for (z=z1; z<=z2; ++z)
  664     {
  665       Token t;
  666 
  667       tmp=tadd(result,t=getvalue(upd_sheet,x,y,z));
  668       tfree(&t);
  669       tfree(&result);
  670       result=tmp;
  671       if (result.type==EEK) return result;
  672     }
  673   }
  674   /*}}}*/
  675   else /* result is sum type error */ /*{{{*/
  676   {
  677     result.type=EEK;
  678     result.u.err=strcpy(malloc(strlen(_("Usage: sum(location,location)"))+1),_("Usage: sum(location,location)"));
  679   }
  680   /*}}}*/
  681   return result;
  682 }
  683 /*}}}*/
  684 /* n */ /*{{{*/
  685 static Token n_func(int argc, const Token argv[])
  686 {
  687   /* variables */ /*{{{*/
  688   Token result;
  689   /*}}}*/
  690 
  691   if (argc==2 && argv[0].type==LOCATION && argv[1].type==LOCATION)
  692   /* result is number of elements */ /*{{{*/
  693   {
  694     /* variables */ /*{{{*/
  695     int x,y,z;
  696     int x1,y1,z1;
  697     int x2,y2,z2;
  698     Token tmp;
  699     int n;
  700     /*}}}*/
  701 
  702     x1=argv[0].u.location[0]; x2=argv[1].u.location[0]; posorder(&x1,&x2);
  703     y1=argv[0].u.location[1]; y2=argv[1].u.location[1]; posorder(&y1,&y2);
  704     z1=argv[0].u.location[2]; z2=argv[1].u.location[2]; posorder(&z1,&z2);
  705     n=0;
  706     for (x=x1; x<=x2; ++x)
  707     for (y=y1; y<=y2; ++y)
  708     for (z=z1; z<=z2; ++z)
  709     {
  710       tmp=getvalue(upd_sheet,x,y,z);
  711       if (tmp.type!=EMPTY) ++n;
  712       tfree(&tmp);
  713     }
  714     result.type=INT;
  715     result.u.integer=n;
  716   }
  717   /*}}}*/
  718   else
  719   /* result is n type error */ /*{{{*/
  720   {
  721     result.type=EEK;
  722     result.u.err=strcpy(malloc(strlen(_("Usage: n(location,location)"))+1),_("Usage: n(location,location)"));
  723   }
  724   /*}}}*/
  725   return result;
  726 }
  727 /*}}}*/
  728 /* int */ /*{{{*/
  729 static Token int_func(int argc, const Token argv[])
  730 {
  731   /* variables */ /*{{{*/
  732   Token result;
  733   /*}}}*/
  734 
  735   if (argc==1 && argv[0].type==FLOAT)
  736   /* result is integer with cutoff fractional part */ /*{{{*/
  737   {
  738     result.type=INT;
  739     result.u.integer=(long)(argv[0].u.flt);
  740   }
  741   /*}}}*/
  742   else if (argc==3 && argv[0].type==FLOAT && argv[1].type==INT && argv[2].type==INT)
  743   /* result is integer with given conversion */ /*{{{*/
  744   {
  745     result.type=INT;
  746     if (argv[0].u.flt<0)
  747     {
  748       if (argv[1].u.integer<-1) result.u.integer=(long)floor(argv[0].u.flt);
  749       else if (argv[1].u.integer==-1) result.u.integer=(long)(argv[0].u.flt-0.5);
  750       else if (argv[1].u.integer==0) result.u.integer=(long)(argv[0].u.flt);
  751       else if (argv[1].u.integer==1) result.u.integer=(long)(argv[0].u.flt+0.5);
  752       else result.u.integer=(long)ceil(argv[0].u.flt);
  753     }
  754     else
  755     {
  756       if (argv[2].u.integer<-1) result.u.integer=(long)floor(argv[0].u.flt);
  757       else if (argv[2].u.integer==-1) result.u.integer=(long)(argv[0].u.flt-0.5);
  758       else if (argv[2].u.integer==0) result.u.integer=(long)(argv[0].u.flt);
  759       else if (argv[2].u.integer==1) result.u.integer=(long)(argv[0].u.flt+0.5);
  760       else result.u.integer=(long)ceil(argv[0].u.flt);
  761     }
  762   }
  763   /*}}}*/
  764   else if (argc==1 && argv[0].type==STRING)
  765   /* result is integer */ /*{{{*/
  766   {
  767     char *s;
  768     
  769     errno=0;
  770     result.u.integer=strtol(argv[0].u.string,&s,10);
  771     if (s==(char*)0 || *s)
  772     {
  773       result.type=EEK;
  774       result.u.err=mystrmalloc(_("int(string): invalid string"));
  775     }
  776     else if (errno==ERANGE && (result.u.integer==LONG_MAX || result.u.integer==LONG_MIN))
  777     {
  778       result.type=EEK;
  779       result.u.err=mystrmalloc(_("int(string): domain error"));
  780     }
  781     else result.type=INT;
  782   }
  783   /*}}}*/
  784   else
  785   /* result is int type error */ /*{{{*/
  786   {
  787     result.type=EEK;
  788     result.u.err=strcpy(malloc(strlen(_("Usage: int(float[,integer,integer])"))+1),_("Usage: int(float[,integer,integer])"));
  789   }
  790   /*}}}*/
  791   return result;
  792 }
  793 /*}}}*/
  794 /* frac */ /*{{{*/
  795 static Token frac_func(int argc, const Token argv[])
  796 {
  797   /* variables */ /*{{{*/
  798   Token result;
  799   double foo;
  800   /*}}}*/
  801 
  802   if (argc==1 && argv[0].type==FLOAT)
  803   /* result is fractional part */ /*{{{*/
  804   {
  805     result.type=FLOAT;
  806     result.u.flt=modf(argv[0].u.flt,&foo);
  807   }
  808   /*}}}*/
  809   else
  810   /* result is frac type error */ /*{{{*/
  811   {
  812     result.type=EEK;
  813     result.u.err=strcpy(malloc(strlen(_("Usage: frac(float)"))+1),_("Usage: frac(float)"));
  814   }
  815   /*}}}*/
  816   return result;
  817 }
  818 /*}}}*/
  819 /* len */ /*{{{*/
  820 static Token len_func(int argc, const Token argv[])
  821 {
  822   /* variables */ /*{{{*/
  823   Token result;
  824   /*}}}*/
  825 
  826   if (argc==1 && argv[0].type==STRING)
  827   /* result is length */ /*{{{*/
  828   {
  829     result.type=INT;
  830     result.u.integer=strlen(argv[0].u.string);
  831   }
  832   /*}}}*/
  833   else
  834   /* result is frac type error */ /*{{{*/
  835   {
  836     result.type=EEK;
  837     result.u.err=mystrmalloc(_("Usage: len(string)"));
  838   }
  839   /*}}}*/
  840   return result;
  841 }
  842 /*}}}*/
  843 /* log */ /*{{{*/
  844 static Token log_func(int argc, const Token argv[])
  845 {
  846   /* variables */ /*{{{*/
  847   double x=-1.0,y=-1.0;
  848   Token result;
  849   /*}}}*/
  850 
  851   /* set x and y to first two arguments */ /*{{{*/
  852   if (argc>=1)
  853   {
  854     if (argv[0].type==FLOAT) x=argv[0].u.flt;
  855     else if (argv[0].type==INT) x=(double)argv[0].u.integer;
  856   }
  857   if (argc==2)
  858   {
  859     if (argv[1].type==FLOAT) y=argv[1].u.flt;
  860     else if (argv[1].type==INT) y=(double)argv[1].u.integer;
  861   }
  862   /*}}}*/
  863   if (argc==1 && (argv[0].type==FLOAT || argv[0].type==INT)) /* result is ln(x) */ /*{{{*/
  864   {
  865     result.type=FLOAT;
  866     result.u.flt=log(x);
  867   }
  868   /*}}}*/
  869   else if (argc==2 && (argv[0].type==FLOAT || argv[0].type==INT) && (argv[1].type==FLOAT || argv[1].type==INT)) /* result is ln(x)/ln(y) */ /*{{{*/
  870   {
  871     result.type=FLOAT;
  872     if (y==CONST_E) result.u.flt=log(x);
  873     else if (y==10.0) result.u.flt=log10(x);
  874     else result.u.flt=log(x)/log(y);
  875   }
  876   /*}}}*/
  877   else /* result is log type error */ /*{{{*/
  878   {
  879     result.type=EEK;
  880     result.u.err=mystrmalloc(_("Usage: log(float[,float])"));
  881   }
  882   /*}}}*/
  883   return result;
  884 }
  885 /*}}}*/
  886 /* minmax */ /*{{{*/
  887 static Token minmax_func(int argc, const Token argv[], int min)
  888 {
  889   /* variables */ /*{{{*/
  890   Token result;
  891   int resultx,resulty,resultz;
  892   /*}}}*/
  893 
  894   if (argc==2 && argv[0].type==LOCATION && argv[1].type==LOCATION)
  895   /* result is min/max */ /*{{{*/
  896   {
  897     /* variables */ /*{{{*/
  898     int x,y,z;
  899     int x1,y1,z1;
  900     int x2,y2,z2;
  901     Token tmp;
  902     /*}}}*/
  903 
  904     x1=argv[0].u.location[0]; x2=argv[1].u.location[0]; posorder(&x1,&x2);
  905     y1=argv[0].u.location[1]; y2=argv[1].u.location[1]; posorder(&y1,&y2);
  906     z1=argv[0].u.location[2]; z2=argv[1].u.location[2]; posorder(&z1,&z2);
  907     result=getvalue(upd_sheet,x1,y1,z1);
  908     resultx=x1;
  909     resulty=y1;
  910     resultz=z1;
  911     for (x=x1; x<=x2; ++x)
  912     for (y=y1; y<=y2; ++y)
  913     for (z=z1; z<=z2; ++z)
  914     {
  915       Token t;
  916 
  917       tmp=(min ? tle(result,t=getvalue(upd_sheet,x,y,z)) : tge(result,t=getvalue(upd_sheet,x,y,z)));
  918       if (tmp.type==INT)
  919       /* successful comparison */ /*{{{*/
  920       {
  921         tfree(&tmp);
  922         if (tmp.u.integer==0)
  923         {
  924           tfree(&result);
  925           result=t;
  926           resultx=x;
  927           resulty=y;
  928           resultz=z;
  929         }
  930         else tfree(&t);
  931       }
  932       /*}}}*/
  933       else
  934       /* successless comparison, return with error */ /*{{{*/
  935       {
  936         tfree(&result);
  937         tfree(&t);
  938         return tmp;
  939       }
  940       /*}}}*/
  941     }
  942     tfree(&result);
  943     result.type=LOCATION;
  944     result.u.location[0]=resultx;
  945     result.u.location[1]=resulty;
  946     result.u.location[2]=resultz;
  947     return result;
  948   }
  949   /*}}}*/
  950   else
  951   /* result is min/max type error */ /*{{{*/
  952   {
  953     result.type=EEK;
  954     result.u.err=mystrmalloc(min ? _("Usage: min(location,location)") : _("Usage: max(location,location)"));
  955     return result;
  956   }
  957   /*}}}*/
  958 }
  959 /*}}}*/
  960 /* min */ /*{{{*/
  961 static Token min_func(int argc, const Token argv[])
  962 {
  963   return minmax_func(argc,argv,1);
  964 }
  965 /*}}}*/
  966 /* max */ /*{{{*/
  967 static Token max_func(int argc, const Token argv[])
  968 {
  969   return minmax_func(argc,argv,0);
  970 }
  971 /*}}}*/
  972 /* abs */ /*{{{*/
  973 static Token abs_func(int argc, const Token argv[])
  974 {
  975   /* variables */ /*{{{*/
  976   Token result;
  977   /*}}}*/
  978 
  979   if (argc==1 && argv[0].type==FLOAT)
  980   /* result is absolute floating point number */ /*{{{*/
  981   {
  982     result.type=FLOAT;
  983     result.u.flt=fabs(argv[0].u.flt);
  984   }
  985   /*}}}*/
  986   else if (argc==1 && argv[0].type==INT)
  987   /* result is absolute integer number */ /*{{{*/
  988   {
  989     result.type=INT;
  990     result.u.integer=(argv[0].u.integer<0 ? -argv[0].u.integer : argv[0].u.integer);
  991   }
  992   /*}}}*/
  993   else
  994   /* result is abs type error */ /*{{{*/
  995   {
  996     result.type=EEK;
  997     result.u.err=mystrmalloc(_("Usage: abs(float|integer)"));
  998   }
  999   /*}}}*/
 1000   return result;
 1001 }
 1002 /*}}}*/
 1003 /* $ */ /*{{{*/
 1004 static Token env_func(int argc, const Token argv[])
 1005 {
 1006   /* variables */ /*{{{*/
 1007   Token result;
 1008   /*}}}*/
 1009 
 1010   if (argc==1 && argv[0].type==STRING)
 1011   {
 1012     const char *e;
 1013 
 1014     if ((e=getenv(argv[0].u.string))==(char*)0) e="";
 1015     result.type=STRING;
 1016     result.u.string=mystrmalloc(e);
 1017   }
 1018   else
 1019   {
 1020     result.type=EEK;
 1021     result.u.err=mystrmalloc(_("Usage: $(string)"));
 1022   }
 1023   return result;
 1024 }
 1025 /*}}}*/
 1026 /* float */ /*{{{*/
 1027 static Token float_func(int argc, const Token argv[])
 1028 {
 1029   Token result;
 1030   
 1031   if (argc==1 && argv[0].type==STRING)
 1032   /* convert string to float */ /*{{{*/
 1033   {
 1034     char *p;
 1035 
 1036     result.u.flt=strtod(argv[0].u.string,&p);
 1037     if (p!=argv[0].u.string && *p=='\0' && dblfinite(result.u.flt)==(const char*)0)
 1038     {
 1039       result.type=FLOAT;
 1040     }
 1041     else
 1042     {
 1043       result.type=EEK;
 1044       result.u.err=mystrmalloc(_("Not a (finite) floating point number"));
 1045     }
 1046   }
 1047   /*}}}*/
 1048   else
 1049   /* float type error */ /*{{{*/
 1050   {
 1051     result.type=EEK;
 1052     result.u.err=mystrmalloc(_("Usage: float(string)"));
 1053   }
 1054   /*}}}*/
 1055   return result;
 1056 }
 1057 /*}}}*/
 1058 /* strftime */ /*{{{*/
 1059 static Token strftime_func(int argc, const Token argv[])
 1060 {
 1061   /* variables */ /*{{{*/
 1062   Token result;
 1063   /*}}}*/
 1064 
 1065   if (argc==1 && argv[0].type==STRING) /* format and return string */ /*{{{*/
 1066   {
 1067     time_t t;
 1068     struct tm *tm;
 1069     char s[1024];
 1070     
 1071     t=time((time_t*)0);
 1072     tm=localtime(&t);
 1073     strftime(s,sizeof(s),argv[0].u.string,tm);
 1074     s[sizeof(s)-1]='\0';
 1075     result.u.string=mystrmalloc(s);
 1076     result.type=STRING;
 1077   }
 1078   /*}}}*/
 1079   else if (argc==2 && argv[0].type==STRING && argv[1].type==INT) /* format and return string */ /*{{{*/
 1080   {
 1081     time_t t;
 1082     struct tm *tm;
 1083     char s[1024];
 1084     
 1085     t=argv[1].u.integer;
 1086     tm=localtime(&t);
 1087     strftime(s,sizeof(s),argv[0].u.string,tm);
 1088     s[sizeof(s)-1]='\0';
 1089     result.u.string=mystrmalloc(s);
 1090     result.type=STRING;
 1091   }
 1092   /*}}}*/
 1093   else /* strftime type error */ /*{{{*/
 1094   {
 1095     result.type=EEK;
 1096     result.u.err=mystrmalloc(_("Usage: strftime(string[,integer])"));
 1097   }
 1098   /*}}}*/
 1099   return result;
 1100 }
 1101 /*}}}*/
 1102 /* clock */ /*{{{*/
 1103 static Token clock_func(int argc, const Token argv[])
 1104 {
 1105   /* variables */ /*{{{*/
 1106   Token result;
 1107   /*}}}*/
 1108 
 1109   if (argc==2 && argv[0].type==INT && argv[1].type==LOCATION) /* clock(condition,location) */ /*{{{*/
 1110   {
 1111     if (argv[0].u.integer) clk(upd_sheet,argv[1].u.location[0],argv[1].u.location[1],argv[1].u.location[2]);
 1112     result.type=EMPTY;
 1113   }
 1114   /*}}}*/
 1115   else if (argc==3 && argv[0].type==INT && argv[1].type==LOCATION && argv[2].type==LOCATION) /* clock(condition,location,location) */ /*{{{*/
 1116   {
 1117     if (argv[0].u.integer)
 1118     {
 1119       /* variables */ /*{{{*/
 1120       int x,y,z;
 1121       int x1,y1,z1;
 1122       int x2,y2,z2;
 1123       /*}}}*/
 1124 
 1125       x1=argv[1].u.location[0]; x2=argv[2].u.location[0]; posorder(&x1,&x2);
 1126       y1=argv[1].u.location[1]; y2=argv[2].u.location[1]; posorder(&y1,&y2);
 1127       z1=argv[1].u.location[2]; z2=argv[2].u.location[2]; posorder(&z1,&z2);
 1128       for (x=x1; x<=x2; ++x)
 1129       for (y=y1; y<=y2; ++y)
 1130       for (z=z1; z<=z2; ++z) clk(upd_sheet,x,y,z);
 1131     }
 1132     result.type=EMPTY;
 1133   }
 1134   /*}}}*/
 1135   else /* wrong usage */ /*{{{*/
 1136   {
 1137     result.type=EEK;
 1138     result.u.err=mystrmalloc(_("Usage: clock(condition,location[,location])"));
 1139   }
 1140   /*}}}*/
 1141   return result;
 1142 }
 1143 /*}}}*/
 1144 /* poly */ /*{{{*/
 1145 static Token poly_func(int argc, const Token argv[])
 1146 {
 1147   /* variables */ /*{{{*/
 1148   Token result;
 1149   int i;
 1150   /*}}}*/
 1151 
 1152   for (i=0; i<argc; ++i) if (argc<2 || (argv[i].type!=INT && argv[i].type!=FLOAT)) /* type error */ /*{{{*/
 1153   {
 1154     result.type=EEK;
 1155     result.u.err=strcpy(malloc(strlen(_("Usage: poly(float|integer,float|integer,...)"))+1),_("Usage: poly(float|integer,float|integer,...)"));
 1156   }
 1157   /*}}}*/
 1158   else
 1159   {
 1160     Token tmp;
 1161 
 1162     result=tcopy(argv[1]);
 1163     for (i=2; i<argc; ++i)
 1164     {
 1165       tmp=tmul(result,argv[0]);
 1166       tfree(&result);
 1167       result=tmp;
 1168       tmp=tadd(result,argv[i]);
 1169       tfree(&result);
 1170       result=tmp;
 1171       if (result.type==EEK) return result;
 1172     }
 1173   }
 1174   return result;
 1175 }
 1176 /*}}}*/
 1177 /* sin */ /*{{{*/
 1178 static Token sin_func(int argc, const Token argv[])
 1179 {
 1180   return sci_func(argc,argv,sin,"sin");
 1181 }
 1182 /*}}}*/
 1183 /* cos */ /*{{{*/
 1184 static Token cos_func(int argc, const Token argv[])
 1185 {
 1186   return sci_func(argc,argv,cos,"cos");
 1187 }
 1188 /*}}}*/
 1189 /* tan */ /*{{{*/
 1190 static Token tan_func(int argc, const Token argv[])
 1191 {
 1192   return sci_func(argc,argv,tan,"tan");
 1193 }
 1194 /*}}}*/
 1195 /* sinh */ /*{{{*/
 1196 static Token sinh_func(int argc, const Token argv[])
 1197 {
 1198   return sci_func(argc,argv,sinh,"sinh");
 1199 }
 1200 /*}}}*/
 1201 /* cosh */ /*{{{*/
 1202 static Token cosh_func(int argc, const Token argv[])
 1203 {
 1204   return sci_func(argc,argv,cosh,"cosh");
 1205 }
 1206 /*}}}*/
 1207 /* tanh */ /*{{{*/
 1208 static Token tanh_func(int argc, const Token argv[])
 1209 {
 1210   return sci_func(argc,argv,tanh,"tanh");
 1211 }
 1212 /*}}}*/
 1213 /* asin */ /*{{{*/
 1214 static Token asin_func(int argc, const Token argv[])
 1215 {
 1216   return sci_func(argc,argv,asin,"asin");
 1217 }
 1218 /*}}}*/
 1219 /* acos */ /*{{{*/
 1220 static Token acos_func(int argc, const Token argv[])
 1221 {
 1222   return sci_func(argc,argv,acos,"acos");
 1223 }
 1224 /*}}}*/
 1225 /* atan */ /*{{{*/
 1226 static Token atan_func(int argc, const Token argv[])
 1227 {
 1228   return sci_func(argc,argv,atan,"atan");
 1229 }
 1230 /*}}}*/
 1231 /* arsinh */ /*{{{*/
 1232 static Token arsinh_func(int argc, const Token argv[])
 1233 {
 1234   return sci_func(argc,argv,arsinh,"arsinh");
 1235 }
 1236 /*}}}*/
 1237 /* arcosh */ /*{{{*/
 1238 static Token arcosh_func(int argc, const Token argv[])
 1239 {
 1240   return sci_func(argc,argv,arcosh,"arcosh");
 1241 }
 1242 /*}}}*/
 1243 /* artanh */ /*{{{*/
 1244 static Token artanh_func(int argc, const Token argv[])
 1245 {
 1246   return sci_func(argc,argv,artanh,"artanh");
 1247 }
 1248 /*}}}*/
 1249 /* rad2deg */ /*{{{*/
 1250 static Token rad2deg_func(int argc, const Token argv[])
 1251 {
 1252   return sci_func(argc,argv,rad2deg,"rad2deg");
 1253 }
 1254 /*}}}*/
 1255 /* deg2rad */ /*{{{*/
 1256 static Token deg2rad_func(int argc, const Token argv[])
 1257 {
 1258   return sci_func(argc,argv,deg2rad,"deg2rad");
 1259 }
 1260 /*}}}*/
 1261 /* rnd */ /*{{{*/
 1262 static Token rnd_func(int argc, const Token argv[])
 1263 {
 1264   /* variables */ /*{{{*/
 1265   Token result;
 1266   /*}}}*/
 1267 
 1268   if (argc==0)
 1269   {
 1270     result.type=FLOAT;
 1271     result.u.flt=rand()/((double)RAND_MAX);
 1272   }
 1273   else
 1274   {
 1275     result.type=EEK;
 1276     result.u.err=mystrmalloc(_("Usage: rnd()"));
 1277   }
 1278   return result;
 1279 }
 1280 /*}}}*/
 1281 /* substr */ /*{{{*/
 1282 static Token substr_func(int argc, const Token argv[])
 1283 {
 1284   /* variables */ /*{{{*/
 1285   Token result;
 1286   /*}}}*/
 1287 
 1288   if (argc==3 && argv[0].type==STRING && argv[1].type==INT && argv[2].type==INT)
 1289   {
 1290     char ss[1024];
 1291     int n, l, b, e;
 1292 
 1293     b = argv[1].u.integer;
 1294     e = argv[2].u.integer;
 1295     l = strlen(argv[0].u.string);
 1296     if( b < 0 ) b = 0;
 1297     if( b > l ) b = l;
 1298     if( e > l ) e = l;
 1299     n = e - b + 1;
 1300     if( n >= 1024 ) n = 1024 - 1;
 1301     if(n > 0) {
 1302     ss[n] = '\0';
 1303     strncpy(ss, argv[0].u.string + b, n);
 1304     result.type=STRING;
 1305     result.u.string=mystrmalloc(ss);
 1306     }
 1307     else {
 1308     result.type=EMPTY;
 1309     }
 1310   }
 1311   else
 1312   {
 1313     result.type=EEK;
 1314     result.u.err=mystrmalloc(_("Usage: substr(string,integer,integer)"));
 1315   }
 1316   return result;
 1317 }
 1318 /*}}}*/
 1319 /* strptime */ /*{{{*/
 1320 static Token strptime_func(int argc, const Token argv[])
 1321 {
 1322   /* variables */ /*{{{*/
 1323   Token result;
 1324   /*}}}*/
 1325 
 1326   if (argc==2 && argv[0].type==STRING && argv[1].type==STRING) /* format and return string */ /*{{{*/
 1327   {
 1328     time_t t;
 1329     struct tm tm;
 1330     
 1331     t=time((time_t*)0);
 1332     tm=*localtime(&t);
 1333     strptime(argv[1].u.string,argv[0].u.string,&tm);
 1334     result.u.integer=mktime(&tm);
 1335     result.type=INT;
 1336   }
 1337   /*}}}*/
 1338   else /* strftime type error */ /*{{{*/
 1339   {
 1340     result.type=EEK;
 1341     result.u.err=mystrmalloc(_("Usage: strptime(string,string)"));
 1342   }
 1343   /*}}}*/
 1344   return result;
 1345 }
 1346 /*}}}*/
 1347 /* time */ /*{{{*/
 1348 static Token time_func(int argc, const Token argv[])
 1349 {
 1350   Token result;
 1351 
 1352   if (argc==0)
 1353   {
 1354     result.type=INT;
 1355     result.u.integer=time((time_t*)0);
 1356   }
 1357   else  
 1358   {
 1359     result.type=EEK;
 1360     result.u.err=mystrmalloc(_("Usage: time()"));
 1361   }
 1362   return result;
 1363 }
 1364 /*}}}*/
 1365   
 1366 /* table of functions */ /*{{{*/
 1367 /* The order of these entries has no influence on performance, but to stay
 1368    compatible, new entries should be appended. */
 1369 Tfunc tfunc[]=
 1370 {
 1371   { "@", at_func },
 1372   { "&", adr_func },
 1373   { "x", x_func },
 1374   { "y", y_func },
 1375   { "z", z_func },
 1376   { "eval", eval_func },
 1377   { "error", error_func },
 1378   { "string", string_func },
 1379   { "sum", sum_func },
 1380   { "n", n_func },
 1381   { "int", int_func },
 1382   { "frac", frac_func },
 1383   { "len", len_func },
 1384   { "min", min_func },
 1385   { "max", max_func },
 1386   { "abs", abs_func },
 1387   { "$", env_func },
 1388   { "float", float_func },
 1389   { "strftime", strftime_func },
 1390   { "clock", clock_func },
 1391   { "poly", poly_func },
 1392   { "e", e_func },
 1393   { "log", log_func },
 1394   { "sin", sin_func },
 1395   { "cos", cos_func },
 1396   { "tan", tan_func },
 1397   { "sinh", sinh_func },
 1398   { "cosh", cosh_func },
 1399   { "tanh", tanh_func },
 1400   { "asin", asin_func },
 1401   { "acos", acos_func },
 1402   { "atan", atan_func },
 1403   { "arsinh", arsinh_func },
 1404   { "arcosh", arcosh_func },
 1405   { "artanh", artanh_func },
 1406   { "deg2rad", deg2rad_func },
 1407   { "rad2deg", rad2deg_func },
 1408   { "rnd", rnd_func },
 1409   { "substr", substr_func },
 1410   { "strptime", strptime_func },
 1411   { "time", time_func },
 1412   { "", (Token (*)(int, const Token[]))0 }
 1413 };
 1414 /*}}}*/