2 * Copyright (c) 2003 Matthijs Hollemans
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
38 char lexfile
[B_PATH_NAME_LENGTH
];
43 const char* rsrc_file
;
45 static jmp_buf abort_jmp
; // for aborting compilation
47 // When it encounters an error, the parser immediately aborts (we don't try
48 // error recovery). But its parse stack may still contain malloc'ed objects.
49 // We keep track of these memory blocks in the mem_list, so we can properly
50 // free them in case of an error (which is the polite thing to do since we
51 // are a shared library). If the compilation was successful, then mem_list
52 // should be empty. In DEBUG mode we dump some statistics to verify that the
53 // parser properly frees up objects when it is done with them.
62 typedef std::list
<mem_t
> mem_list_t
;
63 typedef mem_list_t::iterator mem_iter_t
;
65 static mem_list_t mem_list
;
67 static ptr_list_t mem_list
;
73 AddIncludeDir(const char *file
);
81 AddIncludeDir::AddIncludeDir(const char *file
)
83 // ignore the special stdin file
84 if (!strcmp(file
, "-"))
87 if (fPath
.SetTo(file
) != B_OK
88 || fPath
.GetParent(&fPath
) != B_OK
) {
93 rdef_add_include_dir(fPath
.Path(), false);
97 AddIncludeDir::~AddIncludeDir()
99 if (fPath
.InitCheck() == B_OK
)
100 rdef_remove_include_dir(fPath
.Path());
108 alloc_mem(size_t size
)
110 void *ptr
= malloc(size
); // can be 0
112 abort_compile(B_NO_MEMORY
, "out of memory");
117 mem
.file
= strdup(lexfile
);
119 mem_list
.push_front(mem
);
121 mem_list
.push_front(ptr
);
133 for (mem_iter_t i
= mem_list
.begin(); i
!= mem_list
.end(); ++i
) {
142 mem_list
.remove(ptr
);
153 if (mem_list
.size() != 0)
154 printf("mem_list leaks %ld objects\n", mem_list
.size());
156 for (mem_iter_t i
= mem_list
.begin(); i
!= mem_list
.end(); ) {
157 printf("%p allocated at %s:%ld\n", i
->ptr
, i
->file
, i
->line
);
160 i
= mem_list
.erase(i
);
163 free_ptr_list(mem_list
);
169 abort_compile(status_t err
, const char *format
, ...)
174 rdef_err_line
= yylineno
;
175 strcpy(rdef_err_file
, lexfile
);
177 va_start(ap
, format
);
178 vsprintf(rdef_err_msg
, format
, ap
);
188 longjmp(abort_jmp
, 1);
193 compile_file(char *file
)
195 strcpy(lexfile
, file
);
197 // "-" means reading from stdin
198 if (strcmp(file
, "-"))
199 yyin
= fopen(lexfile
, "r");
204 strcpy(rdef_err_file
, lexfile
);
205 rdef_err
= RDEF_FILE_NOT_FOUND
;
212 if (setjmp(abort_jmp
) == 0) {
216 // About error handling: If the bison-generated parser encounters
217 // a syntax error, it calls yyerror(), aborts parsing, and returns
218 // from yyparse(). For other kinds of errors (semantics, problem
219 // writing to BResources, etc), we bail out with a longjmp(). From
220 // then on, we can tell success or failure by looking at rdef_err.
231 status_t err
= entry
.SetTo(rsrc_file
, true);
233 uint32 openMode
= B_READ_WRITE
| B_CREATE_FILE
;
234 bool clobber
= false;
236 if (!(flags
& RDEF_MERGE_RESOURCES
)) {
237 openMode
|= B_ERASE_FILE
;
241 err
= file
.SetTo(&entry
, openMode
);
243 err
= rsrc
.SetTo(&file
, clobber
);
253 if (rdef_err
== B_OK
|| (flags
& RDEF_MERGE_RESOURCES
) != 0)
256 entry
.Remove(); // throw away output file
264 rdef_compile(const char *outputFile
)
268 if (outputFile
== NULL
|| outputFile
[0] == '\0') {
269 rdef_err
= B_BAD_VALUE
;
273 rsrc_file
= outputFile
;
274 rdef_err
= open_output_file();
275 if (rdef_err
!= B_OK
)
278 for (ptr_iter_t i
= input_files
.begin();
279 (i
!= input_files
.end()) && (rdef_err
== B_OK
); ++i
) {
280 char *path
= (char *)*i
;
282 AddIncludeDir
add(path
);