d6da9b77666907bcb80c4b2504e8f4e42c08e11b
[packages/gawk.git] / gawk-gsub_regenarate.patch
1 diff --git a/ChangeLog b/ChangeLog
2 index bf0f749..913b4a3 100644
3 --- a/ChangeLog
4 +++ b/ChangeLog
5 @@ -1,3 +1,21 @@
6 +2011-07-05         John Haque      <address@hidden>
7
8 +       * awk.h (Op_sub_builtin): New opcode.
9 +       (GSUB, GENSUB, AFTER_ASSIGN, LITERAL): New flags for 
10 +       Op_sub_builtin.
11 +       * awkgram.y (struct tokentab): Change opcode to Op_sub_builtin
12 +       for sub, gsub and gensub.
13 +       (snode): Update processing of sub, gsub and gensub.
14 +       * builtin.c (do_sub, do_gsub, do_gensub): Nuke.
15 +       (sub_common): Renamed to do_sub. Relocate gensub argument
16 +       handling code from do_gensub to here; Simplify the code a
17 +       little bit. 
18 +       * eval.c (r_interpret): Handle Op_sub_builtin. Avoid field
19 +       re-splitting or $0 rebuilding if (g)sub target string is
20 +       a field and no substitutions were done.
21 +       * pprint (profile.c): Add case for the new opcode.
22 +       * print_instruction (debug.c): Ditto.
23 +
24  2011-06-24         Arnold D. Robbins     <arnold@skeeve.com>
25  
26         * Makefile.am (EXTRA_DIST): Add ChangeLog.0.
27 diff --git a/awk.h b/awk.h
28 index 25abf41..e224061 100644
29 --- a/awk.h
30 +++ b/awk.h
31 @@ -521,6 +521,7 @@ typedef enum opcodeval {
32         Op_K_nextfile,
33  
34         Op_builtin,
35 +       Op_sub_builtin,         /* sub, gsub and gensub */
36         Op_in_array,            /* boolean test of membership in array */
37  
38         /* function call instruction */
39 @@ -626,6 +627,16 @@ typedef struct exp_instruction {
40  #define target_jmp      d.di
41  #define target_break    x.xi
42  
43 +/* Op_sub_builtin */
44 +#define sub_flags       d.dl
45 +#define GSUB            0x01   /* builtin is gsub */
46 +#define GENSUB          0x02   /* builtin is gensub */
47 +#define AFTER_ASSIGN    0x04   /* (g)sub target is a field or a special var with
48 +                                * set_XX routine.
49 +                                */
50 +#define LITERAL         0x08   /* target is a literal string */
51 +
52 +
53  /* Op_K_exit */
54  #define target_end      d.di
55  #define target_atexit   x.xi   
56 @@ -1181,9 +1192,7 @@ extern NODE *do_cos(int nargs);
57  extern NODE *do_rand(int nargs);
58  extern NODE *do_srand(int nargs);
59  extern NODE *do_match(int nargs);
60 -extern NODE *do_gsub(int nargs);
61 -extern NODE *do_sub(int nargs);
62 -extern NODE *do_gensub(int nargs);
63 +extern NODE *do_sub(int nargs, unsigned int flags, int *num_matches);
64  extern NODE *format_tree(const char *, size_t, NODE **, long);
65  extern NODE *do_lshift(int nargs);
66  extern NODE *do_rshift(int nargs);
67 diff --git a/awkgram.c b/awkgram.c
68 index 4edec57..ac4ceaa 100644
69 --- a/awkgram.c
70 +++ b/awkgram.c
71 @@ -2065,7 +2065,7 @@ yyreduce:
72      {
73          case 3:
74  
75 -/* Line 1806 of yacc.c  */
76 +/* Line 1821 of yacc.c  */
77  #line 221 "awkgram.y"
78      {
79                 rule = 0;
80 @@ -2075,7 +2075,7 @@ yyreduce:
81  
82    case 5:
83  
84 -/* Line 1806 of yacc.c  */
85 +/* Line 1821 of yacc.c  */
86  #line 227 "awkgram.y"
87      {
88                 next_sourcefile();
89 @@ -2084,7 +2084,7 @@ yyreduce:
90  
91    case 6:
92  
93 -/* Line 1806 of yacc.c  */
94 +/* Line 1821 of yacc.c  */
95  #line 231 "awkgram.y"
96      {
97                 rule = 0;
98 @@ -2098,7 +2098,7 @@ yyreduce:
99  
100    case 7:
101  
102 -/* Line 1806 of yacc.c  */
103 +/* Line 1821 of yacc.c  */
104  #line 243 "awkgram.y"
105      {
106                 (void) append_rule((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
107 @@ -2107,7 +2107,7 @@ yyreduce:
108  
109    case 8:
110  
111 -/* Line 1806 of yacc.c  */
112 +/* Line 1821 of yacc.c  */
113  #line 247 "awkgram.y"
114      {
115                 if (rule != Rule) {
116 @@ -2123,7 +2123,7 @@ yyreduce:
117  
118    case 9:
119  
120 -/* Line 1806 of yacc.c  */
121 +/* Line 1821 of yacc.c  */
122  #line 258 "awkgram.y"
123      {
124                 can_return = FALSE;
125 @@ -2136,7 +2136,7 @@ yyreduce:
126  
127    case 10:
128  
129 -/* Line 1806 of yacc.c  */
130 +/* Line 1821 of yacc.c  */
131  #line 266 "awkgram.y"
132      {
133                 want_source = FALSE;
134 @@ -2146,7 +2146,7 @@ yyreduce:
135  
136    case 11:
137  
138 -/* Line 1806 of yacc.c  */
139 +/* Line 1821 of yacc.c  */
140  #line 274 "awkgram.y"
141      {
142                 if (include_source((yyvsp[(1) - (1)])) < 0)
143 @@ -2159,35 +2159,35 @@ yyreduce:
144  
145    case 12:
146  
147 -/* Line 1806 of yacc.c  */
148 +/* Line 1821 of yacc.c  */
149  #line 282 "awkgram.y"
150      { (yyval) = NULL; }
151      break;
152  
153    case 13:
154  
155 -/* Line 1806 of yacc.c  */
156 +/* Line 1821 of yacc.c  */
157  #line 284 "awkgram.y"
158      { (yyval) = NULL; }
159      break;
160  
161    case 14:
162  
163 -/* Line 1806 of yacc.c  */
164 +/* Line 1821 of yacc.c  */
165  #line 289 "awkgram.y"
166      {  (yyval) = NULL; rule = Rule; }
167      break;
168  
169    case 15:
170  
171 -/* Line 1806 of yacc.c  */
172 +/* Line 1821 of yacc.c  */
173  #line 291 "awkgram.y"
174      {  (yyval) = (yyvsp[(1) - (1)]); rule = Rule; }
175      break;
176  
177    case 16:
178  
179 -/* Line 1806 of yacc.c  */
180 +/* Line 1821 of yacc.c  */
181  #line 293 "awkgram.y"
182      {
183                 INSTRUCTION *tp;
184 @@ -2218,7 +2218,7 @@ yyreduce:
185  
186    case 17:
187  
188 -/* Line 1806 of yacc.c  */
189 +/* Line 1821 of yacc.c  */
190  #line 319 "awkgram.y"
191      {
192                 static int begin_seen = 0;
193 @@ -2234,7 +2234,7 @@ yyreduce:
194  
195    case 18:
196  
197 -/* Line 1806 of yacc.c  */
198 +/* Line 1821 of yacc.c  */
199  #line 330 "awkgram.y"
200      {
201                 static int end_seen = 0;
202 @@ -2250,7 +2250,7 @@ yyreduce:
203  
204    case 19:
205  
206 -/* Line 1806 of yacc.c  */
207 +/* Line 1821 of yacc.c  */
208  #line 341 "awkgram.y"
209      {
210                 (yyvsp[(1) - (1)])->in_rule = rule = BEGINFILE;
211 @@ -2261,7 +2261,7 @@ yyreduce:
212  
213    case 20:
214  
215 -/* Line 1806 of yacc.c  */
216 +/* Line 1821 of yacc.c  */
217  #line 347 "awkgram.y"
218      {
219                 (yyvsp[(1) - (1)])->in_rule = rule = ENDFILE;
220 @@ -2272,7 +2272,7 @@ yyreduce:
221  
222    case 21:
223  
224 -/* Line 1806 of yacc.c  */
225 +/* Line 1821 of yacc.c  */
226  #line 356 "awkgram.y"
227      {
228                 if ((yyvsp[(2) - (5)]) == NULL)
229 @@ -2284,21 +2284,21 @@ yyreduce:
230  
231    case 22:
232  
233 -/* Line 1806 of yacc.c  */
234 +/* Line 1821 of yacc.c  */
235  #line 366 "awkgram.y"
236      { (yyval) = (yyvsp[(1) - (1)]); }
237      break;
238  
239    case 23:
240  
241 -/* Line 1806 of yacc.c  */
242 +/* Line 1821 of yacc.c  */
243  #line 368 "awkgram.y"
244      { (yyval) = (yyvsp[(1) - (1)]); }
245      break;
246  
247    case 24:
248  
249 -/* Line 1806 of yacc.c  */
250 +/* Line 1821 of yacc.c  */
251  #line 370 "awkgram.y"
252      {
253                 yyerror(_("`%s' is a built-in function, it cannot be redefined"),
254 @@ -2314,14 +2314,14 @@ yyreduce:
255  
256    case 25:
257  
258 -/* Line 1806 of yacc.c  */
259 +/* Line 1821 of yacc.c  */
260  #line 381 "awkgram.y"
261      { (yyval) = (yyvsp[(2) - (2)]); }
262      break;
263  
264    case 28:
265  
266 -/* Line 1806 of yacc.c  */
267 +/* Line 1821 of yacc.c  */
268  #line 391 "awkgram.y"
269      {
270                 param_counter = 0;
271 @@ -2331,7 +2331,7 @@ yyreduce:
272  
273    case 29:
274  
275 -/* Line 1806 of yacc.c  */
276 +/* Line 1821 of yacc.c  */
277  #line 396 "awkgram.y"
278      {
279                         NODE *t;
280 @@ -2353,14 +2353,14 @@ yyreduce:
281  
282    case 30:
283  
284 -/* Line 1806 of yacc.c  */
285 +/* Line 1821 of yacc.c  */
286  #line 420 "awkgram.y"
287      { ++want_regexp; }
288      break;
289  
290    case 31:
291  
292 -/* Line 1806 of yacc.c  */
293 +/* Line 1821 of yacc.c  */
294  #line 422 "awkgram.y"
295      {
296                   NODE *n, *exp;
297 @@ -2393,21 +2393,21 @@ yyreduce:
298  
299    case 32:
300  
301 -/* Line 1806 of yacc.c  */
302 +/* Line 1821 of yacc.c  */
303  #line 453 "awkgram.y"
304      { bcfree((yyvsp[(1) - (1)])); }
305      break;
306  
307    case 34:
308  
309 -/* Line 1806 of yacc.c  */
310 +/* Line 1821 of yacc.c  */
311  #line 459 "awkgram.y"
312      {  (yyval) = NULL; }
313      break;
314  
315    case 35:
316  
317 -/* Line 1806 of yacc.c  */
318 +/* Line 1821 of yacc.c  */
319  #line 461 "awkgram.y"
320      {
321                 if ((yyvsp[(2) - (2)]) == NULL)
322 @@ -2425,28 +2425,28 @@ yyreduce:
323  
324    case 36:
325  
326 -/* Line 1806 of yacc.c  */
327 +/* Line 1821 of yacc.c  */
328  #line 474 "awkgram.y"
329      {  (yyval) = NULL; }
330      break;
331  
332    case 39:
333  
334 -/* Line 1806 of yacc.c  */
335 +/* Line 1821 of yacc.c  */
336  #line 484 "awkgram.y"
337      { (yyval) = NULL; }
338      break;
339  
340    case 40:
341  
342 -/* Line 1806 of yacc.c  */
343 +/* Line 1821 of yacc.c  */
344  #line 486 "awkgram.y"
345      { (yyval) = (yyvsp[(2) - (3)]); }
346      break;
347  
348    case 41:
349  
350 -/* Line 1806 of yacc.c  */
351 +/* Line 1821 of yacc.c  */
352  #line 488 "awkgram.y"
353      {
354                 if (do_profiling)
355 @@ -2458,7 +2458,7 @@ yyreduce:
356  
357    case 42:
358  
359 -/* Line 1806 of yacc.c  */
360 +/* Line 1821 of yacc.c  */
361  #line 495 "awkgram.y"
362      {
363                 INSTRUCTION *dflt, *curr = NULL, *cexp, *cstmt;
364 @@ -2553,7 +2553,7 @@ yyreduce:
365  
366    case 43:
367  
368 -/* Line 1806 of yacc.c  */
369 +/* Line 1821 of yacc.c  */
370  #line 585 "awkgram.y"
371      { 
372                 /*
373 @@ -2600,7 +2600,7 @@ yyreduce:
374  
375    case 44:
376  
377 -/* Line 1806 of yacc.c  */
378 +/* Line 1821 of yacc.c  */
379  #line 627 "awkgram.y"
380      {
381                 /*
382 @@ -2647,7 +2647,7 @@ yyreduce:
383  
384    case 45:
385  
386 -/* Line 1806 of yacc.c  */
387 +/* Line 1821 of yacc.c  */
388  #line 669 "awkgram.y"
389      {
390                 INSTRUCTION *ip;
391 @@ -2767,7 +2767,7 @@ regular_loop:
392  
393    case 46:
394  
395 -/* Line 1806 of yacc.c  */
396 +/* Line 1821 of yacc.c  */
397  #line 784 "awkgram.y"
398      {
399                 (yyval) = mk_for_loop((yyvsp[(1) - (12)]), (yyvsp[(3) - (12)]), (yyvsp[(6) - (12)]), (yyvsp[(9) - (12)]), (yyvsp[(12) - (12)]));
400 @@ -2779,7 +2779,7 @@ regular_loop:
401  
402    case 47:
403  
404 -/* Line 1806 of yacc.c  */
405 +/* Line 1821 of yacc.c  */
406  #line 791 "awkgram.y"
407      {
408                 (yyval) = mk_for_loop((yyvsp[(1) - (11)]), (yyvsp[(3) - (11)]), (INSTRUCTION *) NULL, (yyvsp[(8) - (11)]), (yyvsp[(11) - (11)]));
409 @@ -2791,7 +2791,7 @@ regular_loop:
410  
411    case 48:
412  
413 -/* Line 1806 of yacc.c  */
414 +/* Line 1821 of yacc.c  */
415  #line 798 "awkgram.y"
416      {
417                 if (do_profiling)
418 @@ -2803,7 +2803,7 @@ regular_loop:
419  
420    case 49:
421  
422 -/* Line 1806 of yacc.c  */
423 +/* Line 1821 of yacc.c  */
424  #line 808 "awkgram.y"
425      { 
426                 if (! break_allowed)
427 @@ -2817,7 +2817,7 @@ regular_loop:
428  
429    case 50:
430  
431 -/* Line 1806 of yacc.c  */
432 +/* Line 1821 of yacc.c  */
433  #line 817 "awkgram.y"
434      {
435                 if (! continue_allowed)
436 @@ -2831,7 +2831,7 @@ regular_loop:
437  
438    case 51:
439  
440 -/* Line 1806 of yacc.c  */
441 +/* Line 1821 of yacc.c  */
442  #line 826 "awkgram.y"
443      {
444                 /* if inside function (rule = 0), resolve context at run-time */
445 @@ -2845,7 +2845,7 @@ regular_loop:
446  
447    case 52:
448  
449 -/* Line 1806 of yacc.c  */
450 +/* Line 1821 of yacc.c  */
451  #line 835 "awkgram.y"
452      {
453                 if (do_traditional)
454 @@ -2865,7 +2865,7 @@ regular_loop:
455  
456    case 53:
457  
458 -/* Line 1806 of yacc.c  */
459 +/* Line 1821 of yacc.c  */
460  #line 850 "awkgram.y"
461      {
462                 /* Initialize the two possible jump targets, the actual target
463 @@ -2885,7 +2885,7 @@ regular_loop:
464  
465    case 54:
466  
467 -/* Line 1806 of yacc.c  */
468 +/* Line 1821 of yacc.c  */
469  #line 865 "awkgram.y"
470      {
471                 if (! can_return)
472 @@ -2895,7 +2895,7 @@ regular_loop:
473  
474    case 55:
475  
476 -/* Line 1806 of yacc.c  */
477 +/* Line 1821 of yacc.c  */
478  #line 868 "awkgram.y"
479      {
480                 if ((yyvsp[(3) - (4)]) == NULL) {
481 @@ -2909,14 +2909,14 @@ regular_loop:
482  
483    case 57:
484  
485 -/* Line 1806 of yacc.c  */
486 +/* Line 1821 of yacc.c  */
487  #line 888 "awkgram.y"
488      { in_print = TRUE; in_parens = 0; }
489      break;
490  
491    case 58:
492  
493 -/* Line 1806 of yacc.c  */
494 +/* Line 1821 of yacc.c  */
495  #line 889 "awkgram.y"
496      {
497                 /*
498 @@ -3016,14 +3016,14 @@ regular_loop:
499  
500    case 59:
501  
502 -/* Line 1806 of yacc.c  */
503 +/* Line 1821 of yacc.c  */
504  #line 984 "awkgram.y"
505      { sub_counter = 0; }
506      break;
507  
508    case 60:
509  
510 -/* Line 1806 of yacc.c  */
511 +/* Line 1821 of yacc.c  */
512  #line 985 "awkgram.y"
513      {
514                 char *arr = (yyvsp[(2) - (4)])->lextok;
515 @@ -3053,7 +3053,7 @@ regular_loop:
516  
517    case 61:
518  
519 -/* Line 1806 of yacc.c  */
520 +/* Line 1821 of yacc.c  */
521  #line 1014 "awkgram.y"
522      {
523                 static short warned = FALSE;
524 @@ -3077,35 +3077,35 @@ regular_loop:
525  
526    case 62:
527  
528 -/* Line 1806 of yacc.c  */
529 +/* Line 1821 of yacc.c  */
530  #line 1033 "awkgram.y"
531      {  (yyval) = optimize_assignment((yyvsp[(1) - (1)])); }
532      break;
533  
534    case 63:
535  
536 -/* Line 1806 of yacc.c  */
537 +/* Line 1821 of yacc.c  */
538  #line 1038 "awkgram.y"
539      { (yyval) = NULL; }
540      break;
541  
542    case 64:
543  
544 -/* Line 1806 of yacc.c  */
545 +/* Line 1821 of yacc.c  */
546  #line 1040 "awkgram.y"
547      { (yyval) = (yyvsp[(1) - (1)]); }
548      break;
549  
550    case 65:
551  
552 -/* Line 1806 of yacc.c  */
553 +/* Line 1821 of yacc.c  */
554  #line 1045 "awkgram.y"
555      { (yyval) = NULL; }
556      break;
557  
558    case 66:
559  
560 -/* Line 1806 of yacc.c  */
561 +/* Line 1821 of yacc.c  */
562  #line 1047 "awkgram.y"
563      {
564                 if ((yyvsp[(1) - (2)]) == NULL)
565 @@ -3117,14 +3117,14 @@ regular_loop:
566  
567    case 67:
568  
569 -/* Line 1806 of yacc.c  */
570 +/* Line 1821 of yacc.c  */
571  #line 1054 "awkgram.y"
572      { (yyval) = NULL; }
573      break;
574  
575    case 68:
576  
577 -/* Line 1806 of yacc.c  */
578 +/* Line 1821 of yacc.c  */
579  #line 1059 "awkgram.y"
580      {
581                 INSTRUCTION *casestmt = (yyvsp[(5) - (5)]);
582 @@ -3141,7 +3141,7 @@ regular_loop:
583  
584    case 69:
585  
586 -/* Line 1806 of yacc.c  */
587 +/* Line 1821 of yacc.c  */
588  #line 1071 "awkgram.y"
589      {
590                 INSTRUCTION *casestmt = (yyvsp[(4) - (4)]);
591 @@ -3157,14 +3157,14 @@ regular_loop:
592  
593    case 70:
594  
595 -/* Line 1806 of yacc.c  */
596 +/* Line 1821 of yacc.c  */
597  #line 1085 "awkgram.y"
598      {  (yyval) = (yyvsp[(1) - (1)]); }
599      break;
600  
601    case 71:
602  
603 -/* Line 1806 of yacc.c  */
604 +/* Line 1821 of yacc.c  */
605  #line 1087 "awkgram.y"
606      { 
607                 (yyvsp[(2) - (2)])->memory->numbr = -(force_number((yyvsp[(2) - (2)])->memory));
608 @@ -3175,7 +3175,7 @@ regular_loop:
609  
610    case 72:
611  
612 -/* Line 1806 of yacc.c  */
613 +/* Line 1821 of yacc.c  */
614  #line 1093 "awkgram.y"
615      {
616                 bcfree((yyvsp[(1) - (2)]));
617 @@ -3185,14 +3185,14 @@ regular_loop:
618  
619    case 73:
620  
621 -/* Line 1806 of yacc.c  */
622 +/* Line 1821 of yacc.c  */
623  #line 1098 "awkgram.y"
624      {  (yyval) = (yyvsp[(1) - (1)]); }
625      break;
626  
627    case 74:
628  
629 -/* Line 1806 of yacc.c  */
630 +/* Line 1821 of yacc.c  */
631  #line 1100 "awkgram.y"
632      {
633                 (yyvsp[(1) - (1)])->opcode = Op_push_re;
634 @@ -3202,21 +3202,21 @@ regular_loop:
635  
636    case 75:
637  
638 -/* Line 1806 of yacc.c  */
639 +/* Line 1821 of yacc.c  */
640  #line 1108 "awkgram.y"
641      { (yyval) = (yyvsp[(1) - (1)]); }
642      break;
643  
644    case 76:
645  
646 -/* Line 1806 of yacc.c  */
647 +/* Line 1821 of yacc.c  */
648  #line 1110 "awkgram.y"
649      { (yyval) = (yyvsp[(1) - (1)]); }
650      break;
651  
652    case 78:
653  
654 -/* Line 1806 of yacc.c  */
655 +/* Line 1821 of yacc.c  */
656  #line 1120 "awkgram.y"
657      {
658                 (yyval) = (yyvsp[(2) - (3)]);
659 @@ -3225,7 +3225,7 @@ regular_loop:
660  
661    case 79:
662  
663 -/* Line 1806 of yacc.c  */
664 +/* Line 1821 of yacc.c  */
665  #line 1127 "awkgram.y"
666      {
667                 in_print = FALSE;
668 @@ -3236,14 +3236,14 @@ regular_loop:
669  
670    case 80:
671  
672 -/* Line 1806 of yacc.c  */
673 +/* Line 1821 of yacc.c  */
674  #line 1132 "awkgram.y"
675      { in_print = FALSE; in_parens = 0; }
676      break;
677  
678    case 81:
679  
680 -/* Line 1806 of yacc.c  */
681 +/* Line 1821 of yacc.c  */
682  #line 1133 "awkgram.y"
683      {
684                 if ((yyvsp[(1) - (3)])->redir_type == redirect_twoway
685 @@ -3256,7 +3256,7 @@ regular_loop:
686  
687    case 82:
688  
689 -/* Line 1806 of yacc.c  */
690 +/* Line 1821 of yacc.c  */
691  #line 1144 "awkgram.y"
692      {
693                 (yyval) = mk_condition((yyvsp[(3) - (6)]), (yyvsp[(1) - (6)]), (yyvsp[(6) - (6)]), NULL, NULL);
694 @@ -3265,7 +3265,7 @@ regular_loop:
695  
696    case 83:
697  
698 -/* Line 1806 of yacc.c  */
699 +/* Line 1821 of yacc.c  */
700  #line 1149 "awkgram.y"
701      {
702                 (yyval) = mk_condition((yyvsp[(3) - (9)]), (yyvsp[(1) - (9)]), (yyvsp[(6) - (9)]), (yyvsp[(7) - (9)]), (yyvsp[(9) - (9)]));
703 @@ -3274,14 +3274,14 @@ regular_loop:
704  
705    case 88:
706  
707 -/* Line 1806 of yacc.c  */
708 +/* Line 1821 of yacc.c  */
709  #line 1166 "awkgram.y"
710      { (yyval) = NULL; }
711      break;
712  
713    case 89:
714  
715 -/* Line 1806 of yacc.c  */
716 +/* Line 1821 of yacc.c  */
717  #line 1168 "awkgram.y"
718      {
719                 bcfree((yyvsp[(1) - (2)]));
720 @@ -3291,7 +3291,7 @@ regular_loop:
721  
722    case 92:
723  
724 -/* Line 1806 of yacc.c  */
725 +/* Line 1821 of yacc.c  */
726  #line 1181 "awkgram.y"
727      {
728                 append_param((yyvsp[(1) - (1)])->lextok);
729 @@ -3302,7 +3302,7 @@ regular_loop:
730  
731    case 93:
732  
733 -/* Line 1806 of yacc.c  */
734 +/* Line 1821 of yacc.c  */
735  #line 1187 "awkgram.y"
736      {
737                 append_param((yyvsp[(3) - (3)])->lextok);
738 @@ -3314,63 +3314,63 @@ regular_loop:
739  
740    case 94:
741  
742 -/* Line 1806 of yacc.c  */
743 +/* Line 1821 of yacc.c  */
744  #line 1194 "awkgram.y"
745      { /* func_params = NULL; */ }
746      break;
747  
748    case 95:
749  
750 -/* Line 1806 of yacc.c  */
751 +/* Line 1821 of yacc.c  */
752  #line 1196 "awkgram.y"
753      { /* func_params = NULL; */ }
754      break;
755  
756    case 96:
757  
758 -/* Line 1806 of yacc.c  */
759 +/* Line 1821 of yacc.c  */
760  #line 1198 "awkgram.y"
761      { /* func_params = NULL; */ }
762      break;
763  
764    case 97:
765  
766 -/* Line 1806 of yacc.c  */
767 +/* Line 1821 of yacc.c  */
768  #line 1204 "awkgram.y"
769      { (yyval) = NULL; }
770      break;
771  
772    case 98:
773  
774 -/* Line 1806 of yacc.c  */
775 +/* Line 1821 of yacc.c  */
776  #line 1206 "awkgram.y"
777      { (yyval) = (yyvsp[(1) - (1)]); }
778      break;
779  
780    case 99:
781  
782 -/* Line 1806 of yacc.c  */
783 +/* Line 1821 of yacc.c  */
784  #line 1211 "awkgram.y"
785      { (yyval) = NULL; }
786      break;
787  
788    case 100:
789  
790 -/* Line 1806 of yacc.c  */
791 +/* Line 1821 of yacc.c  */
792  #line 1213 "awkgram.y"
793      { (yyval) = (yyvsp[(1) - (1)]); }
794      break;
795  
796    case 101:
797  
798 -/* Line 1806 of yacc.c  */
799 +/* Line 1821 of yacc.c  */
800  #line 1218 "awkgram.y"
801      {  (yyval) = mk_expression_list(NULL, (yyvsp[(1) - (1)])); }
802      break;
803  
804    case 102:
805  
806 -/* Line 1806 of yacc.c  */
807 +/* Line 1821 of yacc.c  */
808  #line 1220 "awkgram.y"
809      {
810                 (yyval) = mk_expression_list((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]));
811 @@ -3380,35 +3380,35 @@ regular_loop:
812  
813    case 103:
814  
815 -/* Line 1806 of yacc.c  */
816 +/* Line 1821 of yacc.c  */
817  #line 1225 "awkgram.y"
818      { (yyval) = NULL; }
819      break;
820  
821    case 104:
822  
823 -/* Line 1806 of yacc.c  */
824 +/* Line 1821 of yacc.c  */
825  #line 1227 "awkgram.y"
826      { (yyval) = NULL; }
827      break;
828  
829    case 105:
830  
831 -/* Line 1806 of yacc.c  */
832 +/* Line 1821 of yacc.c  */
833  #line 1229 "awkgram.y"
834      { (yyval) = NULL; }
835      break;
836  
837    case 106:
838  
839 -/* Line 1806 of yacc.c  */
840 +/* Line 1821 of yacc.c  */
841  #line 1231 "awkgram.y"
842      { (yyval) = NULL; }
843      break;
844  
845    case 107:
846  
847 -/* Line 1806 of yacc.c  */
848 +/* Line 1821 of yacc.c  */
849  #line 1237 "awkgram.y"
850      {
851                 if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == Op_match_rec)
852 @@ -3420,21 +3420,21 @@ regular_loop:
853  
854    case 108:
855  
856 -/* Line 1806 of yacc.c  */
857 +/* Line 1821 of yacc.c  */
858  #line 1244 "awkgram.y"
859      {  (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
860      break;
861  
862    case 109:
863  
864 -/* Line 1806 of yacc.c  */
865 +/* Line 1821 of yacc.c  */
866  #line 1246 "awkgram.y"
867      {  (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
868      break;
869  
870    case 110:
871  
872 -/* Line 1806 of yacc.c  */
873 +/* Line 1821 of yacc.c  */
874  #line 1248 "awkgram.y"
875      {
876                 if ((yyvsp[(1) - (3)])->lasti->opcode == Op_match_rec)
877 @@ -3455,7 +3455,7 @@ regular_loop:
878  
879    case 111:
880  
881 -/* Line 1806 of yacc.c  */
882 +/* Line 1821 of yacc.c  */
883  #line 1264 "awkgram.y"
884      {
885                 if (do_lint_old)
886 @@ -3470,7 +3470,7 @@ regular_loop:
887  
888    case 112:
889  
890 -/* Line 1806 of yacc.c  */
891 +/* Line 1821 of yacc.c  */
892  #line 1274 "awkgram.y"
893      {
894                 if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == Op_match_rec)
895 @@ -3482,35 +3482,35 @@ regular_loop:
896  
897    case 113:
898  
899 -/* Line 1806 of yacc.c  */
900 +/* Line 1821 of yacc.c  */
901  #line 1281 "awkgram.y"
902      { (yyval) = mk_condition((yyvsp[(1) - (5)]), (yyvsp[(2) - (5)]), (yyvsp[(3) - (5)]), (yyvsp[(4) - (5)]), (yyvsp[(5) - (5)])); }
903      break;
904  
905    case 114:
906  
907 -/* Line 1806 of yacc.c  */
908 +/* Line 1821 of yacc.c  */
909  #line 1283 "awkgram.y"
910      { (yyval) = (yyvsp[(1) - (1)]); }
911      break;
912  
913    case 115:
914  
915 -/* Line 1806 of yacc.c  */
916 +/* Line 1821 of yacc.c  */
917  #line 1288 "awkgram.y"
918      { (yyval) = (yyvsp[(1) - (1)]); }
919      break;
920  
921    case 116:
922  
923 -/* Line 1806 of yacc.c  */
924 +/* Line 1821 of yacc.c  */
925  #line 1290 "awkgram.y"
926      { (yyval) = (yyvsp[(1) - (1)]); }
927      break;
928  
929    case 117:
930  
931 -/* Line 1806 of yacc.c  */
932 +/* Line 1821 of yacc.c  */
933  #line 1292 "awkgram.y"
934      {  
935                 (yyvsp[(2) - (2)])->opcode = Op_assign_quotient;
936 @@ -3520,49 +3520,49 @@ regular_loop:
937  
938    case 118:
939  
940 -/* Line 1806 of yacc.c  */
941 +/* Line 1821 of yacc.c  */
942  #line 1300 "awkgram.y"
943      { (yyval) = (yyvsp[(1) - (1)]); }
944      break;
945  
946    case 119:
947  
948 -/* Line 1806 of yacc.c  */
949 +/* Line 1821 of yacc.c  */
950  #line 1302 "awkgram.y"
951      { (yyval) = (yyvsp[(1) - (1)]); }
952      break;
953  
954    case 120:
955  
956 -/* Line 1806 of yacc.c  */
957 +/* Line 1821 of yacc.c  */
958  #line 1307 "awkgram.y"
959      { (yyval) = (yyvsp[(1) - (1)]); }
960      break;
961  
962    case 121:
963  
964 -/* Line 1806 of yacc.c  */
965 +/* Line 1821 of yacc.c  */
966  #line 1309 "awkgram.y"
967      { (yyval) = (yyvsp[(1) - (1)]); }
968      break;
969  
970    case 122:
971  
972 -/* Line 1806 of yacc.c  */
973 +/* Line 1821 of yacc.c  */
974  #line 1314 "awkgram.y"
975      { (yyval) = (yyvsp[(1) - (1)]); }
976      break;
977  
978    case 123:
979  
980 -/* Line 1806 of yacc.c  */
981 +/* Line 1821 of yacc.c  */
982  #line 1316 "awkgram.y"
983      { (yyval) = (yyvsp[(1) - (1)]); }
984      break;
985  
986    case 124:
987  
988 -/* Line 1806 of yacc.c  */
989 +/* Line 1821 of yacc.c  */
990  #line 1318 "awkgram.y"
991      {
992                 int count = 2;
993 @@ -3617,49 +3617,49 @@ regular_loop:
994  
995    case 126:
996  
997 -/* Line 1806 of yacc.c  */
998 +/* Line 1821 of yacc.c  */
999  #line 1373 "awkgram.y"
1000      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1001      break;
1002  
1003    case 127:
1004  
1005 -/* Line 1806 of yacc.c  */
1006 +/* Line 1821 of yacc.c  */
1007  #line 1375 "awkgram.y"
1008      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1009      break;
1010  
1011    case 128:
1012  
1013 -/* Line 1806 of yacc.c  */
1014 +/* Line 1821 of yacc.c  */
1015  #line 1377 "awkgram.y"
1016      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1017      break;
1018  
1019    case 129:
1020  
1021 -/* Line 1806 of yacc.c  */
1022 +/* Line 1821 of yacc.c  */
1023  #line 1379 "awkgram.y"
1024      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1025      break;
1026  
1027    case 130:
1028  
1029 -/* Line 1806 of yacc.c  */
1030 +/* Line 1821 of yacc.c  */
1031  #line 1381 "awkgram.y"
1032      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1033      break;
1034  
1035    case 131:
1036  
1037 -/* Line 1806 of yacc.c  */
1038 +/* Line 1821 of yacc.c  */
1039  #line 1383 "awkgram.y"
1040      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1041      break;
1042  
1043    case 132:
1044  
1045 -/* Line 1806 of yacc.c  */
1046 +/* Line 1821 of yacc.c  */
1047  #line 1385 "awkgram.y"
1048      {
1049                 /*
1050 @@ -3687,7 +3687,7 @@ regular_loop:
1051  
1052    case 133:
1053  
1054 -/* Line 1806 of yacc.c  */
1055 +/* Line 1821 of yacc.c  */
1056  #line 1408 "awkgram.y"
1057      {
1058                 (yyvsp[(2) - (2)])->opcode = Op_postincrement;
1059 @@ -3697,7 +3697,7 @@ regular_loop:
1060  
1061    case 134:
1062  
1063 -/* Line 1806 of yacc.c  */
1064 +/* Line 1821 of yacc.c  */
1065  #line 1413 "awkgram.y"
1066      {
1067                 (yyvsp[(2) - (2)])->opcode = Op_postdecrement;
1068 @@ -3707,7 +3707,7 @@ regular_loop:
1069  
1070    case 135:
1071  
1072 -/* Line 1806 of yacc.c  */
1073 +/* Line 1821 of yacc.c  */
1074  #line 1418 "awkgram.y"
1075      {
1076                 if (do_lint_old) {
1077 @@ -3732,7 +3732,7 @@ regular_loop:
1078  
1079    case 136:
1080  
1081 -/* Line 1806 of yacc.c  */
1082 +/* Line 1821 of yacc.c  */
1083  #line 1443 "awkgram.y"
1084      {
1085                   (yyval) = mk_getline((yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]), (yyvsp[(1) - (4)]), (yyvsp[(2) - (4)])->redir_type);
1086 @@ -3742,49 +3742,49 @@ regular_loop:
1087  
1088    case 137:
1089  
1090 -/* Line 1806 of yacc.c  */
1091 +/* Line 1821 of yacc.c  */
1092  #line 1449 "awkgram.y"
1093      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1094      break;
1095  
1096    case 138:
1097  
1098 -/* Line 1806 of yacc.c  */
1099 +/* Line 1821 of yacc.c  */
1100  #line 1451 "awkgram.y"
1101      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1102      break;
1103  
1104    case 139:
1105  
1106 -/* Line 1806 of yacc.c  */
1107 +/* Line 1821 of yacc.c  */
1108  #line 1453 "awkgram.y"
1109      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1110      break;
1111  
1112    case 140:
1113  
1114 -/* Line 1806 of yacc.c  */
1115 +/* Line 1821 of yacc.c  */
1116  #line 1455 "awkgram.y"
1117      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1118      break;
1119  
1120    case 141:
1121  
1122 -/* Line 1806 of yacc.c  */
1123 +/* Line 1821 of yacc.c  */
1124  #line 1457 "awkgram.y"
1125      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1126      break;
1127  
1128    case 142:
1129  
1130 -/* Line 1806 of yacc.c  */
1131 +/* Line 1821 of yacc.c  */
1132  #line 1459 "awkgram.y"
1133      { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
1134      break;
1135  
1136    case 143:
1137  
1138 -/* Line 1806 of yacc.c  */
1139 +/* Line 1821 of yacc.c  */
1140  #line 1464 "awkgram.y"
1141      {
1142                 (yyval) = list_create((yyvsp[(1) - (1)]));
1143 @@ -3793,7 +3793,7 @@ regular_loop:
1144  
1145    case 144:
1146  
1147 -/* Line 1806 of yacc.c  */
1148 +/* Line 1821 of yacc.c  */
1149  #line 1468 "awkgram.y"
1150      {
1151                 if ((yyvsp[(2) - (2)])->opcode == Op_match_rec) {
1152 @@ -3829,14 +3829,14 @@ regular_loop:
1153  
1154    case 145:
1155  
1156 -/* Line 1806 of yacc.c  */
1157 +/* Line 1821 of yacc.c  */
1158  #line 1499 "awkgram.y"
1159      { (yyval) = (yyvsp[(2) - (3)]); }
1160      break;
1161  
1162    case 146:
1163  
1164 -/* Line 1806 of yacc.c  */
1165 +/* Line 1821 of yacc.c  */
1166  #line 1501 "awkgram.y"
1167      {
1168                 (yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
1169 @@ -3847,7 +3847,7 @@ regular_loop:
1170  
1171    case 147:
1172  
1173 -/* Line 1806 of yacc.c  */
1174 +/* Line 1821 of yacc.c  */
1175  #line 1507 "awkgram.y"
1176      {
1177                 (yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
1178 @@ -3858,7 +3858,7 @@ regular_loop:
1179  
1180    case 148:
1181  
1182 -/* Line 1806 of yacc.c  */
1183 +/* Line 1821 of yacc.c  */
1184  #line 1513 "awkgram.y"
1185      {
1186                 static short warned1 = FALSE;
1187 @@ -3876,7 +3876,7 @@ regular_loop:
1188  
1189    case 151:
1190  
1191 -/* Line 1806 of yacc.c  */
1192 +/* Line 1821 of yacc.c  */
1193  #line 1528 "awkgram.y"
1194      {
1195                 (yyvsp[(1) - (2)])->opcode = Op_preincrement;
1196 @@ -3886,7 +3886,7 @@ regular_loop:
1197  
1198    case 152:
1199  
1200 -/* Line 1806 of yacc.c  */
1201 +/* Line 1821 of yacc.c  */
1202  #line 1533 "awkgram.y"
1203      {
1204                 (yyvsp[(1) - (2)])->opcode = Op_predecrement;
1205 @@ -3896,7 +3896,7 @@ regular_loop:
1206  
1207    case 153:
1208  
1209 -/* Line 1806 of yacc.c  */
1210 +/* Line 1821 of yacc.c  */
1211  #line 1538 "awkgram.y"
1212      {
1213                 (yyval) = list_create((yyvsp[(1) - (1)]));
1214 @@ -3905,7 +3905,7 @@ regular_loop:
1215  
1216    case 154:
1217  
1218 -/* Line 1806 of yacc.c  */
1219 +/* Line 1821 of yacc.c  */
1220  #line 1542 "awkgram.y"
1221      {
1222                 (yyval) = list_create((yyvsp[(1) - (1)]));
1223 @@ -3914,7 +3914,7 @@ regular_loop:
1224  
1225    case 155:
1226  
1227 -/* Line 1806 of yacc.c  */
1228 +/* Line 1821 of yacc.c  */
1229  #line 1546 "awkgram.y"
1230      {
1231                 if ((yyvsp[(2) - (2)])->lasti->opcode == Op_push_i
1232 @@ -3931,7 +3931,7 @@ regular_loop:
1233  
1234    case 156:
1235  
1236 -/* Line 1806 of yacc.c  */
1237 +/* Line 1821 of yacc.c  */
1238  #line 1558 "awkgram.y"
1239      {
1240             /*
1241 @@ -3946,7 +3946,7 @@ regular_loop:
1242  
1243    case 157:
1244  
1245 -/* Line 1806 of yacc.c  */
1246 +/* Line 1821 of yacc.c  */
1247  #line 1571 "awkgram.y"
1248      {
1249                 func_use((yyvsp[(1) - (1)])->lasti->func_name, FUNC_USE);
1250 @@ -3956,7 +3956,7 @@ regular_loop:
1251  
1252    case 158:
1253  
1254 -/* Line 1806 of yacc.c  */
1255 +/* Line 1821 of yacc.c  */
1256  #line 1576 "awkgram.y"
1257      {
1258                 /* indirect function call */
1259 @@ -3994,7 +3994,7 @@ regular_loop:
1260  
1261    case 159:
1262  
1263 -/* Line 1806 of yacc.c  */
1264 +/* Line 1821 of yacc.c  */
1265  #line 1612 "awkgram.y"
1266      {
1267                 param_sanity((yyvsp[(3) - (4)]));
1268 @@ -4013,42 +4013,42 @@ regular_loop:
1269  
1270    case 160:
1271  
1272 -/* Line 1806 of yacc.c  */
1273 +/* Line 1821 of yacc.c  */
1274  #line 1629 "awkgram.y"
1275      { (yyval) = NULL; }
1276      break;
1277  
1278    case 161:
1279  
1280 -/* Line 1806 of yacc.c  */
1281 +/* Line 1821 of yacc.c  */
1282  #line 1631 "awkgram.y"
1283      { (yyval) = (yyvsp[(1) - (1)]); }
1284      break;
1285  
1286    case 162:
1287  
1288 -/* Line 1806 of yacc.c  */
1289 +/* Line 1821 of yacc.c  */
1290  #line 1636 "awkgram.y"
1291      { (yyval) = NULL; }
1292      break;
1293  
1294    case 163:
1295  
1296 -/* Line 1806 of yacc.c  */
1297 +/* Line 1821 of yacc.c  */
1298  #line 1638 "awkgram.y"
1299      { (yyval) = (yyvsp[(1) - (2)]); }
1300      break;
1301  
1302    case 164:
1303  
1304 -/* Line 1806 of yacc.c  */
1305 +/* Line 1821 of yacc.c  */
1306  #line 1643 "awkgram.y"
1307      {  (yyval) = (yyvsp[(1) - (1)]); }
1308      break;
1309  
1310    case 165:
1311  
1312 -/* Line 1806 of yacc.c  */
1313 +/* Line 1821 of yacc.c  */
1314  #line 1645 "awkgram.y"
1315      {
1316                 (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
1317 @@ -4057,7 +4057,7 @@ regular_loop:
1318  
1319    case 166:
1320  
1321 -/* Line 1806 of yacc.c  */
1322 +/* Line 1821 of yacc.c  */
1323  #line 1652 "awkgram.y"
1324      {
1325                 INSTRUCTION *ip = (yyvsp[(1) - (1)])->lasti; 
1326 @@ -4076,7 +4076,7 @@ regular_loop:
1327  
1328    case 167:
1329  
1330 -/* Line 1806 of yacc.c  */
1331 +/* Line 1821 of yacc.c  */
1332  #line 1669 "awkgram.y"
1333      {
1334                 INSTRUCTION *t = (yyvsp[(2) - (3)]);
1335 @@ -4095,14 +4095,14 @@ regular_loop:
1336  
1337    case 168:
1338  
1339 -/* Line 1806 of yacc.c  */
1340 +/* Line 1821 of yacc.c  */
1341  #line 1686 "awkgram.y"
1342      {  (yyval) = (yyvsp[(1) - (1)]); }
1343      break;
1344  
1345    case 169:
1346  
1347 -/* Line 1806 of yacc.c  */
1348 +/* Line 1821 of yacc.c  */
1349  #line 1688 "awkgram.y"
1350      {
1351                 (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
1352 @@ -4111,14 +4111,14 @@ regular_loop:
1353  
1354    case 170:
1355  
1356 -/* Line 1806 of yacc.c  */
1357 +/* Line 1821 of yacc.c  */
1358  #line 1695 "awkgram.y"
1359      { (yyval) = (yyvsp[(1) - (2)]); }
1360      break;
1361  
1362    case 171:
1363  
1364 -/* Line 1806 of yacc.c  */
1365 +/* Line 1821 of yacc.c  */
1366  #line 1700 "awkgram.y"
1367      {
1368                 char *var_name = (yyvsp[(1) - (1)])->lextok;
1369 @@ -4131,7 +4131,7 @@ regular_loop:
1370  
1371    case 172:
1372  
1373 -/* Line 1806 of yacc.c  */
1374 +/* Line 1821 of yacc.c  */
1375  #line 1708 "awkgram.y"
1376      {
1377                 NODE *n;
1378 @@ -4147,7 +4147,7 @@ regular_loop:
1379  
1380    case 173:
1381  
1382 -/* Line 1806 of yacc.c  */
1383 +/* Line 1821 of yacc.c  */
1384  #line 1722 "awkgram.y"
1385      {
1386                 INSTRUCTION *ip = (yyvsp[(1) - (1)])->nexti;
1387 @@ -4165,7 +4165,7 @@ regular_loop:
1388  
1389    case 174:
1390  
1391 -/* Line 1806 of yacc.c  */
1392 +/* Line 1821 of yacc.c  */
1393  #line 1735 "awkgram.y"
1394      {
1395                 (yyval) = list_append((yyvsp[(2) - (3)]), (yyvsp[(1) - (3)]));
1396 @@ -4176,7 +4176,7 @@ regular_loop:
1397  
1398    case 175:
1399  
1400 -/* Line 1806 of yacc.c  */
1401 +/* Line 1821 of yacc.c  */
1402  #line 1744 "awkgram.y"
1403      {
1404                 (yyvsp[(1) - (1)])->opcode = Op_postincrement;
1405 @@ -4185,7 +4185,7 @@ regular_loop:
1406  
1407    case 176:
1408  
1409 -/* Line 1806 of yacc.c  */
1410 +/* Line 1821 of yacc.c  */
1411  #line 1748 "awkgram.y"
1412      {
1413                 (yyvsp[(1) - (1)])->opcode = Op_postdecrement;
1414 @@ -4194,49 +4194,49 @@ regular_loop:
1415  
1416    case 177:
1417  
1418 -/* Line 1806 of yacc.c  */
1419 +/* Line 1821 of yacc.c  */
1420  #line 1751 "awkgram.y"
1421      { (yyval) = NULL; }
1422      break;
1423  
1424    case 179:
1425  
1426 -/* Line 1806 of yacc.c  */
1427 +/* Line 1821 of yacc.c  */
1428  #line 1759 "awkgram.y"
1429      { yyerrok; }
1430      break;
1431  
1432    case 180:
1433  
1434 -/* Line 1806 of yacc.c  */
1435 +/* Line 1821 of yacc.c  */
1436  #line 1763 "awkgram.y"
1437      { yyerrok; }
1438      break;
1439  
1440    case 183:
1441  
1442 -/* Line 1806 of yacc.c  */
1443 +/* Line 1821 of yacc.c  */
1444  #line 1772 "awkgram.y"
1445      { yyerrok; }
1446      break;
1447  
1448    case 184:
1449  
1450 -/* Line 1806 of yacc.c  */
1451 +/* Line 1821 of yacc.c  */
1452  #line 1776 "awkgram.y"
1453      { (yyval) = (yyvsp[(1) - (1)]); yyerrok; }
1454      break;
1455  
1456    case 185:
1457  
1458 -/* Line 1806 of yacc.c  */
1459 +/* Line 1821 of yacc.c  */
1460  #line 1780 "awkgram.y"
1461      { yyerrok; }
1462      break;
1463  
1464  
1465  
1466 -/* Line 1806 of yacc.c  */
1467 +/* Line 1821 of yacc.c  */
1468  #line 4253 "awkgram.c"
1469        default: break;
1470      }
1471 @@ -4485,6 +4485,7 @@ struct token {
1472  #      define  RESX            0x0800  /* Bell Labs Research extension */
1473  #      define  BREAK           0x1000  /* break allowed inside */
1474  #      define  CONTINUE        0x2000  /* continue allowed inside */
1475 +       
1476         NODE *(*ptr)(int);      /* function that implements this keyword */
1477  };
1478  
1479 @@ -4542,9 +4543,9 @@ static const struct token tokentab[] = {
1480  {"for",                Op_K_for,        LEX_FOR,       BREAK|CONTINUE, 0},
1481  {"func",       Op_func, LEX_FUNCTION,  NOT_POSIX|NOT_OLD,      0},
1482  {"function",Op_func, LEX_FUNCTION,     NOT_OLD,        0},
1483 -{"gensub",     Op_builtin,      LEX_BUILTIN,   GAWKX|A(3)|A(4), do_gensub},
1484 +{"gensub",     Op_sub_builtin,  LEX_BUILTIN,   GAWKX|A(3)|A(4), 0},
1485  {"getline",    Op_K_getline_redir,      LEX_GETLINE,   NOT_OLD,        0},
1486 -{"gsub",       Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2)|A(3), do_gsub},
1487 +{"gsub",       Op_sub_builtin,  LEX_BUILTIN,   NOT_OLD|A(2)|A(3), 0},
1488  {"if",         Op_K_if,         LEX_IF,        0,              0},
1489  {"in",         Op_symbol,       LEX_IN,        0,              0},
1490  {"include",  Op_symbol,         LEX_INCLUDE,   GAWKX,  0},
1491 @@ -4575,7 +4576,7 @@ static const struct token tokentab[] = {
1492  #endif
1493  {"strftime",   Op_builtin,      LEX_BUILTIN,   GAWKX|A(0)|A(1)|A(2)|A(3), do_strftime},
1494  {"strtonum",   Op_builtin,    LEX_BUILTIN,     GAWKX|A(1),     do_strtonum},
1495 -{"sub",                Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2)|A(3), do_sub},
1496 +{"sub",                Op_sub_builtin,  LEX_BUILTIN,   NOT_OLD|A(2)|A(3), 0},
1497  {"substr",     Op_builtin,      LEX_BUILTIN,   A(2)|A(3),      do_substr},
1498  {"switch",     Op_K_switch,     LEX_SWITCH,    GAWKX|BREAK,    0},
1499  {"system",     Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_system},
1500 @@ -6286,8 +6287,6 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
1501                 assert(nexp > 0);
1502         }               
1503  
1504 -       r->builtin = tokentab[idx].ptr;
1505 -
1506         /* check against how many args. are allowed for this builtin */
1507         args_allowed = tokentab[idx].flags & ARGS;
1508         if (args_allowed && (args_allowed & A(nexp)) == 0) {
1509 @@ -6296,7 +6295,85 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
1510                 return NULL;
1511         }
1512  
1513 +       /* special processing for sub, gsub and gensub */
1514 +
1515 +       if (tokentab[idx].value == Op_sub_builtin) {
1516 +               const char *operator = tokentab[idx].operator;
1517 +
1518 +               r->sub_flags = 0;
1519 +
1520 +               arg = subn->nexti;              /* first arg list */
1521 +               (void) mk_rexp(arg);
1522 +
1523 +               if (strcmp(operator, "gensub") != 0) {
1524 +                       /* sun and gsub */
1525 +
1526 +                       if (strcmp(operator, "gsub") == 0)
1527 +                               r->sub_flags |= GSUB;
1528 +
1529 +                       arg = arg->lasti->nexti;        /* 2nd arg list */
1530 +                       if (nexp == 2) {
1531 +                               INSTRUCTION *expr;
1532 +                               expr = list_create(instruction(Op_push_i));
1533 +                               expr->nexti->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
1534 +                               (void) mk_expression_list(subn,
1535 +                                               list_append(expr, instruction(Op_field_spec)));
1536 +                       }
1537 +
1538 +                       arg = arg->lasti->nexti;        /* third arg list */
1539 +                       ip = arg->lasti;
1540 +                       if (ip->opcode == Op_push_i) {
1541 +                               if (do_lint)
1542 +                                       lintwarn(_("%s: string literal as last arg of substitute has no effect"),
1543 +                                               operator);
1544 +                               r->sub_flags |= LITERAL;
1545 +                       } else {
1546 +                               if (make_assignable(ip) == NULL)
1547 +                                       yyerror(_("%s third parameter is not a changeable object"),
1548 +                                               operator);
1549 +                               else
1550 +                                       ip->do_reference = TRUE;
1551 +                       }
1552 +
1553 +                       r->expr_count = count_expressions(&subn, FALSE);
1554 +                       ip = subn->lasti;
1555 +
1556 +                       (void) list_append(subn, r);
1557 +
1558 +                       /* add after_assign code */
1559 +                       if (ip->opcode == Op_push_lhs && ip->memory->type == Node_var && ip->memory->var_assign) {
1560 +                               (void) list_append(subn, instruction(Op_var_assign));
1561 +                               subn->lasti->memory = ip->memory;
1562 +                               subn->lasti->assign_var = ip->memory->var_assign;
1563 +                               r->sub_flags |= AFTER_ASSIGN;
1564 +                       } else if (ip->opcode == Op_field_spec_lhs) {
1565 +                               (void) list_append(subn, instruction(Op_field_assign));
1566 +                               subn->lasti->field_assign = (Func_ptr) 0;
1567 +                               ip->target_assign = subn->lasti;
1568 +                               r->sub_flags |= AFTER_ASSIGN;
1569 +                       }
1570 +                       return subn;    
1571 +
1572 +               } else {
1573 +                       /* gensub */
1574 +
1575 +                       r->sub_flags |= GENSUB;
1576 +                       if (nexp == 3) {
1577 +                               ip = instruction(Op_push_i);
1578 +                               ip->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
1579 +                               (void) mk_expression_list(subn,
1580 +                                               list_append(list_create(ip), instruction(Op_field_spec)));
1581 +                       }
1582 +
1583 +                       r->expr_count = count_expressions(&subn, FALSE);
1584 +                       return list_append(subn, r);
1585 +               }
1586 +       }
1587 +
1588 +       r->builtin = tokentab[idx].ptr;
1589 +
1590         /* special case processing for a few builtins */
1591 +
1592         if (r->builtin == do_length) {
1593                 if (nexp == 0) {                
1594                     /* no args. Use $0 */
1595 @@ -6338,71 +6415,6 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
1596                         if (/*ip == arg->nexti  && */ ip->opcode == Op_push)
1597                                 ip->opcode = Op_push_array;
1598                 }
1599 -       } else if (r->builtin == do_sub || r->builtin == do_gsub) {
1600 -               int literal = FALSE;
1601 -               
1602 -               arg = subn->nexti;              /* first arg list */
1603 -               (void) mk_rexp(arg);
1604 -
1605 -               arg = arg->lasti->nexti;        /* 2nd arg list */
1606 -               if (nexp == 2) {
1607 -                       INSTRUCTION *expr;
1608 -                       expr = list_create(instruction(Op_push_i));
1609 -                       expr->nexti->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
1610 -                       (void) mk_expression_list(subn,
1611 -                                       list_append(expr, instruction(Op_field_spec)));
1612 -               }
1613 -
1614 -               arg = arg->lasti->nexti;        /* third arg list */
1615 -               ip = arg->lasti;
1616 -               if (ip->opcode == Op_push_i) {
1617 -                       if (do_lint)
1618 -                               lintwarn(_("%s: string literal as last arg of substitute has no effect"),
1619 -                                       (r->builtin == do_sub) ? "sub" : "gsub");
1620 -                       literal = TRUE;
1621 -               } else {
1622 -                       if (make_assignable(ip) == NULL)
1623 -                               yyerror(_("%s third parameter is not a changeable object"),
1624 -                                       (r->builtin == do_sub) ? "sub" : "gsub");
1625 -                       else
1626 -                               ip->do_reference = TRUE;
1627 -               }
1628 -
1629 -               /* kludge: This is one of the few cases
1630 -                * when we need to know the type of item on stack.
1631 -                * In case of string literal as the last argument,
1632 -                * pass 4 as # of args (See sub_common code in builtin.c).
1633 -                * Other cases like length(array or scalar) seem
1634 -                * to work out ok.
1635 -                */
1636 -               
1637 -               r->expr_count = count_expressions(&subn, FALSE) + !!literal;
1638 -               ip = subn->lasti;
1639 -
1640 -               (void) list_append(subn, r);
1641 -
1642 -               /* add after_assign bytecode(s) */
1643 -               if (ip->opcode == Op_push_lhs && ip->memory->type == Node_var && ip->memory->var_assign) {
1644 -                       (void) list_append(subn, instruction(Op_var_assign));
1645 -                       subn->lasti->memory = ip->memory;
1646 -                       subn->lasti->assign_var = ip->memory->var_assign;
1647 -               } else if (ip->opcode == Op_field_spec_lhs) {
1648 -                       (void) list_append(subn, instruction(Op_field_assign));
1649 -                       subn->lasti->field_assign = (Func_ptr) 0;
1650 -                       ip->target_assign = subn->lasti;
1651 -               }
1652 -               return subn;    
1653 -       } else if (r->builtin == do_gensub) {
1654 -               if (nexp == 3) {
1655 -                       arg = subn->nexti->lasti->nexti->lasti->nexti;  /* 3rd arg list */
1656 -                       ip = instruction(Op_push_i);
1657 -                       ip->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
1658 -                       (void) mk_expression_list(subn,
1659 -                                       list_append(list_create(ip),
1660 -                                               instruction(Op_field_spec)));
1661 -               }
1662 -               arg = subn->nexti;              /* first arg list */
1663 -               (void) mk_rexp(arg);
1664         } else if (r->builtin == do_split) {
1665                 arg = subn->nexti->lasti->nexti;        /* 2nd arg list */
1666                 ip = arg->lasti;
1667 diff --git a/awkgram.y b/awkgram.y
1668 index 6b28b52..4553d09 100644
1669 --- a/awkgram.y
1670 +++ b/awkgram.y
1671 @@ -1795,6 +1795,7 @@ struct token {
1672  #      define  RESX            0x0800  /* Bell Labs Research extension */
1673  #      define  BREAK           0x1000  /* break allowed inside */
1674  #      define  CONTINUE        0x2000  /* continue allowed inside */
1675 +       
1676         NODE *(*ptr)(int);      /* function that implements this keyword */
1677  };
1678  
1679 @@ -1852,9 +1853,9 @@ static const struct token tokentab[] = {
1680  {"for",                Op_K_for,        LEX_FOR,       BREAK|CONTINUE, 0},
1681  {"func",       Op_func, LEX_FUNCTION,  NOT_POSIX|NOT_OLD,      0},
1682  {"function",Op_func, LEX_FUNCTION,     NOT_OLD,        0},
1683 -{"gensub",     Op_builtin,      LEX_BUILTIN,   GAWKX|A(3)|A(4), do_gensub},
1684 +{"gensub",     Op_sub_builtin,  LEX_BUILTIN,   GAWKX|A(3)|A(4), 0},
1685  {"getline",    Op_K_getline_redir,      LEX_GETLINE,   NOT_OLD,        0},
1686 -{"gsub",       Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2)|A(3), do_gsub},
1687 +{"gsub",       Op_sub_builtin,  LEX_BUILTIN,   NOT_OLD|A(2)|A(3), 0},
1688  {"if",         Op_K_if,         LEX_IF,        0,              0},
1689  {"in",         Op_symbol,       LEX_IN,        0,              0},
1690  {"include",  Op_symbol,         LEX_INCLUDE,   GAWKX,  0},
1691 @@ -1885,7 +1886,7 @@ static const struct token tokentab[] = {
1692  #endif
1693  {"strftime",   Op_builtin,      LEX_BUILTIN,   GAWKX|A(0)|A(1)|A(2)|A(3), do_strftime},
1694  {"strtonum",   Op_builtin,    LEX_BUILTIN,     GAWKX|A(1),     do_strtonum},
1695 -{"sub",                Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2)|A(3), do_sub},
1696 +{"sub",                Op_sub_builtin,  LEX_BUILTIN,   NOT_OLD|A(2)|A(3), 0},
1697  {"substr",     Op_builtin,      LEX_BUILTIN,   A(2)|A(3),      do_substr},
1698  {"switch",     Op_K_switch,     LEX_SWITCH,    GAWKX|BREAK,    0},
1699  {"system",     Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(1),   do_system},
1700 @@ -3596,8 +3597,6 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
1701                 assert(nexp > 0);
1702         }               
1703  
1704 -       r->builtin = tokentab[idx].ptr;
1705 -
1706         /* check against how many args. are allowed for this builtin */
1707         args_allowed = tokentab[idx].flags & ARGS;
1708         if (args_allowed && (args_allowed & A(nexp)) == 0) {
1709 @@ -3606,7 +3605,85 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
1710                 return NULL;
1711         }
1712  
1713 +       /* special processing for sub, gsub and gensub */
1714 +
1715 +       if (tokentab[idx].value == Op_sub_builtin) {
1716 +               const char *operator = tokentab[idx].operator;
1717 +
1718 +               r->sub_flags = 0;
1719 +
1720 +               arg = subn->nexti;              /* first arg list */
1721 +               (void) mk_rexp(arg);
1722 +
1723 +               if (strcmp(operator, "gensub") != 0) {
1724 +                       /* sun and gsub */
1725 +
1726 +                       if (strcmp(operator, "gsub") == 0)
1727 +                               r->sub_flags |= GSUB;
1728 +
1729 +                       arg = arg->lasti->nexti;        /* 2nd arg list */
1730 +                       if (nexp == 2) {
1731 +                               INSTRUCTION *expr;
1732 +                               expr = list_create(instruction(Op_push_i));
1733 +                               expr->nexti->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
1734 +                               (void) mk_expression_list(subn,
1735 +                                               list_append(expr, instruction(Op_field_spec)));
1736 +                       }
1737 +
1738 +                       arg = arg->lasti->nexti;        /* third arg list */
1739 +                       ip = arg->lasti;
1740 +                       if (ip->opcode == Op_push_i) {
1741 +                               if (do_lint)
1742 +                                       lintwarn(_("%s: string literal as last arg of substitute has no effect"),
1743 +                                               operator);
1744 +                               r->sub_flags |= LITERAL;
1745 +                       } else {
1746 +                               if (make_assignable(ip) == NULL)
1747 +                                       yyerror(_("%s third parameter is not a changeable object"),
1748 +                                               operator);
1749 +                               else
1750 +                                       ip->do_reference = TRUE;
1751 +                       }
1752 +
1753 +                       r->expr_count = count_expressions(&subn, FALSE);
1754 +                       ip = subn->lasti;
1755 +
1756 +                       (void) list_append(subn, r);
1757 +
1758 +                       /* add after_assign code */
1759 +                       if (ip->opcode == Op_push_lhs && ip->memory->type == Node_var && ip->memory->var_assign) {
1760 +                               (void) list_append(subn, instruction(Op_var_assign));
1761 +                               subn->lasti->memory = ip->memory;
1762 +                               subn->lasti->assign_var = ip->memory->var_assign;
1763 +                               r->sub_flags |= AFTER_ASSIGN;
1764 +                       } else if (ip->opcode == Op_field_spec_lhs) {
1765 +                               (void) list_append(subn, instruction(Op_field_assign));
1766 +                               subn->lasti->field_assign = (Func_ptr) 0;
1767 +                               ip->target_assign = subn->lasti;
1768 +                               r->sub_flags |= AFTER_ASSIGN;
1769 +                       }
1770 +                       return subn;    
1771 +
1772 +               } else {
1773 +                       /* gensub */
1774 +
1775 +                       r->sub_flags |= GENSUB;
1776 +                       if (nexp == 3) {
1777 +                               ip = instruction(Op_push_i);
1778 +                               ip->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
1779 +                               (void) mk_expression_list(subn,
1780 +                                               list_append(list_create(ip), instruction(Op_field_spec)));
1781 +                       }
1782 +
1783 +                       r->expr_count = count_expressions(&subn, FALSE);
1784 +                       return list_append(subn, r);
1785 +               }
1786 +       }
1787 +
1788 +       r->builtin = tokentab[idx].ptr;
1789 +
1790         /* special case processing for a few builtins */
1791 +
1792         if (r->builtin == do_length) {
1793                 if (nexp == 0) {                
1794                     /* no args. Use $0 */
1795 @@ -3648,71 +3725,6 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
1796                         if (/*ip == arg->nexti  && */ ip->opcode == Op_push)
1797                                 ip->opcode = Op_push_array;
1798                 }
1799 -       } else if (r->builtin == do_sub || r->builtin == do_gsub) {
1800 -               int literal = FALSE;
1801 -               
1802 -               arg = subn->nexti;              /* first arg list */
1803 -               (void) mk_rexp(arg);
1804 -
1805 -               arg = arg->lasti->nexti;        /* 2nd arg list */
1806 -               if (nexp == 2) {
1807 -                       INSTRUCTION *expr;
1808 -                       expr = list_create(instruction(Op_push_i));
1809 -                       expr->nexti->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
1810 -                       (void) mk_expression_list(subn,
1811 -                                       list_append(expr, instruction(Op_field_spec)));
1812 -               }
1813 -
1814 -               arg = arg->lasti->nexti;        /* third arg list */
1815 -               ip = arg->lasti;
1816 -               if (ip->opcode == Op_push_i) {
1817 -                       if (do_lint)
1818 -                               lintwarn(_("%s: string literal as last arg of substitute has no effect"),
1819 -                                       (r->builtin == do_sub) ? "sub" : "gsub");
1820 -                       literal = TRUE;
1821 -               } else {
1822 -                       if (make_assignable(ip) == NULL)
1823 -                               yyerror(_("%s third parameter is not a changeable object"),
1824 -                                       (r->builtin == do_sub) ? "sub" : "gsub");
1825 -                       else
1826 -                               ip->do_reference = TRUE;
1827 -               }
1828 -
1829 -               /* kludge: This is one of the few cases
1830 -                * when we need to know the type of item on stack.
1831 -                * In case of string literal as the last argument,
1832 -                * pass 4 as # of args (See sub_common code in builtin.c).
1833 -                * Other cases like length(array or scalar) seem
1834 -                * to work out ok.
1835 -                */
1836 -               
1837 -               r->expr_count = count_expressions(&subn, FALSE) + !!literal;
1838 -               ip = subn->lasti;
1839 -
1840 -               (void) list_append(subn, r);
1841 -
1842 -               /* add after_assign bytecode(s) */
1843 -               if (ip->opcode == Op_push_lhs && ip->memory->type == Node_var && ip->memory->var_assign) {
1844 -                       (void) list_append(subn, instruction(Op_var_assign));
1845 -                       subn->lasti->memory = ip->memory;
1846 -                       subn->lasti->assign_var = ip->memory->var_assign;
1847 -               } else if (ip->opcode == Op_field_spec_lhs) {
1848 -                       (void) list_append(subn, instruction(Op_field_assign));
1849 -                       subn->lasti->field_assign = (Func_ptr) 0;
1850 -                       ip->target_assign = subn->lasti;
1851 -               }
1852 -               return subn;    
1853 -       } else if (r->builtin == do_gensub) {
1854 -               if (nexp == 3) {
1855 -                       arg = subn->nexti->lasti->nexti->lasti->nexti;  /* 3rd arg list */
1856 -                       ip = instruction(Op_push_i);
1857 -                       ip->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
1858 -                       (void) mk_expression_list(subn,
1859 -                                       list_append(list_create(ip),
1860 -                                               instruction(Op_field_spec)));
1861 -               }
1862 -               arg = subn->nexti;              /* first arg list */
1863 -               (void) mk_rexp(arg);
1864         } else if (r->builtin == do_split) {
1865                 arg = subn->nexti->lasti->nexti;        /* 2nd arg list */
1866                 ip = arg->lasti;
1867 diff --git a/builtin.c b/builtin.c
1868 index 724ea6d..d554930 100644
1869 --- a/builtin.c
1870 +++ b/builtin.c
1871 @@ -72,7 +72,6 @@ extern NODE **fields_arr;
1872  extern int output_is_tty;
1873  extern FILE *output_fp;
1874  
1875 -static NODE *sub_common(int nargs, long how_many, int backdigs);
1876  
1877  #define POP_TWO_SCALARS(s1, s2) \
1878  s2 = POP_SCALAR(); \
1879 @@ -2319,7 +2318,7 @@ do_match(int nargs)
1880         return make_number((AWKNUM) rstart);
1881  }
1882  
1883 -/* sub_common --- the common code (does the work) for sub, gsub, and gensub */
1884 +/* do_sub --- do the work for sub, gsub, and gensub */
1885  
1886  /*
1887   * Gsub can be tricksy; particularly when handling the case of null strings.
1888 @@ -2412,12 +2411,12 @@ do_match(int nargs)
1889   * NB: `howmany' conflicts with a SunOS 4.x macro in <sys/param.h>.
1890   */
1891  
1892 -static NODE *
1893 -sub_common(int nargs, long how_many, int backdigs)
1894 +NODE *
1895 +do_sub(int nargs, unsigned int flags, int *num_matches)
1896  {
1897         char *scan;
1898         char *bp, *cp;
1899 -       char *buf;
1900 +       char *buf = NULL;
1901         size_t buflen;
1902         char *matchend;
1903         size_t len;
1904 @@ -2434,38 +2433,77 @@ sub_common(int nargs, long how_many, int backdigs)
1905         NODE *s;                /* subst. pattern */
1906         NODE *t;                /* string to make sub. in; $0 if none given */
1907         NODE *tmp;
1908 -       NODE **lhs;
1909 -       int global = (how_many == -1);
1910 +       NODE **lhs = NULL;
1911 +       long how_many = 1;      /* one substitution for sub, also gensub default */
1912 +       int global;
1913         long current;
1914         int lastmatchnonzero;
1915         char *mb_indices = NULL;
1916 -
1917 -       tmp = PEEK(2);  /* take care of regexp early, in case re_update is fatal */
1918 -       rp = re_update(tmp);
1919         
1920 -       /* original string */
1921 -       if (nargs == 4) {       /* kludge: no of items on stack is really 3,
1922 -                         * See snode(..) in awkgram.y
1923 -                         */ 
1924 -               lhs = NULL;
1925 -               t = POP_STRING();
1926 +       if ((flags & GENSUB) != 0) {
1927 +               double d;
1928 +               NODE *t1;
1929 +
1930 +               tmp = PEEK(3);
1931 +               rp = re_update(tmp);
1932 +
1933 +               t = POP_STRING();       /* original string */
1934 +
1935 +               t1 = POP_SCALAR();      /* value of global flag */
1936 +               if ((t1->flags & (STRCUR|STRING)) != 0) {
1937 +                       if (t1->stlen > 0 && (t1->stptr[0] == 'g' || t1->stptr[0] == 'G'))
1938 +                               how_many = -1;
1939 +                       else {
1940 +                               d = force_number(t1);
1941 +
1942 +                               if ((t1->flags & NUMCUR) != 0)
1943 +                                       goto set_how_many;
1944 +
1945 +                               how_many = 1;
1946 +                       }
1947 +               } else {
1948 +                       d = force_number(t1);
1949 +set_how_many:
1950 +                       if (d < 1)
1951 +                               how_many = 1;
1952 +                       else if (d < LONG_MAX)
1953 +                               how_many = d;
1954 +                       else
1955 +                               how_many = LONG_MAX;
1956 +                       if (d == 0)
1957 +                               warning(_("gensub: third argument of 0 treated as 1"));
1958 +               }
1959 +               DEREF(t1);
1960 +
1961         } else {
1962 -               lhs = POP_ADDRESS();
1963 -               t = force_string(*lhs);
1964 +
1965 +               /* take care of regexp early, in case re_update is fatal */
1966 +
1967 +               tmp = PEEK(2);
1968 +               rp = re_update(tmp);
1969 +
1970 +               if ((flags & GSUB) != 0)
1971 +                       how_many = -1;
1972 +
1973 +               /* original string */
1974 +
1975 +               if ((flags & LITERAL) != 0)
1976 +                       t = POP_STRING();
1977 +               else {
1978 +                       lhs = POP_ADDRESS();
1979 +                       t = force_string(*lhs);
1980 +               }
1981         }
1982  
1983 +       global = (how_many == -1);
1984  
1985 -       s = POP_STRING();               /* replacement text */
1986 +       s = POP_STRING();       /* replacement text */
1987         decr_sp();              /* regexp, already updated above */
1988  
1989         /* do the search early to avoid work on non-match */
1990         if (research(rp, t->stptr, 0, t->stlen, RE_NEED_START) == -1 ||
1991 -           RESTART(rp, t->stptr) > t->stlen) {
1992 -               if (lhs == NULL)
1993 -                       DEREF(t);
1994 -               DEREF(s);
1995 -               return make_number((AWKNUM) 0.0);
1996 -       }
1997 +                       RESTART(rp, t->stptr) > t->stlen)
1998 +               goto done;
1999  
2000         t->flags |= STRING;
2001  
2002 @@ -2476,7 +2514,7 @@ sub_common(int nargs, long how_many, int backdigs)
2003         repl = s->stptr;
2004         replend = repl + s->stlen;
2005         repllen = replend - repl;
2006 -       emalloc(buf, char *, buflen + 2, "sub_common");
2007 +       emalloc(buf, char *, buflen + 2, "do_sub");
2008         buf[buflen] = '\0';
2009         buf[buflen + 1] = '\0';
2010         ampersands = 0;
2011 @@ -2490,7 +2528,7 @@ sub_common(int nargs, long how_many, int backdigs)
2012          * for example.
2013          */
2014         if (gawk_mb_cur_max > 1 && repllen > 0) {
2015 -               emalloc(mb_indices, char *, repllen * sizeof(char), "sub_common");
2016 +               emalloc(mb_indices, char *, repllen * sizeof(char), "do_sub");
2017                 index_multibyte_buffer(repl, mb_indices, repllen);
2018         }
2019  
2020 @@ -2500,7 +2538,7 @@ sub_common(int nargs, long how_many, int backdigs)
2021                         repllen--;
2022                         ampersands++;
2023                 } else if (*scan == '\\') {
2024 -                       if (backdigs) { /* gensub, behave sanely */
2025 +                       if (flags & GENSUB) {   /* gensub, behave sanely */
2026                                 if (isdigit((unsigned char) scan[1])) {
2027                                         ampersands++;
2028                                         scan++;
2029 @@ -2575,7 +2613,7 @@ sub_common(int nargs, long how_many, int backdigs)
2030                                         && (gawk_mb_cur_max == 1
2031                                                 || (repllen > 0 && mb_indices[scan - repl] == 1))
2032                                 ) {
2033 -                                       if (backdigs) { /* gensub, behave sanely */
2034 +                                       if (flags & GENSUB) {   /* gensub, behave sanely */
2035                                                 if (isdigit((unsigned char) scan[1])) {
2036                                                         int dig = scan[1] - '0';
2037                                                         if (dig < NUMSUBPATS(rp, t->stptr) && SUBPATSTART(rp, tp->stptr, dig) != -1) {
2038 @@ -2619,7 +2657,7 @@ sub_common(int nargs, long how_many, int backdigs)
2039                 textlen = text + textlen - matchend;
2040                 text = matchend;
2041  
2042 -               if ((current >= how_many && !global)
2043 +               if ((current >= how_many && ! global)
2044                     || ((long) textlen <= 0 && matchstart == matchend)
2045                     || research(rp, t->stptr, text - t->stptr, textlen, RE_NEED_START) == -1)
2046                         break;
2047 @@ -2628,7 +2666,7 @@ sub_common(int nargs, long how_many, int backdigs)
2048         sofar = bp - buf;
2049         if (buflen - sofar - textlen - 1) {
2050                 buflen = sofar + textlen + 2;
2051 -               erealloc(buf, char *, buflen, "sub_common");
2052 +               erealloc(buf, char *, buflen, "do_sub");
2053                 bp = buf + sofar;
2054         }
2055         for (scan = matchend; scan < text + textlen; scan++)
2056 @@ -2636,102 +2674,39 @@ sub_common(int nargs, long how_many, int backdigs)
2057         *bp = '\0';
2058         textlen = bp - buf;
2059  
2060 -       DEREF(s);
2061 -
2062 -       if (lhs != NULL) {
2063 -               if (matches > 0) {
2064 -                       unref(*lhs);
2065 -                       *lhs = make_str_node(buf, textlen, ALREADY_MALLOCED);   
2066 -               } else
2067 -                       efree(buf);
2068 -       } else {
2069 -               efree(buf);
2070 -               DEREF(t);
2071 -       }
2072 -
2073         if (mb_indices != NULL)
2074                 efree(mb_indices);
2075  
2076 -       return make_number((AWKNUM) matches);
2077 -}
2078 -
2079 -/* do_gsub --- global substitution */
2080 -
2081 -NODE *
2082 -do_gsub(int nargs)
2083 -{
2084 -       return sub_common(nargs, -1, FALSE);
2085 -}
2086 -
2087 -/* do_sub --- single substitution */
2088 -
2089 -NODE *
2090 -do_sub(int nargs)
2091 -{
2092 -       return sub_common(nargs, 1, FALSE);
2093 -}
2094 -
2095 -/* do_gensub --- fix up the tree for sub_common for the gensub function */
2096 -
2097 -NODE *
2098 -do_gensub(int nargs)
2099 -{
2100 -       NODE *t, *tmp, *target, *ret;
2101 -       long how_many = 1;      /* default is one substitution */
2102 -       double d;
2103 -
2104 -       tmp = POP_STRING();     /* target */
2105 -       t = POP_SCALAR();       /* value of global flag */
2106 -
2107 -       /*
2108 -        * We make copy of the original target string, and pass that
2109 -        * in to sub_common() as the target to make the substitution in.
2110 -        * We will then return the result string as the return value of
2111 -        * this function.
2112 -        */
2113 -
2114 -       target = make_string(tmp->stptr, tmp->stlen);
2115 -       DEREF(tmp);
2116 -       PUSH_ADDRESS(& target);
2117 -
2118 -       if ((t->flags & (STRCUR|STRING)) != 0) {
2119 -               if (t->stlen > 0 && (t->stptr[0] == 'g' || t->stptr[0] == 'G'))
2120 -                       how_many = -1;
2121 -               else {
2122 -                       d = force_number(t);
2123 +done:
2124 +       DEREF(s);
2125  
2126 -                       if ((t->flags & NUMCUR) != 0)
2127 -                               goto set_how_many;
2128 +       *num_matches = matches;
2129 +       if ((matches == 0 || (flags & LITERAL) != 0) && buf != NULL)
2130 +               efree(buf); 
2131  
2132 -                       how_many = 1;
2133 +       if (flags & GENSUB) {
2134 +               if (matches > 0) {
2135 +                       /* return the result string */
2136 +                       DEREF(t);
2137 +                       return make_str_node(buf, textlen, ALREADY_MALLOCED);   
2138                 }
2139 -       } else {
2140 -               d = force_number(t);
2141 -set_how_many:
2142 -               if (d < 1)
2143 -                       how_many = 1;
2144 -               else if (d < LONG_MAX)
2145 -                       how_many = d;
2146 -               else
2147 -                       how_many = LONG_MAX;
2148 -               if (d == 0)
2149 -                       warning(_("gensub: third argument of 0 treated as 1"));
2150 -       }
2151 -
2152 -       DEREF(t);
2153  
2154 -       ret = sub_common(3, how_many, TRUE);
2155 -       unref(ret);
2156 +               /* return the original string */
2157 +               return t;
2158 +       }
2159  
2160 -       /*
2161 -        * Note that we don't care what sub_common() returns, since the
2162 -        * easiest thing for the programmer is to return the string, even
2163 -        * if no substitutions were done.
2164 -        */
2165 +       /* For a string literal, must not change the original string. */
2166 +       if (flags & LITERAL)
2167 +               DEREF(t);
2168 +       else if (matches > 0) {
2169 +               unref(*lhs);
2170 +               *lhs = make_str_node(buf, textlen, ALREADY_MALLOCED);   
2171 +       }
2172  
2173 -       return target;
2174 +       return make_number((AWKNUM) matches);
2175  }
2176  
2177 +
2178  /* make_integer - Convert an integer to a number node.  */
2179  
2180  static NODE *
2181 diff --git a/debug.c b/debug.c
2182 index 9b9db34..404042c 100644
2183 --- a/debug.c
2184 +++ b/debug.c
2185 @@ -3740,7 +3740,16 @@ print_instruction(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump)
2186                 break;
2187  
2188         case Op_var_assign:
2189 -               print_func(fp, "[set_%s]\n", pc->memory->vname);
2190 +               if (pc->assign_var)
2191 +                       print_func(fp, "[set_%s()]", pc->memory->vname);
2192 +               print_func(fp, "\n");
2193 +               break;
2194 +
2195 +       case Op_field_assign:
2196 +               if (pc->field_assign)
2197 +                       print_func(fp, "[%s]", pc->field_assign == reset_record ?
2198 +                                       "reset_record()" : "invalidate_field0()");
2199 +               print_func(fp, "\n");
2200                 break;
2201  
2202         case Op_field_spec_lhs:
2203 @@ -3830,6 +3839,27 @@ print_instruction(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump)
2204                                 pc->line_range, pc->target_jmp);
2205                 break;
2206  
2207 +       case Op_sub_builtin:
2208 +       {
2209 +               const char *fname = "sub";
2210 +               static const struct flagtab values[] = {
2211 +                       { GSUB, "GSUB" },
2212 +                       { GENSUB, "GENSUB" },
2213 +                       { AFTER_ASSIGN, "AFTER_ASSIGN" },
2214 +                       { LITERAL, "LITERAL" },
2215 +                       { 0, NULL }
2216 +               };
2217 +
2218 +               if (pc->sub_flags & GSUB)
2219 +                       fname = "gsub";
2220 +               else if (pc->sub_flags & GENSUB)
2221 +                       fname = "gensub";
2222 +               print_func(fp, "%s [arg_count = %ld] [sub_flags = %s]\n",
2223 +                               fname, pc->expr_count,
2224 +                               genflags2str(pc->sub_flags, values));
2225 +       }
2226 +               break;
2227 +       
2228         case Op_builtin:
2229         {
2230                 const char *fname = getfname(pc->builtin);
2231 diff --git a/eval.c b/eval.c
2232 index 4132474..bdbd04b 100644
2233 --- a/eval.c
2234 +++ b/eval.c
2235 @@ -348,6 +348,7 @@ static struct optypetab {
2236         { "Op_K_getline", "getline" },
2237         { "Op_K_nextfile", "nextfile" },
2238         { "Op_builtin", NULL },
2239 +       { "Op_sub_builtin", NULL },
2240         { "Op_in_array", " in " },
2241         { "Op_func_call", NULL },
2242         { "Op_indirect_func_call", NULL },
2243 @@ -2114,11 +2115,13 @@ post:
2244                         break;
2245  
2246                 case Op_var_assign:
2247 -                       pc->assign_var();
2248 +                       if (pc->assign_var)
2249 +                               pc->assign_var();
2250                         break;
2251  
2252                 case Op_field_assign:
2253 -                       pc->field_assign();
2254 +                       if (pc->field_assign)
2255 +                               pc->field_assign();
2256                         break;
2257  
2258                 case Op_concat:
2259 @@ -2256,7 +2259,34 @@ arrayfor:
2260  #endif
2261                                 PUSH(r);
2262                         break;
2263 -                       
2264 +
2265 +               case Op_sub_builtin:
2266 +               {
2267 +                       /* sub, gsub and gensub */
2268
2269 +                       int matches = 0;
2270 +
2271 +                       r = do_sub(pc->expr_count, pc->sub_flags, & matches);
2272 +                       PUSH(r);
2273 +
2274 +                       if (matches == 0 && (pc->sub_flags & AFTER_ASSIGN) != 0) {
2275 +
2276 +                               /* For sub and gsub, must not execute after_assign code;
2277 +                                * If the target is a FIELD, this means no field re-splitting or
2278 +                                * $0 reconstruction. For a special variable as target,
2279 +                                * set_XX routine is not called. 
2280 +                                */
2281 +
2282 +                               ni = pc->nexti;
2283 +                               assert(ni->opcode == Op_field_assign || ni->opcode == Op_var_assign);
2284 +                               if (ni->opcode == Op_field_assign)
2285 +                                       ni->field_assign = (Func_ptr) 0;
2286 +                               else
2287 +                                       ni->assign_var = (Func_ptr) 0;
2288 +                       }
2289 +               }
2290 +                       break;
2291 +
2292                 case Op_K_print:
2293                         do_print(pc->expr_count, pc->redir_type);
2294                         break;
2295 diff --git a/profile.c b/profile.c
2296 index cba8be9..01d1e42 100644
2297 --- a/profile.c
2298 +++ b/profile.c
2299 @@ -507,6 +507,20 @@ cleanup:
2300                 case Op_after_endfile:
2301                         break;
2302  
2303 +               case Op_sub_builtin:
2304 +               {
2305 +                       const char *fname = "sub";
2306 +                       if (pc->sub_flags & GSUB)
2307 +                               fname = "gsub";
2308 +                       else if (pc->sub_flags & GENSUB)
2309 +                               fname = "gensub";
2310 +                       tmp = pp_list(pc->expr_count, "()", ", ");
2311 +                       str = pp_concat(fname, tmp, "");
2312 +                       efree(tmp);
2313 +                       pp_push(Op_sub_builtin, str, CAN_FREE);
2314 +               }
2315 +                       break;
2316 +
2317                 case Op_builtin:
2318                 {
2319                         static char *ext_func = "extension_function()";
This page took 0.310437 seconds and 2 git commands to generate.