1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2014 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * David Korn <dgkorn@gmail.com> *
18 * *
19 ***********************************************************************/
20 //
21 // David Korn
22 // AT&T Labs
23 //
24 // Interface definitions of structures for name-value pairs.
25 // These structures are used for named variables, functions and aliases.
26 //
27 #ifndef _NAME_H
28 #define _NAME_H 1
29
30 #include <stdbool.h>
31 #include <stdio.h>
32
33 #include "ast.h"
34 #include "ast_assert.h"
35 #include "cdt.h"
36 #include "option.h"
37
38 struct pathcomp;
39
40 // Nodes can have all kinds of values. We track the type last stored and check the type is what we
41 // expect on retrieval.
42 //
43 // This list must be kept in sync with the `value_type_names` array in module "name.c". These values
44 // do not have to be in the same order as the elements of the union in `struct Value` but keeping
45 // them in the same order is a good idea. You also have to update the `dprint_vtp_dispatch` array in
46 // module "debug.c" if this list is changed.
47 enum value_type {
48 VT_do_not_use = 0,
49 VT_vp,
50 VT_cp,
51 VT_const_cp,
52 VT_pp,
53 VT_uc,
54 VT_h,
55 VT_i,
56 VT_l,
57 VT_d,
58 VT_f,
59 VT_i16,
60 VT_ip,
61 VT_i16p,
62 VT_i32p,
63 VT_i64p,
64 VT_dp,
65 VT_fp,
66 VT_sfdoublep,
67 VT_np,
68 VT_up,
69 VT_rp,
70 VT_funp,
71 VT_nrp,
72 VT_shbltinp,
73 VT_pathcomp,
74 VT_pidp,
75 VT_uidp,
76 VT_sentinal // this has to be the last member of this enum
77 };
78
79 // The following array in name.c must be kept in sync with enum value_type.
80 extern const char *value_type_names[];
81
82 struct Value {
83 const char *funcname;
84 const char *filename;
85 int line_num;
86 enum value_type type;
87 union {
88 void *vp;
89 char *cp;
90 const char *const_cp;
91 char **pp;
92
93 unsigned char uc;
94 short h;
95 int i;
96 long l;
97 double d;
98 float f;
99 int16_t i16;
100
101 int *ip;
102 int16_t *i16p;
103 int32_t *i32p;
104 int64_t *i64p;
105 double *dp;
106 float *fp;
107
108 Sfdouble_t *sfdoublep;
109 struct Namval *np;
110 struct Value *up;
111 struct Ufunction *rp;
112 struct Namfun *funp;
113 struct Namref *nrp;
114 Shbltin_f shbltinp;
115 struct pathcomp *pathcomp;
116
117 pid_t *pidp;
118 uid_t *uidp;
119 } _val;
120 };
121
122 // I dislike macros like these but since C doesn't support polymorphism directly this is the most
123 // straightforward way to access any of the fields of the value union.
124 //
125 // TODO: Remove the `1 ||` once the obvious bugs introduced by converting `union Value` to the
126 // `struct Value` above have been eliminated.
127 #if 1 || !DEBUG_BUILD
128
129 // Non-debugging versions of the struct Value getter functions.
130 #define fetch_vt(line, value_obj, which) (value_obj)._val.which
131 #define fetch_vtp(line, value_objp, which) (value_objp)->_val.which
132
133 #else
134
135 // Debugging versions of the struct Value getter functions.
136 #define fetch_abort() 0 // abort()
137 #define fetch_backtrace() 0 // dump_backtrace(0)
138
139 #define fetch_vt(line, value_obj, which) \
140 (((value_obj).type == VT_##which || (VT_##which == VT_vp) || \
141 (VT_##which == VT_const_cp && (value_obj).type == VT_cp)) \
142 ? (value_obj)._val.which \
143 : (DPRINTF("fetched value type != stored type:"), \
144 DPRINTF("fetching \"%s\"", value_type_names[VT_##which]), \
145 DPRINTF("stored \"%s\" @ %s:%d in %s()", value_type_names[(value_obj).type], \
146 (value_obj).filename ? (value_obj).filename : "undef", (value_obj).line_num, \
147 (value_obj).funcname ? (value_obj).funcname : "undef"), \
148 fetch_backtrace(), fetch_abort(), (value_obj)._val.which))
149
150 #define fetch_vtp(line, value_objp, which) \
151 (((value_objp)->type == VT_##which || (VT_##which == VT_vp) || \
152 (VT_##which == VT_const_cp && (value_objp)->type == VT_cp)) \
153 ? (value_objp)->_val.which \
154 : (DPRINTF("fetched value type != stored type:"), \
155 DPRINTF("fetching \"%s\"", value_type_names[VT_##which]), \
156 DPRINTF("stored \"%s\" @ %s:%d in %s()", value_type_names[(value_objp)->type], \
157 (value_objp)->filename ? (value_objp)->filename : "undef", \
158 (value_objp)->line_num, \
159 (value_objp)->funcname ? (value_objp)->funcname : "undef"), \
160 fetch_backtrace(), fetch_abort(), (value_objp)->_val.which))
161
162 #endif
163
164 #define dprint_vtp(value_objp) \
165 DPRINTF("stored value type \"%s\" @ %s:%d in %s()", value_type_names[(value_objp)->type], \
166 (value_objp)->filename ? (value_objp)->filename : "undef", (value_objp)->line_num, \
167 (value_objp)->funcname ? (value_objp)->funcname : "undef")
168
169 #define is_vt(value_obj, which) ((value_obj).type == VT_##which)
170
171 #define is_vtp(value_objp, which) ((value_objp)->type == VT_##which)
172
173 // Always store all the meta data. Even if building without the getter checks enabled. That's
174 // because a) the info may be useful when debugging core dumps, and b) the value type is needed for
175 // the IS_VT macro.
176 #define store_vt(line, value_obj, which, val) \
177 do { \
178 (value_obj).funcname = __FUNCTION__; \
179 (value_obj).filename = strrchr(__FILE__, '/') + 1; \
180 (value_obj).line_num = line; \
181 (value_obj).type = VT_##which; \
182 (value_obj)._val.which = val; \
183 } while (0)
184
185 #define store_vtp(line, value_objp, which, val) \
186 do { \
187 (value_objp)->funcname = __FUNCTION__; \
188 (value_objp)->filename = strrchr(__FILE__, '/') + 1; \
189 (value_objp)->line_num = line; \
190 (value_objp)->type = VT_##which; \
191 (value_objp)->_val.which = val; \
192 } while (0)
193
194 // These four macros must be used when retrieving or storing a value in a `struct Value` object.
195 #define FETCH_VT(value_obj, which) fetch_vt(__LINE__, value_obj, which)
196 #define FETCH_VTP(value_objp, which) fetch_vtp(__LINE__, value_objp, which)
197 #define STORE_VT(value_obj, which, val) store_vt(__LINE__, value_obj, which, val)
198 #define STORE_VTP(value_objp, which, val) store_vtp(__LINE__, value_objp, which, val)
199
200 // These two macros can be used to test the type of the value stored in the `struct Value` object.
201 #define IS_VT(value_obj, which) is_vt(value_obj, which)
202 #define IS_VTP(value_objp, which) is_vtp(value_objp, which)
203
204 typedef struct Namdisc Namdisc_t;
205 typedef struct Nambfun Nambfun_t;
206 typedef struct Namarray Namarr_t;
207 typedef struct Namdecl Namdecl_t;
208
209 // Any place that assigns or compares the NV_* symbols below to a var should use `nvflag_t` for the
210 // type of the var rather than `unsigned short`, `int`, etc.
211 typedef uint32_t nvflag_t;
212 // Number of low numbered bits valid in a (struct Namval).nvflag.
213 #define NV_nbits 16
214
215 //
216 // This defines the template for nodes that have their own assignment and or lookup functions.
217 //
218 struct Namdisc {
219 size_t dsize;
220 void (*putval)(Namval_t *, const void *, nvflag_t, Namfun_t *);
221 char *(*getval)(Namval_t *, Namfun_t *);
222 Sfdouble_t (*getnum)(Namval_t *, Namfun_t *);
223 char *(*setdisc)(Namval_t *, const void *, Namval_t *, Namfun_t *);
224 Namval_t *(*createf)(Namval_t *, const void *, nvflag_t, Namfun_t *);
225 Namfun_t *(*clonef)(Namval_t *, Namval_t *, nvflag_t, Namfun_t *);
226 char *(*namef)(const Namval_t *, Namfun_t *);
227 Namval_t *(*nextf)(Namval_t *, Dt_t *, Namfun_t *);
228 Namval_t *(*typef)(Namval_t *, Namfun_t *);
229 int (*readf)(Namval_t *, Sfio_t *, int, Namfun_t *);
230 int (*writef)(Namval_t *, Sfio_t *, int, Namfun_t *);
231 };
232
233 struct Namfun {
234 const Namdisc_t *disc;
235 char nofree;
236 unsigned char subshell;
237 uint32_t dsize;
238 Namfun_t *next;
239 char *last;
240 Namval_t *type;
241 };
242
243 struct Nambfun {
244 Namfun_t fun;
245 int num;
246 const char **bnames;
247 Namval_t *bltins[1];
248 };
249
250 // The following constants define operations on associative arrays performed by `nv_associative()`.
251 enum {
252 ASSOC_OP_INIT_val = 1, // initialize
253 ASSOC_OP_FREE_val, // free array
254 ASSOC_OP_NEXT_val, // advance to next subscript
255 ASSOC_OP_NAME_val, // return subscript name
256 ASSOC_OP_DELETE_val, // delete current subscript
257 ASSOC_OP_ADD_val, // add subscript if not found
258 ASSOC_OP_ADD2_val, // ??? (this used to be the constant zero passed to nv_associative())
259 ASSOC_OP_CURRENT_val, // return current subscript Namval_t*
260 ASSOC_OP_SETSUB_val, // set current subscript
261 };
262
263 typedef struct {
264 int val;
265 } Nvassoc_op_t;
266 extern const Nvassoc_op_t ASSOC_OP_INIT;
267 extern const Nvassoc_op_t ASSOC_OP_FREE;
268 extern const Nvassoc_op_t ASSOC_OP_NEXT;
269 extern const Nvassoc_op_t ASSOC_OP_NAME;
270 extern const Nvassoc_op_t ASSOC_OP_DELETE;
271 extern const Nvassoc_op_t ASSOC_OP_ADD;
272 extern const Nvassoc_op_t ASSOC_OP_ADD2;
273 extern const Nvassoc_op_t ASSOC_OP_CURRENT;
274 extern const Nvassoc_op_t ASSOC_OP_SETSUB;
275
276 // This is an array template header.
277 struct Namarray {
278 Namfun_t namfun;
279 long nelem; // number of elements
280 void *(*fun)(Namval_t *, const char *, Nvassoc_op_t); // associative array ops
281 Dt_t *table; // for subscripts
282 Dt_t *scope; // non-NULL when scoped
283 int flags;
284 };
285
286 // The context pointer for declaration command.
287 struct Namdecl {
288 Namval_t *tp; // point to type
289 const char *optstring;
290 Optdisc_t *optinfof;
291 };
292
293 // This defines the attributes for a name-value node.
294 struct Namval {
295 Dtlink_t nvlink; // space for cdt links
296 char *nvname; // pointer to name of the node
297 nvflag_t nvflag; // attributes
298 uint32_t nvsize; // size or base
299 Namfun_t *nvfun; // pointer to trap functions
300 struct Value nvalue; // value field
301 Shell_t *nvshell; // shell pointer
302 Namval_t *nvenv; // pointer to environment name
303 bool nvenv_is_cp;
304 };
305
306 #define NV_CLASS ".sh.type"
307 #define NV_DATA "_" // special class or instance variable
308 #define NV_MINSZ (sizeof(struct Namval) - sizeof(Dtlink_t) - sizeof(char *))
309 #define nv_namptr(p, n) ((Namval_t *)((char *)(p) + (n)*NV_MINSZ - sizeof(Dtlink_t)))
310
311 // Namval attribute bits for use with nv_isattr(), nv_onattr(), nv_offattr(), etc. These affect how
312 // a namval behaves although not all of them affect the value. Some, such as NV_NOFREE, don't affect
313 // the interpretation of the value but do affect how the namval node behaves.
314 //
315 // For the moment we are limited to 16 bits since the namval->nvflag is an unsigned short.
316 //
317 // Note: If these definitions are changed remember to update `nvflags` in src/cmd/ksh93/sh/debug.c.
318 #define NV_RDONLY ((nvflag_t)1 << 0) // readonly bit -- does not affect the value
319 #define NV_INTEGER ((nvflag_t)1 << 1) // integer attribute
320 #define NV_LTOU ((nvflag_t)1 << 2) // convert to uppercase
321 #define NV_UTOL ((nvflag_t)1 << 3) // convert to lowercase
322 #define NV_ZFILL ((nvflag_t)1 << 4) // right justify and fill with leading zeros
323 #define NV_RJUST ((nvflag_t)1 << 5) // right justify and blank fill
324 #define NV_LJUST ((nvflag_t)1 << 6) // left justify and blank fill
325 #define NV_MISC ((nvflag_t)1 << 7) // this is overloaded to mean many things
326 #define NV_BINARY ((nvflag_t)1 << 8) // fixed size data buffer
327 #define NV_NOFREE ((nvflag_t)1 << 9) // don't free the space when releasing value
328 #define NV_ARRAY ((nvflag_t)1 << 10) // node is an array
329 #define NV_TABLE ((nvflag_t)1 << 11) // node is a dictionary table
330 #define NV_IMPORT ((nvflag_t)1 << 12) // value imported from environment
331 #define NV_EXPORT ((nvflag_t)1 << 13) // export bit -- does not affect the value
332 #define NV_REF ((nvflag_t)1 << 14) // reference bit
333 #define NV_TAGGED ((nvflag_t)1 << 15) // user tagged (typeset -t ...) -- does not affect the value
334
335 // Aliases or compound types.
336 #define NV_RAW NV_LJUST // used only with NV_BINARY
337 #define NV_HOST (NV_RJUST | NV_LJUST) // map to host filename
338 #define NV_MINIMAL NV_IMPORT // node does not contain all fields
339 #define NV_BLTINOPT NV_ZFILL // mark builtins in `shtab_builtins[]` that are optional
340 #define NV_NODISC NV_MISC // ignore disciplines
341 #define NV_CLONED NV_MISC // the value is cloned from an outer scope and thus can't be freed
342
343 #define NV_NOPRINT (NV_LTOU | NV_UTOL) // do not print
344 #define NV_NOALIAS (NV_NOPRINT | NV_IMPORT)
345 #define NV_NOEXPAND NV_RJUST // do not expand alias
346 #define NV_BLTIN (NV_NOPRINT | NV_EXPORT)
347 #define NV_NOTSET (NV_INTEGER | NV_BINARY)
348
349 // The following are used with NV_INTEGER.
350 #define NV_SHORT NV_RJUST // when integers are not long
351 #define NV_LONG NV_UTOL // for long long and long double
352 #define NV_UNSIGN NV_LTOU // for unsigned quantities
353 #define NV_DOUBLE (NV_INTEGER | NV_ZFILL) // for floating point
354 #define NV_EXPNOTE NV_LJUST // for scientific notation
355 #define NV_HEXFLOAT NV_LTOU // for C99 base16 float notation
356
357 // Numeric types.
358 #define NV_INT16P (NV_LJUST | NV_SHORT | NV_INTEGER)
359 // #define NV_UINT16P (NV_LJUST | NV_UNSIGN | NV_SHORT | NV_INTEGER)
360 #define NV_INT16 (NV_SHORT | NV_INTEGER)
361 #define NV_INT32 NV_INTEGER
362 #define NV_INT64 (NV_LONG | NV_INTEGER)
363 #define NV_UINT16 (NV_UNSIGN | NV_SHORT | NV_INTEGER)
364 #define NV_UINT32 (NV_UNSIGN | NV_INTEGER)
365 // #define NV_UINT64 (NV_UNSIGN | NV_LONG | NV_INTEGER)
366 #define NV_FLOAT (NV_SHORT | NV_DOUBLE)
367 #define NV_LDOUBLE (NV_LONG | NV_DOUBLE)
368
369 // JSON handling.
370 #if SUPPORT_JSON
371 #define NV_JSON NV_TAGGED // for json formatting
372 #define NV_JSON_LAST NV_TABLE // last for json formatting
373 #else
374 #define NV_JSON 0
375 #define NV_JSON_LAST 0
376 #endif // SUPPORT_JSON
377
378 // These are for use with nodes which are not name-values.
379 #define NV_FUNCTION (NV_RJUST | NV_FUNCT) // value is shell function
380 #define NV_FPOSIX NV_LJUST // posix function semantics
381 #define NV_FTMP NV_ZFILL // function source in tmpfile
382 #define NV_STATICF NV_INTEGER // static class function
383 #define NV_OPTGET NV_BINARY // function calls getopts
384 #define NV_SHVALUE NV_TABLE // function assigns .sh.value
385
386 // Options for nv_open(), nv_search(), sh_setlist(), etc. They are not valid bits in a nvflag_t;
387 // i.e., (struct Namval*)->nvflag.
388 #define NV_APPEND ((nvflag_t)1 << 16) // append value
389 #define NV_VARNAME ((nvflag_t)1 << 17) // name must be ?(.)id*(.id)
390 #define NV_NOADD ((nvflag_t)1 << 18) // do not add node
391 #define NV_NOSCOPE ((nvflag_t)1 << 19) // look only in current scope
392 #define NV_NOFAIL ((nvflag_t)1 << 20) // return 0 on failure, no msg
393 #define NV_NOARRAY ((nvflag_t)1 << 21) // array name not possible
394 #define NV_IARRAY ((nvflag_t)1 << 22) // for indexed array
395 #define NV_ADD ((nvflag_t)1 << 23) // add node if not found
396 #define NV_UNJUST ((nvflag_t)1 << 23) // clear justify attributes
397 #define NV_TYPE ((nvflag_t)1 << 24)
398 #define NV_STATIC ((nvflag_t)1 << 25)
399 #define NV_COMVAR ((nvflag_t)1 << 26)
400 #define NV_MOVE ((nvflag_t)1 << 27) // for use with nv_clone()
401 #define NV_ASSIGN ((nvflag_t)1 << 28) // assignment is allowed
402 #define NV_DECL ((nvflag_t)1 << 29)
403
404 // This serves two purposes. First, it may help detect an nvflag_t value that has the high bit set
405 // when that should not occur. Second, it provides a way to silence Coverity Scan warnings about
406 // "logically dead code" due to constructs like `nvflag & NV_JSON` always being false when JSON
407 // support is disabled and `NV_JSON` would otherwise be defined as zero.
408 //
409 // This definition causes only the high bit to be set in a portable manner regardless of the size
410 // of nvflag_t.
411 #define NV_INVALID (~(~(nvflag_t)0 >> 1))
412
413 // See the uses of these symbols in name.c.
414 #define NV_NOREF NV_REF // don't follow reference
415 #define NV_FUNCT NV_IDENT // option for nv_create
416 #define NV_IDENT NV_MISC // name must be identifier
417
418 // Name-value attribute test or modification routines. These used to be macros. They are now static
419 // inline functions rather than macros to facilitate instrumentation while still being fast. In
420 // particular validating the nvflag value; both current and new. Variants such as nv_isnull() are
421 // not static inline functions because they do more work and were historically extern functions.
422
423 // Check that nvflag is valid. At the moment this is just a sanity check that the high bit is
424 // not set since that should never happen.
425 #ifdef NDEBUG
426 #define nv_isvalid(nvflag) ((vpoi)0)
427 #else // NDEBUG
nv_isvalid(const nvflag_t nvflag)428 static inline void nv_isvalid(const nvflag_t nvflag) {
429 if (nvflag & NV_INVALID) {
430 DPRINTF("nvflag_t %" PRIX32 " is not valid", nvflag);
431 dump_backtrace(0);
432 abort();
433 }
434 }
435 #endif // NDEBUG
436
437 // Return true if the mask is set in nvflags.
nv_isflag(const nvflag_t nvflags,const nvflag_t mask)438 static inline bool nv_isflag(const nvflag_t nvflags, const nvflag_t mask) {
439 nv_isvalid(nvflags);
440 nv_isvalid(mask);
441 if (!mask) return false;
442 return (nvflags & mask) == mask;
443 }
444
445 // Return any bits in mask that are set in the Namval_t.
446 // TODO: Convert this to returning a truth value (all bits in mask set or not) to mimic nv_isflag().
nv_isattr(const Namval_t * np,const nvflag_t mask)447 static inline int nv_isattr(const Namval_t *np, const nvflag_t mask) { return np->nvflag & mask; }
448
nv_isarray(const Namval_t * np)449 static inline bool nv_isarray(const Namval_t *np) { return nv_isattr(np, NV_ARRAY) == NV_ARRAY; }
450
nv_onattr(Namval_t * np,nvflag_t nvflag)451 static inline void nv_onattr(Namval_t *np, nvflag_t nvflag) {
452 nv_isvalid(nvflag);
453 nv_isvalid(np->nvflag);
454 nvflag &= ~(~(nvflag_t)0U << NV_nbits); // strip bits valid for nv_open() but not nvflag
455 np->nvflag |= nvflag;
456 }
457
nv_offattr(Namval_t * np,nvflag_t nvflag)458 static inline void nv_offattr(Namval_t *np, nvflag_t nvflag) {
459 nv_isvalid(nvflag);
460 nv_isvalid(np->nvflag);
461 nvflag &= ~(~(nvflag_t)0U << NV_nbits); // strip bits valid for nv_open() but not nvflag
462 np->nvflag &= ~nvflag;
463 }
464
nv_setattr(Namval_t * np,nvflag_t nvflag)465 static inline void nv_setattr(Namval_t *np, nvflag_t nvflag) {
466 nv_isvalid(nvflag);
467 nv_isvalid(np->nvflag);
468 nvflag &= ~(~(nvflag_t)0U << NV_nbits); // strip bits valid for nv_open() but not nvflag
469 np->nvflag = nvflag;
470 }
471
472 // The following symbols are for use with nv_disc().
473 enum {
474 DISC_OP_NOOP_val = 1, // ??? (this used to be the magic `0` constant used by four callers)
475 DISC_OP_FIRST_val, // Move or push <fp> to top of the stack or delete top
476 DISC_OP_LAST_val, // Move or push <fp> to bottom of stack or delete last
477 DISC_OP_POP_val, // Delete <fp> from top of the stack
478 DISC_OP_CLONE_val // Replace <fp> with a copy created my malloc() and return it
479 };
480
481 typedef struct {
482 int val;
483 } Nvdisc_op_t;
484
485 extern const Nvdisc_op_t DISC_OP_NOOP;
486 extern const Nvdisc_op_t DISC_OP_FIRST;
487 extern const Nvdisc_op_t DISC_OP_LAST;
488 extern const Nvdisc_op_t DISC_OP_POP;
489 extern const Nvdisc_op_t DISC_OP_CLONE;
490
491 // The following are operations for nv_putsub().
492 #define ARRAY_BITS 22
493 #define ARRAY_ADD ((nvflag_t)1 << (0 + ARRAY_BITS)) // add subscript if not found
494 #define ARRAY_SCAN ((nvflag_t)1 << (1 + ARRAY_BITS)) // For ${array[@]}
495 #define ARRAY_UNDEF ((nvflag_t)1 << (2 + ARRAY_BITS)) // For ${array}
496
497 // These symbols are passed to `nv_discfun()` to cause it to return a set of disciplines that
498 // implement a specific policy. We start with the arbitrary value 19 to help ensure that calling
499 // `nv_discfun()` with an unexpected op value will fail.
500 typedef enum {
501 DISCFUN_ADD = 19, // for vars that have named shell level disciplines (e.g., var.get() {...})
502 DISCFUN_RESTRICT // for vars that cannot be modified in a restricted shell
503 } Nvdiscfun_op_t;
504
505 // Prototype for array interface.
506 extern Namarr_t *nv_arrayptr(Namval_t *);
507 extern Namarr_t *nv_setarray(Namval_t *, void *(*)(Namval_t *, const char *, Nvassoc_op_t));
508 extern int nv_arraynsub(Namarr_t *);
509 extern void *nv_associative(Namval_t *, const char *, Nvassoc_op_t);
510 extern int nv_aindex(Namval_t *);
511 extern bool nv_nextsub(Namval_t *);
512 extern char *nv_getsub(Namval_t *);
513 extern Namval_t *nv_putsub(Namval_t *, char *, long, nvflag_t);
514 extern Namval_t *nv_opensub(Namval_t *);
515
516 // Name-value pair function prototypes.
517 extern bool nv_adddisc(Namval_t *, const char **, Namval_t **);
518 extern int nv_clone(Namval_t *, Namval_t *, nvflag_t);
519 extern void nv_close(Namval_t *);
520 extern Namval_t *nv_create(const char *, Dt_t *, nvflag_t, Namfun_t *);
521 extern void nv_delete(Namval_t *, Dt_t *, nvflag_t);
522 extern Dt_t *nv_dict(Namval_t *);
523 extern Sfdouble_t nv_getn(Namval_t *, Namfun_t *);
524 extern Sfdouble_t nv_getnum(Namval_t *);
525 extern char *nv_getv(Namval_t *, Namfun_t *);
526 extern char *nv_getval(Namval_t *);
527 extern Namfun_t *nv_hasdisc(const Namval_t *, const Namdisc_t *);
528 extern bool nv_isnull(Namval_t *);
529 extern Namfun_t *nv_isvtree(Namval_t *);
530 extern Namval_t *nv_lastdict(void *);
531 extern Namval_t *nv_mkinttype(char *, size_t, int, const char *, Namdisc_t *);
532 extern void nv_newattr(Namval_t *, nvflag_t, int);
533 extern void nv_newtype(Namval_t *);
534 extern Namval_t *nv_open(const char *, Dt_t *, nvflag_t);
535 extern void nv_putval(Namval_t *, const void *, nvflag_t);
536 extern void nv_putv(Namval_t *, const void *, nvflag_t, Namfun_t *);
537 extern bool nv_rename(Namval_t *, nvflag_t);
538 extern int nv_scan(Dt_t *, void (*)(Namval_t *, void *), void *, nvflag_t, nvflag_t);
539 extern char *nv_setdisc(Namval_t *, const void *, Namval_t *, Namfun_t *);
540 extern void nv_setref(Namval_t *, Dt_t *, nvflag_t);
541 extern int nv_settype(Namval_t *, Namval_t *, nvflag_t);
542 extern void nv_setvec(Namval_t *, int, int, char *[]);
543 extern void nv_setvtree(Namval_t *);
544 extern int nv_setsize(Namval_t *, int);
545 extern Namfun_t *nv_disc(Namval_t *, Namfun_t *, Nvdisc_op_t);
546 extern int nv_unall(char **, bool, nvflag_t, Dt_t *, Shell_t *);
547 extern void nv_unset(Namval_t *); /*obsolete */
548 extern void _nv_unset(Namval_t *, nvflag_t);
549 extern Namval_t *nv_search(const char *, Dt_t *, nvflag_t);
550 extern Namval_t *nv_search_namval(const Namval_t *, Dt_t *, nvflag_t);
551 extern char *nv_name(const Namval_t *);
552 extern Namval_t *nv_type(Namval_t *);
553 // Note that the third parameter should be a pointer to a Optdisc_t or a structure where that type
554 // is the first member.
555 extern void nv_addtype(Namval_t *, const char *, void *, size_t);
556 extern const Namdisc_t *nv_discfun(Nvdiscfun_op_t);
557
558 #define nv_unset(np) _nv_unset(np, 0)
559 #define nv_size(np) nv_setsize((np), -1)
560 #define nv_stack(np, nf) nv_disc(np, nf, DISC_OP_NOOP)
561
562 // Used for arrays.
563 #if _ast_sizeof_pointer >= 8
564 #define ARRAY_MAX (1UL << 31) // maximum number of elements in an array
565 #else
566 #define ARRAY_MAX (1UL << ARRAY_BITS) // maximum number of elements in an array
567 #endif
568
569 // Number of elements to grow when array bound exceeded. Must be a power of 2.
570 #define ARRAY_INCR 32
571 #define ARRAY_FILL ((nvflag_t)1 << (3 + ARRAY_BITS)) // used with nv_putsub()
572 #define ARRAY_NOCLONE ((nvflag_t)1 << (4 + ARRAY_BITS)) // do not clone array disc
573 #define ARRAY_NOCHILD ((nvflag_t)1 << (5 + ARRAY_BITS)) // skip compound arrays
574 #define ARRAY_SETSUB ((nvflag_t)1 << (6 + ARRAY_BITS)) // set subscript
575 #define ARRAY_NOSCOPE ((nvflag_t)1 << (7 + ARRAY_BITS)) // top level scope only
576 #define ARRAY_TREE ((nvflag_t)1 << (8 + ARRAY_BITS)) // arrays of compound vars
577
578 // These flags are used as options to array_get().
579 #define ARRAY_ASSIGN 0
580 #define ARRAY_LOOKUP 1
581 #define ARRAY_DELETE 2
582
583 struct Namref {
584 Namval_t *np;
585 Namval_t *table;
586 Namval_t *oldnp;
587 Dt_t *root;
588 char *sub;
589 };
590
591 // This describes a user shell function node.
592 struct Ufunction {
593 int64_t lineno; // line number of function start
594 int *ptree; // address of parse tree
595 short argc; // number of references
596 short running; // function is running
597 char **argv; // reference argument list
598 off_t hoffset; // offset into source or history file
599 Namval_t *nspace; // pointer to name space
600 char *fname; // file name where function defined
601 char *help; // help string
602 Dt_t *sdict; // dictionary for statics
603 Dt_t *fdict; // dictionary node belongs to
604 Namval_t *np; // function node pointer
605 };
606
607 #ifndef ARG_RAW
608 struct argnod;
609 #endif // !ARG_RAW
610
611 // Attributes of Namval_t items.
612
613 // The following attributes are for internal use.
614 #define NV_NOCHANGE (NV_EXPORT | NV_IMPORT | NV_RDONLY | NV_TAGGED | NV_NOFREE | NV_ARRAY)
615 #define NV_PARAM NV_NODISC // expansion use positional params
616
617 #define BLT_ENV (NV_RDONLY) // non-stoppable, can modify environment
618 #define BLT_DISABLE (NV_BINARY) // bltin disabled
619 #define BLT_SPC (NV_TAGGED) // special built-ins
620 #define BLT_EXIT (NV_RJUST) // exit value can be > 255
621 #define BLT_DCL (NV_LJUST) // declaration command
622 #define BLT_NOSFIO (NV_IMPORT) // doesn't use sfio
623
624 #define nv_isref(n) (nv_isattr((n), NV_REF | NV_TAGGED | NV_FUNCT) == NV_REF)
625 #define is_abuiltin(n) (nv_isattr(n, NV_BLTIN | NV_INTEGER) == NV_BLTIN)
626 #define is_afunction(n) (nv_isattr(n, NV_FUNCTION | NV_REF) == NV_FUNCTION)
627 #define nv_funtree(n) FETCH_VT((n)->nvalue, rp)->ptree
628 #define funptr(n) FETCH_VT((n)->nvalue, shbltinp)
629
630 #define NV_SUBQUOTE (NV_ADD << 1) // used with nv_endsubscript
631
632 // NAMNOD macros.
633 //
634 // ... for attributes.
635 #define nv_context(_np) ((void *)(_np)->nvfun)
636 // The following are for name references.
637 #define nv_refnode(_np) FETCH_VT((_np)->nvalue, nrp)->np
638 #define nv_reftree(_np) FETCH_VT((_np)->nvalue, nrp)->root
639 #define nv_reftable(_np) FETCH_VT((_np)->nvalue, nrp)->table
640 #define nv_refsub(_np) FETCH_VT((_np)->nvalue, nrp)->sub
641 #define nv_refoldnp(_np) FETCH_VT((_np)->nvalue, nrp)->oldnp
642 // ... for etc.
643 #define nv_setsize(_np, s) ((_np)->nvsize = ((s)*4) | 2)
644 #undef nv_size
645 #define nv_size(_np) ((_np)->nvsize >> 2)
646 #define nv_attr(_np) ((_np)->nvflag & ~NV_MINIMAL)
647 // ... for arrays.
648 #define array_elem(ap) ((ap)->nelem)
649 // An array is associative if it has a function pointer else it is a simple indexed array.
650 #define is_associative(ap) ((ap)->fun)
651
652 struct nvdir;
653
654 extern int array_maxindex(Namval_t *);
655 extern int array_isempty(Namval_t *);
656 extern char *nv_endsubscript(Namval_t *, char *, nvflag_t, void *);
657 extern Namfun_t *nv_cover(Namval_t *);
658 extern Namarr_t *nv_arrayptr(Namval_t *);
659 extern bool nv_arrayisset(Namval_t *, Namarr_t *);
660 extern bool nv_arraysettype(Namval_t *, Namval_t *, const char *, nvflag_t);
661 extern int nv_aimax(Namval_t *);
662 extern struct Value *nv_aivec(Namval_t *, unsigned char **);
663 extern int nv_aipack(Namarr_t *);
664 extern bool nv_atypeindex(Namval_t *, const char *);
665 extern bool nv_setnotify(Namval_t *, char **);
666 extern bool nv_unsetnotify(Namval_t *, char **);
667 extern struct argnod *nv_onlist(struct argnod *, const char *);
668 extern void nv_optimize(Namval_t *);
669 extern void nv_unref(Namval_t *);
670 extern bool nv_hasget(Namval_t *);
671 void clone_all_disc(Namval_t *, Namval_t *, nvflag_t);
672 extern Namfun_t *nv_clone_disc(Namfun_t *, nvflag_t);
673 extern struct nvdir *nv_diropen(Namval_t *, const char *, void *);
674 extern char *nv_dirnext(void *);
675 extern void nv_dirclose(struct nvdir *);
676 extern char *nv_getvtree(Namval_t *, Namfun_t *);
677 extern void nv_attribute(Namval_t *, Sfio_t *, char *, int);
678 extern Namval_t *nv_bfsearch(const char *, Dt_t *, Namval_t **, char **);
679 extern Namval_t *nv_mkclone(Namval_t *);
680 extern Namval_t *nv_mktype(Namval_t **, int);
681 extern Namval_t *nv_addnode(Namval_t *, int);
682 extern Namval_t *nv_parent(const Namval_t *);
683 extern Namval_t *nv_mount(Namval_t *, const char *name, Dt_t *);
684 extern Namval_t *nv_arraychild(Namval_t *, Namval_t *, int);
685 extern int nv_compare(Dt_t *, void *, void *, Dtdisc_t *);
686 extern void nv_outnode(Namval_t *, Sfio_t *, int, int);
687 extern bool nv_subsaved(Namval_t *, bool);
688 extern void nv_typename(Namval_t *, Sfio_t *);
689 extern void nv_newtype(Namval_t *);
690 extern Namval_t *nv_typeparent(Namval_t *);
691 extern bool nv_istable(const Namval_t *);
692 extern size_t nv_datasize(Namval_t *, size_t *);
693 extern Namfun_t *nv_mapchar(Namval_t *, const char *);
694 extern void nv_checkrequired(Namval_t *);
695
696 extern const Namdisc_t RESTRICTED_disc;
697 extern const Namdisc_t ENUM_disc;
698 extern const Namdisc_t OPTIMIZE_disc;
699 extern bool nv_local;
700 extern Dtdisc_t _Nvdisc;
701 extern const char *nv_discnames[];
702 extern const char e_subscript[];
703 extern const char e_nullset[];
704 extern const char e_notset[];
705 extern const char e_notset2[];
706 extern const char e_noparent[];
707 extern const char e_notelem[];
708 extern const char e_readonly[];
709 extern const char e_badfield[];
710 extern const char e_restricted[];
711 extern const char e_ident[];
712 extern const char e_varname[];
713 extern const char e_noalias[];
714 extern const char e_noarray[];
715 extern const char e_notenum[];
716 extern const char e_nounattr[];
717 extern const char e_aliname[];
718 extern const char e_badexport[];
719 extern const char e_badref[];
720 extern const char e_badsubscript[];
721 extern const char e_noref[];
722 extern const char e_selfref[];
723 extern const char e_staticfun[];
724 extern const char e_envmarker[];
725 extern const char e_badlocale[];
726 extern const char e_loop[];
727 extern const char e_redef[];
728 extern const char e_required[];
729 extern const char e_badappend[];
730 extern const char e_unknowntype[];
731 extern const char e_unknownmap[];
732 extern const char e_mapchararg[];
733 extern const char e_subcomvar[];
734 extern const char e_badtypedef[];
735 extern const char e_typecompat[];
736 extern const char e_globalref[];
737 extern const char e_tolower[];
738 extern const char e_toupper[];
739 extern const char e_wordbreaks[];
740
741 #endif // _NAME_H
742