3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 PINI_SECTION IniFileSectionListHead
= NULL
;
26 ULONG IniFileSectionCount
= 0;
27 ULONG IniFileSettingCount
= 0;
30 BOOL
IniParseFile(PCHAR IniFileData
, ULONG IniFileSize
)
33 ULONG CurrentLineNumber
;
35 ULONG IniFileLineSize
;
37 PINI_SECTION CurrentSection
= NULL
;
38 PINI_SECTION_ITEM CurrentItem
= NULL
;
40 DbgPrint((DPRINT_INIFILE
, "IniParseFile() IniFileSize: %d\n", IniFileSize
));
42 // Start with an 80-byte buffer
44 IniFileLine
= MmAllocateMemory(IniFileLineSize
);
50 // Loop through each line and parse it
51 CurrentLineNumber
= 0;
53 while (CurrentOffset
< IniFileSize
)
55 // First check the line size and increase our buffer if necessary
56 if (IniFileLineSize
< IniGetNextLineSize(IniFileData
, IniFileSize
, CurrentOffset
))
58 IniFileLineSize
= IniGetNextLineSize(IniFileData
, IniFileSize
, CurrentOffset
);
59 MmFreeMemory(IniFileLine
);
60 IniFileLine
= MmAllocateMemory(IniFileLineSize
);
67 // Get the line of data
68 CurrentOffset
= IniGetNextLine(IniFileData
, IniFileSize
, IniFileLine
, IniFileLineSize
, CurrentOffset
);
69 LineLength
= strlen(IniFileLine
);
71 // If it is a blank line or a comment then skip it
72 if (IniIsLineEmpty(IniFileLine
, LineLength
) || IniIsCommentLine(IniFileLine
, LineLength
))
78 // Check if it is a new section
79 if (IniIsSectionName(IniFileLine
, LineLength
))
81 // Allocate a new section structure
82 CurrentSection
= MmAllocateMemory(sizeof(INI_SECTION
));
85 MmFreeMemory(IniFileLine
);
89 RtlZeroMemory(CurrentSection
, sizeof(INI_SECTION
));
91 // Allocate the section name buffer
92 CurrentSection
->SectionName
= MmAllocateMemory(IniGetSectionNameSize(IniFileLine
, LineLength
));
93 if (!CurrentSection
->SectionName
)
95 MmFreeMemory(CurrentSection
);
96 MmFreeMemory(IniFileLine
);
100 // Get the section name
101 IniExtractSectionName(CurrentSection
->SectionName
, IniFileLine
, LineLength
);
103 // Add it to the section list head
104 IniFileSectionCount
++;
105 if (IniFileSectionListHead
== NULL
)
107 IniFileSectionListHead
= CurrentSection
;
111 RtlListInsertTail((PLIST_ITEM
)IniFileSectionListHead
, (PLIST_ITEM
)CurrentSection
);
118 // Check if it is a setting
119 if (IniIsSetting(IniFileLine
, LineLength
))
121 // First check to make sure we're inside a [section]
122 if (CurrentSection
== NULL
)
124 printf("Error: freeldr.ini:%ld: Setting '%s' found outside of a [section].\n", CurrentLineNumber
, IniFileLine
);
125 printf("Press any key to continue...\n");
131 // Allocate a new item structure
132 CurrentItem
= MmAllocateMemory(sizeof(INI_SECTION_ITEM
));
135 MmFreeMemory(IniFileLine
);
139 RtlZeroMemory(CurrentItem
, sizeof(INI_SECTION_ITEM
));
141 // Allocate the setting name buffer
142 CurrentItem
->ItemName
= MmAllocateMemory(IniGetSettingNameSize(IniFileLine
, LineLength
));
143 if (!CurrentItem
->ItemName
)
145 MmFreeMemory(CurrentItem
);
146 MmFreeMemory(IniFileLine
);
150 // Allocate the setting value buffer
151 CurrentItem
->ItemValue
= MmAllocateMemory(IniGetSettingValueSize(IniFileLine
, LineLength
));
152 if (!CurrentItem
->ItemValue
)
154 MmFreeMemory(CurrentItem
->ItemName
);
155 MmFreeMemory(CurrentItem
);
156 MmFreeMemory(IniFileLine
);
160 // Get the section name
161 IniExtractSettingName(CurrentItem
->ItemName
, IniFileLine
, LineLength
);
162 IniExtractSettingValue(CurrentItem
->ItemValue
, IniFileLine
, LineLength
);
164 // Add it to the current section
165 IniFileSettingCount
++;
166 CurrentSection
->SectionItemCount
++;
167 if (CurrentSection
->SectionItemList
== NULL
)
169 CurrentSection
->SectionItemList
= CurrentItem
;
173 RtlListInsertTail((PLIST_ITEM
)CurrentSection
->SectionItemList
, (PLIST_ITEM
)CurrentItem
);
183 DbgPrint((DPRINT_INIFILE
, "Parsed %d sections and %d settings.\n", IniFileSectionCount
, IniFileSettingCount
));
184 DbgPrint((DPRINT_INIFILE
, "IniParseFile() done.\n"));
189 ULONG
IniGetNextLineSize(PCHAR IniFileData
, ULONG IniFileSize
, ULONG CurrentOffset
)
192 ULONG LineCharCount
= 0;
194 // Loop through counting chars until we hit the end of the
195 // file or we encounter a new line char
196 for (Idx
=0; (CurrentOffset
< IniFileSize
); CurrentOffset
++)
198 // Increment the line character count
201 // Check for new line char
202 if (IniFileData
[CurrentOffset
] == '\n')
209 // Add one for the NULL-terminator
212 // Send back line character count
213 return LineCharCount
;
216 ULONG
IniGetNextLine(PCHAR IniFileData
, ULONG IniFileSize
, PCHAR Buffer
, ULONG BufferSize
, ULONG CurrentOffset
)
220 // Loop through grabbing chars until we hit the end of the
221 // file or we encounter a new line char
222 for (Idx
=0; (CurrentOffset
< IniFileSize
); CurrentOffset
++)
224 // If we haven't exceeded our buffer size yet
225 // then store another char
226 if (Idx
< (BufferSize
- 1))
228 Buffer
[Idx
++] = IniFileData
[CurrentOffset
];
231 // Check for new line char
232 if (IniFileData
[CurrentOffset
] == '\n')
239 // Terminate the string
242 // Get rid of newline & linefeed characters (if any)
243 if((Buffer
[strlen(Buffer
)-1] == '\n') || (Buffer
[strlen(Buffer
)-1] == '\r'))
244 Buffer
[strlen(Buffer
)-1] = '\0';
245 if((Buffer
[strlen(Buffer
)-1] == '\n') || (Buffer
[strlen(Buffer
)-1] == '\r'))
246 Buffer
[strlen(Buffer
)-1] = '\0';
248 // Send back new offset
249 return CurrentOffset
;
252 BOOL
IniIsLineEmpty(PCHAR LineOfText
, ULONG TextLength
)
256 // Check for text (skipping whitespace)
257 for (Idx
=0; Idx
<TextLength
; Idx
++)
259 if ((LineOfText
[Idx
] == ' ') ||
260 (LineOfText
[Idx
] == '\t') ||
261 (LineOfText
[Idx
] == '\n') ||
262 (LineOfText
[Idx
] == '\r'))
275 BOOL
IniIsCommentLine(PCHAR LineOfText
, ULONG TextLength
)
279 // Check the first character (skipping whitespace)
280 // and make sure that it is an opening bracket
281 for (Idx
=0; Idx
<TextLength
; Idx
++)
283 if ((LineOfText
[Idx
] == ' ') ||
284 (LineOfText
[Idx
] == '\t'))
288 else if (LineOfText
[Idx
] == INI_FILE_COMMENT_CHAR
)
301 BOOL
IniIsSectionName(PCHAR LineOfText
, ULONG TextLength
)
305 // Check the first character (skipping whitespace)
306 // and make sure that it is an opening bracket
307 for (Idx
=0; Idx
<TextLength
; Idx
++)
309 if ((LineOfText
[Idx
] == ' ') ||
310 (LineOfText
[Idx
] == '\t'))
314 else if (LineOfText
[Idx
] == '[')
327 ULONG
IniGetSectionNameSize(PCHAR SectionNameLine
, ULONG LineLength
)
332 // Find the opening bracket (skipping whitespace)
333 for (Idx
=0; Idx
<LineLength
; Idx
++)
335 if ((SectionNameLine
[Idx
] == ' ') ||
336 (SectionNameLine
[Idx
] == '\t'))
340 else //if (SectionNameLine[Idx] == '[')
346 // Skip past the opening bracket
349 // Count the characters up until the closing bracket or EOL
350 for (NameSize
=0; Idx
<LineLength
; Idx
++)
352 if ((SectionNameLine
[Idx
] == ']') ||
353 (SectionNameLine
[Idx
] == '\0'))
358 // Increment the count
362 // Add one for the NULL-terminator
368 VOID
IniExtractSectionName(PCHAR SectionName
, PCHAR SectionNameLine
, ULONG LineLength
)
373 // Find the opening bracket (skipping whitespace)
374 for (Idx
=0; Idx
<LineLength
; Idx
++)
376 if ((SectionNameLine
[Idx
] == ' ') ||
377 (SectionNameLine
[Idx
] == '\t'))
381 else //if (SectionNameLine[Idx] == '[')
387 // Skip past the opening bracket
390 // Count the characters up until the closing bracket or EOL
391 for (DestIdx
=0; Idx
<LineLength
; Idx
++)
393 if ((SectionNameLine
[Idx
] == ']') ||
394 (SectionNameLine
[Idx
] == '\0'))
399 // Grab a character and increment DestIdx
400 SectionName
[DestIdx
] = SectionNameLine
[Idx
];
404 // Terminate the string
405 SectionName
[DestIdx
] = '\0';
408 BOOL
IniIsSetting(PCHAR LineOfText
, ULONG TextLength
)
412 // Basically just check for an '=' equals sign
413 for (Idx
=0; Idx
<TextLength
; Idx
++)
415 if (LineOfText
[Idx
] == '=')
424 ULONG
IniGetSettingNameSize(PCHAR SettingNameLine
, ULONG LineLength
)
430 for (Idx
=0; Idx
<LineLength
; Idx
++)
432 if ((SettingNameLine
[Idx
] == ' ') ||
433 (SettingNameLine
[Idx
] == '\t'))
443 // Count the characters up until the '=' equals sign or EOL
444 for (NameSize
=0; Idx
<LineLength
; Idx
++)
446 if ((SettingNameLine
[Idx
] == '=') ||
447 (SettingNameLine
[Idx
] == '\0'))
452 // Increment the count
456 // Add one for the NULL-terminator
462 ULONG
IniGetSettingValueSize(PCHAR SettingValueLine
, ULONG LineLength
)
468 for (Idx
=0; Idx
<LineLength
; Idx
++)
470 if ((SettingValueLine
[Idx
] == ' ') ||
471 (SettingValueLine
[Idx
] == '\t'))
481 // Skip the characters up until the '=' equals sign or EOL
482 for (; Idx
<LineLength
; Idx
++)
484 if (SettingValueLine
[Idx
] == '=')
490 // If we hit EOL then obviously the value size is zero
491 if (SettingValueLine
[Idx
] == '\0')
497 // Count the characters up until the EOL
498 for (ValueSize
=0; Idx
<LineLength
; Idx
++)
500 if (SettingValueLine
[Idx
] == '\0')
505 // Increment the count
509 // Add one for the NULL-terminator
515 VOID
IniExtractSettingName(PCHAR SettingName
, PCHAR SettingNameLine
, ULONG LineLength
)
521 for (Idx
=0; Idx
<LineLength
; Idx
++)
523 if ((SettingNameLine
[Idx
] == ' ') ||
524 (SettingNameLine
[Idx
] == '\t'))
534 // Get the characters up until the '=' equals sign or EOL
535 for (DestIdx
=0; Idx
<LineLength
; Idx
++)
537 if ((SettingNameLine
[Idx
] == '=') ||
538 (SettingNameLine
[Idx
] == '\0'))
543 // Grab a character and increment DestIdx
544 SettingName
[DestIdx
] = SettingNameLine
[Idx
];
548 // Terminate the string
549 SettingName
[DestIdx
] = '\0';
552 VOID
IniExtractSettingValue(PCHAR SettingValue
, PCHAR SettingValueLine
, ULONG LineLength
)
558 for (Idx
=0; Idx
<LineLength
; Idx
++)
560 if ((SettingValueLine
[Idx
] == ' ') ||
561 (SettingValueLine
[Idx
] == '\t'))
571 // Skip the characters up until the '=' equals sign or EOL
572 for (; Idx
<LineLength
; Idx
++)
574 if (SettingValueLine
[Idx
] == '=')
580 // If we hit EOL then obviously the value size is zero
581 if (SettingValueLine
[Idx
] == '\0')
583 SettingValue
[0] = '\0';
588 // Get the characters up until the EOL
589 for (DestIdx
=0; Idx
<LineLength
; Idx
++)
591 if (SettingValueLine
[Idx
] == '\0')
596 // Grab a character and increment DestIdx
597 SettingValue
[DestIdx
] = SettingValueLine
[Idx
];
601 // Terminate the string
602 SettingValue
[DestIdx
] = '\0';