// vim: nowrap /* *********** Module: Isapnpconf Created: 15/05/2000 Last Modified: 19/06/2000 Author: Cristiano Otto Von Trompczynski e-mail: cris@conectiva.com.br Description: Here you will find all the functions responsible by executing the parser in the 'isapnp.conf' file. "This module is for you, Penguin!" *********** */ #include "isapnpconf.h" #include #include // Used definitions to search in the CONFIGUREs. #define CONFIGURE "(CONFIGURE" #define END_CONFIGURE "(NAME" #define CARD "# Card" #define END_CARD "End tag" #define IO "(IO" #define INT "(INT" #define DMA "(DMA" /* EM TRATAMENTO PUBLIC int MODULE_isapnpconf::create_struct (SSTRINGS &isapnp) Generates all the structure which will contain the data from the ISAPNP.CONF file RETURN: OK - se sucesso ERROR4 - error trying open/close file ERROR6 - allocation error ERROR7 - file ISAPNP.CONF changed */ PUBLIC int MODULE_isapnpconf::create_struct (SSTRINGS &isapnp){ int n_lines; bool inCard, inConfigure, inSetting; inCard=false; inConfigure=false; inSetting=false; if (read_file(isapnp)==ERROR) //read the 'isapnp.conf' to the struct return ERROR4; if( (cf_start=(struct cf_isapnp*)malloc(sizeof(struct cf_isapnp))) ){ //starting the isapnp struct cf_start->id=NULL; cf_start->version=NULL; cf_start->date=NULL; cf_start->n_card=0; cf_start->card=NULL; }else return ERROR6; struct pcard *tcard=NULL; struct configure *tconf=NULL; struct settings *tset=NULL; int tlines = isapnp.getnb(); for (n_lines=0; n_linesget(); if (n_lines==0){ //read the header read_file_header (buffer); } if (strstr(buffer, CARD)){ //a CARD! set FLAGs; alocate CARD; read CARD if (inConfigure==false && inCard==false){ if ( (tcard=add_card()) ){ inCard=true; read_card_header (n_lines, tcard, isapnp); continue; }else return ERROR6; }else{ return ERROR7; } continue; } if (strstr(buffer, END_CARD)){ //CARD's end! Verify the integrity of the FLAGs if (inConfigure==false && inCard==true){ inCard=false; continue; }else{ return ERROR7; } continue; } if (strstr(buffer, CONFIGURE)){ //a CONFIGURE! set FLAGs; alocate CONFIGURE; read CONFIGURE if (inConfigure==false && inCard==true){ inConfigure=true; if ( (tconf=(struct configure*)add_configure ()) ){ read_configure (tcard, tconf, n_lines, isapnp); continue; }else return ERROR6; }else{ return ERROR7; } continue; } if (strstr(buffer, END_CONFIGURE)){ //CARD's end! Verify the integrity of the FLAGs; read the CONFIGURE if (inConfigure==true && inCard==true){ inConfigure=false; read_end_configure(tconf, n_lines, isapnp); continue; }else return ERROR7; } //an IO, IRQ, DMA! Verify the integrity of the FLAGs! Alocate SETTING; Add SETTING to the Struct; read SETTING if ( (strstr(buffer, IO) || strstr(buffer, INT) || strstr(buffer, DMA)) && inConfigure==true && inCard==true ){ if (inConfigure==true && inCard==true){ if ( (tset=(struct settings*)add_setting ()) ){ if (read_a_setting (n_lines, tset, isapnp)==ERROR) return ERROR6; continue; }else return ERROR6; continue; }else{ return ERROR7; } } } return OK; } /* int MODULE_isapnpconf::read_a_setting (int &line, settings *tset, SSTRINGS &ss) Read the data in a SETTING block of the ss container. When finding IOs, DMAs and IRQs extract their values and add them to the structure. It's also added the number of the line reffering to each data in the structure. RETURN: OK - if success ERROR - ERROR */ PUBLIC int MODULE_isapnpconf::read_a_setting (int &line, settings *tset, SSTRINGS &ss){ char *p=NULL; tset->line_setting=line; // Looking for Setting's void *s=NULL; int nb = ss.getnb(); for (; !(ss.getitem(line)->is_empty()) && line < nb; line++ ){ const char *buffer = ss.getitem(line)->get(); if ( strstr(buffer, END_CONFIGURE) ){ line--; break; } int i=0; char address[7]; if (strstr(buffer, "IO")){ if ( (p=strstr(buffer,"BASE")) ){ if( (s=add_io()) ){ for (i=0, p+=5; *p!=')'&&*p!='\0' && i<6; p++,i++){ address[i]=*p; } address[i]='\0'; bool f=false; for (int j=0;buffer[j]!='('&&buffer[j]!='\0' ;j++) if (buffer[j]=='#'){ f=true; break; } if (!f){ tset->inUse=true; tset->inUseCg=true; } ((struct s_io*)s)->line_io=line; ((struct s_io*)s)->io=strdup(address); continue; }else return ERROR; } } if (strstr(buffer, "DMA")){ if ( (p=strstr(buffer,"CHANNEL")) && strlen(p) > 8 ){ if ( (s=(struct s_dma*)add_dma()) ){ for (i=0, p+=8; *p!=')'&&*p!='\0'; p++,i++){ address[i]=*p; } address[i]='\0'; bool f=false; for (int j=0;buffer[j]!='('&&buffer[j]!='\0' ;j++) if (buffer[j]=='#'){ f=true; break; } if (!f){ tset->inUse=true; tset->inUseCg=true; } ((struct s_dma*)s)->line_dma=line; ((struct s_dma*)s)->dma=strdup(address); continue; }else return ERROR; } } if (strstr(buffer, "INT")){ if ( (p=strstr(buffer,"IRQ")) ){ if ( (s=(struct s_irq*)add_irq()) ){ for (i=0, p+=4; *p!=' '&&*p!='('&&*p!='\0'; p++,i++){ address[i]=*p; } address[i]='\0'; bool f=false; for (int j=0;buffer[j]!='('&&buffer[j]!='\0' ;j++) if (buffer[j]=='#'){ f=true; break; } if (!f){ tset->inUse=true; tset->inUseCg=true; } ((struct s_irq*)s)->line_irq=line; ((struct s_irq*)s)->irq=strdup(address); continue; }else return ERROR; } } } return OK; } /* PUBLIC void MODULE_isapnpconf::read_card_header (int &line, struct pcard *tcard, SSTRINGS &ss) Only reads the CARD Description. It's the only function which reads a comment. RETURN: Nothing */ PUBLIC void MODULE_isapnpconf::read_card_header (int &line, struct pcard *tcard, SSTRINGS &ss){ char *p=NULL; char desc[400]; tcard->line_card=line; desc[0]='\0'; // Check if we have the card description int nb = ss.getnb(); for (; !(ss.getitem(line)->is_empty()) && line < nb; line++ ){ const char *buffer = ss.getitem(line)->get(); if ( (p=strstr(buffer,"ANSI string")) ){ char *pstart, *pend; if ((pstart=strstr(p,"-->")) && (pend=strstr(p,"<--")) && pstart < pend){ pstart+=3; int size = pend-pstart; memcpy(desc, pstart, size); desc[size]=0; } break; } } tcard->description=strdup(desc); } /* void MODULE_isapnpconf::read_configure (struct pcard *tcard, struct configure *dat, int &line, SSTRINGS &ss) Receives as parameters the CARD of this CONFIGURE (to make it add 'Vendor ID' and 'Serial' to the CARD), the CONFIGURE (to extract the data), the line of the CONFIGURE found and the SSTRINGS ss (container which contains all the ISAPNP.CONF data). Read the data os a CONFIGURE: LD, starting line of the CONFIGURE. Adds in this CONFIGURE CARD 'Vendor ID' and 'serial' (in case there's still no CARD). RETURN: Nothing */ PUBLIC void MODULE_isapnpconf::read_configure (struct pcard *tcard, struct configure *dat, int &line, SSTRINGS &ss){ int i; char unknow[512]; unknow[0]='\0'; dat->line_cfg_start=line; const char *buffer = ss.getitem(line)->get(); char *p; // if we relly are in a CONFIGURE if ((p=strstr(buffer,CONFIGURE " "))){ if (tcard->vendor_Id==NULL){ //if we don't have a vendor_id set for (i=0,p+=11; *p!='/' && *p!=0; i++,p++){ unknow[i]=*p; } unknow[i]=0; tcard->vendor_Id=strdup(unknow); //xconf_notice ("tcard->vendor_id:'%s'",unknow); // APAGUE } if (tcard->serial==NULL && (p=strstr(buffer,"/"))){ //if we don't have a vendor_serial set for (i=0, p+=1; *p!=' ' && *p!='(' && *p!=0; i++,p++){ unknow[i]=*p; } unknow[i]=0; tcard->serial=strdup(unknow); //xconf_notice ("tcard->vendor_id:'%s'",unknow); // APAGUE } if ((p=strstr(buffer,"(LD "))){ for (i=0, p+=4; *p!=' ' && *p!=0; i++,p++){ unknow[i]=*p; } unknow[i]=0; dat->ld=atoi(unknow); //xconf_notice ("dat->ld:'%d'",dat->ld); // APAGUE } } /* { //const char *buffer = ss.getitem(line++)->get(); int i=11; for (int k=0; *(buffer+i)!='\0'; i++){ //APAGUEINI // xconf_notice ("buffer:'%s'\n\n*(buffer+i):'%c'",buffer,*(buffer+i)); //APAGUEFIM if ( tcard->vendor_Id==NULL||tcard->serial==NULL ){ unknow[k]=*(buffer+i); switch ( *(buffer+i) ){ case '/': unknow[k]='\0'; tcard->vendor_Id=strdup(unknow); xconf_notice("tcard->vendor_Id:'%s'",unknow); k=0; continue; case ' ': unknow[k]='\0'; tcard->serial=strdup(unknow); xconf_notice("tcard->serial:'%s'",unknow); k=0; continue; } k++; } if ( buffer[i]=='(' && buffer[i+1]=='L' && buffer[i+2]=='D'){ i+=4; char b[4]; int j; for (j=0; 48<=buffer[i] && buffer[i]<=57 && j < 4; i++, j++) b[j]=buffer[i]; b[j]='\0'; ld = atoi(b); break; } } } // Set the value dat->ld=ld;*/ } /* void MODULE_isapnpconf::read_end_configure (struct configure *dat, int &line, SSTRINGS &ss) Receives as a parameter a CONFIGURE address, the line and the ss container. Reads the data at the end of a CONFIGURE. Data with the CONFIGURE description and the line on which this CONFIGURE ends up. RETURN: Nothing */ PUBLIC void MODULE_isapnpconf::read_end_configure (struct configure *dat, int &line, SSTRINGS &ss){ char desc[400]; char *p=NULL; desc[0]='\0'; const char *buf = ss.getitem(line)->get(); if ( (p=strchr( buf,'{' )) ){ int i; for (i=0, p++; *(p+i)!='}'&& *(p+i)!='\0'; i++){ desc[i]=*(p+i); } desc[i]='\0'; } dat->description=strdup(desc); dat->line_cfg_end=line; } /* PUBLIC void MODULE_isapnpconf::read_file_header (const char *cont) Reads the header from the ISAPNP.CONF file. These data won't be used by the program, they're simply stored in the ISAPNP structure. RETURN: Nothing */ PUBLIC void MODULE_isapnpconf::read_file_header (const char *cont){ char tmp_id[30]; char tmp_ver[10]; char tmp_date[15]; char *p; int i=0; tmp_id[0]='\0'; tmp_ver[0]='\0'; tmp_date[0]='\0'; if ( (p=strstr(cont,"Id: ")) ){ //get the Id p+=4; for ( i=0; *(p+i)!=',' && *(p+i)!=' ' && *(p+i)!='\0'; i++ ){ tmp_id[i]=*(p+i); } tmp_id[i]='\0'; //xconf_notice ("tmp_id:'%s'",tmp_id); } if ( (p=strstr(cont,"v ")) ){ //get the version p+=2; for ( i=0; *(p+i)!=',' && *(p+i)!=' ' && *(p+i)!='\0'; i++ ){ tmp_ver[i]=*(p+i); } tmp_ver[i]='\0'; //xconf_notice ("tmp_ver:'%s'",tmp_ver); } p=strstr(cont,"/"); if (*(p+3)=='/'){ while ( p!=cont && *(p-1) >= 48 && *(p-1) < 58 ) p--; for ( i=0; *(p+i)!=',' && *(p+i)!=' ' && *(p+i)!='\0'; i++ ){ tmp_date[i]=*(p+i); } tmp_date[i]='\0'; //xconf_notice ("tmp_date:'%s'",tmp_date); } cf_start->id=strdup(tmp_id); cf_start->version=strdup(tmp_ver); cf_start->date=strdup(tmp_date); //xconf_notice ("cf_start->id='%s'\ncf_start->version='%s'\ncf_start->date='%s'",cf_start->id,cf_start->version,cf_start->date); }