flex parser -> undefined reference
-
hallo leute,
ich beschäftige mich schon eine Ewigkeit mit einem Problem, das ich einfach nicht verstehe.Ich erkläre mal kurz:
ich habe eine flex-parser datei (.lex), die eigentlich nichts anderes tut als einer struktur ein paar attribut-werte zuzuweisen.ich kann mit dem aufruf flex das ganze auch zu einer .c datei machen.
wenn ich allerdings diese .c datei kompilieren will, meckert er über undefined refernces zu meiner struktur.hier erstmal der code von der datei "config.h", also einfach eine headerdatei die festlegt, wie die struktur aussehen soll. vllt liegt ja der fehler darin, dass ich in der .lex datei irgendwas falsch darauf bezieh, deswegen zeig ich euch die auch mal:
/* config.h */ #ifndef ___CONFIG_H_ #define ___CONFIG_H_ #include <inttypes.h> #include "../util/util.h" /* length of the string for the scheduling * algorithm option config->schedalg */ #define ALGSTRINGLENGTH 16 /* struct holding the server and client run-time configuration, * see sample config ../server/server.conf for documentation */ struct conf { char port[7]; int logMask; short ipv; char ip[40]; char workdir[MAX_PATH_LEN]; char logfile[MAX_PATH_LEN]; char schedalg[ALGSTRINGLENGTH]; char bc_port[7]; int bc_interval; char networkDumpLogFile[MAX_PATH_LEN]; }; /* reads the configfile and stores values in the config struct * a global struct conf *config variable is needed * returns 0 on success, -1 on error */ int readConfig(char *configfile); #endif /* ___CONFIG_H_ */
okay und hier dann die datei "config.lex", die ein parser und die headerdatei realisiert: der parser macht halt nix anderes als nach den begriffen für die attribute der struktur zu suchen, und weist denen dann gleich einen standartwert zu (das passiert in der funktion 'readConfig')
%{ /* this is a Parser for a configfile generated by flex */ %} /* we only parse one config-file */ %option noyywrap /* we only parse from files (avoids fileno warning) */ %option never-interactive /* we don't need to unput (avoids yyunput warning) */ %option nounput /************ begin definitions ************/ %{ #include <inttypes.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include "config.h" #include "../util/util.h" #define YYLMAX 128 /* max pattern length */ extern struct conf *config; %} /************ end definitions ************/ /************ begin rules ************/ %% #.*\n /*eat up comments */ [ \t\n\r]+ /* eat up whitespace */ /* find useful configuration setting and copy them to struct conf *config */ /* see config.h for documentation */ workdir\ [a-zA-Z0-9\/\._]+$ {strncpy(config->workdir, &yytext[8], MAX_PATH_LEN);} logfile\ [a-zA-Z0-9\/\._]+$ {strncpy(config->logfile, &yytext[8], MAX_PATH_LEN);} networkDumpLogFile\ [a-zA-Z0-9\/\._]+$ {strncpy(config->networkDumpLogFile, &yytext[19], MAX_PATH_LEN);} forceIpVersion\ [046] {config->ipv = (short) atoi(&yytext[15]);} ip\ [0-9.]* {strncpy(config->ip, &yytext[3],17);} port\ [1024-65535] {strncpy(config->port, &yytext[5],6);} bc_port\ [1024-65535] {strncpy(config->bc_port, &yytext[8],6);} bc_interval\ [0-9]* {config->bc_interval = (int) atoi(&yytext[12]);} logMask\ [0-512] {config->logMask = (int) atoi(&yytext[8]);} scheduler\ rr|pri {strncpy(config->schedalg, &yytext[10], 15);} /* everything left is not understood by the configParser */ .+\n printf("config warning: invalid line: %s", yytext); %% /************ end rules ************/ /************ begin functions ************/ int readConfig(char * configfile){ /* initialize config with default values */ strcpy(config->workdir, "/tmp/sysprak"); strcpy(config->logfile, "/tmp/sysprak/server.log"); strcpy(config->networkDumpLogFile, "/tmp/sysprak/serverDump.log"); config->ipv = 0; strcpy(config->ip, "127.0.0.1"); strcpy(config->port,"4779"); strcpy(config->bc_port, "4777"); config->bc_interval = 10; config->logMask = 283; strcpy(config->schedalg, "rr"); /* end init */ /* open yyin, the input stream for the lexer */ if((yyin = fopen(configfile , "r" )) == NULL) {perror("Fehler fopen"); return -1;} /* call the lexer */ yylex(); fclose(yyin); return 0; } /************ end functions ************/
okay ich hoffe ihr habt soweit nen überblick.
meiner meinung nach macht die .lex datei eigentlich das richtige..wenn ich jetzt also in der console eingebe:
flex -o config.c config.lex
dann ist das kein problem und ich hab ne schöne config.c
wenn ich diese aber kompiliere mit der zeile:
gcc -o config config.c -lfl
dann eben der fehler:
/tmp/ccbaM6MP.o: In function `yylex': config.c:(.text+0x254): undefined reference to `config' config.c:(.text+0x2c8): undefined reference to `config' config.c:(.text+0x33e): undefined reference to `config' config.c:(.text+0x362): undefined reference to `config' config.c:(.text+0x388): undefined reference to `config' /tmp/ccbaM6MP.o:config.c:(.text+0x3b1): more undefined references to `config' follow collect2: ld returned 1 exit status
er findet also scheinbar die struktur 'config' nicht?!
ich weiss nur nicht, wieso er sie nicht findet...tausend danke an den, der sich das mal ankuckt und mir weiterhilft
-
Ist denn die Variablendeklaration in die "config.c" übernommen worden?
extern struct conf *config;
Evtl. mußt du diese in deine "config.h" auslagern.
Und hast du dann in deinem Projekt die Variable 'config' angelegt?
struct conf *config;
-
hallo, danke für die schnelle antwort !!!!
Ist denn die Variablendeklaration in die "config.c" übernommen worden?
ja, die steht drinnen.
Und hast du dann in deinem Projekt die Variable 'config' angelegt?
edit:
kann mir keiner helfen?
was mache ich dann, wenn ich so eine variable angelegt hab?
wie greife ich darauf zu? beim compilen von der config.c ?ich verstehe noch immer nicht, was GENAU dieses 'configfile' in der Funktion
'readConfig' ist..woher kriegt er das? und was genau macht
der aufruf von yyin = fopen(configfile)...
-
Mittels
gcc -o config config.c -lfl
compilierst und linkst du gleich die Datei, d.h. wie ich geschrieben habe, findet er keine Variable namens 'config'.
Kompilier erst mal nur deine Datei (ohne linken):
gcc -c -o object.o config.c
Dann dürften jetzt keine Fehler mehr kommen.
Nun mußt du noch die Objekt-Datei zu deinem Hauptprogramm hinzufügen (ich hoffe, du hast ein makefile dafür)
gcc -c -o main.o main.c gcc -o main main.o config.o -lfl
Und in deinem Hauptprogramm "main.c" mußt du einfach die Definition der Variablen anlegen:
#include "config.h" struct conf *config;
P.S: Ich habe die Objektdateiendung auf ".o" geändert (ist so Standard unter Unix/Linux) - nur Programme sollten keine Endung haben.
Und zu deiner letzten Frage:
wie kommt es daß du mit "lex" hantierst, wenn du nicht mal die Grundlagen kannst?'configfile' ist halt der Name der Datei, die geparst werden soll. Irgendwo im Hauptprogramm mußt du dann readConfig("Textdatei") aufrufen (bzw. ein anderes Programm übernimmt das dann, z.B. yacc).