]> git.pld-linux.org Git - packages/gawk.git/blame - gawk-gsub_regenarate.patch
- fix from upstream for gsub rebuilding $0 when no substiution was done
[packages/gawk.git] / gawk-gsub_regenarate.patch
CommitLineData
efabfe5d
KK
1diff --git a/ChangeLog b/ChangeLog
2index 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.
27diff --git a/awk.h b/awk.h
28index 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);
67diff --git a/awkgram.c b/awkgram.c
68index 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;
1667diff --git a/awkgram.y b/awkgram.y
1668index 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;
1867diff --git a/builtin.c b/builtin.c
1868index 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 *
2181diff --git a/debug.c b/debug.c
2182index 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);
2231diff --git a/eval.c b/eval.c
2232index 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;
2295diff --git a/profile.c b/profile.c
2296index 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.398438 seconds and 4 git commands to generate.