NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

standards/44063: awk: setting NF doesn't affect $<fieldnum>



>Number:         44063
>Category:       standards
>Synopsis:       awk: setting NF doesn't change $i
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    standards-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Nov 07 20:25:00 +0000 2010
>Originator:     Aleksey Cheusov
>Release:        NetBSD 5.1_RC4
>Organization:
>Environment:
System: NetBSD asrock.chizhovka.net 5.1_RC4 NetBSD 5.1_RC4 (GENERIC) #0: Sat 
Oct 30 14:10:25 EEST 2010 
cheusov%asrock.chizhovka.net@localhost:/srv/obj/sys/arch/amd64/compile/GENERIC 
amd64
Architecture: x86_64
Machine: amd64
>Description:

http://www.opengroup.org/onlinepubs/009695399/utilities/awk.html

    ...
    References to nonexistent fields (that is, fields after $NF),
    shall evaluate to the uninitialized value.

Now awk works like the following

    $ echo ' 1  2  3 ' | awk.orig '{NF=2; print "`" $3 "`"}'
    `3`
    $ echo ' 1  2  3 ' | awk.orig '{NF=2; print "`" $0 "`"}' 
    ` 1  2  3 `
    $

As far as I can see POSIX allows variantions about changing $0,
but gawk and mawk change it. The following patch solves the problem
with $3 and makes awk compatible with gawk and mawk.

Result:

    $ echo ' 1  2  3 ' | awk '{NF=2; print "`" $3 "`"}' 
    ``
    $ echo ' 1  2  3 ' | awk '{NF=2; print "`" $0 "`"}' 
    `1 2`
    $ 

>How-To-Repeat:
See above
>Fix:

Index: lib.c
===================================================================
RCS file: /cvsroot/src/dist/nawk/lib.c,v
retrieving revision 1.14
diff -u -r1.14 lib.c
--- lib.c       19 Oct 2008 19:33:47 -0000      1.14
+++ lib.c       7 Nov 2010 19:38:29 -0000
@@ -362,6 +362,7 @@
                }
        }
        setfval(nfloc, (Awkfloat) lastfld);
+       donerec = 1; /* restore */
        if (dbg) {
                for (j = 0; j <= lastfld; j++) {
                        p = fldtab[j];
@@ -393,6 +394,19 @@
        setfval(nfloc, (Awkfloat) n);
 }
 
+void setlastfld(int n) /* set lastfld cleaning fldtab cells if necessary */
+{
+       if (n > nfields)
+               growfldtab(n);
+
+       if (lastfld < n)
+           cleanfld(lastfld+1, n);
+       else
+           cleanfld(n+1, lastfld);
+
+       lastfld = n;
+}
+
 Cell *fieldadr(int n)  /* get nth field */
 {
        if (n < 0)
Index: proto.h
===================================================================
RCS file: /cvsroot/src/dist/nawk/proto.h,v
retrieving revision 1.6.12.2
diff -u -r1.6.12.2 proto.h
--- proto.h     14 Aug 2009 20:32:21 -0000      1.6.12.2
+++ proto.h     7 Nov 2010 19:38:29 -0000
@@ -127,6 +127,7 @@
 extern void    fldbld(void);
 extern void    cleanfld(int, int);
 extern void    newfld(int);
+extern void    setlastfld(int);
 extern int     refldbld(const char *, const char *);
 extern void    recbld(void);
 extern Cell    *fieldadr(int);
Index: tran.c
===================================================================
RCS file: /cvsroot/src/dist/nawk/tran.c,v
retrieving revision 1.14
diff -u -r1.14 tran.c
--- tran.c      19 Oct 2008 19:33:48 -0000      1.14
+++ tran.c      7 Nov 2010 19:38:29 -0000
@@ -298,6 +298,10 @@
                if (fldno > *NF)
                        newfld(fldno);
                   dprintf( ("setting field %d to %g\n", fldno, f) );
+       } else if (&vp->fval == NF) {
+               donerec = 0;    /* mark $0 invalid */
+               setlastfld(f);
+               dprintf( ("setting NF to %g\n", f) );
        } else if (isrec(vp)) {
                donefld = 0;    /* mark $1... invalid */
                donerec = 1;
@@ -324,6 +328,7 @@
 {
        char *t;
        int fldno;
+       Awkfloat f;
 
           dprintf( ("starting setsval %p: %s = \"%s\", t=%o, r,f=%d,%d\n", 
                vp, NN(vp->nval), s, vp->tval, donerec, donefld) );
@@ -347,6 +352,14 @@
        vp->tval &= ~DONTFREE;
           dprintf( ("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n", 
                vp, NN(vp->nval), t,t, vp->tval, donerec, donefld) );
+
+       if (&vp->fval == NF) {
+               donerec = 0;    /* mark $0 invalid */
+               f = getfval(vp);
+               setlastfld(f);
+               dprintf( ("setting NF to %g\n", f) );
+       }
+
        return(vp->sval = t);
 }
 



Home | Main Index | Thread Index | Old Index