aboutsummaryrefslogtreecommitdiffstats
path: root/awk2.c
diff options
context:
space:
mode:
Diffstat (limited to 'awk2.c')
-rw-r--r--awk2.c235
1 files changed, 119 insertions, 116 deletions
diff --git a/awk2.c b/awk2.c
index 38a319c6..798c655a 100644
--- a/awk2.c
+++ b/awk2.c
@@ -5,6 +5,30 @@
* 1986
*
* $Log: awk2.c,v $
+ * Revision 1.47 89/03/22 22:09:50 david
+ * a cleaner way to handle assignment to $n where n > 0
+ *
+ * Revision 1.46 89/03/22 21:01:14 david
+ * delete some obsolete code
+ *
+ * Revision 1.45 89/03/21 19:25:37 david
+ * minor cleanup
+ *
+ * Revision 1.44 89/03/21 18:24:02 david
+ * bug fix in cmp_nodes: strings in which one was a prefix of the other compared equal
+ *
+ * Revision 1.43 89/03/21 10:55:55 david
+ * cleanup and fix of string comparison (0 length was wrong)
+ *
+ * Revision 1.42 89/03/15 22:01:17 david
+ * old case stuff removed
+ * new case stuff added
+ * fixed % operator
+ * strings with embedded \0 can now be compared
+ *
+ * Revision 1.41 89/03/15 21:32:50 david
+ * try to free up memory in as many places as possible
+ *
* Revision 1.40 88/12/15 12:57:31 david
* make casetable static
*
@@ -156,7 +180,7 @@
*
* Revision 1.2 87/10/29 21:45:44 david added support for array membership
* test, as in: if ("yes" in answers) ... this involved one more case: for
- * Node_in_array and rearrangment of the code in assoc_lookup, so thatthe
+ * Node_in_array and rearrangment of the code in assoc_lookup, so that the
* element can be located without being created
*
* Revision 1.1 87/10/27 15:23:28 david Initial revision
@@ -183,17 +207,24 @@
#include "awk.h"
+extern void do_print();
+extern NODE *do_printf();
+extern NODE *func_call();
+extern NODE *do_match();
+extern NODE *do_sub();
+extern NODE *do_getline();
+extern int in_array();
+extern void do_delete();
+
+extern double pow();
+
+static int eval_condition();
+static int is_a_number();
+static NODE *op_assign();
+
NODE *_t; /* used as a temporary in macros */
NODE *_result; /* holds result of tree_eval, for possible freeing */
NODE *ret_node;
-extern NODE *OFMT_node;
-
-/*
- * BEGIN and END blocks need special handling, because we are handed them as
- * raw Node_statement_lists, not as Node_rule_lists.
- */
-extern NODE *begin_block, *end_block;
-NODE *do_sprintf();
/* More of that debugging stuff */
#ifdef DEBUG
@@ -202,7 +233,6 @@ NODE *do_sprintf();
#define DBG_P(X)
#endif
-NODE *func_call();
extern jmp_buf func_tag;
/*
@@ -212,9 +242,12 @@ extern jmp_buf func_tag;
* entries, which may be overkill. Note also that if the system this
* is compiled on doesn't use 7-bit ascii, casetable[] should not be
* defined to the linker, so gawk should not load.
+ *
+ * Do NOT make this array static, it is used in several spots, not
+ * just in this file.
*/
#if 'a' == 97 /* it's ascii */
-static char casetable[] = {
+char casetable[] = {
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
@@ -261,7 +294,7 @@ static char casetable[] = {
'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
};
#else
-/* You lose. You will need a translation table for your character set. */
+#include "You lose. You will need a translation table for your character set."
#endif
/*
@@ -287,8 +320,6 @@ NODE *tree;
extern NODE **fields_arr;
extern int exiting, exit_val;
- NODE *do_printf();
- extern NODE *lookup();
/*
* clean up temporary strings created by evaluating expressions in
@@ -343,21 +374,6 @@ NODE *tree;
break;
case Node_statement_list:
- /*
- * because BEGIN and END do not have Node_rule_list nature,
- * yet can have exits and nexts, we special-case a setjmp of
- * rule_tag here.
- */
- if (tree == begin_block || tree == end_block) {
- switch (_setjmp(rule_tag)) {
- case TAG_CONTINUE: /* next */
- fatal("unexpected \"next\" in %s block",
- tree == begin_block ? "BEGIN" : "END");
- return 1;
- case TAG_BREAK:
- return 0;
- }
- }
for (t = tree; t != NULL; t = t->rnode) {
DBG_P(("Statements", t->lnode));
(void) interpret(t->lnode);
@@ -451,7 +467,7 @@ NODE *tree;
#define arrvar forloop->incr
PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
DBG_P(("AFOR.VAR", tree->hakvar));
- lhs = get_lhs(tree->hakvar);
+ lhs = get_lhs(tree->hakvar, 1);
t = tree->arrvar;
if (tree->arrvar->type == Node_param_list)
t = stack_ptr[tree->arrvar->param_cnt];
@@ -462,13 +478,6 @@ NODE *tree;
if (field_num == 0)
set_record(fields_arr[0]->stptr,
fields_arr[0]->stlen);
- else if (field_num > 0) {
- node0_valid = 0;
- if (NF_node->var_value->numbr == -1 &&
- field_num > NF_node->var_value->numbr)
- assign_number(&(NF_node->var_value),
- (AWKNUM) field_num);
- }
DBG_P(("AFOR.NEXTIS", *lhs));
switch (_setjmp(loop_tag)) {
case 0:
@@ -505,7 +514,7 @@ NODE *tree;
case Node_K_print:
DBG_P(("PRINT", tree));
- (void) do_print(tree);
+ do_print(tree);
break;
case Node_K_printf:
@@ -534,9 +543,6 @@ NODE *tree;
_longjmp(rule_tag, TAG_BREAK);
break;
- case Node_K_function:
- break;
-
case Node_K_return:
DBG_P(("RETURN", NULL));
ret_node = dupnode(tree_eval(tree->lnode));
@@ -563,20 +569,14 @@ NODE *
r_tree_eval(tree)
NODE *tree;
{
- NODE *op_assign();
register NODE *r, *t1, *t2; /* return value & temporary subtrees */
int i;
register NODE **lhs;
int di;
- AWKNUM x;
- int samecase = 0;
- extern int ignorecase;
+ AWKNUM x, x2;
+ long lx;
struct re_pattern_buffer *rp;
extern NODE **fields_arr;
- extern NODE *do_getline();
- extern NODE *do_match();
- extern NODE *do_sub();
- extern double pow();
if (tree->type != Node_var)
source = tree->source_file;
@@ -635,7 +635,7 @@ NODE *tree;
case Node_subscript:
case Node_field_spec:
DBG_P(("var_type ref", tree));
- lhs = get_lhs(tree);
+ lhs = get_lhs(tree, 0);
field_num = -1;
deref = 0;
return *lhs;
@@ -657,27 +657,29 @@ NODE *tree;
}
break;
- case Node_case_match:
- case Node_case_nomatch:
- samecase = 1;
- /* fall through */
case Node_match:
case Node_nomatch:
DBG_P(("ASSIGN_[no]match", tree));
t1 = force_string(tree_eval(tree->lnode));
- if (tree->rnode->type == Node_regex)
+ if (tree->rnode->type == Node_regex) {
rp = tree->rnode->rereg;
- else {
- rp = make_regexp(force_string(tree_eval(tree->rnode)));
+ if (!strict && ((IGNORECASE_node->var_value->numbr != 0)
+ ^ (tree->rnode->re_case != 0))) {
+ /* recompile since case sensitivity differs */
+ rp = tree->rnode->rereg =
+ mk_re_parse(tree->rnode->re_text,
+ (IGNORECASE_node->var_value->numbr != 0));
+ tree->rnode->re_case = (IGNORECASE_node->var_value->numbr != 0);
+ }
+ } else {
+ rp = make_regexp(force_string(tree_eval(tree->rnode)),
+ (IGNORECASE_node->var_value->numbr != 0));
if (rp == NULL)
cant_happen();
}
- if (! strict && (ignorecase || samecase))
- rp->translate = casetable;
i = re_search(rp, t1->stptr, t1->stlen, 0, t1->stlen,
(struct re_registers *) NULL);
- i = (i == -1) ^ (tree->type == Node_match ||
- tree->type == Node_case_match);
+ i = (i == -1) ^ (tree->type == Node_match);
free_temp(t1);
return tmp_number((AWKNUM) i);
@@ -690,19 +692,12 @@ NODE *tree;
case Node_assign:
DBG_P(("ASSIGN", tree));
r = tree_eval(tree->rnode);
- lhs = get_lhs(tree->lnode);
+ lhs = get_lhs(tree->lnode, 1);
*lhs = dupnode(r);
+ do_deref();
if (field_num == 0)
set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
- else if (field_num > 0) {
- node0_valid = 0;
- if (NF_node->var_value->numbr == -1 &&
- field_num > NF_node->var_value->numbr)
- assign_number(&(NF_node->var_value),
- (AWKNUM) field_num);
- }
field_num = -1;
- do_deref();
return *lhs;
/* other assignment types are easier because they are numeric */
@@ -733,8 +728,7 @@ NODE *tree;
t1 = force_string(t1);
t2 = force_string(t2);
- emalloc(r, NODE *, sizeof(NODE), "tree_eval");
- r->type = Node_val;
+ r = newnode(Node_val);
r->flags = (STR|TEMP);
r->stlen = t1->stlen + t2->stlen;
r->stref = 1;
@@ -817,7 +811,9 @@ NODE *tree;
free_temp(t1);
return tmp_number((AWKNUM) 0);
}
- x = ((int) t1->numbr) % ((int) x);
+ lx = t1->numbr / x; /* assignment to long truncates */
+ x2 = lx * x;
+ x = t1->numbr - x2;
free_temp(t1);
return tmp_number(x);
@@ -845,6 +841,7 @@ NODE *tree;
* This makes numeric operations slightly more efficient. Just change the
* value of a numeric node, if possible
*/
+void
assign_number(ptr, value)
NODE **ptr;
AWKNUM value;
@@ -873,24 +870,16 @@ AWKNUM value;
/* Is TREE true or false? Returns 0==false, non-zero==true */
-int
+static int
eval_condition(tree)
NODE *tree;
{
register NODE *t1;
int ret;
- extern double atof();
if (tree == NULL) /* Null trees are the easiest kinds */
return 1;
- switch (tree->type) {
- /* Maybe it's easy; check and see. */
- /* BEGIN and END are always false */
- case Node_K_BEGIN:
- case Node_K_END:
- return 0;
- break;
-
+ if (tree->type == Node_line_range) {
/*
* Node_line_range is kind of like Node_match, EXCEPT: the
* lnode field (more properly, the condpair field) is a node
@@ -904,7 +893,6 @@ NODE *tree;
* able to begin and end on a single input record, so this
* isn't an ELSE IF, as noted above.
*/
- case Node_line_range:
if (!tree->triggered)
if (!eval_condition(tree->condpair->lnode))
return 0;
@@ -922,10 +910,6 @@ NODE *tree;
*/
t1 = tree_eval(tree);
-#ifdef DEBUG
- if (t1->type != Node_val)
- cant_happen();
-#endif
if (t1->flags & STR)
ret = t1->stlen != 0;
else
@@ -992,6 +976,8 @@ cmp_nodes(t1, t2)
NODE *t1, *t2;
{
AWKNUM d;
+ int ret;
+ int len1, len2;
if (t1 == t2)
return 0;
@@ -1038,17 +1024,52 @@ NODE *t1, *t2;
}
strings:
- return strcmp(t1->stptr, t2->stptr);
+ len1 = t1->stlen;
+ len2 = t2->stlen;
+ if (len1 == 0) {
+ if (len2 == 0)
+ return 0;
+ else
+ return -1;
+ } else if (len2 == 0)
+ return 1;
+ ret = memcmp(t1->stptr, t2->stptr, len1 <= len2 ? len1 : len2);
+ if (ret == 0 && len1 != len2)
+ return len1 < len2 ? -1: 1;
+ return ret;
}
-NODE *
+#ifdef NOMEMCMP
+/*
+ * memcmp --- compare strings.
+ *
+ * We use our own routine since it has to act like strcmp() for return
+ * value, and the BSD manual says bcmp() only returns zero/non-zero.
+ */
+
+static int
+memcmp (s1, s2, l)
+register char *s1, *s2;
+register int l;
+{
+ for (; l--; s1++, s2++) {
+ if (*s1 != *s2)
+ return (*s1 - *s2);
+ }
+ return (*--s1 - *--s2);
+}
+#endif
+
+static NODE *
op_assign(tree)
NODE *tree;
{
AWKNUM rval, lval;
NODE **lhs;
+ AWKNUM t1, t2;
+ long ltemp;
- lhs = get_lhs(tree->lnode);
+ lhs = get_lhs(tree->lnode, 1);
lval = force_number(*lhs);
switch(tree->type) {
@@ -1057,17 +1078,10 @@ NODE *tree;
DBG_P(("+-X", tree));
assign_number(lhs,
lval + (tree->type == Node_preincrement ? 1.0 : -1.0));
+ do_deref();
if (field_num == 0)
set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
- else if (field_num > 0) {
- node0_valid = 0;
- if (NF_node->var_value->numbr == -1 &&
- field_num > NF_node->var_value->numbr)
- assign_number(&(NF_node->var_value),
- (AWKNUM) field_num);
- }
field_num = -1;
- do_deref();
return *lhs;
break;
@@ -1076,17 +1090,10 @@ NODE *tree;
DBG_P(("X+-", tree));
assign_number(lhs,
lval + (tree->type == Node_postincrement ? 1.0 : -1.0));
+ do_deref();
if (field_num == 0)
set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
- else if (field_num > 0) {
- node0_valid = 0;
- if (NF_node->var_value->numbr == -1 &&
- field_num > NF_node->var_value->numbr)
- assign_number(&(NF_node->var_value),
- (AWKNUM) field_num);
- }
field_num = -1;
- do_deref();
return tmp_number(lval);
}
@@ -1110,7 +1117,10 @@ NODE *tree;
case Node_assign_mod:
DBG_P(("ASSIGN_mod", tree));
- assign_number(lhs, (AWKNUM) (((int) lval) % ((int) rval)));
+ ltemp = lval / rval; /* assignment to long truncates */
+ t1 = ltemp * rval;
+ t2 = lval - t1;
+ assign_number(lhs, t2);
break;
case Node_assign_plus:
@@ -1123,17 +1133,10 @@ NODE *tree;
assign_number(lhs, lval - rval);
break;
}
+ do_deref();
if (field_num == 0)
set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
- else if (field_num > 0) {
- node0_valid = 0;
- if (NF_node->var_value->numbr == -1 &&
- field_num > NF_node->var_value->numbr)
- assign_number(&(NF_node->var_value),
- (AWKNUM) field_num);
- }
field_num = -1;
- do_deref();
return *lhs;
}