/* "build_isa_pnp_files.c" created by: grayspace aka J. Leveille for: UbixOS Project date: July 7, 2002 purpose: - tool to create the necessary source files for ISAPNP devices based on certain configuration files - built and run by the makefile for the kernel (eventually) NOTES: kinda hacky for now, but hey! it's only an intermediary tool! $Id$ */ // dependancy #include "../grayspace-misc/gsdefines.h" #include "../sys/include/deviceman/bus_resources.h" #include "../sys/include/deviceman/device.h" #include "make_kernel_string_pool.h" #include "build_isa_pnp_files.h" #include <stdlib.h> #include <string.h> #include <stdio.h> #define CLASS_NAME_CHARS (31) #define DEVDESC_MAX_CHARS (255) #define DEVID_CHARS (7) typedef struct tagISAPNP_TEMP_INFO { // device ID in string form char a_IDstr[DEVID_CHARS + 1]; // device description in string form char a_desc[DEVDESC_MAX_CHARS + 1]; // device class in string form char a_class[CLASS_NAME_CHARS + 1]; } ISAPNP_TEMP_INFO; // current temporary info ISAPNP_TEMP_INFO * g_p_infos = NULL; int g_numinfos = 0; static void FreeInfos() { if( g_p_infos ) { free( g_p_infos ); g_p_infos = NULL; } g_numinfos = 0; } static void FreeAll() { FreeInfos(); MakeKSP_ResetAll(); } static void AllocateInfos( int numinfos ) { FreeInfos(); g_p_infos = malloc( sizeof(ISAPNP_TEMP_INFO) * numinfos ); } #define LINEBUFFCHARS ( ( CLASS_NAME_CHARS\ + DEVDESC_MAX_CHARS\ + CLASS_NAME_CHARS\ + 3 ) * 2 ) /* HACK */ const static char * g_ap_validclassnames[] = { DEVICE_CLASS_GENERIC_IDSTR, DEVICE_CLASS_SOUND_DAC_IDSTR, DEVICE_CLASS_VIDEO_IDSTR, DEVICE_CLASS_NIC_IDSTR, DEVICE_CLASS_DISK_CTLR_IDSTR, DEVICE_CLASS_DISK_IDSTR }; #define NUMCLASSNAMES (sizeof(g_ap_validclassnames)/sizeof(char *)) static int ClassNameValid( const char * p_name ) { int i; for( i = 0; i < NUMCLASSNAMES; i++ ) { if( strcmp( p_name, g_ap_validclassnames[i] ) ) { return 1; } } return 0; } const static char g_whitespace[] = " \t\n"; const static char g_classdelimit[] = ";\n"; // returns number of non-white space chars remaining static int RemoveWhiteSpace( char * p_str ) { char buff[LINEBUFFCHARS + 1]; char * p_curchar; int numnonwhitechars; p_curchar = p_str; numnonwhitechars = 0; // skip past leading white space while( *p_curchar != 0 && ( *p_curchar == '\t' || *p_curchar == ' ' ) ) { p_curchar++; } // copy string with no white space to 'buff' strcpy( buff, p_curchar ); // go to last char p_curchar = buff + (strlen(buff) - 1); // if string non empty, NULL terminate buff after last non-whitespace char if( p_curchar >= buff ) { // non empty while( *p_curchar == '\t' || *p_curchar == ' ' ) { p_curchar--; } p_curchar++; if( p_curchar > buff ) { // non empty will remain *p_curchar = 0; // copy back to original string strcpy( p_str, buff ); // return characters remaining return strlen( p_str ); } } // empty string remains return 0; } static int FillInfo( ISAPNP_TEMP_INFO * p_infos, int idx, char * p_line, int linenum ) { char * p_curbuff; ISAPNP_TEMP_INFO * p_i; // get current info p_i = p_infos + idx; // extract pnp ID p_curbuff = p_line; p_curbuff = strtok( p_curbuff, g_whitespace ); if( !p_curbuff ) { // empty line return 0; } if( *p_curbuff == ';' || *p_curbuff == '#' ) { // comment return 0; } if( strlen( p_curbuff ) == DEVID_CHARS ) { // device ID string ok // TODO: parse more thoroughly strcpy( p_i->a_IDstr, p_curbuff ); // fetch everything up until the class name delimiter p_curbuff = strtok( NULL, g_classdelimit ); if( p_curbuff ) { // copy description if( strlen( p_curbuff ) <= DEVDESC_MAX_CHARS ) { strcpy( p_i->a_desc, p_curbuff ); } else { printf( "[FillInfo], Warning, device description too long in line: %d, Ignoring.\n", linenum ); return 0; } // trim it's whitespace RemoveWhiteSpace( p_i->a_desc ); // fetch the class id: p_curbuff = strtok( NULL, g_whitespace ); if( p_curbuff ) { if( ClassNameValid( p_curbuff ) ) { // copy it strcpy( p_i->a_class, p_curbuff ); } else { printf( "[FillInfo], Warning, invalid device class in line: %d, Ignoring.\n", linenum ); return 0; } } else { printf( "[FillInfo], Warning, missing device class in line: %d, Assuming Generic.\n", linenum ); // fill class as generic strcpy( p_i->a_class, DEVICE_CLASS_GENERIC_IDSTR ); } } // success return 1; } printf( "[FillInfo], Warning, invalid PNP-ID in line: %d, Ignoring.\n", linenum ); return 0; } static int ReadInConfigFile( const char * p_path ) { FILE * p_file; int numlines; int linenum; char buff[LINEBUFFCHARS + 1]; // open the file if( !(p_file = fopen( p_path, "rt" )) ) { printf( "[ReadInConfigFile] Error, cannot open file: %s.\n", p_path ); return 0; } // count our maximum number of descriptions // go to beginning of file if( fseek( p_file, 0L, SEEK_SET ) ) { goto failbail; } // count our lines: numlines = 0; while( fgets( buff, LINEBUFFCHARS, p_file ) != NULL ) { numlines++; } // (re)allocate our infos AllocateInfos( numlines ); // fill our infos // go to beginning of file if( fseek( p_file, 0L, SEEK_SET ) ) { goto failbail; } // read each line as info if possible g_numinfos = 0; linenum = 0; while( fgets( buff, LINEBUFFCHARS, p_file ) != NULL ) { if( FillInfo( g_p_infos, g_numinfos, buff, linenum ) ) { g_numinfos++; } linenum++; } // close file fclose( p_file ); if( g_numinfos ) { // success return 1; } failbail: // close file fclose( p_file ); // free infos FreeInfos(); printf( "[ReadInConfigFile] Error parsing file: %s.\n", p_path ); return 0; } static int WriteDescriptionStringsFile( const char * p_path ) { FILE * p_file; int i; // open the file if( !(p_file = fopen( p_path, "wt" )) ) { printf( "[ReadInConfigFile] Error, cannot open file: %s.\n", p_path ); return 0; } // write out every description line for( i = 0; i < g_numinfos; i++ ) { if( fputs( g_p_infos[i].a_desc, p_file ) != EOF ) { if( fputs( "\n", p_file ) != EOF ) { continue; } } goto failbail; } // success: return 1; failbail: // close file fclose( p_file ); printf( "[WriteDescriptionStringsFile] Error, cannot write to file\n" ); return 0; } static int RegisterSubStrings( const char * p_dstpath, const char * p_srcpath ) { // HACK: create for now as well if( Create_SubStringFile( p_dstpath ) ) { if( Add_SubStringsFromFile( p_srcpath ) ) { if( WriteAndClose_SubStringFile() ) { return 1; } } } printf( "[WriteDescriptionSubStringsFile] Error, cannot create sub strings file\n" ); return 0; } static int pnp_str_idx = 0; static int pnp_num_strs = 0; static int RegisterGlobalKStrings( const char * p_dstpath_str, const char * p_dstpath_substr, const char * p_srcpath ) { // register the sub strings if( RegisterSubStrings( p_dstpath_substr, p_srcpath ) ) { // HACK: create for now as well if( Create_StringFile( p_dstpath_str ) ) { if( AppendStringsFromFile( &pnp_str_idx, &pnp_num_strs, p_srcpath ) ) { if( WriteAndClose_StringFile() ) { return 1; } } } printf( "[WriteToGlobalKStrings] Error, cannot create strings file\n" ); } return 0; } static int GenerateGlobalKStringsSource( const char * p_strs_path, const char * p_substrs_path, const char * p_hdr_path, const char * p_hdr_name, const char * p_srccode_path, const char * p_srccode_name, const char ** pp_includes, int numincludes, const char * p_poolname ) { int ok; ok = 0; // open the string file if( Open_StringFile( p_strs_path ) ) { // open the sub string file if( Open_SubStringFile( p_substrs_path ) ) { // generate the source code ok = Create_KStringSourceCode( p_hdr_path, p_hdr_name, p_srccode_path, p_srccode_name, pp_includes, numincludes, p_poolname ); // close the sub string file ok &= Close_SubStringFile(); } // close the string file ok &= Close_StringFile(); } // return success result return ok; } // HACK: char * ap_includes[] = { "\"../../grayspace-misc/gsdefines.h\"", "\"../../sys/include/misc/kernel_string_pool.h\"" }; int main( void ) { char buff[1024]; // first, read in and extract all ISA-PNP devices from configuration file if( !ReadInConfigFile( DEVLIST_FILEPATH_IN ) ) { FreeAll(); return 0; } // now, generate text file of strings used for device descriptions if( !WriteDescriptionStringsFile( DEVSTRINGS_FILEPATH_TMP ) ) { FreeAll(); return 0; } // add strings to global string files if( !RegisterGlobalKStrings( KSTRINGS_FILEPATH_TMP, KSUBSTRINGS_FILEPATH_TMP, DEVSTRINGS_FILEPATH_TMP ) ) { FreeAll(); return 0; } // generate source files if( !GenerateGlobalKStringsSource( KSTRINGS_FILEPATH_TMP, KSUBSTRINGS_FILEPATH_TMP, DEVLIST_KSTR_HDR_OUT_PATH, DEVLIST_KSTR_HDR_OUT, DEVLIST_KSTR_SRC_OUT_PATH, DEVLIST_KSTR_SRC_OUT, ap_includes, sizeof(ap_includes)/sizeof(char *), DEVLIST_KSTR_POOLNAME ) ) { FreeAll(); return 0; } gets( buff ); return 1; }