Misc Changes, Added Logging Subsystem, Fixes to InitRD, Working on RTL8139 driver
[tpg/acess2.git] / Kernel / system.c
index 49af479..463b4e0 100644 (file)
@@ -3,11 +3,25 @@
  * Architecture Independent System Init
  * system.c
  */
-#include <common.h>
+#define DEBUG  0
+#include <acess.h>
+
+// === TYPES ===
+typedef struct
+{
+        int    TrueLine;
+        int    nParts;
+       char    **Parts;
+}      tConfigLine;
+typedef struct
+{
+        int    nLines;
+       tConfigLine     Lines[];
+}      tConfigFile;
 
 // === IMPORTS ===
 extern int     Modules_LoadBuiltins();
-extern int     PCI_Install();
+//extern int   PCI_Install();
 extern void    DMA_Install();
 extern void    Debug_SetKTerminal(char *File);
 extern void    StartupPrint(char *Str);
@@ -18,25 +32,17 @@ void        System_ParseCommandLine(char *ArgString);
 void   System_ParseVFS(char *Arg);
 void   System_ParseSetting(char *Arg);
 void   System_ExecuteScript();
- int   System_Int_GetString(char *Str, char **Dest);
+tConfigFile    *System_Int_ParseFile(char *File);
 
 // === GLOBALS ===
 char   *gsConfigScript = "/Acess/Conf/BootConf.cfg";
 
 // === CODE ===
 void System_Init(char *ArgString)
-{
-       // - Start Builtin Drivers & Filesystems
-       StartupPrint("Scanning PCI Bus...");
-       PCI_Install();
-       StartupPrint("Loading DMA...");
-       DMA_Install();
-       StartupPrint("Loading staticly compiled modules...");
-       Modules_LoadBuiltins();
-       
+{      
        // Set the debug to be echoed to the terminal
-       StartupPrint("Kernel now echoes to VT6 (Ctrl-Alt-F7)");
-       Debug_SetKTerminal("/Devices/VTerm/6");
+       StartupPrint("Kernel now echoes to VT7 (Ctrl-Alt-F8)");
+       Debug_SetKTerminal("/Devices/VTerm/7");
        
        // - Parse Kernel's Command Line
        System_ParseCommandLine(ArgString);
@@ -63,8 +69,10 @@ void System_ParseCommandLine(char *ArgString)
        str = ArgString;
        for( argc = 0; argc < 32; argc++ )
        {
-               while(*str == ' ')      str++;  // Eat Whitespace
-               if(*str == '\0') {      argc--; break;} // End of string
+               // Eat Whitespace
+               while(*str == ' ')      str++;
+               // Check for the end of the string
+               if(*str == '\0') {      argc--; break;} 
                argv[argc] = str;
                while(*str && *str != ' ')
                {
@@ -74,7 +82,7 @@ void System_ParseCommandLine(char *ArgString)
                        }*/
                        str++;
                }
-               if(*str == '\0')        break;  // End of string
+               if(*str == '\0')        break;  // Check for EOS
                *str = '\0';    // Cap off argument string
                str ++; // and increment the string pointer
        }
@@ -158,10 +166,10 @@ void System_ParseSetting(char *Arg)
        // Check for boolean/flag (no '=')
        if(*value == '\0')
        {
-               if(strcmp(Arg, "") == 0) {
-               } else {
+               //if(strcmp(Arg, "") == 0) {
+               //} else {
                        Warning("Kernel flag '%s' is not recognised", Arg);
-               }
+               //}
        }
        else
        {
@@ -185,9 +193,10 @@ void System_ExecuteScript()
 {
         int    fp;
         int    fLen = 0;
-        int    i = 0, lineStart;
-       char    *sArg1, *sArg2, *sArg3;
+        int    i;
        char    *fData;
+       tConfigFile     *file;
+       tConfigLine     *line;
        
        // Open Script
        fp = VFS_Open(gsConfigScript, VFS_OPENFLAG_READ);
@@ -205,148 +214,256 @@ void System_ExecuteScript()
        fData[fLen] = '\0';
        VFS_Close(fp);
        
-       // Read Script
-       while(i < fLen)
+       
+       
+       // Parse File
+       file = System_Int_ParseFile(fData);
+       
+       // Parse each line
+       for( i = 0; i < file->nLines; i++ )
        {
-               sArg1 = sArg2 = sArg3 = NULL;
+               line = &file->Lines[i];
+               if( line->nParts == 0 ) continue;       // Skip blank
                
-               lineStart = i;
-               // Clear leading whitespace and find empty lines
-               while(i < fLen && (fData[i] == ' ' || fData[i]=='\t'))  i ++;
-               if(i == fLen)   break;
-               if(fData[i] == '\n') {
-                       i++;
-                       continue;
-               }
-               
-               // Comment
-               if(fData[i] == ';' || fData[i] == '#') {
-                       while(i < fLen && fData[i] != '\n')     i ++;
-                       i ++;
-                       continue;
+               // Mount Device
+               if( strcmp(line->Parts[0], "mount") == 0 )
+               {
+                       if( line->nParts != 4 ) {
+                               Warning("Configuration command 'mount' requires 3 arguments, %i given",
+                                       line->nParts-1);
+                               continue;
+                       }
+                       //Log("[CFG ] Mount '%s' to '%s' (%s)",
+                       //      line->Parts[1], line->Parts[2], line->Parts[3]);
+                       //! \todo Use an optional 4th argument for the options string
+                       VFS_Mount(line->Parts[1], line->Parts[2], line->Parts[3], "");
                }
-               
-               // Commands
-               // - Mount
-               if(strncmp("mount ", fData+i, 6) == 0) {
-                       i += 6;
-                       i += System_Int_GetString(fData+i, &sArg1);
-                       if(!sArg1)      goto read2eol;
-                       i += System_Int_GetString(fData+i, &sArg2);
-                       if(!sArg2)      goto read2eol;
-                       i += System_Int_GetString(fData+i, &sArg3);
-                       if(!sArg3)      goto read2eol;
-                       //Log("[CFG ] Mount '%s' to '%s' (%s)\n", sArg1, sArg2, sArg3);
-                       VFS_Mount(sArg1, sArg2, sArg3, "");
+               // Load a Module
+               else if(strcmp(line->Parts[0], "module") == 0)
+               {
+                       if( line->nParts < 2 || line->nParts > 3 ) {
+                               Warning("Configuration command 'module' requires 1 or 2 arguments, %i given",
+                                       line->nParts-1);
+                               continue;
+                       }
+                       if( line->nParts == 3 )
+                               Module_LoadFile(line->Parts[1], line->Parts[2]);
+                       else
+                               Module_LoadFile(line->Parts[1], "");
                }
-               // - Load Module
-               else if(strncmp("module ", fData+i, 6) == 0) {
-                       //char  *tmp;
-                       i += 7;
-                       i += System_Int_GetString(fData+i, &sArg1);
-                       if(!sArg1)      goto read2eol;
-                       Module_LoadFile(sArg1, "");     //!\todo Use the rest of the line as the argument string
+               // Load a UDI Module
+               else if(strcmp(line->Parts[0], "udimod") == 0)
+               {
+                       if( line->nParts != 2 ) {
+                               Warning("Configuration command 'udimod' requires 1 argument, %i given",
+                                       line->nParts-1);
+                               continue;
+                       }
+                       Log("[CFG  ] Load UDI Module '%s'", line->Parts[1]);
+                       Module_LoadFile(line->Parts[1], "");
                }
-               // - Load Module
-               else if(strncmp("edimod ", fData+i, 6) == 0) {
-                       i += 7;
-                       i += System_Int_GetString(fData+i, &sArg1);
-                       if(!sArg1)      goto read2eol;
-                       Log("[CFG ] Load EDI Module '%s'\n", sArg1);
-                       Module_LoadFile(sArg1, "");
+               // Load a EDI Module
+               else if(strcmp(line->Parts[0], "edimod") == 0)
+               {
+                       if( line->nParts != 2 ) {
+                               Warning("Configuration command 'edimod' requires 1 argument, %i given",
+                                       line->nParts-1);
+                               continue;
+                       }
+                       Log("[CFG  ] Load EDI Module '%s'", line->Parts[1]);
+                       Module_LoadFile(line->Parts[1], "");
                }
-               // - Symlink
-               else if(strncmp("symlink ", fData+i, 7) == 0) {
-                       i += 8;
-                       i += System_Int_GetString(fData+i, &sArg1);
-                       if(!sArg1)      goto read2eol;
-                       i += System_Int_GetString(fData+i, &sArg2);
-                       if(!sArg2)      goto read2eol;
-                       Log("[CFG ] Symlink '%s' pointing to '%s'\n", sArg1, sArg2);
-                       VFS_Symlink(sArg1, sArg2);
+               // Create a Symbolic Link
+               else if(strcmp(line->Parts[0], "symlink") == 0)
+               {
+                       if( line->nParts != 3 ) {
+                               Warning("Configuration command 'symlink' requires 2 arguments, %i given",
+                                       line->nParts-1);
+                               continue;
+                       }
+                       Log("[CFG  ] Symlink '%s' pointing to '%s'",
+                               line->Parts[1], line->Parts[2]);
+                       VFS_Symlink(line->Parts[1], line->Parts[2]);
                }
-               // - New Directory
-               else if(strncmp("mkdir ", fData+i, 5) == 0) {
-                       i += 6;
-                       i += System_Int_GetString(fData+i, &sArg1);
-                       if(!sArg1)      goto read2eol;
-                       Log("[CFG ] New Directory '%s'\n", sArg1);
-                       VFS_MkDir(sArg1);
+               // Create a Directory
+               else if(strcmp(line->Parts[0], "mkdir") == 0)
+               {
+                       if( line->nParts != 2 ) {
+                               Warning("Configuration command 'mkdir' requires 1 argument, %i given",
+                                       line->nParts-1);
+                               continue;
+                       }
+                       Log("[CFG  ] New Directory '%s'", line->Parts[1]);
+                       VFS_MkDir(line->Parts[1]);
                }
-               // - Spawn a task
-               else if(strncmp("spawn ", fData+i, 5) == 0) {
-                       i += 6;
-                       i += System_Int_GetString(fData+i, &sArg1);
-                       if(!sArg1)      goto read2eol;
-                       Log("[CFG ] Starting '%s' as a new task\n", sArg1);
-                       Proc_Spawn(sArg1);
+               // Spawn a process
+               else if(strcmp(line->Parts[0], "spawn") == 0)
+               {
+                       if( line->nParts != 2 ) {
+                               Warning("Configuration command 'spawn' requires 1 argument, %i given",
+                                       line->nParts-1);
+                               continue;
+                       }
+                       Log("[CFG  ] Starting '%s' as a new task", line->Parts[1]);
+                       Proc_Spawn(line->Parts[1]);
                }
                else {
-                       Warning("Unknown configuration command, Line: '%s'", fData+i);
-                       goto read2eol;
+                       Warning("Unknown configuration command '%s' on line %i",
+                               line->Parts[0],
+                               line->TrueLine
+                               );
                }
-       read2eol:
-               if(sArg1)       free(sArg1);
-               if(sArg2)       free(sArg2);
-               if(sArg3)       free(sArg3);
-               // Skip to EOL
-               while(i < fLen && fData[i] != '\n')     i++;
-               i ++;   // Skip \n
        }
-       free(fData);
+       
+       // Clean up after ourselves
+       for( i = 0; i < file->nLines; i++ ) {
+               if( file->Lines[i].nParts == 0 )        continue;       // Skip blank
+               free( file->Lines[i].Parts );
+       }
+       free( file );
+       free( fData );
 }
 
 /**
- * \fn int System_Int_GetString(char *Str, char **Dest)
- * \brief Gets a string from another
- * \note Destructive
- * \param Str  Input String
- * \param Dest Pointer to output pointer
- * \return Characters eaten from input
+ * \brief Parses a config file
+ * \param FileData     Read/Write buffer containing the config file data
+ *                  (will be modified)
+ * \return ::tConfigFile structure that represents the original contents
+ *         of \a FileData
  */
-int System_Int_GetString(char *Str, char **Dest)
+tConfigFile    *System_Int_ParseFile(char *FileData)
 {
-        int    pos = 0;
-        int    start = 0;
-        int    len;
-        
-       //LogF("GetString: (Str='%s', Dest=0x%x)\n", Str, Dest);
-        
-       while(Str[pos] == ' ' || Str[pos] == '\t')      pos++;
-       if(Str[pos] == '\n' || Str[pos] == '\0') {
-               *Dest = NULL;
-               return pos;
-       }
+       char    *ptr;
+       char    *start;
+        int    nLines = 1;
+        int    i, j;
+       tConfigFile     *ret;
        
-       // Quoted String
-       if(Str[pos] == '"')
-       {
-               pos ++;
-               start = pos;
-               while(Str[pos] != '"')  pos++;
+       ENTER("pFileData", FileData);
+       
+       // Prescan and count the number of lines
+       for(ptr = FileData; *ptr; ptr++)
+       {               
+               if(*ptr != '\n')        continue;
                
-               len = pos - start;
-               *Dest = malloc( len + 1 );
-               memcpy( *Dest, Str+start, len );
-               (*Dest)[len] = '\0';
+               if(ptr == FileData) {
+                       nLines ++;
+                       continue;
+               }
                
-               //LogF("GetString: RETURN *Dest = '%s'\n", *Dest);
+               // Escaped EOL
+               if(ptr[-1] == '\\')     continue;
                
-               pos++;
-               return pos;
+               nLines ++;
        }
        
-       // Non-Quoted String - Whitespace deliminated
-       start = pos;
-       while(Str[pos] != ' ' && Str[pos] != '\t' && Str[pos] != '\n')  pos++;
+       LOG("nLines = %i", nLines);
        
-       len = pos - start;
-       //LogF(" GetString: len = %i\n", len);
-       *Dest = malloc( len + 1 );
-       memcpy( *Dest, Str+start, len );
-       (*Dest)[len] = '\0';
+       // Ok so we have `nLines` lines, now to allocate our return
+       ret = malloc( sizeof(tConfigFile) + sizeof(tConfigLine)*nLines );
+       ret->nLines = nLines;
        
-       //LogF("GetString: RETURN *Dest = '%s'\n", *Dest);
+       // Read the file for real
+       for(
+               ptr = FileData, i = 0;
+               *ptr;
+               i++
+               )
+       {
+               start = ptr;
+               
+               ret->Lines[i].nParts = 0;
+               
+               // Count parts
+               for(;;)
+               {
+                       // Read leading whitespace
+                       while( *ptr == '\t' || *ptr == ' ' )    ptr++;
+                       
+                       // End of line/file
+                       if( *ptr == '\0' || *ptr == '\n' ) {
+                               if(*ptr == '\n')        ptr ++;
+                               break;
+                       }
+                       // Comment
+                       if( *ptr == '#' || *ptr == ';' ) {
+                               while( *ptr && *ptr != '\n' )   ptr ++;
+                               if(*ptr == '\n')        ptr ++;
+                               break;
+                       }
+                       
+                       ret->Lines[i].nParts ++;
+                       // Quoted
+                       if( *ptr == '"' ) {
+                               ptr ++;
+                               while( *ptr && !(*ptr == '"' && ptr[-1] == '\\') && *ptr != '\n' )
+                                       ptr++;
+                               continue;
+                       }
+                       // Unquoted
+                       while( *ptr && !(*ptr == '\t' || *ptr == ' ') && *ptr != '\n' )
+                               ptr++;
+               }
+               
+               LOG("ret->Lines[%i].nParts = %i", i, ret->Lines[i].nParts);
+               
+               if( ret->Lines[i].nParts == 0 ) {
+                       ret->Lines[i].Parts = NULL;
+                       continue;
+               }
+               
+               // Allocate part list
+               ret->Lines[i].Parts = malloc( sizeof(char*) * ret->Lines[i].nParts );
+               
+               // Fill list
+               for( ptr = start, j = 0; ; j++ )
+               {
+                       // Read leading whitespace
+                       while( *ptr == '\t' || *ptr == ' ' )    ptr++;
+                       
+                       // End of line/file
+                       if( *ptr == '\0' || *ptr == '\n' ) {
+                               if(*ptr == '\n')        ptr ++;
+                               break;
+                       }
+                       // Comment
+                       if( *ptr == '#' || *ptr == ';' ) {
+                               while( *ptr && *ptr != '\n' )   ptr ++;
+                               if(*ptr == '\n')        ptr ++;
+                               break;
+                       }
+                       
+                       ret->Lines[i].Parts[j] = ptr;
+                       
+                       // Quoted
+                       if( *ptr == '"' ) {
+                               ptr ++;
+                               while( *ptr && !(*ptr == '"' && ptr[-1] == '\\') && *ptr != '\n' )
+                                       ptr++;
+                       }
+                       // Unquoted
+                       else {
+                               while( *ptr != '\t' && *ptr != ' ' && *ptr != '\n' )
+                                       ptr++;
+                       }
+                       
+                       // Break if we have reached NULL
+                       if( *ptr == '\0' ) {
+                               LOG("ret->Lines[%i].Parts[%i] = '%s'", i, j, ret->Lines[i].Parts[j]);
+                               break;
+                       }
+                       if( *ptr == '\n' ) {
+                               *ptr = '\0';
+                               LOG("ret->Lines[%i].Parts[%i] = '%s'", i, j, ret->Lines[i].Parts[j]);
+                               ptr ++;
+                               break;
+                       }
+                       *ptr = '\0';    // Cap off string
+                       LOG("ret->Lines[%i].Parts[%i] = '%s'", i, j, ret->Lines[i].Parts[j]);
+                       ptr ++; // And increment for the next round
+               }
+       }
        
-       return pos;
+       LEAVE('p', ret);
+       return ret;
 }

UCC git Repository :: git.ucc.asn.au