9fans / plan9port

Plan 9 from User Space
https://9fans.github.io/plan9port/
Other
1.63k stars 321 forks source link

mk: no detection of an empty variable #255

Closed ghost closed 4 years ago

ghost commented 5 years ago
# touch 1.c 2.c 3.c
# echo "int main(){return 0;}" >1.c
# cat rules.mk
MKSHELL=/bin/rc
LD= cc
LDFLAGS=-static -s
CC=     cc
LDADD=  
OBJ = ${SRC:%.c = %.o}

$TAR: $OBJ
    $LD $LDFLAGS -o $target $prereq $LDADD

%.o: %.c
    $CC $CFLAGS -c $stem.c

clean:
    rm -f $TAR $OBJ

ALL= $TAR

all: $ALL

# cat mkfile
TAR=    test    
SRC=    1.c 2.c 3.c
#LDADD=-lz
<rules.mk

# mk
cc $CFLAGS -c 1.c
cc $CFLAGS -c 2.c
cc $CFLAGS -c 3.c
cc -static -s -o test 1.o 2.o 3.o 
cc: error: : No such file or directory
mk: cc -static -s ...  : exit status=exit(1)

It looks like mk wants to build the object *.o on an empty $LDADD variable. Setting this variable (eg. -lc) solves the problem, but this is an ugly approach.

# cat mkfile
TAR=    test    
SRC=    1.c 2.c 3.c

<rules.mk

LDADD= -lc
# mk
cc $CFLAGS -c 1.c
cc $CFLAGS -c 2.c
cc $CFLAGS -c 3.c
cc -static -s -o test 1.o 2.o 3.o -lc

In Plan 9 linking is added by #pragma, so there was no problem there. Does anyone have an idea how to solve this problem correctly? It should probably be added checking for empty variables in the mk code. The dependency graph should ignore such empty dependencies.

Maybe this function should do this additional check and do not copy empty variables?

ghost commented 4 years ago

This patch fixes this error but calls another in rc. Concat fails with null list in rc.

It looks like the null list should be handled differently in rc.

    if(lc!=0 || rc!=0){
        if(lc==0 || rc==0){
            Xerror1("null list in concatenation");
            return;
        }

If we omit the second if(lc==0 || rc==0), then the conclist() should return only available string:

https://github.com/9fans/plan9port/blob/master/src/cmd/rc/exec.c#L555

ghost commented 4 years ago

I'm not sure if this is the right solution (exec.c), but works for me:

void
Xconc(void)
{
    word *lp = runq->argv->words;
    word *rp = runq->argv->next->words;
    word *vp = runq->argv->next->next->words;
    int lc = count(lp), rc = count(rp);
    if (lc == 0 && rc != 0) {
        if (rc != 1)
            goto L1;
        vp = newword(rp->word, vp);
        poplist();
        runq->argv->words = vp;
        return;
    }
    if (lc != 0 && rc == 0) {
        if (lc != 1)
            goto L1;
        vp = newword(lp->word, vp);
        poplist()
        runq->argv->words = vp;
        return;
    }
    if (lc != 1 || rc !=1)
        goto L1;
    vp = conclist(lp, rp, vp);
    poplist();
    poplist();
    runq->argv->words = vp;
    return;
L1:
    Xerror1("mismatched list lengths in concatenation");
}
ghost commented 4 years ago

it's require 2x poplist():

void
Xconc(void)
{
    word *lp = runq->argv->words;
    word *rp = runq->argv->next->words;
    word *vp = runq->argv->next->next->words;
    int lc = count(lp), rc = count(rp);
    if (lc == 0 && rc != 0) {
        if (rc != 1)
            goto L2;
        vp = newword(rp->word, vp);
        goto L1;
    }
    if (lc != 0 && rc == 0) {
        if (lc != 1)
            goto L2;
        vp = newword(lp->word, vp);
        goto L1;
    }
    if (lc != 1 || rc !=1)
        goto L2;
    vp = conclist(lp, rp, vp);
L1:
    poplist();
    poplist();
    runq->argv->words = vp;
    return;
L2:
    Xerror1("mismatched list lengths in concatenation");
}