1 /*
2  * $Id: decompile.c,v 1.15 2000/08/10 21:02:50 danny Exp $
3  *
4  * Copyright � 1990, 1992, 1993, 1999 Free Software Foundation, Inc.
5  *
6  * This file is part of Oleo, the GNU Spreadsheet.
7  *
8  * Oleo is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * Oleo is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Oleo; see the file COPYING.  If not, write to
20  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #ifdef	WITH_DMALLOC
28 #include <dmalloc.h>
29 #endif
30 
31 #include <stdarg.h>
32 #include <ctype.h>
33 #include "global.h"
34 #include "decompile.h"
35 #include "eval.h"
36 #include "cell.h"
37 #include "io-utils.h"
38 #include "cmd.h"
39 
40 struct pr_node
41   {
42     int tightness;
43     int len;
44     char string[1];
45   };
46 
47 
48 static VOIDSTAR save_decomp;
49 static CELLREF decomp_row;
50 static CELLREF decomp_col;
51 
52 /* These #defines are so that we don't have to duplicate code below */
53 /* JF: now obsolete, and should be trashed. */
54 
55 #define F0	Global->a0?"@%s()":"%s()"
56 #define F1	Global->a0?"@%s(%s)":"%s(%s)"
57 #define F2	Global->a0?"@%s(%s, %s)":"%s(%s, %s)"
58 #define F3	Global->a0?"@%s(%s, %s, %s)":"%s(%s, %s, %s)"
59 #define F4	Global->a0?"@%s(%s, %s, %s, %s)":"%s(%s, %s, %s, %s)"
60 #define FN1	Global->a0?"@%s(%s":"%s(%s"
61 
62 /* We decompile things with these wierd node-things.  It's ugly, but it works.
63  */
64 static struct pr_node *
n_alloc(int size,int tightness,char * fmt,...)65 n_alloc (int size, int tightness, char *fmt, ...)
66 {
67   struct pr_node *ret;
68   va_list args;
69 
70   ret = ck_malloc (sizeof (struct pr_node) + size + 1);
71   ret->len = size;
72   ret->tightness = tightness;
73   va_start (args, fmt);
74   vsprintf (ret->string, fmt, args);
75   va_end (args);
76   return ret;
77 }
78 
79 #define n_free(x)	ck_free(x)
80 
81 extern struct pr_node *
82 byte_decompile (expr)
83      unsigned char *expr;
84 {
85   unsigned char byte;
86   double tmp_flt;
87   long tmp_lng;
88   char *tmp_str;
89   struct var *v;
90   unsigned long_skp;
91   unsigned char save_val;
92   unsigned jumpto;
93 
94   struct pr_node *new = 0;
95   int pri;
96   int aso;
97   char *chr;
98 
99   static struct pr_node **the_line;
100   static int line_alloc;
101 
102   static struct pr_node **c_node;
103   struct function *f;
104 
105   if (!the_line)
106     {
107       the_line = (struct pr_node **) ck_malloc (20 * sizeof (struct pr_node *));
108       line_alloc = 20;
109       c_node = the_line;
110     }
111 
112 #ifdef TEST
113   if (!expr)
114     panic ("No expression to decompile");
115 #endif
116 next_byte:
117   byte = *expr++;
118   if (byte < USR1)
119     f = &the_funs[byte];
120   else if (byte < SKIP)
121     {
122       tmp_lng = *expr++;
123       f = &usr_funs[byte - USR1][tmp_lng];
124     }
125   else
126     f = &skip_funs[byte - SKIP];
127 
128   if (f->fn_argn & X_J)
129     jumpto = *expr++;
130   else if (f->fn_argn & X_JL)
131     {
132       jumpto = expr[0] + ((unsigned) (expr[1]) << 8);
133       expr += 2;
134     }
135   else
136     jumpto = 0;
137 
138   switch (GET_COMP (f->fn_comptype))
139     {
140     case C_IF:
141       if (expr[jumpto - 2] != SKIP)
142 	{
143 	  long_skp = 1;
144 	  save_val = expr[jumpto - 3];
145 	  expr[jumpto - 3] = 0;
146 	}
147       else
148 	{
149 	  long_skp = 0;
150 	  save_val = expr[jumpto - 2];
151 	  expr[jumpto - 2] = 0;
152 	}
153       c_node[0] = byte_decompile (expr);
154       c_node++;
155 
156       if (long_skp)
157 	{
158 	  expr[jumpto - 3] = save_val;
159 	  expr += jumpto;
160 	  jumpto = expr[-2] + ((unsigned) (expr[-1]) << 8);
161 	}
162       else
163 	{
164 	  expr[jumpto - 2] = save_val;
165 	  expr += jumpto;
166 	  jumpto = expr[-1];
167 	}
168       save_val = expr[jumpto];
169       expr[jumpto] = 0;
170       c_node[0] = byte_decompile (expr);
171       c_node -= 2;
172       expr[jumpto] = save_val;
173       expr += jumpto;
174       if (byte == IF || byte == IF_L)
175 	{
176 	  if (c_node[0]->tightness <= 1)
177 	    new = n_alloc (8 + c_node[0]->len + c_node[1]->len + c_node[2]->len,
178 			   1,
179 			   "(%s) ? %s : %s", c_node[0]->string, c_node[1]->string, c_node[2]->string);
180 	  else
181 	    new = n_alloc (6 + c_node[0]->len + c_node[1]->len + c_node[2]->len,
182 			   1,
183 			   "%s ? %s : %s", c_node[0]->string, c_node[1]->string, c_node[2]->string);
184 	}
185       else
186 	new = n_alloc (6 + c_node[0]->len + c_node[1]->len + c_node[2]->len + strlen (f->fn_str),
187 		       1000,
188 		       F3, f->fn_str, c_node[0]->string, c_node[1]->string, c_node[2]->string);
189       n_free (c_node[0]);
190       n_free (c_node[1]);
191       n_free (c_node[2]);
192       break;
193 
194     case C_ANDOR:
195       save_val = expr[jumpto];
196       expr[jumpto] = 0;
197       c_node[0] = byte_decompile (expr);
198       expr[jumpto] = save_val;
199       expr += jumpto;
200       c_node++;
201       if (ISINFIX (f->fn_comptype))
202 	{
203 	  pri = GET_IN (f->fn_comptype);
204 	  aso = GET_ASO (f->fn_comptype);
205 	  chr = f->fn_str;
206 	  goto do_infix;
207 	}
208       else
209 	goto do_fn2;
210 
211     case C_STR:
212       tmp_str = backslash_a_string ((char *) expr + jumpto, 2);
213       new = n_alloc (strlen (tmp_str) + 1,
214 		     1000,
215 		     "%s", tmp_str);
216       break;
217 
218     case C_CELL:
219       {
220 	int num1, num2;
221 	char *str;
222 	CELLREF row, col;
223 
224 	row = GET_ROW (expr);
225 	col = GET_COL (expr);
226 	expr += EXP_ADD;
227 
228 	if (Global->a0)
229 	  {
230 	    new = n_alloc (30, 1000, f->fn_str, col_to_str (col), row);
231 	  }
232 	else
233 	  {
234 	    if (byte & ROWREL)
235 	      {
236 		num1 = row - decomp_row;
237 		if (byte & COLREL)
238 		  {
239 		    num2 = col - decomp_col;
240 		    if (row == decomp_row && col == decomp_col)
241 		      str = "rc";
242 		    else if (row == decomp_row)
243 		      {
244 			str = "rc[%+d]";
245 			num1 = num2;
246 		      }
247 		    else if (col == decomp_col)
248 		      str = "r[%+d]c";
249 		    else
250 		      str = "r[%+d]c[%+d]";
251 		  }
252 		else if (row == decomp_row)
253 		  {
254 		    str = "rc%u";
255 		    num1 = num2 = col;
256 		  }
257 		else
258 		  {
259 		    str = "r[%+d]c%u";
260 		    num2 = col;
261 		  }
262 	      }
263 	    else if (byte & COLREL)
264 	      {
265 		num1 = row;
266 		num2 = col - decomp_col;
267 		if (col == decomp_col)
268 		  str = "r%uc";
269 		else
270 		  str = "r%uc[%+d]";
271 	      }
272 	    else
273 	      {
274 		str = "r%uc%u";
275 		num1 = row;
276 		num2 = col;
277 	      }
278 	    new = n_alloc (30, 1000, str, num1, num2);
279 	  }
280 	new->len = strlen (new->string);
281       }
282       break;
283 
284     case C_RANGE:
285       {
286 	char tmprbuf[40];
287 	char tmpcbuf[40];
288 	struct rng rng;
289 
290 	GET_RNG (expr, &rng);
291 	expr += EXP_ADD_RNG;
292 
293 	if (Global->a0)
294 	  new = n_alloc (40, 1000, f->fn_str, col_to_str (rng.lc), rng.lr, col_to_str (rng.hc), rng.hr);
295 	else
296 	  {
297 	    /* Check for special cases */
298 	    if (rng.lr == rng.hr && ((byte & LRREL) ? 1 : 0) == ((byte & HRREL) ? 1 : 0))
299 	      {
300 		if (byte & LRREL)
301 		  {
302 		    if (rng.lr == decomp_row)
303 		      {
304 			tmprbuf[0] = 'r';
305 			tmprbuf[1] = '\0';
306 		      }
307 		    else
308 		      (void) sprintf (tmprbuf, "r[%+d]", rng.lr - decomp_row);
309 		  }
310 		else
311 		  sprintf (tmprbuf, "r%u", rng.lr);
312 	      }
313 	    else if ((byte & LRREL) && (byte & HRREL))
314 	      {
315 		int r1, r2, rtmp;
316 
317 		r1 = rng.lr - decomp_row;
318 		r2 = rng.hr - decomp_row;
319 		if (r1 < r2)
320 		  rtmp = r1, r1 = r2, r2 = rtmp;
321 		(void) sprintf (tmprbuf, "r[%+d:%+d]", r1, r2);
322 	      }
323 	    else if ((byte & LRREL))
324 	      (void) sprintf (tmprbuf, "r[%+d]:%u", rng.lr - decomp_row, rng.hr);
325 	    else if (byte & HRREL)
326 	      (void) sprintf (tmprbuf, "r%u:[%+d]", rng.lr, rng.hr - decomp_row);
327 	    else if (rng.lr < rng.hr)
328 	      (void) sprintf (tmprbuf, "r%u:%u", rng.lr, rng.hr);
329 	    else
330 	      (void) sprintf (tmprbuf, "r%u:%u", rng.hr, rng.lr);
331 
332 	    if (rng.lc == rng.hc && ((byte & LCREL) ? 1 : 0) == ((byte & HCREL) ? 1 : 0))
333 	      {
334 		if (byte & LCREL)
335 		  {
336 		    if (rng.lc == decomp_col)
337 		      {
338 			tmpcbuf[0] = 'c';
339 			tmpcbuf[1] = '\0';
340 		      }
341 		    else
342 		      sprintf (tmpcbuf, "c[%+d]", rng.lc - decomp_col);
343 		  }
344 		else
345 		  sprintf (tmpcbuf, "c%u", rng.lc);
346 	      }
347 	    else if ((byte & LCREL) && (byte & HCREL))
348 	      {
349 		int c1, c2, ctmp;
350 
351 		c1 = rng.lc - decomp_col;
352 		c2 = rng.hc - decomp_col;
353 		if (c1 < c2)
354 		  ctmp = c1, c1 = c2, c2 = ctmp;
355 		(void) sprintf (tmpcbuf, "c[%+d:%+d]", c1, c2);
356 	      }
357 	    else if ((byte & LCREL))
358 	      (void) sprintf (tmpcbuf, "c[%+d]:%u", rng.lc - decomp_col, rng.hc);
359 	    else if (byte & HCREL)
360 	      (void) sprintf (tmpcbuf, "c%u:[%+d]", rng.lc, rng.hc - decomp_col);
361 	    else if (rng.lc < rng.hc)
362 	      (void) sprintf (tmpcbuf, "c%u:%u", rng.lc, rng.hc);
363 	    else
364 	      (void) sprintf (tmpcbuf, "c%u:%u", rng.hc, rng.lc);
365 
366 	    new = n_alloc (40, 1000, "%s%s", tmprbuf, tmpcbuf);
367 	  }
368 	new->len = strlen (new->string);
369       }
370       break;
371 
372     case C_CONST:
373       new = n_alloc (strlen (f->fn_str) + 1, 1000, f->fn_str);
374       break;
375 
376     case C_FN0:
377     case C_FN0X:
378     case C_FN0 | C_T:
379       new = n_alloc (strlen (f->fn_str) + 3,
380 		     1000,
381 		     F0,
382 		     f->fn_str);
383       break;
384 
385     case C_FN1:
386       --c_node;
387       new = n_alloc (c_node[0]->len + strlen (f->fn_str) + 3,
388 		     1000,
389 		     F1, f->fn_str, c_node[0]->string);
390       n_free (*c_node);
391       break;
392 
393     case C_UNA:
394       --c_node;
395       if (c_node[0]->tightness < 9)
396 	{
397 	  new = n_alloc (3 + c_node[0]->len,
398 			 9,
399 			 "%s(%s)", f->fn_str, c_node[0]->string);
400 	}
401       else
402 	{
403 	  new = n_alloc (1 + c_node[0]->len,
404 			 9,
405 			 "%s%s", f->fn_str, c_node[0]->string);
406 	}
407       n_free (*c_node);
408       break;
409 
410     case C_INF:
411       pri = GET_IN (f->fn_comptype);
412       aso = GET_ASO (f->fn_comptype);
413       chr = f->fn_str;
414 
415     do_infix:
416       c_node -= 2;
417       if (c_node[0]->tightness < pri || (c_node[0]->tightness == pri && aso != 1))
418 	{
419 	  if (c_node[1]->tightness < pri || (c_node[1]->tightness == pri && aso != -1))
420 	    new = n_alloc (7 + c_node[0]->len + c_node[1]->len,
421 			   pri,
422 		 "(%s) %s (%s)", c_node[0]->string, chr, c_node[1]->string);
423 	  else
424 	    new = n_alloc (5 + c_node[0]->len + c_node[1]->len,
425 			   pri,
426 		   "(%s) %s %s", c_node[0]->string, chr, c_node[1]->string);
427 	}
428       else if (c_node[1]->tightness < pri || (c_node[1]->tightness == pri && aso != -1))
429 	new = n_alloc (5 + c_node[0]->len + c_node[1]->len,
430 		       pri,
431 		   "%s %s (%s)", c_node[0]->string, chr, c_node[1]->string);
432       else
433 	new = n_alloc (3 + c_node[0]->len + c_node[1]->len,
434 		       pri,
435 		     "%s %s %s", c_node[0]->string, chr, c_node[1]->string);
436 
437       n_free (c_node[0]);
438       n_free (c_node[1]);
439       break;
440 
441     case C_FN2:
442     do_fn2:
443       c_node -= 2;
444       new = n_alloc (c_node[0]->len + c_node[1]->len + strlen (f->fn_str) + 5,
445 		     1000,
446 		     F2, f->fn_str, c_node[0]->string, c_node[1]->string);
447       n_free (c_node[0]);
448       n_free (c_node[1]);
449       break;
450 
451     case C_FN3:
452       c_node -= 3;
453       new = n_alloc (c_node[0]->len + c_node[1]->len + c_node[2]->len + strlen (f->fn_str) + 7,
454 		     1000,
455 		     F3,
456 		     f->fn_str,
457 		     c_node[0]->string,
458 		     c_node[1]->string,
459 		     c_node[2]->string);
460       n_free (c_node[0]);
461       n_free (c_node[1]);
462       n_free (c_node[2]);
463       break;
464 
465     case C_FNN:
466       aso = *expr++;
467       c_node -= aso;
468 
469       if (aso == 1)
470 	new = n_alloc (3 + c_node[0]->len + strlen (f->fn_str),
471 		       1000,
472 		       F1, f->fn_str, c_node[0]->string);
473       else
474 	{
475 	  new = n_alloc (2 + c_node[0]->len + strlen (f->fn_str),
476 			 1000,
477 			 FN1, f->fn_str, c_node[0]->string);
478 	  --aso;
479 	  for (pri = 1; pri < aso; pri++)
480 	    {
481 	      n_free (c_node[0]);
482 	      c_node[0] = new;
483 	      new = n_alloc (2 + new->len + c_node[pri]->len,
484 			     1000,
485 			     "%s, %s", new->string, c_node[pri]->string);
486 	    }
487 	  n_free (c_node[0]);
488 	  c_node[0] = new;
489 	  new = n_alloc (3 + new->len + c_node[aso]->len,
490 			 1000,
491 			 "%s, %s)", new->string, c_node[aso]->string);
492 	}
493       n_free (c_node[0]);
494       break;
495 
496     case C_FN4:
497       c_node -= 4;
498       new = n_alloc (c_node[0]->len + c_node[1]->len + c_node[2]->len + c_node[3]->len + strlen (f->fn_str) + 6,
499 		     1000,
500 		     F4,
501 		     f->fn_str,
502 		     c_node[0]->string,
503 		     c_node[1]->string,
504 		     c_node[2]->string,
505 		     c_node[3]->string);
506       n_free (c_node[0]);
507       n_free (c_node[1]);
508       n_free (c_node[2]);
509       n_free (c_node[3]);
510       break;
511 
512     case C_ERR:
513       tmp_str = (char *) expr + jumpto;
514       expr++;
515       new = n_alloc (strlen (tmp_str) + 1, 1000, "%s", tmp_str);
516       /* bcopy((VOIDSTAR)expr,(VOIDSTAR)&tmp_str,sizeof(char *));
517 		expr+=sizeof(char *);
518 		new=n_alloc(strlen(tmp_str)+1,1000,f->fn_str,tmp_str); */
519       break;
520 
521     case C_FLT:
522       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_flt, sizeof (double));
523       expr += sizeof (double);
524       new = n_alloc (20, 1000, f->fn_str, tmp_flt);
525       new->len = strlen (new->string);
526       break;
527 
528     case C_INT:
529       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_lng, sizeof (long));
530       expr += sizeof (long);
531       new = n_alloc (20, 1000, f->fn_str, tmp_lng);
532       new->len = strlen (new->string);
533       break;
534 
535     case C_VAR:
536       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & v, sizeof (struct var *));
537       expr += sizeof (struct var *);
538       new = n_alloc (strlen (v->var_name) + 1,
539 		     1000,
540 		     f->fn_str, v->var_name);
541       break;
542 
543 
544     default:
545       panic ("Bad decompile %d", f->fn_comptype);
546     }
547   *c_node++ = new;
548   if (c_node == &the_line[line_alloc])
549     {
550       line_alloc *= 2;
551       the_line = ck_realloc (the_line, line_alloc * sizeof (struct pr_node *));
552       c_node = &the_line[line_alloc / 2];
553     }
554 
555   if (*expr)
556     goto next_byte;
557 
558   /* if(c_node != &the_line[1]) {
559 		io_error_msg("%d values on decompile stack!",c_node - the_line);
560 		return the_line[0];
561 	} */
562   new = *--c_node;
563   /* free(the_line); */
564   return new;
565 }
566 
567 /* Actual entry points to this file */
568 /* decomp(row, col, cell) returns a string that can be byte_compiled to create
569    cell->formula  decomp_free() frees up the allocated string */
570 /* Have moved decomp(row, col, cell) to decomp_formula(row, col, cell, tog).
571  * Alias decomp(row, col, cell) behaves exactly as command described
572  * in the comment aboce.  the new int tog argument, if true, can be
573  * used to turn on formatted editing.
574  */
575 char *
decomp(CELLREF r,CELLREF c,CELL * cell)576 decomp (CELLREF r, CELLREF c, CELL *cell)
577 {
578   char *tmp;
579 
580   tmp = decomp_formula (r, c, cell, 0);
581 
582   return (tmp);
583 }
584 char *
decomp_formula(CELLREF r,CELLREF c,CELL * cell,int tog)585 decomp_formula (CELLREF r, CELLREF c, CELL *cell, int tog)
586 {
587   struct pr_node *ret;
588   char *str;
589   extern char *bname[];
590 
591   if (!cell)
592     {
593       str = ck_malloc (1);
594       str[0] = '\0';
595       save_decomp = (VOIDSTAR) str;
596       return str;
597     }
598   decomp_row = r;
599   decomp_col = c;
600   if (cell->cell_formula == 0)
601     {
602       switch (GET_TYP (cell))
603 	{
604 	case 0:
605 	  str = ck_malloc (1);
606 	  str[0] = '\0';
607 	  break;
608 	case TYP_FLT:
609           if (tog)
610             {
611               str = strdup (flt_to_str_fmt(cell));
612             }
613           else
614             {
615               str = strdup (flt_to_str (cell->cell_flt));
616             }
617 	  break;
618 	case TYP_INT:
619 	  str = ck_malloc (20);
620 	  sprintf (str, "%ld", cell->cell_int);
621 	  break;
622 	case TYP_STR:
623 	  str = strdup (backslash_a_string (cell->cell_str, 1));
624 	  break;
625 	case TYP_BOL:
626 	  str = strdup (bname[cell->cell_bol]);
627 	  break;
628 	case TYP_ERR:
629 	  str = strdup (ename[cell->cell_bol]);
630 	  break;
631 	default:
632 	  str = 0;
633 #ifdef TEST
634 	  panic ("Unknown type %d in decomp", GET_TYP (cell));
635 #endif
636 	}
637       save_decomp = (VOIDSTAR) str;
638       return str;
639     }
640   else
641     ret = byte_decompile (cell->cell_formula);
642   save_decomp = (VOIDSTAR) ret;
643   return &(ret->string[0]);
644 }
645 
646 void
decomp_free(void)647 decomp_free (void)
648 {
649 #ifdef TEST
650   if (!save_decomp)
651     panic ("No save decomp");
652   n_free (save_decomp);
653   save_decomp = (VOIDSTAR) 0;
654 #else
655   n_free (save_decomp);
656 #endif
657 }
658 
659 /*
660  * This takes a string and returns a backslashed form suitable for printing.
661  * Iff add_quote is true, it'll add "s at the beginning and end.
662  * Note that this returns a pointer to a static area that is overwritten with
663  * each call. . .
664  *
665  * If add_quote is 1, escape normal quotes, if it is 2, also escape %.
666  */
667 char *
backslash_a_string(char * string,int add_quote)668 backslash_a_string (char *string, int add_quote)
669 {
670 	char		*pf, *pt;
671 	unsigned char	ch;
672 	int		size, len;
673 	static char	*cbuf;
674 	static int	s_cbuf;
675 
676 #define ALLOC_PT()				\
677 	len=strlen(pf);				\
678 	size=pf-string;				\
679 	if(s_cbuf<3+size+4*len) {		\
680 	s_cbuf=3+size+4*len;		\
681 	cbuf= (cbuf) ? ck_realloc(cbuf,s_cbuf) : ck_malloc(s_cbuf); \
682 	}					\
683 	if(size)				\
684 	bcopy(string,cbuf,size);	\
685 	pt=cbuf+size;				\
686 
687 
688 	pt = 0;
689 	pf = string;
690 	if (add_quote) {
691 		ALLOC_PT ()
692 		*pt++ = '"';
693 	}
694 	for (; *pf; pf++) {
695 		ch = *pf;
696 		if (isprint(ch) && ch != '\\'
697 				&& (ch != '%' || !(add_quote == 2))
698 				&& (ch != '"' || !add_quote)) {
699 			if (pt)
700 				*pt++ = ch;
701 			continue;
702 		}
703 
704 		if (!pt) {
705 			ALLOC_PT ()
706 		}
707 		if (ch == '\\') {
708 			*pt++ = '\\';
709 			*pt++ = '\\';
710 		} else if (ch == '"') {
711 			*pt++ = '\\';
712 			*pt++ = ch;
713 		} else if (ch == '%') {
714 			*pt++ = '%';
715 			*pt++ = '%';
716 		} else {
717 			*pt++ = '\\';
718 			*pt++ = ((ch >> 6) & 0x3) + '0';
719 			*pt++ = ((ch >> 3) & 0x7) + '0';
720 			*pt++ = (ch & 0x7) + '0';
721 		}
722 	}
723 	if (add_quote)
724 		*pt++ = '"';
725 	if (pt) {
726 		*pt++ = '\0';
727 		return cbuf;
728 	}
729 	return string;
730 }
731 
732 void
dbg_print_formula(expr)733 dbg_print_formula (expr)
734      unsigned char *expr;
735 {
736   unsigned char byte;
737   struct function *f;
738   double tmp_flt;
739   char *tmp_str;
740   long tmp_int;
741   struct var *v;
742   struct rng rng;
743   char *buf;
744   unsigned jumpto;
745   extern char print_buf[];
746 
747   if (!expr)
748     return;
749   strcpy (print_buf, "Formula: ");
750   buf = print_buf + 9;
751   while (*expr)
752     {
753       byte = *expr++;
754 
755       if (byte < USR1)
756 	f = &the_funs[byte];
757       else if (byte < SKIP)
758 	{
759 	  tmp_int = *expr++;
760 	  f = &usr_funs[byte - USR1][tmp_int];
761 	}
762       else
763 	f = &skip_funs[byte - SKIP];
764 
765       if (f->fn_argn & X_J)
766 	jumpto = *expr++;
767       else if (f->fn_argn & X_JL)
768 	{
769 	  jumpto = expr[0] + ((unsigned) (expr[1]) << 8);
770 	  expr += 2;
771 	}
772       else
773 	jumpto = 0;
774 
775       switch (GET_COMP (f->fn_comptype))
776 	{
777 	case C_IF:
778 	  sprintf (buf, " if%d.%u", byte, jumpto);
779 	  break;
780 	case C_ANDOR:
781 	  sprintf (buf, " andor%d.%u", byte, jumpto);
782 	  break;
783 	case C_ERR:
784 	  tmp_str = (char *) (expr + jumpto);
785 	  byte = *expr++;
786 	  sprintf (buf, " err%d.%p(%s)", byte, tmp_str, tmp_str);
787 	  break;
788 	case C_FLT:
789 	  bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_flt, sizeof (double));
790 	  expr += sizeof (double);
791 	  sprintf (buf, " flt.%.15g", tmp_flt);
792 	  break;
793 	case C_INT:
794 	  bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_int, sizeof (long));
795 	  expr += sizeof (long);
796 	  sprintf (buf, " int.%ld", tmp_int);
797 	  break;
798 	case C_STR:
799 	  tmp_str = (char *) (expr + jumpto);
800 	  sprintf (buf, " str.%p.%s", tmp_str, tmp_str);
801 	  break;
802 	case C_VAR:
803 	  bcopy ((VOIDSTAR) expr, (VOIDSTAR) & v, sizeof (struct var *));
804 	  expr += sizeof (struct var *);
805 	  sprintf (buf, " var.%p.%s", v, v->var_name);
806 	  break;
807 	case C_CELL:
808 	  sprintf (buf, " ref%d.%u.%u", byte, GET_ROW (expr), GET_COL (expr));
809 	  expr += EXP_ADD;
810 	  break;
811 	case C_RANGE:
812 	  GET_RNG (expr, &rng);
813 	  sprintf (buf, " rng%d.%u-%u,%u-%u", byte, rng.lr, rng.hr, rng.lc, rng.hc);
814 	  expr += EXP_ADD_RNG;
815 	  break;
816 	case C_FN0:
817 	case C_FN0X:
818 	case C_FN1:
819 	case C_FN2:
820 	case C_FN3:
821 	case C_FN4:
822 	case C_UNA:
823 	case C_INF:
824 	  sprintf (buf, " fun%d.%s.%p", byte, f->fn_str, f->fn_fun);
825 	  break;
826 
827 	case C_FNN:
828 	  sprintf (buf, " funn%d.%s.%p.%d", byte, f->fn_str, f->fn_fun, *expr++);
829 	  break;
830 	case C_CONST:
831 	  sprintf (buf, " const%s", f->fn_str);
832 	  break;
833 	case C_SKIP:
834 	  sprintf (buf, " skip.%d", jumpto);
835 	  break;
836 	case 0:
837 	  sprintf (buf, " ???%d", byte);
838 	  break;
839 	default:
840 	  io_error_msg ("Unknown decompile type %d", f->fn_comptype);
841 	}
842       buf += strlen (buf);
843     }
844   io_text_line (print_buf);
845 }
846