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
;
30 unsigned int cchValue
;
34 DEFINE
*gpDefines
= 0;
36 const char *gpszCurFile
;
39 convert_path(const char* origpath
)
44 newpath
= strdup(origpath
);
47 while (newpath
[i
] != 0)
50 if (newpath
[i
] == '\\')
56 if (newpath
[i
] == '/')
68 GetFolder(const char* pszFullPath
)
74 LoadFile(const char* pszFileName
, size_t* pFileSize
)
77 void* pFileData
= NULL
;
80 trace("Loading file...");
82 file
= fopen(pszFileName
, "rb");
85 trace("Could not open file\n");
89 fseek(file
, 0L, SEEK_END
);
90 iFileSize
= ftell(file
);
91 fseek(file
, 0L, SEEK_SET
);
92 *pFileSize
= iFileSize
;
93 trace("ok. Size is %d\n", iFileSize
);
95 pFileData
= malloc(iFileSize
+ 1);
97 if (pFileData
!= NULL
)
99 if (iFileSize
!= fread(pFileData
, 1, iFileSize
, file
))
107 trace("Could not allocate memory for file\n");
117 error(char *format
, ...)
121 va_start(valist
, format
);
122 res
= vfprintf(stderr
, format
, valist
);
128 GetNextChar(const char *psz
)
130 while (*psz
== ' ' || *psz
== '\t') psz
++;
135 GetNextLine(char *pszLine
)
137 /* Walk to the end of the line */
138 while (*pszLine
!= 13 && *pszLine
!= 10 && *pszLine
!= 0) pszLine
++;
141 if (pszLine
[0] == 13 && pszLine
[1] == 10)
143 else if (pszLine
[0] == 13 || pszLine
[0] == 10)
155 strxlen(const char *psz
)
158 while (isalnum(*psz
) || *psz
== '_')
167 FindDefine(const char *p
, char **pNext
)
172 cchName
= strxlen(p
);
174 *pNext
= (char*)p
+ cchName
;
176 /* search for the define in the global list */
180 trace("found a define: %s\n", pDefine
->pszName
);
181 if (pDefine
->cchName
== cchName
)
183 if (strncmp(p
, pDefine
->pszName
, cchName
) == 0)
188 pDefine
= pDefine
->pNext
;
194 WriteLine(char *pchLine
, FILE *fileOut
)
196 char *pch
, *pchLineEnd
, *pchVariable
;
200 pchLineEnd
= strchr(pchLine
, '\n');
204 len
= pchLineEnd
- pchLine
+ 1;
209 /* Check if there is a $ variable in the line */
210 pchVariable
= strchr(pch
, '$');
211 if (pchVariable
&& (pchVariable
< pchLineEnd
))
213 /* Write all characters up to the $ */
214 fwrite(pch
, 1, pchVariable
- pch
, fileOut
);
216 /* Try to find the define */
217 pDefine
= FindDefine(pchVariable
+ 1, &pch
);
220 /* We have a define, write the value */
221 fwrite(pDefine
->pszValue
, 1, pDefine
->cchValue
, fileOut
);
225 len
= strxlen(pchVariable
+ 1) + 1;
226 error("Could not find variable '%.*s'\n", len
, pchVariable
);
227 fwrite(pchVariable
, 1, pch
- pchVariable
, fileOut
);
230 len
= pchLineEnd
- pch
+ 1;
234 fwrite(pch
, 1, len
, fileOut
);
241 EvaluateConstant(const char *p
, char **pNext
)
245 pDefine
= FindDefine(p
, pNext
);
253 EvaluateExpression(char *pExpression
, char **pNext
)
256 int inv
, thisval
, val
= 0;
258 trace("evaluating expression\n");
260 pstart
= GetNextChar(pExpression
);
263 error("Parse error: expected '(' \n");
269 /* Get the start of the real expression */
271 if ((p
[0] == '&' && p
[1] == '&') ||
272 (p
[0] == '|' && p
[1] == '|'))
276 p
= GetNextChar(p
+ 1);
278 /* Check for inversion modifier */
282 p
= GetNextChar(p
+ 1);
287 /* Beginning of a new subexpression? */
290 /* Evaluate subexpression */
291 thisval
= EvaluateExpression(p
, &p
);
293 else if (isdigit(*p
))
295 thisval
= strtod(p
, &p
);
296 trace("found a num: %d\n", thisval
);
298 else if (isalpha(*p
) || *p
== '_')
300 thisval
= EvaluateConstant(p
, &p
);
304 error("..Parse error, expected '(' or constant in line %d\n",
312 /* Check how to combine the current value */
313 if (pstart
[0] == '(')
317 else if (pstart
[0] == '&' && pstart
[1] == '&')
319 val
= val
&& thisval
;
321 else if (pstart
[0] == '&' && pstart
[1] != '&')
325 else if (pstart
[0] == '|' && pstart
[1] == '|')
327 trace("found || val = %d, thisval = %d\n", val
, thisval
);
328 val
= val
|| thisval
;
330 else if (pstart
[0] == '|' && pstart
[1] != '|')
334 else if (pstart
[0] == '+')
340 error("+Parse error: expected '(' or operator in Line %d, got %c\n",
347 /* End of current subexpression? */
357 /* Continue with a new start position */
365 ParseInputFile(const char *pszInFile
, FILE *fileOut
)
367 char* pInputData
, *pCurrentLine
, *p1
, *p2
;
368 size_t cbInFileLenth
;
369 int iIfLevel
, iCopyLevel
;
371 trace("parsing input file: %s\n", pszInFile
);
373 /* Set the global file name */
374 gpszCurFile
= pszInFile
;
376 /* Load the input file into memory */
377 pInputData
= LoadFile(pszInFile
, &cbInFileLenth
);
380 error("Could not load input file %s\n", pszInFile
);
384 /* Zero terminate the file */
385 pInputData
[cbInFileLenth
] = 0;
387 pCurrentLine
= pInputData
;
389 iCopyLevel
= iIfLevel
= 0;
391 /* The main processing loop */
394 trace("line %d: ", iLine
);
396 /* If this is a normal line ... */
397 if (pCurrentLine
[0] != '$')
399 /* Check if we are to copy this line */
400 if (iCopyLevel
== iIfLevel
)
403 WriteLine(pCurrentLine
, fileOut
);
408 /* Continue with next line */
412 /* Check for $endif */
413 if (strncmp(pCurrentLine
, "$endif", 6) == 0)
415 trace("found $endif\n");
418 error("Parse error: $endif without $if in %s:%d\n", pszInFile
, iLine
);
421 if (iCopyLevel
== iIfLevel
)
427 /* Continue with next line */
431 /* The rest is only parsed when we are in a true block */
432 if (iCopyLevel
< iIfLevel
)
436 /* Continue with next line */
440 /* Check for $define */
441 if (strncmp(pCurrentLine
, "$define", 7) == 0)
444 char *pchName
, *pchValue
;
445 size_t cchName
, cchValue
;
447 trace("found $define\n");
448 p1
= GetNextChar(pCurrentLine
+ 7);
451 error("Parse error: expected '(' at %s:%d\n",
456 pchName
= GetNextChar(p1
+ 1);
457 cchName
= strxlen(pchName
);
458 p1
= GetNextChar(pchName
+ cchName
);
460 /* Check for assignment */
463 trace("found $define with assignment\n");
464 pchValue
= GetNextChar(p1
+ 1);
465 cchValue
= strxlen(pchValue
);
466 p1
= GetNextChar(pchValue
+ cchValue
);
474 /* Allocate a DEFINE structure */
475 pDefine
= malloc(sizeof(DEFINE
) + cchName
+ cchValue
+ 2);
478 error("Failed to allocate %u bytes\n",
479 sizeof(DEFINE
) + cchName
+ cchValue
+ 2);
483 pDefine
->pszName
= pDefine
->achBuffer
;
484 strncpy(pDefine
->pszName
, pchName
, cchName
);
485 pDefine
->pszName
[cchName
] = 0;
486 pDefine
->cchName
= cchName
;
491 pDefine
->pszValue
= &pDefine
->achBuffer
[cchName
+ 1];
492 strncpy(pDefine
->pszValue
, pchValue
, cchValue
);
493 pDefine
->pszValue
[cchValue
] = 0;
494 pDefine
->cchValue
= cchValue
;
498 pDefine
->pszValue
= 0;
499 pDefine
->cchValue
= 0;
502 /* Insert the new define into the global list */
503 pDefine
->pNext
= gpDefines
;
506 /* Check for closing ')' */
509 error("Parse error: expected ')' at %s:%d\n",
516 else if (strncmp(pCurrentLine
, "$if", 3) == 0)
520 trace("found $if\n");
521 /* Increase the if-level */
524 /* Get beginning of the expression */
525 p1
= GetNextChar(pCurrentLine
+ 3);
527 /* evaluate the expression */
528 val
= EvaluateExpression(p1
, 0);
532 iCopyLevel
= iIfLevel
;
541 /* Check for $include */
542 else if (strncmp(pCurrentLine
, "$include", 8) == 0)
546 trace("found $include\n");
547 p1
= GetNextChar(pCurrentLine
+ 8);
550 error("Parse error: expected '(' at %s:%d, found '%c'\n",
551 pszInFile
, iLine
, *p1
);
555 p2
= strchr(p1
, ')');
558 /* Parse the included file */
559 ret
= ParseInputFile(p1
, fileOut
);
561 /* Restore the global file name */
562 gpszCurFile
= pszInFile
;
564 /* Restore the zeroed character */
573 /* Check for $$ comment */
574 else if (strncmp(pCurrentLine
, "$$", 2) == 0)
576 trace("$$ ignored\n");
577 /* continue with next line */
583 trace("wot:%s\n", pCurrentLine
);
586 /* Continue with next line */
588 while (pCurrentLine
= GetNextLine(pCurrentLine
),
592 /* Free the file data */
595 trace("Done with file.\n\n");
602 main(int argc
, char* argv
[])
604 char *pszInFile
, *pszOutFile
;
610 error("Usage: hpp <inputfile> <outputfile>\n");
614 pszInFile
= convert_path(argv
[1]);
615 pszOutFile
= convert_path(argv
[2]);
617 fileOut
= fopen(pszOutFile
, "wb");
620 error("Cannot open output file %s", pszOutFile
);
624 ret
= ParseInputFile(pszInFile
, fileOut
);