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.
28 PINI_SECTION IniFileSectionListHead
= NULL
;
29 ULONG IniFileSectionCount
= 0;
30 ULONG IniFileSettingCount
= 0;
33 BOOL
IniParseFile(PCHAR IniFileData
, ULONG IniFileSize
)
36 ULONG CurrentLineNumber
;
38 ULONG IniFileLineSize
;
40 PINI_SECTION CurrentSection
= NULL
;
41 PINI_SECTION_ITEM CurrentItem
= NULL
;
43 DbgPrint((DPRINT_INIFILE
, "IniParseFile() IniFileSize: %d\n", IniFileSize
));
45 // Start with an 80-byte buffer
47 IniFileLine
= MmAllocateMemory(IniFileLineSize
);
53 // Loop through each line and parse it
54 CurrentLineNumber
= 0;
56 while (CurrentOffset
< IniFileSize
)
58 // First check the line size and increase our buffer if necessary
59 if (IniFileLineSize
< IniGetNextLineSize(IniFileData
, IniFileSize
, CurrentOffset
))
61 IniFileLineSize
= IniGetNextLineSize(IniFileData
, IniFileSize
, CurrentOffset
);
62 MmFreeMemory(IniFileLine
);
63 IniFileLine
= MmAllocateMemory(IniFileLineSize
);
70 // Get the line of data
71 CurrentOffset
= IniGetNextLine(IniFileData
, IniFileSize
, IniFileLine
, IniFileLineSize
, CurrentOffset
);
72 LineLength
= strlen(IniFileLine
);
74 // If it is a blank line or a comment then skip it
75 if (IniIsLineEmpty(IniFileLine
, LineLength
) || IniIsCommentLine(IniFileLine
, LineLength
))
81 // Check if it is a new section
82 if (IniIsSectionName(IniFileLine
, LineLength
))
84 // Allocate a new section structure
85 CurrentSection
= MmAllocateMemory(sizeof(INI_SECTION
));
88 MmFreeMemory(IniFileLine
);
92 RtlZeroMemory(CurrentSection
, sizeof(INI_SECTION
));
94 // Allocate the section name buffer
95 CurrentSection
->SectionName
= MmAllocateMemory(IniGetSectionNameSize(IniFileLine
, LineLength
));
96 if (!CurrentSection
->SectionName
)
98 MmFreeMemory(CurrentSection
);
99 MmFreeMemory(IniFileLine
);
103 // Get the section name
104 IniExtractSectionName(CurrentSection
->SectionName
, IniFileLine
, LineLength
);
106 // Add it to the section list head
107 IniFileSectionCount
++;
108 if (IniFileSectionListHead
== NULL
)
110 IniFileSectionListHead
= CurrentSection
;
114 RtlListInsertTail((PLIST_ITEM
)IniFileSectionListHead
, (PLIST_ITEM
)CurrentSection
);
121 // Check if it is a setting
122 if (IniIsSetting(IniFileLine
, LineLength
))
124 // First check to make sure we're inside a [section]
125 if (CurrentSection
== NULL
)
127 printf("Error: freeldr.ini:%ld: Setting '%s' found outside of a [section].\n", CurrentLineNumber
, IniFileLine
);
128 printf("Press any key to continue...\n");
134 // Allocate a new item structure
135 CurrentItem
= MmAllocateMemory(sizeof(INI_SECTION_ITEM
));
138 MmFreeMemory(IniFileLine
);
142 RtlZeroMemory(CurrentItem
, sizeof(INI_SECTION_ITEM
));
144 // Allocate the setting name buffer
145 CurrentItem
->ItemName
= MmAllocateMemory(IniGetSettingNameSize(IniFileLine
, LineLength
));
146 if (!CurrentItem
->ItemName
)
148 MmFreeMemory(CurrentItem
);
149 MmFreeMemory(IniFileLine
);
153 // Allocate the setting value buffer
154 CurrentItem
->ItemValue
= MmAllocateMemory(IniGetSettingValueSize(IniFileLine
, LineLength
));
155 if (!CurrentItem
->ItemValue
)
157 MmFreeMemory(CurrentItem
->ItemName
);
158 MmFreeMemory(CurrentItem
);
159 MmFreeMemory(IniFileLine
);
163 // Get the section name
164 IniExtractSettingName(CurrentItem
->ItemName
, IniFileLine
, LineLength
);
165 IniExtractSettingValue(CurrentItem
->ItemValue
, IniFileLine
, LineLength
);
167 // Add it to the current section
168 IniFileSettingCount
++;
169 CurrentSection
->SectionItemCount
++;
170 if (CurrentSection
->SectionItemList
== NULL
)
172 CurrentSection
->SectionItemList
= CurrentItem
;
176 RtlListInsertTail((PLIST_ITEM
)CurrentSection
->SectionItemList
, (PLIST_ITEM
)CurrentItem
);
186 DbgPrint((DPRINT_INIFILE
, "Parsed %d sections and %d settings.\n", IniFileSectionCount
, IniFileSettingCount
));
187 DbgPrint((DPRINT_INIFILE
, "IniParseFile() done.\n"));
192 ULONG
IniGetNextLineSize(PCHAR IniFileData
, ULONG IniFileSize
, ULONG CurrentOffset
)
195 ULONG LineCharCount
= 0;
197 // Loop through counting chars until we hit the end of the
198 // file or we encounter a new line char
199 for (Idx
=0; (CurrentOffset
< IniFileSize
); CurrentOffset
++)
201 // Increment the line character count
204 // Check for new line char
205 if (IniFileData
[CurrentOffset
] == '\n')
212 // Add one for the NULL-terminator
215 // Send back line character count
216 return LineCharCount
;
219 ULONG
IniGetNextLine(PCHAR IniFileData
, ULONG IniFileSize
, PCHAR Buffer
, ULONG BufferSize
, ULONG CurrentOffset
)
223 // Loop through grabbing chars until we hit the end of the
224 // file or we encounter a new line char
225 for (Idx
=0; (CurrentOffset
< IniFileSize
); CurrentOffset
++)
227 // If we haven't exceeded our buffer size yet
228 // then store another char
229 if (Idx
< (BufferSize
- 1))
231 Buffer
[Idx
++] = IniFileData
[CurrentOffset
];
234 // Check for new line char
235 if (IniFileData
[CurrentOffset
] == '\n')
242 // Terminate the string
245 // Get rid of newline & linefeed characters (if any)
246 if((Buffer
[strlen(Buffer
)-1] == '\n') || (Buffer
[strlen(Buffer
)-1] == '\r'))
247 Buffer
[strlen(Buffer
)-1] = '\0';
248 if((Buffer
[strlen(Buffer
)-1] == '\n') || (Buffer
[strlen(Buffer
)-1] == '\r'))
249 Buffer
[strlen(Buffer
)-1] = '\0';
251 // Send back new offset
252 return CurrentOffset
;
255 BOOL
IniIsLineEmpty(PCHAR LineOfText
, ULONG TextLength
)
259 // Check for text (skipping whitespace)
260 for (Idx
=0; Idx
<TextLength
; Idx
++)
262 if ((LineOfText
[Idx
] == ' ') ||
263 (LineOfText
[Idx
] == '\t') ||
264 (LineOfText
[Idx
] == '\n') ||
265 (LineOfText
[Idx
] == '\r'))
278 BOOL
IniIsCommentLine(PCHAR LineOfText
, ULONG TextLength
)
282 // Check the first character (skipping whitespace)
283 // and make sure that it is an opening bracket
284 for (Idx
=0; Idx
<TextLength
; Idx
++)
286 if ((LineOfText
[Idx
] == ' ') ||
287 (LineOfText
[Idx
] == '\t'))
291 else if (LineOfText
[Idx
] == INI_FILE_COMMENT_CHAR
)
304 BOOL
IniIsSectionName(PCHAR LineOfText
, ULONG TextLength
)
308 // Check the first character (skipping whitespace)
309 // and make sure that it is an opening bracket
310 for (Idx
=0; Idx
<TextLength
; Idx
++)
312 if ((LineOfText
[Idx
] == ' ') ||
313 (LineOfText
[Idx
] == '\t'))
317 else if (LineOfText
[Idx
] == '[')
330 ULONG
IniGetSectionNameSize(PCHAR SectionNameLine
, ULONG LineLength
)
335 // Find the opening bracket (skipping whitespace)
336 for (Idx
=0; Idx
<LineLength
; Idx
++)
338 if ((SectionNameLine
[Idx
] == ' ') ||
339 (SectionNameLine
[Idx
] == '\t'))
343 else //if (SectionNameLine[Idx] == '[')
349 // Skip past the opening bracket
352 // Count the characters up until the closing bracket or EOL
353 for (NameSize
=0; Idx
<LineLength
; Idx
++)
355 if ((SectionNameLine
[Idx
] == ']') ||
356 (SectionNameLine
[Idx
] == '\0'))
361 // Increment the count
365 // Add one for the NULL-terminator
371 VOID
IniExtractSectionName(PCHAR SectionName
, PCHAR SectionNameLine
, ULONG LineLength
)
376 // Find the opening bracket (skipping whitespace)
377 for (Idx
=0; Idx
<LineLength
; Idx
++)
379 if ((SectionNameLine
[Idx
] == ' ') ||
380 (SectionNameLine
[Idx
] == '\t'))
384 else //if (SectionNameLine[Idx] == '[')
390 // Skip past the opening bracket
393 // Count the characters up until the closing bracket or EOL
394 for (DestIdx
=0; Idx
<LineLength
; Idx
++)
396 if ((SectionNameLine
[Idx
] == ']') ||
397 (SectionNameLine
[Idx
] == '\0'))
402 // Grab a character and increment DestIdx
403 SectionName
[DestIdx
] = SectionNameLine
[Idx
];
407 // Terminate the string
408 SectionName
[DestIdx
] = '\0';
411 BOOL
IniIsSetting(PCHAR LineOfText
, ULONG TextLength
)
415 // Basically just check for an '=' equals sign
416 for (Idx
=0; Idx
<TextLength
; Idx
++)
418 if (LineOfText
[Idx
] == '=')
427 ULONG
IniGetSettingNameSize(PCHAR SettingNameLine
, ULONG LineLength
)
433 for (Idx
=0; Idx
<LineLength
; Idx
++)
435 if ((SettingNameLine
[Idx
] == ' ') ||
436 (SettingNameLine
[Idx
] == '\t'))
446 // Count the characters up until the '=' equals sign or EOL
447 for (NameSize
=0; Idx
<LineLength
; Idx
++)
449 if ((SettingNameLine
[Idx
] == '=') ||
450 (SettingNameLine
[Idx
] == '\0'))
455 // Increment the count
459 // Add one for the NULL-terminator
465 ULONG
IniGetSettingValueSize(PCHAR SettingValueLine
, ULONG LineLength
)
471 for (Idx
=0; Idx
<LineLength
; Idx
++)
473 if ((SettingValueLine
[Idx
] == ' ') ||
474 (SettingValueLine
[Idx
] == '\t'))
484 // Skip the characters up until the '=' equals sign or EOL
485 for (; Idx
<LineLength
; Idx
++)
487 if (SettingValueLine
[Idx
] == '=')
493 // If we hit EOL then obviously the value size is zero
494 if (SettingValueLine
[Idx
] == '\0')
500 // Count the characters up until the EOL
501 for (ValueSize
=0; Idx
<LineLength
; Idx
++)
503 if (SettingValueLine
[Idx
] == '\0')
508 // Increment the count
512 // Add one for the NULL-terminator
518 VOID
IniExtractSettingName(PCHAR SettingName
, PCHAR SettingNameLine
, ULONG LineLength
)
524 for (Idx
=0; Idx
<LineLength
; Idx
++)
526 if ((SettingNameLine
[Idx
] == ' ') ||
527 (SettingNameLine
[Idx
] == '\t'))
537 // Get the characters up until the '=' equals sign or EOL
538 for (DestIdx
=0; Idx
<LineLength
; Idx
++)
540 if ((SettingNameLine
[Idx
] == '=') ||
541 (SettingNameLine
[Idx
] == '\0'))
546 // Grab a character and increment DestIdx
547 SettingName
[DestIdx
] = SettingNameLine
[Idx
];
551 // Terminate the string
552 SettingName
[DestIdx
] = '\0';
555 VOID
IniExtractSettingValue(PCHAR SettingValue
, PCHAR SettingValueLine
, ULONG LineLength
)
561 for (Idx
=0; Idx
<LineLength
; Idx
++)
563 if ((SettingValueLine
[Idx
] == ' ') ||
564 (SettingValueLine
[Idx
] == '\t'))
574 // Skip the characters up until the '=' equals sign or EOL
575 for (; Idx
<LineLength
; Idx
++)
577 if (SettingValueLine
[Idx
] == '=')
583 // If we hit EOL then obviously the value size is zero
584 if (SettingValueLine
[Idx
] == '\0')
586 SettingValue
[0] = '\0';
591 // Get the characters up until the EOL
592 for (DestIdx
=0; Idx
<LineLength
; Idx
++)
594 if (SettingValueLine
[Idx
] == '\0')
599 // Grab a character and increment DestIdx
600 SettingValue
[DestIdx
] = SettingValueLine
[Idx
];
604 // Terminate the string
605 SettingValue
[DestIdx
] = '\0';