VPR-6.0
|
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