summaryrefslogtreecommitdiffstats
path: root/contrib/awk
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2001-11-02 21:26:14 +0000
committerobrien <obrien@FreeBSD.org>2001-11-02 21:26:14 +0000
commitf99bc3baaa551ba49e40c2deb3b237bf89c299f0 (patch)
treeacfee39db36ee1d9ac8479d265180dbbaa141034 /contrib/awk
parent931e47124f9dbe194217b9c63bb4a40d73229ab5 (diff)
downloadFreeBSD-src-f99bc3baaa551ba49e40c2deb3b237bf89c299f0.zip
FreeBSD-src-f99bc3baaa551ba49e40c2deb3b237bf89c299f0.tar.gz
Merge revs 1.9 (don't choke on long lines),
rev 1.3 (use srandom(time() ^ getpid())) into Gawk 3.1.0.
Diffstat (limited to 'contrib/awk')
-rw-r--r--contrib/awk/builtin.c818
1 files changed, 596 insertions, 222 deletions
diff --git a/contrib/awk/builtin.c b/contrib/awk/builtin.c
index fc9365b..240dca4 100644
--- a/contrib/awk/builtin.c
+++ b/contrib/awk/builtin.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2000 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2001 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -27,6 +27,9 @@
#include "awk.h"
+#if defined(HAVE_FCNTL_H)
+#include <fcntl.h>
+#endif
#undef HUGE
#undef CHARBITS
#undef INTBITS
@@ -35,17 +38,16 @@
#include "random.h"
/* can declare these, since we always use the random shipped with gawk */
-extern char *initstate P((unsigned seed, char *state, int n));
+extern char *initstate P((unsigned long seed, char *state, long n));
extern char *setstate P((char *state));
extern long random P((void));
-extern void srandom P((unsigned int seed));
+extern void srandom P((unsigned long seed));
#endif
extern NODE **fields_arr;
extern int output_is_tty;
static NODE *sub_common P((NODE *tree, int how_many, int backdigs));
-NODE *format_tree P((const char *, int, NODE *));
#ifdef _CRAY
/* Work around a problem in conversion of doubles to exact integers. */
@@ -85,20 +87,20 @@ static void efwrite P((const void *ptr, size_t size, size_t count, FILE *fp,
/* efwrite --- like fwrite, but with error checking */
static void
-efwrite(ptr, size, count, fp, from, rp, flush)
-const void *ptr;
-size_t size, count;
-FILE *fp;
-const char *from;
-struct redirect *rp;
-int flush;
+efwrite(const void *ptr,
+ size_t size,
+ size_t count,
+ FILE *fp,
+ const char *from,
+ struct redirect *rp,
+ int flush)
{
errno = 0;
if (fwrite(ptr, size, count, fp) != count)
goto wrerror;
if (flush
&& ((fp == stdout && output_is_tty)
- || (rp && (rp->flag & RED_NOBUF)))) {
+ || (rp != NULL && (rp->flag & RED_NOBUF)))) {
fflush(fp);
if (ferror(fp))
goto wrerror;
@@ -106,27 +108,28 @@ int flush;
return;
wrerror:
- fatal("%s to \"%s\" failed (%s)", from,
- rp ? rp->value : "standard output",
- errno ? strerror(errno) : "reason unknown");
+ fatal(_("%s to \"%s\" failed (%s)"), from,
+ rp ? rp->value : _("standard output"),
+ errno ? strerror(errno) : _("reason unknown"));
}
/* do_exp --- exponential function */
NODE *
-do_exp(tree)
-NODE *tree;
+do_exp(NODE *tree)
{
NODE *tmp;
double d, res;
tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("exp: received non-numeric argument"));
d = force_number(tmp);
free_temp(tmp);
errno = 0;
res = exp(d);
if (errno == ERANGE)
- warning("exp argument %g is out of range", d);
+ warning(_("exp: argument %g is out of range"), d);
return tmp_number((AWKNUM) res);
}
@@ -139,9 +142,7 @@ NODE *tree;
*/
static FILE *
-stdfile(name, len)
-char *name;
-size_t len;
+stdfile(char *name, size_t len)
{
if (len == 11) {
if (STREQN(name, "/dev/stderr", 11))
@@ -156,8 +157,7 @@ size_t len;
/* do_fflush --- flush output, either named file or pipe or everything */
NODE *
-do_fflush(tree)
-NODE *tree;
+do_fflush(NODE *tree)
{
struct redirect *rp;
NODE *tmp;
@@ -183,14 +183,15 @@ NODE *tree;
}
rp = getredirect(tmp->stptr, tmp->stlen);
- status = 1;
+ status = -1;
if (rp != NULL) {
if ((rp->flag & (RED_WRITE|RED_APPEND)) == 0) {
- /* if (do_lint) */
- warning(
- "fflush: cannot flush: %s `%s' opened for reading, not writing",
- (rp->flag & RED_PIPE) ? "pipe" : "file",
- file);
+ if (rp->flag & RED_PIPE)
+ warning(_("fflush: cannot flush: pipe `%s' opened for reading, not writing"),
+ file);
+ else
+ warning(_("fflush: cannot flush: file `%s' opened for reading, not writing"),
+ file);
free_temp(tmp);
return tmp_number((AWKNUM) status);
}
@@ -199,8 +200,10 @@ NODE *tree;
status = fflush(fp);
} else if ((fp = stdfile(tmp->stptr, tmp->stlen)) != NULL) {
status = fflush(fp);
- } else
- warning("fflush: `%s' is not an open file or pipe", file);
+ } else {
+ status = -1;
+ warning(_("fflush: `%s' is not an open file, pipe or co-process"), file);
+ }
free_temp(tmp);
return tmp_number((AWKNUM) status);
}
@@ -208,8 +211,7 @@ NODE *tree;
/* do_index --- find index of a string */
NODE *
-do_index(tree)
-NODE *tree;
+do_index(NODE *tree)
{
NODE *s1, *s2;
register char *p1, *p2;
@@ -219,6 +221,12 @@ NODE *tree;
s1 = tree_eval(tree->lnode);
s2 = tree_eval(tree->rnode->lnode);
+ if (do_lint) {
+ if ((s1->flags & (STRING|STR)) == 0)
+ lintwarn(_("index: received non-string first argument"));
+ if ((s2->flags & (STRING|STR)) == 0)
+ lintwarn(_("index: received non-string second argument"));
+ }
force_string(s1);
force_string(s2);
p1 = s1->stptr;
@@ -232,7 +240,7 @@ NODE *tree;
while (l1 > 0) {
if (l2 > l1)
break;
- if (casetable[(int)*p1] == casetable[(int)*p2]
+ if (casetable[(unsigned char)*p1] == casetable[(unsigned char)*p2]
&& (l2 == 1 || strncasecmp(p1, p2, l2) == 0)) {
ret = 1 + s1->stlen - l1;
break;
@@ -261,8 +269,7 @@ NODE *tree;
/* double_to_int --- convert double to int, used several places */
double
-double_to_int(d)
-double d;
+double_to_int(double d)
{
if (d >= 0)
d = Floor(d);
@@ -274,13 +281,14 @@ double d;
/* do_int --- convert double to int for awk */
NODE *
-do_int(tree)
-NODE *tree;
+do_int(NODE *tree)
{
NODE *tmp;
double d;
tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("int: received non-numeric argument"));
d = force_number(tmp);
d = double_to_int(d);
free_temp(tmp);
@@ -290,13 +298,14 @@ NODE *tree;
/* do_length --- length of a string or $0 */
NODE *
-do_length(tree)
-NODE *tree;
+do_length(NODE *tree)
{
NODE *tmp;
size_t len;
tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (STRING|STR)) == 0)
+ lintwarn(_("length: received non-string argument"));
len = force_string(tmp)->stlen;
free_temp(tmp);
return tmp_number((AWKNUM) len);
@@ -305,16 +314,17 @@ NODE *tree;
/* do_log --- the log function */
NODE *
-do_log(tree)
-NODE *tree;
+do_log(NODE *tree)
{
NODE *tmp;
double d, arg;
tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("log: received non-numeric argument"));
arg = (double) force_number(tmp);
if (arg < 0.0)
- warning("log called with negative argument %g", arg);
+ warning(_("log: received negative argument %g"), arg);
d = log(arg);
free_temp(tmp);
return tmp_number((AWKNUM) d);
@@ -331,10 +341,11 @@ NODE *tree;
*/
NODE *
-format_tree(fmt_string, n0, carg)
-const char *fmt_string;
-int n0;
-register NODE *carg;
+format_tree(
+ const char *fmt_string,
+ int n0,
+ register NODE *carg,
+ int num_args)
{
/* copy 'l' bytes from 's' to 'obufout' checking for space in the process */
/* difference of pointers should be of ptrdiff_t type, but let us be kind */
@@ -373,21 +384,16 @@ register NODE *carg;
osiz *= 2; \
}
-/*
- * Get the next arg to be formatted. If we've run out of args,
- * return "" (Null string)
- */
-#define parse_next_arg() { \
- if (carg == NULL) { \
- toofew = TRUE; \
- break; \
- } else { \
- arg = tree_eval(carg->lnode); \
- carg = carg->rnode; \
- } \
-}
+ static NODE **the_args = 0;
+ static size_t args_size = 0;
+ size_t cur_arg = 0;
+
+ auto NODE **save_args = 0;
+ auto size_t save_args_size = 0;
+ static int call_level = 0;
NODE *r;
+ int i;
int toofew = FALSE;
char *obuf, *obufout;
size_t osiz, ofre;
@@ -395,7 +401,8 @@ register NODE *carg;
const char *s0, *s1;
int cs1;
NODE *arg;
- long fw, prec;
+ long fw, prec, argnum;
+ int used_dollar;
int lj, alt, big, bigbig, small, have_prec, need_format;
long *cur = NULL;
#ifdef sun386 /* Can't cast unsigned (int/long) from ptr->value */
@@ -423,7 +430,79 @@ register NODE *carg;
osiz = INITIAL_OUT_SIZE;
ofre = osiz - 1;
+ /*
+ * Icky problem. If the args make a nested call to printf/sprintf,
+ * we end up clobbering the static variable `the_args'. Not good.
+ * We don't just malloc and free the_args each time, since most of the
+ * time there aren't nested calls. But if this is a nested call,
+ * save the memory pointed to by the_args and allocate a fresh
+ * array. Then free it on end.
+ */
+ if (++call_level > 1) { /* nested */
+ save_args = the_args;
+ save_args_size = args_size;
+
+ args_size = 0; /* force fresh allocation */
+ }
+
+ if (args_size == 0) {
+ /* allocate array */
+ emalloc(the_args, NODE **, (num_args+1) * sizeof(NODE *), "format_tree");
+ args_size = num_args + 1;
+ } else if (num_args + 1 > args_size) {
+ /* grow it */
+ erealloc(the_args, NODE **, (num_args+1) * sizeof(NODE *), "format_tree");
+ args_size = num_args + 1;
+ }
+
+
+ /* fill it in */
+ /*
+ * We ignore the_args[0] since format strings use
+ * 1-based numbers to indicate the arguments. It's
+ * easiest to just convert to int and index, without
+ * having to remember to subtract 1.
+ */
+ memset(the_args, '\0', num_args * sizeof(NODE *));
+ for (i = 1; carg != NULL; i++, carg = carg->rnode) {
+ NODE *tmp;
+
+ /* Here lies the wumpus's other brother. R.I.P. */
+ tmp = tree_eval(carg->lnode);
+ the_args[i] = dupnode(tmp);
+ free_temp(tmp);
+ }
+ assert(i == num_args);
+ cur_arg = 1;
+
+ /*
+ * Check first for use of `count$'.
+ * If plain argument retrieval was used earlier, choke.
+ * Otherwise, return the requested argument.
+ * If not `count$' now, but it was used earlier, choke.
+ * If this format is more than total number of args, choke.
+ * Otherwise, return the current argument.
+ */
+#define parse_next_arg() { \
+ if (argnum > 0) { \
+ if (cur_arg > 1) \
+ fatal(_("must use `count$' on all formats or none")); \
+ arg = the_args[argnum]; \
+ } else if (used_dollar) { \
+ fatal(_("must use `count$' on all formats or none")); \
+ arg = 0; /* shutup the compiler */ \
+ } else if (cur_arg >= num_args) { \
+ arg = 0; /* shutup the compiler */ \
+ toofew = TRUE; \
+ break; \
+ } else { \
+ arg = the_args[cur_arg]; \
+ cur_arg++; \
+ } \
+}
+
need_format = FALSE;
+ used_dollar = FALSE;
s0 = s1 = fmt_string;
while (n0-- > 0) {
@@ -437,6 +516,7 @@ register NODE *carg;
cur = &fw;
fw = 0;
prec = 0;
+ argnum = 0;
have_prec = FALSE;
signchar = FALSE;
zero_flag = FALSE;
@@ -502,12 +582,42 @@ check_pos:
if (n0 == 0) /* badly formatted control string */
continue;
goto retry;
+ case '$':
+ if (do_traditional)
+ fatal(_("`$' is not permitted in awk formats"));
+ if (cur == &fw) {
+ argnum = fw;
+ fw = 0;
+ used_dollar = TRUE;
+ if (argnum <= 0)
+ fatal(_("arg count with `$' must be > 0"));
+ if (argnum >= num_args)
+ fatal(_("arg count %d greater than total number of supplied arguments"), argnum);
+ } else
+ fatal(_("`$' not permitted after period in format"));
+ goto retry;
case '*':
if (cur == NULL)
break;
- parse_next_arg();
+ if (! do_traditional && ISDIGIT(*s1)) {
+ int val = 0;
+
+ for (; n0 > 0 && *s1 && ISDIGIT(*s1); s1++, n0--) {
+ val *= 10;
+ val += *s1 - '0';
+ }
+ if (*s1 != '$') {
+ fatal(_("no `$' supplied for positional field width or precision"));
+ } else {
+ s1++;
+ n0--;
+ }
+
+ arg = the_args[val];
+ } else {
+ parse_next_arg();
+ }
*cur = force_number(arg);
- free_temp(arg);
if (*cur < 0 && cur == &fw) {
*cur = -*cur;
lj++;
@@ -555,11 +665,11 @@ check_pos:
static int warned = FALSE;
if (do_lint && ! warned) {
- warning("`l' is meaningless in awk formats; ignored");
+ lintwarn(_("`l' is meaningless in awk formats; ignored"));
warned = TRUE;
}
if (do_posix)
- fatal("'l' is not permitted in POSIX awk formats");
+ fatal(_("`l' is not permitted in POSIX awk formats"));
}
big = TRUE;
goto retry;
@@ -570,11 +680,11 @@ check_pos:
static int warned = FALSE;
if (do_lint && ! warned) {
- warning("`L' is meaningless in awk formats; ignored");
+ lintwarn(_("`L' is meaningless in awk formats; ignored"));
warned = TRUE;
}
if (do_posix)
- fatal("'L' is not permitted in POSIX awk formats");
+ fatal(_("`L' is not permitted in POSIX awk formats"));
}
bigbig = TRUE;
goto retry;
@@ -585,11 +695,11 @@ check_pos:
static int warned = FALSE;
if (do_lint && ! warned) {
- warning("`h' is meaningless in awk formats; ignored");
+ lintwarn(_("`h' is meaningless in awk formats; ignored"));
warned = TRUE;
}
if (do_posix)
- fatal("'h' is not permitted in POSIX awk formats");
+ fatal(_("`h' is not permitted in POSIX awk formats"));
}
small = TRUE;
goto retry;
@@ -783,7 +893,6 @@ check_pos:
fw--;
}
s0 = s1;
- free_temp(arg);
break;
out_of_range:
@@ -800,7 +909,6 @@ check_pos:
parse_next_arg();
tmpval = force_number(arg);
format_float:
- free_temp(arg);
if (! have_prec)
prec = DEFAULT_G_PRECISION;
chksize(fw + prec + 9); /* 9 == slop */
@@ -840,35 +948,44 @@ check_pos:
}
if (toofew)
fatal("%s\n\t`%s'\n\t%*s%s",
- "not enough arguments to satisfy format string",
- fmt_string, s1 - fmt_string - 2, "",
- "^ ran out for this one"
- );
+ _("not enough arguments to satisfy format string"),
+ fmt_string, s1 - fmt_string - 2, "",
+ _("^ ran out for this one"));
}
if (do_lint) {
if (need_format)
- warning(
- "printf format specifier does not have control letter");
+ lintwarn(
+ _("[s]printf: format specifier does not have control letter"));
if (carg != NULL)
- warning(
- "too many arguments supplied for format string");
+ lintwarn(
+ _("too many arguments supplied for format string"));
}
bchunk(s0, s1 - s0);
r = make_str_node(obuf, obufout - obuf, ALREADY_MALLOCED);
r->flags |= TEMP;
+
+ for (i = 1; i < num_args; i++) {
+ unref(the_args[i]);
+ }
+
+ if (call_level-- > 1) {
+ free(the_args);
+ the_args = save_args;
+ args_size = save_args_size;
+ }
+
return r;
}
/* do_sprintf --- perform sprintf */
NODE *
-do_sprintf(tree)
-NODE *tree;
+do_sprintf(NODE *tree)
{
NODE *r;
NODE *sfmt = force_string(tree_eval(tree->lnode));
- r = format_tree(sfmt->stptr, sfmt->stlen, tree->rnode);
+ r = format_tree(sfmt->stptr, sfmt->stlen, tree->rnode, tree->printf_count);
free_temp(sfmt);
return r;
}
@@ -876,8 +993,7 @@ NODE *tree;
/* do_printf --- perform printf, including redirection */
void
-do_printf(tree)
-register NODE *tree;
+do_printf(NODE *tree)
{
struct redirect *rp = NULL;
register FILE *fp;
@@ -885,10 +1001,10 @@ register NODE *tree;
if (tree->lnode == NULL) {
if (do_traditional) {
if (do_lint)
- warning("printf: no arguments");
+ lintwarn(_("printf: no arguments"));
return; /* bwk accepts it silently */
}
- fatal("printf: no arguments");
+ fatal(_("printf: no arguments"));
}
if (tree->rnode != NULL) {
@@ -903,33 +1019,36 @@ register NODE *tree;
return;
} else
fp = stdout;
+ tree->lnode->printf_count = tree->printf_count;
tree = do_sprintf(tree->lnode);
efwrite(tree->stptr, sizeof(char), tree->stlen, fp, "printf", rp, TRUE);
+ if (rp != NULL && (rp->flag & RED_TWOWAY) != 0)
+ fflush(rp->fp);
free_temp(tree);
}
/* do_sqrt --- do the sqrt function */
NODE *
-do_sqrt(tree)
-NODE *tree;
+do_sqrt(NODE *tree)
{
NODE *tmp;
double arg;
tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("sqrt: received non-numeric argument"));
arg = (double) force_number(tmp);
free_temp(tmp);
if (arg < 0.0)
- warning("sqrt called with negative argument %g", arg);
+ warning(_("sqrt: called with negative argument %g"), arg);
return tmp_number((AWKNUM) sqrt(arg));
}
/* do_substr --- do the substr function */
NODE *
-do_substr(tree)
-NODE *tree;
+do_substr(NODE *tree)
{
NODE *t1, *t2, *t3;
NODE *r;
@@ -944,13 +1063,13 @@ NODE *tree;
if (d_index < 1.0) {
if (do_lint)
- warning("substr: start index %g invalid, using 1",
- d_index);
+ lintwarn(_("substr: start index %g is invalid, using 1"),
+ d_index);
d_index = 1;
}
if (do_lint && double_to_int(d_index) != d_index)
- warning("substr: non-integer start index %g will be truncated",
- d_index);
+ lintwarn(_("substr: non-integer start index %g will be truncated"),
+ d_index);
indx = d_index - 1; /* awk indices are from 1, C's are from 0 */
@@ -963,33 +1082,33 @@ NODE *tree;
free_temp(t3);
if (d_length <= 0.0) {
if (do_lint)
- warning("substr: length %g is <= 0", d_length);
+ lintwarn(_("substr: length %g is <= 0"), d_length);
free_temp(t1);
return Nnull_string;
}
if (do_lint && double_to_int(d_length) != d_length)
- warning(
- "substr: non-integer length %g will be truncated",
+ lintwarn(
+ _("substr: non-integer length %g will be truncated"),
d_length);
length = d_length;
}
if (t1->stlen == 0) {
if (do_lint)
- warning("substr: source string is zero length");
+ lintwarn(_("substr: source string is zero length"));
free_temp(t1);
return Nnull_string;
}
if ((indx + length) > t1->stlen) {
if (do_lint)
- warning(
- "substr: length %d at position %d exceeds length of first argument (%d)",
+ lintwarn(
+ _("substr: length %d at start index %d exceeds length of first argument (%d)"),
length, indx+1, t1->stlen);
length = t1->stlen - indx;
}
if (indx >= t1->stlen) {
if (do_lint)
- warning("substr: start index %d is past end of string",
+ lintwarn(_("substr: start index %d is past end of string"),
indx+1);
free_temp(t1);
return Nnull_string;
@@ -1002,8 +1121,7 @@ NODE *tree;
/* do_strftime --- format a time stamp */
NODE *
-do_strftime(tree)
-NODE *tree;
+do_strftime(NODE *tree)
{
NODE *t1, *t2, *ret;
struct tm *tm;
@@ -1011,6 +1129,7 @@ NODE *tree;
char *bufp;
size_t buflen, bufsize;
char buf[BUFSIZ];
+ /* FIXME: One day make %d be %e, after C 99 is common. */
static char def_format[] = "%a %b %d %H:%M:%S %Z %Y";
char *format;
int formatlen;
@@ -1023,12 +1142,15 @@ NODE *tree;
t1 = t2 = NULL;
if (tree != NULL) { /* have args */
if (tree->lnode != NULL) {
- t1 = force_string(tree_eval(tree->lnode));
+ NODE *tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (STRING|STR)) == 0)
+ lintwarn(_("strftime: recieved non-string first argument"));
+ t1 = force_string(tmp);
format = t1->stptr;
formatlen = t1->stlen;
if (formatlen == 0) {
if (do_lint)
- warning("strftime called with empty format string");
+ lintwarn(_("strftime: received empty format string"));
free_temp(t1);
return tmp_string("", 0);
}
@@ -1036,6 +1158,8 @@ NODE *tree;
if (tree->rnode != NULL) {
t2 = tree_eval(tree->rnode->lnode);
+ if (do_lint && (t2->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("strftime: recieved non-numeric second argument"));
fclock = (time_t) force_number(t2);
free_temp(t2);
}
@@ -1075,8 +1199,7 @@ NODE *tree;
/* do_systime --- get the time of day */
NODE *
-do_systime(tree)
-NODE *tree;
+do_systime(NODE *tree)
{
time_t lclock;
@@ -1084,13 +1207,57 @@ NODE *tree;
return tmp_number((AWKNUM) lclock);
}
+/* do_mktime --- turn a time string into a timestamp */
+
+NODE *
+do_mktime(NODE *tree)
+{
+ NODE *t1;
+ struct tm then;
+ long year;
+ int month, day, hour, minute, second, count;
+ int dst = -1; /* default is unknown */
+ time_t then_stamp;
+ char save;
+
+ t1 = tree_eval(tree->lnode);
+ if (do_lint && (t1->flags & (STRING|STR)) == 0)
+ lintwarn(_("mktime: received non-string argument"));
+ t1 = force_string(t1);
+
+ save = t1->stptr[t1->stlen];
+ t1->stptr[t1->stlen] = '\0';
+
+ count = sscanf(t1->stptr, "%ld %d %d %d %d %d %d",
+ & year, & month, & day,
+ & hour, & minute, & second,
+ & dst);
+ t1->stptr[t1->stlen] = save;
+ free_temp(t1);
+
+ if (count < 6
+ || month < month - 1
+ || year < year - 1900 || year - 1900 != (int) (year - 1900))
+ return tmp_number((AWKNUM) -1);
+
+ memset(& then, '\0', sizeof(then));
+ then.tm_sec = second;
+ then.tm_min = minute;
+ then.tm_hour = hour;
+ then.tm_mday = day;
+ then.tm_mon = month - 1;
+ then.tm_year = year - 1900;
+ then.tm_isdst = dst;
+
+ then_stamp = mktime(& then);
+ return tmp_number((AWKNUM) then_stamp);
+}
/* do_system --- run an external command */
NODE *
-do_system(tree)
-NODE *tree;
+do_system(NODE *tree)
{
NODE *tmp;
int ret = 0;
@@ -1099,6 +1266,8 @@ NODE *tree;
(void) flush_io(); /* so output is synchronous with gawk's */
tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (STRING|STR)) == 0)
+ lintwarn(_("system: recieved non-string argument"));
cmd = force_string(tmp)->stptr;
if (cmd && *cmd) {
@@ -1121,8 +1290,11 @@ NODE *tree;
save = cmd[tmp->stlen];
cmd[tmp->stlen] = '\0';
+ os_restore_mode(fileno(stdin));
ret = system(cmd);
ret = (ret >> 8) & 0xff;
+ if ((BINMODE & 1) != 0)
+ os_setbinmode(fileno(stdin), O_BINARY);
cmd[tmp->stlen] = save;
}
@@ -1135,8 +1307,7 @@ extern NODE **fmt_list; /* declared in eval.c */
/* do_print --- print items, separated by OFS, terminated with ORS */
void
-do_print(tree)
-register NODE *tree;
+do_print(register NODE *tree)
{
register NODE **t;
struct redirect *rp = NULL;
@@ -1200,25 +1371,29 @@ register NODE *tree;
if (ORSlen > 0)
efwrite(ORS, sizeof(char), (size_t) ORSlen, fp, "print", rp, TRUE);
+ if (rp != NULL && (rp->flag & RED_TWOWAY) != 0)
+ fflush(rp->fp);
+
free(t);
}
/* do_tolower --- lower case a string */
NODE *
-do_tolower(tree)
-NODE *tree;
+do_tolower(NODE *tree)
{
NODE *t1, *t2;
register unsigned char *cp, *cp2;
t1 = tree_eval(tree->lnode);
+ if (do_lint && (t1->flags & (STRING|STR)) == 0)
+ lintwarn(_("tolower: recieved non-string argument"));
t1 = force_string(t1);
t2 = tmp_string(t1->stptr, t1->stlen);
for (cp = (unsigned char *)t2->stptr,
cp2 = (unsigned char *)(t2->stptr + t2->stlen); cp < cp2; cp++)
if (ISUPPER(*cp))
- *cp = tolower(*cp);
+ *cp = TOLOWER(*cp);
free_temp(t1);
return t2;
}
@@ -1226,19 +1401,20 @@ NODE *tree;
/* do_toupper --- upper case a string */
NODE *
-do_toupper(tree)
-NODE *tree;
+do_toupper(NODE *tree)
{
NODE *t1, *t2;
register unsigned char *cp, *cp2;
t1 = tree_eval(tree->lnode);
+ if (do_lint && (t1->flags & (STRING|STR)) == 0)
+ lintwarn(_("toupper: recieved non-string argument"));
t1 = force_string(t1);
t2 = tmp_string(t1->stptr, t1->stlen);
for (cp = (unsigned char *)t2->stptr,
cp2 = (unsigned char *)(t2->stptr + t2->stlen); cp < cp2; cp++)
if (ISLOWER(*cp))
- *cp = toupper(*cp);
+ *cp = TOUPPER(*cp);
free_temp(t1);
return t2;
}
@@ -1246,14 +1422,19 @@ NODE *tree;
/* do_atan2 --- do the atan2 function */
NODE *
-do_atan2(tree)
-NODE *tree;
+do_atan2(NODE *tree)
{
NODE *t1, *t2;
double d1, d2;
t1 = tree_eval(tree->lnode);
t2 = tree_eval(tree->rnode->lnode);
+ if (do_lint) {
+ if ((t1->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("atan2: received non-numeric first argument"));
+ if ((t2->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("atan2: received non-numeric second argument"));
+ }
d1 = force_number(t1);
d2 = force_number(t2);
free_temp(t1);
@@ -1264,13 +1445,14 @@ NODE *tree;
/* do_sin --- do the sin function */
NODE *
-do_sin(tree)
-NODE *tree;
+do_sin(NODE *tree)
{
NODE *tmp;
double d;
tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("sin: received non-numeric argument"));
d = sin((double) force_number(tmp));
free_temp(tmp);
return tmp_number((AWKNUM) d);
@@ -1279,13 +1461,14 @@ NODE *tree;
/* do_cos --- do the cos function */
NODE *
-do_cos(tree)
-NODE *tree;
+do_cos(NODE *tree)
{
NODE *tmp;
double d;
tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("cos: received non-numeric argument"));
d = cos((double) force_number(tmp));
free_temp(tmp);
return tmp_number((AWKNUM) d);
@@ -1298,8 +1481,7 @@ static char state[512];
/* ARGSUSED */
NODE *
-do_rand(tree)
-NODE *tree;
+do_rand(NODE *tree)
{
if (firstrand) {
(void) initstate((unsigned) 1, state, sizeof state);
@@ -1312,8 +1494,7 @@ NODE *tree;
/* do_srand --- seed the random number generator */
NODE *
-do_srand(tree)
-NODE *tree;
+do_srand(NODE *tree)
{
NODE *tmp;
static long save_seed = 1;
@@ -1334,30 +1515,62 @@ NODE *tree;
#endif
else {
tmp = tree_eval(tree->lnode);
+ if (do_lint && (tmp->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("srand: received non-numeric argument"));
srandom((unsigned int) (save_seed = (long) force_number(tmp)));
free_temp(tmp);
}
return tmp_number((AWKNUM) ret);
}
-/* do_match --- match a regexp, set RSTART and RLENGTH */
+/* do_match --- match a regexp, set RSTART and RLENGTH,
+ * optional third arg is array filled with text of
+ * subpatterns enclosed in parens.
+ */
NODE *
-do_match(tree)
-NODE *tree;
+do_match(NODE *tree)
{
- NODE *t1;
- int rstart;
+ NODE *t1, *dest, *it;
+ int rstart, len, ii;
AWKNUM rlength;
Regexp *rp;
+ regoff_t s;
+ char *start;
t1 = force_string(tree_eval(tree->lnode));
- tree = tree->rnode->lnode;
- rp = re_update(tree);
+ tree = tree->rnode;
+ rp = re_update(tree->lnode);
+
+ dest = NULL;
+ if (tree->rnode != NULL) { /* 3rd optional arg for the subpatterns */
+ dest = tree->rnode->lnode;
+ if (dest->type == Node_param_list)
+ dest = stack_ptr[dest->param_cnt];
+ if (dest->type == Node_array_ref)
+ dest = dest->orig_array;
+ if (dest->type != Node_var && dest->type != Node_var_array)
+ fatal(_("match: third argument is not an array"));
+ dest->type = Node_var_array;
+ assoc_clear(dest);
+ }
+
rstart = research(rp, t1->stptr, 0, t1->stlen, TRUE);
if (rstart >= 0) { /* match succeded */
rstart++; /* 1-based indexing */
rlength = REEND(rp, t1->stptr) - RESTART(rp, t1->stptr);
+
+ /* Build the array only if the caller wants the optional subpatterns */
+ if (dest != NULL) {
+ for (ii = 0; (s = SUBPATSTART(rp, t1->stptr, ii)) != -1; ii++) {
+ start = t1->stptr + s;
+ len = SUBPATEND(rp, t1->stptr, ii) - s;
+
+ it = make_string(start, len);
+ it->flags |= MAYBE_NUM;
+ *assoc_lookup(dest, tmp_number((AWKNUM) (ii)), FALSE) = it;
+ }
+ }
} else { /* match failed */
rstart = 0;
rlength = -1.0;
@@ -1432,13 +1645,11 @@ NODE *tree;
*/
/*
- * NB: `howmany' conflicts with a SunOS macro in <sys/param.h>.
+ * NB: `howmany' conflicts with a SunOS 4.x macro in <sys/param.h>.
*/
static NODE *
-sub_common(tree, how_many, backdigs)
-NODE *tree;
-int how_many, backdigs;
+sub_common(NODE *tree, int how_many, int backdigs)
{
register char *scan;
register char *bp, *cp;
@@ -1487,18 +1698,13 @@ int how_many, backdigs;
if (tmp->type == Node_val)
lhs = NULL;
else
- lhs = get_lhs(tmp, &after_assign);
+ lhs = get_lhs(tmp, &after_assign, FALSE);
t->flags |= STRING;
/*
* create a private copy of the string
*/
if (t->stref > 1 || (t->flags & (PERM|FIELD)) != 0) {
- unsigned int saveflags;
-
- saveflags = t->flags;
- t->flags &= ~MALLOC;
- tmp = dupnode(t);
- t->flags = saveflags;
+ tmp = copynode(t);
t = tmp;
priv = TRUE;
}
@@ -1680,8 +1886,7 @@ int how_many, backdigs;
/* do_gsub --- global substitution */
NODE *
-do_gsub(tree)
-NODE *tree;
+do_gsub(NODE *tree)
{
return sub_common(tree, -1, FALSE);
}
@@ -1689,8 +1894,7 @@ NODE *tree;
/* do_sub --- single substitution */
NODE *
-do_sub(tree)
-NODE *tree;
+do_sub(NODE *tree)
{
return sub_common(tree, 1, FALSE);
}
@@ -1698,8 +1902,7 @@ NODE *tree;
/* do_gensub --- fix up the tree for sub_common for the gensub function */
NODE *
-do_gensub(tree)
-NODE *tree;
+do_gensub(NODE *tree)
{
NODE n1, n2, n3, *t, *tmp, *target, *ret;
long how_many = 1; /* default is one substitution */
@@ -1743,6 +1946,8 @@ NODE *tree;
how_many = d;
else
how_many = 1;
+ if (d == 0)
+ warning(_("gensub: 3rd argument of 0 treated as 1"));
}
free_temp(t);
@@ -1766,13 +1971,12 @@ NODE *tree;
* 'format' string HAS to be of "<flags>*.*g" kind, or we bomb!
*/
static void
-sgfmt(buf, format, alt, fwidth, prec, g)
-char *buf; /* return buffer; assumed big enough to hold result */
-const char *format;
-int alt; /* use alternate form flag */
-int fwidth; /* field width in a format */
-int prec; /* indicates desired significant digits, not decimal places */
-double g; /* value to format */
+sgfmt(char *buf, /* return buffer; assumed big enough to hold result */
+ const char *format,
+ int alt, /* use alternate form flag */
+ int fwidth, /* field width in a format */
+ int prec, /* indicates desired significant digits, not decimal places */
+ double g) /* value to format */
{
char dform[40];
register char *gpos;
@@ -1836,173 +2040,191 @@ double g; /* value to format */
}
#endif /* GFMT_WORKAROUND */
-#ifdef BITOPS
#define BITS_PER_BYTE 8 /* if not true, you lose. too bad. */
/* do_lshift --- perform a << operation */
NODE *
-do_lshift(tree)
-NODE *tree;
+do_lshift(NODE *tree)
{
NODE *s1, *s2;
- unsigned long uval, ushift, result;
+ unsigned long uval, ushift, res;
AWKNUM val, shift;
s1 = tree_eval(tree->lnode);
s2 = tree_eval(tree->rnode->lnode);
val = force_number(s1);
shift = force_number(s2);
- free_temp(s1);
- free_temp(s2);
if (do_lint) {
+ if ((s1->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("lshift: received non-numeric first argument"));
+ if ((s2->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("lshift: received non-numeric first argument"));
if (val < 0 || shift < 0)
- warning("lshift(%lf, %lf): negative values will give strange results", val, shift);
+ lintwarn(_("lshift(%lf, %lf): negative values will give strange results"), val, shift);
if (double_to_int(val) != val || double_to_int(shift) != shift)
- warning("lshift(%lf, %lf): fractional values will be truncated", val, shift);
+ lintwarn(_("lshift(%lf, %lf): fractional values will be truncated"), val, shift);
if (shift > (sizeof(unsigned long) * BITS_PER_BYTE))
- warning("lshift(%lf, %lf): too large shift value will give strange results", val, shift);
+ lintwarn(_("lshift(%lf, %lf): too large shift value will give strange results"), val, shift);
}
+ free_temp(s1);
+ free_temp(s2);
+
uval = (unsigned long) val;
ushift = (unsigned long) shift;
- result = uval << ushift;
- return tmp_number((AWKNUM) result);
+ res = uval << ushift;
+ return tmp_number((AWKNUM) res);
}
/* do_rshift --- perform a >> operation */
NODE *
-do_rshift(tree)
-NODE *tree;
+do_rshift(NODE *tree)
{
NODE *s1, *s2;
- unsigned long uval, ushift, result;
+ unsigned long uval, ushift, res;
AWKNUM val, shift;
s1 = tree_eval(tree->lnode);
s2 = tree_eval(tree->rnode->lnode);
val = force_number(s1);
shift = force_number(s2);
- free_temp(s1);
- free_temp(s2);
if (do_lint) {
+ if ((s1->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("rshift: received non-numeric first argument"));
+ if ((s2->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("rshift: received non-numeric first argument"));
if (val < 0 || shift < 0)
- warning("rshift(%lf, %lf): negative values will give strange results", val, shift);
+ lintwarn(_("rshift(%lf, %lf): negative values will give strange results"), val, shift);
if (double_to_int(val) != val || double_to_int(shift) != shift)
- warning("rshift(%lf, %lf): fractional values will be truncated", val, shift);
+ lintwarn(_("rshift(%lf, %lf): fractional values will be truncated"), val, shift);
if (shift > (sizeof(unsigned long) * BITS_PER_BYTE))
- warning("rshift(%lf, %lf): too large shift value will give strange results", val, shift);
+ lintwarn(_("rshift(%lf, %lf): too large shift value will give strange results"), val, shift);
}
+ free_temp(s1);
+ free_temp(s2);
+
uval = (unsigned long) val;
ushift = (unsigned long) shift;
- result = uval >> ushift;
- return tmp_number((AWKNUM) result);
+ res = uval >> ushift;
+ return tmp_number((AWKNUM) res);
}
/* do_and --- perform an & operation */
NODE *
-do_and(tree)
-NODE *tree;
+do_and(NODE *tree)
{
NODE *s1, *s2;
- unsigned long uleft, uright, result;
+ unsigned long uleft, uright, res;
AWKNUM left, right;
s1 = tree_eval(tree->lnode);
s2 = tree_eval(tree->rnode->lnode);
left = force_number(s1);
right = force_number(s2);
- free_temp(s1);
- free_temp(s2);
if (do_lint) {
+ if ((s1->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("and: received non-numeric first argument"));
+ if ((s2->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("and: received non-numeric first argument"));
if (left < 0 || right < 0)
- warning("and(%lf, %lf): negative values will give strange results", left, right);
+ lintwarn(_("and(%lf, %lf): negative values will give strange results"), left, right);
if (double_to_int(left) != left || double_to_int(right) != right)
- warning("and(%lf, %lf): fractional values will be truncated", left, right);
+ lintwarn(_("and(%lf, %lf): fractional values will be truncated"), left, right);
}
+ free_temp(s1);
+ free_temp(s2);
+
uleft = (unsigned long) left;
uright = (unsigned long) right;
- result = uleft & uright;
- return tmp_number((AWKNUM) result);
+ res = uleft & uright;
+ return tmp_number((AWKNUM) res);
}
/* do_or --- perform an | operation */
NODE *
-do_or(tree)
-NODE *tree;
+do_or(NODE *tree)
{
NODE *s1, *s2;
- unsigned long uleft, uright, result;
+ unsigned long uleft, uright, res;
AWKNUM left, right;
s1 = tree_eval(tree->lnode);
s2 = tree_eval(tree->rnode->lnode);
left = force_number(s1);
right = force_number(s2);
- free_temp(s1);
- free_temp(s2);
if (do_lint) {
+ if ((s1->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("or: received non-numeric first argument"));
+ if ((s2->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("or: received non-numeric first argument"));
if (left < 0 || right < 0)
- warning("or(%lf, %lf): negative values will give strange results", left, right);
+ lintwarn(_("or(%lf, %lf): negative values will give strange results"), left, right);
if (double_to_int(left) != left || double_to_int(right) != right)
- warning("or(%lf, %lf): fractional values will be truncated", left, right);
+ lintwarn(_("or(%lf, %lf): fractional values will be truncated"), left, right);
}
+ free_temp(s1);
+ free_temp(s2);
+
uleft = (unsigned long) left;
uright = (unsigned long) right;
- result = uleft | uright;
- return tmp_number((AWKNUM) result);
+ res = uleft | uright;
+ return tmp_number((AWKNUM) res);
}
/* do_xor --- perform an ^ operation */
NODE *
-do_xor(tree)
-NODE *tree;
+do_xor(NODE *tree)
{
NODE *s1, *s2;
- unsigned long uleft, uright, result;
+ unsigned long uleft, uright, res;
AWKNUM left, right;
s1 = tree_eval(tree->lnode);
s2 = tree_eval(tree->rnode->lnode);
left = force_number(s1);
right = force_number(s2);
- free_temp(s1);
- free_temp(s2);
if (do_lint) {
+ if ((s1->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("xor: received non-numeric first argument"));
+ if ((s2->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("xor: received non-numeric first argument"));
if (left < 0 || right < 0)
- warning("xor(%lf, %lf): negative values will give strange results", left, right);
+ lintwarn(_("xor(%lf, %lf): negative values will give strange results"), left, right);
if (double_to_int(left) != left || double_to_int(right) != right)
- warning("xor(%lf, %lf): fractional values will be truncated", left, right);
+ lintwarn(_("xor(%lf, %lf): fractional values will be truncated"), left, right);
}
+ free_temp(s1);
+ free_temp(s2);
+
uleft = (unsigned long) left;
uright = (unsigned long) right;
- result = uleft ^ uright;
- return tmp_number((AWKNUM) result);
+ res = uleft ^ uright;
+ return tmp_number((AWKNUM) res);
}
/* do_compl --- perform a ~ operation */
NODE *
-do_compl(tree)
-NODE *tree;
+do_compl(NODE *tree)
{
NODE *tmp;
double d;
@@ -2013,10 +2235,12 @@ NODE *tree;
free_temp(tmp);
if (do_lint) {
+ if ((tmp->flags & (NUM|NUMBER)) == 0)
+ lintwarn(_("compl: received non-numeric argument"));
if (d < 0)
- warning("compl(%lf): negative value will give strange results", d);
+ lintwarn(_("compl(%lf): negative value will give strange results"), d);
if (double_to_int(d) != d)
- warning("compl(%lf): fractional value will be truncated", d);
+ lintwarn(_("compl(%lf): fractional value will be truncated"), d);
}
uval = (unsigned long) d;
@@ -2027,11 +2251,10 @@ NODE *tree;
/* do_strtonum --- the strtonum function */
NODE *
-do_strtonum(tree)
-NODE *tree;
+do_strtonum(NODE *tree)
{
NODE *tmp;
- double d, arg;
+ double d;
tmp = tree_eval(tree->lnode);
@@ -2045,9 +2268,7 @@ NODE *tree;
free_temp(tmp);
return tmp_number((AWKNUM) d);
}
-#endif /* BITOPS */
-#if defined(BITOPS) || defined(NONDECDATA)
/* nondec2awknum --- convert octal or hex value to double */
/*
@@ -2057,13 +2278,12 @@ NODE *tree;
*/
AWKNUM
-nondec2awknum(str, len)
-char *str;
-size_t len;
+nondec2awknum(char *str, size_t len)
{
AWKNUM retval = 0.0;
char save;
short val;
+ char *start = str;
if (*str == '0' && (str[1] == 'x' || str[1] == 'X')) {
assert(len > 2);
@@ -2107,18 +2327,172 @@ size_t len;
if (strchr(str, '8') != NULL || strchr(str, '9') != NULL)
goto decimal;
for (; len > 0; len--) {
- if (! isdigit(*str))
+ if (! ISDIGIT(*str))
goto done;
+ else if (*str == '8' || *str == '9') {
+ str = start;
+ goto decimal;
+ }
retval = (retval * 8) + (*str - '0');
str++;
}
} else {
decimal:
save = str[len];
- retval = atof(str);
+ retval = strtod(str, NULL);
str[len] = save;
}
done:
return retval;
}
-#endif /* defined(BITOPS) || defined(NONDECDATA) */
+
+/* do_dcgettext --- handle i18n translations */
+
+/*
+ * awk usage is
+ *
+ * str = dcgettext(string [, domain [, category]])
+ *
+ * Default domain is TEXTDOMAIN, default category is LC_MESSAGES.
+ */
+
+NODE *
+do_dcgettext(NODE *tree)
+{
+ NODE *tmp, *t1, *t2;
+ char *string;
+ char *the_result;
+#if ENABLE_NLS && HAVE_LC_MESSAGES && HAVE_DCGETTEXT
+ int lc_cat = -1;
+ char *category, *domain;
+ static struct category_table {
+ int val;
+ char *name;
+ } cat_tab[] = {
+#ifdef LC_ALL
+ { LC_ALL, "LC_ALL" },
+#endif /* LC_ALL */
+#ifdef LC_COLLATE
+ { LC_COLLATE, "LC_COLLATE" },
+#endif /* LC_COLLATE */
+#ifdef LC_CTYPE
+ { LC_CTYPE, "LC_CTYPE" },
+#endif /* LC_CTYPE */
+#ifdef LC_MESSAGES
+ { LC_MESSAGES, "LC_MESSAGES" },
+#endif /* LC_MESSAGES */
+#ifdef LC_MONETARY
+ { LC_MONETARY, "LC_MONETARY" },
+#endif /* LC_MONETARY */
+#ifdef LC_NUMERIC
+ { LC_NUMERIC, "LC_NUMERIC" },
+#endif /* LC_NUMERIC */
+#ifdef LC_RESPONSE
+ { LC_RESPONSE, "LC_RESPONSE" },
+#endif /* LC_RESPONSE */
+#ifdef LC_TIME
+ { LC_TIME, "LC_TIME" },
+#endif /* LC_TIME */
+ };
+#endif /* ENABLE_NLS */
+
+ tmp = tree->lnode; /* first argument */
+ t1 = force_string(tree_eval(tmp));
+ string = t1->stptr;
+
+ t2 = NULL;
+#if ENABLE_NLS && HAVE_LC_MESSAGES && HAVE_DCGETTEXT
+ tree = tree->rnode; /* second argument */
+ if (tree != NULL) {
+ tmp = tree->lnode;
+ t2 = force_string(tree_eval(tmp));
+ domain = t2->stptr;
+ } else
+ domain = TEXTDOMAIN;
+
+ if (tree != NULL && tree->rnode != NULL) { /* third argument */
+ int low, high, i, mid;
+ NODE *t;
+
+ tree = tree->rnode;
+ tmp = tree->lnode;
+ t = force_string(tree_eval(tmp));
+ category = t->stptr;
+
+ /* binary search the table */
+ low = 0;
+ high = (sizeof(cat_tab) / sizeof(cat_tab[0])) - 1;
+ while (low <= high) {
+ mid = (low + high) / 2;
+ i = strcmp(category, cat_tab[mid].name);
+
+ if (i < 0) /* category < mid */
+ high = mid - 1;
+ else if (i > 0) /* category > mid */
+ low = mid + 1;
+ else {
+ lc_cat = cat_tab[mid].val;
+ break;
+ }
+ }
+ if (lc_cat == -1) /* not there */
+ fatal(_("dcgettext: `%s' is not a valid locale category"), category);
+
+ free_temp(t);
+ } else
+ lc_cat = LC_MESSAGES;
+
+ the_result = dcgettext(domain, string, lc_cat);
+#else
+ the_result = string;
+#endif
+ free_temp(t1);
+ if (t2 != NULL)
+ free_temp(t2);
+
+ return tmp_string(the_result, strlen(the_result));
+}
+
+/* do_bindtextdomain --- set the directory for a text domain */
+
+/*
+ * awk usage is
+ *
+ * binding = bindtextdomain(dir [, domain])
+ *
+ * If dir is "", pass NULL to C version.
+ * Default domain is TEXTDOMAIN.
+ */
+
+NODE *
+do_bindtextdomain(NODE *tree)
+{
+ NODE *tmp, *t1, *t2;
+ char *directory, *domain;
+ char *the_result;
+
+ t1 = t2 = NULL;
+ /* set defaults */
+ directory = NULL;
+ domain = TEXTDOMAIN;
+
+ tmp = tree->lnode; /* first argument */
+ t1 = force_string(tree_eval(tmp));
+ if (t1->stlen > 0)
+ directory = t1->stptr;
+
+ tree = tree->rnode; /* second argument */
+ if (tree != NULL) {
+ tmp = tree->lnode;
+ t2 = force_string(tree_eval(tmp));
+ domain = t2->stptr;
+ }
+
+ the_result = bindtextdomain(domain, directory);
+
+ free_temp(t1);
+ if (t2 != NULL)
+ free_temp(t1);
+
+ return tmp_string(the_result, strlen(the_result));
+}
OpenPOWER on IntegriCloud