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
18 #define trace if (0) printf
21 typedef struct _DEFINE
23 struct _DEFINE
*pNext
;
29 DEFINE
*gpDefines
= 0;
31 const char *gpszCurFile
;
34 convert_path(const char* origpath
)
39 newpath
= strdup(origpath
);
42 while (newpath
[i
] != 0)
45 if (newpath
[i
] == '\\')
51 if (newpath
[i
] == '/')
63 GetFolder(const char* pszFullPath
)
69 LoadFile(const char* pszFileName
, size_t* pFileSize
)
72 void* pFileData
= NULL
;
74 file
= fopen(pszFileName
, "rb");
77 fseek(file
, 0L, SEEK_END
);
78 *pFileSize
= ftell(file
);
79 fseek(file
, 0L, SEEK_SET
);
80 pFileData
= malloc(*pFileSize
);
81 if (pFileData
!= NULL
)
83 if (*pFileSize
!= fread(pFileData
, 1, *pFileSize
, file
))
96 error(char *format
, ...)
100 va_start(valist
, format
);
101 res
= vfprintf(stderr
, format
, valist
);
107 GetNextChar(const char *psz
)
109 while (*psz
== ' ' || *psz
== '\t') psz
++;
114 GetNextLine(char *pszLine
)
116 /* Walk to the end of the line */
117 while (*pszLine
!= 13 && *pszLine
!= 10 && *pszLine
!= 0) pszLine
++;
120 if (pszLine
[0] == 13 && pszLine
[1] == 10)
122 else if (pszLine
[0] == 13 || pszLine
[0] == 10)
134 strxlen(const char *psz
)
137 while (isalnum(*psz
) || *psz
== '_')
147 WriteLine(char *pszLine
, FILE *fileOut
)
151 pszEnd
= strchr(pszLine
, '\n');
154 int len
= pszEnd
- pszLine
+ 1;
155 fwrite(pszLine
, 1, len
, fileOut
);
160 EvaluateConstant(const char *p
, char **pNext
)
167 *pNext
= (char*)p
+ len
;
169 /* search for the define in the global list */
173 trace("found a define: %s\n", pDefine
->szName
);
174 if (pDefine
->len
== len
)
176 if (strncmp(p
, pDefine
->szName
, len
) == 0)
181 pDefine
= pDefine
->pNext
;
187 EvaluateExpression(char *pExpression
, char **pNext
)
190 int inv
, thisval
, val
= 0;
192 trace("evaluating expression\n");
194 pstart
= GetNextChar(pExpression
);
197 error("Parse error: expected '(' \n");
203 /* Get the start of the real expression */
205 if ((p
[0] == '&' && p
[1] == '&') ||
206 (p
[0] == '|' && p
[1] == '|'))
210 p
= GetNextChar(p
+ 1);
212 /* Check for inversion modifier */
216 p
= GetNextChar(p
+ 1);
221 /* Beginning of a new subexpression? */
224 /* Evaluate subexpression */
225 thisval
= EvaluateExpression(p
, &p
);
227 else if (isdigit(*p
))
229 thisval
= strtod(p
, &p
);
230 trace("found a num: %d\n", thisval
);
232 else if (isalpha(*p
) || *p
== '_')
234 thisval
= EvaluateConstant(p
, &p
);
238 error("..Parse error, expected '(' or constant in line %d\n",
246 /* Check how to combine the current value */
247 if (pstart
[0] == '(')
251 else if (pstart
[0] == '&' && pstart
[1] == '&')
253 val
= val
&& thisval
;
255 else if (pstart
[0] == '&' && pstart
[1] != '&')
259 else if (pstart
[0] == '|' && pstart
[1] == '|')
261 trace("found || val = %d, thisval = %d\n", val
, thisval
);
262 val
= val
|| thisval
;
264 else if (pstart
[0] == '|' && pstart
[1] != '|')
268 else if (pstart
[0] == '+')
274 error("+Parse error: expected '(' or operator in Line %d, got %c\n",
281 /* End of current subexpression? */
291 /* Continue with a new start position */
299 ParseInputFile(const char *pszInFile
, FILE *fileOut
)
301 char* pInputData
, *pCurrentLine
, *p1
, *p2
;
302 size_t cbInFileLenth
, len
;
303 int iIfLevel
, iCopyLevel
;
305 trace("parsing input file: %s\n", pszInFile
);
307 /* Set the global file name */
308 gpszCurFile
= pszInFile
;
310 /* Load the input file into memory */
311 pInputData
= LoadFile(pszInFile
, &cbInFileLenth
);
314 error("Could not load input file %s\n", pszInFile
);
318 /* Zero terminate the file */
319 pInputData
[cbInFileLenth
] = 0;
321 pCurrentLine
= pInputData
;
323 iCopyLevel
= iIfLevel
= 0;
325 /* The main processing loop */
328 trace("line %d: ", iLine
);
330 /* If this is a normal line ... */
331 if (pCurrentLine
[0] != '$')
333 /* Check if we are to copy this line */
334 if (iCopyLevel
== iIfLevel
)
337 WriteLine(pCurrentLine
, fileOut
);
342 /* Continue with next line */
346 /* Check for $endif */
347 if (strncmp(pCurrentLine
, "$endif", 6) == 0)
349 trace("found $endif\n");
352 error("Parse error: $endif without $if in %s:%d\n", pszInFile
, iLine
);
355 if (iCopyLevel
== iIfLevel
)
361 /* Continue with next line */
365 /* The rest is only parsed when we are in a true block */
366 if (iCopyLevel
< iIfLevel
)
370 /* Continue with next line */
374 /* Check for $define */
375 if (strncmp(pCurrentLine
, "$define", 7) == 0)
379 trace("found $define\n");
380 p1
= GetNextChar(pCurrentLine
+ 7);
383 error("Parse error: expected '(' at %s:%d\n",
387 p1
= GetNextChar(p1
+ 1);
392 error("Parse error: expected ')' at %s:%d\n",
397 /* Insert the new define into the global list */
398 pDefine
= malloc(sizeof(DEFINE
) + len
);
399 strncpy(pDefine
->szName
, p1
, len
);
400 pDefine
->szName
[len
] = 0;
403 pDefine
->pNext
= gpDefines
;
408 else if (strncmp(pCurrentLine
, "$if", 3) == 0)
412 trace("found $if\n");
413 /* Increase the if-level */
416 /* Get beginning of the expression */
417 p1
= GetNextChar(pCurrentLine
+ 3);
419 /* evaluate the expression */
420 val
= EvaluateExpression(p1
, 0);
424 iCopyLevel
= iIfLevel
;
433 /* Check for $include */
434 else if (strncmp(pCurrentLine
, "$include", 8) == 0)
438 trace("found $include\n");
439 p1
= GetNextChar(pCurrentLine
+ 8);
442 error("Parse error: expected '(' at %s:%d, found '%c'\n",
443 pszInFile
, iLine
, *p1
);
447 p2
= strchr(p1
, ')');
450 /* Parse the included file */
451 ret
= ParseInputFile(p1
, fileOut
);
453 /* Restore the global file name */
454 gpszCurFile
= pszInFile
;
462 /* Check for $$ comment */
463 else if (strncmp(pCurrentLine
, "$$", 2) == 0)
465 trace("$$ ignored\n");
466 /* continue with next line */
472 trace("wot:%s\n", pCurrentLine
);
475 /* Continue with next line */
477 while (pCurrentLine
= GetNextLine(pCurrentLine
),
481 /* Free the file data */
489 main(int argc
, char* argv
[])
491 char *pszInFolder
, *pszInFile
, *pszOutFile
;
497 error("Usage: hc <inputfile> <outputfile>\n");
501 pszInFile
= convert_path(argv
[1]);
502 pszOutFile
= convert_path(argv
[2]);
503 pszInFolder
= GetFolder(pszInFile
);
505 fileOut
= fopen(pszOutFile
, "wb");
508 error("Cannot open output file %s", pszOutFile
);
512 ret
= ParseInputFile(pszInFile
, fileOut
);