VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
ReadLine.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <assert.h>
5 #include "util.h"
6 #include "ReadLine.h"
7 
8 /* Pass in a pointer to a token list. Is freed and then set to null */
9 void FreeTokens(INOUTP char ***TokensPtr) {
10  assert(*TokensPtr);
11  assert(**TokensPtr);
12 
13  free(**TokensPtr); /* Free the string data */
14  free(*TokensPtr); /* Free token list */
15  *TokensPtr = NULL; /* Invalidate pointer since mem is gone */
16 }
17 
18 /* Returns number of tokens in list. Zero if null list */
19 int CountTokens(INP char **Tokens) {
20  int count = 0;
21 
22  if (NULL == Tokens) {
23  return 0;
24  };
25  while (Tokens[count]) {
26  ++count;
27  };
28  return count;
29 }
30 
31 /* Reads in a single line from file, splits into tokens and allocates
32  * a list of tokens. Returns the an array of character arrays with the
33  * final item being marked by an empty string.
34  * Returns NULL on EOF
35  * NB: Token list is does as two allocations, one for pointer list
36  * and one for character array. Free what pointer points to and then
37  * free the pointer itself */
38 char **
39 ReadLineTokens(INOUTP FILE * InFile, INOUTP int *LineNum) {
40 
41  enum {
42  BUFFSIZE = 65536
43  };
44  /* This is much more than enough */
45  char Buffer[BUFFSIZE]; /* Must match BUFFSIZE */
46  char *Res;
47  char *Last;
48  char *Cur;
49  char *Dst;
50  char **Tokens;
51  int TokenCount;
52  int Len;
53  int CurToken;
54  boolean InToken;
55 
56  do {
57  /* Read the string */
58  Res = fgets(Buffer, BUFFSIZE, InFile);
59  if (NULL == Res) {
60  if (feof(InFile)) {
61  return NULL; /* Return NULL on EOF */
62  } else {
63  vpr_printf(TIO_MESSAGE_ERROR, "Unexpected error reading file\n");
64  exit(1);
65  }
66  }
67  ++(*LineNum);
68 
69  /* Strip newline if any */
70  Last = Buffer + strlen(Buffer);
71  if ((Last > Buffer) && ('\n' == Last[-1])) {
72  --Last;
73  }
74  if ((Last > Buffer) && ('\r' == Last[-1])) {
75  --Last;
76  }
77 
78  /* Handle continued lines */
79  while ((Last > Buffer) && ('\\' == Last[-1])) {
80  /* Strip off the backslash */
81  --Last;
82 
83  /* Read next line by giving pointer to null-char as start for next */
84  Res = fgets(Last, (BUFFSIZE - (Last - Buffer)), InFile);
85  if (NULL == Res) {
86  if (feof(InFile)) {
87  return NULL; /* Return NULL on EOF */
88  } else {
89  vpr_printf(TIO_MESSAGE_ERROR,
90  "Unexpected error reading file\n");
91  exit(1);
92  }
93  }
94  ++(*LineNum);
95 
96  /* Strip newline */
97  Last = Buffer + strlen(Buffer);
98  if ((Last > Buffer) && ('\n' == Last[-1])) {
99  --Last;
100  }
101  if ((Last > Buffer) && ('\r' == Last[-1])) {
102  --Last;
103  }
104  }
105 
106  /* Strip comment if any */
107  Cur = Buffer;
108  while (Cur < Last) {
109  if ('#' == *Cur) {
110  Last = Cur;
111  break;
112  }
113  ++Cur;
114  }
115 
116  /* Count tokens and find size */
117  assert(Last < (Buffer + BUFFSIZE));
118  Len = 0;
119  TokenCount = 0;
120  Cur = Buffer;
121  InToken = FALSE;
122  while (Cur < Last) {
123  if (InToken) {
124  if ((' ' == *Cur) || ('\t' == *Cur)) {
125  InToken = FALSE;
126  } else {
127  ++Len;
128  }
129  } else {
130  if ((' ' != *Cur) && ('\t' != *Cur)) {
131  ++TokenCount;
132  ++Len;
133  InToken = TRUE;
134  }
135  }
136  ++Cur; /* Advance pointer */
137  }
138  } while (0 == TokenCount);
139 
140  /* Find the size of mem to alloc. Use a contiguous block so is
141  * easy to deallocate */
142  Len = (sizeof(char) * Len) + /* Length of actual data */
143  (sizeof(char) * TokenCount); /* Null terminators */
144 
145  /* Alloc the pointer list and data list. Count the final
146  * empty string we will use as list terminator */
147  Tokens = (char **) my_malloc(sizeof(char *) * (TokenCount + 1));
148  *Tokens = (char *) my_malloc(sizeof(char) * Len);
149 
150  /* Copy tokens to result */
151  Cur = Buffer;
152  Dst = *Tokens;
153  InToken = FALSE;
154  CurToken = 0;
155  while (Cur < Last) {
156  if (InToken) {
157  if ((' ' == *Cur) || ('\t' == *Cur)) {
158  InToken = FALSE;
159  *Dst = '\0'; /* Null term token */
160  ++Dst;
161  ++CurToken;
162  } else {
163  *Dst = *Cur; /* Copy char */
164  ++Dst;
165  }
166  } else {
167  if ((' ' != *Cur) && ('\t' != *Cur)) {
168  Tokens[CurToken] = Dst; /* Set token start pointer */
169  *Dst = *Cur; /* Copy char */
170  ++Dst;
171  InToken = TRUE;
172  }
173  }
174  ++Cur; /* Advance pointer */
175  }
176  if (InToken) {
177  *Dst = '\0'; /* Null term final token */
178  ++Dst;
179  ++CurToken;
180  }
181  assert(CurToken == TokenCount);
182 
183  /* Set the final empty string entry */
184  Tokens[CurToken] = NULL;
185 
186  /* Return the string list */
187  return Tokens;
188 }
189 
#define INOUTP
Definition: util.h:21
Definition: util.h:12
char ** ReadLineTokens(INOUTP FILE *InFile, INOUTP int *LineNum)
Definition: ReadLine.c:39
static void * my_malloc(int ibytes)
Definition: graphics.c:499
#define INP
Definition: util.h:19
int CountTokens(INP char **Tokens)
Definition: ReadLine.c:19
void FreeTokens(INOUTP char ***TokensPtr)
Definition: ReadLine.c:9
messagelogger vpr_printf
Definition: util.c:17
Definition: util.h:12