"Fossies" - the Fresh Open Source Software Archive

Member "teapot-2.3.0/wk1.c" (6 Feb 2012, 32019 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 "wk1.c" see the Fossies "Dox" file reference documentation.

    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 #include <assert.h>
   10 #include <errno.h>
   11 #include <limits.h>
   12 #include <math.h>
   13 #include <stdio.h>
   14 #include <stdlib.h>
   15 #include <string.h>
   16 #ifdef OLD_REALLOC
   17 #define realloc(s,l) myrealloc(s,l)
   18 #endif
   19 
   20 #ifdef DMALLOC
   21 #include "dmalloc.h"
   22 #endif
   23 
   24 
   25 #include "eval.h"
   26 #include "main.h"
   27 #include "misc.h"
   28 #include "sheet.h"
   29 #include "wk1.h"
   30 /*}}}*/
   31 /* #defines */ /*{{{*/
   32 #define WK1DEBUG 0
   33 #define LOTUS123 0x0404
   34 #define SYMPHONY 0x0405
   35 /* Applix uses that, too */
   36 #define EXCEL    0x0406
   37 /*}}}*/
   38 
   39 static int unrpn(const char *s, const int *offset, int top, Token **t, int *tokens);
   40 
   41 #if WK1DEBUG
   42 static FILE *se;
   43 #endif
   44 
   45 /* it      -- convert string to int */ /*{{{*/
   46 static int it(const char *s)
   47 {
   48   return (((unsigned int)((const unsigned char)*s))|(*(s+1)<<8));
   49 }
   50 /*}}}*/
   51 /* dbl     -- convert string to double */ /*{{{*/
   52 static double dbl(const unsigned char *s)
   53 {
   54   double x;
   55   int sg,e,i;
   56 
   57   x=0.0;
   58   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[0]&i);
   59   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[1]&i);
   60   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[2]&i);
   61   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[3]&i);
   62   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[4]&i);
   63   for (i=1; i<256; i<<=1) x=x/2.0+!!(s[5]&i);
   64   x=x/2.0+!!(s[6]&0x01);
   65   x=x/2.0+!!(s[6]&0x02);
   66   x=x/2.0+!!(s[6]&0x04);
   67   x=x/2.0+!!(s[6]&0x08);
   68   x=x/2.0+1.0;
   69   if ((e=((s[6]>>4)+((s[7]&0x7f)<<4))-1023)==-1023)
   70   {
   71     x=0.0;
   72     e=0;
   73   }
   74   if (s[7]&0x80) sg=-1; else sg=1;
   75 #if WK1DEBUG
   76   fprintf(se,"%02x %02x %02x %02x %02x %02x %02x %02x ",s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7]);
   77   fprintf(se,"%f (exp 2^%d)\r\n",sg*ldexp(x,e),e);
   78 #endif
   79   return (sg*ldexp(x,e));
   80 }
   81 /*}}}*/
   82 /* format  -- convert string into format */ /*{{{*/
   83 static void format(unsigned char s, Cell *cell)
   84 {
   85 #if WK1DEBUG
   86   fprintf(se,", format 0x%02x",s);
   87   if (s&0x80) fprintf(se,", locked");
   88 #endif
   89   switch (((unsigned int)(s&0x70))>>4)
   90   {
   91     case 0: /* fixed with given precision */ /*{{{*/
   92     {
   93       cell->precision=s&0x0f;
   94       cell->scientific=0;
   95       break;
   96     }
   97     /*}}}*/
   98     case 1: /* scientifix with given presision */ /*{{{*/
   99     {
  100       cell->precision=s&0x0f;
  101       cell->scientific=1;
  102       break;
  103     }
  104     /*}}}*/
  105     case 2: /* currency with given precision */ /*{{{*/
  106     {
  107       cell->precision=s&0x0f;
  108       break;
  109     }
  110     /*}}}*/
  111     case 3: /* percent with given precision */ /*{{{*/
  112     {
  113       cell->precision=s&0x0f;
  114       break;
  115     }
  116     /*}}}*/
  117     case 4: /* comma with given precision */ /*{{{*/
  118     {
  119       cell->precision=s&0x0f;
  120       break;
  121     }
  122     /*}}}*/
  123     case 5: /* unused */ break;
  124     case 6: /* unused */ break;
  125     case 7:
  126     {
  127       switch (s&0x0f)
  128       {
  129         case 0: /* +/- */; break;
  130         case 1: /* general */; break;
  131         case 2: /* day-month-year */; break;
  132         case 3: /* day-month */; break;
  133         case 4: /* month-year */; break;
  134         case 5: /* text */; break;
  135         case 6: /* hidden */; break;
  136         case 7: /* date;hour-min-sec */; break;
  137         case 8: /* date;hour-min */; break;
  138         case 9: /* date;intnt'l1 */; break;
  139         case 10: /* date;intnt'l2 */; break;
  140         case 11: /* time;intnt'l1 */; break;
  141         case 12: /* time;intnt'l2 */; break;
  142         case 13: /* unused13 */; break;
  143         case 14: /* unused14 */; break;
  144         case 15: /* default special format */; break;
  145       }
  146       break;
  147     }
  148   }
  149 }
  150 /*}}}*/
  151 /* pair    -- convert coordinate pair */ /*{{{*/
  152 static int pair(const char *s, Token **t, int *tokens)
  153 {
  154   int x,y;
  155 
  156   x=it(s); y=it(s+2);
  157   if (t)
  158   {
  159     if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  160     t[*tokens]->type=OPERATOR;
  161     t[*tokens]->u.op=OP;
  162 #if WK1DEBUG
  163     fprintf(se,"[(");
  164 #endif
  165   }
  166   if (tokens) ++(*tokens);
  167   switch (x&0xc000)
  168   {
  169     case 0x0000: /* MSB -> 0 0 */ /*{{{*/
  170     {
  171       x=x&0x2000 ? x|0xc000 : x&0x3fff;
  172       if (t)
  173       {
  174         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  175         t[*tokens]->type=INT;
  176         t[*tokens]->u.integer=x;
  177 #if WK1DEBUG
  178         fprintf(se,"%d",x);
  179 #endif
  180       }
  181       if (tokens) ++(*tokens);
  182       break;
  183     }
  184     /*}}}*/
  185     case 0x4000: assert(0); break;
  186     case 0x8000: /* MSB -> 1 0 */ /*{{{*/
  187     {
  188       x=x&0x2000 ? x|0xc000 : x&0x3fff;
  189       if (x!=0)
  190       {
  191         if (t)
  192         {
  193           if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+2]=malloc(sizeof(Token)))==(Token*)0) return -1;
  194           t[*tokens]->type=FIDENT;
  195           t[*tokens]->u.fident=identcode("x",1);
  196           t[*tokens+1]->type=OPERATOR;
  197           t[*tokens+1]->u.op=OP;
  198           t[*tokens+2]->type=OPERATOR;
  199           t[*tokens+2]->u.op=CP;
  200 #if WK1DEBUG
  201           fprintf(se,"x()");
  202 #endif
  203         }
  204         if (tokens) *tokens+=3;
  205         if (t)
  206         {
  207           if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1;
  208           t[*tokens]->type=OPERATOR;
  209           t[*tokens+1]->type=INT;
  210           if (x<0)
  211           {
  212             t[*tokens]->u.op=MINUS;
  213             t[*tokens+1]->u.integer=-x;
  214 #if WK1DEBUG
  215             fprintf(se,"-%d",-x);
  216 #endif
  217           }
  218           else
  219           {
  220             t[*tokens]->u.op=PLUS;
  221             t[*tokens+1]->u.integer=x;
  222 #if WK1DEBUG
  223             fprintf(se,"+%d",x);
  224 #endif
  225           }
  226         }
  227         if (tokens) *tokens+=2;
  228       }
  229       break;
  230     }
  231     /*}}}*/
  232     case 0xc000: assert(0); break;
  233   }
  234   if (t)
  235   {
  236     if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  237     t[*tokens]->type=OPERATOR;
  238     t[*tokens]->u.op=COMMA;
  239 #if WK1DEBUG
  240     fprintf(se,",");
  241 #endif
  242   }
  243   if (tokens) ++(*tokens);
  244   switch (y&0xc000)
  245   {
  246     case 0x0000: /* MSB -> 0 0 */ /*{{{*/
  247     {
  248       y=y&0x2000 ? y|0xc000 : y&0x3fff;
  249       if (t)
  250       {
  251         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  252         t[*tokens]->type=INT;
  253         t[*tokens]->u.integer=y;
  254 #if WK1DEBUG
  255         fprintf(se,"%d",y);
  256 #endif
  257       }
  258       if (tokens) ++(*tokens);
  259       break;
  260     }
  261     /*}}}*/
  262     case 0x4000: assert(0); break;
  263     case 0x8000: /* MSB -> 1 0 */ /*{{{*/
  264     {
  265       y=y&0x2000 ? y|0xc000 : y&0x3fff;
  266       if (y)
  267       {
  268         if (t)
  269         {
  270           if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+2]=malloc(sizeof(Token)))==(Token*)0) return -1;
  271           t[*tokens]->type=FIDENT;
  272           t[*tokens]->u.fident=identcode("y",1);
  273           t[*tokens+1]->type=OPERATOR;
  274           t[*tokens+1]->u.op=OP;
  275           t[*tokens+2]->type=OPERATOR;
  276           t[*tokens+2]->u.op=CP;
  277 #if WK1DEBUG
  278           fprintf(se,"y()");
  279 #endif
  280         }
  281         if (tokens) *tokens+=3;
  282         if (t)
  283         {
  284           if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1;
  285           t[*tokens]->type=OPERATOR;
  286           t[*tokens+1]->type=INT;
  287           if (y<0)
  288           {
  289             if (t)
  290             {
  291               t[*tokens]->u.op=MINUS;
  292               t[*tokens+1]->u.integer=-y;
  293 #if WK1DEBUG
  294               fprintf(se,"-%d",-y);
  295 #endif
  296             }
  297           }
  298           else
  299           {
  300             if (t)
  301             {
  302               t[*tokens]->u.op=PLUS;
  303               t[*tokens+1]->u.integer=y;
  304 #if WK1DEBUG
  305               fprintf(se,"+%d",y);
  306 #endif
  307             }
  308           }
  309         }
  310         if (tokens) *tokens+=2;
  311       }
  312       break;
  313     }
  314     /*}}}*/
  315     case 0xc000: assert(0); break;
  316   }
  317   if (t)
  318   {
  319     if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  320     t[*tokens]->type=OPERATOR;
  321     t[*tokens]->u.op=CP;
  322 #if WK1DEBUG
  323     fprintf(se,")]");
  324 #endif
  325   }
  326   if (tokens) ++(*tokens);
  327   return 0;
  328 }
  329 /*}}}*/
  330 /* sumup   -- sum up arguments */ /*{{{*/
  331 static int sumup(const char *s, const int *offset, int top, Token **t, int *tokens, int argc)
  332 {
  333   int low;
  334 
  335   if (top<0) return -1;
  336   if (argc>1)
  337   {
  338     low=unrpn(s,offset,top,(Token**)0,(int*)0);
  339     if (low<0) return -1;
  340     sumup(s,offset,low-1,t,tokens,argc-1);
  341     if (t)
  342     {
  343       if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  344       t[*tokens]->type=OPERATOR;
  345       t[*tokens]->u.op=PLUS;
  346 #if WK1DEBUG
  347       fprintf(se,"[+]");
  348 #endif
  349     }
  350     if (tokens) ++(*tokens);
  351   }
  352   if (s[offset[top]]==2)
  353   {
  354     if (t)
  355     {
  356       if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1;
  357       t[*tokens]->type=FIDENT;
  358       t[*tokens]->u.fident=identcode("sum",3);
  359       t[*tokens+1]->type=OPERATOR;
  360       t[*tokens+1]->u.op=OP;
  361 #if WK1DEBUG
  362       fprintf(se,"[sum(]");
  363 #endif
  364     }
  365     if (tokens) *tokens+=2;
  366   }
  367   low=unrpn(s,offset,top,t,tokens);
  368   if (s[offset[top]]==2)
  369   {
  370     if (t)
  371     {
  372       if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  373       t[*tokens]->type=OPERATOR;
  374       t[*tokens]->u.op=CP;
  375 #if WK1DEBUG
  376       fprintf(se,"[)]");
  377 #endif
  378     }
  379     if (tokens) ++(*tokens);
  380   }
  381   return low;
  382 }
  383 /*}}}*/
  384 /* unrpn   -- convert RPN expression to infix */ /*{{{*/
  385 static int unrpn(const char *s, const int *offset, int top, Token **t, int *tokens)
  386 {
  387   int low;
  388   
  389   if (top<0) return -1;
  390   switch (s[offset[top]])
  391   {
  392     case  0: /* double constant                    */ /*{{{*/
  393     {
  394       if (t)
  395       {
  396         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  397         t[*tokens]->type=FLOAT;
  398         t[*tokens]->u.flt=dbl((const unsigned char*)s+offset[top]+1);
  399 #if WK1DEBUG
  400         fprintf(se,"[constant %f]",dbl((const unsigned char*)s+offset[top]+1));
  401 #endif
  402       }
  403       if (tokens) ++(*tokens);
  404       low=top;
  405       break;
  406     }
  407     /*}}}*/
  408     case  1: /* variable                           */ /*{{{*/
  409     {
  410       if (t)
  411       {
  412         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  413         t[*tokens]->type=FIDENT;
  414         t[*tokens]->u.fident=identcode("@",1);
  415       }
  416       if (tokens) ++(*tokens);
  417       if (pair(s+offset[top]+1,t,tokens)==-1) low=-1; else low=top;
  418       break;
  419     }
  420     /*}}}*/
  421     case  2: /* range                              */ /*{{{*/
  422     {
  423       if (t)
  424       {
  425         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  426         t[*tokens]->type=FIDENT;
  427         t[*tokens]->u.fident=identcode("&",1);
  428 #if WK1DEBUG
  429         fprintf(se,"[&]");
  430 #endif
  431       }
  432       if (tokens) ++(*tokens);
  433       pair(s+offset[top]+1,t,tokens);
  434       if (t)
  435       {
  436         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0 || (t[*tokens+1]=malloc(sizeof(Token)))==(Token*)0) return -1;
  437         t[*tokens]->type=OPERATOR;
  438         t[*tokens]->u.fident=COMMA;
  439         t[*tokens+1]->type=FIDENT;
  440         t[*tokens+1]->u.op=identcode("&",1);
  441 #if WK1DEBUG
  442         fprintf(se,"[,&]");
  443 #endif
  444       }
  445       if (tokens) *tokens+=2;
  446       pair(s+offset[top]+5,t,tokens);
  447       low=top;
  448       break;
  449     }
  450     /*}}}*/
  451     case  3: /* return                             */ /*{{{*/
  452     {
  453       low=unrpn(s,offset,top-1,t,tokens);
  454       if (t)
  455       {
  456         t[*tokens]=(Token*)0;
  457 #if WK1DEBUG
  458         fprintf(se,"[RETURN]");
  459 #endif
  460       }
  461       if (tokens) ++(*tokens);
  462       break;
  463     }
  464     /*}}}*/
  465     case  4: /* paren                              */ /*{{{*/
  466     {
  467       if (t)
  468       {
  469         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  470         t[*tokens]->type=OPERATOR;
  471         t[*tokens]->u.op=OP;
  472 #if WK1DEBUG
  473         fprintf(se,"[(]");
  474 #endif
  475       }
  476       if (tokens) ++(*tokens);
  477       low=unrpn(s,offset,top-1,t,tokens);
  478       if (t)
  479       {
  480         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  481         t[*tokens]->type=OPERATOR;
  482         t[*tokens]->u.op=CP;
  483 #if WK1DEBUG
  484         fprintf(se,"[)]");
  485 #endif
  486       }
  487       if (tokens) ++(*tokens);
  488       break;
  489     }
  490     /*}}}*/
  491     case  5: /* int constant                       */ /*{{{*/
  492     {
  493       if (t)
  494       {
  495         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  496         t[*tokens]->type=INT;
  497         t[*tokens]->u.integer=it(s+offset[top]+1);
  498 #if WK1DEBUG
  499         fprintf(se,"[constant %d]",it(s+offset[top]+1));
  500 #endif
  501       }
  502       if (tokens) ++(*tokens);
  503       low=top;
  504       break;
  505     }
  506     /*}}}*/
  507     case  9:
  508     case 10:
  509     case 11:
  510     case 12:
  511     case 13:
  512     case 14:
  513     case 15:
  514     case 16:
  515     case 17:
  516     case 18:
  517     case 19: /* +, -, *, /, ^, -, !=, <=, >=, <, > */ /*{{{*/
  518     {
  519       if (t)
  520       {
  521         low=unrpn(s,offset,top-1,(Token**)0,(int*)0);
  522         low=unrpn(s,offset,low-1,t,tokens);
  523         if (low<0) return -1;
  524         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  525         t[*tokens]->type=OPERATOR;
  526         switch (s[offset[top]])
  527         {
  528           case  9: /* +  */ /*{{{*/
  529           {
  530             t[*tokens]->u.op=PLUS;
  531 #if WK1DEBUG
  532             fprintf(se,"[+]");
  533 #endif
  534             break;
  535           }
  536           /*}}}*/
  537           case 10: /* -  */ /*{{{*/
  538           {
  539             t[*tokens]->u.op=MINUS;
  540 #if WK1DEBUG
  541             fprintf(se,"[-]");
  542 #endif
  543             break;
  544           }
  545           /*}}}*/
  546           case 11: /* *  */ /*{{{*/
  547           {
  548             t[*tokens]->u.op=MUL;
  549 #if WK1DEBUG
  550             fprintf(se,"[*]");
  551 #endif
  552             break;
  553           }
  554           /*}}}*/
  555           case 12: /* /  */ /*{{{*/
  556           {
  557             t[*tokens]->u.op=DIV;
  558 #if WK1DEBUG
  559             fprintf(se,"[/]");
  560 #endif
  561             break;
  562           }
  563           /*}}}*/
  564           case 13: /* ^  */ /*{{{*/
  565           {
  566             t[*tokens]->u.op=POW;
  567 #if WK1DEBUG
  568             fprintf(se,"[^]");
  569 #endif
  570             break;
  571           }
  572           /*}}}*/
  573           case 14: /* == */ /*{{{*/
  574           {
  575             t[*tokens]->u.op=ISEQUAL;
  576 #if WK1DEBUG
  577             fprintf(se,"[==]");
  578 #endif
  579             break;
  580           }
  581           /*}}}*/
  582           case 15: /* != */ /*{{{*/
  583           {
  584             t[*tokens]->u.op=NE;
  585 #if WK1DEBUG
  586             fprintf(se,"[!=]");
  587 #endif
  588             break;
  589           }
  590           /*}}}*/
  591           case 16: /* <= */ /*{{{*/
  592           {
  593             t[*tokens]->u.op=LE;
  594 #if WK1DEBUG
  595             fprintf(se,"[<=]");
  596 #endif
  597             break;
  598           }
  599           /*}}}*/
  600           case 17: /* >= */ /*{{{*/
  601           {
  602             t[*tokens]->u.op=GE;
  603 #if WK1DEBUG
  604             fprintf(se,"[>=]");
  605 #endif
  606             break;
  607           }
  608           /*}}}*/
  609           case 18: /* <  */ /*{{{*/
  610           {
  611             t[*tokens]->u.op=LT;
  612 #if WK1DEBUG
  613             fprintf(se,"[<]");
  614 #endif
  615             break;
  616           }
  617           /*}}}*/
  618           case 19: /* >  */ /*{{{*/
  619           {
  620             t[*tokens]->u.op=GT;
  621 #if WK1DEBUG
  622             fprintf(se,"[>]");
  623 #endif
  624             break;
  625           }
  626           /*}}}*/
  627           default: assert(0);
  628         }
  629         if (tokens) ++(*tokens);
  630         unrpn(s,offset,top-1,t,tokens);
  631       }
  632       else
  633       {
  634         low=unrpn(s,offset,top-1,(Token**)0,tokens);
  635         if (tokens) ++(*tokens);
  636         low=unrpn(s,offset,low-1,(Token**)0,tokens);
  637       }
  638       break;
  639     }
  640     /*}}}*/
  641     case 23: /* unary +                            */ /*{{{*/
  642     {
  643       low=unrpn(s,offset,top-1,t,tokens);
  644       break;
  645     }
  646     /*}}}*/
  647     case 80: /* sum                                */ /*{{{*/
  648     {
  649       int argc;
  650       
  651       argc=s[offset[top]+1];
  652 #if WK1DEBUG
  653       if (t) fprintf(se,"[sum argc=%d]",argc);
  654 #endif
  655       if (t)
  656       {
  657         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  658         t[*tokens]->type=OPERATOR;
  659         t[*tokens]->u.op=OP;
  660 #if WK1DEBUG
  661         fprintf(se,"[(]");
  662 #endif
  663       }
  664       if (tokens) ++(*tokens);
  665       low=sumup(s,offset,top-1,t,tokens,argc);
  666       if (t)
  667       {
  668         if ((t[*tokens]=malloc(sizeof(Token)))==(Token*)0) return -1;
  669         t[*tokens]->type=OPERATOR;
  670         t[*tokens]->u.op=CP;
  671 #if WK1DEBUG
  672         fprintf(se,"[)]");
  673 #endif
  674       }
  675       if (tokens) ++(*tokens);
  676       break;
  677     }
  678     /*}}}*/
  679     default: assert(0); low=-1;
  680   }
  681   return (low<0 ? -1 : low);
  682 }
  683 /*}}}*/
  684 
  685 /* loadwk1 -- load WK1 file */ /*{{{*/
  686 const char *loadwk1(Sheet *sheet, const char *name)
  687 {
  688   /* variables */ /*{{{*/
  689   FILE *fp;
  690   const char *err;
  691   int head[4];
  692   char *body=(char*)0,*newbody;
  693   size_t bodymaxlen=0;
  694   size_t bodylen;
  695   int found_bof=0,found_eof=0;
  696   /*}}}*/
  697 
  698 #if WK1DEBUG
  699   se=fopen("/dev/tty","w"); assert(se!=(FILE*)0); fprintf(se,"\r\n");
  700 #endif
  701   if ((fp=fopen(name,"r"))==(FILE*)0) return strerror(errno);
  702   err=(const char*)0;
  703   while (1)
  704   {
  705     /* read header */ /*{{{*/
  706     if ((head[0]=getc(fp))==EOF) break;
  707     if ((head[1]=getc(fp))==EOF) { err=_("The record header appears to be truncated"); goto ouch; }
  708     if ((head[2]=getc(fp))==EOF) { err=_("The record header appears to be truncated"); goto ouch; }
  709     if ((head[3]=getc(fp))==EOF) { err=_("The record header appears to be truncated"); goto ouch; }
  710     bodylen=head[2]|(head[3]<<8);
  711     /*}}}*/
  712     /* read body */ /*{{{*/
  713     if (bodylen>bodymaxlen)
  714     {
  715       newbody=realloc(body,bodymaxlen=bodylen);
  716       if (newbody==(char*)0) { err=_("Out of memory"); goto ouch; }
  717       else body=newbody;
  718     }
  719     if (bodylen) if (fread(body,bodylen,1,fp)!=1) { err=_("The record body appears to be truncated"); goto ouch; }
  720     /*}}}*/
  721     /* process record */ /*{{{*/
  722 #if WK1DEBUG
  723     fprintf(se,"bodylen %d, type %04x\r\n",bodylen,head[0]|(head[1]<<8));
  724 #endif
  725     switch (head[0]|(head[1]<<8))
  726     {
  727       /* BOF           -- Beginning of file                */ /*{{{*/
  728       case 0x0:
  729       {
  730         if (bodylen!=2) { err=_("Invalid record body length"); goto ouch; }
  731         if (!found_bof)
  732         {
  733           freesheet(sheet,0);
  734           found_bof=it(body);
  735         }
  736         break;
  737       }
  738       /*}}}*/
  739       /* EOF           -- End of file                      */ /*{{{*/
  740       case 0x1:
  741       {
  742         if (bodylen!=0) { err=_("Invalid record body length"); goto ouch; }
  743         found_eof=1;
  744         break;
  745       }
  746       /*}}}*/
  747       /* CALCMODE      -- Calculation mode                 */ /*{{{*/
  748       case 0x2:
  749       {
  750         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
  751         /* (unsigned char)body[0] means: */
  752         /* 0 -- manual                   */
  753         /* 0xff -- automatic             */
  754         break;
  755       }
  756       /*}}}*/
  757       /* CALCORDER     -- Calculation order                */ /*{{{*/
  758       case 0x3:
  759       {
  760         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
  761         /* (unsigned char)body[0] means: */
  762         /*    0 -- natural               */
  763         /*    1 -- by column             */
  764         /* 0xff -- by row                */
  765         break;
  766       }
  767       /*}}}*/
  768       /* SPLIT         -- Split window type                */ /*{{{*/
  769       case 0x4:
  770       {
  771         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
  772         /* (unsigned)body[0] means: */
  773         /*    0: not split          */
  774         /*    1: vertical split     */
  775         /* 0xff: horizontal split   */
  776         break;
  777       }
  778       /*}}}*/
  779       /* SYNC          -- Split window sync                */ /*{{{*/
  780       case 0x5:
  781       {
  782         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
  783         /* (unsigned)body[0] means: */
  784         /*    0: not synchronized   */
  785         /* 0xff: synchronized       */
  786         break;
  787       }
  788       /*}}}*/
  789       /* RANGE         -- Active worksheet range           */ /*{{{*/
  790       case 0x6:
  791       {
  792         if (bodylen!=8) { err=_("Invalid record body length"); goto ouch; }
  793         resize(sheet,it(body+4),it(body+6),0);
  794         /* range is from &(it(body),it(body+2)) to &(it(body+4),it(body+6)) */
  795         break;
  796       }
  797       /*}}}*/
  798       /* WINDOW1       -- Window 1 record                  */ /*{{{*/
  799       case 0x7:
  800       {
  801         /* 31 is the specification, but Applix generates 32 while claiming to be Excel */
  802         if (bodylen!=31 && (found_bof!=EXCEL && bodylen!=32)) { err=_("Invalid record body length"); goto ouch; }
  803         break;
  804       }
  805       /*}}}*/
  806       /* COLW1         -- Column width, window 1           */ /*{{{*/
  807       case 0x8:
  808       {
  809         if (bodylen!=3) { err=_("Invalid record body length"); goto ouch; }
  810         break;
  811       }
  812       /*}}}*/
  813       /* WINTWO        -- Window 2 record                  */ /*{{{*/
  814       case 0x9:
  815       {
  816         if (bodylen!=31) { err=_("Invalid record body length"); goto ouch; }
  817         break;
  818       }
  819       /*}}}*/
  820       /* COLW2         -- Column width, window 2           */ /*{{{*/
  821       case 0xA:
  822       {
  823         if (bodylen!=3) { err=_("Invalid record body length"); goto ouch; }
  824         break;
  825       }
  826       /*}}}*/
  827       /* _("nN)ame")          -- Named range                      */ /*{{{*/
  828       case 0xB:
  829       {
  830         if (bodylen!=24) { err=_("Invalid record body length"); goto ouch; }
  831         break;
  832       }
  833       /*}}}*/
  834       /* BLANK         -- Blank cell                       */ /*{{{*/
  835       case 0xC:
  836       {
  837         if (bodylen!=5) { err=_("Invalid record body length"); goto ouch; }
  838         initcell(sheet,it(body+1),it(body+3),0);
  839         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
  840         break;
  841       }
  842       /*}}}*/
  843       /* INTEGER       -- Integer number cell              */ /*{{{*/
  844       case 0xD:
  845       {
  846         Token **t;
  847 
  848         assert(bodylen==7);
  849         initcell(sheet,it(body+1),it(body+3),0);
  850         t=malloc(2*sizeof(Token*));
  851         t[0]=malloc(sizeof(Token));
  852         t[1]=(Token*)0;
  853         t[0]->type=INT;
  854         t[0]->u.integer=it(body+5);
  855         putcont(sheet,it(body+1),it(body+3),0,t,0);
  856         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
  857         break;
  858       }
  859       /*}}}*/
  860       /* NUMBER        -- Floating point number            */ /*{{{*/
  861       case 0xE:
  862       {
  863         Token **t;
  864 
  865         assert(bodylen==13);
  866         initcell(sheet,it(body+1),it(body+3),0);
  867         t=malloc(2*sizeof(Token*));
  868         t[0]=malloc(sizeof(Token));
  869         t[1]=(Token*)0;
  870         t[0]->type=FLOAT;
  871         t[0]->u.flt=dbl((unsigned char*)body+5);
  872         putcont(sheet,it(body+1),it(body+3),0,t,0);
  873         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
  874         break;
  875       }
  876       /*}}}*/
  877       /* _("lL)abel")         -- Label cell                       */ /*{{{*/
  878       case 0xF:
  879       {
  880         Token **t;
  881 
  882         assert(bodylen>=6 && bodylen<=245);
  883         initcell(sheet,it(body+1),it(body+3),0);
  884         t=malloc(2*sizeof(Token*));
  885         t[0]=malloc(sizeof(Token));
  886         t[1]=(Token*)0;
  887         t[0]->type=STRING;
  888         t[0]->u.string=mystrmalloc(body+6);
  889         putcont(sheet,it(body+1),it(body+3),0,t,0);
  890         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
  891         break;
  892       }
  893       /*}}}*/
  894       /* FORMULA       -- Formula cell                     */ /*{{{*/
  895       case 0x10:
  896       {
  897         int i,j,size;
  898         int *offset;
  899         int tokens;
  900         Token **t;
  901 
  902         assert(bodylen>15);
  903         if ((offset=malloc(it(body+13)*sizeof(int)))==0) { err=_("Out of memory"); goto ouch; }
  904 #if WK1DEBUG
  905         fprintf(se,"FORMULA: &(%d,%d)=",it(body+1),it(body+3));
  906 #endif
  907         for (i=15,size=it(body+13)+15,j=0; i<size; ++i,++j)
  908         {
  909           offset[j]=i;
  910           switch(body[i])
  911           {
  912             case  0: /* double constant */ /*{{{*/
  913             {
  914               i+=8;
  915               break;
  916             }
  917             /*}}}*/
  918             case  1: /* variable */ /*{{{*/
  919             {
  920               i+=4;
  921               break;
  922             }
  923             /*}}}*/
  924             case  2: /* range */ /*{{{*/
  925             {
  926               i+=8;
  927               break;
  928             }
  929             /*}}}*/
  930             case  5: /* int constant */ /*{{{*/
  931             {
  932               i+=2;
  933               break;
  934             }
  935             /*}}}*/
  936             case 80: /* sum */ /*{{{*/
  937             {
  938               ++i;
  939               break;
  940             }
  941             /*}}}*/
  942           }
  943         }
  944 #if WK1DEBUG
  945         fprintf(se,", value %f",dbl((unsigned char*)body+5));
  946 #endif
  947         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
  948 #if WK1DEBUG
  949         fprintf(se,"\r\n");
  950 #endif
  951         tokens=0; unrpn(body,offset,j-1,(Token**)0,&tokens);
  952         if ((t=malloc(tokens*sizeof(Token*)))==(Token**)0)
  953         {
  954           free(offset);
  955           err=_("Out of memory");
  956           goto ouch;
  957         }
  958         for (; tokens; --tokens) t[tokens-1]=(Token*)0;
  959         if (unrpn(body,offset,j-1,t,&tokens)==-1)
  960         {
  961           err=_("Out of memory");
  962           tvecfree(t);
  963           goto ouch;
  964         }
  965         else
  966         {
  967 #if WK1DEBUG
  968         fprintf(se,"[<-- %d tokens]\r\n",tokens);
  969 #endif
  970         free(offset);
  971         initcell(sheet,it(body+1),it(body+3),0);
  972         SHEET(sheet,it(body+1),it(body+3),0)->value.type=FLOAT;
  973         SHEET(sheet,it(body+1),it(body+3),0)->value.u.flt=dbl((unsigned char*)body+5);
  974         putcont(sheet,it(body+1),it(body+3),0,t,0);
  975         }
  976         break;
  977       }
  978       /*}}}*/
  979       /* TABLE         -- Data table range                 */ /*{{{*/
  980       case 0x18: assert(bodylen==25); break;
  981       /*}}}*/
  982       /* ORANGE/QRANGE -- Query range                      */ /*{{{*/
  983       case 0x19: assert(bodylen==25); break;
  984       /*}}}*/
  985       /* PRANGE        -- Print range                      */ /*{{{*/
  986       case 0x1A: assert(bodylen==8); break;
  987       /*}}}*/
  988       /* SRANGE        -- Sort range                       */ /*{{{*/
  989       case 0x1B: assert(bodylen==8); break;
  990       /*}}}*/
  991       /* FRANGE        -- Fill range                       */ /*{{{*/
  992       case 0x1C: assert(bodylen==8); break;
  993       /*}}}*/
  994       /* KRANGE1       -- Primary sort key range           */ /*{{{*/
  995       case 0x1D: assert(bodylen==9); break;
  996       /*}}}*/
  997       /* HRANGE        -- Distribution range               */ /*{{{*/
  998       case 0x20: assert(bodylen==16); break;
  999       /*}}}*/
 1000       /* KRANGE2       -- Secondary sort key range         */ /*{{{*/
 1001       case 0x23: assert(bodylen==9); break;
 1002       /*}}}*/
 1003       /* PROTEC        -- Global protection                */ /*{{{*/
 1004       case 0x24:
 1005       {
 1006         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
 1007         /* (unsigned)body[0] means: */
 1008         /*    0: off                */
 1009         /* 0xff: on                 */
 1010         break;
 1011       }
 1012       /*}}}*/
 1013       /* FOOTER        -- Print footer                     */ /*{{{*/
 1014       case 0x25:
 1015       {
 1016         if (body[bodylen-1]!='\0' || bodylen<1 || bodylen>243) { err=_("Invalid record body length"); goto ouch; }
 1017         break;
 1018       }
 1019       /*}}}*/
 1020       /* HEADER        -- Print header                     */ /*{{{*/
 1021       case 0x26:
 1022       {
 1023         if (body[bodylen-1]!='\0' || bodylen<1 || bodylen>243) { err=_("Invalid record body length"); goto ouch; }
 1024         break;
 1025       }
 1026       /*}}}*/
 1027       /* SETUP         -- Print setup                      */ /*{{{*/
 1028       case 0x27: assert(bodylen==40); break;
 1029       /*}}}*/
 1030       /* MARGINS       -- Print margins code               */ /*{{{*/
 1031       case 0x28: assert(bodylen==10); break;
 1032       /*}}}*/
 1033       /* LABELFMT      -- Label alignment                  */ /*{{{*/
 1034       case 0x29:
 1035       {
 1036         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
 1037         /* (unsigned char)body[0] means: */
 1038         /* 0x22: right aligned labels    */
 1039         /* 0x27: left aligned labels     */
 1040         /* 0x5e: centered labels         */
 1041         break;
 1042       }
 1043       /*}}}*/
 1044       /* TITLES        -- Print borders                    */ /*{{{*/
 1045       case 0x2A: assert(bodylen==16); break;
 1046       /*}}}*/
 1047       /* GRAPH         -- Current graph settings           */ /*{{{*/
 1048       case 0x2D:
 1049       {
 1050         /* The specification says bodylen is 437, Excel 5 says it are */
 1051         /* 443 bytes.  We better silently ignore this.                */
 1052         break;
 1053       }
 1054       /*}}}*/
 1055       /* NGRAPH        -- Named graph settings             */ /*{{{*/
 1056       case 0x2E: assert(bodylen==453); break;
 1057       /*}}}*/
 1058       /* CALCCOUNT     -- Iteration count                  */ /*{{{*/
 1059       case 0x2F:
 1060       {
 1061         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
 1062         /* Do up to %d Iterations */
 1063         break;
 1064       }
 1065       /*}}}*/
 1066       /* UNFORMATTED   -- Formatted/unformatted print      */ /*{{{*/
 1067       case 0x30: assert(bodylen==1); break;
 1068       /*}}}*/
 1069       /* CURSORW12     -- Cursor location                  */ /*{{{*/
 1070       case 0x31:
 1071       {
 1072         if (bodylen!=1) { err=_("Invalid record body length"); goto ouch; }
 1073         /* (unsigned)body[0] means cursor in window: */
 1074         /* 1: 1                                      */
 1075         /* 2: 2                                      */
 1076         break;
 1077       }
 1078       /*}}}*/
 1079       /* WINDOW        -- Symphony window settings         */ /*{{{*/
 1080       case 0x32: assert(bodylen==144); break;
 1081       /*}}}*/
 1082       /* STRING        -- Value of string formula          */ /*{{{*/
 1083       case 0x33:
 1084       {
 1085         Token **t;
 1086 
 1087         assert(bodylen>=6 && bodylen<=245);
 1088         initcell(sheet,it(body+1),it(body+3),0);
 1089         t=malloc(2*sizeof(Token*));
 1090         t[0]=malloc(sizeof(Token));
 1091         t[1]=(Token*)0;
 1092         t[0]->type=STRING;
 1093         t[0]->u.string=mystrmalloc(body+5);
 1094         putcont(sheet,it(body+1),it(body+3),0,t,0);
 1095         format((unsigned char)body[0],SHEET(sheet,it(body+1),it(body+3),0));
 1096         break;
 1097       }
 1098       /*}}}*/
 1099       /* PASSWORD      -- File lockout (CHKSUM)            */ /*{{{*/
 1100       case 0x37: assert(bodylen==4); break;
 1101       /*}}}*/
 1102       /* LOCKED        -- Lock flag                        */ /*{{{*/
 1103       case 0x38: assert(bodylen==1); break;
 1104       /*}}}*/
 1105       /* QUERY         -- Symphony query settings          */ /*{{{*/
 1106       case 0x3C: assert(bodylen==127); break;
 1107       /*}}}*/
 1108       /* QUERYNAME     -- Query name                       */ /*{{{*/
 1109       case 0x3D: assert(bodylen==16); break;
 1110       /*}}}*/
 1111       /* PRINT         -- Symphony print record            */ /*{{{*/
 1112       case 0x3E: assert(bodylen==679); break;
 1113       /*}}}*/
 1114       /* PRINTNAME     -- Print record name                */ /*{{{*/
 1115       case 0x3F: assert(bodylen==16); break;
 1116       /*}}}*/
 1117       /* GRAPH2        -- Symphony graph record            */ /*{{{*/
 1118       case 0x40: assert(bodylen==499); break;
 1119       /*}}}*/
 1120       /* GRAPHNAME     -- Graph record name                */ /*{{{*/
 1121       case 0x41: assert(bodylen==16); break;
 1122       /*}}}*/
 1123       /* ZOOM          -- Orig coordinates expanded window */ /*{{{*/
 1124       case 0x42: assert(bodylen==9); break;
 1125       /*}}}*/
 1126       /* SYMSPLIT      -- No. of split windows             */ /*{{{*/
 1127       case 0x43: assert(bodylen==2); break;
 1128       /*}}}*/
 1129       /* NSROWS        -- No. of screen rows               */ /*{{{*/
 1130       case 0x44: assert(bodylen==2); break;
 1131       /*}}}*/
 1132       /* NSCOLS        -- No. of screen columns            */ /*{{{*/
 1133       case 0x45: assert(bodylen==2); break;
 1134       /*}}}*/
 1135       /* RULER         -- Named ruler range                */ /*{{{*/
 1136       case 0x46: assert(bodylen==25); break;
 1137       /*}}}*/
 1138       /* NNAME         -- Named sheet range                */ /*{{{*/
 1139       case 0x47: assert(bodylen==25); break;
 1140       /*}}}*/
 1141       /* ACOMM         -- Autoload.comm code               */ /*{{{*/
 1142       case 0x48: assert(bodylen==65); break;
 1143       /*}}}*/
 1144       /* AMACRO        -- Autoexecute macro address        */ /*{{{*/
 1145       case 0x49: assert(bodylen==8); break;
 1146       /*}}}*/
 1147       /* PARSE         -- Query parse information          */ /*{{{*/
 1148       case 0x4A: assert(bodylen==16); break;
 1149       /*}}}*/
 1150     }
 1151     /*}}}*/
 1152     if (!found_bof) { err=_("This is not a WK1 file"); goto ouch; }
 1153   }
 1154   if (!found_eof) err=_("File truncated");
 1155   ouch:
 1156   if (body) free(body);
 1157   if (fclose(fp)==EOF && err==(const char*)0) err=strerror(errno);
 1158   sheet->changed=0;
 1159   cachelabels(sheet);
 1160   forceupdate(sheet);
 1161   return err;
 1162 }
 1163 /*}}}*/