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.
27 PINI_SECTION IniFileSectionListHead
= NULL
;
28 U32 IniFileSectionCount
= 0;
29 U32 IniFileSettingCount
= 0;
32 BOOL
IniParseFile(PUCHAR IniFileData
, U32 IniFileSize
)
35 U32 CurrentLineNumber
;
39 PINI_SECTION CurrentSection
= NULL
;
40 PINI_SECTION_ITEM CurrentItem
= NULL
;
42 DbgPrint((DPRINT_INIFILE
, "IniParseFile() IniFileSize: %d\n", IniFileSize
));
44 IniFileSectionListHead
= NULL
;
45 IniFileSectionCount
= 0;
46 IniFileSettingCount
= 0;
48 // Start with an 80-byte buffer
50 IniFileLine
= MmAllocateMemory(IniFileLineSize
);
56 // Loop through each line and parse it
57 CurrentLineNumber
= 0;
59 while (CurrentOffset
< IniFileSize
)
61 // First check the line size and increase our buffer if necessary
62 if (IniFileLineSize
< IniGetNextLineSize(IniFileData
, IniFileSize
, CurrentOffset
))
64 IniFileLineSize
= IniGetNextLineSize(IniFileData
, IniFileSize
, CurrentOffset
);
65 MmFreeMemory(IniFileLine
);
66 IniFileLine
= MmAllocateMemory(IniFileLineSize
);
73 // Get the line of data
74 CurrentOffset
= IniGetNextLine(IniFileData
, IniFileSize
, IniFileLine
, IniFileLineSize
, CurrentOffset
);
75 LineLength
= strlen(IniFileLine
);
77 // If it is a blank line or a comment then skip it
78 if (IniIsLineEmpty(IniFileLine
, LineLength
) || IniIsCommentLine(IniFileLine
, LineLength
))
84 // Check if it is a new section
85 if (IniIsSectionName(IniFileLine
, LineLength
))
87 // Allocate a new section structure
88 CurrentSection
= MmAllocateMemory(sizeof(INI_SECTION
));
91 MmFreeMemory(IniFileLine
);
95 RtlZeroMemory(CurrentSection
, sizeof(INI_SECTION
));
97 // Allocate the section name buffer
98 CurrentSection
->SectionName
= MmAllocateMemory(IniGetSectionNameSize(IniFileLine
, LineLength
));
99 if (!CurrentSection
->SectionName
)
101 MmFreeMemory(CurrentSection
);
102 MmFreeMemory(IniFileLine
);
106 // Get the section name
107 IniExtractSectionName(CurrentSection
->SectionName
, IniFileLine
, LineLength
);
109 // Add it to the section list head
110 IniFileSectionCount
++;
111 if (IniFileSectionListHead
== NULL
)
113 IniFileSectionListHead
= CurrentSection
;
117 RtlListInsertTail((PLIST_ITEM
)IniFileSectionListHead
, (PLIST_ITEM
)CurrentSection
);
124 // Check if it is a setting
125 if (IniIsSetting(IniFileLine
, LineLength
))
127 // First check to make sure we're inside a [section]
128 if (CurrentSection
== NULL
)
130 printf("Error: freeldr.ini:%ld: Setting '%s' found outside of a [section].\n", CurrentLineNumber
, IniFileLine
);
131 printf("Press any key to continue...\n");
137 // Allocate a new item structure
138 CurrentItem
= MmAllocateMemory(sizeof(INI_SECTION_ITEM
));
141 MmFreeMemory(IniFileLine
);
145 RtlZeroMemory(CurrentItem
, sizeof(INI_SECTION_ITEM
));
147 // Allocate the setting name buffer
148 CurrentItem
->ItemName
= MmAllocateMemory(IniGetSettingNameSize(IniFileLine
, LineLength
));
149 if (!CurrentItem
->ItemName
)
151 MmFreeMemory(CurrentItem
);
152 MmFreeMemory(IniFileLine
);
156 // Allocate the setting value buffer
157 CurrentItem
->ItemValue
= MmAllocateMemory(IniGetSettingValueSize(IniFileLine
, LineLength
));
158 if (!CurrentItem
->ItemValue
)
160 MmFreeMemory(CurrentItem
->ItemName
);
161 MmFreeMemory(CurrentItem
);
162 MmFreeMemory(IniFileLine
);
166 // Get the section name
167 IniExtractSettingName(CurrentItem
->ItemName
, IniFileLine
, LineLength
);
168 IniExtractSettingValue(CurrentItem
->ItemValue
, IniFileLine
, LineLength
);
170 // Add it to the current section
171 IniFileSettingCount
++;
172 CurrentSection
->SectionItemCount
++;
173 if (CurrentSection
->SectionItemList
== NULL
)
175 CurrentSection
->SectionItemList
= CurrentItem
;
179 RtlListInsertTail((PLIST_ITEM
)CurrentSection
->SectionItemList
, (PLIST_ITEM
)CurrentItem
);
189 DbgPrint((DPRINT_INIFILE
, "Parsed %d sections and %d settings.\n", IniFileSectionCount
, IniFileSettingCount
));
190 DbgPrint((DPRINT_INIFILE
, "IniParseFile() done.\n"));
195 U32
IniGetNextLineSize(PUCHAR IniFileData
, U32 IniFileSize
, U32 CurrentOffset
)
198 U32 LineCharCount
= 0;
200 // Loop through counting chars until we hit the end of the
201 // file or we encounter a new line char
202 for (Idx
=0; (CurrentOffset
< IniFileSize
); CurrentOffset
++)
204 // Increment the line character count
207 // Check for new line char
208 if (IniFileData
[CurrentOffset
] == '\n')
215 // Add one for the NULL-terminator
218 // Send back line character count
219 return LineCharCount
;
222 U32
IniGetNextLine(PUCHAR IniFileData
, U32 IniFileSize
, PUCHAR Buffer
, U32 BufferSize
, U32 CurrentOffset
)
226 // Loop through grabbing chars until we hit the end of the
227 // file or we encounter a new line char
228 for (Idx
=0; (CurrentOffset
< IniFileSize
); CurrentOffset
++)
230 // If we haven't exceeded our buffer size yet
231 // then store another char
232 if (Idx
< (BufferSize
- 1))
234 Buffer
[Idx
++] = IniFileData
[CurrentOffset
];
237 // Check for new line char
238 if (IniFileData
[CurrentOffset
] == '\n')
245 // Terminate the string
248 // Get rid of newline & linefeed characters (if any)
249 if((Buffer
[strlen(Buffer
)-1] == '\n') || (Buffer
[strlen(Buffer
)-1] == '\r'))
250 Buffer
[strlen(Buffer
)-1] = '\0';
251 if((Buffer
[strlen(Buffer
)-1] == '\n') || (Buffer
[strlen(Buffer
)-1] == '\r'))
252 Buffer
[strlen(Buffer
)-1] = '\0';
254 // Send back new offset
255 return CurrentOffset
;
258 BOOL
IniIsLineEmpty(PUCHAR LineOfText
, U32 TextLength
)
262 // Check for text (skipping whitespace)
263 for (Idx
=0; Idx
<TextLength
; Idx
++)
265 if ((LineOfText
[Idx
] == ' ') ||
266 (LineOfText
[Idx
] == '\t') ||
267 (LineOfText
[Idx
] == '\n') ||
268 (LineOfText
[Idx
] == '\r'))
281 BOOL
IniIsCommentLine(PUCHAR LineOfText
, U32 TextLength
)
285 // Check the first character (skipping whitespace)
286 // and make sure that it is an opening bracket
287 for (Idx
=0; Idx
<TextLength
; Idx
++)
289 if ((LineOfText
[Idx
] == ' ') ||
290 (LineOfText
[Idx
] == '\t'))
294 else if (LineOfText
[Idx
] == INI_FILE_COMMENT_CHAR
)
307 BOOL
IniIsSectionName(PUCHAR LineOfText
, U32 TextLength
)
311 // Check the first character (skipping whitespace)
312 // and make sure that it is an opening bracket
313 for (Idx
=0; Idx
<TextLength
; Idx
++)
315 if ((LineOfText
[Idx
] == ' ') ||
316 (LineOfText
[Idx
] == '\t'))
320 else if (LineOfText
[Idx
] == '[')
333 U32
IniGetSectionNameSize(PUCHAR SectionNameLine
, U32 LineLength
)
338 // Find the opening bracket (skipping whitespace)
339 for (Idx
=0; Idx
<LineLength
; Idx
++)
341 if ((SectionNameLine
[Idx
] == ' ') ||
342 (SectionNameLine
[Idx
] == '\t'))
346 else //if (SectionNameLine[Idx] == '[')
352 // Skip past the opening bracket
355 // Count the characters up until the closing bracket or EOL
356 for (NameSize
=0; Idx
<LineLength
; Idx
++)
358 if ((SectionNameLine
[Idx
] == ']') ||
359 (SectionNameLine
[Idx
] == '\0'))
364 // Increment the count
368 // Add one for the NULL-terminator
374 VOID
IniExtractSectionName(PUCHAR SectionName
, PUCHAR SectionNameLine
, U32 LineLength
)
379 // Find the opening bracket (skipping whitespace)
380 for (Idx
=0; Idx
<LineLength
; Idx
++)
382 if ((SectionNameLine
[Idx
] == ' ') ||
383 (SectionNameLine
[Idx
] == '\t'))
387 else //if (SectionNameLine[Idx] == '[')
393 // Skip past the opening bracket
396 // Count the characters up until the closing bracket or EOL
397 for (DestIdx
=0; Idx
<LineLength
; Idx
++)
399 if ((SectionNameLine
[Idx
] == ']') ||
400 (SectionNameLine
[Idx
] == '\0'))
405 // Grab a character and increment DestIdx
406 SectionName
[DestIdx
] = SectionNameLine
[Idx
];
410 // Terminate the string
411 SectionName
[DestIdx
] = '\0';
414 BOOL
IniIsSetting(PUCHAR LineOfText
, U32 TextLength
)
418 // Basically just check for an '=' equals sign
419 for (Idx
=0; Idx
<TextLength
; Idx
++)
421 if (LineOfText
[Idx
] == '=')
430 U32
IniGetSettingNameSize(PUCHAR SettingNameLine
, U32 LineLength
)
436 for (Idx
=0; Idx
<LineLength
; Idx
++)
438 if ((SettingNameLine
[Idx
] == ' ') ||
439 (SettingNameLine
[Idx
] == '\t'))
449 // Count the characters up until the '=' equals sign or EOL
450 for (NameSize
=0; Idx
<LineLength
; Idx
++)
452 if ((SettingNameLine
[Idx
] == '=') ||
453 (SettingNameLine
[Idx
] == '\0'))
458 // Increment the count
462 // Add one for the NULL-terminator
468 U32
IniGetSettingValueSize(PUCHAR SettingValueLine
, U32 LineLength
)
474 for (Idx
=0; Idx
<LineLength
; Idx
++)
476 if ((SettingValueLine
[Idx
] == ' ') ||
477 (SettingValueLine
[Idx
] == '\t'))
487 // Skip the characters up until the '=' equals sign or EOL
488 for (; Idx
<LineLength
; Idx
++)
490 if (SettingValueLine
[Idx
] == '=')
496 // If we hit EOL then obviously the value size is zero
497 if (SettingValueLine
[Idx
] == '\0')
503 // Count the characters up until the EOL
504 for (ValueSize
=0; Idx
<LineLength
; Idx
++)
506 if (SettingValueLine
[Idx
] == '\0')
511 // Increment the count
515 // Add one for the NULL-terminator
521 VOID
IniExtractSettingName(PUCHAR SettingName
, PUCHAR SettingNameLine
, U32 LineLength
)
527 for (Idx
=0; Idx
<LineLength
; Idx
++)
529 if ((SettingNameLine
[Idx
] == ' ') ||
530 (SettingNameLine
[Idx
] == '\t'))
540 // Get the characters up until the '=' equals sign or EOL
541 for (DestIdx
=0; Idx
<LineLength
; Idx
++)
543 if ((SettingNameLine
[Idx
] == '=') ||
544 (SettingNameLine
[Idx
] == '\0'))
549 // Grab a character and increment DestIdx
550 SettingName
[DestIdx
] = SettingNameLine
[Idx
];
554 // Terminate the string
555 SettingName
[DestIdx
] = '\0';
558 VOID
IniExtractSettingValue(PUCHAR SettingValue
, PUCHAR SettingValueLine
, U32 LineLength
)
564 for (Idx
=0; Idx
<LineLength
; Idx
++)
566 if ((SettingValueLine
[Idx
] == ' ') ||
567 (SettingValueLine
[Idx
] == '\t'))
577 // Skip the characters up until the '=' equals sign or EOL
578 for (; Idx
<LineLength
; Idx
++)
580 if (SettingValueLine
[Idx
] == '=')
586 // If we hit EOL then obviously the value size is zero
587 if (SettingValueLine
[Idx
] == '\0')
589 SettingValue
[0] = '\0';
594 // Get the characters up until the EOL
595 for (DestIdx
=0; Idx
<LineLength
; Idx
++)
597 if (SettingValueLine
[Idx
] == '\0')
602 // Grab a character and increment DestIdx
603 SettingValue
[DestIdx
] = SettingValueLine
[Idx
];
607 // Terminate the string
608 SettingValue
[DestIdx
] = '\0';