2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Header preprocessor
4 * PURPOSE: Generates header files from other header files
5 * PROGRAMMER; Timo Kreuzer
20 #define trace if (0) printf
23 typedef struct _DEFINE
25 struct _DEFINE
*pNext
;
31 DEFINE
*gpDefines
= 0;
33 const char *gpszCurFile
;
36 convert_path(const char* origpath
)
41 newpath
= strdup(origpath
);
44 while (newpath
[i
] != 0)
47 if (newpath
[i
] == '\\')
53 if (newpath
[i
] == '/')
65 GetFolder(const char* pszFullPath
)
71 LoadFile(const char* pszFileName
, size_t* pFileSize
)
74 void* pFileData
= NULL
;
77 trace("Loading file...");
79 file
= fopen(pszFileName
, "rb");
82 trace("Could not open file\n");
86 fseek(file
, 0L, SEEK_END
);
87 iFileSize
= ftell(file
);
88 fseek(file
, 0L, SEEK_SET
);
89 *pFileSize
= iFileSize
;
90 trace("ok. Size is %d\n", iFileSize
);
92 pFileData
= malloc(iFileSize
+ 1);
94 if (pFileData
!= NULL
)
96 if (iFileSize
!= fread(pFileData
, 1, iFileSize
, file
))
104 trace("Could not allocate memory for file\n");
114 error(char *format
, ...)
118 va_start(valist
, format
);
119 res
= vfprintf(stderr
, format
, valist
);
125 GetNextChar(const char *psz
)
127 while (*psz
== ' ' || *psz
== '\t') psz
++;
132 GetNextLine(char *pszLine
)
134 /* Walk to the end of the line */
135 while (*pszLine
!= 13 && *pszLine
!= 10 && *pszLine
!= 0) pszLine
++;
138 if (pszLine
[0] == 13 && pszLine
[1] == 10)
140 else if (pszLine
[0] == 13 || pszLine
[0] == 10)
152 strxlen(const char *psz
)
155 while (isalnum(*psz
) || *psz
== '_')
165 WriteLine(char *pszLine
, FILE *fileOut
)
169 pszEnd
= strchr(pszLine
, '\n');
172 int len
= pszEnd
- pszLine
+ 1;
173 fwrite(pszLine
, 1, len
, fileOut
);
178 EvaluateConstant(const char *p
, char **pNext
)
185 *pNext
= (char*)p
+ len
;
187 /* search for the define in the global list */
191 trace("found a define: %s\n", pDefine
->szName
);
192 if (pDefine
->len
== len
)
194 if (strncmp(p
, pDefine
->szName
, len
) == 0)
199 pDefine
= pDefine
->pNext
;
205 EvaluateExpression(char *pExpression
, char **pNext
)
208 int inv
, thisval
, val
= 0;
210 trace("evaluating expression\n");
212 pstart
= GetNextChar(pExpression
);
215 error("Parse error: expected '(' \n");
221 /* Get the start of the real expression */
223 if ((p
[0] == '&' && p
[1] == '&') ||
224 (p
[0] == '|' && p
[1] == '|'))
228 p
= GetNextChar(p
+ 1);
230 /* Check for inversion modifier */
234 p
= GetNextChar(p
+ 1);
239 /* Beginning of a new subexpression? */
242 /* Evaluate subexpression */
243 thisval
= EvaluateExpression(p
, &p
);
245 else if (isdigit(*p
))
247 thisval
= strtod(p
, &p
);
248 trace("found a num: %d\n", thisval
);
250 else if (isalpha(*p
) || *p
== '_')
252 thisval
= EvaluateConstant(p
, &p
);
256 error("..Parse error, expected '(' or constant in line %d\n",
264 /* Check how to combine the current value */
265 if (pstart
[0] == '(')
269 else if (pstart
[0] == '&' && pstart
[1] == '&')
271 val
= val
&& thisval
;
273 else if (pstart
[0] == '&' && pstart
[1] != '&')
277 else if (pstart
[0] == '|' && pstart
[1] == '|')
279 trace("found || val = %d, thisval = %d\n", val
, thisval
);
280 val
= val
|| thisval
;
282 else if (pstart
[0] == '|' && pstart
[1] != '|')
286 else if (pstart
[0] == '+')
292 error("+Parse error: expected '(' or operator in Line %d, got %c\n",
299 /* End of current subexpression? */
309 /* Continue with a new start position */
317 ParseInputFile(const char *pszInFile
, FILE *fileOut
)
319 char* pInputData
, *pCurrentLine
, *p1
, *p2
;
320 size_t cbInFileLenth
, len
;
321 int iIfLevel
, iCopyLevel
;
323 trace("parsing input file: %s\n", pszInFile
);
325 /* Set the global file name */
326 gpszCurFile
= pszInFile
;
328 /* Load the input file into memory */
329 pInputData
= LoadFile(pszInFile
, &cbInFileLenth
);
332 error("Could not load input file %s\n", pszInFile
);
336 /* Zero terminate the file */
337 pInputData
[cbInFileLenth
] = 0;
339 pCurrentLine
= pInputData
;
341 iCopyLevel
= iIfLevel
= 0;
343 /* The main processing loop */
346 trace("line %d: ", iLine
);
348 /* If this is a normal line ... */
349 if (pCurrentLine
[0] != '$')
351 /* Check if we are to copy this line */
352 if (iCopyLevel
== iIfLevel
)
355 WriteLine(pCurrentLine
, fileOut
);
360 /* Continue with next line */
364 /* Check for $endif */
365 if (strncmp(pCurrentLine
, "$endif", 6) == 0)
367 trace("found $endif\n");
370 error("Parse error: $endif without $if in %s:%d\n", pszInFile
, iLine
);
373 if (iCopyLevel
== iIfLevel
)
379 /* Continue with next line */
383 /* The rest is only parsed when we are in a true block */
384 if (iCopyLevel
< iIfLevel
)
388 /* Continue with next line */
392 /* Check for $define */
393 if (strncmp(pCurrentLine
, "$define", 7) == 0)
397 trace("found $define\n");
398 p1
= GetNextChar(pCurrentLine
+ 7);
401 error("Parse error: expected '(' at %s:%d\n",
405 p1
= GetNextChar(p1
+ 1);
410 error("Parse error: expected ')' at %s:%d\n",
415 /* Insert the new define into the global list */
416 pDefine
= malloc(sizeof(DEFINE
) + len
);
417 strncpy(pDefine
->szName
, p1
, len
);
418 pDefine
->szName
[len
] = 0;
421 pDefine
->pNext
= gpDefines
;
426 else if (strncmp(pCurrentLine
, "$if", 3) == 0)
430 trace("found $if\n");
431 /* Increase the if-level */
434 /* Get beginning of the expression */
435 p1
= GetNextChar(pCurrentLine
+ 3);
437 /* evaluate the expression */
438 val
= EvaluateExpression(p1
, 0);
442 iCopyLevel
= iIfLevel
;
451 /* Check for $include */
452 else if (strncmp(pCurrentLine
, "$include", 8) == 0)
456 trace("found $include\n");
457 p1
= GetNextChar(pCurrentLine
+ 8);
460 error("Parse error: expected '(' at %s:%d, found '%c'\n",
461 pszInFile
, iLine
, *p1
);
465 p2
= strchr(p1
, ')');
468 /* Parse the included file */
469 ret
= ParseInputFile(p1
, fileOut
);
471 /* Restore the global file name */
472 gpszCurFile
= pszInFile
;
474 /* Restore the zeroed character */
483 /* Check for $$ comment */
484 else if (strncmp(pCurrentLine
, "$$", 2) == 0)
486 trace("$$ ignored\n");
487 /* continue with next line */
493 trace("wot:%s\n", pCurrentLine
);
496 /* Continue with next line */
498 while (pCurrentLine
= GetNextLine(pCurrentLine
),
502 /* Free the file data */
505 trace("Done with file.\n\n");
512 main(int argc
, char* argv
[])
514 char *pszInFolder
, *pszInFile
, *pszOutFile
;
520 error("Usage: hpp <inputfile> <outputfile>\n");
524 pszInFile
= convert_path(argv
[1]);
525 pszOutFile
= convert_path(argv
[2]);
526 pszInFolder
= GetFolder(pszInFile
);
528 fileOut
= fopen(pszOutFile
, "wb");
531 error("Cannot open output file %s", pszOutFile
);
535 ret
= ParseInputFile(pszInFile
, fileOut
);