/* * Copyright (C) 2010 Michael Brown . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #define eprintf(...) fprintf ( stderr, __VA_ARGS__ ) /** Command-line options */ struct options { }; /** Error usage information */ struct einfo { /** Size of error information record */ uint32_t size; /** Error number */ uint32_t error; /** Offset to error description (NUL-terminated) */ uint32_t desc; /** Offset to file name (NUL-terminated) */ uint32_t file; /** Line number */ uint32_t line; } __attribute__ (( packed )); /** * Process einfo file * * @v infile Filename * @v opts Command-line options */ static void einfo ( const char *infile, struct options *opts __attribute__ (( unused )) ) { int fd; struct stat stat; size_t len; void *start; struct einfo *einfo; /* Open einfo file */ if ( ( fd = open ( infile, O_RDONLY ) ) < 0 ) { eprintf ( "Cannot open \"%s\": %s\n", infile, strerror ( errno ) ); exit ( 1 ); } /* Get file size */ if ( fstat ( fd, &stat ) < 0 ) { eprintf ( "Cannot stat \"%s\": %s\n", infile, strerror ( errno ) ); exit ( 1 ); } len = stat.st_size; if ( len ) { /* Map file */ if ( ( start = mmap ( NULL, len, PROT_READ, MAP_SHARED, fd, 0 ) ) == MAP_FAILED ) { eprintf ( "Cannot mmap \"%s\": %s\n", infile, strerror ( errno ) ); exit ( 1 ); } /* Iterate over einfo records */ for ( einfo = start ; ( ( void * ) einfo ) < ( start + len ) ; einfo = ( ( ( void * ) einfo ) + einfo->size ) ) { printf ( "%08x\t%s\t%d\t%s\n", einfo->error, ( ( ( char * ) einfo ) + einfo->file ), einfo->line, ( ( ( char * ) einfo ) + einfo->desc ) ); } /* Unmap file */ munmap ( start, len ); } /* Close file */ close ( fd ); } /** * Print help * * @v program_name Program name */ static void print_help ( const char *program_name ) { eprintf ( "Syntax: %s file1.einfo [file2.einfo...]\n", program_name ); } /** * Parse command-line options * * @v argc Argument count * @v argv Argument list * @v opts Options structure to populate */ static int parse_options ( const int argc, char **argv, struct options *opts __attribute__ (( unused )) ) { int c; while (1) { int option_index = 0; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { 0, 0, 0, 0 } }; if ( ( c = getopt_long ( argc, argv, "s:h", long_options, &option_index ) ) == -1 ) { break; } switch ( c ) { case 'h': print_help ( argv[0] ); exit ( 0 ); case '?': default: exit ( 2 ); } } return optind; } int main ( int argc, char **argv ) { struct options opts = { }; int infile_index; const char *infile; /* Parse command-line arguments */ infile_index = parse_options ( argc, argv, &opts ); if ( argc <= infile_index ) { print_help ( argv[0] ); exit ( 2 ); } /* Process each einfo file */ for ( ; infile_index < argc ; infile_index++ ) { infile = argv[infile_index]; einfo ( infile, &opts ); } return 0; }