user2015915
user2015915

Reputation: 107

Undefined Reference to a function which is defined already

I am trying to construct an expression compiler. When I try to compile my following main.c, it gives me the following errors:

    cc -O -o compile error.o lex.o table.o main.o code.o
    main.o: In function `terms':
    main.c:(.text+0x1be): undefined reference to `popopand'
    main.c:(.text+0x1c5): undefined reference to `popopand'
    main.c:(.text+0x1e7): undefined reference to `popoptor'
    main.o: In function `term':
    main.c:(.text+0x26b): undefined reference to `factoor'
    main.o: In function `expresses':
    main.c:(.text+0x302): undefined reference to `popopand'
    main.c:(.text+0x309): undefined reference to `popopand'
    main.c:(.text+0x32b): undefined reference to `popoptor'
    main.o: In function `stmt':
    main.c:(.text+0x4cf): undefined reference to `popopand'
    main.c:(.text+0x4d6): undefined reference to `popopand'
    main.c:(.text+0x4dd): undefined reference to `popoptor'
    main.o: In function `stmts':
    main.c:(.text+0x582): undefined reference to `eerror'
    collect2: ld returned 1 exit status
    make: *** [compile] Error 1

And my main.c is following code:

#include "global.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define STACK 100

int opandstk[STACK],optorstk[STACK];
int topoptor=-1,topopand=-1;
int curtoken;

main(argc,argv) int argc;char *argv[];{

    char msg[BUFSIZ];
    char *sp;

    if(argc!=2){
        sprintf(msg,"usage: %s filename",argv[0]);
        error(msg,PANIC);
    }
    emit(TEXT,BLANK,BLANK);
    curtoken=yygettoken();
    if(stmts()){
        if(curtoken=='\n' || curtoken==EOFILE){
            curtoken=yygettoken();
            if(curtoken==EOFILE){
                emit(EXIT,insert("0"),BLANK);
                data();
            }
        }
    }
    else
        error("end of file or end of line expected.",PANIC);
    exit(0);
}
stmts(){
    if(curtoken=='\n' || curtoken==EOFILE)
        return 1;
    if(curtoken==IDENT){
        if(stmt())
            if(stmts())
                return 1;
    }
    error("end of file or end of line or identifier expected.",PANIC);
}
stmt(){
    int rhs;
    if(curtoken==IDENT){
        pushopand(lookup(yytext));
        curtoken=yygettoken();
        if(curtoken=='='){
            pushoptor(ASSIGN);
            curtoken=yygettoken();
            if(express()){
                if(curtoken==';'){
                    curtoken=yygettoken();
                    rhs=popopand();
                    emit(popoptor(),popopand(),rhs);
                    return 1;
                }
                error("';' expected.",PANIC);
            }

        }
        error("'=' expected.",PANIC);
    }
    error("identifier expected.",PANIC);
}
express(){
    if(curtoken==IDENT || curtoken==INTEGER || curtoken=='('){
        if(term() && expresses())
            return 1;
    }
    error("identifier,integer or '(' expected.",PANIC);
}
expresses(){
    int lhs,rhs,temp;
    if(curtoken==')' || curtoken==';')
        return 1;
    if(curtoken=='-' || curtoken=='+'){
        if(curtoken=='-')
            pushoptor(SUB);
        else
            pushoptor(ADD);
        curtoken=yygettoken();
        if (term()){
            rhs=popopand();
            lhs=popopand();
            temp=mktmp();
            emit(ASSIGN,temp,lhs);
            emit(popoptor(),temp,rhs);
            pushopand(temp);
            if(expresses())
                return 1;
        }
    }
    error("')',';','-' or '+'expected.",PANIC);
}
term(){
    if(curtoken==IDENT || curtoken==INTEGER || curtoken=='(')
        if(factor() && terms())
            return 1;
    error("identifier,integer or '(' expected.",PANIC);
}
terms(){
    int lhs,rhs,temp;
    if(curtoken=='/' || curtoken=='*'){
        if(curtoken=='/')
            pushoptor(DIV);
        else
            pushoptor(MULT);
        curtoken=yygettoken();
        if (factor()){
            rhs=popopand();
            lhs=popopand();
            temp=mktmp();
            emit(ASSIGN,temp,lhs);
            emit(popoptor(),temp,rhs);
            pushopand(temp);
            if(terms())
                return 1;
        }

    }
    else if(curtoken=='-' || curtoken=='+'|| curtoken==')' || curtoken==';')
        return 1;
    error("'/','*','-','+',';'or ')'expected.",PANIC);
}
factor(){
    if(curtoken=='('){
        curtoken=yygettoken();
        if (express()){
            if(curtoken==')'){
                curtoken=yygettoken();
                return 1;
            }
            error("')' expected",PANIC);
        }

    }
    if(curtoken==INTEGER || curtoken==IDENT){
        pushopand(lookup(yytext));
        curtoken=yygettoken();
        return 1;
    }
    error("'(',integer or identifier expected",PANIC);
}
pushopand(i) int i;{
    if(++topopand==STACK)
        error("internal error: operand stack overflow",PANIC);
    opandstk[topopand]=i;
}
int 
popopand(){
    if(topopand==-1)
        error("internal error: operand stack underflow",PANIC);
    return (opandstk[topopand--]);
}
pushoptor(i) int i;{
    if(++topoptor==STACK)
        error("internal error: operator stack overflow",PANIC);
    opandstk[topoptor]=i;
}
int 
popoptor(){
    if(topoptor==-1)
        error("internal error: operator stack underflow",PANIC);
    return (opandstk[topoptor--]);
}
int 
mktmp(){
    static int seed=0;
    char name[BUFSIZ];
    sprintf(name,"-xxx%d",seed++);
    return (insert(name,NONLITERAL));
}

And my Makefile is:

compile: error.o lex.o table.o code.o main.o
    cc -O -o compile error.o lex.o table.o main.o code.o
main.o: global.h
    cc -c -O main.c
code.o: global.h
    cc -c -O code.c
error.o:global.h
    cc -c -O error.c    
lex.o:  global.h
    cc -c -O lex.c
table.o: global.h
    cc -c -O table.c

Will any mentor advice me to resolve those errors? Thanx in advance.

Upvotes: 0

Views: 4099

Answers (2)

Keith Thompson
Keith Thompson

Reputation: 263637

At least part of the problem is in your Makefile.

This:

main.o: global.h
    cc -c -O main.c

says that main.o depends on global.h, but not on main.c. Which means that even if you correct errors in main.c, typing make won't recompile it, and it will try to re-link with the existing main.o compiled from the old version of main.c.

Fix your Makefile so that each foo.o depends on the corresponding foo.c.

As for your code, it's using old-style function definitions, which have been obsolescent since the 1989 ANSI C standard. It's also calling functions before they've been declared or defined, which is invalid as of the 1999 ISO C standard (that would result in a compile-time warning or error message, not the link-time errors you're seeing).

The first thing I'd do (after fixing the Makefile) is to update all your definitions to a more modern style, and add prototypes to the top of the source file so that everything is declared before it's called. For example, change this:

main(argc,argv) int argc;char *argv[];{

to this:

int main(int argc, char *argv[]) {

and this:

stmts(){

to this:

void stmts(void) {

If you're using gcc (cc is commonly a symlink, to gcc), use options that will produce more warnings, such as [g]cc -std=c99 -pedantic -Wall -Wextra.

Replacing the old-style definitions might not fix the problems you're seeing, and it might not be completely necessary if you're using a compiler that accepts old-style code, but it will make the code easier to maintain and to track down any problems. For example, with old-style definitions the compiler won't complain if you call a function with the wrong number of arguments; with prototypes, it will.

Upvotes: 1

haccks
haccks

Reputation: 106122

You should add prototypes of your functions before the definition of main (specially for C99 and latter).

Upvotes: 1

Related Questions