Package: devscripts Version: 2.10.35lenny3 Severity: normal --- Please enter the report below this line. --- licensecheck failed to detect the GPL license in gyachi's lib/parsecfg.* because it used this style of framing:
/**************/ /* text here */ /**************/ After converting to the following format the license was correctly detected: /************** * text here * **************/ Sample files (pristine and modified) are attached. --- System information. --- Architecture: amd64 Kernel: Linux 2.6.29-rc7-heidi Debian Release: 5.0 500 stable snapshot.debian.net 500 stable security.debian.org 500 stable ftp.ro.debian.org 10 unstable ftp.ro.debian.org 1 experimental ftp.ro.debian.org --- Package information. --- Depends (Version) | Installed =======================-+-=========== dpkg-dev | 1.14.25 perl | 5.10.0-19 libc6 (>= 2.7-1) | 2.7-18 --- Output from package bug script --- -- Regards, EddyP ============================================= "Imagination is more important than knowledge" A.Einstein
/*************************************************************************** * * * parsecfg - a library for parsing a configuration file * * Copyright (C) 1999 Yuuki NINOMIYA, g...@smn.enjoy.ne.jp * * * * 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, 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., 59 Temple Place - Suite 330, * * Boston, MA 02111-1307, USA. * * * ***************************************************************************/ /* parsecfg Ver 3.0.3 */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <errno.h> #include "parsecfg.h" /* proto type declaration of private functions */ void cfgFatalFunc(cfgErrorCode,char *,int,char *); void (*cfgFatal)(cfgErrorCode,char *,int,char *) = cfgFatalFunc; /* default error handler */ int parse_simple(char *file,FILE *fp,char *ptr,cfgStruct cfg[],int *line); void parse_values_between_braces(char *file,FILE *fp,char *parameter,cfgStruct cfg[],int *line,cfgFileType type,int section); char *parse_word(char *ptr,char **word,cfgKeywordValue word_type); int store_value(cfgStruct cfg[],char *parameter,char *value,cfgFileType type,int section); int parse_ini(char *file,FILE *fp,char *ptr,cfgStruct cfg[],int *line,int *section); int alloc_for_new_section(cfgStruct cfg[],int *section); char *get_single_line_without_first_spaces(FILE *fp,char **gotstr,int *line); char *rm_first_spaces(char *ptr); char *dynamic_fgets(FILE *fp); /* static variables */ char **parsecfg_section_name=NULL; int parsecfg_maximum_section; /*************************************************************/ /* PUBLIC FUCNCTIONS */ /*************************************************************/ /* -------------------------------------------------- NAME cfgSetFatalFunc FUNCTION handle new error handler INPUT f ... pointer to new error handler OUTPUT none -------------------------------------------------- */ void cfgSetFatalFunc(void (*f)(cfgErrorCode,char *,int,char *)) { cfgFatal = f; } /* -------------------------------------------------- NAME cfgParse FUNCTION parse a configuration file (main function) INPUT file ... name of the configuration file cfg .... array of possible variables type ... type of the configuration file + CFG_SIMPLE .. simple 1:1 + CFG_INI ..... like Windows INI file OUTPUT the maximum sections (if type==CFG_INI then always return 0) -------------------------------------------------- */ int cfgParse(char *file,cfgStruct cfg[],cfgFileType type) { char *line_buf; char *ptr; int line=0; FILE *fp; int error_code; int max_cfg=-1; fp=fopen(file,"r"); if(fp==NULL){ cfgFatal(CFG_OPEN_FAIL,file,0,NULL); } while((ptr=get_single_line_without_first_spaces(fp,&line_buf,&line))!=NULL){ switch(type){ case CFG_SIMPLE: if((error_code=parse_simple(file,fp,ptr,cfg,&line))!=CFG_NO_ERROR){ cfgFatal(error_code,file,line,line_buf); } break; case CFG_INI: if((error_code=parse_ini(file,fp,ptr,cfg,&line,&max_cfg))!=CFG_NO_ERROR){ cfgFatal(error_code,file,line,line_buf); } break; default: cfgFatal(CFG_INTERNAL_ERROR,file,0,NULL); } free(line_buf); } parsecfg_maximum_section=max_cfg+1; return(parsecfg_maximum_section); } /* -------------------------------------------------- NAME cfgSectionNameToNumber FUNCTION convert section name to number INPUT name ... section name OUTPUT section number (0,1,2,...) if no matching, return -1 -------------------------------------------------- */ int cfgSectionNameToNumber(const char *name) { int i; for(i=0;i<parsecfg_maximum_section;i++){ if(strcasecmp(name,parsecfg_section_name[i])==0){ return(i); } } return(-1); } /* -------------------------------------------------- NAME cfgSectionNumberToName FUNCTION convert section number to name INPUT num ... section number (0,1,2,...) OUTPUT pointer to section name if no section, return NULL -------------------------------------------------- */ char *cfgSectionNumberToName(int num) { if(num>parsecfg_maximum_section-1 || num<0){ return(NULL); } return(parsecfg_section_name[num]); } /*************************************************************/ /* PRIVATE FUCNCTIONS */ /*************************************************************/ /* -------------------------------------------------- NAME cfgFatalFunc FUNCTION error handler INPUT error_code ... reason of error file ......... the configuration file line ......... line number causing error str .......... strings at above line OUTPUT never return -------------------------------------------------- */ void cfgFatalFunc(cfgErrorCode error_code,char *file,int line,char *str) { switch(error_code){ case CFG_OPEN_FAIL: fprintf(stderr,"Configuration file `%s' is not found.\n",file); return; /* changed, PhrozenSmoke, dont exit on this */ case CFG_SYNTAX_ERROR: fprintf(stderr,"%s(%d): %s\nsyntax error\n",file,line,str); return; /* changed, PhrozenSmoke, dont exit on this */ case CFG_WRONG_PARAMETER: fprintf(stderr,"%s(%d): %s\nunrecognized parameter\n",file,line,str); break; case CFG_INTERNAL_ERROR: fprintf(stderr,"%s(%d): %s\ninternal error\n",file,line,str); break; case CFG_INVALID_NUMBER: fprintf(stderr,"%s(%d): %s\ninvalid number\n",file,line,str); break; case CFG_OUT_OF_RANGE: fprintf(stderr,"%s(%d): %s\nout of range\n",file,line,str); break; case CFG_MEM_ALLOC_FAIL: fprintf(stderr,"%s(%d): %s\nCannot allocate memory.\n",file,line,str); break; case CFG_BOOL_ERROR: fprintf(stderr,"%s(%d): %s\nIt must be specified TRUE or FALSE.\n",file,line,str); break; case CFG_USED_SECTION: fprintf(stderr,"%s(%d): %s\nThe section name is already used.\n",file,line,str); break; default: fprintf(stderr,"%s(%d): %s\nunexplained error\n",file,line,str); break; } exit(1); } /* -------------------------------------------------- NAME parse_simple FUNCTION parse as simple 1:1 file INPUT file .. name of the configuration file fp .... file pointer to the configuration file ptr ... pointer of current parsing cfg ... array of possible variables line .. pointer to current working line OUTPUT error code (no error is CFG_NO_ERROR) -------------------------------------------------- */ int parse_simple(char *file,FILE *fp,char *ptr,cfgStruct cfg[],int *line) { char *parameter; char *value; int error_code; if((ptr=parse_word(ptr,¶meter,CFG_PARAMETER))==NULL){ return(CFG_SYNTAX_ERROR); } if(*ptr=='{'){ ptr=rm_first_spaces(ptr+1); if(*ptr!='\0' && *ptr!='#'){ return(CFG_SYNTAX_ERROR); } parse_values_between_braces(file,fp,parameter,cfg,line,CFG_SIMPLE,0); }else{ if((ptr=parse_word(ptr,&value,CFG_VALUE))==NULL){ return(CFG_SYNTAX_ERROR); } if((error_code=store_value(cfg,parameter,value,CFG_SIMPLE,0))!=CFG_NO_ERROR){ return(error_code); } free(parameter); free(value); } return(CFG_NO_ERROR); } /* -------------------------------------------------- NAME parse_word FUNCTION parse a word INPUT ptr ... pointer of current parsing word .. pointer of pointer for parsed word (dynamic allocating) word_type ... what word type parse as + CFG_PARAMETER ... parameter + CFG_VALUE ....... value + CFG_SECTION ..... section OUTPUT new current pointer (if syntax error, return NULL) -------------------------------------------------- */ char *parse_word(char *ptr,char **word,cfgKeywordValue word_type) { int len=0; cfgQuote quote_flag; switch(*ptr){ case '\"': quote_flag=CFG_DOUBLE_QUOTE; ptr++; break; case '\'': quote_flag=CFG_SINGLE_QUOTE; ptr++; break; default: quote_flag=CFG_NO_QUOTE; break; } for(;;){ if(quote_flag==CFG_NO_QUOTE){ if(*(ptr+len)==' ' || *(ptr+len)=='\t' || *(ptr+len)=='\0' || *(ptr+len)=='#' || (*(ptr+len)=='=' && word_type==CFG_PARAMETER) || (*(ptr+len)==']' && word_type==CFG_SECTION)){ break; } }else if(quote_flag==CFG_DOUBLE_QUOTE){ if(*(ptr+len)=='\"'){ /* Patched by PhrozenSmoke: Allow quotation marks inside the configuration file values, so status messages, auto-away messages, etc. can have quotes in them! */ if (word_type==CFG_VALUE) { len++; if (! strrchr(ptr+len,'\"')) {len--; break;} /* last quote, so stop */ else {continue;} /* not last quote mark, so keep going */ } break; } }else if(quote_flag==CFG_SINGLE_QUOTE){ if(*(ptr+len)=='\''){ /* Patched by PhrozenSmoke: Allow apostrophe marks inside the configuration file values, so status messages, auto-away messages, etc. can have apostrophe in them! */ if (word_type==CFG_VALUE) { len++; if (! strrchr(ptr+len,'\'')) {len--; break;} /* last apostrophe, so stop */ else {continue;} /* not last apostrophe mark, so keep going */ } break; } } if(*(ptr+len)=='\0'){ return(NULL); } len++; } if((*word=malloc(len+1))==NULL){ cfgFatalFunc(CFG_MEM_ALLOC_FAIL,"unknown",0,""); } strncpy(*word,ptr,len); *(*word+len)='\0'; ptr+=(len+(quote_flag==CFG_NO_QUOTE ? 0 : 1)); ptr=rm_first_spaces(ptr); switch(word_type){ case CFG_PARAMETER: if(*ptr!='='){ return(NULL); } ptr++; ptr=rm_first_spaces(ptr); break; case CFG_VALUE: if(*ptr!='\0' && *ptr!='#'){ return(NULL); } break; case CFG_SECTION: if(*ptr!=']'){ return(NULL); } break; default: return(NULL); } return(ptr); } /* -------------------------------------------------- NAME store_value FUNCTION store the value according to cfg INPUT cfg ......... array of possible variables parameter ... parameter value ....... value type ........ type of the configuration file section ..... section number OUTPUT error code -------------------------------------------------- */ int store_value(cfgStruct cfg[],char *parameter,char *value,cfgFileType type,int section) { int num; long tmp = 0; unsigned long utmp; char *endptr; char *strptr; cfgList *listptr; char **valptr; for(num=0;cfg[num].type!=CFG_END;num++){ if(strcasecmp(parameter,cfg[num].parameterName)==0){ errno=0; switch(cfg[num].type){ case CFG_BOOL: if(strcasecmp(value,"TRUE")==0 || strcasecmp(value,"YES")==0 || strcasecmp(value,"T")==0 || strcasecmp(value,"Y")==0 || strcasecmp(value,"1")==0){ if(type==CFG_INI){ *(*(int **)(cfg[num].value)+section)=1; }else{ *(int *)(cfg[num].value)=1; } return(CFG_NO_ERROR); }else if(strcasecmp(value,"FALSE")==0 || strcasecmp(value,"NO")==0 || strcasecmp(value,"F")==0 || strcasecmp(value,"N")==0 || strcasecmp(value,"0")==0){ if(type==CFG_INI){ *(*(int **)(cfg[num].value)+section)=0; }else{ *(int *)(cfg[num].value)=0; } return(CFG_NO_ERROR); } return(CFG_BOOL_ERROR); case CFG_STRING: if(type==CFG_INI){ valptr=(*(char ***)(cfg[num].value)+section); }else{ valptr=(char **)(cfg[num].value); } if (*valptr) { free(*valptr); } if ((*valptr=strdup(value)) == NULL) { return(CFG_MEM_ALLOC_FAIL); } return(CFG_NO_ERROR); case CFG_INT: tmp=strtol(value, &endptr, 0); if(*endptr){ return(CFG_INVALID_NUMBER); } if(errno==ERANGE || tmp>INT_MAX || tmp<INT_MIN){ return(CFG_OUT_OF_RANGE); } if(type==CFG_INI){ *(*(int **)(cfg[num].value)+section)=tmp; }else{ *(int *)(cfg[num].value)=tmp; } return(CFG_NO_ERROR); case CFG_UINT: utmp=strtoul(value,&endptr,10); if(*endptr){ return(CFG_INVALID_NUMBER); } if(errno==ERANGE || tmp>UINT_MAX){ return(CFG_OUT_OF_RANGE); } if(type==CFG_INI){ *(*(unsigned int **)(cfg[num].value)+section)=utmp; }else{ *(unsigned int *)(cfg[num].value)=utmp; } return(CFG_NO_ERROR); case CFG_LONG: tmp=strtol(value,&endptr,10); if(*endptr){ return(CFG_INVALID_NUMBER); } if(errno==ERANGE){ return(CFG_OUT_OF_RANGE); } if(type==CFG_INI){ *(*(long **)(cfg[num].value)+section)=tmp; }else{ *(long *)(cfg[num].value)=tmp; } return(CFG_NO_ERROR); case CFG_ULONG: utmp=strtoul(value,&endptr,10); if(*endptr){ return(CFG_INVALID_NUMBER); } if(errno==ERANGE){ return(CFG_OUT_OF_RANGE); } if(type==CFG_INI){ *(*(unsigned long **)(cfg[num].value)+section)=utmp; }else{ *(unsigned long *)(cfg[num].value)=utmp; } return(CFG_NO_ERROR); case CFG_STRING_LIST: if(type==CFG_INI){ listptr=*(*(cfgList ***)(cfg[num].value)+section); }else{ listptr=*(cfgList **)(cfg[num].value); } if(listptr!=NULL){ while(listptr->next!=NULL){ listptr=listptr->next; } if((listptr=listptr->next=malloc(sizeof(cfgList)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } }else{ if((listptr=malloc(sizeof(cfgList)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } if(type==CFG_INI){ *(*(cfgList ***)(cfg[num].value)+section)=listptr; }else{ *(cfgList **)(cfg[num].value)=listptr; } } if((strptr=malloc(strlen(value)+1))==NULL){ return(CFG_MEM_ALLOC_FAIL); } strcpy(strptr,value); listptr->str=strptr; listptr->next=NULL; return(CFG_NO_ERROR); default: return(CFG_INTERNAL_ERROR); } } } /* Chris Pinkham, 11/5/2002. don't abort loading file just because we */ /* found a parameter we don't like, just */ /* ignore it and load the rest. */ return(CFG_NO_ERROR); return(CFG_WRONG_PARAMETER); } /* -------------------------------------------------- NAME parse_values_between_braces FUNCTION parse values between braces INPUT file ....... name of the configuraion file fp ......... file pointer to the configuration file parameter .. parameter cfg ........ array of possible variables line ....... pointer to current working line OUTPUT none -------------------------------------------------- */ void parse_values_between_braces(char *file,FILE *fp,char *parameter,cfgStruct cfg[],int *line,cfgFileType type,int section) { char *line_buf; char *value; char *ptr; int error_code; while((ptr=get_single_line_without_first_spaces(fp,&line_buf,line))!=NULL){ if(*ptr=='}'){ ptr=rm_first_spaces(ptr+1); if(*ptr!='\0' && *ptr!='#'){ cfgFatal(CFG_SYNTAX_ERROR,file,*line,line_buf); } free(line_buf); return; } if(parse_word(ptr,&value,CFG_VALUE)==NULL){ cfgFatal(CFG_SYNTAX_ERROR,file,*line,line_buf); } if((error_code=store_value(cfg,parameter,value,type,section))!=CFG_NO_ERROR){ cfgFatal(error_code,file,*line,line_buf); } free(line_buf); free(value); } } /* -------------------------------------------------- NAME parse_ini FUNCTION parse the configuration file as like Windows INI file INPUT file .. name of the configuration file fp .... file pointer to the configuration file ptr ... pointer of current parsing cfg ... array of possible variables line .. pointer to current working line section ... pointer to current section number OUTPUT error code (no error is CFG_NO_ERROR) -------------------------------------------------- */ int parse_ini(char *file,FILE *fp,char *ptr,cfgStruct cfg[],int *line,int *section) { char *parameter; char *value; int error_code; int i; if(*ptr=='['){ if((error_code=alloc_for_new_section(cfg,section))!=CFG_NO_ERROR){ return(error_code); } ptr=rm_first_spaces(ptr+1); parsecfg_section_name=realloc(parsecfg_section_name,sizeof(char *)*(*section+1)); if((ptr=parse_word(ptr,&parsecfg_section_name[*section],CFG_SECTION))==NULL){ return(CFG_SYNTAX_ERROR); } for(i=0;i<*section;i++){ if(strcasecmp(parsecfg_section_name[*section],parsecfg_section_name[i])==0){ return(CFG_USED_SECTION); } } ptr=rm_first_spaces(ptr+1); if(*ptr!='\0' && *ptr!='#'){ return(CFG_SYNTAX_ERROR); } return(CFG_NO_ERROR); } if((ptr=parse_word(ptr,¶meter,CFG_PARAMETER))==NULL){ return(CFG_SYNTAX_ERROR); } if(*ptr=='{'){ ptr=rm_first_spaces(ptr+1); if(*ptr!='\0' && *ptr!='#'){ return(CFG_SYNTAX_ERROR); } parse_values_between_braces(file,fp,parameter,cfg,line,CFG_INI,*section); }else{ if((ptr=parse_word(ptr,&value,CFG_VALUE))==NULL){ return(CFG_SYNTAX_ERROR); } if((error_code=store_value(cfg,parameter,value,CFG_INI,*section))!=CFG_NO_ERROR){ return(error_code); } free(parameter); free(value); } return(CFG_NO_ERROR); } /* -------------------------------------------------- NAME alloc_for_new_section FUNCTION allocate memory for new section INPUT cfg ....... array of possible variables section ... pointer to current section number OUTPUT error code -------------------------------------------------- */ int alloc_for_new_section(cfgStruct cfg[],int *section) { int num; void *ptr; (*section)++; for(num=0;cfg[num].type!=CFG_END;num++){ switch(cfg[num].type){ case CFG_BOOL: case CFG_INT: case CFG_UINT: if(*section==0){ *(int **)(cfg[num].value)=NULL; } if((ptr=realloc(*(int **)(cfg[num].value),sizeof(int)*(*section+1)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } *(int **)(cfg[num].value)=ptr; if(cfg[num].type==CFG_BOOL){ *(*((int **)(cfg[num].value))+*section)=-1; }else{ *(*((int **)(cfg[num].value))+*section)=0; } break; case CFG_LONG: case CFG_ULONG: if(*section==0){ *(long **)(cfg[num].value)=NULL; } if((ptr=realloc(*(long **)(cfg[num].value),sizeof(long)*(*section+1)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } *(long **)(cfg[num].value)=ptr; *(*((long **)(cfg[num].value))+*section)=0; break; case CFG_STRING: if(*section==0){ *(char ***)(cfg[num].value)=NULL; } if((ptr=realloc(*(char ***)(cfg[num].value),sizeof(char *)*(*section+1)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } *(char ***)(cfg[num].value)=ptr; *(*(char ***)(cfg[num].value)+*section)=NULL; break; case CFG_STRING_LIST: if(*section==0){ *(cfgList ***)(cfg[num].value)=NULL; } if((ptr=realloc(*(cfgList ***)(cfg[num].value),sizeof(cfgList *)*(*section+1)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } *(cfgList ***)(cfg[num].value)=ptr; *(*(cfgList ***)(cfg[num].value)+*section)=NULL; break; default: return(CFG_INTERNAL_ERROR); } } return(CFG_NO_ERROR); } /* -------------------------------------------------- NAME rm_first_spaces FUNCTION remove lead-off spaces and tabs in the string INPUT ptr ... pointer to string OUTPUT new poniter after removing -------------------------------------------------- */ char *rm_first_spaces(char *ptr) { while(*ptr==' ' || *ptr=='\t'){ ptr++; } return(ptr); } /* -------------------------------------------------- NAME get_single_line_without_first_spaces FUNCTION get a single line without lead-off spaces and tabs from file INPUT fp ....... file pointer gotptr ... pointer stored got string line ..... pointer to line number OUTPUT new poniter after removing -------------------------------------------------- */ char *get_single_line_without_first_spaces(FILE *fp,char **gotstr,int *line) { char *ptr; for(;;){ if((*gotstr=dynamic_fgets(fp))==NULL){ return(NULL); } (*line)++; ptr=rm_first_spaces(*gotstr); if(*ptr!='#' && *ptr!='\0'){ return(ptr); } free(*gotstr); } } /* -------------------------------------------------- NAME dynamic_fgets FUNCTION fgets with dynamic allocated memory INPUT fp ... file pointer OUTPUT pointer to got strings -------------------------------------------------- */ char *dynamic_fgets(FILE *fp) { char *ptr; char temp[128]; int i; ptr=malloc(1); if(ptr==NULL){ cfgFatalFunc(CFG_MEM_ALLOC_FAIL,"unknown",0,""); } *ptr='\0'; for(i=0;;i++){ if(fgets(temp,128,fp)==NULL){ free(ptr); return(NULL); } ptr=realloc(ptr,127*(i+1)+1); if(ptr==NULL){ cfgFatalFunc(CFG_MEM_ALLOC_FAIL,"unknown",0,""); } strcat(ptr,temp); if(strchr(temp,'\n')!=NULL){ *strchr(ptr,'\n')='\0'; return(ptr); } } }
/*************************************************************************** * * * parsecfg - a library for parsing a configuration file * * Copyright (C) 1999 Yuuki NINOMIYA, g...@smn.enjoy.ne.jp * * * * 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, 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., 59 Temple Place - Suite 330, * * Boston, MA 02111-1307, USA. * * * ***************************************************************************/ #ifndef PARSECFG_H_INCLUDED #define PARSECFG_H_INCLUDED /* error code */ typedef enum{ CFG_NO_ERROR, CFG_OPEN_FAIL, CFG_SYNTAX_ERROR, CFG_WRONG_PARAMETER, CFG_INTERNAL_ERROR, CFG_INVALID_NUMBER, CFG_OUT_OF_RANGE, CFG_MEM_ALLOC_FAIL, CFG_BOOL_ERROR, CFG_USED_SECTION, } cfgErrorCode; /* type of the configuration file */ typedef enum{ CFG_SIMPLE, CFG_INI, } cfgFileType; /* constants for recognized value types */ typedef enum{ CFG_END, CFG_BOOL, CFG_STRING, CFG_INT, CFG_UINT, CFG_LONG, CFG_ULONG, CFG_STRING_LIST, } cfgValueType; typedef enum{ CFG_PARAMETER, CFG_VALUE, CFG_SECTION, } cfgKeywordValue; typedef enum{ CFG_NO_QUOTE, CFG_SINGLE_QUOTE, CFG_DOUBLE_QUOTE, } cfgQuote; typedef struct{ char *parameterName; cfgValueType type; void *value; } cfgStruct; typedef struct cfglist *cfgListPtr; typedef struct cfglist{ char *str; cfgListPtr next; } cfgList; /* proto type declaration of public functions */ void cfgSetFatalFunc(void (*f)(cfgErrorCode,char *,int,char *)); int cfgParse(char *file,cfgStruct cfg[],cfgFileType type); int cfgSectionNameToNumber(const char *name); char *cfgSectionNumberToName(int num); #endif /* PARSECFG_H_INCLUDED */
/***************************************************************************/ /* */ /* parsecfg - a library for parsing a configuration file */ /* Copyright (C) 1999 Yuuki NINOMIYA, g...@smn.enjoy.ne.jp */ /* */ /* 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, 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., 59 Temple Place - Suite 330, */ /* Boston, MA 02111-1307, USA. */ /* */ /***************************************************************************/ /* parsecfg Ver 3.0.3 */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <errno.h> #include "parsecfg.h" /* proto type declaration of private functions */ void cfgFatalFunc(cfgErrorCode,char *,int,char *); void (*cfgFatal)(cfgErrorCode,char *,int,char *) = cfgFatalFunc; /* default error handler */ int parse_simple(char *file,FILE *fp,char *ptr,cfgStruct cfg[],int *line); void parse_values_between_braces(char *file,FILE *fp,char *parameter,cfgStruct cfg[],int *line,cfgFileType type,int section); char *parse_word(char *ptr,char **word,cfgKeywordValue word_type); int store_value(cfgStruct cfg[],char *parameter,char *value,cfgFileType type,int section); int parse_ini(char *file,FILE *fp,char *ptr,cfgStruct cfg[],int *line,int *section); int alloc_for_new_section(cfgStruct cfg[],int *section); char *get_single_line_without_first_spaces(FILE *fp,char **gotstr,int *line); char *rm_first_spaces(char *ptr); char *dynamic_fgets(FILE *fp); /* static variables */ char **parsecfg_section_name=NULL; int parsecfg_maximum_section; /*************************************************************/ /* PUBLIC FUCNCTIONS */ /*************************************************************/ /* -------------------------------------------------- NAME cfgSetFatalFunc FUNCTION handle new error handler INPUT f ... pointer to new error handler OUTPUT none -------------------------------------------------- */ void cfgSetFatalFunc(void (*f)(cfgErrorCode,char *,int,char *)) { cfgFatal = f; } /* -------------------------------------------------- NAME cfgParse FUNCTION parse a configuration file (main function) INPUT file ... name of the configuration file cfg .... array of possible variables type ... type of the configuration file + CFG_SIMPLE .. simple 1:1 + CFG_INI ..... like Windows INI file OUTPUT the maximum sections (if type==CFG_INI then always return 0) -------------------------------------------------- */ int cfgParse(char *file,cfgStruct cfg[],cfgFileType type) { char *line_buf; char *ptr; int line=0; FILE *fp; int error_code; int max_cfg=-1; fp=fopen(file,"r"); if(fp==NULL){ cfgFatal(CFG_OPEN_FAIL,file,0,NULL); } while((ptr=get_single_line_without_first_spaces(fp,&line_buf,&line))!=NULL){ switch(type){ case CFG_SIMPLE: if((error_code=parse_simple(file,fp,ptr,cfg,&line))!=CFG_NO_ERROR){ cfgFatal(error_code,file,line,line_buf); } break; case CFG_INI: if((error_code=parse_ini(file,fp,ptr,cfg,&line,&max_cfg))!=CFG_NO_ERROR){ cfgFatal(error_code,file,line,line_buf); } break; default: cfgFatal(CFG_INTERNAL_ERROR,file,0,NULL); } free(line_buf); } parsecfg_maximum_section=max_cfg+1; return(parsecfg_maximum_section); } /* -------------------------------------------------- NAME cfgSectionNameToNumber FUNCTION convert section name to number INPUT name ... section name OUTPUT section number (0,1,2,...) if no matching, return -1 -------------------------------------------------- */ int cfgSectionNameToNumber(const char *name) { int i; for(i=0;i<parsecfg_maximum_section;i++){ if(strcasecmp(name,parsecfg_section_name[i])==0){ return(i); } } return(-1); } /* -------------------------------------------------- NAME cfgSectionNumberToName FUNCTION convert section number to name INPUT num ... section number (0,1,2,...) OUTPUT pointer to section name if no section, return NULL -------------------------------------------------- */ char *cfgSectionNumberToName(int num) { if(num>parsecfg_maximum_section-1 || num<0){ return(NULL); } return(parsecfg_section_name[num]); } /*************************************************************/ /* PRIVATE FUCNCTIONS */ /*************************************************************/ /* -------------------------------------------------- NAME cfgFatalFunc FUNCTION error handler INPUT error_code ... reason of error file ......... the configuration file line ......... line number causing error str .......... strings at above line OUTPUT never return -------------------------------------------------- */ void cfgFatalFunc(cfgErrorCode error_code,char *file,int line,char *str) { switch(error_code){ case CFG_OPEN_FAIL: fprintf(stderr,"Configuration file `%s' is not found.\n",file); return; /* changed, PhrozenSmoke, dont exit on this */ case CFG_SYNTAX_ERROR: fprintf(stderr,"%s(%d): %s\nsyntax error\n",file,line,str); return; /* changed, PhrozenSmoke, dont exit on this */ case CFG_WRONG_PARAMETER: fprintf(stderr,"%s(%d): %s\nunrecognized parameter\n",file,line,str); break; case CFG_INTERNAL_ERROR: fprintf(stderr,"%s(%d): %s\ninternal error\n",file,line,str); break; case CFG_INVALID_NUMBER: fprintf(stderr,"%s(%d): %s\ninvalid number\n",file,line,str); break; case CFG_OUT_OF_RANGE: fprintf(stderr,"%s(%d): %s\nout of range\n",file,line,str); break; case CFG_MEM_ALLOC_FAIL: fprintf(stderr,"%s(%d): %s\nCannot allocate memory.\n",file,line,str); break; case CFG_BOOL_ERROR: fprintf(stderr,"%s(%d): %s\nIt must be specified TRUE or FALSE.\n",file,line,str); break; case CFG_USED_SECTION: fprintf(stderr,"%s(%d): %s\nThe section name is already used.\n",file,line,str); break; default: fprintf(stderr,"%s(%d): %s\nunexplained error\n",file,line,str); break; } exit(1); } /* -------------------------------------------------- NAME parse_simple FUNCTION parse as simple 1:1 file INPUT file .. name of the configuration file fp .... file pointer to the configuration file ptr ... pointer of current parsing cfg ... array of possible variables line .. pointer to current working line OUTPUT error code (no error is CFG_NO_ERROR) -------------------------------------------------- */ int parse_simple(char *file,FILE *fp,char *ptr,cfgStruct cfg[],int *line) { char *parameter; char *value; int error_code; if((ptr=parse_word(ptr,¶meter,CFG_PARAMETER))==NULL){ return(CFG_SYNTAX_ERROR); } if(*ptr=='{'){ ptr=rm_first_spaces(ptr+1); if(*ptr!='\0' && *ptr!='#'){ return(CFG_SYNTAX_ERROR); } parse_values_between_braces(file,fp,parameter,cfg,line,CFG_SIMPLE,0); }else{ if((ptr=parse_word(ptr,&value,CFG_VALUE))==NULL){ return(CFG_SYNTAX_ERROR); } if((error_code=store_value(cfg,parameter,value,CFG_SIMPLE,0))!=CFG_NO_ERROR){ return(error_code); } free(parameter); free(value); } return(CFG_NO_ERROR); } /* -------------------------------------------------- NAME parse_word FUNCTION parse a word INPUT ptr ... pointer of current parsing word .. pointer of pointer for parsed word (dynamic allocating) word_type ... what word type parse as + CFG_PARAMETER ... parameter + CFG_VALUE ....... value + CFG_SECTION ..... section OUTPUT new current pointer (if syntax error, return NULL) -------------------------------------------------- */ char *parse_word(char *ptr,char **word,cfgKeywordValue word_type) { int len=0; cfgQuote quote_flag; switch(*ptr){ case '\"': quote_flag=CFG_DOUBLE_QUOTE; ptr++; break; case '\'': quote_flag=CFG_SINGLE_QUOTE; ptr++; break; default: quote_flag=CFG_NO_QUOTE; break; } for(;;){ if(quote_flag==CFG_NO_QUOTE){ if(*(ptr+len)==' ' || *(ptr+len)=='\t' || *(ptr+len)=='\0' || *(ptr+len)=='#' || (*(ptr+len)=='=' && word_type==CFG_PARAMETER) || (*(ptr+len)==']' && word_type==CFG_SECTION)){ break; } }else if(quote_flag==CFG_DOUBLE_QUOTE){ if(*(ptr+len)=='\"'){ /* Patched by PhrozenSmoke: Allow quotation marks inside the configuration file values, so status messages, auto-away messages, etc. can have quotes in them! */ if (word_type==CFG_VALUE) { len++; if (! strrchr(ptr+len,'\"')) {len--; break;} /* last quote, so stop */ else {continue;} /* not last quote mark, so keep going */ } break; } }else if(quote_flag==CFG_SINGLE_QUOTE){ if(*(ptr+len)=='\''){ /* Patched by PhrozenSmoke: Allow apostrophe marks inside the configuration file values, so status messages, auto-away messages, etc. can have apostrophe in them! */ if (word_type==CFG_VALUE) { len++; if (! strrchr(ptr+len,'\'')) {len--; break;} /* last apostrophe, so stop */ else {continue;} /* not last apostrophe mark, so keep going */ } break; } } if(*(ptr+len)=='\0'){ return(NULL); } len++; } if((*word=malloc(len+1))==NULL){ cfgFatalFunc(CFG_MEM_ALLOC_FAIL,"unknown",0,""); } strncpy(*word,ptr,len); *(*word+len)='\0'; ptr+=(len+(quote_flag==CFG_NO_QUOTE ? 0 : 1)); ptr=rm_first_spaces(ptr); switch(word_type){ case CFG_PARAMETER: if(*ptr!='='){ return(NULL); } ptr++; ptr=rm_first_spaces(ptr); break; case CFG_VALUE: if(*ptr!='\0' && *ptr!='#'){ return(NULL); } break; case CFG_SECTION: if(*ptr!=']'){ return(NULL); } break; default: return(NULL); } return(ptr); } /* -------------------------------------------------- NAME store_value FUNCTION store the value according to cfg INPUT cfg ......... array of possible variables parameter ... parameter value ....... value type ........ type of the configuration file section ..... section number OUTPUT error code -------------------------------------------------- */ int store_value(cfgStruct cfg[],char *parameter,char *value,cfgFileType type,int section) { int num; long tmp = 0; unsigned long utmp; char *endptr; char *strptr; cfgList *listptr; char **valptr; for(num=0;cfg[num].type!=CFG_END;num++){ if(strcasecmp(parameter,cfg[num].parameterName)==0){ errno=0; switch(cfg[num].type){ case CFG_BOOL: if(strcasecmp(value,"TRUE")==0 || strcasecmp(value,"YES")==0 || strcasecmp(value,"T")==0 || strcasecmp(value,"Y")==0 || strcasecmp(value,"1")==0){ if(type==CFG_INI){ *(*(int **)(cfg[num].value)+section)=1; }else{ *(int *)(cfg[num].value)=1; } return(CFG_NO_ERROR); }else if(strcasecmp(value,"FALSE")==0 || strcasecmp(value,"NO")==0 || strcasecmp(value,"F")==0 || strcasecmp(value,"N")==0 || strcasecmp(value,"0")==0){ if(type==CFG_INI){ *(*(int **)(cfg[num].value)+section)=0; }else{ *(int *)(cfg[num].value)=0; } return(CFG_NO_ERROR); } return(CFG_BOOL_ERROR); case CFG_STRING: if(type==CFG_INI){ valptr=(*(char ***)(cfg[num].value)+section); }else{ valptr=(char **)(cfg[num].value); } if (*valptr) { free(*valptr); } if ((*valptr=strdup(value)) == NULL) { return(CFG_MEM_ALLOC_FAIL); } return(CFG_NO_ERROR); case CFG_INT: tmp=strtol(value, &endptr, 0); if(*endptr){ return(CFG_INVALID_NUMBER); } if(errno==ERANGE || tmp>INT_MAX || tmp<INT_MIN){ return(CFG_OUT_OF_RANGE); } if(type==CFG_INI){ *(*(int **)(cfg[num].value)+section)=tmp; }else{ *(int *)(cfg[num].value)=tmp; } return(CFG_NO_ERROR); case CFG_UINT: utmp=strtoul(value,&endptr,10); if(*endptr){ return(CFG_INVALID_NUMBER); } if(errno==ERANGE || tmp>UINT_MAX){ return(CFG_OUT_OF_RANGE); } if(type==CFG_INI){ *(*(unsigned int **)(cfg[num].value)+section)=utmp; }else{ *(unsigned int *)(cfg[num].value)=utmp; } return(CFG_NO_ERROR); case CFG_LONG: tmp=strtol(value,&endptr,10); if(*endptr){ return(CFG_INVALID_NUMBER); } if(errno==ERANGE){ return(CFG_OUT_OF_RANGE); } if(type==CFG_INI){ *(*(long **)(cfg[num].value)+section)=tmp; }else{ *(long *)(cfg[num].value)=tmp; } return(CFG_NO_ERROR); case CFG_ULONG: utmp=strtoul(value,&endptr,10); if(*endptr){ return(CFG_INVALID_NUMBER); } if(errno==ERANGE){ return(CFG_OUT_OF_RANGE); } if(type==CFG_INI){ *(*(unsigned long **)(cfg[num].value)+section)=utmp; }else{ *(unsigned long *)(cfg[num].value)=utmp; } return(CFG_NO_ERROR); case CFG_STRING_LIST: if(type==CFG_INI){ listptr=*(*(cfgList ***)(cfg[num].value)+section); }else{ listptr=*(cfgList **)(cfg[num].value); } if(listptr!=NULL){ while(listptr->next!=NULL){ listptr=listptr->next; } if((listptr=listptr->next=malloc(sizeof(cfgList)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } }else{ if((listptr=malloc(sizeof(cfgList)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } if(type==CFG_INI){ *(*(cfgList ***)(cfg[num].value)+section)=listptr; }else{ *(cfgList **)(cfg[num].value)=listptr; } } if((strptr=malloc(strlen(value)+1))==NULL){ return(CFG_MEM_ALLOC_FAIL); } strcpy(strptr,value); listptr->str=strptr; listptr->next=NULL; return(CFG_NO_ERROR); default: return(CFG_INTERNAL_ERROR); } } } /* Chris Pinkham, 11/5/2002. don't abort loading file just because we */ /* found a parameter we don't like, just */ /* ignore it and load the rest. */ return(CFG_NO_ERROR); return(CFG_WRONG_PARAMETER); } /* -------------------------------------------------- NAME parse_values_between_braces FUNCTION parse values between braces INPUT file ....... name of the configuraion file fp ......... file pointer to the configuration file parameter .. parameter cfg ........ array of possible variables line ....... pointer to current working line OUTPUT none -------------------------------------------------- */ void parse_values_between_braces(char *file,FILE *fp,char *parameter,cfgStruct cfg[],int *line,cfgFileType type,int section) { char *line_buf; char *value; char *ptr; int error_code; while((ptr=get_single_line_without_first_spaces(fp,&line_buf,line))!=NULL){ if(*ptr=='}'){ ptr=rm_first_spaces(ptr+1); if(*ptr!='\0' && *ptr!='#'){ cfgFatal(CFG_SYNTAX_ERROR,file,*line,line_buf); } free(line_buf); return; } if(parse_word(ptr,&value,CFG_VALUE)==NULL){ cfgFatal(CFG_SYNTAX_ERROR,file,*line,line_buf); } if((error_code=store_value(cfg,parameter,value,type,section))!=CFG_NO_ERROR){ cfgFatal(error_code,file,*line,line_buf); } free(line_buf); free(value); } } /* -------------------------------------------------- NAME parse_ini FUNCTION parse the configuration file as like Windows INI file INPUT file .. name of the configuration file fp .... file pointer to the configuration file ptr ... pointer of current parsing cfg ... array of possible variables line .. pointer to current working line section ... pointer to current section number OUTPUT error code (no error is CFG_NO_ERROR) -------------------------------------------------- */ int parse_ini(char *file,FILE *fp,char *ptr,cfgStruct cfg[],int *line,int *section) { char *parameter; char *value; int error_code; int i; if(*ptr=='['){ if((error_code=alloc_for_new_section(cfg,section))!=CFG_NO_ERROR){ return(error_code); } ptr=rm_first_spaces(ptr+1); parsecfg_section_name=realloc(parsecfg_section_name,sizeof(char *)*(*section+1)); if((ptr=parse_word(ptr,&parsecfg_section_name[*section],CFG_SECTION))==NULL){ return(CFG_SYNTAX_ERROR); } for(i=0;i<*section;i++){ if(strcasecmp(parsecfg_section_name[*section],parsecfg_section_name[i])==0){ return(CFG_USED_SECTION); } } ptr=rm_first_spaces(ptr+1); if(*ptr!='\0' && *ptr!='#'){ return(CFG_SYNTAX_ERROR); } return(CFG_NO_ERROR); } if((ptr=parse_word(ptr,¶meter,CFG_PARAMETER))==NULL){ return(CFG_SYNTAX_ERROR); } if(*ptr=='{'){ ptr=rm_first_spaces(ptr+1); if(*ptr!='\0' && *ptr!='#'){ return(CFG_SYNTAX_ERROR); } parse_values_between_braces(file,fp,parameter,cfg,line,CFG_INI,*section); }else{ if((ptr=parse_word(ptr,&value,CFG_VALUE))==NULL){ return(CFG_SYNTAX_ERROR); } if((error_code=store_value(cfg,parameter,value,CFG_INI,*section))!=CFG_NO_ERROR){ return(error_code); } free(parameter); free(value); } return(CFG_NO_ERROR); } /* -------------------------------------------------- NAME alloc_for_new_section FUNCTION allocate memory for new section INPUT cfg ....... array of possible variables section ... pointer to current section number OUTPUT error code -------------------------------------------------- */ int alloc_for_new_section(cfgStruct cfg[],int *section) { int num; void *ptr; (*section)++; for(num=0;cfg[num].type!=CFG_END;num++){ switch(cfg[num].type){ case CFG_BOOL: case CFG_INT: case CFG_UINT: if(*section==0){ *(int **)(cfg[num].value)=NULL; } if((ptr=realloc(*(int **)(cfg[num].value),sizeof(int)*(*section+1)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } *(int **)(cfg[num].value)=ptr; if(cfg[num].type==CFG_BOOL){ *(*((int **)(cfg[num].value))+*section)=-1; }else{ *(*((int **)(cfg[num].value))+*section)=0; } break; case CFG_LONG: case CFG_ULONG: if(*section==0){ *(long **)(cfg[num].value)=NULL; } if((ptr=realloc(*(long **)(cfg[num].value),sizeof(long)*(*section+1)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } *(long **)(cfg[num].value)=ptr; *(*((long **)(cfg[num].value))+*section)=0; break; case CFG_STRING: if(*section==0){ *(char ***)(cfg[num].value)=NULL; } if((ptr=realloc(*(char ***)(cfg[num].value),sizeof(char *)*(*section+1)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } *(char ***)(cfg[num].value)=ptr; *(*(char ***)(cfg[num].value)+*section)=NULL; break; case CFG_STRING_LIST: if(*section==0){ *(cfgList ***)(cfg[num].value)=NULL; } if((ptr=realloc(*(cfgList ***)(cfg[num].value),sizeof(cfgList *)*(*section+1)))==NULL){ return(CFG_MEM_ALLOC_FAIL); } *(cfgList ***)(cfg[num].value)=ptr; *(*(cfgList ***)(cfg[num].value)+*section)=NULL; break; default: return(CFG_INTERNAL_ERROR); } } return(CFG_NO_ERROR); } /* -------------------------------------------------- NAME rm_first_spaces FUNCTION remove lead-off spaces and tabs in the string INPUT ptr ... pointer to string OUTPUT new poniter after removing -------------------------------------------------- */ char *rm_first_spaces(char *ptr) { while(*ptr==' ' || *ptr=='\t'){ ptr++; } return(ptr); } /* -------------------------------------------------- NAME get_single_line_without_first_spaces FUNCTION get a single line without lead-off spaces and tabs from file INPUT fp ....... file pointer gotptr ... pointer stored got string line ..... pointer to line number OUTPUT new poniter after removing -------------------------------------------------- */ char *get_single_line_without_first_spaces(FILE *fp,char **gotstr,int *line) { char *ptr; for(;;){ if((*gotstr=dynamic_fgets(fp))==NULL){ return(NULL); } (*line)++; ptr=rm_first_spaces(*gotstr); if(*ptr!='#' && *ptr!='\0'){ return(ptr); } free(*gotstr); } } /* -------------------------------------------------- NAME dynamic_fgets FUNCTION fgets with dynamic allocated memory INPUT fp ... file pointer OUTPUT pointer to got strings -------------------------------------------------- */ char *dynamic_fgets(FILE *fp) { char *ptr; char temp[128]; int i; ptr=malloc(1); if(ptr==NULL){ cfgFatalFunc(CFG_MEM_ALLOC_FAIL,"unknown",0,""); } *ptr='\0'; for(i=0;;i++){ if(fgets(temp,128,fp)==NULL){ free(ptr); return(NULL); } ptr=realloc(ptr,127*(i+1)+1); if(ptr==NULL){ cfgFatalFunc(CFG_MEM_ALLOC_FAIL,"unknown",0,""); } strcat(ptr,temp); if(strchr(temp,'\n')!=NULL){ *strchr(ptr,'\n')='\0'; return(ptr); } } }
/***************************************************************************/ /* */ /* parsecfg - a library for parsing a configuration file */ /* Copyright (C) 1999 Yuuki NINOMIYA, g...@smn.enjoy.ne.jp */ /* */ /* 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, 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., 59 Temple Place - Suite 330, */ /* Boston, MA 02111-1307, USA. */ /* */ /***************************************************************************/ #ifndef PARSECFG_H_INCLUDED #define PARSECFG_H_INCLUDED /* error code */ typedef enum{ CFG_NO_ERROR, CFG_OPEN_FAIL, CFG_SYNTAX_ERROR, CFG_WRONG_PARAMETER, CFG_INTERNAL_ERROR, CFG_INVALID_NUMBER, CFG_OUT_OF_RANGE, CFG_MEM_ALLOC_FAIL, CFG_BOOL_ERROR, CFG_USED_SECTION, } cfgErrorCode; /* type of the configuration file */ typedef enum{ CFG_SIMPLE, CFG_INI, } cfgFileType; /* constants for recognized value types */ typedef enum{ CFG_END, CFG_BOOL, CFG_STRING, CFG_INT, CFG_UINT, CFG_LONG, CFG_ULONG, CFG_STRING_LIST, } cfgValueType; typedef enum{ CFG_PARAMETER, CFG_VALUE, CFG_SECTION, } cfgKeywordValue; typedef enum{ CFG_NO_QUOTE, CFG_SINGLE_QUOTE, CFG_DOUBLE_QUOTE, } cfgQuote; typedef struct{ char *parameterName; cfgValueType type; void *value; } cfgStruct; typedef struct cfglist *cfgListPtr; typedef struct cfglist{ char *str; cfgListPtr next; } cfgList; /* proto type declaration of public functions */ void cfgSetFatalFunc(void (*f)(cfgErrorCode,char *,int,char *)); int cfgParse(char *file,cfgStruct cfg[],cfgFileType type); int cfgSectionNameToNumber(const char *name); char *cfgSectionNumberToName(int num); #endif /* PARSECFG_H_INCLUDED */
signature.asc
Description: OpenPGP digital signature