* array.c - routines for associative arrays.
* Copyright (C) 1986, 1988, 1989, 1991, 1992 the Free Software Foundation, Inc.
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
* GAWK is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* GAWK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with GAWK; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
static NODE
*assoc_find
P((NODE
*symbol
, NODE
*subs
, int hash1
));
if (tree
->type
!= Node_expression_list
)
return force_string(tree_eval(tree
));
r
= force_string(tree_eval(tree
->lnode
));
subseplen
= SUBSEP_node
->lnode
->stlen
;
subsep
= SUBSEP_node
->lnode
->stptr
;
len
= r
->stlen
+ subseplen
+ 2;
emalloc(str
, char *, len
, "concat_exp");
memcpy(str
, r
->stptr
, r
->stlen
+1);
memcpy(s
, subsep
, subseplen
+1);
r
= force_string(tree_eval(tree
->lnode
));
len
+= r
->stlen
+ subseplen
;
erealloc(str
, char *, len
, "concat_exp");
memcpy(s
, r
->stptr
, r
->stlen
+1);
r
= make_str_node(str
, s
- str
, ALREADY_MALLOCED
);
/* Flush all the values in symbol[] before doing a split() */
if (symbol
->var_array
== 0)
for (i
= 0; i
< HASHSIZE
; i
++) {
for (bucket
= symbol
->var_array
[i
]; bucket
; bucket
= next
) {
symbol
->var_array
[i
] = 0;
* calculate the hash function of the string in subs
register unsigned long h
= 0, g
;
static NODE
* /* NULL if not found */
assoc_find(symbol
, subs
, hash1
)
register NODE
*bucket
, *prev
= 0;
for (bucket
= symbol
->var_array
[hash1
]; bucket
; bucket
= bucket
->ahnext
) {
if (cmp_nodes(bucket
->ahname
, subs
) == 0) {
if (prev
) { /* move found to front of chain */
prev
->ahnext
= bucket
->ahnext
;
bucket
->ahnext
= symbol
->var_array
[hash1
];
symbol
->var_array
[hash1
] = bucket
;
prev
= bucket
; /* save previous list entry */
* test whether the array element symbol[subs] exists or not
if (symbol
->type
== Node_param_list
)
symbol
= stack_ptr
[symbol
->param_cnt
];
if (symbol
->var_array
== 0)
subs
= concat_exp(subs
); /* concat_exp returns a string node */
hash1
= hash(subs
->stptr
, subs
->stlen
);
if (assoc_find(symbol
, subs
, hash1
) == NULL
) {
* SYMBOL is the address of the node (or other pointer) being dereferenced.
* SUBS is a number or string used as the subscript.
* Find SYMBOL[SUBS] in the assoc array. Install it with value "" if it
* isn't there. Returns a pointer ala get_lhs to where its value is stored
assoc_lookup(symbol
, subs
)
(void) force_string(subs
);
hash1
= hash(subs
->stptr
, subs
->stlen
);
if (symbol
->var_array
== 0) { /* this table really should grow
size
= sizeof(NODE
*) * HASHSIZE
;
emalloc(symbol
->var_array
, NODE
**, size
, "assoc_lookup");
memset((char *)symbol
->var_array
, 0, size
);
symbol
->type
= Node_var_array
;
bucket
= assoc_find(symbol
, subs
, hash1
);
return &(bucket
->ahvalue
);
/* It's not there, install it. */
if (do_lint
&& subs
->stlen
== 0)
warning("subscript of array `%s' is null string",
bucket
->type
= Node_ahash
;
bucket
->ahname
= dupnode(subs
);
unsigned int saveflags
= subs
->flags
;
bucket
->ahname
= dupnode(subs
);
/* array subscripts are strings */
bucket
->ahname
->flags
&= ~NUMBER
;
bucket
->ahname
->flags
|= STRING
;
bucket
->ahvalue
= Nnull_string
;
bucket
->ahnext
= symbol
->var_array
[hash1
];
symbol
->var_array
[hash1
] = bucket
;
return &(bucket
->ahvalue
);
register NODE
*bucket
, *last
;
if (symbol
->type
== Node_param_list
)
symbol
= stack_ptr
[symbol
->param_cnt
];
if (symbol
->var_array
== 0)
subs
= concat_exp(tree
); /* concat_exp returns string node */
hash1
= hash(subs
->stptr
, subs
->stlen
);
for (bucket
= symbol
->var_array
[hash1
]; bucket
; last
= bucket
, bucket
= bucket
->ahnext
)
if (cmp_nodes(bucket
->ahname
, subs
) == 0)
last
->ahnext
= bucket
->ahnext
;
symbol
->var_array
[hash1
] = bucket
->ahnext
;
assoc_scan(symbol
, lookat
)
if (!symbol
->var_array
) {
lookat
->arr_ptr
= symbol
->var_array
;
lookat
->arr_end
= lookat
->arr_ptr
+ HASHSIZE
; /* added */
lookat
->bucket
= symbol
->var_array
[0];
while (lookat
->arr_ptr
< lookat
->arr_end
) {
if (lookat
->bucket
!= 0) {
lookat
->retval
= lookat
->bucket
->ahname
;
lookat
->bucket
= lookat
->bucket
->ahnext
;
if (lookat
->arr_ptr
< lookat
->arr_end
)
lookat
->bucket
= *(lookat
->arr_ptr
);