ReactOS  0.4.14-dev-115-g4576127
hpp.c
Go to the documentation of this file.
1 /*
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
6  *
7  */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <ctype.h>
14 
15 //#define DBG 1
16 
17 #if DBG
18 #define trace printf
19 #else
20 #define trace if (0) printf
21 #endif
22 
23 typedef struct _DEFINE
24 {
25  struct _DEFINE *pNext;
26  int val;
27  char *pszName;
28  unsigned int cchName;
29  char *pszValue;
30  unsigned int cchValue;
31  char achBuffer[1];
32 } DEFINE, *PDEFINE;
33 
35 int iLine;
36 const char *gpszCurFile;
37 
38 char*
39 convert_path(const char* origpath)
40 {
41  char* newpath;
42  int i;
43 
44  newpath = strdup(origpath);
45 
46  i = 0;
47  while (newpath[i] != 0)
48  {
49 #ifdef UNIX_PATHS
50  if (newpath[i] == '\\')
51  {
52  newpath[i] = '/';
53  }
54 #else
55 #ifdef DOS_PATHS
56  if (newpath[i] == '/')
57  {
58  newpath[i] = '\\';
59  }
60 #endif
61 #endif
62  i++;
63  }
64  return newpath;
65 }
66 
67 char*
68 GetFolder(const char* pszFullPath)
69 {
70  return ".";
71 }
72 
73 void*
74 LoadFile(const char* pszFileName, size_t* pFileSize)
75 {
76  FILE* file;
77  void* pFileData = NULL;
78  int iFileSize;
79 
80  trace("Loading file...");
81 
82  file = fopen(pszFileName, "rb");
83  if (!file)
84  {
85  trace("Could not open file\n");
86  return NULL;
87  }
88 
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);
94 
95  pFileData = malloc(iFileSize + 1);
96 
97  if (pFileData != NULL)
98  {
99  if (iFileSize != fread(pFileData, 1, iFileSize, file))
100  {
101  free(pFileData);
102  pFileData = NULL;
103  }
104  }
105  else
106  {
107  trace("Could not allocate memory for file\n");
108  }
109 
110  fclose(file);
111 
112  return pFileData;
113 }
114 
115 
116 int
117 error(char *format, ...)
118 {
119  va_list valist;
120  int res;
123  va_end(valist);
124  return res;
125 }
126 
127 char*
128 GetNextChar(const char *psz)
129 {
130  while (*psz == ' ' || *psz == '\t') psz++;
131  return (char*)psz;
132 }
133 
134 char*
135 GetNextLine(char *pszLine)
136 {
137  /* Walk to the end of the line */
138  while (*pszLine != 13 && *pszLine != 10 && *pszLine != 0) pszLine++;
139 
140  /* Skip one CR/LF */
141  if (pszLine[0] == 13 && pszLine[1] == 10)
142  pszLine += 2;
143  else if (pszLine[0] == 13 || pszLine[0] == 10)
144  pszLine++;
145 
146  if (*pszLine == 0)
147  {
148  return 0;
149  }
150 
151  return pszLine;
152 }
153 
154 int
155 strxlen(const char *psz)
156 {
157  int len = 0;
158  while (isalnum(*psz) || *psz == '_')
159  {
160  psz++;
161  len++;
162  }
163  return len;
164 }
165 
166 PDEFINE
167 FindDefine(const char *p, char **pNext)
168 {
169  PDEFINE pDefine;
170  int cchName;
171 
172  cchName = strxlen(p);
173  if (pNext)
174  *pNext = (char*)p + cchName;
175 
176  /* search for the define in the global list */
177  pDefine = gpDefines;
178  while (pDefine != 0)
179  {
180  trace("found a define: %s\n", pDefine->pszName);
181  if (pDefine->cchName == cchName)
182  {
183  if (strncmp(p, pDefine->pszName, cchName) == 0)
184  {
185  return pDefine;
186  }
187  }
188  pDefine = pDefine->pNext;
189  }
190  return 0;
191 }
192 
193 void
194 WriteLine(char *pchLine, FILE *fileOut)
195 {
196  char *pch, *pchLineEnd, *pchVariable;
197  int len;
198  PDEFINE pDefine;
199 
200  pchLineEnd = strchr(pchLine, '\n');
201  if (pchLineEnd == 0)
202  return;
203 
204  len = pchLineEnd - pchLine + 1;
205 
206  pch = pchLine;
207  while (len > 0)
208  {
209  /* Check if there is a $ variable in the line */
210  pchVariable = strchr(pch, '$');
211  if (pchVariable && (pchVariable < pchLineEnd))
212  {
213  /* Write all characters up to the $ */
214  fwrite(pch, 1, pchVariable - pch, fileOut);
215 
216  /* Try to find the define */
217  pDefine = FindDefine(pchVariable + 1, &pch);
218  if (pDefine != 0)
219  {
220  /* We have a define, write the value */
221  fwrite(pDefine->pszValue, 1, pDefine->cchValue, fileOut);
222  }
223  else
224  {
225  len = strxlen(pchVariable + 1) + 1;
226  error("Could not find variable '%.*s'\n", len, pchVariable);
227  fwrite(pchVariable, 1, pch - pchVariable, fileOut);
228  }
229 
230  len = pchLineEnd - pch + 1;
231  }
232  else
233  {
234  fwrite(pch, 1, len, fileOut);
235  break;
236  }
237  }
238 }
239 
240 int
241 EvaluateConstant(const char *p, char **pNext)
242 {
243  PDEFINE pDefine;
244 
245  pDefine = FindDefine(p, pNext);
246  if (!pDefine)
247  return 0;
248 
249  return pDefine->val;
250 }
251 
252 int
254 {
255  char *p, *pstart;
256  int inv, thisval, val = 0;
257 
258  trace("evaluating expression\n");
259 
260  pstart = GetNextChar(pExpression);
261  if (*pstart != '(')
262  {
263  error("Parse error: expected '(' \n");
264  return -1;
265  }
266 
267  while (1)
268  {
269  /* Get the start of the real expression */
270  p = pstart;
271  if ((p[0] == '&' && p[1] == '&') ||
272  (p[0] == '|' && p[1] == '|'))
273  {
274  p++;
275  }
276  p = GetNextChar(p + 1);
277 
278  /* Check for inversion modifier */
279  if (*p == '!')
280  {
281  inv = 1;
282  p = GetNextChar(p + 1);
283  }
284  else
285  inv = 0;
286 
287  /* Beginning of a new subexpression? */
288  if (*p == '(')
289  {
290  /* Evaluate subexpression */
291  thisval = EvaluateExpression(p, &p);
292  }
293  else if (isdigit(*p))
294  {
295  thisval = strtod(p, &p);
296  trace("found a num: %d\n", thisval);
297  }
298  else if (isalpha(*p) || *p == '_')
299  {
300  thisval = EvaluateConstant(p, &p);
301  }
302  else
303  {
304  error("..Parse error, expected '(' or constant in line %d\n",
305  iLine);
306  return -1;
307  }
308 
309  if (inv)
310  thisval = !thisval;
311 
312  /* Check how to combine the current value */
313  if (pstart[0] == '(')
314  {
315  val = thisval;
316  }
317  else if (pstart[0] == '&' && pstart[1] == '&')
318  {
319  val = val && thisval;
320  }
321  else if (pstart[0] == '&' && pstart[1] != '&')
322  {
323  val = val & thisval;
324  }
325  else if (pstart[0] == '|' && pstart[1] == '|')
326  {
327  trace("found || val = %d, thisval = %d\n", val, thisval);
328  val = val || thisval;
329  }
330  else if (pstart[0] == '|' && pstart[1] != '|')
331  {
332  val = val | thisval;
333  }
334  else if (pstart[0] == '+')
335  {
336  val = val + thisval;
337  }
338  else
339  {
340  error("+Parse error: expected '(' or operator in Line %d, got %c\n",
341  iLine, pstart[0]);
342  return -1;
343  }
344 
345  p = GetNextChar(p);
346 
347  /* End of current subexpression? */
348  if (*p == ')')
349  {
350  if (pNext)
351  {
352  *pNext = p + 1;
353  }
354  return val;
355  }
356 
357  /* Continue with a new start position */
358  pstart = p;
359  }
360 
361  return val;
362 }
363 
364 int
365 ParseInputFile(const char *pszInFile, FILE *fileOut)
366 {
367  char* pInputData, *pCurrentLine, *p1, *p2;
368  size_t cbInFileLenth;
369  int iIfLevel, iCopyLevel;
370 
371  trace("parsing input file: %s\n", pszInFile);
372 
373  /* Set the global file name */
374  gpszCurFile = pszInFile;
375 
376  /* Load the input file into memory */
377  pInputData = LoadFile(pszInFile, &cbInFileLenth);
378  if (!pInputData)
379  {
380  error("Could not load input file %s\n", pszInFile);
381  return -1;
382  }
383 
384  /* Zero terminate the file */
385  pInputData[cbInFileLenth] = 0;
386 
387  pCurrentLine = pInputData;
388  iLine = 1;
389  iCopyLevel = iIfLevel = 0;
390 
391  /* The main processing loop */
392  do
393  {
394  trace("line %d: ", iLine);
395 
396  /* If this is a normal line ... */
397  if (pCurrentLine[0] != '$')
398  {
399  /* Check if we are to copy this line */
400  if (iCopyLevel == iIfLevel)
401  {
402  trace("copying\n");
403  WriteLine(pCurrentLine, fileOut);
404  }
405  else
406  trace("skipping\n");
407 
408  /* Continue with next line */
409  continue;
410  }
411 
412  /* Check for $endif */
413  if (strncmp(pCurrentLine, "$endif", 6) == 0)
414  {
415  trace("found $endif\n");
416  if (iIfLevel <= 0)
417  {
418  error("Parse error: $endif without $if in %s:%d\n", pszInFile, iLine);
419  return -1;
420  }
421  if (iCopyLevel == iIfLevel)
422  {
423  iCopyLevel--;
424  }
425  iIfLevel--;
426 
427  /* Continue with next line */
428  continue;
429  }
430 
431  /* The rest is only parsed when we are in a true block */
432  if (iCopyLevel < iIfLevel)
433  {
434  trace("skipping\n");
435 
436  /* Continue with next line */
437  continue;
438  }
439 
440  /* Check for $define */
441  if (strncmp(pCurrentLine, "$define", 7) == 0)
442  {
443  PDEFINE pDefine;
444  char *pchName, *pchValue;
445  size_t cchName, cchValue;
446 
447  trace("found $define\n");
448  p1 = GetNextChar(pCurrentLine + 7);
449  if (*p1 != '(')
450  {
451  error("Parse error: expected '(' at %s:%d\n",
452  pszInFile, iLine);
453  return -1;
454  }
455 
456  pchName = GetNextChar(p1 + 1);
457  cchName = strxlen(pchName);
458  p1 = GetNextChar(pchName + cchName);
459 
460  /* Check for assignment */
461  if (*p1 == '=')
462  {
463  trace("found $define with assignment\n");
464  pchValue = GetNextChar(p1 + 1);
465  cchValue = strxlen(pchValue);
466  p1 = GetNextChar(pchValue + cchValue);
467  }
468  else
469  {
470  pchValue = 0;
471  cchValue = 0;
472  }
473 
474  /* Allocate a DEFINE structure */
475  pDefine = malloc(sizeof(DEFINE) + cchName + cchValue + 2);
476  if (pDefine == 0)
477  {
478  error("Failed to allocate %u bytes\n",
479  sizeof(DEFINE) + cchName + cchValue + 2);
480  return -1;
481  }
482 
483  pDefine->pszName = pDefine->achBuffer;
484  strncpy(pDefine->pszName, pchName, cchName);
485  pDefine->pszName[cchName] = 0;
486  pDefine->cchName = cchName;
487  pDefine->val = 1;
488 
489  if (pchValue != 0)
490  {
491  pDefine->pszValue = &pDefine->achBuffer[cchName + 1];
492  strncpy(pDefine->pszValue, pchValue, cchValue);
493  pDefine->pszValue[cchValue] = 0;
494  pDefine->cchValue = cchValue;
495  }
496  else
497  {
498  pDefine->pszValue = 0;
499  pDefine->cchValue = 0;
500  }
501 
502  /* Insert the new define into the global list */
503  pDefine->pNext = gpDefines;
504  gpDefines = pDefine;
505 
506  /* Check for closing ')' */
507  if (*p1 != ')')
508  {
509  error("Parse error: expected ')' at %s:%d\n",
510  pszInFile, iLine);
511  return -1;
512  }
513  }
514 
515  /* Check for $if */
516  else if (strncmp(pCurrentLine, "$if", 3) == 0)
517  {
518  int val;
519 
520  trace("found $if\n");
521  /* Increase the if-level */
522  iIfLevel++;
523 
524  /* Get beginning of the expression */
525  p1 = GetNextChar(pCurrentLine + 3);
526 
527  /* evaluate the expression */
528  val = EvaluateExpression(p1, 0);
529 
530  if (val)
531  {
532  iCopyLevel = iIfLevel;
533  }
534  else if (val == -1)
535  {
536  /* Parse error */
537  return -1;
538  }
539  }
540 
541  /* Check for $include */
542  else if (strncmp(pCurrentLine, "$include", 8) == 0)
543  {
544  int ret;
545 
546  trace("found $include\n");
547  p1 = GetNextChar(pCurrentLine + 8);
548  if (*p1 != '(')
549  {
550  error("Parse error: expected '(' at %s:%d, found '%c'\n",
551  pszInFile, iLine, *p1);
552  return -1;
553  }
554  p1++;
555  p2 = strchr(p1, ')');
556  *p2 = 0;
557 
558  /* Parse the included file */
559  ret = ParseInputFile(p1, fileOut);
560 
561  /* Restore the global file name */
562  gpszCurFile = pszInFile;
563 
564  /* Restore the zeroed character */
565  *p2 = ')';
566 
567  if (ret == -1)
568  {
569  return -1;
570  }
571  }
572 
573  /* Check for $$ comment */
574  else if (strncmp(pCurrentLine, "$$", 2) == 0)
575  {
576  trace("$$ ignored\n");
577  /* continue with next line */
578  continue;
579  }
580 
581  else
582  {
583  trace("wot:%s\n", pCurrentLine);
584  }
585 
586  /* Continue with next line */
587  }
588  while (pCurrentLine = GetNextLine(pCurrentLine),
589  iLine++,
590  pCurrentLine != 0);
591 
592  /* Free the file data */
593  free(pInputData);
594 
595  trace("Done with file.\n\n");
596 
597  return 0;
598 }
599 
600 
601 int
602 main(int argc, char* argv[])
603 {
604  char *pszInFile, *pszOutFile;
605  FILE* fileOut;
606  int ret;
607 
608  if (argc != 3)
609  {
610  error("Usage: hpp <inputfile> <outputfile>\n");
611  exit(1);
612  }
613 
614  pszInFile = convert_path(argv[1]);
615  pszOutFile = convert_path(argv[2]);
616 
617  fileOut = fopen(pszOutFile, "wb");
618  if (fileOut == NULL)
619  {
620  error("Cannot open output file %s", pszOutFile);
621  exit(1);
622  }
623 
624  ret = ParseInputFile(pszInFile, fileOut);
625 
626  fclose(fileOut);
627  free(pszInFile);
628  free(pszOutFile);
629 
630  return ret;
631 }
static int argc
Definition: ServiceArgs.c:12
char * GetFolder(const char *pszFullPath)
Definition: hpp.c:68
int error(char *format,...)
Definition: hpp.c:117
struct _DEFINE * pNext
Definition: hpp.c:25
_Check_return_ double __cdecl strtod(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr)
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define free
Definition: debug_ros.c:5
char * GetNextLine(char *pszLine)
Definition: hpp.c:135
unsigned int cchName
Definition: hpp.c:28
PDEFINE FindDefine(const char *p, char **pNext)
Definition: hpp.c:167
#define isalpha(c)
Definition: acclib.h:74
DEFINE * gpDefines
Definition: hpp.c:34
void WriteLine(char *pchLine, FILE *fileOut)
Definition: hpp.c:194
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
_Check_return_opt_ _CRTIMP size_t __cdecl fwrite(_In_reads_bytes_(_Size *_Count) const void *_Str, _In_ size_t _Size, _In_ size_t _Count, _Inout_ FILE *_File)
#define argv
Definition: mplay32.c:18
const char * gpszCurFile
Definition: hpp.c:36
Definition: hpp.c:23
#define pch(ap)
Definition: match.c:418
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define trace
Definition: hpp.c:20
int EvaluateExpression(char *pExpression, char **pNext)
Definition: hpp.c:253
_In_ PSID _Out_writes_to_opt_ cchName LPSTR _Inout_ LPDWORD cchName
Definition: winbase.h:2713
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_opt_ _CRTIMP size_t __cdecl fread(_Out_writes_bytes_(_ElementSize *_Count) void *_DstBuf, _In_ size_t _ElementSize, _In_ size_t _Count, _Inout_ FILE *_File)
#define va_end(ap)
Definition: acmsvcex.h:90
unsigned int cchValue
Definition: hpp.c:30
int iLine
Definition: hpp.c:35
_Check_return_ _CRTIMP char *__cdecl strdup(_In_opt_z_ const char *_Src)
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:41
smooth NULL
Definition: ftsmooth.c:416
_Check_return_opt_ _CRTIMP int __cdecl fseek(_Inout_ FILE *_File, _In_ long _Offset, _In_ int _Origin)
struct _DEFINE DEFINE
char * va_list
Definition: acmsvcex.h:78
void * LoadFile(const char *pszFileName, size_t *pFileSize)
Definition: hpp.c:74
#define isdigit(c)
Definition: acclib.h:68
int ParseInputFile(const char *pszInFile, FILE *fileOut)
Definition: hpp.c:365
GLuint GLfloat * val
Definition: glext.h:7180
#define SEEK_SET
Definition: jmemansi.c:26
const char file[]
Definition: icontest.c:11
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
char * pszName
Definition: hpp.c:27
int ret
static const WCHAR L[]
Definition: oid.c:1250
GLenum GLsizei len
Definition: glext.h:6722
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
int main(int argc, char *argv[])
Definition: hpp.c:602
LPSTR pExpression
Definition: symbols.c:93
#define va_start(ap, A)
Definition: acmsvcex.h:91
char * strchr(const char *String, int ch)
Definition: utclib.c:501
int EvaluateConstant(const char *p, char **pNext)
Definition: hpp.c:241
GLuint res
Definition: glext.h:9613
_Check_return_ _CRTIMP long __cdecl ftell(_Inout_ FILE *_File)
FILE * stderr
#define SEEK_END
Definition: cabinet.c:27
int val
Definition: hpp.c:26
#define malloc
Definition: debug_ros.c:4
char * convert_path(const char *origpath)
Definition: hpp.c:39
char achBuffer[1]
Definition: hpp.c:31
static __ms_va_list valist
Definition: printf.c:59
void exit(int exitcode)
Definition: _exit.c:33
GLfloat GLfloat p
Definition: glext.h:8902
_Check_return_opt_ _CRTIMP int __cdecl vfprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format, va_list _ArgList)
char * GetNextChar(const char *psz)
Definition: hpp.c:128
struct _DEFINE * PDEFINE
int strxlen(const char *psz)
Definition: hpp.c:155
char * pszValue
Definition: hpp.c:29
Definition: fci.c:126