// parse.cc #include "parse.h" char *mystrdup(char *todup) { if(todup == NULL) return NULL; char *p = new char[strlen(todup)+1]; strcpy(p, todup); return p; } Parse::Parse(char *filename) { // init FileName = mystrdup(filename); StartPos = 0; EndPos = 0; FD = NULL; CL = NULL; Valid = 0; NumOfLines = 0; NumOfVar = 0; Line = new char[2048]; VarArg = NULL; VarNam = NULL; VarType = NULL; Default = NULL; Description = NULL; Author = NULL; Usage = NULL; Version = NULL; FD = fopen(FileName, "rb"); if(FD == NULL) { perror(FileName); Valid = -1; return; } // finde Stelle an der command line beginnt und endet. Valid = FindBeginEnd(); if(Valid != 0) return; fprintf(stderr, "Number of lines to parse: %d\n", NumOfLines); VarArg = new char* [NumOfLines]; VarNam = new char* [NumOfLines]; VarType = new char* [NumOfLines]; Default = new char* [NumOfLines]; Description = new char* [NumOfLines]; int i; for(i = 0; i < NumOfLines; i++) { VarArg[i] = NULL; VarNam[i] = NULL; VarType[i] = NULL; Default[i] = NULL; Description[i] = NULL; } Valid = ScanArguments(); if(Valid == -1) { fprintf(stderr, "Error in line: %s\n", Line); return; } fprintf(stderr, "Building include file "); Valid = BuiltInclude(); if(Valid == 0) fprintf(stderr, "- ok.\n"); else fprintf(stderr, "- there was an error!\n"); } Parse::~Parse(void) { if(FD != NULL) fclose(FD); delete [] Line; if(VarArg!=NULL) { int i; for(i = 0; i < NumOfLines; i++) { delete [] VarArg[i]; delete [] VarNam[i]; delete [] VarType[i]; delete [] Default[i]; delete [] Description[i]; } delete [] VarArg; delete [] VarNam; delete [] VarType; delete [] Default; delete [] Description; } } char Parse::GetC(void) { char c = getc(FD); if(c == '\r') { // CR & LF will be only LF c = getc(FD); if(c == '\n') return c; else { ungetc(c, FD); return '\r'; } } else return c; } int Parse::ReadWhiteSpace(void) { while(Line[PosInLine] == ' ') PosInLine++; return 0; } int Parse::ReadToEndOfLine(void) { char c; c = GetC(); while((c != EOF) && (c != '\n')) { c = GetC(); } if(c == EOF) return -1; else return 0; } int Parse::FindBeginEnd(void) { char c; unsigned long pos; int out; fseek(FD, 0, SEEK_SET); out = 0; pos = ftell(FD); c = GetC(); while((c != EOF) && (!out)) { if(c == '#') { out = Compare("if 0"); if(out) { ReadToEndOfLine(); out = Compare("$command line$"); if(out) { ReadToEndOfLine(); StartPos = ftell(FD); } } } pos = ftell(FD); c = GetC(); } if(out == 0) return -1; // the begining was not found out = 0; NumOfLines = 0; while((c != EOF) && (!out)) { if(c == '#') { out = Compare("endif"); if(out) EndPos = pos; } else if(c == '\n') NumOfLines++; pos = ftell(FD); c = GetC(); } if(out == 0) return -1; return 0; } int Parse::Compare(char *str) { // the position in the file is after the comparison: // 1. if the following characters are equal at the end of the // part to compare. // 2. otherwise the same position where the comparison starts. int i; char *cstr, c; unsigned long pos; pos = ftell(FD); c = GetC(); cstr = new char[strlen(str)+1]; i = 0; cstr[i] = c; i++; while((i < strlen(str)) && c != EOF) { cstr[i] = GetC(); i++; } if(c == EOF) { delete [] cstr; fseek(FD, pos, SEEK_SET); return 0; } cstr[i] = '\0'; if(strcmp(str, cstr) == 0) { delete [] cstr; return 1; } else { delete [] cstr; fseek(FD, pos, SEEK_SET); return 0; } } int Parse::Status(void) { return Valid; } int Parse::ScanArguments(void) { fprintf(stderr, "Parsing the lines"); fseek(FD, StartPos, SEEK_SET); int mes, i; for(i = 0; i < NumOfLines; i++) { fprintf(stderr, "."); if(ReadLine() == -1) { fprintf(stderr, "\n"); return -1; } PosInLine = 0; if(Line[PosInLine] != '#') { // could be a commentar line mes = ReadText(); if(mes == -1) { fprintf(stderr, "\nError in ReadText().\n"); return -1; } } else { PosInLine++; ReadWhiteSpace(); mes = ReadVarArg(i); if(mes == -1) { fprintf(stderr, "\nError in ReadVarArg().\n"); return -1; } mes = ReadVarNam(i); if(mes == -1) { fprintf(stderr, "\nError in ReadVarNam().\n"); return -1; } mes = ReadVarType(i); if(mes == -1) { fprintf(stderr, "\nError in ReadVarType().\n"); return -1; } else if(strcmp("string", VarType[i]) == 0) { mes = ReadDefDesString(i); if(mes == -1) { fprintf(stderr, "\nError while reading default and description\n" "for a string variable.\n"); return -1; } } else { // try what is next default or description // description beginns with a " and ends with a " if(Line[PosInLine] == '\"') {// there is no default for this variable mes = ReadDescription(i); if(mes == -1) { fprintf(stderr, "\nError in ReadDescription().\n"); return -1; } } else { // there will be a default value mes = ReadDefault(i); if(mes == -1) { fprintf(stderr, "\nError in ReadDefault().\n"); return -1; } else { mes = ReadDescription(i); if(mes == -1) { fprintf(stderr, "\nError in ReadDescription().\n"); return -1; } } } } } } // for i fprintf(stderr, "\n"); return 0; } int Parse::ReadDefDesString(int x) { if(Line[PosInLine] == '\0') return -1; char def[1024]; char des[1024]; int i = 0; if(Line[PosInLine] != '\"') return -1; def[i] = Line[PosInLine]; PosInLine++; i++; while(Line[PosInLine]!='\0') { def[i] = Line[PosInLine]; i++; if(Line[PosInLine] == '\"') break; PosInLine++; } def[i] = '\0'; if(Line[PosInLine] != '\"') return -1; else PosInLine++; ReadWhiteSpace(); if(Line[PosInLine] == '\0') { def[strlen(def)-1] = '\0'; // remove " at the end Description[x] = mystrdup(def+1); // it's allright: def return 0; } i = 0; if(Line[PosInLine] != '\"') return -1; des[i] = Line[PosInLine]; PosInLine++; while(Line[PosInLine]!='\0') { des[i] = Line[PosInLine]; i++; if(Line[PosInLine] == '\"') break; PosInLine++; } i--; des[i] = '\0'; if(Line[PosInLine] != '\"') return -1; Default[x] = mystrdup(def); Description[x] = mystrdup(des); return 0; } int Parse::Info(void) { int i; for(i = 0; i < NumOfLines; i++) { fprintf(stderr, "ActVar: %s ActNam: %s ActType %s\n", VarArg[i], VarNam[i], VarType[i]); fprintf(stderr, " Default: %s Description: %s\n", Default[i], Description[i]); } fprintf(stderr, "Author %s Version %s\n", Author, Version); fprintf(stderr, "Usage %s\n", Usage); } int Parse::ReadVarArg(int x) { if(Line[PosInLine] == '\0') return -1; unsigned long len, i; len = strlen(Line); i = 0; char arg[1024]; while((PosInLine\n" "#include \n" "#include \n" "}\n\n"; fprintf(CL, code, nameh, name, name); code = "struct InterVallInt {\n" " int From;\n" " int To;\n" "};\n\n" "struct InterVallFloat {\n" " float From;\n" " float To;\n" "};\n\n" "struct EventMod {\n" " char *FileName;\n" " unsigned long Offset, Length;\n" " int ListNr, Begin, End;\n" " EventMod *Next;\n" "};\n\n" "// typedef int bool;\n" "typedef char* string;\n" "typedef InterVallInt intervallint;\n" "typedef InterVallFloat intervallfloat;\n" "typedef EventMod eventlist;\n\n"; fprintf(CL, code); int i; for(i = 0; i < NumOfLines; i++) { if(VarArg[i] == NULL) continue; else { fprintf(CL, "extern %s \t%s;\n", VarType[i], VarNam[i]); } } fprintf(CL, "extern char \t*Copyright;\n"); code = "\n\n// writes the usage message to stderr\n" "void Usage(char*);\n\n" "// parses the command line\n" "int ParseCommandLine(int, char**);\n\n" "#endif\n\n"; fprintf(CL, code); fclose(CL); return 0; } int Parse::BuiltCC(char *namecc, char *nameh) { CL = fopen(namecc, "wb"); if(CL == NULL) return -1; char *code; code = "// file for parsing the command line and usage message.\n" "// %s\n\n" "#include \"%s\"\n\n"; fprintf(CL, code, namecc, nameh); int i; for(i = 0; i < NumOfLines; i++) { if(VarArg[i] == NULL) continue; else { fprintf(CL, "%s \t%s;\n", VarType[i], VarNam[i]); } } fprintf(CL, "char \t*Copyright;\n"); fprintf(CL, "\n"); code = "char *mystrdup(char *todup)\n" "{\n" " if(todup == NULL)\n" " return NULL;\n" " char *p = new char[strlen(todup)+1];\n" " strcpy(p, todup);\n" " return p;\n" "}\n"; fprintf(CL, code); code = "char copyrightinternal[]=\n" "\"This is the internal copyright message and could be substitute.\\n\"\n" "\"by our own one. This copyright message is only for the\\n\"\n" "\"command line parser and not for the whole program.\\n\"\n" "\"Copyright (C) for the command line parser:\\n\"\n" "\" 1994 R. Schamburger, Institut fuer Physiologie und\\n\"\n" "\" Biokybernetik (IPB), Universitaet Erlangen, Deutschland\\n\"\n" "\" Permission to use, copy, modify, distribute, and sell this\\n\"\n" "\" software and its documentation for any purpose is hereby\\n\"\n" "\" granted without fee, provided that the above copyright notice\\n\"\n" "\" appear in all copies and related publications and that both\\n\"\n" "\" that copyright notice and this permission notice appear in\\n\"\n" "\" supporting documentation. The authors make no representations\\n\"\n" "\" about the suitability of this software for any purpose. It is\\n\"\n" "\" provided \\\"as is\\\" without express or implied warranty.\\n\\n\"\n" "\" Send your comments, suggestions or bug reports to\\n\"\n" "\" ftpebs@uni-erlangen.de\\n\\n\";\n"; fprintf(CL, code); delete [] nameh; delete [] namecc; int err = 0; err += BuiltUsageCode(); err += BuiltParserCode(); fclose(CL); if(err != 0) return -1; else return 0; } int Parse::BuiltUsageCode(void) { if(CL == NULL) return -1; fprintf(CL,"\n"); fprintf(CL, "void Usage(char *pname)\n"); fprintf(CL, "{\n"); if(Usage != NULL) fprintf(CL, " fprintf(stderr, \"Usage : %s\\n\");\n", Usage); if(Author != NULL) fprintf(CL, " fprintf(stderr, \"Author : %s\\n\");\n", Author); if(Version != NULL) fprintf(CL, " fprintf(stderr, \"Version: %s\\n\");\n", Version); fprintf(CL, " fprintf(stderr, \" %%s {arguments}\\n\", pname);\n"); fprintf(CL, " fprintf(stderr, \"\\targuments:\\n\");\n"); fprintf(CL, " fprintf(stderr, \" *\\t-c \\tcopyright message\\n\");\n"); fprintf(CL, " fprintf(stderr, \" *\\t-h \\thelp or usage" " message\\n\");\n"); int i; char *des; for(i = 0; i < NumOfLines; i++) { if(VarArg[i] == NULL) continue; else { if(Description[i] == NULL) des = ""; else des = Description[i]; if((Default[i] != NULL) || (strcmp(VarType[i], "bool")==0)) fprintf(CL, " fprintf(stderr, \" *\\t%s \\t%s\\n\");\n", VarArg[i], des); else fprintf(CL, " fprintf(stderr, \"\\t%s \\t%s\\n\");\n", VarArg[i], des); } } fprintf(CL, "fprintf(stderr, \"\\n * means that this argument" " is optional.\\n\");\n"); fprintf(CL, " fprintf(stderr, \"\\n\");\n"); fprintf(CL, "}\n"); fprintf(CL, "\n"); return 0; } int Parse::BuiltEventParser(void) { int y; int found = 0; for(y=0; yNext);\n" " delete pars_event;\n" " }\n" "}\n\n"; fprintf(CL, code); code = "int ParseEventWord(EventMod *pars_event, char *pars_text0)\n" "{\n" " char *pars_text = mystrdup(pars_text0);\n" " int pars_textlen = strlen(pars_text);\n" " int pars_out = 0;\n" " int pars_pos1 = 0;\n" " int pars_pos2 = 0;\n" " char pars_c;\n" " char pars_helpbuf[1024];\n" " for(;;) {\n" " pars_event->FileName = NULL;\n" " pars_event->Offset = 0;\n" " pars_event->Length = 0;\n" " pars_event->ListNr = -1;\n" " pars_event->Begin = 0;\n" " pars_event->End = 0;\n" " pars_event->Next = NULL;\n" " // read the filename\n" " while(pars_text[pars_pos2]!='#'&&pars_text[pars_pos2]!='+'&&\n" " pars_text[pars_pos2]!=','&&pars_text[pars_pos2]!=':'&&\n" " pars_text[pars_pos2]!='@'&&pars_textlen>=pars_pos2)\n" " pars_pos2++;\n" " pars_c = pars_text[pars_pos2];\n" " pars_text[pars_pos2] = '\\0';\n" " pars_event->FileName = mystrdup(pars_text+pars_pos1);\n" " pars_text[pars_pos2] = pars_c;\n" " pars_pos1=pars_pos2+1;\n" "\n" " while((!pars_out) && (pars_textlen>=pars_pos2)) {\n" " if(pars_text[pars_pos2] == '#') { // read listnr\n" " pars_pos2++;\n" " while(pars_text[pars_pos2]!='+'&&\n" " pars_text[pars_pos2]!=','&&pars_text[pars_pos2]!=':'&&\n" " pars_text[pars_pos2]!='@'&&pars_textlen>=pars_pos2)\n" " pars_pos2++;\n" " pars_c = pars_text[pars_pos2];\n" " pars_text[pars_pos2] = '\\0';\n" " strcpy(pars_helpbuf, pars_text+pars_pos1);\n" " pars_text[pars_pos2] = pars_c;\n" " pars_pos1=pars_pos2+1;\n" " pars_event->ListNr = atoi(pars_helpbuf);\n" " } else if(pars_text[pars_pos2] == '+') { // read offset\n" " pars_pos2++;\n" " while(pars_text[pars_pos2]!=','&&pars_text[pars_pos2]!=':'&&\n" " pars_text[pars_pos2]!='@'&&pars_textlen>=pars_pos2)\n" " pars_pos2++;\n" " pars_c = pars_text[pars_pos2];\n" " pars_text[pars_pos2] = '\\0';\n" " strcpy(pars_helpbuf, pars_text+pars_pos1);\n" " pars_text[pars_pos2] = pars_c;\n" " pars_pos1=pars_pos2+1;\n" " pars_event->Offset = atoi(pars_helpbuf);\n" " } else if(pars_text[pars_pos2] == ',') { // read length\n" " pars_pos2++;\n" " while(pars_text[pars_pos2]!=':'&&\n" " pars_text[pars_pos2]!='@'&&pars_textlen>=pars_pos2)\n" " pars_pos2++;\n" " pars_c = pars_text[pars_pos2];\n" " pars_text[pars_pos2] = '\\0';\n" " strcpy(pars_helpbuf, pars_text+pars_pos1);\n" " pars_text[pars_pos2] = pars_c;\n" " pars_pos1=pars_pos2+1;\n" " pars_event->Length = atoi(pars_helpbuf);\n" " } else if(pars_text[pars_pos2] == ':') { // read intervall\n" " pars_pos2++;\n" " while(pars_text[pars_pos2]!='-'&&pars_textlen>=pars_pos2)\n" " pars_pos2++;\n" " pars_c = pars_text[pars_pos2];\n" " pars_text[pars_pos2] = '\\0';\n" " strcpy(pars_helpbuf, pars_text+pars_pos1);\n" " pars_text[pars_pos2] = pars_c;\n" " pars_pos1=pars_pos2+1;\n" " pars_event->Begin = atoi(pars_helpbuf);\n" " while(pars_text[pars_pos2]!='@'&&pars_textlen>=pars_pos2)\n" " pars_pos2++;\n" " pars_c = pars_text[pars_pos2];\n" " pars_text[pars_pos2] = '\\0';\n" " strcpy(pars_helpbuf, pars_text+pars_pos1);\n" " pars_text[pars_pos2] = pars_c;\n" " pars_pos1=pars_pos2+1;\n" " pars_event->End = atoi(pars_helpbuf);\n" " pars_pos1 = pars_pos2+1;\n" " } else if(pars_text[pars_pos2]=='@' && " "pars_text[pars_pos2+1]!='\\0') {\n" " pars_event->Next = new EventMod;\n" " pars_event = pars_event->Next;\n" " pars_pos2++;\n" " pars_pos1=pars_pos2;\n" " break;\n" " }\n" " else {\n" " fprintf(stderr, \"Error: something is wrong with: %%s\\n\", " "pars_text);\n" " fprintf(stderr, \" look at position: %%d\\n\", pars_pos2+1);\n" " delete [] pars_text;\n" " return -1;\n" " }\n" " if(pars_pos2>=pars_textlen)\n" " pars_out = 1;\n" " } //while\n" // while " if(pars_pos2>=pars_textlen) {\n" " break;\n" " }\n" " } //for\n" //for " delete [] pars_text;\n" " return 0;\n" "}\n\n"; fprintf(CL, code, VarNam[y]); return 0; } int Parse::BuiltParserCode(void) { if(CL == NULL) return -1; char *code; int y, mes, k; BuiltEventParser(); code = "int ParseCommandLine(int pars_num, char **pars_vec)\n" "{\n" " // set defaults\n"; fprintf(CL, code); int numofstrings = 0; for(y=0; y= pars_num) {\n" " fprintf(stderr, \"Error: missing some values!\\n\");\n" " Usage(pars_vec[0]);\n" " return -1;\n" " }\n" " %s = atoi(pars_vec[pars_i]);\n"; fprintf(CL, code, VarNam[y]); } else if(strcmp("float", VarType[y])==0) { code = " pars_i++;\n" " if(pars_i >= pars_num) {\n" " fprintf(stderr, \"Error: missing some values!\\n\");\n" " Usage(pars_vec[0]);\n" " return -1;\n" " }\n" " %s = atof(pars_vec[pars_i]);\n"; fprintf(CL, code, VarNam[y]); } else if(strcmp("intervallint", VarType[y])==0) { code = " pars_i++;\n" " pars_i++;\n" " if(pars_i >= pars_num) {\n" " fprintf(stderr, \"Error: missing some values!\\n\");\n" " Usage(pars_vec[0]);\n" " return -1;\n" " }\n" " %s.From = atoi(pars_vec[pars_i-1]);\n" " %s.To = atoi(pars_vec[pars_i]);\n"; fprintf(CL, code, VarNam[y], VarNam[y]); } else if(strcmp("intervallfloat", VarType[y])==0) { code = " pars_i++;\n" " pars_i++;\n" " if(pars_i >= pars_num) {\n" " fprintf(stderr, \"Error: issing some values!\\n\");\n" " Usage(pars_vec[0]);\n" " return -1;\n" " }\n" " %s.From = atof(pars_vec[pars_i-1]);\n" " %s.To = atof(pars_vec[pars_i]);\n"; fprintf(CL, code, VarNam[y], VarNam[y]); } else if(strcmp("string", VarType[y])==0) { code = " pars_i++;\n" " if(pars_i >= pars_num) {\n" " fprintf(stderr, \"Error: missing some values!\\n\");\n" " Usage(pars_vec[0]);\n" " return -1;\n" " }\n" " %s = pars_vec[pars_i];\n"; fprintf(CL, code, VarNam[y]); } else if(strcmp("eventlist", VarType[y])==0) { code = " pars_i++;\n" " if(pars_i >= pars_num) {\n" " fprintf(stderr, \"Error: missing some values!\\n\");\n" " Usage(pars_vec[0]);\n" " return -1;\n" " }\n" " if(%s.Next != NULL) {\n" " ClearEvents(%s.Next);\n" " %s.Next = NULL;\n" " }\n" " if(ParseEventWord(&%s, pars_vec[pars_i])!=0)\n" " return -1;\n"; fprintf(CL, code, VarNam[y], VarNam[y], VarNam[y], VarNam[y]); } return 0; }