/* RUN-TIME CONFIGURATION FILE PARSER */ /********************************************************************** * * zparse.y -- * Copyright (C) 2000 The New Zealand Digital Library Project * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *********************************************************************/ %{ /* verbatim C code - functions, etc */ #include #include #include #include #include "z3950cfg.h" #define YYDEBUG 1 #define YYERROR_VERBOSE 1 /* can't use default yyparse(), as this name is used elsewhere (eg mg)*/ #define yyin zconfigin #define yyparse zconfigparse char defLanguage=0; /* defined in parse.fl */ extern int lineno; #ifndef YYRECOVERING int YYRECOVERING=0; /* this is supposed to already be defined as a macro */ #endif /* defined in z3950proto.cpp */ struct z3950cfg *zserver_list=NULL; /* this is set in z3950proto.cpp */ FILE *errfile; int yylex(void); int yyerror(char *string); void errormsg(char *str); %} %union { char *string; struct z3950cfg *cfg; struct z3950aboutlist *about; int number; } /* keywords */ /***** NOTE: can explicitly give values for each token, AND give a string for the token name eg %token GSDLVERSION 257 "Version" *******/ %token GSDLVERSION 257 %token GENERAL_SECTION 258 SEARCH_SECTION 259 %token BROWSE_SECTION 260 MACROS_SECTION 261 %token MAINTAINER 262 %token PUBLIC 263 %token TRUE 264 FALSE 265 %token LANGUAGES 266 EN 267 FR 268 MI 269 ZH 270 DE 271 %token NAME 272 %token STRING 273 %token ICON 274 SMALLICON 275 %token ABOUT 276 %token SEARCHTEXT 277 %token DOCUMENT 278 SECTION 279 %token BROWSE 280 TYPE 281 FORMAT 282 /* classifiers */ %token LIST 283 SORTEDLIST 284 SECTIONLIST 285 SORTEDSECTIONLIST 286 %token DATELIST 287 /* formats */ %token ICONLINK 288 TEXTLINK 289 /* layouts */ %token DOCUMENTIMAGES 290 DOCUMENTHEADER 291 DOCUMENTTEXT 292 %token DOCUMENTBUTTONS 293 DOCUMENTARROWSBOTTOM 294 /* all other text */ %token DATA 295 %type zserver zserverlist %type port %type icon smallicon lang name %type about aboutLang aboutList %% /* grammar */ z3950 : version zserverlist {zserver_list=$2;} | version {zserver_list=NULL;} /* if all commented out or none... */ version : GSDLVERSION {;} | {fprintf(errfile,"No version - not GSDL config file?\n");return(1);} zserverlist : zserverlist zserver {if ($2!=NULL) {$2->next=$1;$$=$2;}} | zserver ; zserver : DATA DATA port DATA name icon smallicon about { if (YYRECOVERING) {$$=NULL;YYRECOVERING=0;} else { if(($$=malloc(sizeof(struct z3950cfg)))==NULL) { fprintf(errfile,"malloc failed\n"); return(1); } $$->shortname=$1; $$->hostname=$2; $$->port=$3; $$->dbname=$4; $$->longname=$5; $$->icon=$6; $$->smallicon=$7; $$->about=$8; $$->next=NULL; } } | error {$$=NULL; fprintf(errfile,"discarding zserver (line %d)\n",lineno);} ; name : STRING {;} | {errormsg("Database name needs to be followed by a short " "descriptive name (enclosed in \" marks)"); $$=NULL; YYRECOVERING=1;} /* we should scrap this server */ port : ':' DATA {$$=atoi($2);} | {$$=210;} /* default z39.50 server port */ ; icon : ICON STRING {$$=$2;} | ICON DATA {$$=$2; errormsg("Icon must be enclosed in quotes"); yylex();yylex();} | {$$=NULL;} smallicon : SMALLICON STRING {$$=$2;} | SMALLICON DATA {$$=$2; /* this is because of the ':' */ errormsg("Smallicon must be enclosed in quotes.\n"); yylex();yylex(); } | {$$=NULL;} about : aboutList {defLanguage=0;} | {$$=NULL;} aboutList : aboutLang {;} /* note this action reverses the order of the list */ | aboutList aboutLang {$$=$2;$2->next=$1;} aboutLang : ABOUT lang STRING { if(($$=malloc(sizeof(struct z3950aboutlist))) ==NULL) { fprintf(errfile,"Malloc failed\n"); return(1); } $$->lang=$2; $$->text=$3; $$->next=NULL; } | ABOUT STRING { if (defLanguage) { fprintf(errfile,"warning: (line %d): already have a default language in config file\n",lineno); } else defLanguage=1; if(($$=malloc(sizeof(struct z3950aboutlist))) ==NULL) { fprintf(errfile,"Malloc failed\n"); return(1); } $$->lang=NULL; /* default lang... */ $$->text=$2; $$->next=NULL; } /* this can only happen once (default lang) */ /* languages should be done using a lookup, rather than hard-coding them as tokens. Also '_' token for en_BR */ lang : DATA '_' DATA { $$=malloc(strlen($1)+strlen($3)+1); strncpy($$,$1,strlen($1)); $$[strlen($1)]='_'; strncpy($$+strlen($1)+1,$3,strlen($3)); free($1);free($3); } | DATA {;} /*lang '_' DATA {;} */ /* | EN {;} | FR {;} | MI {;} | ZH {;} | DE {;} | DATA {errormsg("unknown language");}*/ | error {errormsg("missing language");} /*documentHeader : DOCUMENTHEADER STRING {;} | {;} documentText : DOCUMENTTEXT STRING {;} | {;} */ %% /*int strncasecmp (const char *, const char *,size_t);*/ int yyerror(char *string) { fprintf(errfile,"Parse error (line %d) near \n\"%s\"<---:%s\n",lineno, yylval.string,string); return(1); } void errormsg(char *str) { fprintf(errfile,"Err (line %d, near \"%s\"): %s.\n",lineno, yylval.string,str); } /* * int main (int argc, char *argv[]) { if (argc==2) if (argv[1][0]=='-'&&argv[1][1]=='d') yydebug=1; yyparse(); return(0); } * */