2013-11-10 61 views
0

我想構建一個表達式編譯器。 當我嘗試編譯我下面的main.c,它給了我下面的錯誤:未定義引用已定義的函數

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 

而我的main.c是下面的代碼:

#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)); 
} 

而我的Makefile:

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 

任何指導者會建議我解決這些錯誤嗎? Thanx提前。

+0

你確定'main'的語法正確嗎? – haccks

+1

@haccks ??? 'main()'是正確的代碼OP張貼... – 2013-11-10 08:22:45

+1

@haccks:它是「正確」的1980年的代碼.... – Mat

回答

1

問題的至少一部分在您的Makefile

此:

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

main.o取決於global.h,但不能在main.c。這意味着即使您更正了main.c中的錯誤,輸入make也不會重新編譯它,並且它會嘗試重新鏈接現有main.o編譯的版本的main.c

修復您的Makefile,使每個foo.o取決於相應的foo.c

至於你的代碼,它使用的是舊式的函數定義,自1989年的ANSI C標準以來它已經過時。它還在聲明或定義之前調用函數,這在1999 ISO ISO標準中是無效的(這會導致編譯時警告或錯誤消息,而不是您看到的鏈接時錯誤)。

我會做的第一件事(修復Makefile之後)是將所有定義更新爲更現代的樣式,並將原型添加到源文件的頂部,以便在調用之前聲明所有內容。例如,更改此:

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

這樣:

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

這:

stmts(){ 

這樣:

void stmts(void) { 

如果你正在使用gcc( cc通常是符號鏈接,到gcc),使用將生成更多警告的選項,例如[g]cc -std=c99 -pedantic -Wall -Wextra

替換舊式定義可能無法解決您所看到的問題,如果您使用接受舊式代碼的編譯器,但它可能不會完全必要,但它會使代碼更易於維護並追查任何問題。例如,使用舊式定義時,如果調用參數數量錯誤的函數,編譯器不會抱怨;與原型,它會。

0

您應該在main(特別是C99和後者)的定義之前添加函數的原型。