Changed the x86 architecture to have tPAddr be 64-bits always
authorJohn Hodge <tpg@prelude.(none)>
Mon, 28 Dec 2009 13:20:37 +0000 (21:20 +0800)
committerJohn Hodge <tpg@prelude.(none)>
Mon, 28 Dec 2009 13:20:37 +0000 (21:20 +0800)
- tPAddr being a constant size allows PAE to be selected at
  runtime (when I complete it :))
- Related bugfixes (where tPAddr was assumed to be 32-bits)
- Also fixed bugs in the config file parser
- Added -g flag to the build (working on a disable switch)

14 files changed:
Kernel/Makefile
Kernel/Makefile.BuildNum
Kernel/arch/x86/include/arch.h
Kernel/arch/x86/include/mm_phys.h
Kernel/arch/x86/include/mm_virt.h
Kernel/arch/x86/include/proc.h
Kernel/arch/x86/link.ld
Kernel/arch/x86/mm_phys.c
Kernel/arch/x86/mm_virt.c
Kernel/arch/x86/proc.c
Kernel/bin/elf.c
Kernel/bin/elf.h
Kernel/include/binary.h
Kernel/system.c

index 10c63ff..427f4e0 100644 (file)
@@ -20,6 +20,11 @@ CFLAGS               += -Wall -Werror -O3 -fno-stack-protector -fno-builtin
 ASFLAGS                += -D ARCH=\"$(ARCH)\"
 LDFLAGS                += -T arch/$(ARCHDIR)/link.ld
 
+if $(KERNEL_DEBUG) != "" then
+       LDFLAGS += -g
+if $(KERNEL_DEBUG) != "" then
+       CFLAGS += -g
+
 OBJ = $(addprefix arch/$(ARCHDIR)/,$(A_OBJ))
 OBJ += heap.o messages.o debug.o modules.o lib.o syscalls.o system.o threads.o drvutil.o
 OBJ += binary.o bin/elf.o
@@ -54,7 +59,7 @@ apidoc:
 $(BIN): $(OBJ) $(MODS) arch/$(ARCHDIR)/link.ld Makefile
        @echo --- LD -o $(BIN)
        @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) $(MODS) -Map ../Map.$(ARCH).txt
-       @objdump $(BIN) -D > $(BIN).dsm
+       @objdump $(BIN) -D -S > $(BIN).dsm
        @wc -l $(SRCFILES) > LineCounts.$(ARCH).txt
        @echo BUILD_NUM = `calc $(BUILD_NUM)+1` > Makefile.BuildNum
 
index 65deeab..41c16ab 100644 (file)
@@ -1 +1 @@
-BUILD_NUM = 1084
+BUILD_NUM = 1124
index 77cdd70..0afc51d 100644 (file)
@@ -70,11 +70,7 @@ typedef signed long          Sint32;
 typedef signed long long       Sint64;
 typedef Uint   size_t;
 
-#if USE_PAE
 typedef Uint64 tPAddr;
-#else
-typedef Uint32 tPAddr;
-#endif
 typedef Uint32 tVAddr;
 
 typedef struct {
index 8d46109..2d35587 100644 (file)
@@ -7,8 +7,9 @@
 
 // === FUNCTIONS ===
 extern tPAddr  MM_AllocPhys();
-extern void    MM_RefPhys(Uint32 Addr);
-extern void    MM_DerefPhys(Uint32 Addr);
+extern tPAddr  MM_AllocPhysRange(int Pages);
+extern void    MM_RefPhys(tPAddr Addr);
+extern void    MM_DerefPhys(tPAddr Addr);
 extern int     MM_GetRefCount(tPAddr Addr);
 
 #endif
index 2dc3b30..ec6ca82 100644 (file)
@@ -10,7 +10,7 @@ extern void   MM_SetCR3(Uint32 CR3);
 extern tPAddr  MM_Allocate(tVAddr VAddr);
 extern void    MM_Deallocate(tVAddr VAddr);
 extern int     MM_Map(tVAddr VAddr, tPAddr PAddr);
-extern tVAddr  MM_Clone();
+extern tPAddr  MM_Clone();
 extern tVAddr  MM_NewKStack();
 extern tVAddr  MM_NewWorkerStack();
 
index 6619ec0..5a99c9c 100644 (file)
@@ -25,7 +25,7 @@ typedef struct sTSS {
        Uint32  ES, CS, DS, SS, FS, GS;
        Uint32  LDTR;
        Uint16  Resvd, IOPB;    // IO Permissions Bitmap
-} tTSS;
+} __attribute__((packed)) tTSS;
 
 // === FUNCTIONS ===
 extern void    Proc_Start();
index 7bce719..a142747 100644 (file)
@@ -36,7 +36,19 @@ SECTIONS {
                *(KEXPORT)
                gKernelSymbolsEnd = .;
 
+
        }
+       /*
+       .debug_abbrev : { *(.debug_abbrev) }
+       .debug_info : { *(.debug_info) }
+       .debug_line : { *(.debug_line) }
+       .debug_loc : { *(.debug_loc) }
+       .debug_pubnames : { *(.debug_pubnames) }
+       .debug_aranges : { *(.debug_aranges) }
+       .debug_ranges : { *(.debug_ranges) }
+       .debug_str : { *(.debug_str) }
+       .debug_frame : { *(.debug_frame) }
+       */
        
        .padata ALIGN (0x1000) : AT(ADDR(.padata) - 0xC0000000) {
                *(.padata)
index 1b79650..cbb48b0 100644 (file)
 extern void    gKernelEnd;
 
 // === PROTOTYPES ===
-Uint32 MM_AllocPhys();
-void   MM_RefPhys(Uint32 Addr);
-void   MM_DerefPhys(Uint32 Addr);
+tPAddr MM_AllocPhys();
+tPAddr MM_AllocPhysRange(int Pages);
+void   MM_RefPhys(tPAddr Addr);
+void   MM_DerefPhys(tPAddr Addr);
 
 // === GLOBALS ===
  int   giPhysAlloc = 0;
@@ -72,6 +73,7 @@ void MM_Install(tMBoot_Info *MBoot)
                MM_Allocate( REFERENCE_BASE + (num<<12) );
        }
        
+       LOG("Filling");
        // Fill references
        gaPageReferences = (void*)REFERENCE_BASE;
        memsetd(gaPageReferences, 1, kernelPages);
@@ -89,7 +91,7 @@ tPAddr MM_AllocPhys()
 {
         int    num = giPageCount / 32 / 32;
         int    a, b, c;
-       Uint32  ret;
+       tPAddr  ret;
        
        LOCK( &giPhysAlloc );
        
@@ -129,7 +131,7 @@ tPAddr MM_AllocPhysRange(int Pages)
 {
         int    num = giPageCount / 32 / 32;
         int    a, b, c;
-       Uint32  ret;
+       tPAddr  ret;
        
        LOCK( &giPhysAlloc );
        
index 02bc9ac..b87967d 100644 (file)
 
 #define INVLPG(addr)   __asm__ __volatile__ ("invlpg (%0)"::"r"(addr))
 
+#if USE_PAE
+typedef Uint64 tTabEnt;
+#else
+typedef Uint32 tTabEnt;
+#endif
+
 // === IMPORTS ===
 extern Uint32  gaInitPageDir[1024];
 extern Uint32  gaInitPageTable[1024];
@@ -55,12 +61,18 @@ void        MM_DumpTables(tVAddr Start, tVAddr End);
 tPAddr MM_DuplicatePage(tVAddr VAddr);
 
 // === GLOBALS ===
-tPAddr *gaPageTable = (void*)PAGE_TABLE_ADDR;
-tPAddr *gaPageDir = (void*)PAGE_DIR_ADDR;
-tPAddr *gaPageCR3 = (void*)PAGE_CR3_ADDR;
-tPAddr *gaTmpTable = (void*)TMP_TABLE_ADDR;
-tPAddr *gaTmpDir = (void*)TMP_DIR_ADDR;
-tPAddr *gTmpCR3 = (void*)TMP_CR3_ADDR;
+#define gaPageTable    ((tTabEnt*)PAGE_TABLE_ADDR)
+#define gaPageDir      ((tTabEnt*)PAGE_DIR_ADDR)
+#define gaPageCR3      ((tTabEnt*)PAGE_CR3_ADDR)
+#define gaTmpTable     ((tTabEnt*)TMP_TABLE_ADDR)
+#define gaTmpDir       ((tTabEnt*)TMP_DIR_ADDR)
+#define gTmpCR3        ((tTabEnt*)TMP_CR3_ADDR)
+//tPAddr       *gaPageTable = (void*)PAGE_TABLE_ADDR;
+//tPAddr       *gaPageDir = (void*)PAGE_DIR_ADDR;
+//tPAddr       *gaPageCR3 = (void*)PAGE_CR3_ADDR;
+//tPAddr       *gaTmpTable = (void*)TMP_TABLE_ADDR;
+//tPAddr       *gaTmpDir = (void*)TMP_DIR_ADDR;
+//tPAddr       *gTmpCR3 = (void*)TMP_CR3_ADDR;
  int   gilTempMappings = 0;
  int   gilTempFractal = 0;
 Uint32 gWorkerStacks[(NUM_WORKER_STACKS+31)/32];
@@ -75,6 +87,7 @@ void MM_PreinitVirtual()
 {
        gaInitPageDir[ 0 ] = 0;
        gaInitPageDir[ PAGE_TABLE_ADDR >> 22 ] = ((Uint)&gaInitPageDir - KERNEL_BASE) | 3;
+       INVLPG( PAGE_TABLE_ADDR );
 }
 
 /**
@@ -253,13 +266,17 @@ void MM_DumpTables(tVAddr Start, tVAddr End)
 tPAddr MM_Allocate(tVAddr VAddr)
 {
        tPAddr  paddr;
+       //ENTER("xVAddr", VAddr);
+       //__asm__ __volatile__ ("xchg %bx,%bx");
        // Check if the directory is mapped
        if( gaPageDir[ VAddr >> 22 ] == 0 )
        {
                // Allocate directory
                paddr = MM_AllocPhys();
+               //LOG("paddr = 0x%llx (new table)", paddr);
                if( paddr == 0 ) {
                        Warning("MM_Allocate - Out of Memory (Called by %p)", __builtin_return_address(0));
+                       LEAVE('i',0);
                        return 0;
                }
                // Map
@@ -268,19 +285,23 @@ tPAddr MM_Allocate(tVAddr VAddr)
                if(VAddr < MM_USER_MAX) gaPageDir[ VAddr >> 22 ] |= PF_USER;
                
                INVLPG( &gaPageDir[ VAddr >> 22 ] );
+               //LOG("Clearing new table");
                memsetd( &gaPageTable[ (VAddr >> 12) & ~0x3FF ], 0, 1024 );
        }
        // Check if the page is already allocated
        else if( gaPageTable[ VAddr >> 12 ] != 0 ) {
                Warning("MM_Allocate - Allocating to used address (%p)", VAddr);
+               //LEAVE('X', gaPageTable[ VAddr >> 12 ] & ~0xFFF);
                return gaPageTable[ VAddr >> 12 ] & ~0xFFF;
        }
        
        // Allocate
        paddr = MM_AllocPhys();
+       //LOG("paddr = 0x%llx", paddr);
        if( paddr == 0 ) {
                Warning("MM_Allocate - Out of Memory when allocating at %p (Called by %p)",
                        VAddr, __builtin_return_address(0));
+               //LEAVE('i',0);
                return 0;
        }
        // Map
@@ -290,6 +311,7 @@ tPAddr MM_Allocate(tVAddr VAddr)
        // Invalidate Cache for address
        INVLPG( VAddr & ~0xFFF );
        
+       //LEAVE('X', paddr);
        return paddr;
 }
 
@@ -694,7 +716,7 @@ tVAddr MM_NewWorkerStack()
  */
 void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
 {
-       tPAddr  *ent;
+       tTabEnt *ent;
        if( !(gaPageDir[VAddr >> 22] & 1) )     return ;
        if( !(gaPageTable[VAddr >> 12] & 1) )   return ;
        
index 60f015b..8b2e49b 100644 (file)
@@ -113,6 +113,10 @@ void ArchThreads_Init()
                gTSSs = &gTSS0;
        #if USE_MP
        }
+       #endif
+       
+       Log("sizeof(tTSS) = %i", sizeof(tTSS));
+       Log("sizeof(tGDT) = %i", sizeof(tGDT));
        
        // Initialise Double Fault TSS
        gGDT[5].LimitLow = sizeof(tTSS);
@@ -123,21 +127,23 @@ void ArchThreads_Init()
        gGDT[5].BaseMid = (Uint)&gDoubleFault_TSS >> 16;
        gGDT[5].BaseHi = (Uint)&gDoubleFault_TSS >> 24;
        
-       // Initialise TSS
+       #if USE_MP
+       // Initialise Normal TSS(s)
        for(pos=0;pos<giNumCPUs;pos++)
        {
        #else
        pos = 0;
        #endif
+               Log("pos = %i", pos);
                gTSSs[pos].SS0 = 0x10;
                gTSSs[pos].ESP0 = 0;    // Set properly by scheduler
+               gGDT[6+pos].BaseLow = ((Uint)(&gTSSs[pos])) & 0xFFFF;
+               gGDT[6+pos].BaseMid = ((Uint)(&gTSSs[pos])) >> 16;
+               gGDT[6+pos].BaseHi = ((Uint)(&gTSSs[pos])) >> 24;
                gGDT[6+pos].LimitLow = sizeof(tTSS);
                gGDT[6+pos].LimitHi = 0;
                gGDT[6+pos].Access = 0x89;      // Type
                gGDT[6+pos].Flags = 0x4;
-               gGDT[6+pos].BaseLow = (Uint)&gTSSs[pos] & 0xFFFF;
-               gGDT[6+pos].BaseMid = (Uint)&gTSSs[pos] >> 16;
-               gGDT[6+pos].BaseHi = (Uint)&gTSSs[pos] >> 24;
        #if USE_MP
        }
        for(pos=0;pos<giNumCPUs;pos++) {
index 2f37739..6719a41 100644 (file)
@@ -76,7 +76,7 @@ tBinary *Elf_Load(int fp)
        LOG("iPageCount = %i", iPageCount);\r
        \r
        // Allocate Information Structure\r
-       ret = malloc( sizeof(tBinary) + 3*sizeof(Uint)*iPageCount );\r
+       ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );\r
        // Fill Info Struct\r
        ret->Entry = hdr.entrypoint;\r
        ret->Base = -1;         // Set Base to maximum value\r
@@ -106,9 +106,7 @@ tBinary *Elf_Load(int fp)
                if(phtab[i].Type != PT_LOAD)    continue;\r
                \r
                // Find Base\r
-               if(phtab[i].VAddr < ret->Base)  ret->Base = phtab[i].VAddr;
-\r
-               k = 0;\r
+               if(phtab[i].VAddr < ret->Base)  ret->Base = phtab[i].VAddr;\r
                \r
                LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}",\r
                        i, phtab[i].VAddr, phtab[i].Offset, phtab[i].FileSize);\r
@@ -123,7 +121,7 @@ tBinary *Elf_Load(int fp)
                \r
                // Get Pages\r
                count = ( (phtab[i].VAddr&0xFFF) + phtab[i].FileSize + 0xFFF) >> 12;\r
-               for(;k<count;k++)\r
+               for( k = 0; k < count; k ++ )\r
                {\r
                        ret->Pages[j+k].Virtual = phtab[i].VAddr + (k<<12);\r
                        ret->Pages[j+k].Physical = phtab[i].Offset + (k<<12);   // Store the offset in the physical address\r
index a2ba394..07f5ec1 100644 (file)
@@ -33,7 +33,7 @@ struct sElf32_Ehdr {
        Uint16  shentsize;      //!< Section Header Entry Size\r
        Uint16  shentcount;     //!< Section Header Entry Count\r
        Uint16  shstrindex;     //!< Section Header String Table Index\r
-};\r
+} __attribute__ ((packed));\r
 \r
 /**\r
  \name Executable Types\r
@@ -101,7 +101,7 @@ struct sElf32_Shent {
        Uint32  info;\r
        Uint32  addralign;\r
        Uint32  entsize;\r
-}    //sizeof = 40\r
+} __attribute__ ((packed));    //sizeof = 40\r
 \r
 struct elf_sym_s {\r
        union {\r
@@ -113,7 +113,7 @@ struct elf_sym_s {
        Uint8   info;\r
        Uint8   other;\r
        Uint16  shndx;\r
-};\r
+} __attribute__ ((packed));\r
 #define        STN_UNDEF       0       // Undefined Symbol\r
 \r
 enum {\r
@@ -137,18 +137,18 @@ struct sElf32_Phdr {
        Uint32  MemSize;\r
        Uint32  Flags;\r
        Uint32  Align;\r
-};\r
+} __attribute__ ((packed));\r
 \r
 struct elf32_rel_s {\r
        Uint32  r_offset;\r
        Uint32  r_info;\r
-};\r
+} __attribute__ ((packed));\r
 \r
 struct elf32_rela_s {\r
        Uint32  r_offset;\r
        Uint32  r_info;\r
        Sint32  r_addend;\r
-};\r
+} __attribute__ ((packed));\r
 \r
 enum {\r
        R_386_NONE = 0, // none\r
@@ -172,7 +172,7 @@ enum {
 struct elf32_dyn_s {\r
        Uint32  d_tag;\r
        Uint32  d_val;  //Also d_ptr\r
-};\r
+} __attribute__ ((packed));\r
 \r
 enum {\r
        DT_NULL,        //!< Marks End of list\r
index ed163bd..a126551 100644 (file)
@@ -7,6 +7,20 @@
 #define _BINARY_H
 
 // === TYPES ===
+typedef struct sBinaryPage
+{
+       /**
+        * \brief Physical address, or file offset
+        * 
+        * Physical address of this page or, when the file is not yet
+        * loaded, this is a file offset (or -1 for uninitialised data)
+        */
+       tPAddr  Physical;
+       tVAddr  Virtual;        //!< Virtual load address
+       Uint16  Size;   //!< Number of bytes to load from the file
+       Uint16  Flags;  //!< Load Flags
+} __attribute__ ((packed))     tBinaryPage;
+
 /**
  * \brief Defines a binary file
  * 
@@ -57,18 +71,7 @@ typedef struct sBinary
         * \brief Array of pages defined by this binary
         * \note Contains \a NumPages entries
         */
-       struct {
-               /**
-                * \brief Physical address, or file offset
-                * 
-                * Physical address of this page or, when the file is not yet
-                * loaded, this is a file offset (or -1 for uninitialised data)
-                */
-               tPAddr  Physical;
-               tVAddr  Virtual;        //!< Virtual load address
-               Uint16  Size;   //!< Number of bytes to load from the file
-               Uint16  Flags;  //!< Load Flags
-       }       Pages[];
+       tBinaryPage     Pages[];
 }      tBinary;
 
 /**
index 66630ce..3d1ebca 100644 (file)
@@ -3,6 +3,7 @@
  * Architecture Independent System Init
  * system.c
  */
+#define DEBUG  1
 #include <common.h>
 
 // === TYPES ===
@@ -198,7 +199,7 @@ void System_ExecuteScript()
 {
         int    fp;
         int    fLen = 0;
-        int    i = 0;
+        int    i;
        char    *fData;
        tConfigFile     *file;
        tConfigLine     *line;
@@ -287,7 +288,7 @@ void System_ExecuteScript()
                }
                // Create Directory
                else if(strcmp(line->Parts[0], "mkdir") == 0) {
-                       if( line->nParts != 3 ) {
+                       if( line->nParts != 2 ) {
                                Warning("Configuration command 'mkdir' requires 1 argument, %i given",
                                        line->nParts-1);
                                continue;
@@ -297,7 +298,7 @@ void System_ExecuteScript()
                }
                // Spawn a process
                else if(strcmp(line->Parts[0], "spawn") == 0) {
-                       if( line->nParts != 3 ) {
+                       if( line->nParts != 2 ) {
                                Warning("Configuration command 'spawn' requires 1 argument, %i given",
                                        line->nParts-1);
                                continue;
@@ -315,6 +316,7 @@ void System_ExecuteScript()
        
        // 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 );
@@ -332,10 +334,12 @@ tConfigFile       *System_Int_ParseFile(char *FileData)
 {
        char    *ptr;
        char    *start;
-        int    nLines = 0;
+        int    nLines = 1;
         int    i, j;
        tConfigFile     *ret;
        
+       ENTER("pFileData", FileData);
+       
        // Prescan and count the number of lines
        for(ptr = FileData; *ptr; ptr++)
        {               
@@ -346,23 +350,14 @@ tConfigFile       *System_Int_ParseFile(char *FileData)
                        continue;
                }
                
-               #if 0   // Don't handle windows style EOLs
-               if(ptr[-1] == '\r')
-               {
-                       if( &ptr[-1] == FileData ) {
-                               nLines ++;
-                               continue;
-                       }
-                       if(ptr[-2] == '\\')     continue;
-               }
-               #endif
-               
                // Escaped EOL
                if(ptr[-1] == '\\')     continue;
                
                nLines ++;
        }
        
+       LOG("nLines = %i", nLines);
+       
        // Ok so we have `nLines` lines, now to allocate our return
        ret = malloc( sizeof(tConfigFile) + sizeof(tConfigLine)*nLines );
        ret->nLines = nLines;
@@ -382,12 +377,19 @@ tConfigFile       *System_Int_ParseFile(char *FileData)
                for(;;)
                {
                        // Read leading whitespace
-                       while( *ptr && (*ptr == '\t' || *ptr == ' ') )  ptr++;
+                       while( *ptr == '\t' || *ptr == ' ' )    ptr++;
                        
                        // End of line/file
-                       if( *ptr == '\0' || *ptr == '\n' )      break;
+                       if( *ptr == '\0' || *ptr == '\n' ) {
+                               if(*ptr == '\n')        ptr ++;
+                               break;
+                       }
                        // Comment
-                       if( *ptr == '#' || *ptr == ';' )        break;
+                       if( *ptr == '#' || *ptr == ';' ) {
+                               while( *ptr && *ptr != '\n' )   ptr ++;
+                               if(*ptr == '\n')        ptr ++;
+                               break;
+                       }
                        
                        ret->Lines[i].nParts ++;
                        // Quoted
@@ -398,10 +400,17 @@ tConfigFile       *System_Int_ParseFile(char *FileData)
                                continue;
                        }
                        // Unquoted
-                       while( *ptr && !(*ptr == '\t' || *ptr == ' ') )
+                       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 );
                
@@ -409,13 +418,19 @@ tConfigFile       *System_Int_ParseFile(char *FileData)
                for( ptr = start, j = 0; ; j++ )
                {
                        // Read leading whitespace
-                       while( *ptr && (*ptr == '\t' || *ptr == ' ') )  ptr++;
+                       while( *ptr == '\t' || *ptr == ' ' )    ptr++;
                        
                        // End of line/file
-                       if( *ptr == '\0' || *ptr == '\n' )      break;
+                       if( *ptr == '\0' || *ptr == '\n' ) {
+                               if(*ptr == '\n')        ptr ++;
+                               break;
+                       }
                        // Comment
-                       if( *ptr == '#' || *ptr == ';' )        break;
-                       
+                       if( *ptr == '#' || *ptr == ';' ) {
+                               while( *ptr && *ptr != '\n' )   ptr ++;
+                               if(*ptr == '\n')        ptr ++;
+                               break;
+                       }
                        
                        ret->Lines[i].Parts[j] = ptr;
                        
@@ -427,16 +442,27 @@ tConfigFile       *System_Int_ParseFile(char *FileData)
                        }
                        // Unquoted
                        else {
-                               while( *ptr && !(*ptr == '\t' || *ptr == ' ') )
+                               while( *ptr != '\t' && *ptr != ' ' && *ptr != '\n' )
                                        ptr++;
                        }
                        
                        // Break if we have reached NULL
-                       if( *ptr == '\0' )      break;
+                       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
                }
        }
        
+       LEAVE('p', ret);
        return ret;
 }

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