[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gawk-diffs] [SCM] gawk branch, gawk-4.0-stable, updated. b8c993f5a867f3
From: |
Arnold Robbins |
Subject: |
[gawk-diffs] [SCM] gawk branch, gawk-4.0-stable, updated. b8c993f5a867f38fa9edd343d7d90b4b36800be2 |
Date: |
Wed, 10 Aug 2011 19:36:41 +0000 |
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".
The branch, gawk-4.0-stable has been updated
via b8c993f5a867f38fa9edd343d7d90b4b36800be2 (commit)
from 0d1a4f152fa45eda08b5877e4989c3250beb280e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=b8c993f5a867f38fa9edd343d7d90b4b36800be2
commit b8c993f5a867f38fa9edd343d7d90b4b36800be2
Author: Arnold D. Robbins <address@hidden>
Date: Wed Aug 10 22:36:00 2011 +0300
BEGINFILE/ENDFILE code redone.
diff --git a/ChangeLog b/ChangeLog
index 684bb9d..3ac6378 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2011-08-10 John Haque <address@hidden>
+
+ BEGINFILE/ENDFILE related code redone.
+
+ * awk.h (prev_frame_size, has_endfile, target_get_record,
+ target_newfile): New defines.
+ * awkgram.y (mk_program): Initialize has_endfile appropriately for
+ Op_get_record.
+ (parse_program): Initialize new jump targets for
+ Op_get_record and Op_newfile.
+ * eval.c (unwind_stack): Change argument to number of
+ items to be left in the stack. Adjust code.
+ (pop_fcall, pop_stack): New defines.
+ (setup_frame): Initialize prev_frame_size.
+ (exec_state, EXEC_STATE): New structure and typedef.
+ (exec_state_stack): New variable.
+ (push_exec_state, pop_exec_state): New functions to save and
+ later retrieve an execution state.
+ (r_interpret): Use the new functions and the defines in
+ cases Op_K_getline, Op_after_beginfile, Op_after_endfile,
+ Op_newfile and Op_K_exit.
+ * io.c (after_beginfile): When skipping a file using nextfile,
+ return zero in case there was an error opening the file.
+ (has_endfile): Nuke global variable.
+ (inrec): Add a second argument to pass errno to the calling
+ routine.
+ * debug.c (print_instruction): Update cases.
+
2011-08-10 Arnold D. Robbins <address@hidden>
Fix (apparently long-standing) problem with FIELDWIDTHS.
diff --git a/awk.h b/awk.h
index f3d3665..4b4210f 100644
--- a/awk.h
+++ b/awk.h
@@ -304,6 +304,7 @@ typedef struct exp_node {
struct {
union {
struct exp_node *lptr;
+ struct exp_instruction *li;
long ll;
} l;
union {
@@ -311,7 +312,7 @@ typedef struct exp_node {
Regexp *preg;
struct exp_node **av;
void (*uptr)(void);
- struct exp_instruction *iptr;
+ struct exp_instruction *ri;
} r;
union {
struct exp_node *extra;
@@ -391,7 +392,7 @@ typedef struct exp_node {
#define param vname
#define parmlist sub.nodep.x.param_list
-#define code_ptr sub.nodep.r.iptr
+#define code_ptr sub.nodep.r.ri
#define re_reg sub.nodep.r.preg
#define re_flags sub.nodep.reflags
@@ -412,12 +413,13 @@ typedef struct exp_node {
/* Node_frame: */
#define stack sub.nodep.r.av
#define func_node sub.nodep.x.extra
-#define reti sub.nodep.reflags
+#define prev_frame_size sub.nodep.reflags
+#define reti sub.nodep.l.li
/* Node_var: */
#define var_value lnode
#define var_update sub.nodep.r.uptr
-#define var_assign sub.nodep.x.aptr
+#define var_assign sub.nodep.x.aptr
/* Node_var_array: */
#define var_array sub.nodep.r.av
@@ -642,12 +644,21 @@ typedef struct exp_instruction {
#define target_end d.di
#define target_atexit x.xi
-/* Op_newfile, Op_K_getline */
+/* Op_newfile, Op_K_getline, Op_nextfile */
#define target_endfile x.xi
+/* Op_newfile */
+#define target_get_record x.xi
+
+/* Op_get_record, Op_K_nextfile */
+#define target_newfile d.di
+
/* Op_K_getline */
#define target_beginfile d.di
+/* Op_get_record */
+#define has_endfile x.xl
+
/* Op_token */
#define lextok d.name
@@ -687,7 +698,7 @@ typedef struct exp_instruction {
#define func_body x.xn
/* Op_func_call */
-#define inrule d.dl
+#define inrule d.dl
/* Op_subscript */
#define sub_count d.dl
@@ -1306,7 +1317,7 @@ extern char *find_source(const char *src, struct stat
*stb, int *errcode);
extern NODE *do_getline_redir(int intovar, int redirtype);
extern NODE *do_getline(int intovar, IOBUF *iop);
extern struct redirect *getredirect(const char *str, int len);
-extern int inrec(IOBUF *iop);
+extern int inrec(IOBUF *iop, int *errcode);
extern int nextfile(IOBUF **curfile, int skipping);
/* main.c */
extern int arg_assign(char *arg, int initing);
diff --git a/awkgram.c b/awkgram.c
index 6471150..a4d9f5d 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -2855,7 +2855,7 @@ regular_loop:
error_ln((yyvsp[(1) - (2)])->source_line,
_("`nextfile' used in %s action"),
ruletab[rule]);
- (yyvsp[(1) - (2)])->target_jmp = ip_newfile;
+ (yyvsp[(1) - (2)])->target_newfile = ip_newfile;
(yyvsp[(1) - (2)])->target_endfile = ip_endfile;
(yyval) = list_create((yyvsp[(1) - (2)]));
}
@@ -4821,8 +4821,7 @@ mk_program()
if (endfile_block == NULL)
endfile_block = list_create(ip_endfile);
else {
- extern int has_endfile; /* kludge for use in inrec (io.c) */
- has_endfile = TRUE;
+ ip_rec->has_endfile = TRUE;
(void) list_prepend(endfile_block, ip_endfile);
}
@@ -4914,10 +4913,12 @@ parse_program(INSTRUCTION **pcode)
else {
ip_endfile = instruction(Op_no_op);
ip_beginfile = instruction(Op_no_op);
- ip_newfile = instruction(Op_newfile); /* target for `nextfile'
*/
+ ip_rec = instruction(Op_get_record); /* target for `next', also
ip_newfile */
+ ip_newfile = bcalloc(Op_newfile, 2, 0); /* target for
`nextfile' */
ip_newfile->target_jmp = ip_end;
ip_newfile->target_endfile = ip_endfile;
- ip_rec = instruction(Op_get_record); /* target for `next' */
+ (ip_newfile + 1)->target_get_record = ip_rec;
+ ip_rec->target_newfile = ip_newfile;
ip_atexit = instruction(Op_atexit); /* target for `exit' in
END block */
}
diff --git a/awkgram.y b/awkgram.y
index fb917c2..6d3f1f7 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -840,7 +840,7 @@ non_compound_stmt
error_ln($1->source_line,
_("`nextfile' used in %s action"),
ruletab[rule]);
- $1->target_jmp = ip_newfile;
+ $1->target_newfile = ip_newfile;
$1->target_endfile = ip_endfile;
$$ = list_create($1);
}
@@ -2131,8 +2131,7 @@ mk_program()
if (endfile_block == NULL)
endfile_block = list_create(ip_endfile);
else {
- extern int has_endfile; /* kludge for use in inrec (io.c) */
- has_endfile = TRUE;
+ ip_rec->has_endfile = TRUE;
(void) list_prepend(endfile_block, ip_endfile);
}
@@ -2224,10 +2223,12 @@ parse_program(INSTRUCTION **pcode)
else {
ip_endfile = instruction(Op_no_op);
ip_beginfile = instruction(Op_no_op);
- ip_newfile = instruction(Op_newfile); /* target for `nextfile'
*/
+ ip_rec = instruction(Op_get_record); /* target for `next', also
ip_newfile */
+ ip_newfile = bcalloc(Op_newfile, 2, 0); /* target for
`nextfile' */
ip_newfile->target_jmp = ip_end;
ip_newfile->target_endfile = ip_endfile;
- ip_rec = instruction(Op_get_record); /* target for `next' */
+ (ip_newfile + 1)->target_get_record = ip_rec;
+ ip_rec->target_newfile = ip_newfile;
ip_atexit = instruction(Op_atexit); /* target for `exit' in
END block */
}
diff --git a/debug.c b/debug.c
index 4cda95c..29ce8b1 100644
--- a/debug.c
+++ b/debug.c
@@ -3796,9 +3796,19 @@ print_instruction(INSTRUCTION *pc, Func_print
print_func, FILE *fp, int in_dump)
break;
case Op_K_nextfile:
+ print_func(fp, "[target_newfile = %p] [target_endfile = %p]\n",
+ pc->target_newfile, pc->target_endfile);
+ break;
+
case Op_newfile:
print_func(fp, "[target_jmp = %p] [target_endfile = %p]\n",
pc->target_jmp, pc->target_endfile);
+ print_func(fp, "%*s[target_get_record = %p]\n",
+ noffset, "", (pc + 1)->target_get_record);
+ break;
+
+ case Op_get_record:
+ print_func(fp, "[target_newfile = %p]\n", pc->target_newfile);
break;
case Op_jmp:
@@ -5374,28 +5384,27 @@ pre_execute_code(INSTRUCTION **pi)
return (ei == *pi);
}
-extern void unwind_stack(STACK_ITEM *sp_bottom);
+extern INSTRUCTION *unwind_stack(long n);
static NODE *
execute_code(volatile INSTRUCTION *code)
{
volatile NODE *r = NULL;
volatile jmp_buf fatal_tag_stack;
- STACK_ITEM *ctxt_stack_bottom;
+ long save_stack_size;
/* We use one global stack for all contexts.
- * Remember stack bottom for current context; in case of
- * a fatal error, unwind stack until stack_ptr is below that 'bottom'.
+ * Save # of items in stack; in case of
+ * a fatal error, pop stack until it has that many items.
*/
- ctxt_stack_bottom = stack_ptr + 1;
+ save_stack_size = (stack_ptr - stack_bottom) + 1;
PUSH_BINDING(fatal_tag_stack, fatal_tag, fatal_tag_valid);
if (setjmp(fatal_tag) == 0) {
(void) r_interpret((INSTRUCTION *) code);
- assert(stack_ptr == ctxt_stack_bottom);
r = POP_SCALAR();
} else /* fatal error */
- unwind_stack(ctxt_stack_bottom);
+ (void) unwind_stack(save_stack_size);
POP_BINDING(fatal_tag_stack, fatal_tag, fatal_tag_valid);
diff --git a/doc/gawk.info b/doc/gawk.info
index e344c40..70fb686 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -8967,13 +8967,16 @@ implementations, or if `gawk' is in compatibility mode
(*note
Options::), `nextfile' is not special.
Upon execution of the `nextfile' statement, any `ENDFILE' rules are
-executed, `FILENAME' is updated to the name of the next data file
-listed on the command line, `FNR' is reset to one, `ARGIND' is
-incremented, any `BEGINFILE' rules are executed, and processing starts
-over with the first rule in the program. (`ARGIND' hasn't been
-introduced yet. *Note Built-in Variables::.) If the `nextfile'
-statement causes the end of the input to be reached, then the code in
-any `END' rules is executed. *Note BEGIN/END::.
+executed except in the case as mentioned below, `FILENAME' is updated
+to the name of the next data file listed on the command line, `FNR' is
+reset to one, `ARGIND' is incremented, any `BEGINFILE' rules are
+executed, and processing starts over with the first rule in the program.
+(`ARGIND' hasn't been introduced yet. *Note Built-in Variables::.) If
+the `nextfile' statement causes the end of the input to be reached,
+then the code in any `END' rules is executed. An exception to this is
+when the `nextfile' is invoked during execution of any statement in an
+`END' rule; In this case, it causes the program to stop immediately.
+*Note BEGIN/END::.
The `nextfile' statement is useful when there are many data files to
process but it isn't necessary to process every record in every file.
@@ -8983,7 +8986,8 @@ accomplishes this much more efficiently.
In addition, `nextfile' is useful inside a `BEGINFILE' rule to skip
over a file that would otherwise cause `gawk' to exit with a fatal
-error. *Note BEGINFILE/ENDFILE::.
+error. In this case, `ENDFILE' rules are not executed. *Note
+BEGINFILE/ENDFILE::.
While one might think that `close(FILENAME)' would accomplish the
same as `nextfile', this isn't true. `close()' is reserved for closing
@@ -26008,7 +26012,7 @@ Index
* functions, user-defined, counts: Profiling. (line 132)
* functions, user-defined, library of: Library Functions. (line 6)
* functions, user-defined, next/nextfile statements and <1>: Nextfile
Statement.
- (line 40)
+ (line 44)
* functions, user-defined, next/nextfile statements and: Next Statement.
(line 45)
* G-d: Acknowledgments. (line 81)
@@ -26522,7 +26526,7 @@ Index
* nextfile statement, BEGINFILE/ENDFILE patterns and: BEGINFILE/ENDFILE.
(line 26)
* nextfile statement, user-defined functions and: Nextfile Statement.
- (line 40)
+ (line 44)
* nexti debugger command: Dgawk Execution Control.
(line 49)
* NF variable <1>: Auto-set. (line 107)
@@ -27622,241 +27626,241 @@ Node: Break Statement374114
Node: Continue Statement376104
Node: Next Statement377891
Node: Nextfile Statement380281
-Node: Exit Statement382578
-Node: Built-in Variables384994
-Node: User-modified386089
-Ref: User-modified-Footnote-1394115
-Node: Auto-set394177
-Ref: Auto-set-Footnote-1403468
-Node: ARGC and ARGV403673
-Node: Arrays407524
-Node: Array Basics409029
-Node: Array Intro409740
-Node: Reference to Elements414058
-Node: Assigning Elements416328
-Node: Array Example416819
-Node: Scanning an Array418551
-Node: Delete421217
-Ref: Delete-Footnote-1423652
-Node: Numeric Array Subscripts423709
-Node: Uninitialized Subscripts425892
-Node: Multi-dimensional427520
-Node: Multi-scanning430614
-Node: Arrays of Arrays432198
-Node: Functions436775
-Node: Built-in437597
-Node: Calling Built-in438675
-Node: Numeric Functions440663
-Ref: Numeric Functions-Footnote-1444428
-Ref: Numeric Functions-Footnote-2444785
-Ref: Numeric Functions-Footnote-3444833
-Node: String Functions445102
-Ref: String Functions-Footnote-1468599
-Ref: String Functions-Footnote-2468728
-Ref: String Functions-Footnote-3468976
-Node: Gory Details469063
-Ref: table-sub-escapes470742
-Ref: table-sub-posix-92472096
-Ref: table-sub-proposed473439
-Ref: table-posix-sub474789
-Ref: table-gensub-escapes476335
-Ref: Gory Details-Footnote-1477542
-Ref: Gory Details-Footnote-2477593
-Node: I/O Functions477744
-Ref: I/O Functions-Footnote-1484399
-Node: Time Functions484546
-Ref: Time Functions-Footnote-1495438
-Ref: Time Functions-Footnote-2495506
-Ref: Time Functions-Footnote-3495664
-Ref: Time Functions-Footnote-4495775
-Ref: Time Functions-Footnote-5495887
-Ref: Time Functions-Footnote-6496114
-Node: Bitwise Functions496380
-Ref: table-bitwise-ops496938
-Ref: Bitwise Functions-Footnote-1501098
-Node: Type Functions501282
-Node: I18N Functions501752
-Node: User-defined503379
-Node: Definition Syntax504183
-Ref: Definition Syntax-Footnote-1509093
-Node: Function Example509162
-Node: Function Caveats511756
-Node: Calling A Function512177
-Node: Variable Scope513292
-Node: Pass By Value/Reference515267
-Node: Return Statement518707
-Node: Dynamic Typing521688
-Node: Indirect Calls522423
-Node: Internationalization532108
-Node: I18N and L10N533534
-Node: Explaining gettext534220
-Ref: Explaining gettext-Footnote-1539286
-Ref: Explaining gettext-Footnote-2539470
-Node: Programmer i18n539635
-Node: Translator i18n543835
-Node: String Extraction544628
-Ref: String Extraction-Footnote-1545589
-Node: Printf Ordering545675
-Ref: Printf Ordering-Footnote-1548459
-Node: I18N Portability548523
-Ref: I18N Portability-Footnote-1550972
-Node: I18N Example551035
-Ref: I18N Example-Footnote-1553670
-Node: Gawk I18N553742
-Node: Advanced Features554359
-Node: Nondecimal Data555872
-Node: Array Sorting557455
-Node: Controlling Array Traversal558155
-Node: Controlling Scanning With A Function558902
-Node: Controlling Scanning566605
-Ref: Controlling Scanning-Footnote-1570406
-Node: Array Sorting Functions570722
-Ref: Array Sorting Functions-Footnote-1574238
-Ref: Array Sorting Functions-Footnote-2574331
-Node: Two-way I/O574525
-Ref: Two-way I/O-Footnote-1579957
-Node: TCP/IP Networking580027
-Node: Profiling582871
-Node: Library Functions590345
-Ref: Library Functions-Footnote-1593352
-Node: Library Names593523
-Ref: Library Names-Footnote-1596994
-Ref: Library Names-Footnote-2597214
-Node: General Functions597300
-Node: Strtonum Function598253
-Node: Assert Function601183
-Node: Round Function604509
-Node: Cliff Random Function606052
-Node: Ordinal Functions607068
-Ref: Ordinal Functions-Footnote-1610138
-Ref: Ordinal Functions-Footnote-2610390
-Node: Join Function610599
-Ref: Join Function-Footnote-1612370
-Node: Gettimeofday Function612570
-Node: Data File Management616285
-Node: Filetrans Function616917
-Node: Rewind Function621056
-Node: File Checking622443
-Node: Empty Files623537
-Node: Ignoring Assigns625767
-Node: Getopt Function627320
-Ref: Getopt Function-Footnote-1638624
-Node: Passwd Functions638827
-Ref: Passwd Functions-Footnote-1647802
-Node: Group Functions647890
-Node: Walking Arrays655974
-Node: Sample Programs657543
-Node: Running Examples658208
-Node: Clones658936
-Node: Cut Program660160
-Node: Egrep Program670005
-Ref: Egrep Program-Footnote-1677778
-Node: Id Program677888
-Node: Split Program681504
-Ref: Split Program-Footnote-1685023
-Node: Tee Program685151
-Node: Uniq Program687954
-Node: Wc Program695383
-Ref: Wc Program-Footnote-1699649
-Ref: Wc Program-Footnote-2699849
-Node: Miscellaneous Programs699941
-Node: Dupword Program701129
-Node: Alarm Program703160
-Node: Translate Program707909
-Ref: Translate Program-Footnote-1712296
-Ref: Translate Program-Footnote-2712524
-Node: Labels Program712658
-Ref: Labels Program-Footnote-1716029
-Node: Word Sorting716113
-Node: History Sorting719997
-Node: Extract Program721836
-Ref: Extract Program-Footnote-1729319
-Node: Simple Sed729447
-Node: Igawk Program732509
-Ref: Igawk Program-Footnote-1747666
-Ref: Igawk Program-Footnote-2747867
-Node: Anagram Program748005
-Node: Signature Program751073
-Node: Debugger752173
-Node: Debugging753084
-Node: Debugging Concepts753497
-Node: Debugging Terms755353
-Node: Awk Debugging757976
-Node: Sample dgawk session758868
-Node: dgawk invocation759360
-Node: Finding The Bug760542
-Node: List of Debugger Commands767028
-Node: Breakpoint Control768339
-Node: Dgawk Execution Control771975
-Node: Viewing And Changing Data775326
-Node: Dgawk Stack778663
-Node: Dgawk Info780123
-Node: Miscellaneous Dgawk Commands784071
-Node: Readline Support789499
-Node: Dgawk Limitations790337
-Node: Language History792526
-Node: V7/SVR3.1794038
-Node: SVR4796359
-Node: POSIX797801
-Node: BTL798809
-Node: POSIX/GNU799543
-Node: Common Extensions804694
-Node: Ranges and Locales805801
-Ref: Ranges and Locales-Footnote-1810408
-Node: Contributors810629
-Node: Installation814891
-Node: Gawk Distribution815785
-Node: Getting816269
-Node: Extracting817095
-Node: Distribution contents818787
-Node: Unix Installation824009
-Node: Quick Installation824626
-Node: Additional Configuration Options826588
-Node: Configuration Philosophy828065
-Node: Non-Unix Installation830407
-Node: PC Installation830865
-Node: PC Binary Installation832164
-Node: PC Compiling834012
-Node: PC Testing836956
-Node: PC Using838132
-Node: Cygwin842317
-Node: MSYS843317
-Node: VMS Installation843831
-Node: VMS Compilation844434
-Ref: VMS Compilation-Footnote-1845441
-Node: VMS Installation Details845499
-Node: VMS Running847134
-Node: VMS Old Gawk848741
-Node: Bugs849215
-Node: Other Versions853068
-Node: Notes858349
-Node: Compatibility Mode859041
-Node: Additions859824
-Node: Accessing The Source860636
-Node: Adding Code862061
-Node: New Ports868028
-Node: Dynamic Extensions872141
-Node: Internals873517
-Node: Plugin License882620
-Node: Sample Library883254
-Node: Internal File Description883940
-Node: Internal File Ops887655
-Ref: Internal File Ops-Footnote-1892436
-Node: Using Internal File Ops892576
-Node: Future Extensions894953
-Node: Basic Concepts897457
-Node: Basic High Level898214
-Ref: Basic High Level-Footnote-1902249
-Node: Basic Data Typing902434
-Node: Floating Point Issues906959
-Node: String Conversion Precision908042
-Ref: String Conversion Precision-Footnote-1909742
-Node: Unexpected Results909851
-Node: POSIX Floating Point Problems911677
-Ref: POSIX Floating Point Problems-Footnote-1915382
-Node: Glossary915420
-Node: Copying940396
-Node: GNU Free Documentation License977953
-Node: Index1003090
+Node: Exit Statement382826
+Node: Built-in Variables385242
+Node: User-modified386337
+Ref: User-modified-Footnote-1394363
+Node: Auto-set394425
+Ref: Auto-set-Footnote-1403716
+Node: ARGC and ARGV403921
+Node: Arrays407772
+Node: Array Basics409277
+Node: Array Intro409988
+Node: Reference to Elements414306
+Node: Assigning Elements416576
+Node: Array Example417067
+Node: Scanning an Array418799
+Node: Delete421465
+Ref: Delete-Footnote-1423900
+Node: Numeric Array Subscripts423957
+Node: Uninitialized Subscripts426140
+Node: Multi-dimensional427768
+Node: Multi-scanning430862
+Node: Arrays of Arrays432446
+Node: Functions437023
+Node: Built-in437845
+Node: Calling Built-in438923
+Node: Numeric Functions440911
+Ref: Numeric Functions-Footnote-1444676
+Ref: Numeric Functions-Footnote-2445033
+Ref: Numeric Functions-Footnote-3445081
+Node: String Functions445350
+Ref: String Functions-Footnote-1468847
+Ref: String Functions-Footnote-2468976
+Ref: String Functions-Footnote-3469224
+Node: Gory Details469311
+Ref: table-sub-escapes470990
+Ref: table-sub-posix-92472344
+Ref: table-sub-proposed473687
+Ref: table-posix-sub475037
+Ref: table-gensub-escapes476583
+Ref: Gory Details-Footnote-1477790
+Ref: Gory Details-Footnote-2477841
+Node: I/O Functions477992
+Ref: I/O Functions-Footnote-1484647
+Node: Time Functions484794
+Ref: Time Functions-Footnote-1495686
+Ref: Time Functions-Footnote-2495754
+Ref: Time Functions-Footnote-3495912
+Ref: Time Functions-Footnote-4496023
+Ref: Time Functions-Footnote-5496135
+Ref: Time Functions-Footnote-6496362
+Node: Bitwise Functions496628
+Ref: table-bitwise-ops497186
+Ref: Bitwise Functions-Footnote-1501346
+Node: Type Functions501530
+Node: I18N Functions502000
+Node: User-defined503627
+Node: Definition Syntax504431
+Ref: Definition Syntax-Footnote-1509341
+Node: Function Example509410
+Node: Function Caveats512004
+Node: Calling A Function512425
+Node: Variable Scope513540
+Node: Pass By Value/Reference515515
+Node: Return Statement518955
+Node: Dynamic Typing521936
+Node: Indirect Calls522671
+Node: Internationalization532356
+Node: I18N and L10N533782
+Node: Explaining gettext534468
+Ref: Explaining gettext-Footnote-1539534
+Ref: Explaining gettext-Footnote-2539718
+Node: Programmer i18n539883
+Node: Translator i18n544083
+Node: String Extraction544876
+Ref: String Extraction-Footnote-1545837
+Node: Printf Ordering545923
+Ref: Printf Ordering-Footnote-1548707
+Node: I18N Portability548771
+Ref: I18N Portability-Footnote-1551220
+Node: I18N Example551283
+Ref: I18N Example-Footnote-1553918
+Node: Gawk I18N553990
+Node: Advanced Features554607
+Node: Nondecimal Data556120
+Node: Array Sorting557703
+Node: Controlling Array Traversal558403
+Node: Controlling Scanning With A Function559150
+Node: Controlling Scanning566853
+Ref: Controlling Scanning-Footnote-1570654
+Node: Array Sorting Functions570970
+Ref: Array Sorting Functions-Footnote-1574486
+Ref: Array Sorting Functions-Footnote-2574579
+Node: Two-way I/O574773
+Ref: Two-way I/O-Footnote-1580205
+Node: TCP/IP Networking580275
+Node: Profiling583119
+Node: Library Functions590593
+Ref: Library Functions-Footnote-1593600
+Node: Library Names593771
+Ref: Library Names-Footnote-1597242
+Ref: Library Names-Footnote-2597462
+Node: General Functions597548
+Node: Strtonum Function598501
+Node: Assert Function601431
+Node: Round Function604757
+Node: Cliff Random Function606300
+Node: Ordinal Functions607316
+Ref: Ordinal Functions-Footnote-1610386
+Ref: Ordinal Functions-Footnote-2610638
+Node: Join Function610847
+Ref: Join Function-Footnote-1612618
+Node: Gettimeofday Function612818
+Node: Data File Management616533
+Node: Filetrans Function617165
+Node: Rewind Function621304
+Node: File Checking622691
+Node: Empty Files623785
+Node: Ignoring Assigns626015
+Node: Getopt Function627568
+Ref: Getopt Function-Footnote-1638872
+Node: Passwd Functions639075
+Ref: Passwd Functions-Footnote-1648050
+Node: Group Functions648138
+Node: Walking Arrays656222
+Node: Sample Programs657791
+Node: Running Examples658456
+Node: Clones659184
+Node: Cut Program660408
+Node: Egrep Program670253
+Ref: Egrep Program-Footnote-1678026
+Node: Id Program678136
+Node: Split Program681752
+Ref: Split Program-Footnote-1685271
+Node: Tee Program685399
+Node: Uniq Program688202
+Node: Wc Program695631
+Ref: Wc Program-Footnote-1699897
+Ref: Wc Program-Footnote-2700097
+Node: Miscellaneous Programs700189
+Node: Dupword Program701377
+Node: Alarm Program703408
+Node: Translate Program708157
+Ref: Translate Program-Footnote-1712544
+Ref: Translate Program-Footnote-2712772
+Node: Labels Program712906
+Ref: Labels Program-Footnote-1716277
+Node: Word Sorting716361
+Node: History Sorting720245
+Node: Extract Program722084
+Ref: Extract Program-Footnote-1729567
+Node: Simple Sed729695
+Node: Igawk Program732757
+Ref: Igawk Program-Footnote-1747914
+Ref: Igawk Program-Footnote-2748115
+Node: Anagram Program748253
+Node: Signature Program751321
+Node: Debugger752421
+Node: Debugging753332
+Node: Debugging Concepts753745
+Node: Debugging Terms755601
+Node: Awk Debugging758224
+Node: Sample dgawk session759116
+Node: dgawk invocation759608
+Node: Finding The Bug760790
+Node: List of Debugger Commands767276
+Node: Breakpoint Control768587
+Node: Dgawk Execution Control772223
+Node: Viewing And Changing Data775574
+Node: Dgawk Stack778911
+Node: Dgawk Info780371
+Node: Miscellaneous Dgawk Commands784319
+Node: Readline Support789747
+Node: Dgawk Limitations790585
+Node: Language History792774
+Node: V7/SVR3.1794286
+Node: SVR4796607
+Node: POSIX798049
+Node: BTL799057
+Node: POSIX/GNU799791
+Node: Common Extensions804942
+Node: Ranges and Locales806049
+Ref: Ranges and Locales-Footnote-1810656
+Node: Contributors810877
+Node: Installation815139
+Node: Gawk Distribution816033
+Node: Getting816517
+Node: Extracting817343
+Node: Distribution contents819035
+Node: Unix Installation824257
+Node: Quick Installation824874
+Node: Additional Configuration Options826836
+Node: Configuration Philosophy828313
+Node: Non-Unix Installation830655
+Node: PC Installation831113
+Node: PC Binary Installation832412
+Node: PC Compiling834260
+Node: PC Testing837204
+Node: PC Using838380
+Node: Cygwin842565
+Node: MSYS843565
+Node: VMS Installation844079
+Node: VMS Compilation844682
+Ref: VMS Compilation-Footnote-1845689
+Node: VMS Installation Details845747
+Node: VMS Running847382
+Node: VMS Old Gawk848989
+Node: Bugs849463
+Node: Other Versions853316
+Node: Notes858597
+Node: Compatibility Mode859289
+Node: Additions860072
+Node: Accessing The Source860884
+Node: Adding Code862309
+Node: New Ports868276
+Node: Dynamic Extensions872389
+Node: Internals873765
+Node: Plugin License882868
+Node: Sample Library883502
+Node: Internal File Description884188
+Node: Internal File Ops887903
+Ref: Internal File Ops-Footnote-1892684
+Node: Using Internal File Ops892824
+Node: Future Extensions895201
+Node: Basic Concepts897705
+Node: Basic High Level898462
+Ref: Basic High Level-Footnote-1902497
+Node: Basic Data Typing902682
+Node: Floating Point Issues907207
+Node: String Conversion Precision908290
+Ref: String Conversion Precision-Footnote-1909990
+Node: Unexpected Results910099
+Node: POSIX Floating Point Problems911925
+Ref: POSIX Floating Point Problems-Footnote-1915630
+Node: Glossary915668
+Node: Copying940644
+Node: GNU Free Documentation License978201
+Node: Index1003338
End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index 87d8ff2..9dbd45c 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -12161,16 +12161,17 @@ or if @command{gawk} is in compatibility mode
@code{nextfile} is not special.
Upon execution of the @code{nextfile} statement,
-any @code{ENDFILE} rules are executed,
address@hidden is
+any @code{ENDFILE} rules are executed except in the case as
+mentioned below, @code{FILENAME} is
updated to the name of the next @value{DF} listed on the command line,
@code{FNR} is reset to one, @code{ARGIND} is incremented,
any @code{BEGINFILE} rules are executed, and processing
starts over with the first rule in the program.
(@code{ARGIND} hasn't been introduced yet. @xref{Built-in Variables}.)
If the @code{nextfile} statement causes the end of the input to be reached,
-then the code in any @code{END} rules is executed.
address@hidden/END}.
+then the code in any @code{END} rules is executed. An exception to this is
+when the @code{nextfile} is invoked during execution of any statement in an
address@hidden rule; In this case, it causes the program to stop immediately.
@xref{BEGIN/END}.
The @code{nextfile} statement is useful when there are many @value{DF}s
to process but it isn't necessary to process every record in every file.
@@ -12180,7 +12181,8 @@ statement accomplishes this much more efficiently.
In addition, @code{nextfile} is useful inside a @code{BEGINFILE}
rule to skip over a file that would otherwise cause @command{gawk}
-to exit with a fatal error. @xref{BEGINFILE/ENDFILE}.
+to exit with a fatal error. In this case, @code{ENDFILE} rules are not
+executed. @xref{BEGINFILE/ENDFILE}.
While one might think that @samp{close(FILENAME)} would accomplish
the same as @code{nextfile}, this isn't true. @code{close()} is
diff --git a/eval.c b/eval.c
index ea45efd..0a4a738 100644
--- a/eval.c
+++ b/eval.c
@@ -30,7 +30,7 @@ extern double pow(double x, double y);
extern double modf(double x, double *yp);
extern double fmod(double x, double y);
NODE **fcall_list;
-long fcall_count;
+long fcall_count = 0;
int currule = 0;
IOBUF *curfile = NULL; /* current data file */
int exiting = FALSE;
@@ -678,7 +678,7 @@ pop_frame()
#endif
}
#else /* not PROFILING or DEBUGGING */
-#define push_frame(p) /* nothing */
+#define push_frame(p) /* nothing */
#define pop_frame() /* nothing */
#endif
@@ -690,7 +690,6 @@ pop_frame()
void
dump_fcall_stack(FILE *fp)
{
-
NODE *f, *func;
long i = 0;
@@ -1150,12 +1149,6 @@ r_get_lhs(NODE *n, int reference)
case Node_var:
break;
-#if 0
- case Node_builtin:
- /* in gawk for a while */
- fatal(_("assignment is not allowed to result of builtin
function"));
-#endif
-
default:
cant_happen();
}
@@ -1242,7 +1235,7 @@ calc_exp(AWKNUM x1, AWKNUM x2)
/* setup_frame --- setup new frame for function call */
-static void
+static INSTRUCTION *
setup_frame(INSTRUCTION *pc)
{
NODE *r = NULL;
@@ -1329,18 +1322,23 @@ setup_frame(INSTRUCTION *pc)
DEREF(r);
}
+ frame_ptr->vname = source; /* save current source */
+
push_frame(frame_ptr);
/* save current frame in stack */
PUSH(frame_ptr);
+
/* setup new frame */
getnode(frame_ptr);
frame_ptr->type = Node_frame;
frame_ptr->stack = sp;
+ frame_ptr->prev_frame_size = (stack_ptr - stack_bottom); /* size of the
previous stack frame */
frame_ptr->func_node = f;
frame_ptr->vname = NULL;
+ frame_ptr->reti = pc; /* on return execute pc->nexti */
- frame_ptr->reti = (unsigned long) pc; /* on return execute pc->nexti */
+ return f->code_ptr;
}
@@ -1369,13 +1367,18 @@ restore_frame(NODE *fp)
}
if (frame_ptr->stack != NULL)
efree(frame_ptr->stack);
- ri = (INSTRUCTION *) frame_ptr->reti; /* execution in calling frame
- * resumes from ri->nexti.
- */
+ ri = frame_ptr->reti; /* execution in calling frame
+ * resumes from ri->nexti.
+ */
freenode(frame_ptr);
pop_frame();
+ /* restore frame */
frame_ptr = fp;
+ /* restore source */
+ source = fp->vname;
+ fp->vname = NULL;
+
return ri->nexti;
}
@@ -1395,33 +1398,40 @@ free_arrayfor(NODE *r)
freenode(r);
}
-/* unwind_stack --- pop the runtime stack */
-void
-unwind_stack(STACK_ITEM *sp_bottom)
+/* unwind_stack --- pop items off the run-time stack;
+ * 'n' is the # of items left in the stack.
+ */
+
+INSTRUCTION *
+unwind_stack(long n)
{
NODE *r;
+ INSTRUCTION *cp = NULL;
+ STACK_ITEM *sp;
- while (stack_ptr >= sp_bottom) {
- r = POP();
- switch (r->type) {
- case Node_instruction:
- freenode(r);
- break;
+ if (stack_empty())
+ return NULL;
+
+ sp = stack_bottom + n;
+
+ if (stack_ptr < sp)
+ return NULL;
+ while (r = POP()) {
+ switch (r->type) {
case Node_frame:
- (void) restore_frame(r);
- source = frame_ptr->vname;
+ cp = restore_frame(r);
break;
-
case Node_arrayfor:
free_arrayfor(r);
break;
-
case Node_val:
DEREF(r);
break;
-
+ case Node_instruction:
+ freenode(r);
+ break;
default:
if (in_main_context())
fatal(_("unwind_stack: unexpected type `%s'"),
@@ -1435,8 +1445,19 @@ unwind_stack(STACK_ITEM *sp_bottom)
*/
break;
}
+
+ if (stack_ptr < sp)
+ break;
}
-}
+ return cp;
+}
+
+
+/* pop_fcall --- pop off the innermost frame */
+#define pop_fcall() unwind_stack(frame_ptr->prev_frame_size)
+
+/* pop the run-time stack */
+#define pop_stack() (void) unwind_stack(0)
/*
@@ -1563,6 +1584,75 @@ POP_CODE()
}
+/* Implementation of BEGINFILE and ENDFILE requires saving an execution
+ * state and the ability to return to that state. The state is
+ * defined by the instruction triggering the BEGINFILE/ENDFILE rule, the
+ * run-time stack, the rule and the source file. The source line is available
in
+ * the instruction and hence is not considered a part of the execution state.
+ */
+
+
+typedef struct exec_state {
+ struct exec_state *next;
+
+ INSTRUCTION *cptr; /* either getline (Op_K_getline) or the
+ * implicit "open-file, read-record" loop
(Op_newfile).
+ */
+
+ int rule; /* rule for the INSTRUCTION */
+
+ long stack_size; /* For this particular usage, it is sufficient to
save
+ * only the size of the call stack. We do not
+ * store the actual stack pointer to avoid problems
+ * in case the stack gets realloc-ed.
+ */
+
+ const char *source; /* source file for the INSTRUCTION */
+} EXEC_STATE;
+
+static EXEC_STATE exec_state_stack;
+
+/* push_exec_state --- save an execution state on stack */
+
+static void
+push_exec_state(INSTRUCTION *cp, int rule, char *src, STACK_ITEM *sp)
+{
+ EXEC_STATE *es;
+
+ emalloc(es, EXEC_STATE *, sizeof(EXEC_STATE), "push_exec_state");
+ es->rule = rule;
+ es->cptr = cp;
+ es->stack_size = (sp - stack_bottom) + 1;
+ es->source = src;
+ es->next = exec_state_stack.next;
+ exec_state_stack.next = es;
+}
+
+
+/* pop_exec_state --- pop one execution state off the stack */
+
+static INSTRUCTION *
+pop_exec_state(int *rule, char **src, long *sz)
+{
+ INSTRUCTION *cp;
+ EXEC_STATE *es;
+
+ es = exec_state_stack.next;
+ if (es == NULL)
+ return NULL;
+ cp = es->cptr;
+ if (rule != NULL)
+ *rule = es->rule;
+ if (src != NULL)
+ *src = (char *) es->source;
+ if (sz != NULL)
+ *sz = es->stack_size;
+ exec_state_stack.next = es->next;
+ efree(es);
+ return cp;
+}
+
+
/*
* r_interpret:
* code is a list of instructions to run. returns the exit value
@@ -1598,6 +1688,7 @@ r_interpret(INSTRUCTION *code)
#endif
int stdio_problem = FALSE;
+
if (args_array == NULL)
emalloc(args_array, NODE **, (max_args + 2)*sizeof(NODE *),
"r_interpret");
else
@@ -2227,7 +2318,7 @@ post:
/*
* Actual array for use in lint warning
* in Op_arrayfor_incr
- */
+ */
list[num_elems] = array;
arrayfor:
@@ -2383,10 +2474,8 @@ match_re:
/* save current frame along with source */
func_call:
- frame_ptr->vname = source; /* save current
source */
- setup_frame(pc);
-
- ni = f->code_ptr; /* function code */
+ ni = setup_frame(pc);
+
if (ni->opcode == Op_ext_func) {
/* dynamically set source and line numbers for
an extension builtin. */
ni->source_file = source;
@@ -2401,29 +2490,11 @@ func_call:
case Op_K_return:
m = POP_SCALAR(); /* return value */
- r = POP();
- while (r->type != Node_frame) {
- switch (r->type) {
- case Node_arrayfor:
- free_arrayfor(r);
- break;
- case Node_val:
- DEREF(r);
- break;
- case Node_instruction:
- freenode(r);
- break;
- default:
- break;
- }
- r = POP();
- }
-
- ni = restore_frame(r);
- source = frame_ptr->vname;
-
+ ni = pop_fcall();
+
/* put the return value back on stack */
PUSH(m);
+
JUMPTO(ni);
case Op_K_getline_redir:
@@ -2439,13 +2510,20 @@ func_call:
if (currule == BEGINFILE || currule == ENDFILE)
fatal(_("non-redirected `getline' invalid
inside `%s' rule"),
ruletab[currule]);
+
do {
int ret;
- ret = nextfile(&curfile, FALSE);
+ ret = nextfile(& curfile, FALSE);
if (ret <= 0)
r = do_getline(pc->into_var, curfile);
else {
- PUSH_CODE(pc);
+
+ /* Save execution state so that we can
return to it
+ * from Op_after_beginfile or
Op_after_endfile.
+ */
+
+ push_exec_state(pc, currule, source,
stack_ptr);
+
if (curfile == NULL)
JUMPTO((pc +
1)->target_endfile);
else
@@ -2457,84 +2535,125 @@ func_call:
break;
case Op_after_endfile:
- ni = POP_CODE();
+ /* Find the execution state to return to */
+ ni = pop_exec_state(& currule, & source, NULL);
+
assert(ni->opcode == Op_newfile || ni->opcode ==
Op_K_getline);
JUMPTO(ni);
case Op_after_beginfile:
- after_beginfile(&curfile);
- ni = POP_CODE();
+ after_beginfile(& curfile);
+
+ /* Find the execution state to return to */
+ ni = pop_exec_state(& currule, & source, NULL);
+
+ assert(ni->opcode == Op_newfile || ni->opcode ==
Op_K_getline);
if (ni->opcode == Op_K_getline
|| curfile == NULL /* skipping
directory argument */
)
JUMPTO(ni);
- PUSH_CODE(ni); /* for use in Op_K_nextfile and
Op_get_record */
- break; /* Op_get_record */
+
+ break; /* read a record, Op_get_record */
case Op_newfile:
{
int ret;
- ret = nextfile(&curfile, FALSE);
- if (ret < 0)
- JUMPTO(pc->target_jmp); /* end block or
Op_atexit */
- else if (ret > 0) {
- PUSH_CODE(pc);
- if (curfile == NULL)
- JUMPTO(pc->target_endfile);
- break; /* beginfile block */
- } else
- PUSH_CODE(pc);
- /* fall through */
+
+ ret = nextfile(& curfile, FALSE);
+
+ if (ret < 0) /* end of input */
+ JUMPTO(pc->target_jmp); /* end block or
Op_atexit */
+
+ if (ret == 0) /* read a record */
+ JUMPTO((pc + 1)->target_get_record);
+
+ /* ret > 0 */
+ /* Save execution state for use in Op_after_beginfile
or Op_after_endfile. */
+
+ push_exec_state(pc, currule, source, stack_ptr);
+
+ if (curfile == NULL) /* EOF */
+ JUMPTO(pc->target_endfile);
+ /* else
+ execute beginfile block */
}
+ break;
- case Op_get_record:
- if (curfile == NULL) { /* from getline without
redirection */
- ni = POP_CODE(); /* Op_newfile */
- ni = ni->target_jmp; /* end_block or
Op_atexit */
- } else if (inrec(curfile) == 0)
- break; /* prog(rule) block
*/
- else
- ni = POP_CODE(); /* Op_newfile */
- JUMPTO(ni);
+ case Op_get_record:
+ {
+ int errcode = 0;
+
+ ni = pc->target_newfile;
+ if (curfile == NULL) {
+ /* from non-redirected getline, e.g.:
+ * {
+ * while (getline > 0) ;
+ * }
+ */
+
+ ni = ni->target_jmp; /* end_block or
Op_atexit */
+ JUMPTO(ni);
+ }
+
+ if (inrec(curfile, & errcode) != 0) {
+ if (errcode > 0 && (do_traditional || !
pc->has_endfile))
+ fatal(_("error reading input file `%s':
%s"),
+ curfile->name,
strerror(errcode));
+
+ JUMPTO(ni);
+ } /* else
+ prog (rule) block */
+ }
+ break;
case Op_K_nextfile:
+ {
+ int ret;
+
if (currule != Rule && currule != BEGINFILE)
- fatal(_("`nextfile' cannot be called from a
`%s' rule"), ruletab[currule]);
- (void) nextfile(&curfile, TRUE);
- while (currule == BEGINFILE) {
- r = POP();
- switch (r->type) {
- case Node_instruction:
- ni = r->code_ptr;
- freenode(r);
- if (ni->opcode == Op_newfile ||
ni->opcode == Op_K_getline)
- JUMPTO(ni);
- break;
- case Node_frame:
- (void) restore_frame(r);
- source = frame_ptr->vname;
- break;
- case Node_arrayfor:
- free_arrayfor(r);
- break;
- case Node_val:
- DEREF(r);
- break;
- default:
- break;
- }
- }
+ fatal(_("`nextfile' cannot be called from a
`%s' rule"),
+ ruletab[currule]);
- assert(currule != BEGINFILE);
- unwind_stack(stack_bottom + 1); /* don't pop Op_newfile
*/
- JUMPTO(pc->target_endfile); /* endfile
block */
+ ret = nextfile(& curfile, TRUE); /* skip current
file */
- case Op_K_exit:
- if (currule == END)
- ni = pc->target_atexit;
- else
- ni = pc->target_end;
+ if (currule == BEGINFILE) {
+ long stack_size;
+
+ ni = pop_exec_state(& currule, & source, &
stack_size);
+
+ assert(ni->opcode == Op_K_getline || ni->opcode
== Op_newfile);
+
+ /* pop stack returning to the state of
Op_K_getline or Op_newfile. */
+ unwind_stack(stack_size);
+
+ if (ret == 0) {
+ /* There was an error opening the file;
+ * don't run ENDFILE block(s).
+ */
+
+ JUMPTO(ni);
+ } else {
+ /* do run ENDFILE block(s) first. */
+
+ /* Execution state to return to in
Op_after_endfile. */
+ push_exec_state(ni, currule, source,
stack_ptr);
+
+ JUMPTO(pc->target_endfile);
+ }
+ } /* else
+ Start over with the first rule. */
+
+ /* empty the run-time stack to avoid memory leak */
+ pop_stack();
+
+ /* Push an execution state for Op_after_endfile to
return to */
+ push_exec_state(pc->target_newfile, currule, source,
stack_ptr);
+ JUMPTO(pc->target_endfile);
+ }
+ break;
+
+ case Op_K_exit:
exiting = TRUE;
POP_NUMBER(x1);
exit_val = (int) x1;
@@ -2546,19 +2665,36 @@ func_call:
/* else
just pass anything else on through */
#endif
- /* jump to either the first end_block instruction
- * or to Op_atexit
+
+ if (currule == BEGINFILE || currule == ENDFILE) {
+
+ /* Find the rule of the saved execution state
(Op_K_getline/Op_newfile).
+ * This is needed to prevent multiple execution
of any END rules:
+ * gawk 'BEGINFILE { exit(1) } \
+ * END { while (getline > 0); }' in1 in2
+ */
+
+ (void) pop_exec_state(& currule, & source,
NULL);
+ }
+
+ pop_stack(); /* empty stack, don't leak memory */
+
+ /* Jump to either the first END block instruction
+ * or to Op_atexit.
*/
- unwind_stack(stack_bottom);
+
+ if (currule == END)
+ ni = pc->target_atexit;
+ else
+ ni = pc->target_end;
JUMPTO(ni);
case Op_K_next:
if (currule != Rule)
fatal(_("`next' cannot be called from a `%s'
rule"), ruletab[currule]);
- /* jump to Op_get_record */
- unwind_stack(stack_bottom + 1); /* don't pop Op_newfile
*/
- JUMPTO(pc->target_jmp);
+ pop_stack();
+ JUMPTO(pc->target_jmp); /* Op_get_record, read next
record */
case Op_pop:
#if defined(GAWKDEBUG) || defined(ARRAYDEBUG)
diff --git a/io.c b/io.c
index c062610..1dcf217 100644
--- a/io.c
+++ b/io.c
@@ -214,7 +214,6 @@ static Regexp *RS_re_no_case;
static Regexp *RS_regexp;
int RS_is_null;
-int has_endfile = FALSE;
extern int output_is_tty;
extern NODE *ARGC_node;
@@ -262,10 +261,6 @@ after_beginfile(IOBUF **curfile)
iop = *curfile;
assert(iop != NULL);
-#if 0
- if (iop == NULL)
- return;
-#endif
if (iop->fd == INVALID_HANDLE) {
const char *fname;
@@ -309,10 +304,13 @@ nextfile(IOBUF **curfile, int skipping)
IOBUF *iop = *curfile;
if (skipping) { /* for 'nextfile' call */
- if (iop != NULL)
+ errcode = 0;
+ if (iop != NULL) {
+ errcode = iop->errcode;
(void) iop_close(iop);
+ }
*curfile = NULL;
- return 0; /* return value not used */
+ return (errcode == 0);
}
if (iop != NULL) {
@@ -409,28 +407,23 @@ set_NR()
/* inrec --- This reads in a record from the input file */
int
-inrec(IOBUF *iop)
+inrec(IOBUF *iop, int *errcode)
{
char *begin;
int cnt;
int retval = 0;
- int errcode = 0;
if (at_eof(iop) && no_data_left(iop))
cnt = EOF;
else if ((iop->flag & IOP_CLOSED) != 0)
cnt = EOF;
else
- cnt = get_a_record(&begin, iop, & errcode);
+ cnt = get_a_record(&begin, iop, errcode);
if (cnt == EOF) {
retval = 1;
- if (errcode > 0) {
- update_ERRNO_saved(errcode);
- if (do_traditional || ! has_endfile)
- fatal(_("error reading input file `%s': %s"),
- iop->name, strerror(errcode));
- }
+ if (*errcode > 0)
+ update_ERRNO_saved(*errcode);
} else {
NR += 1;
FNR += 1;
diff --git a/test/ChangeLog b/test/ChangeLog
index 87b9cf1..334f196 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,6 +1,7 @@
2011-08-10 Arnold D. Robbins <address@hidden>
- * Makefile.am (fwtest3): New test.
+ * Makefile.am (beginfile2, fwtest3): New tests.
+ * beginfile2.awk, beginfile2.in, beginfile2.ok: New files.
* fwtest3.awk, fwtest3.in, fwtest3.ok: New files.
2011-08-09 Arnold D. Robbins <address@hidden>
diff --git a/test/Makefile.am b/test/Makefile.am
index 43b2659..a778995 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -115,6 +115,9 @@ EXTRA_DIST = \
badargs.ok \
beginfile1.awk \
beginfile1.ok \
+ beginfile2.in \
+ beginfile2.ok \
+ beginfile2.sh \
binmode1.ok \
childin.awk \
childin.in \
@@ -806,9 +809,11 @@ UNIX_TESTS = \
GAWK_EXT_TESTS = \
aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \
- backw badargs beginfile1 binmode1 clos1way delsub devfd devfd1 \
+ backw badargs beginfile1 beginfile2 \
+ binmode1 clos1way delsub devfd devfd1 \
devfd2 dumpvars exit fieldwdth fpat1 fpat2 fpatnull fsfwfs funlen \
- fwtest fwtest2 fwtest3 gensub gensub2 getlndir gnuops2 gnuops3 gnureops
\
+ fwtest fwtest2 fwtest3 \
+ gensub gensub2 getlndir gnuops2 gnuops3 gnureops \
icasefs icasers igncdym igncfs ignrcas2 ignrcase indirectcall lint \
lintold lintwarn manyfiles match1 match2 match3 mbstr1 nastyparm \
next nondec nondec2 patsplit posix printfbad1 printfbad2 procinfs \
@@ -1358,6 +1363,11 @@ beginfile1::
@AWKPATH=$(srcdir) $(AWK) -f address@hidden $(srcdir)/address@hidden .
./no/such/file Makefile >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+beginfile2:
+ @echo $@
+ @-AWK="$(AWKPROG)" $(srcdir)/address@hidden $(srcdir)/address@hidden >
_$@ 2>&1
+ @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+
dumpvars::
@echo $@
@AWKPATH=$(srcdir) $(AWK) --dump-variables 1 < $(srcdir)/address@hidden
>/dev/null 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Makefile.in b/test/Makefile.in
index a31cd10..1f1f582 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -300,6 +300,9 @@ EXTRA_DIST = \
badargs.ok \
beginfile1.awk \
beginfile1.ok \
+ beginfile2.in \
+ beginfile2.ok \
+ beginfile2.sh \
binmode1.ok \
childin.awk \
childin.in \
@@ -456,6 +459,9 @@ EXTRA_DIST = \
fwtest2.awk \
fwtest2.in \
fwtest2.ok \
+ fwtest3.awk \
+ fwtest3.in \
+ fwtest3.ok \
gensub.awk \
gensub.in \
gensub.ok \
@@ -988,9 +994,11 @@ UNIX_TESTS = \
GAWK_EXT_TESTS = \
aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \
- backw badargs beginfile1 binmode1 clos1way delsub devfd devfd1 \
+ backw badargs beginfile1 beginfile2 \
+ binmode1 clos1way delsub devfd devfd1 \
devfd2 dumpvars exit fieldwdth fpat1 fpat2 fpatnull fsfwfs funlen \
- fwtest fwtest2 gensub gensub2 getlndir gnuops2 gnuops3 gnureops \
+ fwtest fwtest2 fwtest3 \
+ gensub gensub2 getlndir gnuops2 gnuops3 gnureops \
icasefs icasers igncdym igncfs ignrcas2 ignrcase indirectcall lint \
lintold lintwarn manyfiles match1 match2 match3 mbstr1 nastyparm \
next nondec nondec2 patsplit posix printfbad1 printfbad2 procinfs \
@@ -1706,6 +1714,11 @@ beginfile1::
@AWKPATH=$(srcdir) $(AWK) -f address@hidden $(srcdir)/address@hidden .
./no/such/file Makefile >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+beginfile2:
+ @echo $@
+ @-AWK="$(AWKPROG)" $(srcdir)/address@hidden $(srcdir)/address@hidden >
_$@ 2>&1
+ @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+
dumpvars::
@echo $@
@AWKPATH=$(srcdir) $(AWK) --dump-variables 1 < $(srcdir)/address@hidden
>/dev/null 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -2701,6 +2714,11 @@ fwtest2:
@AWKPATH=$(srcdir) $(AWK) -f address@hidden < $(srcdir)/address@hidden
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+fwtest3:
+ @echo fwtest3
+ @AWKPATH=$(srcdir) $(AWK) -f address@hidden < $(srcdir)/address@hidden
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+
gensub:
@echo gensub
@AWKPATH=$(srcdir) $(AWK) -f address@hidden < $(srcdir)/address@hidden
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index 0ea9673..cfbfc79 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -955,6 +955,11 @@ fwtest2:
@AWKPATH=$(srcdir) $(AWK) -f address@hidden < $(srcdir)/address@hidden
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+fwtest3:
+ @echo fwtest3
+ @AWKPATH=$(srcdir) $(AWK) -f address@hidden < $(srcdir)/address@hidden
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+
gensub:
@echo gensub
@AWKPATH=$(srcdir) $(AWK) -f address@hidden < $(srcdir)/address@hidden
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/beginfile2.in b/test/beginfile2.in
new file mode 100644
index 0000000..5b7cc83
--- /dev/null
+++ b/test/beginfile2.in
@@ -0,0 +1,242 @@
+#TEST1#
+BEGINFILE {
+ print "In BEGINFILE:", FILENAME
+}
+BEGIN {
+ count = 0
+ print "In BEGIN"
+ while (getline > 0)
+ count++;
+ print count == NR
+}
+
+#TEST2#
+BEGINFILE {
+ print "In BEGINFILE:", FILENAME
+ nextfile
+}
+ENDFILE{
+ print "In ENDFILE:", FILENAME
+}
+
+
+#TEST3#
+BEGINFILE {
+ print "In BEGINFILE:", FILENAME
+}
+END {
+ print "executing END rule"
+ ARGV[ARGC++] = "beginfile.sh";
+ count = 0
+ while (getline> 0)
+ count++;
+ print count == FNR
+ print "Done executing END rule"
+}
+ENDFILE {
+ print "In ENDFILE:", FILENAME
+}
+
+#TEST4#
+BEGINFILE {
+ print "In BEGINFILE:", FILENAME
+ nextfile
+}
+END {
+ print "executing END rule"
+ ARGV[ARGC++] = "beginfile.sh";
+ getline
+ print $0
+ print "Done executing END rule"
+}
+ENDFILE {
+ print "ENDFILE:", FILENAME
+}
+
+
+#TEST5#
+BEGIN {
+ getline
+ count++
+ print NR, count
+}
+{
+ count++
+}
+END {
+ print NR == count
+}
+
+#TEST6#
+BEGINFILE {
+ print "In BEGINFILE:", FILENAME
+ count = 0
+}
+BEGIN {
+ getline
+ count++
+ print FNR, count
+}
+{
+ count++
+}
+ENDFILE {
+ print "In ENDFILE:", FILENAME
+ print count == FNR
+}
+
+#TEST7#
+BEGINFILE {
+ print "In BEGINFILE:", FILENAME
+ count = 0
+ if (ARGIND == 1)
+ nextfile
+}
+BEGIN {
+ getline
+ print "In BEGIN:", FILENAME
+}
+{ count++ }
+ENDFILE {
+ print "In ENDFILE:", FILENAME
+ print (FNR - count)
+}
+
+#TEST8#
+function f(a, b) {
+ getline
+ print FILENAME
+ print a, b
+}
+function g(x, y) {
+ return x
+}
+BEGINFILE { nextfile }
+BEGIN { g(3, f(1, 2)) }
+
+#TEST9#
+function f(a, b) {
+ b = b ":" a;
+ if (skip || ERRNO != "") {
+ print "Skipping:", b
+ nextfile
+ }
+ return b
+}
+BEGINFILE { print "In BEGINFILE:", f(FILENAME, ++i)}
+FNR == 1 { print "In Rule:", FILENAME }
+ENDFILE { print "In ENDFILE:", FILENAME }
+
+#TEST10#
+function f() {
+ nextfile
+}
+function g( cnt) {
+ cnt = 0
+ while (getline > 0)
+ cnt++;
+ return cnt
+}
+BEGINFILE { if (ARGIND == 1) f(); }
+BEGIN {
+ print g(), NR
+}
+
+#TEST11#
+function f(a, b) {
+ print a
+ nextfile
+ print b
+}
+function g(x, y) {
+ print x
+ getline
+ return y
+}
+BEGINFILE { ARGIND == 1 ? g(3, f(FILENAME, 2)) : f(3, g(FILENAME, 2)) }
+
+#TEST12#
+BEGINFILE {
+ print "In BEGINFILE:", FILENAME
+}
+function g() {
+ nextfile
+}
+function f( cnt) {
+ print cnt + 0
+ while (getline > 0) {
+ if (++cnt == 2) {
+ g()
+ print "shouldn't see this line"
+ }
+ }
+}
+{
+ print FNR
+ f()
+}
+ENDFILE {
+ print "In ENDFILE:", FILENAME
+}
+
+#TEST13#
+# exit in BEGINFILE
+BEGINFILE {
+ print "In BEGINFILE:", FILENAME
+ exit(0)
+}
+ENDFILE {
+ print "In ENDFILE:", FILENAME
+}
+END {
+ print "In END:", FILENAME
+ while (getline > 0)
+ ;
+ print "shouldn't see this line"
+}
+
+#TEST14#
+# exit in ENDFILE
+BEGINFILE {
+ print "In BEGINFILE:", FILENAME
+}
+ENDFILE {
+ print "In ENDFILE:", FILENAME
+ exit(0)
+}
+END {
+ print "In END:", FILENAME
+ while (getline > 0)
+ ;
+ print "shouldn't see this line"
+}
+
+#TEST15#
+BEGINFILE {
+ print "BEGINFILE:", FILENAME
+}
+{ nextfile }
+END {
+ print NR
+}
+
+#TEST16#
+BEGINFILE {
+ print "In BEGINFILE:", FILENAME
+}
+BEGIN {
+ getline
+ print "In BEGIN:", FILENAME
+}
+{
+ if (NR == FNR) {
+ print "In Rule:", FILENAME
+ nextfile
+ }
+ exit(0)
+}
+
+ENDFILE {
+ print "In ENDFILE: ", FILENAME
+}
+
diff --git a/test/beginfile2.ok b/test/beginfile2.ok
new file mode 100644
index 0000000..c3029c7
--- /dev/null
+++ b/test/beginfile2.ok
@@ -0,0 +1,90 @@
+--Test 1a--
+In BEGIN
+In BEGINFILE: beginfile2.in
+1
+--Test 1b--
+In BEGIN
+In BEGINFILE: beginfile2.in
+In BEGINFILE: /file/does/not/exist
+gawk: cmd. line:3: fatal: cannot open file `/file/does/not/exist' for reading
(No such file or directory)
+--Test 2--
+In BEGINFILE: beginfile2.in
+In ENDFILE: beginfile2.in
+In BEGINFILE: /file/does/not/exist
+--Test 3--
+In BEGINFILE: beginfile2.in
+In ENDFILE: beginfile2.in
+executing END rule
+In BEGINFILE: beginfile.sh
+gawk: cmd. line:3: fatal: cannot open file `beginfile.sh' for reading (No such
file or directory)
+--Test 4--
+In BEGINFILE: beginfile2.in
+ENDFILE: beginfile2.in
+executing END rule
+In BEGINFILE: beginfile.sh
+
+Done executing END rule
+--Test 5--
+1 1
+1
+--Test 6--
+In BEGINFILE: beginfile2.in
+1 1
+In ENDFILE: beginfile2.in
+1
+--Test 7--
+In BEGINFILE: beginfile2.in
+In ENDFILE: beginfile2.in
+0
+In BEGINFILE: beginfile2.sh
+In BEGIN: beginfile2.sh
+In ENDFILE: beginfile2.sh
+1
+--Test 8--
+beginfile2.in
+1 2
+--Test 9a--
+Skipping: 1:/file/does/not/exist
+In BEGINFILE: 2:beginfile2.in
+In Rule: beginfile2.in
+In ENDFILE: beginfile2.in
+--Test 9b--
+Skipping: 1:/file/does/not/exist
+Skipping: 2:beginfile2.in
+In ENDFILE: beginfile2.in
+--Test 10--
+82 82
+--Test 11--
+beginfile2.in
+beginfile2.sh
+gawk: cmd. line:9: fatal: non-redirected `getline' invalid inside `BEGINFILE'
rule
+--Test 12--
+In BEGINFILE: beginfile2.in
+1
+0
+In ENDFILE: beginfile2.in
+In BEGINFILE: beginfile2.sh
+1
+0
+In ENDFILE: beginfile2.sh
+--Test 13--
+In BEGINFILE: beginfile2.in
+In END: beginfile2.in
+In ENDFILE: beginfile2.in
+In BEGINFILE: beginfile2.sh
+--Test 14--
+In BEGINFILE: beginfile2.in
+In ENDFILE: beginfile2.in
+In END: beginfile2.in
+In BEGINFILE: beginfile2.sh
+In ENDFILE: beginfile2.sh
+--Test 15--
+BEGINFILE: beginfile2.in
+BEGINFILE: beginfile2.sh
+2
+--Test 16--
+In BEGINFILE: beginfile2.in
+In BEGIN: beginfile2.in
+In Rule: beginfile2.in
+In ENDFILE: beginfile2.in
+In BEGINFILE: beginfile2.sh
diff --git a/test/beginfile2.sh b/test/beginfile2.sh
new file mode 100755
index 0000000..19deef6
--- /dev/null
+++ b/test/beginfile2.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+# beginfile2.sh --- test BEGINFILE/ENDFILE/getline/nextfile/exit combinations
+
+AWK="../gawk"
+AWKPROG="beginfile2.in"
+SCRIPT=`basename $0`
+
+if [ "$AWK" = "" ]
+then
+ echo $0: You must set AWK >&2
+ exit 1
+fi
+
+echo "--Test 1a--"
+prog=$($AWK '/#TEST1#/, /#TEST2#/' $AWKPROG)
+$AWK "$prog" $AWKPROG
+echo "--Test 1b--"
+$AWK "$prog" $AWKPROG /file/does/not/exist
+
+echo "--Test 2--"
+prog=$($AWK '/#TEST2#/, /#TEST3#/' $AWKPROG)
+$AWK "$prog" $AWKPROG /file/does/not/exist
+
+echo "--Test 3--"
+prog=$($AWK '/#TEST3#/, /#TEST4#/' $AWKPROG)
+$AWK "$prog" $AWKPROG
+
+echo "--Test 4--"
+prog=$($AWK '/#TEST4#/, /#TEST5#/' $AWKPROG)
+$AWK "$prog" $AWKPROG
+
+echo "--Test 5--"
+prog=$($AWK '/#TEST5#/, /#TEST6#/' $AWKPROG)
+$AWK "$prog" $AWKPROG
+
+echo "--Test 6--"
+prog=$($AWK '/#TEST6#/, /#TEST7#/' $AWKPROG)
+$AWK "$prog" $AWKPROG
+
+echo "--Test 7--"
+prog=$($AWK '/#TEST7#/, /#TEST8#/' $AWKPROG)
+$AWK "$prog" $AWKPROG $SCRIPT
+
+echo "--Test 8--"
+prog=$($AWK '/#TEST8#/, /#TEST9#/' $AWKPROG)
+$AWK "$prog" $AWKPROG
+
+echo "--Test 9a--"
+prog=$($AWK '/#TEST9#/, /#TEST10#/' $AWKPROG)
+$AWK "$prog" /file/does/not/exist $AWKPROG
+echo "--Test 9b--"
+$AWK -vskip=1 "$prog" /file/does/not/exist $AWKPROG
+
+echo "--Test 10--"
+prog=$($AWK '/#TEST10#/, /#TEST11#/' $AWKPROG)
+$AWK "$prog" $AWKPROG $SCRIPT
+
+echo "--Test 11--"
+prog=$($AWK '/#TEST11#/, /#TEST12#/' $AWKPROG)
+$AWK "$prog" $AWKPROG $SCRIPT
+
+echo "--Test 12--"
+prog=$($AWK '/#TEST12#/, /#TEST13#/' $AWKPROG)
+$AWK "$prog" $AWKPROG $SCRIPT
+
+echo "--Test 13--"
+prog=$($AWK '/#TEST13#/, /#TEST14#/' $AWKPROG)
+$AWK "$prog" $AWKPROG $SCRIPT
+
+echo "--Test 14--"
+prog=$($AWK '/#TEST14#/, /#TEST15#/' $AWKPROG)
+$AWK "$prog" $AWKPROG $SCRIPT
+
+echo "--Test 15--"
+prog=$($AWK '/#TEST15#/, /#TEST16#/' $AWKPROG)
+$AWK "$prog" $AWKPROG $SCRIPT
+
+echo "--Test 16--"
+prog=$($AWK '/#TEST16#/, /#TEST17#/' $AWKPROG)
+$AWK "$prog" $AWKPROG $SCRIPT
+
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 28 +++
awk.h | 25 ++-
awkgram.c | 11 +-
awkgram.y | 11 +-
debug.c | 23 ++-
doc/gawk.info | 496 ++++++++++++++++++++++++++--------------------------
doc/gawk.texi | 12 +-
eval.c | 378 +++++++++++++++++++++++++++-------------
io.c | 25 +--
test/ChangeLog | 3 +-
test/Makefile.am | 14 ++-
test/Makefile.in | 22 ++-
test/Maketests | 5 +
test/beginfile2.in | 242 +++++++++++++++++++++++++
test/beginfile2.ok | 90 ++++++++++
test/beginfile2.sh | 82 +++++++++
16 files changed, 1050 insertions(+), 417 deletions(-)
create mode 100644 test/beginfile2.in
create mode 100644 test/beginfile2.ok
create mode 100755 test/beginfile2.sh
hooks/post-receive
--
gawk
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gawk-diffs] [SCM] gawk branch, gawk-4.0-stable, updated. b8c993f5a867f38fa9edd343d7d90b4b36800be2,
Arnold Robbins <=