aboutsummaryrefslogtreecommitdiffstats
path: root/awkgram.y
diff options
context:
space:
mode:
Diffstat (limited to 'awkgram.y')
-rw-r--r--awkgram.y117
1 files changed, 29 insertions, 88 deletions
diff --git a/awkgram.y b/awkgram.y
index 6721bcdc..a4d36976 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2014 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2015 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -57,7 +57,6 @@ static int include_source(INSTRUCTION *file);
static int load_library(INSTRUCTION *file);
static void next_sourcefile(void);
static char *tokexpand(void);
-static bool is_deferred_variable(const char *name);
#define instruction(t) bcalloc(t, 1, 0)
@@ -79,8 +78,6 @@ static int count_expressions(INSTRUCTION **list, bool isarg);
static INSTRUCTION *optimize_assignment(INSTRUCTION *exp);
static void add_lint(INSTRUCTION *list, LINTTYPE linttype);
-static void process_deferred();
-
enum defref { FUNC_DEFINE, FUNC_USE, FUNC_EXT };
static void func_use(const char *name, enum defref how);
static void check_funcs(void);
@@ -90,10 +87,10 @@ static int one_line_close(int fd);
static void split_comment(void);
static void check_comment(void);
+static bool at_seen = false;
static bool want_source = false;
static bool want_regexp = false; /* lexical scanning kludge */
static char *in_function; /* parsing kludge */
-static bool symtab_used = false; /* program used SYMTAB */
static int rule = 0;
const char *const ruletab[] = {
@@ -216,8 +213,6 @@ program
| program LEX_EOF
{
next_sourcefile();
- if (sourcefile == srcfiles)
- process_deferred();
}
| program error
{
@@ -234,6 +229,7 @@ rule
: pattern action
{
(void) append_rule($1, $2);
+ first_rule = false;
}
| pattern statement_term
{
@@ -255,11 +251,13 @@ rule
| '@' LEX_INCLUDE source statement_term
{
want_source = false;
+ at_seen = false;
yyerrok;
}
| '@' LEX_LOAD library statement_term
{
want_source = false;
+ at_seen = false;
yyerrok;
}
;
@@ -414,7 +412,10 @@ func_name
YYABORT;
}
| '@' LEX_EVAL
- { $$ = $2; }
+ {
+ $$ = $2;
+ at_seen = false;
+ }
;
lex_builtin
@@ -1695,12 +1696,24 @@ func_call
*/
$$ = list_prepend($2, t);
+ at_seen = false;
}
;
direct_func_call
: FUNC_CALL '(' opt_expression_list r_paren
{
+ NODE *n;
+
+ if (! at_seen) {
+ n = lookup($1->func_name);
+ if (n != NULL && n->type != Node_func
+ && n->type != Node_ext_func && n->type != Node_old_ext_func) {
+ error_ln($1->source_line,
+ _("attempt to use non-function `%s' in function call"),
+ $1->func_name);
+ }
+ }
param_sanity($3);
$1->opcode = Op_func_call;
$1->func_body = NULL;
@@ -2403,6 +2416,9 @@ parse_program(INSTRUCTION **pcode)
if (ret == 0) /* avoid spurious warning if parser aborted with YYABORT */
check_funcs();
+ if (do_posix && ! check_param_names())
+ errcount++;
+
if (args_array == NULL)
emalloc(args_array, NODE **, (max_args + 2) * sizeof(NODE *), "parse_program");
else
@@ -3233,10 +3249,8 @@ yylex(void)
pushback();
break;
case ']':
- if (tokstart[0] == '['
- && (tok == tokstart + 1
- || (tok == tokstart + 2
- && tokstart[1] == '^')))
+ if (tok[-1] == '['
+ || (tok[-2] == '[' && tok[-1] == '^'))
/* do nothing */;
else
in_brack--;
@@ -3334,6 +3348,7 @@ retry:
return lasttok = NEWLINE;
case '@':
+ at_seen = true;
return lasttok = '@';
case '\\':
@@ -4477,7 +4492,7 @@ install_function(char *fname, INSTRUCTION *fi, INSTRUCTION *plist)
int pcount = 0;
r = lookup(fname);
- if (r != NULL || is_deferred_variable(fname)) {
+ if (r != NULL) {
error_ln(fi->source_line, _("function name `%s' previously defined"), fname);
return -1;
}
@@ -4670,50 +4685,6 @@ param_sanity(INSTRUCTION *arglist)
}
}
-/* deferred variables --- those that are only defined if needed. */
-
-/*
- * Is there any reason to use a hash table for deferred variables? At the
- * moment, there are only 1 to 3 such variables, so it may not be worth
- * the overhead. If more modules start using this facility, it should
- * probably be converted into a hash table.
- */
-
-static struct deferred_variable {
- NODE *(*load_func)(void);
- struct deferred_variable *next;
- char name[1]; /* variable-length array */
-} *deferred_variables;
-
-/* register_deferred_variable --- add a var name and loading function to the list */
-
-void
-register_deferred_variable(const char *name, NODE *(*load_func)(void))
-{
- struct deferred_variable *dv;
- size_t sl = strlen(name);
-
- emalloc(dv, struct deferred_variable *, sizeof(*dv)+sl,
- "register_deferred_variable");
- dv->load_func = load_func;
- dv->next = deferred_variables;
- memcpy(dv->name, name, sl+1);
- deferred_variables = dv;
-}
-
-/* is_deferred_variable --- check if NAME is a deferred variable */
-
-static bool
-is_deferred_variable(const char *name)
-{
- struct deferred_variable *dv;
- for (dv = deferred_variables; dv != NULL; dv = dv->next)
- if (strcmp(name, dv->name) == 0)
- return true;
- return false;
-}
-
-
/* variable --- make sure NAME is in the symbol table */
NODE *
@@ -4725,44 +4696,14 @@ variable(int location, char *name, NODETYPE type)
if (r->type == Node_func || r->type == Node_ext_func )
error_ln(location, _("function `%s' called with space between name and `(',\nor used as a variable or an array"),
r->vname);
- if (r == symbol_table)
- symtab_used = true;
} else {
/* not found */
- struct deferred_variable *dv;
-
- for (dv = deferred_variables; true; dv = dv->next) {
- if (dv == NULL) {
- /*
- * This is the only case in which we may not free the string.
- */
- return install_symbol(name, type);
- }
- if (strcmp(name, dv->name) == 0) {
- r = (*dv->load_func)();
- break;
- }
- }
+ return install_symbol(name, type);
}
efree(name);
return r;
}
-/* process_deferred --- if the program uses SYMTAB, load deferred variables */
-
-static void
-process_deferred()
-{
- struct deferred_variable *dv;
-
- if (! symtab_used)
- return;
-
- for (dv = deferred_variables; dv != NULL; dv = dv->next) {
- (void) dv->load_func();
- }
-}
-
/* make_regnode --- make a regular expression node */
static NODE *