1 | /* |
1 | /* |
2 | parse_formula.c - Part of psiconv, a PSION 5 file formats converter |
2 | parse_formula.c - Part of psiconv, a PSION 5 file formats converter |
3 | Copyright (c) 2001 Frodo Looijaard <frodol@dds.nl> |
3 | Copyright (c) 2001-2005 Frodo Looijaard <frodo@frodo.looijaard.name> |
4 | |
4 | |
5 | This program is free software; you can redistribute it and/or modify |
5 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by |
6 | it under the terms of the GNU General Public License as published by |
7 | the Free Software Foundation; either version 2 of the License, or |
7 | the Free Software Foundation; either version 2 of the License, or |
8 | (at your option) any later version. |
8 | (at your option) any later version. |
… | |
… | |
22 | |
22 | |
23 | #include <stdlib.h> |
23 | #include <stdlib.h> |
24 | |
24 | |
25 | #include "parse_routines.h" |
25 | #include "parse_routines.h" |
26 | #include "error.h" |
26 | #include "error.h" |
|
|
27 | |
|
|
28 | #ifdef DMALLOC |
|
|
29 | #include <dmalloc.h> |
|
|
30 | #endif |
|
|
31 | |
27 | |
32 | |
28 | struct formula_element |
33 | struct formula_element |
29 | { |
34 | { |
30 | psiconv_formula_type_t formula_type; |
35 | psiconv_formula_type_t formula_type; |
31 | int number_of_args; |
36 | int number_of_args; |
… | |
… | |
46 | {psiconv_formula_op_mul,2,"*"}, |
51 | {psiconv_formula_op_mul,2,"*"}, |
47 | {psiconv_formula_op_div,2,"/"}, |
52 | {psiconv_formula_op_div,2,"/"}, |
48 | {psiconv_formula_op_pow,2,"^"}, |
53 | {psiconv_formula_op_pow,2,"^"}, |
49 | {psiconv_formula_op_pos,1,"+"}, |
54 | {psiconv_formula_op_pos,1,"+"}, |
50 | {psiconv_formula_op_neg,1,"-"}, |
55 | {psiconv_formula_op_neg,1,"-"}, |
51 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
56 | {psiconv_formula_op_not,1,"NOT"}, |
52 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
57 | {psiconv_formula_op_and,2,"AND"}, |
53 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, /* 10 */ |
58 | {psiconv_formula_op_or,2,"OR"}, /* 10 */ |
54 | {psiconv_formula_op_con,2,"&"}, |
59 | {psiconv_formula_op_con,2,"&"}, |
55 | {psiconv_formula_op_bra,1,"{}"}, |
60 | {psiconv_formula_op_bra,1,"()"}, |
56 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
61 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
57 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
62 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
58 | {psiconv_formula_mark_eof,0,"End of formula"}, |
63 | {psiconv_formula_mark_eof,0,"End of formula"}, |
59 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
64 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
60 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
65 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
… | |
… | |
284 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
289 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
285 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
290 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
286 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
291 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
287 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
292 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
288 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
293 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
289 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
|
|
290 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
|
|
291 | {psiconv_formula_unknown,0,"*UNKNOWN*"}, |
|
|
292 | {psiconv_formula_unknown,0,"*UNKNOWN*"}}; |
294 | {psiconv_formula_unknown,0,"*UNKNOWN*"}}; |
293 | |
295 | |
294 | static psiconv_string_t psiconv_read_sheet_string(const psiconv_buffer buf, |
|
|
295 | int lev, |
|
|
296 | psiconv_u32 off,int *length, int *status) |
|
|
297 | { |
|
|
298 | int stringlen,i,len,localstatus; |
|
|
299 | psiconv_string_t result; |
|
|
300 | char *res_copy; |
|
|
301 | |
|
|
302 | psiconv_progress(lev+1,off,"Going to read a sheet string"); |
|
|
303 | |
|
|
304 | stringlen = psiconv_read_u8(buf,lev+2,off,&localstatus); |
|
|
305 | if (localstatus) |
|
|
306 | goto ERROR1; |
|
|
307 | psiconv_debug(lev+2,off,"Length: %i",stringlen); |
|
|
308 | len = 1; |
|
|
309 | |
|
|
310 | result = malloc(stringlen + 1); |
|
|
311 | if (!result) |
|
|
312 | goto ERROR1; |
|
|
313 | for (i = 0; (i < stringlen) && !localstatus; i++) |
|
|
314 | result[i] = psiconv_read_u8(buf,lev,off+i+len,&localstatus); |
|
|
315 | if (localstatus) |
|
|
316 | goto ERROR2; |
|
|
317 | result[stringlen] = 0; |
|
|
318 | len += stringlen; |
|
|
319 | |
|
|
320 | res_copy = psiconv_make_printable(result); |
|
|
321 | if (!res_copy) |
|
|
322 | goto ERROR2; |
|
|
323 | psiconv_debug(lev+2,off,"Contents: `%s'",res_copy); |
|
|
324 | free(res_copy); |
|
|
325 | |
|
|
326 | if (length) |
|
|
327 | *length = len; |
|
|
328 | |
|
|
329 | if (status) |
|
|
330 | *status = 0; |
|
|
331 | |
|
|
332 | psiconv_progress(lev+1,off+len-1,"End of sheet string (total length: %08x)", |
|
|
333 | len); |
|
|
334 | |
|
|
335 | return result; |
|
|
336 | |
|
|
337 | |
|
|
338 | ERROR2: |
|
|
339 | free(result); |
|
|
340 | ERROR1: |
|
|
341 | psiconv_warn(lev+1,off,"Reading of sheet string failed"); |
|
|
342 | if (status) |
|
|
343 | *status = localstatus; |
|
|
344 | if (length) |
|
|
345 | *length = 0; |
|
|
346 | return NULL; |
|
|
347 | } |
|
|
348 | |
|
|
349 | |
|
|
350 | static int psiconv_parse_sheet_ref(const psiconv_buffer buf,int lev, |
296 | static int psiconv_parse_sheet_ref(const psiconv_config config, |
|
|
297 | const psiconv_buffer buf,int lev, |
351 | psiconv_u32 off, int *length, |
298 | psiconv_u32 off, int *length, |
352 | psiconv_sheet_ref_t *result) |
299 | psiconv_sheet_ref_t *result) |
353 | { |
300 | { |
354 | int res; |
301 | int res; |
355 | psiconv_u16 temp; |
302 | psiconv_u16 temp; |
356 | |
303 | |
357 | psiconv_progress(lev+1,off,"Going to read a sheet ref"); |
304 | psiconv_progress(config,lev+1,off,"Going to read a sheet ref"); |
358 | psiconv_progress(lev+2,off,"Going to read the offset encoding"); |
305 | psiconv_progress(config,lev+2,off,"Going to read the offset encoding"); |
359 | temp = psiconv_read_u16(buf,lev+2,off,&res); |
306 | temp = psiconv_read_u16(config,buf,lev+2,off,&res); |
360 | if (res) { |
307 | if (res) { |
361 | if (length) |
308 | if (length) |
362 | *length = 0; |
309 | *length = 0; |
363 | return res; |
310 | return res; |
364 | } |
311 | } |
365 | psiconv_debug(lev+2,off,"Encoded word: %04x",temp); |
312 | psiconv_debug(config,lev+2,off,"Encoded word: %04x",temp); |
366 | result->absolute = (temp & 0x4000)?psiconv_bool_true:psiconv_bool_false; |
313 | result->absolute = (temp & 0x4000)?psiconv_bool_true:psiconv_bool_false; |
367 | result->offset = (temp & 0x3fff) * ((temp & 0x8000)?-1:1); |
314 | result->offset = (temp & 0x3fff) * ((temp & 0x8000)?-1:1); |
368 | psiconv_debug(lev+2,off,"Reference: %s offset %d", |
315 | psiconv_debug(config,lev+2,off,"Reference: %s offset %d", |
369 | result->absolute?"absolute":"relative",result->offset); |
316 | result->absolute?"absolute":"relative",result->offset); |
370 | if (length) |
317 | if (length) |
371 | *length = 2; |
318 | *length = 2; |
372 | return 0; |
319 | return 0; |
373 | } |
320 | } |
374 | |
321 | |
375 | static int psiconv_parse_sheet_cell_reference(const psiconv_buffer buf,int lev, |
322 | static int psiconv_parse_sheet_cell_reference(const psiconv_config config, |
|
|
323 | const psiconv_buffer buf,int lev, |
376 | psiconv_u32 off, int *length, |
324 | psiconv_u32 off, int *length, |
377 | psiconv_sheet_cell_reference_t *result) |
325 | psiconv_sheet_cell_reference_t *result) |
378 | { |
326 | { |
379 | int len = 0; |
327 | int len = 0; |
380 | int leng,res; |
328 | int leng,res; |
381 | psiconv_u8 temp; |
329 | psiconv_u8 temp; |
382 | |
330 | |
383 | psiconv_progress(lev+1,off+len,"Going to read a sheet cell reference"); |
331 | psiconv_progress(config,lev+1,off+len,"Going to read a sheet cell reference"); |
384 | psiconv_progress(lev+2,off+len,"Going to read the row reference"); |
332 | psiconv_progress(config,lev+2,off+len,"Going to read the row reference"); |
385 | if ((res = psiconv_parse_sheet_ref(buf,lev+2,off+len,&leng,&result->row))) |
333 | if ((res = psiconv_parse_sheet_ref(config,buf,lev+2,off+len,&leng,&result->row))) |
386 | goto ERROR; |
334 | goto ERROR; |
387 | len += leng; |
335 | len += leng; |
388 | psiconv_progress(lev+2,off+len,"Going to read the column reference"); |
336 | psiconv_progress(config,lev+2,off+len,"Going to read the column reference"); |
389 | if ((res = psiconv_parse_sheet_ref(buf,lev+2,off+len,&leng,&result->column))) |
337 | if ((res = psiconv_parse_sheet_ref(config,buf,lev+2,off+len,&leng,&result->column))) |
390 | goto ERROR; |
338 | goto ERROR; |
391 | len += leng; |
339 | len += leng; |
392 | |
340 | |
393 | psiconv_progress(lev+2,off+len, |
341 | psiconv_progress(config,lev+2,off+len, |
394 | "Going to read the trailing byte (%02x expected)",0); |
342 | "Going to read the trailing byte (%02x expected)",0); |
395 | temp = psiconv_read_u8(buf,lev+2,off+len,&res); |
343 | temp = psiconv_read_u8(config,buf,lev+2,off+len,&res); |
396 | if (res) |
344 | if (res) |
397 | goto ERROR; |
345 | goto ERROR; |
398 | if (temp != 0) { |
346 | if (temp != 0) { |
399 | psiconv_warn(lev+2,off+len,"Unknown byte in cell reference (ignored"); |
347 | psiconv_warn(config,lev+2,off+len,"Unknown byte in cell reference (ignored"); |
400 | psiconv_debug(lev+2,off+len,"Trailing byte: %02x",temp); |
348 | psiconv_debug(config,lev+2,off+len,"Trailing byte: %02x",temp); |
401 | } |
349 | } |
402 | len ++; |
350 | len ++; |
403 | psiconv_progress(lev,off+len-1, |
351 | psiconv_progress(config,lev,off+len-1, |
404 | "End of cell reference (total length: %08x)", len); |
352 | "End of cell reference (total length: %08x)", len); |
405 | if (length) |
353 | if (length) |
406 | *length = len; |
354 | *length = len; |
407 | return 0; |
355 | return 0; |
408 | ERROR: |
356 | ERROR: |
409 | if (length) |
357 | if (length) |
410 | *length = 0; |
358 | *length = 0; |
411 | return res; |
359 | return res; |
412 | } |
360 | } |
413 | |
361 | |
414 | static int psiconv_parse_sheet_cell_block(const psiconv_buffer buf,int lev, |
362 | static int psiconv_parse_sheet_cell_block(const psiconv_config config, |
|
|
363 | const psiconv_buffer buf,int lev, |
415 | psiconv_u32 off, int *length, |
364 | psiconv_u32 off, int *length, |
416 | psiconv_sheet_cell_block_t *result) |
365 | psiconv_sheet_cell_block_t *result) |
417 | { |
366 | { |
418 | int len = 0; |
367 | int len = 0; |
419 | int leng,res; |
368 | int leng,res; |
420 | |
369 | |
421 | psiconv_progress(lev+1,off+len,"Going to read a sheet cell block"); |
370 | psiconv_progress(config,lev+1,off+len,"Going to read a sheet cell block"); |
422 | psiconv_progress(lev+2,off+len,"Going to read the first cell"); |
371 | psiconv_progress(config,lev+2,off+len,"Going to read the first cell"); |
423 | if ((res = psiconv_parse_sheet_cell_reference(buf,lev+2,off+len,&leng, |
372 | if ((res = psiconv_parse_sheet_cell_reference(config,buf,lev+2,off+len,&leng, |
424 | &result->first))) |
373 | &result->first))) |
425 | goto ERROR; |
374 | goto ERROR; |
426 | len += leng; |
375 | len += leng; |
427 | psiconv_progress(lev+2,off+len,"Going to read the last cell"); |
376 | psiconv_progress(config,lev+2,off+len,"Going to read the last cell"); |
428 | if ((res = psiconv_parse_sheet_cell_reference(buf,lev+2,off+len,&leng, |
377 | if ((res = psiconv_parse_sheet_cell_reference(config,buf,lev+2,off+len,&leng, |
429 | &result->last))) |
378 | &result->last))) |
430 | goto ERROR; |
379 | goto ERROR; |
431 | len += leng; |
380 | len += leng; |
432 | psiconv_progress(lev,off+len-1, |
381 | psiconv_progress(config,lev,off+len-1, |
433 | "End of cell block (total length: %08x)", len); |
382 | "End of cell block (total length: %08x)", len); |
434 | if (length) |
383 | if (length) |
435 | *length = len; |
384 | *length = len; |
436 | return 0; |
385 | return 0; |
437 | ERROR: |
386 | ERROR: |
438 | if (length) |
387 | if (length) |
439 | *length = 0; |
388 | *length = 0; |
440 | return res; |
389 | return res; |
441 | } |
390 | } |
442 | |
391 | |
443 | static int psiconv_parse_formula_element_list(const psiconv_buffer buf, int lev, |
392 | static int psiconv_parse_formula_element_list(const psiconv_config config, |
|
|
393 | const psiconv_buffer buf, int lev, |
444 | psiconv_u32 off, int *length, |
394 | psiconv_u32 off, int *length, |
445 | psiconv_formula *result, |
395 | psiconv_formula *result, |
446 | psiconv_u32 maxlen) |
396 | psiconv_u32 maxlen) |
447 | { |
397 | { |
448 | int res=0; |
398 | int res=0; |
449 | int len=0; |
399 | int len=0; |
450 | int leng; |
400 | int leng; |
451 | int eof = 0; |
401 | int eof = 0; |
452 | psiconv_u8 marker,submarker; |
402 | psiconv_u8 marker,submarker,submarker2; |
453 | psiconv_formula_list formula_stack; |
403 | psiconv_formula_list formula_stack; |
454 | psiconv_formula formula,subformula,subformula1,subformula2, |
404 | psiconv_formula formula,subformula,subformula1,subformula2, |
455 | subformula3,subformula4; |
405 | subformula3,subformula4; |
456 | psiconv_u16 temp,nr_of_subs; |
406 | psiconv_u16 temp,nr_of_subs; |
457 | |
407 | |
458 | psiconv_progress(lev+1,off,"Going to read a formula element list"); |
408 | psiconv_progress(config,lev+1,off,"Going to read a formula element list"); |
459 | if (!(*result = malloc(sizeof(**result)))) |
409 | if (!(*result = malloc(sizeof(**result)))) |
460 | goto ERROR1; |
410 | goto ERROR1; |
461 | if (!(formula_stack = psiconv_list_new(sizeof(struct psiconv_formula_s)))) |
411 | if (!(formula_stack = psiconv_list_new(sizeof(struct psiconv_formula_s)))) |
462 | goto ERROR2; |
412 | goto ERROR2; |
463 | if (!(formula = malloc(sizeof(*formula)))) |
413 | if (!(formula = malloc(sizeof(*formula)))) |
… | |
… | |
476 | if (!(subformula4 = malloc(sizeof(*subformula4)))) |
426 | if (!(subformula4 = malloc(sizeof(*subformula4)))) |
477 | goto ERROR7; |
427 | goto ERROR7; |
478 | subformula4->type = psiconv_formula_unknown; |
428 | subformula4->type = psiconv_formula_unknown; |
479 | |
429 | |
480 | while (!eof && len+off < maxlen) { |
430 | while (!eof && len+off < maxlen) { |
481 | psiconv_progress(lev+3,off+len,"Going to read a formula item marker"); |
431 | psiconv_progress(config,lev+3,off+len,"Going to read a formula item marker"); |
482 | marker = psiconv_read_u8(buf,lev+2,off+len,&res); |
432 | marker = psiconv_read_u8(config,buf,lev+2,off+len,&res); |
483 | if (res) |
433 | if (res) |
484 | goto ERROR8; |
434 | goto ERROR8; |
485 | psiconv_debug(lev+3,off+len,"Marker: %02x (%s)",marker, |
435 | psiconv_debug(config,lev+3,off+len,"Marker: %02x (%s)",marker, |
486 | formula_elements[marker].name); |
436 | formula_elements[marker].name); |
487 | len ++; |
437 | len ++; |
488 | |
438 | |
489 | if (formula_elements[marker].formula_type == psiconv_formula_unknown) { |
439 | if (formula_elements[marker].formula_type == psiconv_formula_unknown) { |
490 | psiconv_warn(lev+3,off+len,"Unknown formula marker found!"); |
440 | psiconv_error(config,lev+3,off+len,"Unknown formula marker found!"); |
491 | goto ERROR8; |
441 | goto ERROR8; |
492 | } else if ((formula_elements[marker].formula_type == |
442 | } else if ((formula_elements[marker].formula_type == |
493 | psiconv_formula_mark_eof) || |
443 | psiconv_formula_mark_eof) || |
494 | (formula_elements[marker].formula_type == |
444 | (formula_elements[marker].formula_type == |
495 | psiconv_formula_mark_opend) || |
445 | psiconv_formula_mark_opend) || |
496 | (formula_elements[marker].formula_type == |
446 | (formula_elements[marker].formula_type == |
497 | psiconv_formula_mark_opsep)) { |
447 | psiconv_formula_mark_opsep)) { |
498 | len--; |
448 | len--; |
499 | psiconv_progress(lev+3,off+len,"End of this formula list"); |
449 | psiconv_progress(config,lev+3,off+len,"End of this formula list"); |
500 | eof = 1; |
450 | eof = 1; |
501 | } else if (formula_elements[marker].formula_type == |
451 | } else if (formula_elements[marker].formula_type == |
502 | psiconv_formula_dat_int) { |
452 | psiconv_formula_dat_int) { |
503 | psiconv_progress(lev+3,off+len,"Next item: an integer"); |
453 | psiconv_progress(config,lev+3,off+len,"Next item: an integer"); |
504 | formula->data.dat_int = psiconv_read_u32(buf,lev+2,off+len,&res); |
454 | formula->data.dat_int = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
505 | if (res) |
455 | if (res) |
506 | goto ERROR8; |
456 | goto ERROR8; |
507 | formula->type = formula_elements[marker].formula_type; |
457 | formula->type = formula_elements[marker].formula_type; |
508 | psiconv_debug(lev+3,off+len,"Value: %08x",formula->data.dat_int); |
458 | psiconv_debug(config,lev+3,off+len,"Value: %08x",formula->data.dat_int); |
509 | len += 4; |
459 | len += 4; |
510 | if ((res = psiconv_list_add(formula_stack,formula))) |
460 | if ((res = psiconv_list_add(formula_stack,formula))) |
511 | goto ERROR8; |
461 | goto ERROR8; |
512 | formula->type = psiconv_formula_unknown; |
462 | formula->type = psiconv_formula_unknown; |
513 | } else if (formula_elements[marker].formula_type == |
463 | } else if (formula_elements[marker].formula_type == |
514 | psiconv_formula_dat_float) { |
464 | psiconv_formula_dat_float) { |
515 | psiconv_progress(lev+3,off+len,"Next item: a float"); |
465 | psiconv_progress(config,lev+3,off+len,"Next item: a float"); |
516 | formula->data.dat_float = psiconv_read_float(buf,lev+2,off+len,&leng, |
466 | formula->data.dat_float = psiconv_read_float(config,buf,lev+2,off+len,&leng, |
517 | &res); |
467 | &res); |
518 | if (res) |
468 | if (res) |
519 | goto ERROR8; |
469 | goto ERROR8; |
520 | formula->type = formula_elements[marker].formula_type; |
470 | formula->type = formula_elements[marker].formula_type; |
521 | psiconv_debug(lev+3,off+len,"Value: %f",formula->data.dat_float); |
471 | psiconv_debug(config,lev+3,off+len,"Value: %f",formula->data.dat_float); |
522 | len += leng; |
472 | len += leng; |
523 | if ((res = psiconv_list_add(formula_stack,formula))) |
473 | if ((res = psiconv_list_add(formula_stack,formula))) |
524 | goto ERROR8; |
474 | goto ERROR8; |
525 | formula->type = psiconv_formula_unknown; |
475 | formula->type = psiconv_formula_unknown; |
526 | } else if (formula_elements[marker].formula_type == |
476 | } else if (formula_elements[marker].formula_type == |
527 | psiconv_formula_dat_cellref) { |
477 | psiconv_formula_dat_cellref) { |
528 | psiconv_progress(lev+3,off+len,"Next item: a cell reference"); |
478 | psiconv_progress(config,lev+3,off+len,"Next item: a cell reference"); |
529 | if ((res = psiconv_parse_sheet_cell_reference(buf,lev+2,off+len,&leng, |
479 | if ((res = psiconv_parse_sheet_cell_reference(config,buf,lev+2,off+len,&leng, |
530 | &formula->data.dat_cellref))) |
480 | &formula->data.dat_cellref))) |
531 | goto ERROR8; |
481 | goto ERROR8; |
532 | formula->type = formula_elements[marker].formula_type; |
482 | formula->type = formula_elements[marker].formula_type; |
533 | len += leng; |
483 | len += leng; |
534 | if ((res = psiconv_list_add(formula_stack,formula))) |
484 | if ((res = psiconv_list_add(formula_stack,formula))) |
… | |
… | |
536 | formula->type = psiconv_formula_unknown; |
486 | formula->type = psiconv_formula_unknown; |
537 | } else if ((formula_elements[marker].formula_type == |
487 | } else if ((formula_elements[marker].formula_type == |
538 | psiconv_formula_dat_cellblock) || |
488 | psiconv_formula_dat_cellblock) || |
539 | (formula_elements[marker].formula_type == |
489 | (formula_elements[marker].formula_type == |
540 | psiconv_formula_dat_vcellblock)) { |
490 | psiconv_formula_dat_vcellblock)) { |
541 | psiconv_progress(lev+3,off+len,"Next item: a cell block"); |
491 | psiconv_progress(config,lev+3,off+len,"Next item: a cell block"); |
542 | if ((res = psiconv_parse_sheet_cell_block(buf,lev+2,off+len,&leng, |
492 | if ((res = psiconv_parse_sheet_cell_block(config,buf,lev+2,off+len,&leng, |
543 | &formula->data.dat_cellblock))) |
493 | &formula->data.dat_cellblock))) |
544 | goto ERROR8; |
494 | goto ERROR8; |
545 | formula->type = formula_elements[marker].formula_type; |
495 | formula->type = formula_elements[marker].formula_type; |
546 | len += leng; |
496 | len += leng; |
547 | if ((res = psiconv_list_add(formula_stack,formula))) |
497 | if ((res = psiconv_list_add(formula_stack,formula))) |
548 | goto ERROR8; |
498 | goto ERROR8; |
549 | formula->type = psiconv_formula_unknown; |
499 | formula->type = psiconv_formula_unknown; |
550 | } else if (formula_elements[marker].formula_type == |
500 | } else if (formula_elements[marker].formula_type == |
551 | psiconv_formula_dat_string) { |
501 | psiconv_formula_dat_string) { |
552 | psiconv_progress(lev+3,off+len,"Next item: a string"); |
502 | psiconv_progress(config,lev+3,off+len,"Next item: a string"); |
553 | formula->data.dat_string = |
503 | formula->data.dat_string = |
554 | psiconv_read_sheet_string(buf,lev+2,off+len,&leng,&res); |
504 | psiconv_read_short_string(config,buf,lev+2,off+len,&leng,&res); |
555 | if (res) |
505 | if (res) |
556 | goto ERROR8; |
506 | goto ERROR8; |
557 | formula->type = formula_elements[marker].formula_type; |
507 | formula->type = formula_elements[marker].formula_type; |
558 | len += leng; |
508 | len += leng; |
559 | if ((res = psiconv_list_add(formula_stack,formula))) |
509 | if ((res = psiconv_list_add(formula_stack,formula))) |
560 | goto ERROR8; |
510 | goto ERROR8; |
561 | formula->type = psiconv_formula_unknown; |
511 | formula->type = psiconv_formula_unknown; |
562 | } else if ((formula_elements[marker].formula_type == |
512 | } else if ((formula_elements[marker].formula_type == |
563 | psiconv_formula_dat_var) || |
513 | psiconv_formula_dat_var)) { |
564 | (formula_elements[marker].formula_type == |
514 | psiconv_progress(config,lev+3,off+len,"Next item: a variable reference"); |
565 | psiconv_formula_dat_vcellblock)) { |
515 | formula->data.dat_variable = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
566 | psiconv_warn(lev+3,off+len,"Not yet supported formula mark!"); |
516 | if (res) |
567 | goto ERROR8; |
517 | goto ERROR8; |
|
|
518 | formula->type = formula_elements[marker].formula_type; |
|
|
519 | len += 4; |
|
|
520 | if ((res = psiconv_list_add(formula_stack,formula))) |
|
|
521 | goto ERROR8; |
|
|
522 | formula->type = psiconv_formula_unknown; |
568 | } else if (formula_elements[marker].number_of_args == -1) { |
523 | } else if (formula_elements[marker].number_of_args == -1) { |
569 | psiconv_progress(lev+3,off+len,"Going to parse a vararg function"); |
524 | psiconv_progress(config,lev+3,off+len,"Going to parse a vararg function"); |
570 | if (!(formula->data.fun_operands = |
525 | if (!(formula->data.fun_operands = |
571 | psiconv_list_new(sizeof(*formula)))) |
526 | psiconv_list_new(sizeof(*formula)))) |
572 | goto ERROR8; |
527 | goto ERROR8; |
573 | formula->type = formula_elements[marker].formula_type; |
528 | formula->type = formula_elements[marker].formula_type; |
574 | nr_of_subs = 0; |
529 | nr_of_subs = 0; |
575 | do { |
530 | do { |
576 | nr_of_subs ++; |
531 | nr_of_subs ++; |
577 | psiconv_progress(lev+4,off+len,"Going to read vararg argument %d", |
532 | psiconv_progress(config,lev+4,off+len,"Going to read vararg argument %d", |
578 | nr_of_subs); |
533 | nr_of_subs); |
579 | if ((res = psiconv_parse_formula_element_list(buf,lev+4,off+len,&leng, |
534 | if ((res = psiconv_parse_formula_element_list(config,buf,lev+4,off+len,&leng, |
580 | &subformula,maxlen))) |
535 | &subformula,maxlen))) |
581 | goto ERROR8; |
536 | goto ERROR8; |
582 | len += leng; |
537 | len += leng; |
583 | if ((res = psiconv_list_add(formula->data.fun_operands,subformula))) { |
538 | if ((res = psiconv_list_add(formula->data.fun_operands,subformula))) { |
584 | psiconv_free_formula(subformula); |
539 | psiconv_free_formula(subformula); |
585 | goto ERROR8; |
540 | goto ERROR8; |
586 | } |
541 | } |
587 | free(subformula); |
542 | free(subformula); |
588 | psiconv_progress(lev+4,off+len,"Going to read the next marker"); |
543 | psiconv_progress(config,lev+4,off+len,"Going to read the next marker"); |
589 | submarker = psiconv_read_u8(buf,lev+4,off+len,&res); |
544 | submarker = psiconv_read_u8(config,buf,lev+4,off+len,&res); |
590 | len ++; |
545 | len ++; |
591 | if (res) |
546 | if (res) |
592 | goto ERROR8; |
547 | goto ERROR8; |
|
|
548 | submarker2 = psiconv_read_u8(config,buf,lev+4,off+len,&res); |
|
|
549 | if (res) |
|
|
550 | goto ERROR8; |
593 | } while (formula_elements[submarker].formula_type |
551 | } while ((formula_elements[submarker].formula_type |
594 | == psiconv_formula_mark_opsep); |
552 | == psiconv_formula_mark_opsep) && |
|
|
553 | (formula_elements[submarker2].formula_type |
|
|
554 | != psiconv_formula_mark_opend)); |
|
|
555 | if ((formula_elements[submarker].formula_type == |
|
|
556 | psiconv_formula_mark_opsep) && |
|
|
557 | (formula_elements[submarker2].formula_type == |
|
|
558 | psiconv_formula_mark_opend)) { |
|
|
559 | submarker=submarker2; |
|
|
560 | len++; |
|
|
561 | } |
595 | if (formula_elements[submarker].formula_type |
562 | if (formula_elements[submarker].formula_type |
596 | != psiconv_formula_mark_opend) { |
563 | != psiconv_formula_mark_opend) { |
597 | psiconv_warn(lev+3,off+len,"Formula corrupted!"); |
564 | psiconv_error(config,lev+3,off+len,"Formula corrupted!"); |
598 | psiconv_debug(lev+3,off+len,"Found unexpected marker %02x",submarker); |
565 | psiconv_debug(config,lev+3,off+len,"Found unexpected marker %02x",submarker); |
599 | goto ERROR8; |
566 | goto ERROR8; |
600 | } |
567 | } |
601 | psiconv_progress(lev+3,off+len,"Going to read the repeated marker %02x", |
568 | psiconv_progress(config,lev+3,off+len,"Going to read the repeated marker %02x", |
602 | marker); |
569 | marker); |
603 | submarker = psiconv_read_u8(buf,lev+3,off+len,&res); |
570 | submarker = psiconv_read_u8(config,buf,lev+3,off+len,&res); |
604 | if (res) |
571 | if (res) |
605 | goto ERROR8; |
572 | goto ERROR8; |
606 | if (submarker != marker) { |
573 | if (submarker != marker) { |
607 | psiconv_warn(lev+3,off+len,"Formula corrupted!"); |
574 | psiconv_error(config,lev+3,off+len,"Formula corrupted!"); |
608 | psiconv_debug(lev+3,off+len,"Expected marker %02x, found %02x", |
575 | psiconv_debug(config,lev+3,off+len,"Expected marker %02x, found %02x", |
609 | marker,submarker); |
576 | marker,submarker); |
610 | goto ERROR8; |
577 | goto ERROR8; |
611 | } |
578 | } |
612 | len++; |
579 | len++; |
613 | psiconv_progress(lev+3,off+len, |
580 | psiconv_progress(config,lev+3,off+len, |
614 | "Going to read the number of arguments (%d expected)", |
581 | "Going to read the number of arguments (%d expected)", |
615 | nr_of_subs); |
582 | nr_of_subs); |
616 | temp = psiconv_read_u16(buf,lev+3,off+len,&res); |
583 | temp = psiconv_read_u16(config,buf,lev+3,off+len,&res); |
617 | if (res) |
584 | if (res) |
618 | goto ERROR8; |
585 | goto ERROR8; |
619 | if (temp != nr_of_subs) { |
586 | if (temp != nr_of_subs) { |
620 | psiconv_warn(lev+3,off+len,"Formula corrupted!"); |
587 | psiconv_error(config,lev+3,off+len,"Formula corrupted!"); |
621 | psiconv_debug(lev+3,off+len, |
588 | psiconv_debug(config,lev+3,off+len, |
622 | "Read %d arguments, but formula says there are %d", |
589 | "Read %d arguments, but formula says there are %d", |
623 | nr_of_subs,temp); |
590 | nr_of_subs,temp); |
624 | goto ERROR8; |
591 | goto ERROR8; |
625 | } |
592 | } |
626 | len += 2; |
593 | len += 2; |
… | |
… | |
661 | subformula4->type = subformula3->type = subformula2->type = |
628 | subformula4->type = subformula3->type = subformula2->type = |
662 | subformula1->type = formula->type = psiconv_formula_unknown; |
629 | subformula1->type = formula->type = psiconv_formula_unknown; |
663 | } |
630 | } |
664 | } |
631 | } |
665 | if ((len+off > maxlen) || !eof) { |
632 | if ((len+off > maxlen) || !eof) { |
666 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
633 | psiconv_error(config,lev+2,off+len,"Formula corrupted!"); |
667 | psiconv_debug(lev+2,off+len,"Expected end: %04x, found end: %04x", |
634 | psiconv_debug(config,lev+2,off+len,"Expected end: %04x, found end: %04x", |
668 | maxlen,len+off); |
635 | maxlen,len+off); |
669 | goto ERROR8; |
636 | goto ERROR8; |
670 | } |
637 | } |
671 | if ((psiconv_list_length(formula_stack)) != 1) { |
638 | if ((psiconv_list_length(formula_stack)) != 1) { |
672 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
639 | psiconv_error(config,lev+2,off+len,"Formula corrupted!"); |
673 | psiconv_debug(lev+2,off+len,"More than one item left on the stack (%d)", |
640 | psiconv_debug(config,lev+2,off+len,"More than one item left on the stack (%d)", |
674 | psiconv_list_length(formula_stack)); |
641 | psiconv_list_length(formula_stack)); |
675 | goto ERROR8; |
642 | goto ERROR8; |
676 | } |
643 | } |
677 | if ((res = psiconv_list_pop(formula_stack,*result))) |
644 | if ((res = psiconv_list_pop(formula_stack,*result))) |
678 | goto ERROR8; |
645 | goto ERROR8; |
… | |
… | |
680 | free(formula); |
647 | free(formula); |
681 | |
648 | |
682 | if (length) |
649 | if (length) |
683 | *length = len; |
650 | *length = len; |
684 | |
651 | |
685 | psiconv_progress(lev,off+len-1, |
652 | psiconv_progress(config,lev,off+len-1, |
686 | "End of formula element list (total length: %08x)", len); |
653 | "End of formula element list (total length: %08x)", len); |
687 | return 0; |
654 | return 0; |
688 | |
655 | |
689 | ERROR8: |
656 | ERROR8: |
690 | psiconv_free_formula(subformula4); |
657 | psiconv_free_formula(subformula4); |
… | |
… | |
699 | ERROR3: |
666 | ERROR3: |
700 | psiconv_free_formula_list(formula_stack); |
667 | psiconv_free_formula_list(formula_stack); |
701 | ERROR2: |
668 | ERROR2: |
702 | free (*result); |
669 | free (*result); |
703 | ERROR1: |
670 | ERROR1: |
704 | psiconv_warn(lev+1,off,"Reading of formula element list failed"); |
671 | psiconv_error(config,lev+1,off,"Reading of formula element list failed"); |
705 | if (length) |
672 | if (length) |
706 | *length = 0; |
673 | *length = 0; |
707 | if (!res) |
674 | if (!res) |
708 | return -PSICONV_E_NOMEM; |
675 | return -PSICONV_E_NOMEM; |
709 | else |
676 | else |
… | |
… | |
711 | } |
678 | } |
712 | |
679 | |
713 | |
680 | |
714 | |
681 | |
715 | |
682 | |
716 | int psiconv_parse_formula(const psiconv_buffer buf, int lev, |
683 | int psiconv_parse_formula(const psiconv_config config, |
|
|
684 | const psiconv_buffer buf, int lev, |
717 | psiconv_u32 off, int *length, |
685 | psiconv_u32 off, int *length, |
718 | psiconv_formula *result) |
686 | psiconv_formula *result) |
719 | { |
687 | { |
720 | int res=0; |
688 | int res=0; |
721 | int len=0; |
689 | int len=0; |
722 | int leng; |
690 | int leng; |
723 | psiconv_u32 bytelen,formula_end; |
691 | psiconv_u32 bytelen,formula_end; |
724 | psiconv_u8 temp; |
692 | psiconv_u8 temp; |
725 | |
693 | |
726 | psiconv_progress(lev+1,off,"Going to read a formula"); |
694 | psiconv_progress(config,lev+1,off,"Going to read a formula"); |
727 | |
695 | |
728 | psiconv_progress(lev+2,off+len, |
696 | psiconv_progress(config,lev+2,off+len, |
729 | "Going to read the formula byte length"); |
697 | "Going to read the formula byte length"); |
730 | bytelen = psiconv_read_S(buf,lev+2,off+len,&leng,&res); |
698 | bytelen = psiconv_read_S(config,buf,lev+2,off+len,&leng,&res); |
731 | if (res) |
699 | if (res) |
732 | goto ERROR1; |
700 | goto ERROR1; |
733 | psiconv_debug(lev+2,off+len,"Formula byte length: %d",bytelen); |
701 | psiconv_debug(config,lev+2,off+len,"Formula byte length: %d",bytelen); |
734 | len += leng; |
702 | len += leng; |
735 | bytelen += len; |
703 | bytelen += len; |
736 | formula_end = off + bytelen; |
704 | formula_end = off + bytelen; |
737 | |
705 | |
738 | psiconv_progress(lev+2,off+len,"Going to read the formula elements list"); |
706 | psiconv_progress(config,lev+2,off+len,"Going to read the formula elements list"); |
739 | if ((res = psiconv_parse_formula_element_list(buf,lev+2,off+len,&leng, |
707 | if ((res = psiconv_parse_formula_element_list(config,buf,lev+2,off+len,&leng, |
740 | result,formula_end))) |
708 | result,formula_end))) |
741 | goto ERROR1; |
709 | goto ERROR1; |
742 | len += leng; |
710 | len += leng; |
743 | |
711 | |
744 | psiconv_progress(lev+2,off+len,"Going to read the eof marker"); |
712 | psiconv_progress(config,lev+2,off+len,"Going to read the eof marker"); |
745 | temp = psiconv_read_u8(buf,lev+2,off+len,&res); |
713 | temp = psiconv_read_u8(config,buf,lev+2,off+len,&res); |
746 | if (res) |
714 | if (res) |
747 | goto ERROR2; |
715 | goto ERROR2; |
748 | if (formula_elements[temp].formula_type != psiconv_formula_mark_eof) { |
716 | if (formula_elements[temp].formula_type != psiconv_formula_mark_eof) { |
749 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
717 | psiconv_error(config,lev+2,off+len,"Formula corrupted!"); |
750 | psiconv_debug(lev+2,off+len,"Expected marker: %02x, found byte: %02x", |
718 | psiconv_debug(config,lev+2,off+len,"Expected marker: %02x, found byte: %02x", |
751 | 0x15,temp); |
719 | 0x15,temp); |
752 | goto ERROR2; |
720 | goto ERROR2; |
753 | } |
721 | } |
754 | len ++; |
722 | len ++; |
755 | |
723 | |
756 | if (off+len != formula_end) { |
724 | if (off+len != formula_end) { |
757 | psiconv_warn(lev+2,off+len,"Formula corrupted!"); |
725 | psiconv_error(config,lev+2,off+len,"Formula corrupted!"); |
758 | psiconv_debug(lev+2,off+len,"Expected end: %04x, found end: %04x", |
726 | psiconv_debug(config,lev+2,off+len,"Expected end: %04x, found end: %04x", |
759 | formula_end,len+off); |
727 | formula_end,len+off); |
760 | goto ERROR2; |
728 | goto ERROR2; |
761 | } |
729 | } |
762 | |
730 | |
763 | if (length) |
731 | if (length) |
764 | *length = len; |
732 | *length = len; |
765 | |
733 | |
766 | psiconv_progress(lev,off+len-1, |
734 | psiconv_progress(config,lev,off+len-1, |
767 | "End of formula (total length: %08x)", len); |
735 | "End of formula (total length: %08x)", len); |
768 | return 0; |
736 | return 0; |
769 | |
737 | |
770 | ERROR2: |
738 | ERROR2: |
771 | psiconv_free_formula(*result); |
739 | psiconv_free_formula(*result); |
772 | ERROR1: |
740 | ERROR1: |
773 | psiconv_warn(lev+1,off,"Reading of formula failed"); |
741 | psiconv_error(config,lev+1,off,"Reading of formula failed"); |
774 | if (length) |
742 | if (length) |
775 | *length = 0; |
743 | *length = 0; |
776 | if (!res) |
744 | if (!res) |
777 | return -PSICONV_E_NOMEM; |
745 | return -PSICONV_E_NOMEM; |
778 | else |
746 | else |