VPR-6.0

libvpr/ReadLine.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <string.h>
00003 #include <stdlib.h>
00004 #include <assert.h>
00005 #include "util.h"
00006 #include "ReadLine.h"
00007 
00008 
00009 /** Pass in a pointer to a token list. Is freed and then set to null */
00010 void
00011 FreeTokens(INOUTP char ***TokensPtr)
00012 {
00013     assert(*TokensPtr);
00014     assert(**TokensPtr);
00015 
00016     free(**TokensPtr);          /* Free the string data */
00017     free(*TokensPtr);           /* Free token list */
00018     *TokensPtr = NULL;          /* Invalidate pointer since mem is gone */
00019 }
00020 
00021 
00022 /** Returns number of tokens in list. Zero if null list */
00023 int
00024 CountTokens(INP char **Tokens)
00025 {
00026     int count = 0;
00027 
00028     if(NULL == Tokens)
00029         {
00030             return 0;
00031         };
00032     while(Tokens[count])
00033         {
00034             ++count;
00035         };
00036     return count;
00037 }
00038 
00039 
00040 /** Reads in a single line from file, splits into tokens and allocates
00041  * a list of tokens. Returns the an array of character arrays with the
00042  * final item being marked by an empty string.
00043  * Returns NULL on EOF
00044  * NB: Token list is does as two allocations, one for pointer list
00045  * and one for character array. Free what pointer points to and then
00046  * free the pointer itself 
00047  */
00048 char **
00049 ReadLineTokens(INOUTP FILE * InFile,
00050                INOUTP int *LineNum)
00051 {
00052 
00053     enum
00054     { BUFFSIZE = 65536 };       /* This is much more than enough */
00055     char Buffer[BUFFSIZE];      /* Must match BUFFSIZE */
00056     char *Res;
00057     char *Last;
00058     char *Cur;
00059     char *Dst;
00060     char **Tokens;
00061     int TokenCount;
00062     int Len;
00063     int CurToken;
00064     boolean InToken;
00065 
00066     do
00067         {
00068             /* Read the string */
00069             Res = fgets(Buffer, BUFFSIZE, InFile);
00070             if(NULL == Res)
00071                 {
00072                     if(feof(InFile))
00073                         {
00074                             return NULL;        /* Return NULL on EOF */
00075                         }
00076                     else
00077                         {
00078                             printf(ERRTAG "Unexpected error reading file\n");
00079                             exit(1);
00080                         }
00081                 }
00082             ++(*LineNum);
00083 
00084             /* Strip newline if any */
00085             Last = Buffer + strlen(Buffer);
00086             if((Last > Buffer) && ('\n' == Last[-1]))
00087                 {
00088                     --Last;
00089                 }
00090             if((Last > Buffer) && ('\r' == Last[-1]))
00091                 {
00092                     --Last;
00093                 }
00094 
00095             /* Handle continued lines */
00096             while((Last > Buffer) && ('\\' == Last[-1]))
00097                 {
00098                     /* Strip off the backslash */
00099                     --Last;
00100 
00101                     /* Read next line by giving pointer to null-char as start for next */
00102                     Res = fgets(Last, (BUFFSIZE - (Last - Buffer)), InFile);
00103                     if(NULL == Res)
00104                         {
00105                             if(feof(InFile))
00106                                 {
00107                                     return NULL;        /* Return NULL on EOF */
00108                                 }
00109                             else
00110                                 {
00111                                     printf(ERRTAG
00112                                            "Unexpected error reading file\n");
00113                                     exit(1);
00114                                 }
00115                         }
00116                     ++(*LineNum);
00117 
00118                     /* Strip newline */
00119                     Last = Buffer + strlen(Buffer);
00120                     if((Last > Buffer) && ('\n' == Last[-1]))
00121                         {
00122                             --Last;
00123                         }
00124                     if((Last > Buffer) && ('\r' == Last[-1]))
00125                         {
00126                             --Last;
00127                         }
00128                 }
00129 
00130             /* Strip comment if any */
00131             Cur = Buffer;
00132             while(Cur < Last)
00133                 {
00134                     if('#' == *Cur)
00135                         {
00136                             Last = Cur;
00137                             break;
00138                         }
00139                     ++Cur;
00140                 }
00141 
00142             /* Count tokens and find size */
00143             assert(Last < (Buffer + BUFFSIZE));
00144             Len = 0;
00145             TokenCount = 0;
00146             Cur = Buffer;
00147             InToken = FALSE;
00148             while(Cur < Last)
00149                 {
00150                     if(InToken)
00151                         {
00152                             if((' ' == *Cur) || ('\t' == *Cur))
00153                                 {
00154                                     InToken = FALSE;
00155                                 }
00156                             else
00157                                 {
00158                                     ++Len;
00159                                 }
00160                         }
00161                     else
00162                         {
00163                             if((' ' != *Cur) && ('\t' != *Cur))
00164                                 {
00165                                     ++TokenCount;
00166                                     ++Len;
00167                                     InToken = TRUE;
00168                                 }
00169                         }
00170                     ++Cur;      /* Advance pointer */
00171                 }
00172         }
00173     while(0 == TokenCount);
00174 
00175     /* Find the size of mem to alloc. Use a contiguous block so is 
00176      * easy to deallocate */
00177     Len = (sizeof(char) * Len) +        /* Length of actual data */
00178         (sizeof(char) * TokenCount);    /* Null terminators */
00179 
00180     /* Alloc the pointer list and data list. Count the final 
00181      * empty string we will use as list terminator */
00182     Tokens = (char **)my_malloc(sizeof(char *) * (TokenCount + 1));
00183     *Tokens = (char *)my_malloc(sizeof(char) * Len);
00184 
00185     /* Copy tokens to result */
00186     Cur = Buffer;
00187     Dst = *Tokens;
00188     InToken = FALSE;
00189     CurToken = 0;
00190     while(Cur < Last)
00191         {
00192             if(InToken)
00193                 {
00194                     if((' ' == *Cur) || ('\t' == *Cur))
00195                         {
00196                             InToken = FALSE;
00197                             *Dst = '\0';        /* Null term token */
00198                             ++Dst;
00199                             ++CurToken;
00200                         }
00201                     else
00202                         {
00203                             *Dst = *Cur;        /* Copy char */
00204                             ++Dst;
00205                         }
00206                 }
00207             else
00208                 {
00209                     if((' ' != *Cur) && ('\t' != *Cur))
00210                         {
00211                             Tokens[CurToken] = Dst;     /* Set token start pointer */
00212                             *Dst = *Cur;        /* Copy char */
00213                             ++Dst;
00214                             InToken = TRUE;
00215                         }
00216                 }
00217             ++Cur;              /* Advance pointer */
00218         }
00219     if(InToken)
00220         {
00221             *Dst = '\0';        /* Null term final token */
00222             ++Dst;
00223             ++CurToken;
00224         }
00225     assert(CurToken == TokenCount);
00226 
00227     /* Set the final empty string entry */
00228     Tokens[CurToken] = NULL;
00229 
00230     /* Return the string list */
00231     return Tokens;
00232 }
00233