c-hdr-parser: add header open and syntax validation checks
This commit is contained in:
parent
159c172082
commit
02266b4dea
1 changed files with 70 additions and 1 deletions
|
@ -4,6 +4,7 @@
|
|||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h> /*close()*/
|
||||
|
||||
/// realloc s1 and append s2 to it (modifies only s1)
|
||||
char *cstr_append(char *s1, const char *s2) {
|
||||
|
@ -37,6 +38,62 @@ FILE *open_c_header(const char *cc_cmd, const char *hdr_fn) {
|
|||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a header file through the compiler to validate it's syntax
|
||||
*/
|
||||
int valid_c_header(const char *cc_cmd, const char *hdr_fn) {
|
||||
|
||||
static const char tmppath[] = "/tmp/.";
|
||||
|
||||
char *test_fn = strdup(tmppath);
|
||||
if ( test_fn == NULL ) return 0;
|
||||
test_fn = cstr_append(test_fn, hdr_fn);
|
||||
if ( test_fn == NULL ) return 0;
|
||||
test_fn = cstr_append(test_fn, ".o.XXXXXX");
|
||||
if ( test_fn == NULL ) return 0;
|
||||
|
||||
// NOTE: This generates a unique filename by replacing the 'XXXXXX' with random chars then
|
||||
// opens the file. It MODIFIES its argument string to contain the random chars selected to
|
||||
// replace the 'XXXXXX' so after call if the filedesc is valid, test_fn is the true filename.
|
||||
int r = mkstemp(test_fn);
|
||||
if ( r == -1 ) {
|
||||
free( test_fn );
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(r);
|
||||
|
||||
char *cmd = strdup("echo \"#include <");
|
||||
if ( cmd == NULL ) goto FAILRET;
|
||||
cmd = cstr_append(cmd, hdr_fn);
|
||||
if ( cmd == NULL ) goto FAILRET;
|
||||
cmd = cstr_append(cmd, ">\" | ");
|
||||
if ( cmd == NULL ) goto FAILRET;
|
||||
cmd = cstr_append(cmd, cc_cmd);
|
||||
if ( cmd == NULL ) goto FAILRET;
|
||||
cmd = cstr_append(cmd, " -I . -c -x c -o "); /*include ./; compile only, don't link; c syntax*/
|
||||
if ( cmd == NULL ) goto FAILRET;
|
||||
cmd = cstr_append(cmd, test_fn);
|
||||
if ( cmd == NULL ) goto FAILRET;
|
||||
cmd = cstr_append(cmd, " -"); /*use stdin*/
|
||||
if ( cmd == NULL ) goto FAILRET;
|
||||
|
||||
puts(cmd);
|
||||
|
||||
int ret = system(cmd);
|
||||
|
||||
remove( test_fn );
|
||||
free( test_fn );
|
||||
free( cmd );
|
||||
|
||||
return (ret == 0);
|
||||
FAILRET:
|
||||
remove( test_fn );
|
||||
free( test_fn );
|
||||
if ( cmd ) free( cmd );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Parse a series of keywords/identifiers until a non-kw/id is found indicating the end
|
||||
char ** parse_c_header_identkws(size_t *nidkws, int *c, FILE *f) {
|
||||
|
||||
|
@ -559,8 +616,9 @@ int main(int argc, char *argv[]) {
|
|||
if ( argc <= 1 ) return 1;
|
||||
|
||||
const char *cmd = getenv("CC");
|
||||
cmd = (cmd == NULL) ? "cc" : cmd;
|
||||
|
||||
FILE *fhdr = open_c_header(((cmd == NULL) ? "cc" : cmd), argv[1]);
|
||||
FILE *fhdr = open_c_header(cmd, argv[1]);
|
||||
|
||||
if ( fhdr == NULL ) {
|
||||
perror(argv[1]);
|
||||
|
@ -570,6 +628,17 @@ int main(int argc, char *argv[]) {
|
|||
size_t ndecl = 0;
|
||||
char **decl = parse_c_header(&ndecl, fhdr);
|
||||
|
||||
int r = pclose(fhdr);
|
||||
if ( r != 0 ) {
|
||||
fprintf(stdout, "[ERROR] Failed to read c-header '%s', CC=%s returned %d\n", argv[1], cmd, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( !valid_c_header(cmd, argv[1]) ) {
|
||||
fprintf(stdout, "[ERROR] System CC=%s failed to validate the syntax of c-header: %s\n", cmd, argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (size_t n=0; n < ndecl; n++) {
|
||||
puts(decl[n]);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue