aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2012-10-05 12:56:31 +0200
committerArnold D. Robbins <arnold@skeeve.com>2012-10-05 12:56:31 +0200
commitbcb0224f8f2d19cd03a2527eec2f5eb42abef7cd (patch)
tree674e7412188b1c7fb6decd02575e70f0d74247b6
parent5caf2424094016b9a26c5d9d74b25cab39671478 (diff)
parent81896b422307105edb9908958bbedd09967d9a05 (diff)
downloadegawk-bcb0224f8f2d19cd03a2527eec2f5eb42abef7cd.tar.gz
egawk-bcb0224f8f2d19cd03a2527eec2f5eb42abef7cd.tar.bz2
egawk-bcb0224f8f2d19cd03a2527eec2f5eb42abef7cd.zip
Merge branch 'symtab'
-rw-r--r--ChangeLog48
-rw-r--r--awk.h32
-rw-r--r--awkgram.c272
-rw-r--r--awkgram.y14
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/awkcard.in24
-rw-r--r--doc/gawk.166
-rw-r--r--doc/gawk.info602
-rw-r--r--doc/gawk.texi64
-rw-r--r--eval.c1
-rw-r--r--interpret.h47
-rw-r--r--main.c8
-rw-r--r--profile.c9
-rw-r--r--symbol.c302
-rw-r--r--test/ChangeLog7
-rw-r--r--test/Makefile.am91
-rw-r--r--test/Makefile.in130
-rw-r--r--test/Maketests40
-rw-r--r--test/functab1.awk3
-rw-r--r--test/functab1.ok2
-rw-r--r--test/functab2.awk8
-rw-r--r--test/functab2.ok2
-rw-r--r--test/functab3.awk10
-rw-r--r--test/functab3.ok2
-rw-r--r--test/functab4.awk14
-rw-r--r--test/functab4.ok3
-rw-r--r--test/id.awk11
-rw-r--r--test/id.ok32
-rw-r--r--test/symtab1.awk18
-rw-r--r--test/symtab1.ok31
-rw-r--r--test/symtab2.awk6
-rw-r--r--test/symtab2.ok2
-rw-r--r--test/symtab3.awk1
-rw-r--r--test/symtab3.ok2
34 files changed, 1259 insertions, 649 deletions
diff --git a/ChangeLog b/ChangeLog
index 2e13d319..1aa1097a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -17,6 +17,54 @@
extension/Makefile.in, extension/aclocal.m4, test/Makefile.in:
Regenerated.
+ * interpret.h (Op_Subscript): Added lint warnings for FUNCTAB
+ and SYMTAB.
+
+2012-10-02 Arnold D. Robbins <arnold@skeeve.com>
+
+ * awk.h (func_table): Declare.
+ * awkgram.y: If do_posix or do_traditional, then check for
+ delete on SYMTAB. Add check for delete on FUNCTAB, also.
+ * interpret.h (Op_Subscript): For FUNCTAB, return the element name
+ as its value too. Avoids lots of weirdness and allows indirect calls
+ after assignment from FUNCTAB["foo"] to work.
+ (Op_store_sub): Disallow assignment to elements of FUNCTAB.
+ (Op_indirect_func_all): Turn assert into check and fatal error.
+ * symbol.c (func_table): No longer static.
+ (lookup): If do_posix or do_traditional, skip the global table.
+ (release_all_vars): Clear func_table too.
+
+2012-09-25 Arnold D. Robbins <arnold@skeeve.com>
+
+ First cut at SYMTAB and FUNCTAB. This does the following:
+ - Change symbol table handling to use gawk arrays.
+ - Store symbols in SYMTAB array and allow indirect access
+ through SYMTAB to variables, both getting and setting.
+ - List function names in FUNCTAB indexes; Values cannot be
+ used at the moment.
+ - No documentation yet.
+
+ * awk.h (Node_hashnode, hnext, hname, hlength, hcode, hvalue):
+ Removed, not needed any more.
+ (init_symbol_table, symbol_table): Add declarations.
+ * awkgram.y: Disallow delete on SYMTAB, fix warning for tawk
+ extension if traditional.
+ * eval.c (nodetypes): Remove Node_hashnode element.
+ * interpret.h (Op_subscript, Op_store_sub): Handle SYMTAB and go
+ through to the actual value.
+ * main.c (main): Init Nnull_string earlier. Add call to
+ init_symbol_table().
+ * profile.c (pp_str, pp_len): Change definitions.
+ (pp_next): New macro.
+ (pp_push, pp_pop): Adjust uses.
+ * symbol.c (variables): Removed.
+ (global_table, param_table, func_table, symbol_table,
+ installing_specials): New variables.
+ (lookup, make_params, install_params, remove_params, remove_symbol,
+ make_symbol, install, get_symbols, release_all_vars, append_symbol,
+ release_symbols, load_symbols): Rework logic considerably.
+ (init_symbol_table): New function.
+
2012-09-23 Arnold D. Robbins <arnold@skeeve.com>
`delete array' and `nextfile' are now in POSIX.
diff --git a/awk.h b/awk.h
index 28ed92ce..f7f41209 100644
--- a/awk.h
+++ b/awk.h
@@ -314,7 +314,6 @@ typedef enum nodevals {
Node_func, /* lnode is param. list, rnode is body */
Node_ext_func, /* extension function, code_ptr is builtin code */
- Node_hashnode, /* an identifier in the symbol table */
Node_array_ref, /* array passed by ref as parameter */
Node_array_tree, /* Hashed array tree (HAT) */
Node_array_leaf, /* Linear 1-D array */
@@ -462,17 +461,11 @@ typedef struct exp_node {
#define nextp sub.nodep.l.lptr
#define rnode sub.nodep.r.rptr
-/* Node_hashnode, Node_param_list */
-#define hnext sub.nodep.r.rptr
-#define hname vname
-#define hlength sub.nodep.reserved
-#define hcode sub.nodep.cnt
-#define hvalue sub.nodep.x.extra
+/* Node_param_list */
+#define param vname
/* Node_param_list, Node_func */
#define param_cnt sub.nodep.l.ll
-/* Node_param_list */
-#define param vname
/* Node_func */
#define fparms sub.nodep.rn
@@ -1372,15 +1365,15 @@ if (--val) \
/* array.c */
typedef enum sort_context { SORTED_IN = 1, ASORT, ASORTI } SORT_CTXT;
enum assoc_list_flags {
-AINDEX = 0x01, /* list of indices */
-AVALUE = 0x02, /* list of values */
-AINUM = 0x04, /* numeric index */
-AISTR = 0x08, /* string index */
-AVNUM = 0x10, /* numeric scalar value */
-AVSTR = 0x20, /* string scalar value */
-AASC = 0x40, /* ascending order */
-ADESC = 0x80, /* descending order */
-ADELETE = 0x100, /* need a single index; for use in do_delete_loop */
+ AINDEX = 0x01, /* list of indices */
+ AVALUE = 0x02, /* list of values */
+ AINUM = 0x04, /* numeric index */
+ AISTR = 0x08, /* string index */
+ AVNUM = 0x10, /* numeric scalar value */
+ AVSTR = 0x20, /* string scalar value */
+ AASC = 0x40, /* ascending order */
+ ADESC = 0x80, /* descending order */
+ ADELETE = 0x100, /* need a single index; for use in do_delete_loop */
};
extern NODE *make_array(void);
@@ -1670,6 +1663,9 @@ extern int get_numbase(const char *str, bool use_locale);
/* symbol.c */
extern void load_symbols();
+extern void init_symbol_table();
+extern NODE *symbol_table;
+extern NODE *func_table;
extern NODE *install_symbol(char *name, NODETYPE type);
extern NODE *remove_symbol(NODE *r);
extern void destroy_symbol(NODE *r);
diff --git a/awkgram.c b/awkgram.c
index d83aa034..a3759980 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -733,19 +733,19 @@ static const yytype_uint16 yyrline[] =
372, 373, 377, 396, 395, 429, 431, 436, 437, 450,
455, 456, 460, 462, 464, 471, 561, 603, 645, 758,
765, 772, 782, 791, 800, 809, 820, 836, 835, 859,
- 871, 871, 969, 969, 995, 1018, 1024, 1025, 1031, 1032,
- 1039, 1044, 1056, 1070, 1072, 1080, 1085, 1087, 1095, 1097,
- 1106, 1107, 1115, 1120, 1120, 1131, 1135, 1143, 1144, 1147,
- 1149, 1154, 1155, 1164, 1165, 1170, 1175, 1181, 1183, 1185,
- 1192, 1193, 1199, 1200, 1205, 1207, 1212, 1214, 1216, 1218,
- 1224, 1231, 1233, 1235, 1251, 1261, 1268, 1270, 1275, 1277,
- 1279, 1287, 1289, 1294, 1296, 1301, 1303, 1305, 1355, 1357,
- 1359, 1361, 1363, 1365, 1367, 1369, 1392, 1397, 1402, 1427,
- 1433, 1435, 1437, 1439, 1441, 1443, 1448, 1452, 1484, 1486,
- 1492, 1498, 1511, 1512, 1513, 1518, 1523, 1527, 1531, 1546,
- 1559, 1564, 1600, 1618, 1619, 1625, 1626, 1631, 1633, 1640,
- 1657, 1674, 1676, 1683, 1688, 1696, 1706, 1718, 1727, 1731,
- 1735, 1739, 1743, 1747, 1750, 1752, 1756, 1760, 1764
+ 871, 871, 969, 969, 1002, 1032, 1038, 1039, 1045, 1046,
+ 1053, 1058, 1070, 1084, 1086, 1094, 1099, 1101, 1109, 1111,
+ 1120, 1121, 1129, 1134, 1134, 1145, 1149, 1157, 1158, 1161,
+ 1163, 1168, 1169, 1178, 1179, 1184, 1189, 1195, 1197, 1199,
+ 1206, 1207, 1213, 1214, 1219, 1221, 1226, 1228, 1230, 1232,
+ 1238, 1245, 1247, 1249, 1265, 1275, 1282, 1284, 1289, 1291,
+ 1293, 1301, 1303, 1308, 1310, 1315, 1317, 1319, 1369, 1371,
+ 1373, 1375, 1377, 1379, 1381, 1383, 1406, 1411, 1416, 1441,
+ 1447, 1449, 1451, 1453, 1455, 1457, 1462, 1466, 1498, 1500,
+ 1506, 1512, 1525, 1526, 1527, 1532, 1537, 1541, 1545, 1560,
+ 1573, 1578, 1614, 1632, 1633, 1639, 1640, 1645, 1647, 1654,
+ 1671, 1688, 1690, 1697, 1702, 1710, 1720, 1732, 1741, 1745,
+ 1749, 1753, 1757, 1761, 1764, 1766, 1770, 1774, 1778
};
#endif
@@ -2990,6 +2990,13 @@ regular_print:
(yyvsp[(2) - (4)])->opcode = Op_push_array;
(yyvsp[(2) - (4)])->memory = variable((yyvsp[(2) - (4)])->source_line, arr, Node_var_new);
+ if (! do_posix && ! do_traditional) {
+ if ((yyvsp[(2) - (4)])->memory == symbol_table)
+ fatal(_("`delete' is not allowed with SYMTAB"));
+ else if ((yyvsp[(2) - (4)])->memory == func_table)
+ fatal(_("`delete' is not allowed with FUNCTAB"));
+ }
+
if ((yyvsp[(4) - (4)]) == NULL) {
/*
* As of September 2012, POSIX has added support
@@ -3013,7 +3020,7 @@ regular_print:
case 64:
/* Line 1787 of yacc.c */
-#line 1000 "awkgram.y"
+#line 1007 "awkgram.y"
{
static bool warned = false;
char *arr = (yyvsp[(3) - (4)])->lextok;
@@ -3031,36 +3038,43 @@ regular_print:
(yyvsp[(3) - (4)])->opcode = Op_push_array;
(yyvsp[(1) - (4)])->expr_count = 0;
(yyval) = list_append(list_create((yyvsp[(3) - (4)])), (yyvsp[(1) - (4)]));
+
+ if (! do_posix && ! do_traditional) {
+ if ((yyvsp[(3) - (4)])->memory == symbol_table)
+ fatal(_("`delete' is not allowed with SYMTAB"));
+ else if ((yyvsp[(3) - (4)])->memory == func_table)
+ fatal(_("`delete' is not allowed with FUNCTAB"));
+ }
}
break;
case 65:
/* Line 1787 of yacc.c */
-#line 1019 "awkgram.y"
+#line 1033 "awkgram.y"
{ (yyval) = optimize_assignment((yyvsp[(1) - (1)])); }
break;
case 66:
/* Line 1787 of yacc.c */
-#line 1024 "awkgram.y"
+#line 1038 "awkgram.y"
{ (yyval) = NULL; }
break;
case 67:
/* Line 1787 of yacc.c */
-#line 1026 "awkgram.y"
+#line 1040 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 68:
/* Line 1787 of yacc.c */
-#line 1031 "awkgram.y"
+#line 1045 "awkgram.y"
{ (yyval) = NULL; }
break;
case 69:
/* Line 1787 of yacc.c */
-#line 1033 "awkgram.y"
+#line 1047 "awkgram.y"
{
if ((yyvsp[(1) - (2)]) == NULL)
(yyval) = list_create((yyvsp[(2) - (2)]));
@@ -3071,13 +3085,13 @@ regular_print:
case 70:
/* Line 1787 of yacc.c */
-#line 1040 "awkgram.y"
+#line 1054 "awkgram.y"
{ (yyval) = NULL; }
break;
case 71:
/* Line 1787 of yacc.c */
-#line 1045 "awkgram.y"
+#line 1059 "awkgram.y"
{
INSTRUCTION *casestmt = (yyvsp[(5) - (5)]);
if ((yyvsp[(5) - (5)]) == NULL)
@@ -3093,7 +3107,7 @@ regular_print:
case 72:
/* Line 1787 of yacc.c */
-#line 1057 "awkgram.y"
+#line 1071 "awkgram.y"
{
INSTRUCTION *casestmt = (yyvsp[(4) - (4)]);
if ((yyvsp[(4) - (4)]) == NULL)
@@ -3108,13 +3122,13 @@ regular_print:
case 73:
/* Line 1787 of yacc.c */
-#line 1071 "awkgram.y"
+#line 1085 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 74:
/* Line 1787 of yacc.c */
-#line 1073 "awkgram.y"
+#line 1087 "awkgram.y"
{
NODE *n = (yyvsp[(2) - (2)])->memory;
(void) force_number(n);
@@ -3126,7 +3140,7 @@ regular_print:
case 75:
/* Line 1787 of yacc.c */
-#line 1081 "awkgram.y"
+#line 1095 "awkgram.y"
{
bcfree((yyvsp[(1) - (2)]));
(yyval) = (yyvsp[(2) - (2)]);
@@ -3135,13 +3149,13 @@ regular_print:
case 76:
/* Line 1787 of yacc.c */
-#line 1086 "awkgram.y"
+#line 1100 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 77:
/* Line 1787 of yacc.c */
-#line 1088 "awkgram.y"
+#line 1102 "awkgram.y"
{
(yyvsp[(1) - (1)])->opcode = Op_push_re;
(yyval) = (yyvsp[(1) - (1)]);
@@ -3150,19 +3164,19 @@ regular_print:
case 78:
/* Line 1787 of yacc.c */
-#line 1096 "awkgram.y"
+#line 1110 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 79:
/* Line 1787 of yacc.c */
-#line 1098 "awkgram.y"
+#line 1112 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 81:
/* Line 1787 of yacc.c */
-#line 1108 "awkgram.y"
+#line 1122 "awkgram.y"
{
(yyval) = (yyvsp[(2) - (3)]);
}
@@ -3170,7 +3184,7 @@ regular_print:
case 82:
/* Line 1787 of yacc.c */
-#line 1115 "awkgram.y"
+#line 1129 "awkgram.y"
{
in_print = false;
in_parens = 0;
@@ -3180,13 +3194,13 @@ regular_print:
case 83:
/* Line 1787 of yacc.c */
-#line 1120 "awkgram.y"
+#line 1134 "awkgram.y"
{ in_print = false; in_parens = 0; }
break;
case 84:
/* Line 1787 of yacc.c */
-#line 1121 "awkgram.y"
+#line 1135 "awkgram.y"
{
if ((yyvsp[(1) - (3)])->redir_type == redirect_twoway
&& (yyvsp[(3) - (3)])->lasti->opcode == Op_K_getline_redir
@@ -3198,7 +3212,7 @@ regular_print:
case 85:
/* Line 1787 of yacc.c */
-#line 1132 "awkgram.y"
+#line 1146 "awkgram.y"
{
(yyval) = mk_condition((yyvsp[(3) - (6)]), (yyvsp[(1) - (6)]), (yyvsp[(6) - (6)]), NULL, NULL);
}
@@ -3206,7 +3220,7 @@ regular_print:
case 86:
/* Line 1787 of yacc.c */
-#line 1137 "awkgram.y"
+#line 1151 "awkgram.y"
{
(yyval) = mk_condition((yyvsp[(3) - (9)]), (yyvsp[(1) - (9)]), (yyvsp[(6) - (9)]), (yyvsp[(7) - (9)]), (yyvsp[(9) - (9)]));
}
@@ -3214,13 +3228,13 @@ regular_print:
case 91:
/* Line 1787 of yacc.c */
-#line 1154 "awkgram.y"
+#line 1168 "awkgram.y"
{ (yyval) = NULL; }
break;
case 92:
/* Line 1787 of yacc.c */
-#line 1156 "awkgram.y"
+#line 1170 "awkgram.y"
{
bcfree((yyvsp[(1) - (2)]));
(yyval) = (yyvsp[(2) - (2)]);
@@ -3229,19 +3243,19 @@ regular_print:
case 93:
/* Line 1787 of yacc.c */
-#line 1164 "awkgram.y"
+#line 1178 "awkgram.y"
{ (yyval) = NULL; }
break;
case 94:
/* Line 1787 of yacc.c */
-#line 1166 "awkgram.y"
+#line 1180 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]) ; }
break;
case 95:
/* Line 1787 of yacc.c */
-#line 1171 "awkgram.y"
+#line 1185 "awkgram.y"
{
(yyvsp[(1) - (1)])->param_count = 0;
(yyval) = list_create((yyvsp[(1) - (1)]));
@@ -3250,7 +3264,7 @@ regular_print:
case 96:
/* Line 1787 of yacc.c */
-#line 1176 "awkgram.y"
+#line 1190 "awkgram.y"
{
(yyvsp[(3) - (3)])->param_count = (yyvsp[(1) - (3)])->lasti->param_count + 1;
(yyval) = list_append((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]));
@@ -3260,55 +3274,55 @@ regular_print:
case 97:
/* Line 1787 of yacc.c */
-#line 1182 "awkgram.y"
+#line 1196 "awkgram.y"
{ (yyval) = NULL; }
break;
case 98:
/* Line 1787 of yacc.c */
-#line 1184 "awkgram.y"
+#line 1198 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (2)]); }
break;
case 99:
/* Line 1787 of yacc.c */
-#line 1186 "awkgram.y"
+#line 1200 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (3)]); }
break;
case 100:
/* Line 1787 of yacc.c */
-#line 1192 "awkgram.y"
+#line 1206 "awkgram.y"
{ (yyval) = NULL; }
break;
case 101:
/* Line 1787 of yacc.c */
-#line 1194 "awkgram.y"
+#line 1208 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 102:
/* Line 1787 of yacc.c */
-#line 1199 "awkgram.y"
+#line 1213 "awkgram.y"
{ (yyval) = NULL; }
break;
case 103:
/* Line 1787 of yacc.c */
-#line 1201 "awkgram.y"
+#line 1215 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 104:
/* Line 1787 of yacc.c */
-#line 1206 "awkgram.y"
+#line 1220 "awkgram.y"
{ (yyval) = mk_expression_list(NULL, (yyvsp[(1) - (1)])); }
break;
case 105:
/* Line 1787 of yacc.c */
-#line 1208 "awkgram.y"
+#line 1222 "awkgram.y"
{
(yyval) = mk_expression_list((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]));
yyerrok;
@@ -3317,31 +3331,31 @@ regular_print:
case 106:
/* Line 1787 of yacc.c */
-#line 1213 "awkgram.y"
+#line 1227 "awkgram.y"
{ (yyval) = NULL; }
break;
case 107:
/* Line 1787 of yacc.c */
-#line 1215 "awkgram.y"
+#line 1229 "awkgram.y"
{ (yyval) = NULL; }
break;
case 108:
/* Line 1787 of yacc.c */
-#line 1217 "awkgram.y"
+#line 1231 "awkgram.y"
{ (yyval) = NULL; }
break;
case 109:
/* Line 1787 of yacc.c */
-#line 1219 "awkgram.y"
+#line 1233 "awkgram.y"
{ (yyval) = NULL; }
break;
case 110:
/* Line 1787 of yacc.c */
-#line 1225 "awkgram.y"
+#line 1239 "awkgram.y"
{
if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == Op_match_rec)
lintwarn_ln((yyvsp[(2) - (3)])->source_line,
@@ -3352,19 +3366,19 @@ regular_print:
case 111:
/* Line 1787 of yacc.c */
-#line 1232 "awkgram.y"
+#line 1246 "awkgram.y"
{ (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 112:
/* Line 1787 of yacc.c */
-#line 1234 "awkgram.y"
+#line 1248 "awkgram.y"
{ (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 113:
/* Line 1787 of yacc.c */
-#line 1236 "awkgram.y"
+#line 1250 "awkgram.y"
{
if ((yyvsp[(1) - (3)])->lasti->opcode == Op_match_rec)
warning_ln((yyvsp[(2) - (3)])->source_line,
@@ -3384,7 +3398,7 @@ regular_print:
case 114:
/* Line 1787 of yacc.c */
-#line 1252 "awkgram.y"
+#line 1266 "awkgram.y"
{
if (do_lint_old)
warning_ln((yyvsp[(2) - (3)])->source_line,
@@ -3398,7 +3412,7 @@ regular_print:
case 115:
/* Line 1787 of yacc.c */
-#line 1262 "awkgram.y"
+#line 1276 "awkgram.y"
{
if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == Op_match_rec)
lintwarn_ln((yyvsp[(2) - (3)])->source_line,
@@ -3409,31 +3423,31 @@ regular_print:
case 116:
/* Line 1787 of yacc.c */
-#line 1269 "awkgram.y"
+#line 1283 "awkgram.y"
{ (yyval) = mk_condition((yyvsp[(1) - (5)]), (yyvsp[(2) - (5)]), (yyvsp[(3) - (5)]), (yyvsp[(4) - (5)]), (yyvsp[(5) - (5)])); }
break;
case 117:
/* Line 1787 of yacc.c */
-#line 1271 "awkgram.y"
+#line 1285 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 118:
/* Line 1787 of yacc.c */
-#line 1276 "awkgram.y"
+#line 1290 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 119:
/* Line 1787 of yacc.c */
-#line 1278 "awkgram.y"
+#line 1292 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 120:
/* Line 1787 of yacc.c */
-#line 1280 "awkgram.y"
+#line 1294 "awkgram.y"
{
(yyvsp[(2) - (2)])->opcode = Op_assign_quotient;
(yyval) = (yyvsp[(2) - (2)]);
@@ -3442,43 +3456,43 @@ regular_print:
case 121:
/* Line 1787 of yacc.c */
-#line 1288 "awkgram.y"
+#line 1302 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 122:
/* Line 1787 of yacc.c */
-#line 1290 "awkgram.y"
+#line 1304 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 123:
/* Line 1787 of yacc.c */
-#line 1295 "awkgram.y"
+#line 1309 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 124:
/* Line 1787 of yacc.c */
-#line 1297 "awkgram.y"
+#line 1311 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 125:
/* Line 1787 of yacc.c */
-#line 1302 "awkgram.y"
+#line 1316 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 126:
/* Line 1787 of yacc.c */
-#line 1304 "awkgram.y"
+#line 1318 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 127:
/* Line 1787 of yacc.c */
-#line 1306 "awkgram.y"
+#line 1320 "awkgram.y"
{
int count = 2;
bool is_simple_var = false;
@@ -3529,43 +3543,43 @@ regular_print:
case 129:
/* Line 1787 of yacc.c */
-#line 1358 "awkgram.y"
+#line 1372 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 130:
/* Line 1787 of yacc.c */
-#line 1360 "awkgram.y"
+#line 1374 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 131:
/* Line 1787 of yacc.c */
-#line 1362 "awkgram.y"
+#line 1376 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 132:
/* Line 1787 of yacc.c */
-#line 1364 "awkgram.y"
+#line 1378 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 133:
/* Line 1787 of yacc.c */
-#line 1366 "awkgram.y"
+#line 1380 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 134:
/* Line 1787 of yacc.c */
-#line 1368 "awkgram.y"
+#line 1382 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 135:
/* Line 1787 of yacc.c */
-#line 1370 "awkgram.y"
+#line 1384 "awkgram.y"
{
/*
* In BEGINFILE/ENDFILE, allow `getline var < file'
@@ -3592,7 +3606,7 @@ regular_print:
case 136:
/* Line 1787 of yacc.c */
-#line 1393 "awkgram.y"
+#line 1407 "awkgram.y"
{
(yyvsp[(2) - (2)])->opcode = Op_postincrement;
(yyval) = mk_assignment((yyvsp[(1) - (2)]), NULL, (yyvsp[(2) - (2)]));
@@ -3601,7 +3615,7 @@ regular_print:
case 137:
/* Line 1787 of yacc.c */
-#line 1398 "awkgram.y"
+#line 1412 "awkgram.y"
{
(yyvsp[(2) - (2)])->opcode = Op_postdecrement;
(yyval) = mk_assignment((yyvsp[(1) - (2)]), NULL, (yyvsp[(2) - (2)]));
@@ -3610,7 +3624,7 @@ regular_print:
case 138:
/* Line 1787 of yacc.c */
-#line 1403 "awkgram.y"
+#line 1417 "awkgram.y"
{
if (do_lint_old) {
warning_ln((yyvsp[(4) - (5)])->source_line,
@@ -3634,7 +3648,7 @@ regular_print:
case 139:
/* Line 1787 of yacc.c */
-#line 1428 "awkgram.y"
+#line 1442 "awkgram.y"
{
(yyval) = mk_getline((yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]), (yyvsp[(1) - (4)]), (yyvsp[(2) - (4)])->redir_type);
bcfree((yyvsp[(2) - (4)]));
@@ -3643,43 +3657,43 @@ regular_print:
case 140:
/* Line 1787 of yacc.c */
-#line 1434 "awkgram.y"
+#line 1448 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 141:
/* Line 1787 of yacc.c */
-#line 1436 "awkgram.y"
+#line 1450 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 142:
/* Line 1787 of yacc.c */
-#line 1438 "awkgram.y"
+#line 1452 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 143:
/* Line 1787 of yacc.c */
-#line 1440 "awkgram.y"
+#line 1454 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 144:
/* Line 1787 of yacc.c */
-#line 1442 "awkgram.y"
+#line 1456 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 145:
/* Line 1787 of yacc.c */
-#line 1444 "awkgram.y"
+#line 1458 "awkgram.y"
{ (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 146:
/* Line 1787 of yacc.c */
-#line 1449 "awkgram.y"
+#line 1463 "awkgram.y"
{
(yyval) = list_create((yyvsp[(1) - (1)]));
}
@@ -3687,7 +3701,7 @@ regular_print:
case 147:
/* Line 1787 of yacc.c */
-#line 1453 "awkgram.y"
+#line 1467 "awkgram.y"
{
if ((yyvsp[(2) - (2)])->opcode == Op_match_rec) {
(yyvsp[(2) - (2)])->opcode = Op_nomatch;
@@ -3723,13 +3737,13 @@ regular_print:
case 148:
/* Line 1787 of yacc.c */
-#line 1485 "awkgram.y"
+#line 1499 "awkgram.y"
{ (yyval) = (yyvsp[(2) - (3)]); }
break;
case 149:
/* Line 1787 of yacc.c */
-#line 1487 "awkgram.y"
+#line 1501 "awkgram.y"
{
(yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
if ((yyval) == NULL)
@@ -3739,7 +3753,7 @@ regular_print:
case 150:
/* Line 1787 of yacc.c */
-#line 1493 "awkgram.y"
+#line 1507 "awkgram.y"
{
(yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
if ((yyval) == NULL)
@@ -3749,7 +3763,7 @@ regular_print:
case 151:
/* Line 1787 of yacc.c */
-#line 1499 "awkgram.y"
+#line 1513 "awkgram.y"
{
static bool warned = false;
@@ -3766,7 +3780,7 @@ regular_print:
case 154:
/* Line 1787 of yacc.c */
-#line 1514 "awkgram.y"
+#line 1528 "awkgram.y"
{
(yyvsp[(1) - (2)])->opcode = Op_preincrement;
(yyval) = mk_assignment((yyvsp[(2) - (2)]), NULL, (yyvsp[(1) - (2)]));
@@ -3775,7 +3789,7 @@ regular_print:
case 155:
/* Line 1787 of yacc.c */
-#line 1519 "awkgram.y"
+#line 1533 "awkgram.y"
{
(yyvsp[(1) - (2)])->opcode = Op_predecrement;
(yyval) = mk_assignment((yyvsp[(2) - (2)]), NULL, (yyvsp[(1) - (2)]));
@@ -3784,7 +3798,7 @@ regular_print:
case 156:
/* Line 1787 of yacc.c */
-#line 1524 "awkgram.y"
+#line 1538 "awkgram.y"
{
(yyval) = list_create((yyvsp[(1) - (1)]));
}
@@ -3792,7 +3806,7 @@ regular_print:
case 157:
/* Line 1787 of yacc.c */
-#line 1528 "awkgram.y"
+#line 1542 "awkgram.y"
{
(yyval) = list_create((yyvsp[(1) - (1)]));
}
@@ -3800,7 +3814,7 @@ regular_print:
case 158:
/* Line 1787 of yacc.c */
-#line 1532 "awkgram.y"
+#line 1546 "awkgram.y"
{
if ((yyvsp[(2) - (2)])->lasti->opcode == Op_push_i
&& ((yyvsp[(2) - (2)])->lasti->memory->flags & (STRCUR|STRING)) == 0
@@ -3819,7 +3833,7 @@ regular_print:
case 159:
/* Line 1787 of yacc.c */
-#line 1547 "awkgram.y"
+#line 1561 "awkgram.y"
{
/*
* was: $$ = $2
@@ -3833,7 +3847,7 @@ regular_print:
case 160:
/* Line 1787 of yacc.c */
-#line 1560 "awkgram.y"
+#line 1574 "awkgram.y"
{
func_use((yyvsp[(1) - (1)])->lasti->func_name, FUNC_USE);
(yyval) = (yyvsp[(1) - (1)]);
@@ -3842,7 +3856,7 @@ regular_print:
case 161:
/* Line 1787 of yacc.c */
-#line 1565 "awkgram.y"
+#line 1579 "awkgram.y"
{
/* indirect function call */
INSTRUCTION *f, *t;
@@ -3879,7 +3893,7 @@ regular_print:
case 162:
/* Line 1787 of yacc.c */
-#line 1601 "awkgram.y"
+#line 1615 "awkgram.y"
{
param_sanity((yyvsp[(3) - (4)]));
(yyvsp[(1) - (4)])->opcode = Op_func_call;
@@ -3897,37 +3911,37 @@ regular_print:
case 163:
/* Line 1787 of yacc.c */
-#line 1618 "awkgram.y"
+#line 1632 "awkgram.y"
{ (yyval) = NULL; }
break;
case 164:
/* Line 1787 of yacc.c */
-#line 1620 "awkgram.y"
+#line 1634 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 165:
/* Line 1787 of yacc.c */
-#line 1625 "awkgram.y"
+#line 1639 "awkgram.y"
{ (yyval) = NULL; }
break;
case 166:
/* Line 1787 of yacc.c */
-#line 1627 "awkgram.y"
+#line 1641 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (2)]); }
break;
case 167:
/* Line 1787 of yacc.c */
-#line 1632 "awkgram.y"
+#line 1646 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 168:
/* Line 1787 of yacc.c */
-#line 1634 "awkgram.y"
+#line 1648 "awkgram.y"
{
(yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
}
@@ -3935,7 +3949,7 @@ regular_print:
case 169:
/* Line 1787 of yacc.c */
-#line 1641 "awkgram.y"
+#line 1655 "awkgram.y"
{
INSTRUCTION *ip = (yyvsp[(1) - (1)])->lasti;
int count = ip->sub_count; /* # of SUBSEP-seperated expressions */
@@ -3953,7 +3967,7 @@ regular_print:
case 170:
/* Line 1787 of yacc.c */
-#line 1658 "awkgram.y"
+#line 1672 "awkgram.y"
{
INSTRUCTION *t = (yyvsp[(2) - (3)]);
if ((yyvsp[(2) - (3)]) == NULL) {
@@ -3971,13 +3985,13 @@ regular_print:
case 171:
/* Line 1787 of yacc.c */
-#line 1675 "awkgram.y"
+#line 1689 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 172:
/* Line 1787 of yacc.c */
-#line 1677 "awkgram.y"
+#line 1691 "awkgram.y"
{
(yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
}
@@ -3985,13 +3999,13 @@ regular_print:
case 173:
/* Line 1787 of yacc.c */
-#line 1684 "awkgram.y"
+#line 1698 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (2)]); }
break;
case 174:
/* Line 1787 of yacc.c */
-#line 1689 "awkgram.y"
+#line 1703 "awkgram.y"
{
char *var_name = (yyvsp[(1) - (1)])->lextok;
@@ -4003,7 +4017,7 @@ regular_print:
case 175:
/* Line 1787 of yacc.c */
-#line 1697 "awkgram.y"
+#line 1711 "awkgram.y"
{
char *arr = (yyvsp[(1) - (2)])->lextok;
(yyvsp[(1) - (2)])->memory = variable((yyvsp[(1) - (2)])->source_line, arr, Node_var_new);
@@ -4014,7 +4028,7 @@ regular_print:
case 176:
/* Line 1787 of yacc.c */
-#line 1707 "awkgram.y"
+#line 1721 "awkgram.y"
{
INSTRUCTION *ip = (yyvsp[(1) - (1)])->nexti;
if (ip->opcode == Op_push
@@ -4030,7 +4044,7 @@ regular_print:
case 177:
/* Line 1787 of yacc.c */
-#line 1719 "awkgram.y"
+#line 1733 "awkgram.y"
{
(yyval) = list_append((yyvsp[(2) - (3)]), (yyvsp[(1) - (3)]));
if ((yyvsp[(3) - (3)]) != NULL)
@@ -4040,7 +4054,7 @@ regular_print:
case 178:
/* Line 1787 of yacc.c */
-#line 1728 "awkgram.y"
+#line 1742 "awkgram.y"
{
(yyvsp[(1) - (1)])->opcode = Op_postincrement;
}
@@ -4048,7 +4062,7 @@ regular_print:
case 179:
/* Line 1787 of yacc.c */
-#line 1732 "awkgram.y"
+#line 1746 "awkgram.y"
{
(yyvsp[(1) - (1)])->opcode = Op_postdecrement;
}
@@ -4056,43 +4070,43 @@ regular_print:
case 180:
/* Line 1787 of yacc.c */
-#line 1735 "awkgram.y"
+#line 1749 "awkgram.y"
{ (yyval) = NULL; }
break;
case 182:
/* Line 1787 of yacc.c */
-#line 1743 "awkgram.y"
+#line 1757 "awkgram.y"
{ yyerrok; }
break;
case 183:
/* Line 1787 of yacc.c */
-#line 1747 "awkgram.y"
+#line 1761 "awkgram.y"
{ yyerrok; }
break;
case 186:
/* Line 1787 of yacc.c */
-#line 1756 "awkgram.y"
+#line 1770 "awkgram.y"
{ yyerrok; }
break;
case 187:
/* Line 1787 of yacc.c */
-#line 1760 "awkgram.y"
+#line 1774 "awkgram.y"
{ (yyval) = (yyvsp[(1) - (1)]); yyerrok; }
break;
case 188:
/* Line 1787 of yacc.c */
-#line 1764 "awkgram.y"
+#line 1778 "awkgram.y"
{ yyerrok; }
break;
/* Line 1787 of yacc.c */
-#line 4108 "awkgram.c"
+#line 4122 "awkgram.c"
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -4322,7 +4336,7 @@ yyreturn:
/* Line 2048 of yacc.c */
-#line 1766 "awkgram.y"
+#line 1780 "awkgram.y"
struct token {
diff --git a/awkgram.y b/awkgram.y
index f5294e4e..22b0b767 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -973,6 +973,13 @@ regular_print:
$2->opcode = Op_push_array;
$2->memory = variable($2->source_line, arr, Node_var_new);
+ if (! do_posix && ! do_traditional) {
+ if ($2->memory == symbol_table)
+ fatal(_("`delete' is not allowed with SYMTAB"));
+ else if ($2->memory == func_table)
+ fatal(_("`delete' is not allowed with FUNCTAB"));
+ }
+
if ($4 == NULL) {
/*
* As of September 2012, POSIX has added support
@@ -1014,6 +1021,13 @@ regular_print:
$3->opcode = Op_push_array;
$1->expr_count = 0;
$$ = list_append(list_create($3), $1);
+
+ if (! do_posix && ! do_traditional) {
+ if ($3->memory == symbol_table)
+ fatal(_("`delete' is not allowed with SYMTAB"));
+ else if ($3->memory == func_table)
+ fatal(_("`delete' is not allowed with FUNCTAB"));
+ }
}
| exp
{ $$ = optimize_assignment($1); }
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 8d19b091..6f390aed 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -9,6 +9,10 @@
bug report from William Bresler <wbresler@acm.org>. Add a link
to the ISO website.
+ * gawk.texi, gawk.1, awkcard.in: Document FUNCTAB, SYMTAB, and
+ PROCINFO["identifiers"]. Including that delete does not work
+ on FUNCTAB and SYMTAB.
+
2012-09-23 Arnold D. Robbins <arnold@skeeve.com>
* gawk.texi (Nextfile Statement): Document that it's now part of POSIX
diff --git a/doc/awkcard.in b/doc/awkcard.in
index 372d5587..9fae7cce 100644
--- a/doc/awkcard.in
+++ b/doc/awkcard.in
@@ -551,7 +551,8 @@ variables, each element being the value of
that variable.
T}
\*(CB\*(FCERRNO\fP T{
-String describing the error if a
+... String describing the error if a
+String error value if a
\*(FCgetline\*(FR
redirection or read
fails, or if
@@ -580,6 +581,10 @@ T}
Input field separator, a space by default
(see \fHFields\fP above).
T}
+\*(CB\*(FCFUNCTAB\fP T{
+An array indexed by the names of all user-defined
+and extension functions.\*(CD
+T}
\*(CB\*(FCIGNORECASE\fP T{
If non-zero, all regular expression and string
operations ignore case.
@@ -594,13 +599,13 @@ T}
\*(CB\*(FCLINT\fP T{
Provides dynamic control of the \*(FC\-\^\-lint\fP
option from within an AWK program.
-When true, \*(GK
-prints lint warnings.
-When assigned the string value \*(FC"fatal"\*(FR,
-lint warnings become fatal errors.
-Any other true value just prints warnings.\*(CD
+... When true, \*(GK
+... prints lint warnings.
+... When assigned the string value \*(FC"fatal"\*(FR,
+... lint warnings become fatal errors.
+... Any other true value just prints warnings.
T}
-\*(FCNF\fP T{
+\*(CD\*(FCNF\fP T{
Number of fields in the current input record.
T}
\*(FCNR\fP T{
@@ -650,6 +655,11 @@ Character(s) used to separate multiple subscripts
in array elements, by default \*(FC"\e034"\*(FR. (See
\fHArrays\fP below).
T}
+\*(CB\*(FCSYMTAB\fP T{
+An array indexed by the names of all global
+variables and arrays. May be used to indirectly
+set variable and array values.\*(CD
+T}
\*(CB\*(FCTEXTDOMAIN\fP T{
The internationalization text domain,
for finding the localized
diff --git a/doc/gawk.1 b/doc/gawk.1
index 494ab16d..31fcef1f 100644
--- a/doc/gawk.1
+++ b/doc/gawk.1
@@ -14,7 +14,7 @@
. if \w'\(rq' .ds rq "\(rq
. \}
.\}
-.TH GAWK 1 "Aug 09 2012" "Free Software Foundation" "Utility Commands"
+.TH GAWK 1 "Oct 02 2012" "Free Software Foundation" "Utility Commands"
.SH NAME
gawk \- pattern scanning and processing language
.SH SYNOPSIS
@@ -989,6 +989,17 @@ The input field separator, a space by default. See
.BR Fields ,
above.
.TP
+.B FUNCTAB
+An array whose indices are the names of all the user-defined
+or extension functions in the program.
+.BR NOTE :
+The array values cannot currently be used.
+Also, you may not use the
+.B delete
+statment with the
+.B FUNCTAB
+array.
+.TP
.B IGNORECASE
Controls the case-sensitivity of all regular expression
and string operations. If
@@ -1108,6 +1119,35 @@ or \fB"FIELDWIDTHS"\fP if field splitting with
.B FIELDWIDTHS
is in effect.
.TP
+\fBPROCINFO["identifiers"]\fP
+A subarray, indexed by the names of all identifiers used in the
+text of the AWK program. For each identifier, the value of the element is one of the following:
+.RS
+.TP
+\fB"array"\fR
+The identifier is an array.
+.TP
+\fB"extension"\fR
+The identifier is an extension function loaded via
+.BR @load .
+.TP
+\fB"scalar"\fR
+The identifier is a scalar.
+.TP
+\fB"untyped"\fR
+The identifier is untyped (could be used as a scalar or array,
+.I gawk
+doesn't know yet).
+.TP
+\fB"user"\fR
+The identifier is a user-defined function.
+.RE
+The values indicate what
+.I gawk
+knows about the identifiers after it has finished parsing the program; they are
+.I not
+updated while the program runs.
+.TP
\fBPROCINFO["gid"]\fP
the value of the
.IR getgid (2)
@@ -1236,6 +1276,30 @@ The length of the string matched by
The character used to separate multiple subscripts in array
elements, by default \fB"\e034"\fR.
.TP
+.B SYMTAB
+An array whose indices are the names of all currently defined
+global variables and arrays in the program. The array may be used
+for indirect access to read or write the value of a variable:
+.PP
+.RS
+.ft B
+foo = 5
+SYMTAB["foo"] = 4
+print foo # prints 4
+.ft R
+.RE
+.PP
+The
+.B isarray()
+function may be used to test if an element in
+.B SYMTAB
+is an array.
+You may not use the
+.B delete
+statment with the
+.B SYMTAB
+array.
+.TP
.B TEXTDOMAIN
The text domain of the \*(AK program; used to find the localized
translations for the program's strings.
diff --git a/doc/gawk.info b/doc/gawk.info
index 1a28ab52..08fbc297 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -9602,6 +9602,12 @@ with a pound sign (`#').
create or remove fields from the current record. *Note Changing
Fields::.
+`FUNCTAB #'
+ An array whose indices are the names of all the user-defined or
+ extension functions in the program. *NOTE*: The array values
+ cannot currently be used. Also, you may not use the `delete'
+ statement with the `FUNCTAB' array.
+
`NR'
The number of input records `awk' has processed since the
beginning of the program's execution (*note Records::). `NR' is
@@ -9624,6 +9630,32 @@ with a pound sign (`#').
effect, or `"FPAT"' if field matching with `FPAT' is in
effect.
+ `PROCINFO["identifiers"]'
+ A subarray, indexed by the names of all identifiers used in
+ the text of the AWK program. For each identifier, the value
+ of the element is one of the following:
+
+ `"array"'
+ The identifier is an array.
+
+ `"extension"'
+ The identifier is an extension function loaded via
+ `@load'.
+
+ `"scalar"'
+ The identifier is a scalar.
+
+ `"untyped"'
+ The identifier is untyped (could be used as a scalar or
+ array, `gawk' doesn't know yet).
+
+ `"user"'
+ The identifier is a user-defined function.
+
+ The values indicate what `gawk' knows about the identifiers
+ after it has finished parsing the program; they are _not_
+ updated while the program runs.
+
`PROCINFO["gid"]'
The value of the `getgid()' system call.
@@ -9705,6 +9737,23 @@ with a pound sign (`#').
implementations, or if `gawk' is in compatibility mode (*note
Options::), it is not special.
+`SYMTAB #'
+ An array whose indices are the names of all currently defined
+ global variables and arrays in the program. The array may be used
+ for indirect access to read or write the value of a variable:
+
+ foo = 5
+ SYMTAB["foo"] = 4
+ print foo # prints 4
+
+ The `isarray()' function (*note Type Functions::) may be used to
+ test if an element in `SYMTAB' is an array. Also, you may not use
+ the `delete' statement with the `SYMTAB' array.
+
+ NOTE: In order to avoid severe time-travel paradoxes(2),
+ neither `FUNCTAB' nor `SYMTAB' are available as elements
+ within the `SYMTAB' array.
+
Advanced Notes: Changing `NR' and `FNR'
---------------------------------------
@@ -9734,6 +9783,8 @@ file by resetting `NR' to zero when `FILENAME' changed.
to `"-"', even if there were data files to be processed. This behavior
was incorrect and should not be relied upon in your programs.
+ (2) Not to mention difficult implementation issues.
+

File: gawk.info, Node: ARGC and ARGV, Prev: Auto-set, Up: Built-in Variables
@@ -25971,7 +26022,7 @@ Index
(line 67)
* advanced features, data files as single record: Records. (line 180)
* advanced features, fixed-width data: Constant Size. (line 9)
-* advanced features, FNR/NR variables: Auto-set. (line 225)
+* advanced features, FNR/NR variables: Auto-set. (line 274)
* advanced features, gawk: Advanced Features. (line 6)
* advanced features, gawk, network programming: TCP/IP Networking.
(line 6)
@@ -26476,7 +26527,7 @@ Index
(line 47)
* dark corner, FILENAME variable <1>: Auto-set. (line 93)
* dark corner, FILENAME variable: Getline Notes. (line 19)
-* dark corner, FNR/NR variables: Auto-set. (line 225)
+* dark corner, FNR/NR variables: Auto-set. (line 274)
* dark corner, format-control characters: Control Letters. (line 18)
* dark corner, FS as null string: Single Character Fields.
(line 20)
@@ -26646,6 +26697,7 @@ Index
* differences in awk and gawk, FIELDWIDTHS variable: User-modified.
(line 35)
* differences in awk and gawk, FPAT variable: User-modified. (line 45)
+* differences in awk and gawk, FUNCTAB variable: Auto-set. (line 119)
* differences in awk and gawk, function arguments (gawk): Calling Built-in.
(line 16)
* differences in awk and gawk, getline command: Getline. (line 19)
@@ -26670,14 +26722,14 @@ Index
(line 6)
* differences in awk and gawk, print/printf statements: Format Modifiers.
(line 13)
-* differences in awk and gawk, PROCINFO array: Auto-set. (line 124)
+* differences in awk and gawk, PROCINFO array: Auto-set. (line 130)
* differences in awk and gawk, record separators: Records. (line 117)
* differences in awk and gawk, regexp constants: Using Constant Regexps.
(line 43)
* differences in awk and gawk, regular expressions: Case-sensitivity.
(line 26)
* differences in awk and gawk, RS/RT variables: Records. (line 172)
-* differences in awk and gawk, RT variable: Auto-set. (line 214)
+* differences in awk and gawk, RT variable: Auto-set. (line 246)
* differences in awk and gawk, single-character fields: Single Character Fields.
(line 6)
* differences in awk and gawk, split() function: String Functions.
@@ -26686,6 +26738,7 @@ Index
* differences in awk and gawk, strings, storing: Records. (line 192)
* differences in awk and gawk, strtonum() function (gawk): String Functions.
(line 404)
+* differences in awk and gawk, SYMTAB variable: Auto-set. (line 254)
* differences in awk and gawk, TEXTDOMAIN variable: User-modified.
(line 162)
* differences in awk and gawk, trunc-mod operation: Arithmetic Ops.
@@ -26956,7 +27009,7 @@ Index
* floating-point, numbers: General Arithmetic. (line 6)
* FNR variable <1>: Auto-set. (line 103)
* FNR variable: Records. (line 6)
-* FNR variable, changing: Auto-set. (line 225)
+* FNR variable, changing: Auto-set. (line 274)
* for statement: For Statement. (line 6)
* for statement, in arrays: Scanning an Array. (line 20)
* format specifiers, mixing regular with positional specifiers: Printf Ordering.
@@ -26999,6 +27052,7 @@ Index
* FSF (Free Software Foundation) <1>: Glossary. (line 301)
* FSF (Free Software Foundation) <2>: Getting. (line 10)
* FSF (Free Software Foundation): Manual History. (line 6)
+* FUNCTAB array: Auto-set. (line 119)
* function calls: Function Calls. (line 6)
* function calls, indirect: Indirect Calls. (line 6)
* function pointers: Indirect Calls. (line 6)
@@ -27086,6 +27140,7 @@ Index
* gawk, FPAT variable in <1>: User-modified. (line 45)
* gawk, FPAT variable in: Splitting By Content.
(line 26)
+* gawk, FUNCTAB array in: Auto-set. (line 119)
* gawk, function arguments and: Calling Built-in. (line 16)
* gawk, functions, adding: Dynamic Extensions. (line 9)
* gawk, hexadecimal numbers and: Nondecimal-numbers. (line 42)
@@ -27117,7 +27172,7 @@ Index
* gawk, OS/2 version of: PC Using. (line 11)
* gawk, PROCINFO array in <1>: Two-way I/O. (line 116)
* gawk, PROCINFO array in <2>: Time Functions. (line 46)
-* gawk, PROCINFO array in: Auto-set. (line 124)
+* gawk, PROCINFO array in: Auto-set. (line 130)
* gawk, regexp constants and: Using Constant Regexps.
(line 28)
* gawk, regular expressions, case sensitivity: Case-sensitivity.
@@ -27125,7 +27180,7 @@ Index
* gawk, regular expressions, operators: GNU Regexp Operators.
(line 6)
* gawk, regular expressions, precedence: Regexp Operators. (line 161)
-* gawk, RT variable in <1>: Auto-set. (line 214)
+* gawk, RT variable in <1>: Auto-set. (line 246)
* gawk, RT variable in <2>: Getline/Variable/File.
(line 10)
* gawk, RT variable in <3>: Multiple Line. (line 129)
@@ -27134,6 +27189,7 @@ Index
* gawk, source code, obtaining: Getting. (line 6)
* gawk, splitting fields and: Constant Size. (line 87)
* gawk, string-translation functions: I18N Functions. (line 6)
+* gawk, SYMTAB array in: Auto-set. (line 254)
* gawk, TEXTDOMAIN variable in: User-modified. (line 162)
* gawk, timestamps: Time Functions. (line 6)
* gawk, uses for: Preface. (line 36)
@@ -27536,9 +27592,9 @@ Index
(line 49)
* noassign.awk program: Ignoring Assigns. (line 15)
* not Boolean-logic operator: Boolean Ops. (line 6)
-* NR variable <1>: Auto-set. (line 119)
+* NR variable <1>: Auto-set. (line 125)
* NR variable: Records. (line 6)
-* NR variable, changing: Auto-set. (line 225)
+* NR variable, changing: Auto-set. (line 274)
* null strings <1>: Basic Data Typing. (line 26)
* null strings <2>: Truth Values. (line 6)
* null strings <3>: Regexp Field Splitting.
@@ -27821,7 +27877,7 @@ Index
* PROCINFO array <3>: Passwd Functions. (line 6)
* PROCINFO array <4>: Two-way I/O. (line 116)
* PROCINFO array <5>: Time Functions. (line 46)
-* PROCINFO array <6>: Auto-set. (line 124)
+* PROCINFO array <6>: Auto-set. (line 130)
* PROCINFO array: Obsolete. (line 11)
* profiling awk programs: Profiling. (line 6)
* profiling awk programs, dynamically: Profiling. (line 171)
@@ -27963,7 +28019,7 @@ Index
* right angle bracket (>), >> operator (I/O): Redirection. (line 50)
* right shift, bitwise: Bitwise Functions. (line 32)
* Ritchie, Dennis: Basic Data Typing. (line 55)
-* RLENGTH variable: Auto-set. (line 201)
+* RLENGTH variable: Auto-set. (line 233)
* RLENGTH variable, match() function and: String Functions. (line 223)
* Robbins, Arnold <1>: Future Extensions. (line 6)
* Robbins, Arnold <2>: Bugs. (line 32)
@@ -27990,9 +28046,9 @@ Index
* RS variable: Records. (line 20)
* RS variable, multiline records and: Multiple Line. (line 17)
* rshift() function (gawk): Bitwise Functions. (line 52)
-* RSTART variable: Auto-set. (line 207)
+* RSTART variable: Auto-set. (line 239)
* RSTART variable, match() function and: String Functions. (line 223)
-* RT variable <1>: Auto-set. (line 214)
+* RT variable <1>: Auto-set. (line 246)
* RT variable <2>: Getline/Variable/File.
(line 10)
* RT variable <3>: Multiple Line. (line 129)
@@ -28184,6 +28240,7 @@ Index
* substr() function: String Functions. (line 481)
* Sumner, Andrew: Other Versions. (line 55)
* switch statement: Switch Statement. (line 6)
+* SYMTAB array: Auto-set. (line 254)
* syntactic ambiguity: /= operator vs. /=.../ regexp constant: Assignment Ops.
(line 148)
* system() function: I/O Functions. (line 63)
@@ -28617,264 +28674,265 @@ Node: Built-in Variables393879
Node: User-modified394974
Ref: User-modified-Footnote-1403329
Node: Auto-set403391
-Ref: Auto-set-Footnote-1413299
-Node: ARGC and ARGV413504
-Node: Arrays417355
-Node: Array Basics418860
-Node: Array Intro419686
-Node: Reference to Elements424004
-Node: Assigning Elements426274
-Node: Array Example426765
-Node: Scanning an Array428497
-Node: Controlling Scanning430811
-Ref: Controlling Scanning-Footnote-1435744
-Node: Delete436060
-Ref: Delete-Footnote-1438825
-Node: Numeric Array Subscripts438882
-Node: Uninitialized Subscripts441065
-Node: Multi-dimensional442693
-Node: Multi-scanning445787
-Node: Arrays of Arrays447378
-Node: Functions452023
-Node: Built-in452845
-Node: Calling Built-in453923
-Node: Numeric Functions455911
-Ref: Numeric Functions-Footnote-1459743
-Ref: Numeric Functions-Footnote-2460100
-Ref: Numeric Functions-Footnote-3460148
-Node: String Functions460417
-Ref: String Functions-Footnote-1483914
-Ref: String Functions-Footnote-2484043
-Ref: String Functions-Footnote-3484291
-Node: Gory Details484378
-Ref: table-sub-escapes486057
-Ref: table-sub-posix-92487411
-Ref: table-sub-proposed488754
-Ref: table-posix-sub490104
-Ref: table-gensub-escapes491650
-Ref: Gory Details-Footnote-1492857
-Ref: Gory Details-Footnote-2492908
-Node: I/O Functions493059
-Ref: I/O Functions-Footnote-1499714
-Node: Time Functions499861
-Ref: Time Functions-Footnote-1510753
-Ref: Time Functions-Footnote-2510821
-Ref: Time Functions-Footnote-3510979
-Ref: Time Functions-Footnote-4511090
-Ref: Time Functions-Footnote-5511202
-Ref: Time Functions-Footnote-6511429
-Node: Bitwise Functions511695
-Ref: table-bitwise-ops512253
-Ref: Bitwise Functions-Footnote-1516474
-Node: Type Functions516658
-Node: I18N Functions517128
-Node: User-defined518755
-Node: Definition Syntax519559
-Ref: Definition Syntax-Footnote-1524469
-Node: Function Example524538
-Node: Function Caveats527132
-Node: Calling A Function527553
-Node: Variable Scope528668
-Node: Pass By Value/Reference530643
-Node: Return Statement534083
-Node: Dynamic Typing537064
-Node: Indirect Calls537799
-Node: Internationalization547484
-Node: I18N and L10N548910
-Node: Explaining gettext549596
-Ref: Explaining gettext-Footnote-1554662
-Ref: Explaining gettext-Footnote-2554846
-Node: Programmer i18n555011
-Node: Translator i18n559211
-Node: String Extraction560004
-Ref: String Extraction-Footnote-1560965
-Node: Printf Ordering561051
-Ref: Printf Ordering-Footnote-1563835
-Node: I18N Portability563899
-Ref: I18N Portability-Footnote-1566348
-Node: I18N Example566411
-Ref: I18N Example-Footnote-1569046
-Node: Gawk I18N569118
-Node: Advanced Features569735
-Node: Nondecimal Data571248
-Node: Array Sorting572831
-Node: Controlling Array Traversal573528
-Node: Array Sorting Functions581766
-Ref: Array Sorting Functions-Footnote-1585440
-Ref: Array Sorting Functions-Footnote-2585533
-Node: Two-way I/O585727
-Ref: Two-way I/O-Footnote-1591159
-Node: TCP/IP Networking591229
-Node: Profiling594073
-Node: Library Functions601527
-Ref: Library Functions-Footnote-1604534
-Node: Library Names604705
-Ref: Library Names-Footnote-1608176
-Ref: Library Names-Footnote-2608396
-Node: General Functions608482
-Node: Strtonum Function609435
-Node: Assert Function612365
-Node: Round Function615691
-Node: Cliff Random Function617234
-Node: Ordinal Functions618250
-Ref: Ordinal Functions-Footnote-1621320
-Ref: Ordinal Functions-Footnote-2621572
-Node: Join Function621781
-Ref: Join Function-Footnote-1623552
-Node: Getlocaltime Function623752
-Node: Data File Management627467
-Node: Filetrans Function628099
-Node: Rewind Function632238
-Node: File Checking633625
-Node: Empty Files634719
-Node: Ignoring Assigns636949
-Node: Getopt Function638502
-Ref: Getopt Function-Footnote-1649806
-Node: Passwd Functions650009
-Ref: Passwd Functions-Footnote-1658984
-Node: Group Functions659072
-Node: Walking Arrays667156
-Node: Sample Programs668725
-Node: Running Examples669390
-Node: Clones670118
-Node: Cut Program671342
-Node: Egrep Program681187
-Ref: Egrep Program-Footnote-1688960
-Node: Id Program689070
-Node: Split Program692686
-Ref: Split Program-Footnote-1696205
-Node: Tee Program696333
-Node: Uniq Program699136
-Node: Wc Program706565
-Ref: Wc Program-Footnote-1710831
-Ref: Wc Program-Footnote-2711031
-Node: Miscellaneous Programs711123
-Node: Dupword Program712311
-Node: Alarm Program714342
-Node: Translate Program719091
-Ref: Translate Program-Footnote-1723478
-Ref: Translate Program-Footnote-2723706
-Node: Labels Program723840
-Ref: Labels Program-Footnote-1727211
-Node: Word Sorting727295
-Node: History Sorting731179
-Node: Extract Program733018
-Ref: Extract Program-Footnote-1740501
-Node: Simple Sed740629
-Node: Igawk Program743691
-Ref: Igawk Program-Footnote-1758848
-Ref: Igawk Program-Footnote-2759049
-Node: Anagram Program759187
-Node: Signature Program762255
-Node: Debugger763355
-Node: Debugging764321
-Node: Debugging Concepts764754
-Node: Debugging Terms766610
-Node: Awk Debugging769207
-Node: Sample Debugging Session770099
-Node: Debugger Invocation770619
-Node: Finding The Bug771948
-Node: List of Debugger Commands778436
-Node: Breakpoint Control779770
-Node: Debugger Execution Control783434
-Node: Viewing And Changing Data786794
-Node: Execution Stack790150
-Node: Debugger Info791617
-Node: Miscellaneous Debugger Commands795598
-Node: Readline Support801043
-Node: Limitations801874
-Node: Arbitrary Precision Arithmetic804126
-Ref: Arbitrary Precision Arithmetic-Footnote-1805768
-Node: General Arithmetic805916
-Node: Floating Point Issues807636
-Node: String Conversion Precision808517
-Ref: String Conversion Precision-Footnote-1810223
-Node: Unexpected Results810332
-Node: POSIX Floating Point Problems812485
-Ref: POSIX Floating Point Problems-Footnote-1816310
-Node: Integer Programming816348
-Node: Floating-point Programming818101
-Ref: Floating-point Programming-Footnote-1824410
-Node: Floating-point Representation824674
-Node: Floating-point Context825839
-Ref: table-ieee-formats826681
-Node: Rounding Mode828065
-Ref: table-rounding-modes828544
-Ref: Rounding Mode-Footnote-1831548
-Node: Gawk and MPFR831729
-Node: Arbitrary Precision Floats832971
-Ref: Arbitrary Precision Floats-Footnote-1835400
-Node: Setting Precision835711
-Node: Setting Rounding Mode838444
-Ref: table-gawk-rounding-modes838848
-Node: Floating-point Constants840028
-Node: Changing Precision841452
-Ref: Changing Precision-Footnote-1842852
-Node: Exact Arithmetic843026
-Node: Arbitrary Precision Integers846134
-Ref: Arbitrary Precision Integers-Footnote-1849134
-Node: Dynamic Extensions849281
-Node: Plugin License850199
-Node: Sample Library850813
-Node: Internal File Description851497
-Node: Internal File Ops855210
-Ref: Internal File Ops-Footnote-1859773
-Node: Using Internal File Ops859913
-Node: Language History862289
-Node: V7/SVR3.1863811
-Node: SVR4866132
-Node: POSIX867574
-Node: BTL868582
-Node: POSIX/GNU869316
-Node: Common Extensions874851
-Node: Ranges and Locales875958
-Ref: Ranges and Locales-Footnote-1880576
-Ref: Ranges and Locales-Footnote-2880603
-Ref: Ranges and Locales-Footnote-3880863
-Node: Contributors881084
-Node: Installation885380
-Node: Gawk Distribution886274
-Node: Getting886758
-Node: Extracting887584
-Node: Distribution contents889276
-Node: Unix Installation894498
-Node: Quick Installation895115
-Node: Additional Configuration Options897077
-Node: Configuration Philosophy898554
-Node: Non-Unix Installation900896
-Node: PC Installation901354
-Node: PC Binary Installation902653
-Node: PC Compiling904501
-Node: PC Testing907445
-Node: PC Using908621
-Node: Cygwin912806
-Node: MSYS913806
-Node: VMS Installation914320
-Node: VMS Compilation914923
-Ref: VMS Compilation-Footnote-1915930
-Node: VMS Installation Details915988
-Node: VMS Running917623
-Node: VMS Old Gawk919230
-Node: Bugs919704
-Node: Other Versions923556
-Node: Notes928871
-Node: Compatibility Mode929458
-Node: Additions930241
-Node: Accessing The Source931168
-Node: Adding Code932594
-Node: New Ports938636
-Node: Derived Files942771
-Ref: Derived Files-Footnote-1948076
-Ref: Derived Files-Footnote-2948110
-Ref: Derived Files-Footnote-3948710
-Node: Future Extensions948808
-Node: Basic Concepts950295
-Node: Basic High Level950976
-Ref: Basic High Level-Footnote-1955011
-Node: Basic Data Typing955196
-Node: Glossary958551
-Node: Copying983726
-Node: GNU Free Documentation License1021283
-Node: Index1046420
+Ref: Auto-set-Footnote-1415085
+Ref: Auto-set-Footnote-2415290
+Node: ARGC and ARGV415346
+Node: Arrays419197
+Node: Array Basics420702
+Node: Array Intro421528
+Node: Reference to Elements425846
+Node: Assigning Elements428116
+Node: Array Example428607
+Node: Scanning an Array430339
+Node: Controlling Scanning432653
+Ref: Controlling Scanning-Footnote-1437586
+Node: Delete437902
+Ref: Delete-Footnote-1440667
+Node: Numeric Array Subscripts440724
+Node: Uninitialized Subscripts442907
+Node: Multi-dimensional444535
+Node: Multi-scanning447629
+Node: Arrays of Arrays449220
+Node: Functions453865
+Node: Built-in454687
+Node: Calling Built-in455765
+Node: Numeric Functions457753
+Ref: Numeric Functions-Footnote-1461585
+Ref: Numeric Functions-Footnote-2461942
+Ref: Numeric Functions-Footnote-3461990
+Node: String Functions462259
+Ref: String Functions-Footnote-1485756
+Ref: String Functions-Footnote-2485885
+Ref: String Functions-Footnote-3486133
+Node: Gory Details486220
+Ref: table-sub-escapes487899
+Ref: table-sub-posix-92489253
+Ref: table-sub-proposed490596
+Ref: table-posix-sub491946
+Ref: table-gensub-escapes493492
+Ref: Gory Details-Footnote-1494699
+Ref: Gory Details-Footnote-2494750
+Node: I/O Functions494901
+Ref: I/O Functions-Footnote-1501556
+Node: Time Functions501703
+Ref: Time Functions-Footnote-1512595
+Ref: Time Functions-Footnote-2512663
+Ref: Time Functions-Footnote-3512821
+Ref: Time Functions-Footnote-4512932
+Ref: Time Functions-Footnote-5513044
+Ref: Time Functions-Footnote-6513271
+Node: Bitwise Functions513537
+Ref: table-bitwise-ops514095
+Ref: Bitwise Functions-Footnote-1518316
+Node: Type Functions518500
+Node: I18N Functions518970
+Node: User-defined520597
+Node: Definition Syntax521401
+Ref: Definition Syntax-Footnote-1526311
+Node: Function Example526380
+Node: Function Caveats528974
+Node: Calling A Function529395
+Node: Variable Scope530510
+Node: Pass By Value/Reference532485
+Node: Return Statement535925
+Node: Dynamic Typing538906
+Node: Indirect Calls539641
+Node: Internationalization549326
+Node: I18N and L10N550752
+Node: Explaining gettext551438
+Ref: Explaining gettext-Footnote-1556504
+Ref: Explaining gettext-Footnote-2556688
+Node: Programmer i18n556853
+Node: Translator i18n561053
+Node: String Extraction561846
+Ref: String Extraction-Footnote-1562807
+Node: Printf Ordering562893
+Ref: Printf Ordering-Footnote-1565677
+Node: I18N Portability565741
+Ref: I18N Portability-Footnote-1568190
+Node: I18N Example568253
+Ref: I18N Example-Footnote-1570888
+Node: Gawk I18N570960
+Node: Advanced Features571577
+Node: Nondecimal Data573090
+Node: Array Sorting574673
+Node: Controlling Array Traversal575370
+Node: Array Sorting Functions583608
+Ref: Array Sorting Functions-Footnote-1587282
+Ref: Array Sorting Functions-Footnote-2587375
+Node: Two-way I/O587569
+Ref: Two-way I/O-Footnote-1593001
+Node: TCP/IP Networking593071
+Node: Profiling595915
+Node: Library Functions603369
+Ref: Library Functions-Footnote-1606376
+Node: Library Names606547
+Ref: Library Names-Footnote-1610018
+Ref: Library Names-Footnote-2610238
+Node: General Functions610324
+Node: Strtonum Function611277
+Node: Assert Function614207
+Node: Round Function617533
+Node: Cliff Random Function619076
+Node: Ordinal Functions620092
+Ref: Ordinal Functions-Footnote-1623162
+Ref: Ordinal Functions-Footnote-2623414
+Node: Join Function623623
+Ref: Join Function-Footnote-1625394
+Node: Getlocaltime Function625594
+Node: Data File Management629309
+Node: Filetrans Function629941
+Node: Rewind Function634080
+Node: File Checking635467
+Node: Empty Files636561
+Node: Ignoring Assigns638791
+Node: Getopt Function640344
+Ref: Getopt Function-Footnote-1651648
+Node: Passwd Functions651851
+Ref: Passwd Functions-Footnote-1660826
+Node: Group Functions660914
+Node: Walking Arrays668998
+Node: Sample Programs670567
+Node: Running Examples671232
+Node: Clones671960
+Node: Cut Program673184
+Node: Egrep Program683029
+Ref: Egrep Program-Footnote-1690802
+Node: Id Program690912
+Node: Split Program694528
+Ref: Split Program-Footnote-1698047
+Node: Tee Program698175
+Node: Uniq Program700978
+Node: Wc Program708407
+Ref: Wc Program-Footnote-1712673
+Ref: Wc Program-Footnote-2712873
+Node: Miscellaneous Programs712965
+Node: Dupword Program714153
+Node: Alarm Program716184
+Node: Translate Program720933
+Ref: Translate Program-Footnote-1725320
+Ref: Translate Program-Footnote-2725548
+Node: Labels Program725682
+Ref: Labels Program-Footnote-1729053
+Node: Word Sorting729137
+Node: History Sorting733021
+Node: Extract Program734860
+Ref: Extract Program-Footnote-1742343
+Node: Simple Sed742471
+Node: Igawk Program745533
+Ref: Igawk Program-Footnote-1760690
+Ref: Igawk Program-Footnote-2760891
+Node: Anagram Program761029
+Node: Signature Program764097
+Node: Debugger765197
+Node: Debugging766163
+Node: Debugging Concepts766596
+Node: Debugging Terms768452
+Node: Awk Debugging771049
+Node: Sample Debugging Session771941
+Node: Debugger Invocation772461
+Node: Finding The Bug773790
+Node: List of Debugger Commands780278
+Node: Breakpoint Control781612
+Node: Debugger Execution Control785276
+Node: Viewing And Changing Data788636
+Node: Execution Stack791992
+Node: Debugger Info793459
+Node: Miscellaneous Debugger Commands797440
+Node: Readline Support802885
+Node: Limitations803716
+Node: Arbitrary Precision Arithmetic805968
+Ref: Arbitrary Precision Arithmetic-Footnote-1807610
+Node: General Arithmetic807758
+Node: Floating Point Issues809478
+Node: String Conversion Precision810359
+Ref: String Conversion Precision-Footnote-1812065
+Node: Unexpected Results812174
+Node: POSIX Floating Point Problems814327
+Ref: POSIX Floating Point Problems-Footnote-1818152
+Node: Integer Programming818190
+Node: Floating-point Programming819943
+Ref: Floating-point Programming-Footnote-1826252
+Node: Floating-point Representation826516
+Node: Floating-point Context827681
+Ref: table-ieee-formats828523
+Node: Rounding Mode829907
+Ref: table-rounding-modes830386
+Ref: Rounding Mode-Footnote-1833390
+Node: Gawk and MPFR833571
+Node: Arbitrary Precision Floats834813
+Ref: Arbitrary Precision Floats-Footnote-1837242
+Node: Setting Precision837553
+Node: Setting Rounding Mode840286
+Ref: table-gawk-rounding-modes840690
+Node: Floating-point Constants841870
+Node: Changing Precision843294
+Ref: Changing Precision-Footnote-1844694
+Node: Exact Arithmetic844868
+Node: Arbitrary Precision Integers847976
+Ref: Arbitrary Precision Integers-Footnote-1850976
+Node: Dynamic Extensions851123
+Node: Plugin License852041
+Node: Sample Library852655
+Node: Internal File Description853339
+Node: Internal File Ops857052
+Ref: Internal File Ops-Footnote-1861615
+Node: Using Internal File Ops861755
+Node: Language History864131
+Node: V7/SVR3.1865653
+Node: SVR4867974
+Node: POSIX869416
+Node: BTL870424
+Node: POSIX/GNU871158
+Node: Common Extensions876693
+Node: Ranges and Locales877800
+Ref: Ranges and Locales-Footnote-1882418
+Ref: Ranges and Locales-Footnote-2882445
+Ref: Ranges and Locales-Footnote-3882705
+Node: Contributors882926
+Node: Installation887222
+Node: Gawk Distribution888116
+Node: Getting888600
+Node: Extracting889426
+Node: Distribution contents891118
+Node: Unix Installation896340
+Node: Quick Installation896957
+Node: Additional Configuration Options898919
+Node: Configuration Philosophy900396
+Node: Non-Unix Installation902738
+Node: PC Installation903196
+Node: PC Binary Installation904495
+Node: PC Compiling906343
+Node: PC Testing909287
+Node: PC Using910463
+Node: Cygwin914648
+Node: MSYS915648
+Node: VMS Installation916162
+Node: VMS Compilation916765
+Ref: VMS Compilation-Footnote-1917772
+Node: VMS Installation Details917830
+Node: VMS Running919465
+Node: VMS Old Gawk921072
+Node: Bugs921546
+Node: Other Versions925398
+Node: Notes930713
+Node: Compatibility Mode931300
+Node: Additions932083
+Node: Accessing The Source933010
+Node: Adding Code934436
+Node: New Ports940478
+Node: Derived Files944613
+Ref: Derived Files-Footnote-1949918
+Ref: Derived Files-Footnote-2949952
+Ref: Derived Files-Footnote-3950552
+Node: Future Extensions950650
+Node: Basic Concepts952137
+Node: Basic High Level952818
+Ref: Basic High Level-Footnote-1956853
+Node: Basic Data Typing957038
+Node: Glossary960393
+Node: Copying985568
+Node: GNU Free Documentation License1023125
+Node: Index1048262

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index 2a55b978..f0378b30 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -13015,6 +13015,16 @@ assigning a value to @code{NF} has the potential to affect
to @code{NF} can be used to create or remove fields from the
current record. @xref{Changing Fields}.
+@cindex @code{FUNCTAB} array
+@cindex @command{gawk}, @code{FUNCTAB} array in
+@cindex differences in @command{awk} and @command{gawk}, @code{FUNCTAB} variable
+@item FUNCTAB #
+An array whose indices are the names of all the user-defined
+or extension functions in the program.
+@strong{NOTE}: The array values cannot currently be used.
+Also, you may not use the @code{delete} statement with the
+@code{FUNCTAB} array.
+
@cindex @code{NR} variable
@item NR
The number of input records @command{awk} has processed since
@@ -13044,6 +13054,34 @@ This is
@code{"FIELDWIDTHS"} if field splitting with @code{FIELDWIDTHS} is in effect,
or @code{"FPAT"} if field matching with @code{FPAT} is in effect.
+@item PROCINFO["identifiers"]
+A subarray, indexed by the names of all identifiers used in the
+text of the AWK program. For each identifier, the value of the element is one of the following:
+
+@table @code
+@item "array"
+The identifier is an array.
+
+@item "extension"
+The identifier is an extension function loaded via
+@code{@@load}.
+
+@item "scalar"
+The identifier is a scalar.
+
+@item "untyped"
+The identifier is untyped (could be used as a scalar or array,
+@command{gawk} doesn't know yet).
+
+@item "user"
+The identifier is a user-defined function.
+@end table
+
+@noindent
+The values indicate what @command{gawk} knows about the identifiers
+after it has finished parsing the program; they are @emph{not} updated
+while the program runs.
+
@item PROCINFO["gid"]
The value of the @code{getgid()} system call.
@@ -13142,6 +13180,32 @@ In other @command{awk} implementations,
or if @command{gawk} is in compatibility mode
(@pxref{Options}),
it is not special.
+
+@cindex @command{gawk}, @code{SYMTAB} array in
+@cindex @code{SYMTAB} array
+@cindex differences in @command{awk} and @command{gawk}, @code{SYMTAB} variable
+@item SYMTAB #
+An array whose indices are the names of all currently defined
+global variables and arrays in the program. The array may be used
+for indirect access to read or write the value of a variable:
+
+@example
+foo = 5
+SYMTAB["foo"] = 4
+print foo # prints 4
+@end example
+
+@noindent
+The @code{isarray()} function (@pxref{Type Functions}) may be used to test
+if an element in @code{SYMTAB} is an array.
+Also, you may not use the @code{delete} statement with the
+@code{SYMTAB} array.
+
+@quotation NOTE
+In order to avoid severe time-travel paradoxes@footnote{Not to mention difficult
+implementation issues.}, neither @code{FUNCTAB} nor @code{SYMTAB}
+are available as elements within the @code{SYMTAB} array.
+@end quotation
@end table
@c ENDOFRANGE bvconi
@c ENDOFRANGE vbconi
diff --git a/eval.c b/eval.c
index f7037872..4c3e6ab6 100644
--- a/eval.c
+++ b/eval.c
@@ -243,7 +243,6 @@ static const char *const nodetypes[] = {
"Node_param_list",
"Node_func",
"Node_ext_func",
- "Node_hashnode",
"Node_array_ref",
"Node_array_tree",
"Node_array_leaf",
diff --git a/interpret.h b/interpret.h
index c7380bd4..ab6c9b33 100644
--- a/interpret.h
+++ b/interpret.h
@@ -210,8 +210,32 @@ top:
lintwarn(_("subscript of array `%s' is null string"), array_vname(t1));
}
- r = *assoc_lookup(t1, t2);
+ /* for FUNCTAB, get the name as the element value */
+ if (t1 == func_table) {
+ static bool warned = false;
+
+ if (do_lint && ! warned) {
+ warned = true;
+ lintwarn(_("FUNCTAB is a gawk extension"));
+ }
+ r = t2;
+ } else {
+ r = *assoc_lookup(t1, t2);
+ }
DEREF(t2);
+
+ /* for SYMTAB, step through to the actual variable */
+ if (t1 == symbol_table) {
+ static bool warned = false;
+
+ if (do_lint && ! warned) {
+ warned = true;
+ lintwarn(_("SYMTAB is a gawk extension"));
+ }
+ if (r->type == Node_var)
+ r = r->var_value;
+ }
+
if (r->type == Node_val)
UPREF(r);
PUSH(r);
@@ -531,6 +555,12 @@ mod:
array_vname(t1), (int) t2->stlen, t2->stptr);
}
DEREF(t2);
+
+ if (t1 == func_table)
+ fatal(_("cannot assign to elements of FUNCTAB"));
+ else if (t1 == symbol_table && (*lhs)->type == Node_var)
+ lhs = & ((*lhs)->var_value);
+
unref(*lhs);
*lhs = POP_SCALAR();
break;
@@ -876,7 +906,10 @@ match_re:
arg_count = (pc + 1)->expr_count;
t1 = PEEK(arg_count); /* indirect var */
- assert(t1->type == Node_val); /* @a[1](p) not allowed in grammar */
+
+ if (t1->type != Node_val) /* @a[1](p) not allowed in grammar */
+ fatal(_("indirect function call requires a simple scalar value"));
+
t1 = force_string(t1);
if (t1->stlen > 0) {
/* retrieve function definition node */
@@ -890,9 +923,13 @@ match_re:
f = lookup(t1->stptr);
}
- if (f == NULL || f->type != Node_func)
- fatal(_("function called indirectly through `%s' does not exist"),
- pc->func_name);
+ if (f == NULL || f->type != Node_func) {
+ if (f->type == Node_ext_func)
+ fatal(_("cannot (yet) call extension functions indirectly"));
+ else
+ fatal(_("function called indirectly through `%s' does not exist"),
+ pc->func_name);
+ }
pc->func_body = f; /* save for next call */
ni = setup_frame(pc);
diff --git a/main.c b/main.c
index f2a3c66b..e1cdd3d3 100644
--- a/main.c
+++ b/main.c
@@ -288,12 +288,18 @@ main(int argc, char **argv)
if (argc < 2)
usage(EXIT_FAILURE, stderr);
+ /* initialize the null string */
+ Nnull_string = make_string("", 0);
+
/* Robustness: check that file descriptors 0, 1, 2 are open */
init_fds();
/* init array handling. */
array_init();
+ /* init the symbol tables */
+ init_symbol_table();
+
output_fp = stdout;
/* we do error messages ourselves on invalid options */
@@ -588,8 +594,6 @@ out:
/* load group set */
init_groupset();
- /* initialize the null string */
- Nnull_string = make_string("", 0);
#ifdef HAVE_MPFR
if (do_mpfr) {
mpz_init(Nnull_string->mpg_i);
diff --git a/profile.c b/profile.c
index 16aa1cdd..dfac5c10 100644
--- a/profile.c
+++ b/profile.c
@@ -37,8 +37,9 @@ static NODE *pp_pop(void);
static void pp_free(NODE *n);
const char *redir2str(int redirtype);
-#define pp_str hname
-#define pp_len hlength
+#define pp_str vname
+#define pp_len sub.nodep.reserved
+#define pp_next rnode
#define DONT_FREE 1
#define CAN_FREE 2
@@ -135,7 +136,7 @@ pp_push(int type, char *s, int flag)
n->pp_len = strlen(s);
n->flags = flag;
n->type = type;
- n->hnext = pp_stack;
+ n->pp_next = pp_stack;
pp_stack = n;
}
@@ -144,7 +145,7 @@ pp_pop()
{
NODE *n;
n = pp_stack;
- pp_stack = n->hnext;
+ pp_stack = n->pp_next;
return n;
}
diff --git a/symbol.c b/symbol.c
index dd89796e..afec7315 100644
--- a/symbol.c
+++ b/symbol.c
@@ -30,19 +30,44 @@ extern INSTRUCTION *rule_list;
#define HASHSIZE 1021
-static NODE *variables[HASHSIZE];
static int func_count; /* total number of functions */
static int var_count; /* total number of global variables and functions */
static NODE *symbol_list;
static void (*install_func)(NODE *) = NULL;
static NODE *make_symbol(char *name, NODETYPE type);
-static NODE *install(char *name, NODE *hp, NODETYPE type);
+static NODE *install(char *name, NODE *parm, NODETYPE type);
static void free_bcpool(INSTRUCTION *pl);
static AWK_CONTEXT *curr_ctxt = NULL;
static int ctxt_level;
+static NODE *global_table, *param_table;
+NODE *symbol_table, *func_table;
+
+/* Use a flag to avoid a strcmp() call inside install() */
+static bool installing_specials = false;
+
+/* init_symbol_table --- make sure the symbol tables are initialized */
+
+void
+init_symbol_table()
+{
+ getnode(global_table);
+ memset(global_table, '\0', sizeof(NODE));
+ init_array(global_table);
+
+ getnode(param_table);
+ memset(param_table, '\0', sizeof(NODE));
+ init_array(param_table);
+
+ installing_specials = true;
+ func_table = install_symbol(estrdup("FUNCTAB", 7), Node_var_array);
+
+ symbol_table = install_symbol(estrdup("SYMTAB", 6), Node_var_array);
+ installing_specials = false;
+}
+
/*
* install_symbol:
* Install a global name in the symbol table, even if it is already there.
@@ -56,24 +81,45 @@ install_symbol(char *name, NODETYPE type)
}
-/* lookup --- find the most recent global or param node for name
+/*
+ * lookup --- find the most recent global or param node for name
* installed by install_symbol
*/
NODE *
lookup(const char *name)
{
- NODE *hp;
- size_t len;
- int hash1;
-
- len = strlen(name);
- hash1 = hash(name, len, (unsigned long) HASHSIZE, NULL);
- for (hp = variables[hash1]; hp != NULL; hp = hp->hnext) {
- if (hp->hlength == len && strncmp(hp->hname, name, len) == 0)
- return hp->hvalue;
+ NODE *n;
+ NODE *tmp;
+ /* ``It's elephants, all the way down.'' */
+ NODE *tables[] = {
+ param_table, /* parameters shadow everything */
+ global_table, /* SYMTAB and FUNCTAB found first, can't be redefined */
+ func_table, /* then functions */
+ symbol_table, /* then globals */
+ NULL,
+ };
+ int i;
+
+ tmp = make_string(name, strlen(name));
+
+ n = NULL;
+ for (i = 0; tables[i] != NULL; i++) {
+ if (tables[i]->table_size == 0)
+ continue;
+
+ if ((do_posix || do_traditional) && tables[i] == global_table)
+ continue;
+
+ n = in_array(tables[i], tmp);
+ if (n != NULL) {
+ unref(tmp);
+ return n;
+ }
}
- return NULL;
+
+ unref(tmp);
+ return n; /* NULL */
}
/* make_params --- allocate function parameters for the symbol table */
@@ -81,7 +127,7 @@ lookup(const char *name)
NODE *
make_params(char **pnames, int pcount)
{
- NODE *hp, *parms;
+ NODE *p, *parms;
int i;
if (pcount <= 0 || pnames == NULL)
@@ -90,12 +136,10 @@ make_params(char **pnames, int pcount)
emalloc(parms, NODE *, pcount * sizeof(NODE), "make_params");
memset(parms, '\0', pcount * sizeof(NODE));
- for (i = 0, hp = parms; i < pcount; i++, hp++) {
- hp->type = Node_param_list;
- hp->hname = pnames[i]; /* shadows pname and vname */
- hp->hlength = strlen(pnames[i]);
- hp->param_cnt = i;
- hp->hvalue = hp; /* points to itself */
+ for (i = 0, p = parms; i < pcount; i++, p++) {
+ p->type = Node_param_list;
+ p->param = pnames[i]; /* shadows pname and vname */
+ p->param_cnt = i;
}
return parms;
@@ -117,7 +161,7 @@ install_params(NODE *func)
)
return;
for (i = 0; i < pcount; i++)
- (void) install(NULL, parms + i, Node_param_list);
+ (void) install(parms[i].param, parms + i, Node_param_list);
}
@@ -128,8 +172,8 @@ install_params(NODE *func)
void
remove_params(NODE *func)
{
- NODE *parms, *p, *prev, *n;
- int i, pcount, hash1;
+ NODE *parms, *p;
+ int i, pcount;
if (func == NULL)
return;
@@ -140,22 +184,15 @@ remove_params(NODE *func)
return;
for (i = pcount - 1; i >= 0; i--) {
+ NODE *tmp;
+
p = parms + i;
- hash1 = p->hcode;
- if (hash1 < 0 || hash1 >= HASHSIZE)
- continue;
- for (prev = NULL, n = variables[hash1]; n != NULL;
- prev = n, n = n->hnext) {
- if (n == p)
- break;
- }
- if (n == NULL)
- continue;
- if (prev == NULL)
- variables[hash1] = n->hnext; /* param at the head of the chain */
- else
- prev->hnext = n->hnext; /* param not at the head */
+ tmp = make_string(p->vname, strlen(p->vname));
+ (void) assoc_remove(param_table, tmp);
+ unref(tmp);
}
+
+ assoc_clear(param_table); /* shazzam! */
}
@@ -164,33 +201,16 @@ remove_params(NODE *func)
NODE *
remove_symbol(NODE *r)
{
- NODE *prev, *hp;
- int hash1;
-
- hash1 = hash(r->vname, strlen(r->vname), (unsigned long) HASHSIZE, NULL);
- for (prev = NULL, hp = variables[hash1]; hp != NULL;
- prev = hp, hp = hp->hnext) {
- if (hp->hvalue == r)
- break;
- }
+ NODE *n = in_array(symbol_table, r);
- if (hp == NULL)
- return NULL;
- assert(hp->hcode == hash1);
-
- if (prev == NULL)
- variables[hash1] = hp->hnext; /* symbol at the head of chain */
- else
- prev->hnext = hp->hnext; /* symbol not at the head */
-
- if (r->type == Node_param_list)
- return r; /* r == hp */
- if (r->type == Node_func)
- func_count--;
- if (r->type != Node_ext_func)
- var_count--;
- freenode(hp);
- return r;
+ if (n == NULL)
+ return n;
+
+ n = dupnode(n);
+
+ (void) assoc_remove(symbol_table, r);
+
+ return n;
}
@@ -248,46 +268,56 @@ destroy_symbol(NODE *r)
static NODE *
make_symbol(char *name, NODETYPE type)
{
- NODE *hp, *r;
+ NODE *r;
- getnode(hp);
- hp->type = Node_hashnode;
- hp->hlength = strlen(name);
- hp->hname = name;
getnode(r);
memset(r, '\0', sizeof(NODE));
- hp->hvalue = r;
if (type == Node_var_array)
init_array(r);
else if (type == Node_var)
r->var_value = dupnode(Nnull_string);
r->vname = name;
r->type = type;
- return hp;
+
+ return r;
}
/* install --- install a global name or function parameter in the symbol table */
static NODE *
-install(char *name, NODE *hp, NODETYPE type)
+install(char *name, NODE *parm, NODETYPE type)
{
- int hash1;
NODE *r;
+ NODE **aptr;
+ NODE *table;
+ NODE *n_name;
+
+ n_name = make_string(name, strlen(name));
+ table = symbol_table;
+
+ if (type == Node_param_list) {
+ table = param_table;
+ } else if (type == Node_func || type == Node_ext_func) {
+ table = func_table;
+ } else if (installing_specials) {
+ table = global_table;
+ }
- if (hp == NULL) {
+ if (parm != NULL) {
+ r = parm;
+ } else {
/* global symbol */
- hp = make_symbol(name, type);
+ r = make_symbol(name, type);
if (type == Node_func)
func_count++;
- if (type != Node_ext_func)
+ if (type != Node_ext_func && table != global_table)
var_count++; /* total, includes Node_func */
}
- r = hp->hvalue;
- hash1 = hash(hp->hname, hp->hlength, (unsigned long) HASHSIZE, NULL);
- hp->hcode = hash1;
- hp->hnext = variables[hash1];
- variables[hash1] = hp;
+ aptr = assoc_lookup(table, n_name);
+ unref(*aptr);
+ *aptr = r;
+ unref(n_name);
if (install_func)
(*install_func)(r);
@@ -322,30 +352,33 @@ get_symbols(SYMBOL_TYPE what, int sort)
{
int i;
NODE **table;
- NODE *hp, *r;
+ NODE **list;
+ NODE *r;
long j, count = 0;
+ long max;
+ NODE *the_table;
- if (what == FUNCTION)
+ if (what == FUNCTION) {
count = func_count;
- else /* if (what == VARIABLE) */
+ the_table = func_table;
+ } else { /* what == VARIABLE */
count = var_count;
+ the_table = symbol_table;
+ update_global_values();
+ }
emalloc(table, NODE **, (count + 1) * sizeof(NODE *), "symbol_list");
- if (what == VARIABLE)
- update_global_values();
- for (i = j = 0; i < HASHSIZE; i++)
- for (hp = variables[i]; hp != NULL; hp = hp->hnext) {
- if (hp->type != Node_hashnode)
- continue;
- r = hp->hvalue;
- if (r->type == Node_ext_func)
- continue;
- if (what == FUNCTION && r->type == Node_func)
- table[j++] = r;
- else if (what == VARIABLE)
- table[j++] = r;
- }
+ max = the_table->table_size * 2;
+ list = assoc_list(the_table, "@unsorted", ASORTI);
+ for (i = j = 0; i < max; i += 2) {
+ r = list[i+1];
+ if (r->type == Node_ext_func)
+ continue;
+ if (what == VARIABLE || r->type == Node_func)
+ table[j++] = r;
+ }
+ efree(list);
if (sort && count > 1)
qsort(table, count, sizeof(NODE *), comp_symbol); /* Shazzam! */
@@ -417,25 +450,9 @@ foreach_func(NODE **table, int (*pfunc)(INSTRUCTION *, void *), void *data)
void
release_all_vars()
{
- int i;
- NODE *hp, *r, *next;
-
- for (i = 0; i < HASHSIZE; i++)
- for (hp = variables[i]; hp != NULL; hp = next) {
- next = hp->hnext;
- if (hp->type != Node_hashnode)
- continue;
- r = hp->hvalue;
- if (r->type == Node_func || r->type == Node_ext_func)
- continue;
- if (r->type == Node_var_array)
- assoc_clear(r);
- else if (r->type == Node_var)
- unref(r->var_value);
- efree(r->vname);
- freenode(r);
- freenode(hp);
- }
+ assoc_clear(symbol_table);
+ assoc_clear(func_table);
+ assoc_clear(global_table);
}
@@ -446,12 +463,12 @@ release_all_vars()
void
append_symbol(NODE *r)
{
- NODE *hp;
+ NODE *p;
- getnode(hp);
- hp->lnode = r;
- hp->rnode = symbol_list->rnode;
- symbol_list->rnode = hp;
+ getnode(p);
+ p->lnode = r;
+ p->rnode = symbol_list->rnode;
+ symbol_list->rnode = p;
}
/* release_symbol --- free symbol list and optionally remove symbol from symbol table */
@@ -459,17 +476,17 @@ append_symbol(NODE *r)
void
release_symbols(NODE *symlist, int keep_globals)
{
- NODE *hp, *next;
+ NODE *p, *next;
- for (hp = symlist->rnode; hp != NULL; hp = next) {
+ for (p = symlist->rnode; p != NULL; p = next) {
if (! keep_globals) {
/* destroys globals, function, and params
* if still in symbol table
*/
- destroy_symbol(hp->lnode);
+ destroy_symbol(p->lnode);
}
- next = hp->rnode;
- freenode(hp);
+ next = p->rnode;
+ freenode(p);
}
symlist->rnode = NULL;
}
@@ -479,12 +496,19 @@ release_symbols(NODE *symlist, int keep_globals)
void
load_symbols()
{
- NODE *hp, *r;
+ NODE *r;
NODE *tmp;
NODE *sym_array;
NODE **aptr;
- long i;
- NODE *user, *extension, *variable, *scalar,*array;
+ long i, j, max;
+ NODE *user, *extension, *untyped, *scalar, *array;
+ NODE **list;
+ NODE *tables[] = {
+ func_table,
+ symbol_table,
+ global_table,
+ NULL
+ };
if (PROCINFO_node == NULL)
return;
@@ -506,15 +530,16 @@ load_symbols()
user = make_string("user", 4);
extension = make_string("extension", 9);
scalar = make_string("scalar", 6);
- variable = make_string("variable", 8);
+ untyped = make_string("untyped", 7);
array = make_string("array", 5);
- for (i = 0; i < HASHSIZE; i++) {
- for (hp = variables[i]; hp != NULL; hp = hp->hnext) {
- if (hp->type != Node_hashnode)
- continue;
-
- r = hp->hvalue;
+ for (i = 0; tables[i] != NULL; i++) {
+ list = assoc_list(tables[i], "@unsorted", ASORTI);
+ max = tables[i]->table_size * 2;
+ if (max == 0)
+ continue;
+ for (j = 0; j < max; j += 2) {
+ r = list[j+1];
if ( r->type == Node_ext_func
|| r->type == Node_func
|| r->type == Node_var
@@ -538,7 +563,7 @@ load_symbols()
*aptr = dupnode(array);
break;
case Node_var_new:
- *aptr = dupnode(variable);
+ *aptr = dupnode(untyped);
break;
default:
cant_happen();
@@ -546,12 +571,13 @@ load_symbols()
}
}
}
+ efree(list);
}
unref(user);
unref(extension);
unref(scalar);
- unref(variable);
+ unref(untyped);
unref(array);
}
diff --git a/test/ChangeLog b/test/ChangeLog
index 3f5a7bce..bd327f24 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -5,6 +5,13 @@
* Makefile.am (shlib-tests): config.h is in builddir.
(beginfile2): So is gawk itself.
+ * Makefile.am (functab1, functab2, functab3, functab4, id, symtab1,
+ symtab2, symtab3): New tests.
+ * functab1.awk, functab1.ok, functab2.awk, functab2.ok, functab3.awk,
+ functab3.ok, functab4.awk, functab4.ok, id.awk, id.ok, symtab1.awk,
+ symtab1.ok, symtab2.awk, symtab2.ok, symtab3.awk, symtab3.ok:
+ New files.
+
2012-09-23 Arnold D. Robbins <arnold@skeeve.com>
* lintwarn.ok: Updated.
diff --git a/test/Makefile.am b/test/Makefile.am
index 135ddd80..c64e1e3b 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -47,8 +47,6 @@ EXTRA_DIST = \
anchgsub.awk \
anchgsub.in \
anchgsub.ok \
- arraysort.awk \
- arraysort.ok \
argarray.awk \
argarray.in \
argarray.ok \
@@ -62,6 +60,8 @@ EXTRA_DIST = \
arrayprm3.ok \
arrayref.awk \
arrayref.ok \
+ arraysort.awk \
+ arraysort.ok \
arrymem1.awk \
arrymem1.ok \
arryref2.awk \
@@ -160,10 +160,10 @@ EXTRA_DIST = \
defref.ok \
delargv.awk \
delargv.ok \
- delarprm.awk \
- delarprm.ok \
delarpm2.awk \
delarpm2.ok \
+ delarprm.awk \
+ delarprm.ok \
delfunc.awk \
delfunc.ok \
delsub.awk \
@@ -199,8 +199,8 @@ EXTRA_DIST = \
fcall_exit.awk \
fcall_exit.ok \
fcall_exit2.awk \
- fcall_exit2.ok \
fcall_exit2.in \
+ fcall_exit2.ok \
fflush.ok \
fflush.sh \
fieldwdth.awk \
@@ -214,9 +214,9 @@ EXTRA_DIST = \
fldchgnf.awk \
fldchgnf.in \
fldchgnf.ok \
+ fmtspcl-mpfr.ok \
fmtspcl.awk \
fmtspcl.tok \
- fmtspcl-mpfr.ok \
fmttest.awk \
fmttest.ok \
fnamedat.awk \
@@ -227,9 +227,9 @@ EXTRA_DIST = \
fnarray2.awk \
fnarray2.in \
fnarray2.ok \
+ fnarydel-mpfr.ok \
fnarydel.awk \
fnarydel.ok \
- fnarydel-mpfr.ok \
fnaryscl.awk \
fnaryscl.ok \
fnasgnm.awk \
@@ -239,13 +239,19 @@ EXTRA_DIST = \
fnmatch.ok \
fnmisc.awk \
fnmisc.ok \
+ fnparydl-mpfr.ok \
fnparydl.awk \
fnparydl.ok \
- fnparydl-mpfr.ok \
+ fordel.awk \
+ fordel.ok \
fork.awk \
fork.ok \
fork2.awk \
fork2.ok \
+ forref.awk \
+ forref.ok \
+ forsimp.awk \
+ forsimp.ok \
fpat1.awk \
fpat1.in \
fpat1.ok \
@@ -257,12 +263,6 @@ EXTRA_DIST = \
fpatnull.awk \
fpatnull.in \
fpatnull.ok \
- fordel.awk \
- fordel.ok \
- forref.awk \
- forref.ok \
- forsimp.awk \
- forsimp.ok \
fsbs.awk \
fsbs.in \
fsbs.ok \
@@ -279,6 +279,14 @@ EXTRA_DIST = \
fstabplus.in \
fstabplus.ok \
fts.awk \
+ functab1.awk \
+ functab1.ok \
+ functab2.awk \
+ functab2.ok \
+ functab3.awk \
+ functab3.ok \
+ functab4.awk \
+ functab4.ok \
funlen.awk \
funlen.in \
funlen.ok \
@@ -367,29 +375,31 @@ EXTRA_DIST = \
icasers.awk \
icasers.in \
icasers.ok \
+ id.awk \
+ id.ok \
igncdym.awk \
igncdym.in \
igncdym.ok \
igncfs.awk \
igncfs.in \
igncfs.ok \
+ ignrcas2.awk \
+ ignrcas2.ok \
ignrcase.awk \
ignrcase.in \
ignrcase.ok \
- ignrcas2.awk \
- ignrcas2.ok \
- inclib.awk \
- include.awk \
- include.ok \
- include2.ok \
incdupe.ok \
incdupe2.ok \
incdupe3.ok \
- inchello.awk \
incdupe4.ok \
incdupe5.ok \
incdupe6.ok \
incdupe7.ok \
+ inchello.awk \
+ inclib.awk \
+ include.awk \
+ include.ok \
+ include2.ok \
indirectcall.awk \
indirectcall.in \
indirectcall.ok \
@@ -434,8 +444,8 @@ EXTRA_DIST = \
longsub.in \
longsub.ok \
longwrds.awk \
- longwrds.ok \
longwrds.in \
+ longwrds.ok \
manglprm.awk \
manglprm.in \
manglprm.ok \
@@ -602,9 +612,6 @@ EXTRA_DIST = \
prdupval.awk \
prdupval.in \
prdupval.ok \
- profile2.ok \
- profile3.awk \
- profile3.ok \
prec.awk \
prec.ok \
printf0.awk \
@@ -626,24 +633,30 @@ EXTRA_DIST = \
prmreuse.ok \
procinfs.awk \
procinfs.ok \
+ profile2.ok \
+ profile3.awk \
+ profile3.ok \
prt1eval.awk \
prt1eval.ok \
prtoeval.awk \
prtoeval.ok \
pty1.awk \
pty1.ok \
+ rand-mpfr.ok \
rand.awk \
rand.ok \
- rand-mpfr.ok \
range1.awk \
range1.in \
range1.ok \
- readdir0.awk \
readdir.awk \
+ readdir0.awk \
rebt8b1.awk \
rebt8b1.ok \
rebt8b2.awk \
rebt8b2.ok \
+ rebuf.awk \
+ rebuf.in \
+ rebuf.ok \
redfilnm.awk \
redfilnm.in \
redfilnm.ok \
@@ -657,9 +670,6 @@ EXTRA_DIST = \
regtest.sh \
regx8bit.awk \
regx8bit.ok \
- rebuf.awk \
- rebuf.in \
- rebuf.ok \
reindops.awk \
reindops.in \
reindops.ok \
@@ -757,16 +767,16 @@ EXTRA_DIST = \
sprintfc.ok \
strcat1.awk \
strcat1.ok \
+ strftime.awk \
+ strftlng.awk \
+ strftlng.ok \
+ strnum1.awk \
+ strnum1.ok \
strtod.awk \
strtod.in \
strtod.ok \
- strnum1.awk \
- strnum1.ok \
strtonum.awk \
strtonum.ok \
- strftime.awk \
- strftlng.awk \
- strftlng.ok \
subamp.awk \
subamp.in \
subamp.ok \
@@ -783,6 +793,12 @@ EXTRA_DIST = \
swaplns.ok \
switch2.awk \
switch2.ok \
+ symtab1.awk \
+ symtab1.ok \
+ symtab2.awk \
+ symtab2.ok \
+ symtab3.awk \
+ symtab3.ok \
synerr1.awk \
synerr1.ok \
synerr2.awk \
@@ -837,6 +853,7 @@ EXTRA_DIST = \
zeroflag.awk \
zeroflag.ok
+
TESTS_WE_ARE_NOT_DOING_YET_FIXME_ONE_DAY = longdbl
# Get rid of core files when cleaning and generated .ok file
@@ -890,9 +907,10 @@ GAWK_EXT_TESTS = \
backw badargs beginfile1 beginfile2 binmode1 charasbytes \
clos1way delsub devfd devfd1 devfd2 dumpvars exit \
fieldwdth fpat1 fpat2 fpat3 fpatnull fsfwfs funlen \
+ functab1 functab2 functab3 functab4 \
fwtest fwtest2 fwtest3 \
gensub gensub2 getlndir gnuops2 gnuops3 gnureops \
- icasefs icasers igncdym igncfs ignrcas2 ignrcase indirectcall \
+ icasefs icasers id igncdym igncfs ignrcas2 ignrcase indirectcall \
lint lintold lintwarn \
manyfiles match1 match2 match3 mbstr1 \
nastyparm next nondec nondec2 \
@@ -901,6 +919,7 @@ GAWK_EXT_TESTS = \
rebuf regx8bit reint reint2 rsstart1 \
rsstart2 rsstart3 rstest6 shadow sortfor sortu splitarg4 strftime \
strtonum switch2 \
+ symtab1 symtab2 symtab3 \
include include2 incdupe incdupe2 incdupe3 \
incdupe4 incdupe5 incdupe6 incdupe7
diff --git a/test/Makefile.in b/test/Makefile.in
index e60c1c6e..db461f52 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -259,8 +259,6 @@ EXTRA_DIST = \
anchgsub.awk \
anchgsub.in \
anchgsub.ok \
- arraysort.awk \
- arraysort.ok \
argarray.awk \
argarray.in \
argarray.ok \
@@ -274,6 +272,8 @@ EXTRA_DIST = \
arrayprm3.ok \
arrayref.awk \
arrayref.ok \
+ arraysort.awk \
+ arraysort.ok \
arrymem1.awk \
arrymem1.ok \
arryref2.awk \
@@ -372,10 +372,10 @@ EXTRA_DIST = \
defref.ok \
delargv.awk \
delargv.ok \
- delarprm.awk \
- delarprm.ok \
delarpm2.awk \
delarpm2.ok \
+ delarprm.awk \
+ delarprm.ok \
delfunc.awk \
delfunc.ok \
delsub.awk \
@@ -411,8 +411,8 @@ EXTRA_DIST = \
fcall_exit.awk \
fcall_exit.ok \
fcall_exit2.awk \
- fcall_exit2.ok \
fcall_exit2.in \
+ fcall_exit2.ok \
fflush.ok \
fflush.sh \
fieldwdth.awk \
@@ -426,9 +426,9 @@ EXTRA_DIST = \
fldchgnf.awk \
fldchgnf.in \
fldchgnf.ok \
+ fmtspcl-mpfr.ok \
fmtspcl.awk \
fmtspcl.tok \
- fmtspcl-mpfr.ok \
fmttest.awk \
fmttest.ok \
fnamedat.awk \
@@ -439,9 +439,9 @@ EXTRA_DIST = \
fnarray2.awk \
fnarray2.in \
fnarray2.ok \
+ fnarydel-mpfr.ok \
fnarydel.awk \
fnarydel.ok \
- fnarydel-mpfr.ok \
fnaryscl.awk \
fnaryscl.ok \
fnasgnm.awk \
@@ -451,13 +451,19 @@ EXTRA_DIST = \
fnmatch.ok \
fnmisc.awk \
fnmisc.ok \
+ fnparydl-mpfr.ok \
fnparydl.awk \
fnparydl.ok \
- fnparydl-mpfr.ok \
+ fordel.awk \
+ fordel.ok \
fork.awk \
fork.ok \
fork2.awk \
fork2.ok \
+ forref.awk \
+ forref.ok \
+ forsimp.awk \
+ forsimp.ok \
fpat1.awk \
fpat1.in \
fpat1.ok \
@@ -469,12 +475,6 @@ EXTRA_DIST = \
fpatnull.awk \
fpatnull.in \
fpatnull.ok \
- fordel.awk \
- fordel.ok \
- forref.awk \
- forref.ok \
- forsimp.awk \
- forsimp.ok \
fsbs.awk \
fsbs.in \
fsbs.ok \
@@ -491,6 +491,14 @@ EXTRA_DIST = \
fstabplus.in \
fstabplus.ok \
fts.awk \
+ functab1.awk \
+ functab1.ok \
+ functab2.awk \
+ functab2.ok \
+ functab3.awk \
+ functab3.ok \
+ functab4.awk \
+ functab4.ok \
funlen.awk \
funlen.in \
funlen.ok \
@@ -579,29 +587,31 @@ EXTRA_DIST = \
icasers.awk \
icasers.in \
icasers.ok \
+ id.awk \
+ id.ok \
igncdym.awk \
igncdym.in \
igncdym.ok \
igncfs.awk \
igncfs.in \
igncfs.ok \
+ ignrcas2.awk \
+ ignrcas2.ok \
ignrcase.awk \
ignrcase.in \
ignrcase.ok \
- ignrcas2.awk \
- ignrcas2.ok \
- inclib.awk \
- include.awk \
- include.ok \
- include2.ok \
incdupe.ok \
incdupe2.ok \
incdupe3.ok \
- inchello.awk \
incdupe4.ok \
incdupe5.ok \
incdupe6.ok \
incdupe7.ok \
+ inchello.awk \
+ inclib.awk \
+ include.awk \
+ include.ok \
+ include2.ok \
indirectcall.awk \
indirectcall.in \
indirectcall.ok \
@@ -646,8 +656,8 @@ EXTRA_DIST = \
longsub.in \
longsub.ok \
longwrds.awk \
- longwrds.ok \
longwrds.in \
+ longwrds.ok \
manglprm.awk \
manglprm.in \
manglprm.ok \
@@ -814,9 +824,6 @@ EXTRA_DIST = \
prdupval.awk \
prdupval.in \
prdupval.ok \
- profile2.ok \
- profile3.awk \
- profile3.ok \
prec.awk \
prec.ok \
printf0.awk \
@@ -838,24 +845,30 @@ EXTRA_DIST = \
prmreuse.ok \
procinfs.awk \
procinfs.ok \
+ profile2.ok \
+ profile3.awk \
+ profile3.ok \
prt1eval.awk \
prt1eval.ok \
prtoeval.awk \
prtoeval.ok \
pty1.awk \
pty1.ok \
+ rand-mpfr.ok \
rand.awk \
rand.ok \
- rand-mpfr.ok \
range1.awk \
range1.in \
range1.ok \
- readdir0.awk \
readdir.awk \
+ readdir0.awk \
rebt8b1.awk \
rebt8b1.ok \
rebt8b2.awk \
rebt8b2.ok \
+ rebuf.awk \
+ rebuf.in \
+ rebuf.ok \
redfilnm.awk \
redfilnm.in \
redfilnm.ok \
@@ -869,9 +882,6 @@ EXTRA_DIST = \
regtest.sh \
regx8bit.awk \
regx8bit.ok \
- rebuf.awk \
- rebuf.in \
- rebuf.ok \
reindops.awk \
reindops.in \
reindops.ok \
@@ -969,16 +979,16 @@ EXTRA_DIST = \
sprintfc.ok \
strcat1.awk \
strcat1.ok \
+ strftime.awk \
+ strftlng.awk \
+ strftlng.ok \
+ strnum1.awk \
+ strnum1.ok \
strtod.awk \
strtod.in \
strtod.ok \
- strnum1.awk \
- strnum1.ok \
strtonum.awk \
strtonum.ok \
- strftime.awk \
- strftlng.awk \
- strftlng.ok \
subamp.awk \
subamp.in \
subamp.ok \
@@ -995,6 +1005,12 @@ EXTRA_DIST = \
swaplns.ok \
switch2.awk \
switch2.ok \
+ symtab1.awk \
+ symtab1.ok \
+ symtab2.awk \
+ symtab2.ok \
+ symtab3.awk \
+ symtab3.ok \
synerr1.awk \
synerr1.ok \
synerr2.awk \
@@ -1102,9 +1118,10 @@ GAWK_EXT_TESTS = \
backw badargs beginfile1 beginfile2 binmode1 charasbytes \
clos1way delsub devfd devfd1 devfd2 dumpvars exit \
fieldwdth fpat1 fpat2 fpat3 fpatnull fsfwfs funlen \
+ functab1 functab2 functab3 functab4 \
fwtest fwtest2 fwtest3 \
gensub gensub2 getlndir gnuops2 gnuops3 gnureops \
- icasefs icasers igncdym igncfs ignrcas2 ignrcase indirectcall \
+ icasefs icasers id igncdym igncfs ignrcas2 ignrcase indirectcall \
lint lintold lintwarn \
manyfiles match1 match2 match3 mbstr1 \
nastyparm next nondec nondec2 \
@@ -1113,6 +1130,7 @@ GAWK_EXT_TESTS = \
rebuf regx8bit reint reint2 rsstart1 \
rsstart2 rsstart3 rstest6 shadow sortfor sortu splitarg4 strftime \
strtonum switch2 \
+ symtab1 symtab2 symtab3 \
include include2 incdupe incdupe2 incdupe3 \
incdupe4 incdupe5 incdupe6 incdupe7
@@ -3014,6 +3032,26 @@ funlen:
@AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+functab1:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+functab2:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+functab3:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+functab4:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
fwtest:
@echo $@
@AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -3069,6 +3107,11 @@ icasers:
@AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+id:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
igncdym:
@echo $@
@AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -3204,6 +3247,21 @@ switch2:
@AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+symtab1:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+symtab2:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+symtab3:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
include:
@echo $@
@AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index 3951c3ff..6490410c 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -960,6 +960,26 @@ funlen:
@AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+functab1:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+functab2:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+functab3:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+functab4:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
fwtest:
@echo $@
@AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1015,6 +1035,11 @@ icasers:
@AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+id:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
igncdym:
@echo $@
@AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1150,6 +1175,21 @@ switch2:
@AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+symtab1:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+symtab2:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+symtab3:
+ @echo $@
+ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
include:
@echo $@
@AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/functab1.awk b/test/functab1.awk
new file mode 100644
index 00000000..05692684
--- /dev/null
+++ b/test/functab1.awk
@@ -0,0 +1,3 @@
+BEGIN {
+ delete FUNCTAB
+}
diff --git a/test/functab1.ok b/test/functab1.ok
new file mode 100644
index 00000000..2a60a4cb
--- /dev/null
+++ b/test/functab1.ok
@@ -0,0 +1,2 @@
+gawk: functab1.awk:3: fatal: `delete' is not allowed with FUNCTAB
+EXIT CODE: 2
diff --git a/test/functab2.awk b/test/functab2.awk
new file mode 100644
index 00000000..9a07dfc3
--- /dev/null
+++ b/test/functab2.awk
@@ -0,0 +1,8 @@
+function foo()
+{
+ print "foo!"
+}
+
+BEGIN {
+ FUNCTAB["a"] = "something"
+}
diff --git a/test/functab2.ok b/test/functab2.ok
new file mode 100644
index 00000000..32b07ad3
--- /dev/null
+++ b/test/functab2.ok
@@ -0,0 +1,2 @@
+gawk: functab2.awk:7: fatal: cannot assign to elements of FUNCTAB
+EXIT CODE: 2
diff --git a/test/functab3.awk b/test/functab3.awk
new file mode 100644
index 00000000..98fa49b1
--- /dev/null
+++ b/test/functab3.awk
@@ -0,0 +1,10 @@
+function foo()
+{
+ print "foo!"
+}
+
+BEGIN {
+ x = FUNCTAB["foo"]
+ print "x =", x
+ @x()
+}
diff --git a/test/functab3.ok b/test/functab3.ok
new file mode 100644
index 00000000..66f53d72
--- /dev/null
+++ b/test/functab3.ok
@@ -0,0 +1,2 @@
+x = foo
+foo!
diff --git a/test/functab4.awk b/test/functab4.awk
new file mode 100644
index 00000000..0d9d4267
--- /dev/null
+++ b/test/functab4.awk
@@ -0,0 +1,14 @@
+@load "filefuncs"
+
+function foo()
+{
+ print "foo!"
+}
+
+BEGIN {
+ x = FUNCTAB["chdir"]
+ print "x =", x
+ @x("/tmp")
+ printf "we are now in --> "
+ system("/bin/pwd || /usr/bin/pwd")
+}
diff --git a/test/functab4.ok b/test/functab4.ok
new file mode 100644
index 00000000..70a520b7
--- /dev/null
+++ b/test/functab4.ok
@@ -0,0 +1,3 @@
+x = chdir
+gawk: functab4.awk:11: fatal: cannot (yet) call extension functions indirectly
+EXIT CODE: 2
diff --git a/test/id.awk b/test/id.awk
new file mode 100644
index 00000000..2a35e42c
--- /dev/null
+++ b/test/id.awk
@@ -0,0 +1,11 @@
+function function1()
+{
+ print "function1"
+}
+
+BEGIN {
+ an_array[1] = 1
+
+ for (i in PROCINFO["identifiers"])
+ printf("%s -> %s\n", i, PROCINFO["identifiers"][i])
+}
diff --git a/test/id.ok b/test/id.ok
new file mode 100644
index 00000000..d31573de
--- /dev/null
+++ b/test/id.ok
@@ -0,0 +1,32 @@
+FUNCTAB -> array
+ARGV -> array
+SYMTAB -> array
+ORS -> scalar
+ROUNDMODE -> scalar
+i -> untyped
+OFS -> scalar
+ERRNO -> scalar
+FNR -> scalar
+LINT -> scalar
+IGNORECASE -> scalar
+NR -> scalar
+function1 -> user
+ARGIND -> scalar
+NF -> scalar
+TEXTDOMAIN -> scalar
+CONVFMT -> scalar
+FIELDWIDTHS -> scalar
+ARGC -> scalar
+an_array -> untyped
+PROCINFO -> array
+PREC -> scalar
+SUBSEP -> scalar
+FPAT -> scalar
+RS -> scalar
+FS -> scalar
+OFMT -> scalar
+RLENGTH -> scalar
+RT -> scalar
+BINMODE -> scalar
+FILENAME -> scalar
+RSTART -> scalar
diff --git a/test/symtab1.awk b/test/symtab1.awk
new file mode 100644
index 00000000..6ca7d632
--- /dev/null
+++ b/test/symtab1.awk
@@ -0,0 +1,18 @@
+function dumparray(name, array, i)
+{
+ for (i in array)
+ if (isarray(array[i]))
+ dumparray(name "[" i "]", array[i])
+ else
+ printf("%s[%s] = %s\n", name, i, array[i])
+}
+
+BEGIN {
+ a[1] = 1
+ a[2][1] = 21
+ for (i in SYMTAB)
+ if (isarray(SYMTAB[i]))
+ dumparray(i, SYMTAB[i])
+ else
+ printf("SYMTAB[\"%s\"] = \"%s\"\n", i, SYMTAB[i])
+}
diff --git a/test/symtab1.ok b/test/symtab1.ok
new file mode 100644
index 00000000..3e435dd2
--- /dev/null
+++ b/test/symtab1.ok
@@ -0,0 +1,31 @@
+ARGV[0] = gawk
+SYMTAB["i"] = "i"
+SYMTAB["ROUNDMODE"] = "N"
+SYMTAB["ORS"] = "
+"
+SYMTAB["OFS"] = " "
+SYMTAB["LINT"] = "0"
+SYMTAB["FNR"] = "0"
+SYMTAB["ERRNO"] = ""
+SYMTAB["NR"] = "0"
+SYMTAB["IGNORECASE"] = "0"
+SYMTAB["TEXTDOMAIN"] = "messages"
+SYMTAB["NF"] = "-1"
+SYMTAB["ARGIND"] = "0"
+a[1] = 1
+a[2][1] = 21
+SYMTAB["ARGC"] = "1"
+SYMTAB["FIELDWIDTHS"] = ""
+SYMTAB["CONVFMT"] = "%.6g"
+SYMTAB["SUBSEP"] = ""
+SYMTAB["PREC"] = "53"
+SYMTAB["RS"] = "
+"
+SYMTAB["FPAT"] = "[^[:space:]]+"
+SYMTAB["RT"] = ""
+SYMTAB["RLENGTH"] = "0"
+SYMTAB["OFMT"] = "%.6g"
+SYMTAB["FS"] = " "
+SYMTAB["RSTART"] = "0"
+SYMTAB["FILENAME"] = ""
+SYMTAB["BINMODE"] = "0"
diff --git a/test/symtab2.awk b/test/symtab2.awk
new file mode 100644
index 00000000..bb26f75d
--- /dev/null
+++ b/test/symtab2.awk
@@ -0,0 +1,6 @@
+BEGIN {
+ a = 5
+ printf "a = %d, SYMTAB[\"a\"] = %d\n", a, SYMTAB["a"]
+ SYMTAB["a"] = 4
+ printf "a = %d, SYMTAB[\"a\"] = %d\n", a, SYMTAB["a"]
+}
diff --git a/test/symtab2.ok b/test/symtab2.ok
new file mode 100644
index 00000000..23d2bf69
--- /dev/null
+++ b/test/symtab2.ok
@@ -0,0 +1,2 @@
+a = 5, SYMTAB["a"] = 5
+a = 4, SYMTAB["a"] = 4
diff --git a/test/symtab3.awk b/test/symtab3.awk
new file mode 100644
index 00000000..4c2026dc
--- /dev/null
+++ b/test/symtab3.awk
@@ -0,0 +1 @@
+BEGIN { a = 5 ; delete SYMTAB["a"] }
diff --git a/test/symtab3.ok b/test/symtab3.ok
new file mode 100644
index 00000000..5b283583
--- /dev/null
+++ b/test/symtab3.ok
@@ -0,0 +1,2 @@
+gawk: symtab3.awk:1: fatal: `delete' is not allowed with SYMTAB
+EXIT CODE: 2