"Fossies" - the Fresh Open Source Software Archive 
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 /*}}}*/