2013-11-10 34 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和后者)的定义之前添加函数的原型。