/*
"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;
}