1 /*------------------------------------------------------------*
2 | var.c |
3 | copyright 1999, Andrew Sumner (andrewsumner@yahoo.com) |
4 | |
5 | This is a source file for the awka package, a translator |
6 | of the AWK programming language to ANSI C. |
7 | |
8 | This library is free software; you can redistribute it |
9 | and/or modify it under the terms of the GNU General |
10 | Public License (GPL). |
11 | |
12 | This library is distributed in the hope that it will be |
13 | useful, but WITHOUT ANY WARRANTY; without even the implied |
14 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
15 | PURPOSE. |
16 *------------------------------------------------------------*/
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <limits.h>
22 #include <ctype.h>
23
24 #define _VAR_C
25 #define _IN_LIBRARY
26
27 #ifndef TRUE
28 # define TRUE 1
29 # define FALSE 0
30 #endif
31 char _awka_arg_change = FALSE;
32
33 #include "libawka.h"
34 #include "number.h"
35 #include "garbage.h"
36
37 struct _fnvar {
38 a_VAR **var;
39 char *status;
40 int used;
41 int prevused;
42 int allc;
43 };
44
45 struct _fn {
46 char *fn;
47 struct _fnvar *fnvar;
48 int push;
49 int allc;
50 int nvar;
51 } *_awka_fn = NULL;
52
53 int _awka_fn_allc = 0, _awka_fn_used = 0;
54
55 a_VAR *
awka_argval(int fn_idx,a_VAR * var,int arg_no,int arg_count,a_VARARG * va)56 awka_argval(int fn_idx, a_VAR *var, int arg_no, int arg_count, a_VARARG *va)
57 {
58 a_VAR *ret;
59
60 arg_no--;
61 if (fn_idx == -1 || arg_no >= arg_count || arg_no < 0)
62 {
63 _awka_tmpvar(ret);
64 awka_killvar(ret);
65 return ret;
66 }
67
68 if (va->used == 0 || var->type != a_VARARR)
69 return var;
70
71 if (va->used == 1)
72 return awka_arraysearch1( var,
73 va->var[0],
74 a_ARR_CREATE,
75 TRUE );
76
77 return awka_arraysearch( var,
78 va,
79 a_ARR_CREATE );
80 }
81
82 int
_awka_registerfn(char * fn,int nvar)83 _awka_registerfn(char *fn, int nvar)
84 {
85 int i, j;
86
87 for (i=0; i<_awka_fn_used; i++)
88 if (!strcmp(_awka_fn[i].fn, fn))
89 return i;
90
91 if (i == _awka_fn_used)
92 {
93 if (_awka_fn_allc == 0)
94 {
95 _awka_fn_allc = 10;
96 malloc( &_awka_fn, 10 * sizeof(struct _fn));
97 }
98 else if (_awka_fn_used == _awka_fn_allc)
99 {
100 _awka_fn_allc += 10;
101 realloc( &_awka_fn, _awka_fn_allc * sizeof(struct _fn));
102 }
103
104 _awka_fn_used++;
105 malloc( &_awka_fn[i].fn, strlen(fn)+1);
106 strcpy(_awka_fn[i].fn, fn);
107 _awka_fn[i].allc = 10;
108 _awka_fn[i].push = 0;
109 _awka_fn[i].nvar = nvar;
110 malloc( &_awka_fn[i].fnvar, 10 * sizeof(struct _fnvar));
111 for (j = 0; j<_awka_fn[i].allc; j++)
112 {
113 _awka_fn[i].fnvar[j].var = NULL;
114 _awka_fn[i].fnvar[j].status = NULL;
115 _awka_fn[i].fnvar[j].used = 0;
116 _awka_fn[i].fnvar[j].prevused = 0;
117 _awka_fn[i].fnvar[j].allc = 0;
118 }
119 }
120
121 return i;
122 }
123
124 /*
125 * addfnvar - this nonsense registers local variables
126 * within user functions.
127 */
128 void
_awka_addfnvar(int i,int var_idx,a_VAR * var,int type)129 _awka_addfnvar(int i, int var_idx, a_VAR *var, int type)
130 {
131 register int j;
132
133 j = _awka_fn[i].push-1;
134 _awka_fn[i].fnvar[j].used = (_awka_fn[i].fnvar[j].used <= var_idx ?
135 var_idx + 1 : _awka_fn[i].fnvar[j].used);
136 _awka_fn[i].fnvar[j].var[var_idx] = var;
137 _awka_fn[i].fnvar[j].prevused = _awka_fn[i].fnvar[j].used;
138 _awka_fn[i].fnvar[j].status[var_idx] = type;
139 if (type == 2)
140 var->type = a_VARARR;
141 }
142
143 a_VAR *
_awka_usefnvar(int i,int var_idx)144 _awka_usefnvar(int i, int var_idx)
145 {
146 register int j = _awka_fn[i].push-1;
147 a_VAR *var;
148
149 if (_awka_fn[i].fnvar[j].prevused > var_idx)
150 {
151 var = _awka_fn[i].fnvar[j].var[ var_idx ];
152 _awka_fn[i].fnvar[j].used = (_awka_fn[i].fnvar[j].used <= var_idx ?
153 var_idx + 1 : _awka_fn[i].fnvar[j].used);
154 return var;
155 }
156 else
157 return NULL;
158 }
159
160 /*
161 * awka_addfncall - denotes a call to a registered function, allocating
162 * space if necessary for its local variables.
163 */
164 a_VAR *
_awka_addfncall(int i)165 _awka_addfncall(int i)
166 {
167 register int j, k;
168 a_VAR *ret;
169
170 _awka_tmpvar(ret); /* bugfix for eiso */
171 _awka_gc_deeper();
172
173 if (_awka_fn[i].push == _awka_fn[i].allc)
174 {
175 _awka_fn[i].allc += 10;
176 realloc( &_awka_fn[i].fnvar, _awka_fn[i].allc * sizeof(struct _fnvar));
177 for (j = _awka_fn[i].push; j<_awka_fn[i].allc; j++)
178 {
179 _awka_fn[i].fnvar[j].var = NULL;
180 _awka_fn[i].fnvar[j].used = 0;
181 _awka_fn[i].fnvar[j].prevused = 0;
182 _awka_fn[i].fnvar[j].allc = 0;
183 }
184 }
185
186 j = _awka_fn[i].push;
187 _awka_fn[i].push++;
188 if (_awka_fn[i].fnvar[j].allc == 0 && _awka_fn[i].nvar)
189 {
190 _awka_fn[i].fnvar[j].allc = _awka_fn[i].nvar;
191 malloc( &_awka_fn[i].fnvar[j].var, _awka_fn[i].nvar * sizeof(a_VAR *));
192 malloc( &_awka_fn[i].fnvar[j].status, _awka_fn[i].nvar);
193 for (k=0; k<_awka_fn[i].nvar; k++)
194 _awka_fn[i].fnvar[j].var[k] = NULL;
195 }
196 if (ret->ptr)
197 {
198 if (ret->type == a_VARREG)
199 _awka_re2null(ret);
200 else
201 {
202 ret->ptr[0] = '\0';
203 ret->slen = 0;
204 }
205 }
206 else
207 ret->type = a_VARNUL;
208 return ret;
209 }
210
211 /*
212 * awka_retfn - this frees local variables in user-functions upon
213 * a return.
214 */
215 void
_awka_retfn(int i)216 _awka_retfn(int i)
217 {
218 register int j, k;
219 a_VAR *var;
220
221 if (_awka_fn[i].push == 0)
222 return;
223 _awka_fn[i].push--;
224 j = _awka_fn[i].push;
225
226 for (k=0; k<_awka_fn[i].fnvar[j].used; k++)
227 {
228 var = _awka_fn[i].fnvar[j].var[k];
229 if (!var) continue;
230 if (var->ptr)
231 {
232 /* if this is a local function var, manage its memory */
233 if (!_awka_fn[i].fnvar[j].status[k])
234 {
235 if (!var->allc)
236 var->ptr = NULL;
237 else
238 awka_killvar(var);
239 }
240 else if (var->type == a_VARARR)
241 {
242 awka_arrayclear(var);
243 free(var->ptr);
244 var->ptr = NULL;
245 var->allc = 0;
246 }
247 else
248 {
249 awka_gets1(var);
250 var->ptr[0] = '\0';
251 }
252 }
253 if (var->type == a_VARDBL)
254 {
255 /* if (var->ptr) awka_killvar(var); */
256 var->type = a_VARNUL;
257 }
258 var->slen = 0;
259 var->dval = 0.0;
260 var->type2 = 0;
261 }
262 _a_gc_depth--;
263 _awka_fn[i].fnvar[j].used = 0;
264 }
265
266 void
awka_killvar(a_VAR * v)267 awka_killvar( a_VAR *v )
268 {
269 if (!v) return;
270
271 if (v->ptr)
272 {
273 if (v->type == a_VARARR)
274 {
275 awka_arrayclear(v);
276 free(v->ptr);
277 }
278 else if (v->type != a_VARREG)
279 free(v->ptr);
280 }
281
282 v->ptr = NULL;
283 v->dval = 0.0;
284 v->allc = 0;
285 v->slen = 0;
286 v->type2 = 0;
287 v->type = a_VARNUL;
288 }
289
290 void
_awka_re2s(a_VAR * v)291 _awka_re2s( a_VAR *v )
292 {
293 awka_regexp *r;
294
295 if (v->type != a_VARREG) return;
296 r = (awka_regexp *) v->ptr;
297 malloc( &v->ptr, (v->slen = r->strlen) + 1 );
298 memcpy(v->ptr, r->origstr, v->slen+1);
299 v->type = a_VARSTR;
300 v->allc = v->slen+1;
301 v->type2 = 0;
302 }
303
304 void
_awka_re2null(a_VAR * v)305 _awka_re2null( a_VAR *v )
306 {
307 if (v->type != a_VARREG) return;
308 v->type = a_VARNUL;
309 v->allc = v->slen = 0;
310 v->type2 = 0;
311 v->ptr = NULL;
312 }
313
314 double
awka_postinc(a_VAR * v)315 awka_postinc( a_VAR *v )
316 {
317 double d = awka_setd(v);
318 v->dval++;
319 return d;
320 }
321
322 double
awka_postdec(a_VAR * v)323 awka_postdec( a_VAR *v )
324 {
325 double d = awka_setd(v);
326 v->dval--;
327 return d;
328 }
329
330 a_VAR *
_awka_getdval(a_VAR * v,char * file,int line)331 _awka_getdval( a_VAR *v, char *file, int line )
332 {
333 switch (v->type)
334 {
335 case a_VARREG:
336 _awka_re2s(v);
337 /* fall through */
338 case a_VARSTR:
339 case a_VARUNK:
340 if (v->type2 == (char) -1)
341 v->dval = 0;
342 else if (v->ptr)
343 v->dval = strtod(v->ptr, NULL);
344 else
345 v->dval = 0;
346 break;
347 case a_VARNUL:
348 v->dval = 0.0;
349 break;
350 case a_VARARR:
351 awka_error("runtime error: awka_getd in file %s, line %d - %s\n", file,line,"array used as scalar");
352 }
353
354 if (v->type2 != (char) -1)
355 v->type2 = a_DBLSET;
356 return v;
357 }
358
359 a_VAR *
_awka_setdval(a_VAR * v,char * file,int line)360 _awka_setdval( a_VAR *v, char *file, int line )
361 {
362 if (v->type == a_VARREG)
363 _awka_re2null(v);
364
365 _awka_set_FW(v);
366
367 v->type2 = 0;
368 if (v->type == a_VARSTR || v->type == a_VARUNK)
369 {
370 if (v->ptr)
371 {
372 v->dval = strtod(v->ptr, NULL);
373 free(v->ptr);
374 }
375 v->ptr = NULL;
376 v->slen = 0;
377 v->allc = 0;
378 v->type = a_VARDBL;
379 return v;
380 }
381 else if (v->type == a_VARNUL)
382 {
383 v->type = a_VARDBL;
384 v->dval = 0.0;
385 /* v->ptr = NULL; */
386 return v;
387 }
388 else
389 {
390 /* array */
391 awka_error("runtime error: awka_setd in file %s, line %d - %s\n", file,line,"array used as scalar");
392 }
393
394 /* dead code - have to check this... */
395 if (_awka_setdoln == TRUE)
396 _awka_setdol0_len = TRUE;
397 if (v == a_bivar[a_DOL0])
398 {
399 _rebuild0_now = FALSE;
400 _rebuildn = TRUE;
401 }
402 return v;
403 }
404
405 char *
_awka_getsval(a_VAR * v,char ofmt,char * file,int line)406 _awka_getsval( a_VAR *v, char ofmt, char *file, int line )
407 {
408 char varbuf[256], *ptr = NULL;
409 register int i;
410
411 switch (v->type)
412 {
413 case a_VARDBL:
414 i = (int) (v->dval);
415 if ((double) i == v->dval)
416 {
417 sprintf(varbuf, "%d", i);
418 v->slen = strlen(varbuf);
419 }
420 else
421 {
422 if (ofmt)
423 sprintf(varbuf, awka_gets1(a_bivar[a_OFMT]), v->dval);
424 else
425 sprintf(varbuf, awka_gets1(a_bivar[a_CONVFMT]), v->dval);
426 v->slen = strlen(varbuf);
427 }
428 if (!v->ptr || (v->temp == 2 && v->allc <= v->slen))
429 v->allc = malloc( &v->ptr, v->slen + 1 );
430 else if (v->allc <= v->slen)
431 v->allc = realloc( &v->ptr, v->slen + 1 );
432
433 memcpy(v->ptr, varbuf, v->slen+1);
434 v->type2 = (ofmt ? 0 : a_STRSET);
435 return v->ptr;
436
437 case a_VARSTR:
438 case a_VARUNK:
439 v->allc = malloc( &v->ptr, 8 );
440 ptr = v->ptr;
441 v->slen = 0;
442 v->ptr[0] = '\0';
443 return ptr;
444
445 case a_VARREG:
446 if (v->ptr)
447 {
448 _awka_re2s(v);
449 v->type = a_VARSTR;
450 return v->ptr;
451 }
452 v->dval = 0.0;
453 v->type = a_VARNUL;
454 /* fall thru */
455 case a_VARNUL:
456 ptr = _awka_tmpstr(1);
457 ptr[0] = '\0';
458 v->slen = 0;
459 return ptr;
460
461 case a_VARARR:
462 awka_error("runtime error: awka_gets in file %s, line %d - array used as scalar.\n",file,line);
463
464 default:
465 awka_error("runtime error: awka_gets in file %s, line %d - unexpected type value (%d).\n",file,line,v->type);
466 }
467
468 return ptr; /* can't get here anyway */
469 }
470
471 awka_regexp *
_awka_getreval(a_VAR * v,char * file,int line,char type)472 _awka_getreval( a_VAR *v, char *file, int line, char type )
473 {
474 awka_regexp *r = NULL;
475 switch (v->type)
476 {
477 case a_VARDBL:
478 awka_gets1(v);
479 break;
480
481 case a_VARNUL:
482 v->allc = malloc( &v->ptr, 1 );
483 v->ptr[0] = '\0';
484 v->slen = 0;
485 break;
486
487 case a_VARARR:
488 awka_error("runtime error: awka_getre in file %s, line %d - %s\n", file,line,"array used as scalar");
489 }
490
491 if (!v->ptr)
492 {
493 v->allc = malloc( &v->ptr, 1 );
494 v->slen = 0;
495 v->ptr[0] = '\0';
496 }
497
498 switch (type)
499 {
500 case _RE_SPLIT:
501 r = _awka_compile_regexp_SPLIT(v->ptr, v->slen); break;
502 case _RE_MATCH:
503 r = _awka_compile_regexp_MATCH(v->ptr, v->slen); break;
504 case _RE_GSUB:
505 r = _awka_compile_regexp_GSUB(v->ptr, v->slen); break;
506 }
507 if (!r)
508 awka_error("runtime error: Regular Expression failed to compile, file %s line %d\n",file,line);
509 free(v->ptr);
510 v->ptr = (char *) r;
511
512 v->type = a_VARREG;
513 return r;
514 }
515
516 char **
awka_setsval(a_VAR * v,char * file,int line)517 awka_setsval( a_VAR *v, char *file, int line )
518 {
519 if (v->type == a_VARARR)
520 awka_error("runtime error: awka_sets in file %s, line %d - %s\n", file,line,"array used as scalar");
521 else if (v->type == a_VARREG)
522 _awka_re2null(v);
523 else if (v->ptr)
524 {
525 free(v->ptr);
526 v->ptr = NULL;
527 }
528
529 v->slen = 0;
530 v->allc = 0;
531 v->type2 = 0;
532 v->type = a_VARSTR;
533 return &(v->ptr);
534 }
535
536 a_VAR *
awka_strdcpy(a_VAR * v,double d)537 awka_strdcpy( a_VAR *v, double d )
538 {
539 char tmp[256];
540 int i = (int) d;
541
542 if ((double) i == d)
543 sprintf(tmp, "%d", i);
544 else
545 sprintf(tmp, awka_gets1(a_bivar[a_CONVFMT]), d);
546
547 i = strlen(tmp);
548
549 if (v->type == a_VARSTR || v->type == a_VARUNK)
550 {
551 if (!v->ptr)
552 v->allc = malloc( &v->ptr, i+1 );
553 else if (i >= v->allc)
554 v->allc = realloc( &v->ptr, i+1 );
555 }
556 else
557 v->allc = malloc( &v->ptr, i+1 );
558
559 v->slen = i;
560 memcpy(v->ptr, tmp, i+1);
561 v->type = a_VARSTR;
562 return v;
563 }
564
565 a_VAR *
awka_strscpy(a_VAR * v,char * s)566 awka_strscpy( a_VAR *v, char *s )
567 {
568 register int i = strlen(s);
569 if (v->type == a_VARSTR || v->type == a_VARUNK)
570 {
571 if (!v->ptr)
572 v->allc = malloc( &v->ptr, i+1 );
573 else if (v->allc < i)
574 v->allc = realloc( &v->ptr, i+1 );
575 }
576 else
577 v->allc = malloc( &v->ptr, i+1 );
578
579 v->slen = i;
580 memcpy(v->ptr, s, i+1);
581 v->type = a_VARSTR;
582 return v;
583 }
584
585 a_VAR *
awka_vardup(a_VAR * v)586 awka_vardup( a_VAR *v )
587 {
588 a_VAR *ret;
589 _awka_tmpvar(ret);
590 awka_varcpy(ret, v);
591 return ret;
592 }
593
594 double
awka_vardblset(a_VAR * v,double d)595 awka_vardblset( a_VAR *v, double d )
596 {
597 if (v->type == a_VARARR)
598 awka_error("runtime error: awka_vardblset - %s\n", "array used as scalar");
599
600 _awka_set_FW(v);
601 if (v->type == a_VARREG)
602 _awka_re2null(v);
603
604 _awka_set_FW(v);
605
606 v->type2 = 0;
607 if (v->type == a_VARSTR || v->type == a_VARUNK)
608 {
609 if (v->ptr)
610 free(v->ptr);
611 v->ptr = NULL;
612 v->slen = 0;
613 v->allc = 0;
614 }
615
616 v->type = a_VARDBL;
617 v->dval = d;
618
619 if (_awka_setdoln == TRUE)
620 _awka_setdol0_len = TRUE;
621 if (v == a_bivar[a_DOL0])
622 {
623 _rebuild0_now = FALSE;
624 _rebuildn = TRUE;
625 }
626 return v->dval;
627 }
628
629 a_VAR *
awka_varcpy(a_VAR * va,a_VAR * vb)630 awka_varcpy( a_VAR *va, a_VAR *vb )
631 {
632 int prev_len = -1;
633 register char *ptr;
634 register unsigned int allc;
635
636 if (vb->type == a_VARARR || va->type == a_VARARR)
637 awka_error("runtime error: awka_varcpy - %s\n", "array used as scalar");
638
639 _awka_set_FW(va);
640 if (va == vb) return va;
641
642 va->dval = vb->dval;
643 va->type2 = vb->type2;
644
645 switch (vb->type)
646 {
647 case a_VARSTR:
648 case a_VARUNK:
649 prev_len = va->slen;
650 if (vb->temp == 1)
651 { /* don't need vb beyond this statement */
652 /* swap pointers - this is very efficient */
653 if (va->type == a_VARREG)
654 _awka_re2null(va);
655 ptr = va->ptr;
656 allc = va->allc;
657 va->ptr = vb->ptr;
658 va->allc = vb->allc;
659 va->slen = vb->slen;
660 vb->ptr = ptr;
661 if (ptr) ptr[0] = '\0';
662 vb->type2 = 0;
663 vb->slen = 0;
664 vb->allc = allc;
665 vb->dval = 0;
666 }
667 else
668 {
669 /* we need both va & vb, memcpy is necessary */
670 awka_forcestr(va);
671 if (va->ptr && va->allc <= vb->slen)
672 va->allc = realloc( &va->ptr, vb->slen+1 );
673 else if (!va->ptr)
674 va->allc = malloc( &va->ptr, vb->slen+1 );
675 memcpy(va->ptr, vb->ptr, vb->slen+1);
676 va->slen = vb->slen;
677 }
678 va->type = vb->type;
679 va->type2 = vb->type2;
680 break;
681
682 case a_VARREG:
683 if (va->ptr) awka_killvar(va);
684 va->ptr = vb->ptr;
685 break;
686
687 case a_VARDBL:
688 if (vb->ptr && vb->type2 == a_STRSET)
689 {
690 if (!va->ptr || !va->allc)
691 va->allc = malloc( &va->ptr, vb->slen+1 );
692 else if (va->ptr && va->allc <= vb->slen)
693 va->allc = realloc( &va->ptr, vb->slen+1 );
694 memcpy(va->ptr, vb->ptr, vb->slen+1);
695 va->slen = vb->slen;
696 }
697 }
698 va->type = vb->type;
699
700 if (_awka_setdoln == TRUE)
701 {
702 if (prev_len != -1)
703 {
704 _awka_dol0_len -= prev_len;
705 _awka_dol0_len += vb->slen;
706 _awka_setdoln = _awka_setdol0_len = FALSE;
707 }
708 else
709 _awka_setdol0_len = TRUE;
710 }
711 if (va == a_bivar[a_DOL0])
712 {
713 _rebuild0_now = FALSE;
714 _rebuildn = TRUE;
715 }
716 return va;
717 }
718
719 void
_awka_checkunk(a_VAR * va)720 _awka_checkunk(a_VAR *va)
721 {
722 if (va->type2 == 0 && va->ptr)
723 {
724 if (!isalpha(va->ptr[0]) &&
725 _awka_isnumber(va->ptr) == TRUE)
726 {
727 va->type2 = a_DBLSET;
728 va->dval = strtod(va->ptr, NULL);
729 }
730 /*
731 else
732 va->type2 = -1;
733 */ /* commented in 0.5.10 as causing grief */
734 }
735 }
736
737 double
awka_varcmp(a_VAR * va,a_VAR * vb)738 awka_varcmp( a_VAR *va, a_VAR *vb )
739 {
740 int i;
741
742 if (vb->type == a_VARARR || va->type == a_VARARR)
743 awka_error("runtime error: awka_varcmp", "array used as scalar");
744
745 if (va == vb) return 0;
746 if (va->type == a_VARUNK && va->type2 == 0 && va->ptr)
747 _awka_checkunk(va);
748 if (vb->type == a_VARUNK && vb->type2 == 0 && vb->ptr)
749 _awka_checkunk(vb);
750 if ((va->type <= a_VARDBL ||
751 (va->type == a_VARUNK && va->type2 == a_DBLSET)) &&
752 (vb->type <= a_VARDBL ||
753 (vb->type == a_VARUNK && vb->type2 == a_DBLSET)))
754 {
755 /* double comparison */
756 if (va->dval == vb->dval)
757 return 0;
758 else
759 return ((va->dval < vb->dval) ? -1 : 1);
760 }
761
762 i = strcmp(awka_gets1(va), awka_gets1(vb));
763 return ((i == 0) ? 0 : ((i < 0) ? -1 : 1));
764 }
765
766 int
awka_vartrue(a_VAR * v)767 awka_vartrue( a_VAR *v )
768 {
769 if (v->type == a_VARSTR && v->ptr)
770 {
771 if (v->ptr[0] != '\0')
772 return 1;
773 else
774 return 0;
775 }
776 if (v->type == a_VARDBL && v->dval != 0.0)
777 return 1;
778 if (v->type == a_VARUNK)
779 {
780 if (v->ptr && v->ptr[0] != '\0' && strcmp(v->ptr, "0"))
781 return 1;
782 if (v->type2 == a_DBLSET && v->dval != 0.0)
783 return 1;
784 }
785 if (v->type == a_VARREG)
786 return 1;
787 return 0;
788 }
789
790 double
awka_var2dblcmp(a_VAR * va,double d)791 awka_var2dblcmp( a_VAR *va, double d )
792 {
793 int i;
794
795 if (va->type == a_VARARR)
796 awka_error("runtime error: awka_var2dblcmp", "array used as scalar");
797
798 if (va->type == a_VARUNK && va->type2 == 0 && va->ptr)
799 _awka_checkunk(va);
800
801 if (va->type <= a_VARDBL || (va->type == a_VARUNK && va->type2 == a_DBLSET))
802 return (va->dval == d ? 0 : (va->dval < d ? -1 : 1));
803 if (!(i = strcmp(awka_gets1(va), awka_tmp_dbl2str(d))))
804 return 0;
805 return (i < 0 ? -1 : 1);
806 }
807
808 double
awka_dbl2varcmp(double d,a_VAR * va)809 awka_dbl2varcmp( double d, a_VAR *va )
810 {
811 int i;
812
813 if (va->type == a_VARARR)
814 awka_error("runtime error: awka_var2dblcmp", "array used as scalar");
815
816 if (va->type2 == 0 && va->ptr && va->type == a_VARUNK)
817 _awka_checkunk(va);
818
819 if (va->type <= a_VARDBL || (va->type == a_VARUNK && va->type2 == a_DBLSET))
820 {
821 i = (d == va->dval ? 0 : (d < va->dval ? -1 : 1));
822 return (double) i;
823 }
824 if (!(i = strcmp(awka_tmp_dbl2str(d), awka_gets1(va))))
825 return 0;
826 return (i < 0 ? -1 : 1);
827 }
828
829 int
awka_nullval(char * s)830 awka_nullval( char *s )
831 {
832 double d;
833 char *p;
834
835 d = strtod(s, NULL);
836 if (!d)
837 {
838 p = s + (strlen(s)-1);
839 while ((*p == ' ' || *p == '\t') && p > s) p--;
840 p++;
841 *p = '\0';
842 p = s;
843 while (*p == ' ' || *p == '\t') p++;
844 while (*p)
845 {
846 if (isalpha(*p) ||
847 (ispunct(*p) && *p != '.') ||
848 (isdigit(*p) && *p != '0')) break;
849 p++;
850 }
851 if (*p == '\0')
852 return 1;
853 }
854 return 0;
855 }
856
857
858 a_VAR *
awka_tmp_dbl2var(double d)859 awka_tmp_dbl2var(double d)
860 {
861 a_VAR *v;
862
863 _awka_tmpvar(v);
864 if (v->ptr && v->type == a_VARREG)
865 _awka_re2null(v);
866
867 /* v->ptr = NULL; */
868 v->type = a_VARDBL;
869 v->slen = 0;
870 /* v->allc = 0; */
871 v->dval = d;
872 v->type2 = 0;
873 return v;
874 }
875
876 a_VAR *
awka_ro_str2var(char * c)877 awka_ro_str2var(char *c)
878 {
879 a_VAR *v;
880 int i = strlen(c);
881
882 _awka_tmpvar_ro(v);
883
884 v->type = a_VARSTR;
885 v->ptr = c;
886 v->slen = i;
887 v->allc = 0;
888 v->dval = 0;
889 v->type2 = 0;
890 return v;
891 }
892
893 a_VAR *
awka_tmp_str2var(char * c)894 awka_tmp_str2var(char *c)
895 {
896 a_VAR *v;
897 int i = strlen(c);
898
899 _awka_tmpvar(v);
900
901 if (v->type == a_VARSTR || v->type == a_VARUNK || v->type == a_VARREG)
902 {
903 if (v->type == a_VARREG) _awka_re2null(v);
904 if (v->allc <= i)
905 v->allc = realloc( &v->ptr, i+1 );
906 else if (!v->ptr)
907 v->allc = malloc( &v->ptr, i+1 );
908 }
909 else
910 {
911 if (v->ptr) free(v->ptr);
912 v->allc = malloc( &v->ptr, i+1 );
913 }
914
915 v->type = a_VARSTR;
916 memcpy(v->ptr, c, i+1);
917 v->slen = i;
918 v->dval = 0;
919 v->type2 = 0;
920
921 return v;
922 }
923
924 a_VAR *
awka_tmp_re2var(awka_regexp * r)925 awka_tmp_re2var(awka_regexp *r)
926 {
927 a_VAR *v;
928
929 _awka_tmpvar(v);
930
931 if (v->ptr)
932 awka_killvar(v);
933
934 v->ptr = (char *) r;
935 v->type = a_VARREG;
936 v->slen = 0;
937 v->allc = 0;
938 v->dval = 0;
939 v->type2 = 0;
940
941 return v;
942 }
943
944 char *
awka_tmp_dbl2str(double d)945 awka_tmp_dbl2str(double d)
946 {
947 char *s, tmp[256];
948 int i = (int) d, len;
949
950 if ((double) i == d)
951 sprintf(tmp, "%d", i);
952 else
953 sprintf(tmp, awka_gets1(a_bivar[a_CONVFMT]), d);
954
955 i = strlen(tmp)+1;
956 len = i + (32 - (i % 32));
957
958 _awka_tmpvar_c(s, len);
959 memcpy(s, tmp, i);
960 return s;
961 }
962
963 #ifdef MEM_DEBUG
964 char *
awka_strcpy(a_VAR * v,char * s)965 awka_strcpy(a_VAR *v, char *s)
966 {
967 register int _slen = strlen(s)+1, allc_len;
968 _awka_set_FW(v);
969 if (v->type == a_VARREG)
970 _awka_re2s(v);
971 if (v->type != a_VARSTR && v->type != a_VARUNK)
972 awka_setsval(v, __FILE__, __LINE__);
973 if (v->ptr && v->allc <= _slen)
974 v->allc = realloc( (void **) &v->ptr, _slen );
975 else if (!v->ptr)
976 v->allc = malloc( (void **) &v->ptr, _slen );
977 v->slen = _slen-1;
978 memcpy(v->ptr, s, _slen);
979 v->type = a_VARSTR;
980 v->type2 = 0;
981 if (v == a_bivar[a_DOL0])
982 {
983 _rebuild0_now = FALSE;
984 _rebuildn = TRUE;
985 }
986 return v->ptr;
987 }
988 #endif
989
990