1 /*--------------------------------------------------*
2 | var.h |
3 | Header file for var.c, part of the Awka |
4 | Library, Copyright 1999, Andrew Sumner. |
5 | This file is covered by the GNU General Public |
6 | License (GPL). |
7 *--------------------------------------------------*/
8
9 #ifndef _VAR_H
10 #define _VAR_H
11
12 #define a_VARNUL 0 /* vars not set to anything yet */
13 #define a_VARDBL 1 /* vars set to double */
14 #define a_VARSTR 2 /* vars set to string */
15 #define a_VARARR 4 /* array variables */
16 #define a_VARREG 5 /* regular expressions */
17 #define a_VARUNK 6 /* contents of a split array & return from getline */
18
19 #define a_DBLSET 7 /* indicates string var with double value set */
20 #define a_STRSET 8 /* indicates double var with string value set */
21
22 /* builtin variables */
23 #define a_ARGC 0
24 #define a_ARGIND 1
25 #define a_ARGV 2
26 #define a_CONVFMT 3
27 #define a_ENVIRON 4
28 #define a_FILENAME 5
29 #define a_FNR 6
30 #define a_FS 7
31 #define a_NF 8
32 #define a_NR 9
33 #define a_OFMT 10
34 #define a_OFS 11
35 #define a_ORS 12
36 #define a_RLENGTH 13
37 #define a_RS 14
38 #define a_RSTART 15
39 #define a_RT 16
40 #define a_SUBSEP 17
41 #define a_DOL0 18
42 #define a_DOLN 19
43 #define a_FIELDWIDTHS 20
44 #define a_SAVEWIDTHS 21
45 #define a_SORTTYPE 22
46 #define a_PROCINFO 23
47
48 #define a_BIVARS 24
49
50 #define _RE_SPLIT 0
51 #define _RE_MATCH 1
52 #define _RE_GSUB 2
53
54 typedef struct {
55 double dval; /* double value, set when type & a_DBLVAR */
56 char * ptr; /* string value, except with array vars */
57 unsigned int slen; /* length of ptr as returned by strlen */
58 unsigned int allc; /* space mallocated for ptr */
59 char type; /* records current cast of variable */
60 char type2; /* for string vars, TRUE if dval is set */
61 char temp; /* TRUE if a temporary variable */
62 } a_VAR;
63
64 typedef struct {
65 a_VAR *var[256];
66 int used;
67 } a_VARARG;
68
69 void awka_killvar( a_VAR * );
70 a_VAR * _awka_getdval( a_VAR *, char *, int );
71 a_VAR * _awka_setdval( a_VAR *, char *, int );
72 char * _awka_getsval( a_VAR *, char, char *, int );
73 char ** awka_setsval( a_VAR *, char *, int );
74 awka_regexp * _awka_getreval( a_VAR *, char *, int, char );
75 awka_regexp * _awka_compile_regexp_SPLIT(char *str, unsigned len);
76 awka_regexp * _awka_compile_regexp_MATCH(char *str, unsigned len);
77 awka_regexp * _awka_compile_regexp_GSUB(char *str, unsigned len);
78 a_VAR * awka_strdcpy( a_VAR *, double d );
79 a_VAR * awka_strscpy( a_VAR *, char *s );
80 double awka_vardblset( a_VAR *, double d );
81 a_VAR * awka_varcpy( a_VAR *, a_VAR * );
82 int awka_vartrue( a_VAR *v );
83 double awka_varcmp( a_VAR *, a_VAR * );
84 double awka_dbl2varcmp( double, a_VAR * );
85 double awka_var2dblcmp( a_VAR *, double );
86 int awka_nullval( char * );
87 double awka_str2pow( char * );
88 void awka_parsecmdline(int first);
89 a_VAR * awka_tmp_dbl2var(double);
90 char * awka_tmp_dbl2str(double);
91 a_VAR * awka_tmp_str2var(char *);
92 a_VAR * awka_ro_str2var(char *);
93 a_VAR * awka_tmp_str2revar(char *);
94 a_VAR * awka_tmp_re2var(awka_regexp *r);
95 void _awka_re2s(a_VAR *);
96 void _awka_re2null(a_VAR *);
97 a_VAR * awka_vardup(a_VAR *);
98 double awka_postinc(a_VAR *);
99 double awka_postdec(a_VAR *);
100
101 #ifndef _INIT_C
102 extern a_VAR *a_bivar[a_BIVARS];
103 #else
104 a_VAR *a_bivar[a_BIVARS];
105 #endif
106
107 #ifndef _VAR_C
108 extern char _awka_arg_change;
109 #endif
110
111 #ifndef _ARRAY_C
112 extern char fs_or_fw, _awka_setdol0_len;
113 extern char _rebuild0, _rebuildn, _rebuild0_now;
114 #endif
115
116 #define _awka_set_FW(v) \
117 if ((v) == a_bivar[a_FS]) \
118 fs_or_fw = 0; \
119 else if ((v) == a_bivar[a_FIELDWIDTHS]) \
120 fs_or_fw = 1;
121
122 static int
awka_isadbl(char * s,int len)123 awka_isadbl( char *s, int len )
124 {
125 register char *p = s, dot = FALSE;
126
127 /* while (*p == ' ') p++; */
128 for ( ;*p; p++)
129 {
130 if (*p == '.')
131 {
132 if (dot == TRUE)
133 return FALSE;
134 dot = TRUE;
135 continue;
136 }
137 if (*p == ' ') break;
138 if (!isdigit(*p)) return FALSE;
139 }
140
141 if (!*p) return TRUE;
142
143 /* while (*p == ' ') p++; */
144 if (*p) return FALSE;
145 return TRUE;
146 }
147
148 static a_VAR *
awka_getdval(a_VAR * v,char * file,int line)149 awka_getdval( a_VAR *v, char *file, int line )
150 {
151 if (v->type == a_VARDBL || v->type2 == a_DBLSET)
152 return v;
153 return _awka_getdval(v, file, line);
154 }
155
156 static a_VAR *
awka_setdval(a_VAR * v,char * file,int line)157 awka_setdval( a_VAR *v, char *file, int line )
158 {
159 v->type2 = 0;
160 if (v->type == a_VARDBL)
161 return v;
162
163 return _awka_setdval(v, file, line);
164 }
165
166 static char *
awka_getsval(a_VAR * v,char ofmt,char * file,int line)167 awka_getsval( a_VAR *v, char ofmt, char *file, int line )
168 {
169 if (v->type == a_VARSTR || v->type == a_VARUNK ||
170 (v->type == a_VARDBL && v->type2 == a_STRSET))
171 return v->ptr;
172 return _awka_getsval(v, ofmt, file, line );
173 }
174
175 static char *
awka_getsvalP(a_VAR * v,char ofmt,char * file,int line)176 awka_getsvalP( a_VAR *v, char ofmt, char *file, int line )
177 {
178 if (v->type == a_VARSTR || v->type == a_VARUNK)
179 return v->ptr;
180 return _awka_getsval(v, ofmt, file, line );
181 }
182
183 static awka_regexp *
awka_getreval(a_VAR * v,char * file,int line)184 awka_getreval( a_VAR *v, char *file, int line )
185 {
186 v->type2 = 0;
187 if (v->type == a_VARREG && v->ptr)
188 return (awka_regexp *) v->ptr;
189 return _awka_getreval(v, file, line, _RE_MATCH);
190 }
191
192 static void
awka_forcestr(a_VAR * v)193 awka_forcestr( a_VAR *v )
194 {
195 v->type2 = 0;
196 if (v->type != a_VARSTR && v->type != a_VARUNK)
197 awka_setsval(v, __FILE__, __LINE__);
198 v->type = a_VARSTR;
199 }
200
201 static a_VAR *
awka_argv()202 awka_argv()
203 {
204 _awka_arg_change = TRUE;
205 return a_bivar[a_ARGV];
206 }
207
208 static a_VAR *
awka_argc()209 awka_argc()
210 {
211 _awka_arg_change = TRUE;
212 return a_bivar[a_ARGC];
213 }
214
215 static void
awka_lcopy(a_VAR * va,a_VAR * vb)216 awka_lcopy(a_VAR *va, a_VAR *vb)
217 {
218 va->ptr = vb->ptr;
219 va->slen = vb->slen;
220 va->allc = 0;
221 va->dval = vb->dval;
222 va->type = vb->type;
223 va->type2 = vb->type2;
224 }
225
226 #define awka_getd(v) (awka_getdval((v),__FILE__,__LINE__)->dval)
227 #define awka_setd(v) (awka_setdval((v),__FILE__,__LINE__)->dval)
228 #define awka_gets(v) (awka_getsval((v),0,__FILE__,__LINE__))
229 #define awka_getsP(v) (awka_getsvalP((v),1,__FILE__,__LINE__))
230 #define awka_sets(v) (*(awka_setsval((v),__FILE__,__LINE__)))
231 #define awka_getre(v) (awka_getreval((v),__FILE__,__LINE__))
232
233 #define awka_gets1(v) ((v)->ptr && ((v)->type == a_VARSTR || (v)->type == a_VARUNK) ? (v)->ptr : _awka_getsval((v),0,__FILE__,__LINE__))
234 #define awka_gets1P(v) ((v)->ptr && ((v)->type == a_VARSTR || (v)->type == a_VARUNK) ? (v)->ptr : _awka_getsval((v),1,__FILE__,__LINE__))
235 #define awka_getd1(v) ((v)->type == a_VARDBL || (v)->type2 == a_DBLSET ? (v)->dval : _awka_getdval((v),__FILE__,__LINE__)->dval)
236
237 #define awka_poi(v) (((v)->type == a_VARDBL && (v)->type2 != a_STRSET) ? ((v)->dval)++ : awka_postinc(v))
238 #define awka_pri(v) (((v)->type == a_VARDBL && (v)->type2 != a_STRSET) ? ++(v)->dval : ++awka_setd(v))
239 #define awka_pod(v) (((v)->type == a_VARDBL && (v)->type2 != a_STRSET) ? ((v)->dval)-- : awka_postdec(v))
240 #define awka_prd(v) (((v)->type == a_VARDBL && (v)->type2 != a_STRSET) ? --(v)->dval : --awka_setd(v))
241
242 #define awka_varinit(v) { \
243 malloc( (void **) &(v), sizeof(a_VAR) ); \
244 (v)->dval = 0.0; \
245 (v)->temp = (v)->type2 = 0; \
246 (v)->type = a_VARNUL; \
247 (v)->slen = (v)->allc = 0; \
248 (v)->ptr = NULL; }
249
250 a_VAR * awka_argval(int, a_VAR *, int, int, a_VARARG *);
251 void _awka_addfnvar(int, int, a_VAR *, int);
252 a_VAR * _awka_usefnvar(int, int);
253 a_VAR * _awka_addfncall(int);
254 void _awka_retfn(int);
255 int _awka_registerfn(char *, int);
256
257 static a_VAR *
awka_fn_varinit(int fn_idx,int var_idx,int type)258 awka_fn_varinit(int fn_idx, int var_idx, int type)
259 {
260 a_VAR *var;
261
262 if (!(var = _awka_usefnvar(fn_idx, var_idx)))
263 {
264 awka_varinit(var);
265 var->temp = 2;
266 _awka_addfnvar(fn_idx, var_idx, var, type);
267 }
268 return var;
269 }
270
271 #ifdef MEM_DEBUG
272 char *awka_strcpy(a_VAR *v, char *s);
273 #else
274 static char *
awka_strcpy(a_VAR * v,char * s)275 awka_strcpy(a_VAR *v, char *s)
276 {
277 register int _slen = strlen(s)+1;
278 _awka_set_FW(v);
279 if (v->type == a_VARREG)
280 _awka_re2s(v);
281 if (v->type != a_VARSTR && v->type != a_VARUNK)
282 awka_setsval(v, __FILE__, __LINE__);
283 if (v->ptr && v->allc <= _slen)
284 v->allc = realloc( (void **) &v->ptr, _slen );
285 else if (!v->ptr)
286 v->allc = malloc( (void **) &v->ptr, _slen );
287 v->slen = _slen-1;
288 memcpy(v->ptr, s, _slen);
289 v->type = a_VARSTR;
290 v->type2 = 0;
291 if (v == a_bivar[a_DOL0])
292 {
293 _rebuild0_now = _rebuild0 = FALSE;
294 _rebuildn = _awka_setdol0_len = TRUE;
295 }
296 return v->ptr;
297 }
298 #endif
299
300 static char *
awka_strncpy(a_VAR * v,char * s,int _slen)301 awka_strncpy(a_VAR *v, char *s, int _slen)
302 {
303 _awka_set_FW(v);
304 if (v->type == a_VARREG)
305 _awka_re2s(v);
306 if (v->type != a_VARSTR && v->type != a_VARUNK)
307 awka_setsval(v, __FILE__, __LINE__);
308 if (v->ptr && v->allc <= _slen+1)
309 v->allc = realloc( (void **) &v->ptr, _slen+1 );
310 else if (!v->ptr)
311 v->allc = malloc( (void **) &v->ptr, _slen+1 );
312 v->slen = _slen;
313 memcpy(v->ptr, s, _slen);
314 v->ptr[_slen] = '\0';
315 v->type = a_VARSTR;
316 v->type2 = 0;
317 return v->ptr;
318 }
319
320 static void
awka_setstrlen(a_VAR * v,register int slen)321 awka_setstrlen(a_VAR *v, register int slen)
322 {
323 _awka_set_FW(v);
324 slen++;
325 if (v->type == a_VARREG)
326 _awka_re2s(v);
327 if (v->type != a_VARSTR && v->type != a_VARUNK)
328 awka_setsval(v, __FILE__, __LINE__);
329 if (v->ptr && v->allc < slen)
330 v->allc = realloc( (void **) &v->ptr, slen );
331 else if (!(v)->ptr)
332 v->allc = malloc( (void **) &v->ptr, slen );
333 v->slen = slen - 1;
334 v->type2 = 0;
335 }
336
337 #define awka_strtrue(s) ((s)[0] != '\0' ? 1 : 0)
338
339 static double
_awka_dnotzero(double d,char * file,int line)340 _awka_dnotzero(double d, char *file, int line)
341 {
342 if (d == 0.0)
343 awka_error("Math Error: Divide By Zero, file %s line %d.\n",file,line);
344 return d;
345 }
346
347 #define awka_dnotzero(d) _awka_dnotzero(d, __FILE__, __LINE__)
348
349 static double
awka_div(double d1,double d2)350 awka_div(double d1, double d2)
351 {
352 if (d2 == 0.0)
353 awka_error("Math Error: Divide By Zero");
354 return d1 / d2;
355 }
356
357 #endif
358