ReactOS  0.4.12-dev-918-g6c6e7b8
parse.c
Go to the documentation of this file.
1 /*
2  * FreeLoader
3  * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include <freeldr.h>
21 #include <debug.h>
22 
24 
29 
30 
31 BOOLEAN IniParseFile(PCHAR IniFileData, ULONG IniFileSize)
32 {
33  ULONG CurrentOffset;
34  ULONG CurrentLineNumber;
35  PCHAR IniFileLine;
36  ULONG IniFileLineSize;
37  ULONG LineLength;
38  PINI_SECTION CurrentSection = NULL;
39  PINI_SECTION_ITEM CurrentItem = NULL;
40 
41  TRACE("IniParseFile() IniFileSize: %d\n", IniFileSize);
42 
44  {
47  }
48 
49  // Start with an 80-byte buffer
50  IniFileLineSize = 80;
51  IniFileLine = FrLdrTempAlloc(IniFileLineSize, TAG_INI_FILE);
52  if (!IniFileLine)
53  {
54  return FALSE;
55  }
56 
57  // Loop through each line and parse it
58  CurrentLineNumber = 0;
59  CurrentOffset = 0;
60  while (CurrentOffset < IniFileSize)
61  {
62  // First check the line size and increase our buffer if necessary
63  if (IniFileLineSize < IniGetNextLineSize(IniFileData, IniFileSize, CurrentOffset))
64  {
65  IniFileLineSize = IniGetNextLineSize(IniFileData, IniFileSize, CurrentOffset);
66  FrLdrTempFree(IniFileLine, TAG_INI_FILE);
67  IniFileLine = FrLdrTempAlloc(IniFileLineSize, TAG_INI_FILE);
68  if (!IniFileLine)
69  {
70  return FALSE;
71  }
72  }
73 
74  // Get the line of data
75  CurrentOffset = IniGetNextLine(IniFileData, IniFileSize, IniFileLine, IniFileLineSize, CurrentOffset);
76  LineLength = (ULONG)strlen(IniFileLine);
77 
78  // If it is a blank line or a comment then skip it
79  if (IniIsLineEmpty(IniFileLine, LineLength) || IniIsCommentLine(IniFileLine, LineLength))
80  {
81  CurrentLineNumber++;
82  continue;
83  }
84 
85  // Check if it is a new section
86  if (IniIsSectionName(IniFileLine, LineLength))
87  {
88  // Allocate a new section structure
89  CurrentSection = FrLdrTempAlloc(sizeof(INI_SECTION), TAG_INI_SECTION);
90  if (!CurrentSection)
91  {
92  FrLdrTempFree(IniFileLine, TAG_INI_FILE);
93  return FALSE;
94  }
95 
96  RtlZeroMemory(CurrentSection, sizeof(INI_SECTION));
97 
98  // Allocate the section name buffer
99  CurrentSection->SectionName = FrLdrTempAlloc(IniGetSectionNameSize(IniFileLine, LineLength), TAG_INI_NAME);
100  if (!CurrentSection->SectionName)
101  {
102  FrLdrTempFree(CurrentSection, TAG_INI_FILE);
103  FrLdrTempFree(IniFileLine, TAG_INI_FILE);
104  return FALSE;
105  }
106 
107  // Get the section name
108  IniExtractSectionName(CurrentSection->SectionName, IniFileLine, LineLength);
109  InitializeListHead(&CurrentSection->SectionItemList);
110 
111  // Add it to the section list head
113  InsertTailList(&IniFileSectionListHead, &CurrentSection->ListEntry);
114 
115  CurrentLineNumber++;
116  continue;
117  }
118 
119  // Check if it is a setting
120  if (IniIsSetting(IniFileLine, LineLength))
121  {
122  // First check to make sure we're inside a [section]
123  if (CurrentSection == NULL)
124  {
125  printf("Error: freeldr.ini:%lu: Setting '%s' found outside of a [section].\n", CurrentLineNumber, IniFileLine);
126  printf("Press any key to continue...\n");
127  MachConsGetCh();
128  CurrentLineNumber++;
129  continue;
130  }
131 
132  // Allocate a new item structure
133  CurrentItem = FrLdrTempAlloc(sizeof(INI_SECTION_ITEM), TAG_INI_SECTION_ITEM);
134  if (!CurrentItem)
135  {
136  FrLdrTempFree(IniFileLine, TAG_INI_FILE);
137  return FALSE;
138  }
139 
140  RtlZeroMemory(CurrentItem, sizeof(INI_SECTION_ITEM));
141 
142  // Allocate the setting name buffer
143  CurrentItem->ItemName = FrLdrTempAlloc(IniGetSettingNameSize(IniFileLine, LineLength), TAG_INI_NAME);
144  if (!CurrentItem->ItemName)
145  {
146  FrLdrTempFree(CurrentItem, TAG_INI_SECTION_ITEM);
147  FrLdrTempFree(IniFileLine, TAG_INI_FILE);
148  return FALSE;
149  }
150 
151  // Allocate the setting value buffer
152  CurrentItem->ItemValue = FrLdrTempAlloc(IniGetSettingValueSize(IniFileLine, LineLength), TAG_INI_VALUE);
153  if (!CurrentItem->ItemValue)
154  {
155  FrLdrTempFree(CurrentItem->ItemName, TAG_INI_NAME);
156  FrLdrTempFree(CurrentItem, TAG_INI_SECTION_ITEM);
157  FrLdrTempFree(IniFileLine, TAG_INI_FILE);
158  return FALSE;
159  }
160 
161  // Get the section name
162  IniExtractSettingName(CurrentItem->ItemName, IniFileLine, LineLength);
163  IniExtractSettingValue(CurrentItem->ItemValue, IniFileLine, LineLength);
164 
165  // Add it to the current section
167  CurrentSection->SectionItemCount++;
168  InsertTailList(&CurrentSection->SectionItemList, &CurrentItem->ListEntry);
169 
170  CurrentLineNumber++;
171  continue;
172  }
173 
174  CurrentLineNumber++;
175  }
176 
177  FrLdrTempFree(IniFileLine, TAG_INI_FILE);
178 
179  TRACE("Parsed %d sections and %d settings.\n", IniFileSectionCount, IniFileSettingCount);
180  TRACE("IniParseFile() done.\n");
181 
182  return TRUE;
183 }
184 
185 ULONG IniGetNextLineSize(PCHAR IniFileData, ULONG IniFileSize, ULONG CurrentOffset)
186 {
187  ULONG LineCharCount = 0;
188 
189  // Loop through counting chars until we hit the end of the
190  // file or we encounter a new line char
191  for (; (CurrentOffset < IniFileSize); CurrentOffset++)
192  {
193  // Increment the line character count
194  LineCharCount++;
195 
196  // Check for new line char
197  if (IniFileData[CurrentOffset] == '\n')
198  {
199  break;
200  }
201  }
202 
203  // Add one for the NULL-terminator
204  LineCharCount++;
205 
206  // Send back line character count
207  return LineCharCount;
208 }
209 
210 ULONG IniGetNextLine(PCHAR IniFileData, ULONG IniFileSize, PCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset)
211 {
212  ULONG Idx;
213 
214  // Loop through grabbing chars until we hit the end of the
215  // file or we encounter a new line char
216  for (Idx=0; (CurrentOffset < IniFileSize); CurrentOffset++)
217  {
218  // If we haven't exceeded our buffer size yet
219  // then store another char
220  if (Idx < (BufferSize - 1))
221  {
222  Buffer[Idx++] = IniFileData[CurrentOffset];
223  }
224 
225  // Check for new line char
226  if (IniFileData[CurrentOffset] == '\n')
227  {
228  CurrentOffset++;
229  break;
230  }
231  }
232 
233  // Terminate the string
234  Buffer[Idx] = '\0';
235 
236  // Get rid of newline & linefeed characters (if any)
237  while(Idx && (Buffer[--Idx] == '\n' || Buffer[Idx] == '\r'))
238  Buffer[Idx] = '\0';
239 
240  // Send back new offset
241  return CurrentOffset;
242 }
243 
244 BOOLEAN IniIsLineEmpty(PCHAR LineOfText, ULONG TextLength)
245 {
246  ULONG Idx;
247 
248  // Check for text (skipping whitespace)
249  for (Idx=0; Idx<TextLength; Idx++)
250  {
251  if ((LineOfText[Idx] == ' ') ||
252  (LineOfText[Idx] == '\t') ||
253  (LineOfText[Idx] == '\n') ||
254  (LineOfText[Idx] == '\r'))
255  {
256  continue;
257  }
258  else
259  {
260  return FALSE;
261  }
262  }
263 
264  return TRUE;
265 }
266 
267 BOOLEAN IniIsCommentLine(PCHAR LineOfText, ULONG TextLength)
268 {
269  ULONG Idx;
270 
271  // Check the first character (skipping whitespace)
272  // and make sure that it is an opening bracket
273  for (Idx=0; Idx<TextLength; Idx++)
274  {
275  if ((LineOfText[Idx] == ' ') ||
276  (LineOfText[Idx] == '\t'))
277  {
278  continue;
279  }
280  else if (LineOfText[Idx] == INI_FILE_COMMENT_CHAR)
281  {
282  return TRUE;
283  }
284  else
285  {
286  break;
287  }
288  }
289 
290  return FALSE;
291 }
292 
293 BOOLEAN IniIsSectionName(PCHAR LineOfText, ULONG TextLength)
294 {
295  ULONG Idx;
296 
297  // Check the first character (skipping whitespace)
298  // and make sure that it is an opening bracket
299  for (Idx=0; Idx<TextLength; Idx++)
300  {
301  if ((LineOfText[Idx] == ' ') ||
302  (LineOfText[Idx] == '\t'))
303  {
304  continue;
305  }
306  else if (LineOfText[Idx] == '[')
307  {
308  return TRUE;
309  }
310  else
311  {
312  break;
313  }
314  }
315 
316  return FALSE;
317 }
318 
319 ULONG IniGetSectionNameSize(PCHAR SectionNameLine, ULONG LineLength)
320 {
321  ULONG Idx;
322  ULONG NameSize;
323 
324  // Find the opening bracket (skipping whitespace)
325  for (Idx=0; Idx<LineLength; Idx++)
326  {
327  if ((SectionNameLine[Idx] == ' ') ||
328  (SectionNameLine[Idx] == '\t'))
329  {
330  continue;
331  }
332  else //if (SectionNameLine[Idx] == '[')
333  {
334  break;
335  }
336  }
337 
338  // Skip past the opening bracket
339  Idx++;
340 
341  // Count the characters up until the closing bracket or EOL
342  for (NameSize=0; Idx<LineLength; Idx++)
343  {
344  if ((SectionNameLine[Idx] == ']') ||
345  (SectionNameLine[Idx] == '\0'))
346  {
347  break;
348  }
349 
350  // Increment the count
351  NameSize++;
352  }
353 
354  // Add one for the NULL-terminator
355  NameSize++;
356 
357  return NameSize;
358 }
359 
360 VOID IniExtractSectionName(PCHAR SectionName, PCHAR SectionNameLine, ULONG LineLength)
361 {
362  ULONG Idx;
363  ULONG DestIdx;
364 
365  // Find the opening bracket (skipping whitespace)
366  for (Idx=0; Idx<LineLength; Idx++)
367  {
368  if ((SectionNameLine[Idx] == ' ') ||
369  (SectionNameLine[Idx] == '\t'))
370  {
371  continue;
372  }
373  else //if (SectionNameLine[Idx] == '[')
374  {
375  break;
376  }
377  }
378 
379  // Skip past the opening bracket
380  Idx++;
381 
382  // Count the characters up until the closing bracket or EOL
383  for (DestIdx=0; Idx<LineLength; Idx++)
384  {
385  if ((SectionNameLine[Idx] == ']') ||
386  (SectionNameLine[Idx] == '\0'))
387  {
388  break;
389  }
390 
391  // Grab a character and increment DestIdx
392  SectionName[DestIdx] = SectionNameLine[Idx];
393  DestIdx++;
394  }
395 
396  // Terminate the string
397  SectionName[DestIdx] = '\0';
398 }
399 
400 BOOLEAN IniIsSetting(PCHAR LineOfText, ULONG TextLength)
401 {
402  ULONG Idx;
403 
404  // Basically just check for an '=' equals sign
405  for (Idx=0; Idx<TextLength; Idx++)
406  {
407  if (LineOfText[Idx] == '=')
408  {
409  return TRUE;
410  }
411  }
412 
413  return FALSE;
414 }
415 
416 ULONG IniGetSettingNameSize(PCHAR SettingNameLine, ULONG LineLength)
417 {
418  ULONG Idx;
419  ULONG NameSize;
420 
421  // Skip whitespace
422  for (Idx=0; Idx<LineLength; Idx++)
423  {
424  if ((SettingNameLine[Idx] == ' ') ||
425  (SettingNameLine[Idx] == '\t'))
426  {
427  continue;
428  }
429  else
430  {
431  break;
432  }
433  }
434 
435  // Count the characters up until the '=' equals sign or EOL
436  for (NameSize=0; Idx<LineLength; Idx++)
437  {
438  if ((SettingNameLine[Idx] == '=') ||
439  (SettingNameLine[Idx] == '\0'))
440  {
441  break;
442  }
443 
444  // Increment the count
445  NameSize++;
446  }
447 
448  // Add one for the NULL-terminator
449  NameSize++;
450 
451  return NameSize;
452 }
453 
454 ULONG IniGetSettingValueSize(PCHAR SettingValueLine, ULONG LineLength)
455 {
456  ULONG Idx;
457  ULONG ValueSize;
458 
459  // Skip whitespace
460  for (Idx=0; Idx<LineLength; Idx++)
461  {
462  if ((SettingValueLine[Idx] == ' ') ||
463  (SettingValueLine[Idx] == '\t'))
464  {
465  continue;
466  }
467  else
468  {
469  break;
470  }
471  }
472 
473  // Skip the characters up until the '=' equals sign or EOL
474  for (; Idx<LineLength; Idx++)
475  {
476  if (SettingValueLine[Idx] == '=')
477  {
478  Idx++;
479  break;
480  }
481 
482  // If we hit EOL then obviously the value size is zero
483  if (SettingValueLine[Idx] == '\0')
484  {
485  return 0;
486  }
487  }
488 
489  // Count the characters up until the EOL
490  for (ValueSize=0; Idx<LineLength; Idx++)
491  {
492  if (SettingValueLine[Idx] == '\0')
493  {
494  break;
495  }
496 
497  // Increment the count
498  ValueSize++;
499  }
500 
501  // Add one for the NULL-terminator
502  ValueSize++;
503 
504  return ValueSize;
505 }
506 
507 VOID IniExtractSettingName(PCHAR SettingName, PCHAR SettingNameLine, ULONG LineLength)
508 {
509  ULONG Idx;
510  ULONG DestIdx;
511 
512  // Skip whitespace
513  for (Idx=0; Idx<LineLength; Idx++)
514  {
515  if ((SettingNameLine[Idx] == ' ') ||
516  (SettingNameLine[Idx] == '\t'))
517  {
518  continue;
519  }
520  else
521  {
522  break;
523  }
524  }
525 
526  // Get the characters up until the '=' equals sign or EOL
527  for (DestIdx=0; Idx<LineLength; Idx++)
528  {
529  if ((SettingNameLine[Idx] == '=') ||
530  (SettingNameLine[Idx] == '\0'))
531  {
532  break;
533  }
534 
535  // Grab a character and increment DestIdx
536  SettingName[DestIdx] = SettingNameLine[Idx];
537  DestIdx++;
538  }
539 
540  // Terminate the string
541  SettingName[DestIdx] = '\0';
542 }
543 
544 VOID IniExtractSettingValue(PCHAR SettingValue, PCHAR SettingValueLine, ULONG LineLength)
545 {
546  ULONG Idx;
547  ULONG DestIdx;
548 
549  // Skip whitespace
550  for (Idx=0; Idx<LineLength; Idx++)
551  {
552  if ((SettingValueLine[Idx] == ' ') ||
553  (SettingValueLine[Idx] == '\t'))
554  {
555  continue;
556  }
557  else
558  {
559  break;
560  }
561  }
562 
563  // Skip the characters up until the '=' equals sign or EOL
564  for (; Idx<LineLength; Idx++)
565  {
566  if (SettingValueLine[Idx] == '=')
567  {
568  Idx++;
569  break;
570  }
571 
572  // If we hit EOL then obviously the value size is zero
573  if (SettingValueLine[Idx] == '\0')
574  {
575  SettingValue[0] = '\0';
576  return;
577  }
578  }
579 
580  // Get the characters up until the EOL
581  for (DestIdx=0; Idx<LineLength; Idx++)
582  {
583  if (SettingValueLine[Idx] == '\0')
584  {
585  break;
586  }
587 
588  // Grab a character and increment DestIdx
589  SettingValue[DestIdx] = SettingValueLine[Idx];
590  DestIdx++;
591  }
592 
593  // Terminate the string
594  SettingValue[DestIdx] = '\0';
595 }
signed char * PCHAR
Definition: retypes.h:7
PCHAR ItemValue
Definition: inifile.h:37
#define TRUE
Definition: types.h:120
#define MachConsGetCh()
Definition: machine.h:88
#define TAG_INI_VALUE
Definition: inifile.h:28
#define INI_FILE_COMMENT_CHAR
Definition: inifile.h:22
#define TAG_INI_NAME
Definition: inifile.h:27
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
VOID IniExtractSettingValue(PCHAR SettingValue, PCHAR SettingValueLine, ULONG LineLength)
Definition: parse.c:544
DBG_DEFAULT_CHANNEL(INIFILE)
LIST_ENTRY ListEntry
Definition: inifile.h:48
#define InsertTailList(ListHead, Entry)
LIST_ENTRY ListEntry
Definition: inifile.h:35
BOOLEAN IniParseFile(PCHAR IniFileData, ULONG IniFileSize)
Definition: parse.c:31
BOOLEAN IniIsSectionName(PCHAR LineOfText, ULONG TextLength)
Definition: parse.c:293
BOOLEAN IniFileSectionInitialized
Definition: parse.c:26
ULONG IniFileSettingCount
Definition: parse.c:28
VOID IniExtractSectionName(PCHAR SectionName, PCHAR SectionNameLine, ULONG LineLength)
Definition: parse.c:360
ULONG IniGetNextLine(PCHAR IniFileData, ULONG IniFileSize, PCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset)
Definition: parse.c:210
ULONG IniGetSettingValueSize(PCHAR SettingValueLine, ULONG LineLength)
Definition: parse.c:454
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
PCHAR ItemName
Definition: inifile.h:36
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
BOOLEAN IniIsLineEmpty(PCHAR LineOfText, ULONG TextLength)
Definition: parse.c:244
BOOLEAN IniIsCommentLine(PCHAR LineOfText, ULONG TextLength)
Definition: parse.c:267
ULONG SectionItemCount
Definition: inifile.h:50
#define TRACE(s)
Definition: solgame.cpp:4
LIST_ENTRY IniFileSectionListHead
Definition: parse.c:25
ULONG IniGetSectionNameSize(PCHAR SectionNameLine, ULONG LineLength)
Definition: parse.c:319
ULONG IniFileSectionCount
Definition: parse.c:27
#define TAG_INI_SECTION_ITEM
Definition: inifile.h:26
#define BufferSize
Definition: classpnp.h:419
ULONG IniGetSettingNameSize(PCHAR SettingNameLine, ULONG LineLength)
Definition: parse.c:416
LIST_ENTRY SectionItemList
Definition: inifile.h:51
Definition: typedefs.h:117
#define TAG_INI_FILE
Definition: inifile.h:24
ULONG IniGetNextLineSize(PCHAR IniFileData, ULONG IniFileSize, ULONG CurrentOffset)
Definition: parse.c:185
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
PCHAR SectionName
Definition: inifile.h:49
VOID IniExtractSettingName(PCHAR SettingName, PCHAR SettingNameLine, ULONG LineLength)
Definition: parse.c:507
BOOLEAN IniIsSetting(PCHAR LineOfText, ULONG TextLength)
Definition: parse.c:400
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define TAG_INI_SECTION
Definition: inifile.h:25
#define printf
Definition: config.h:203
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186