| /* | |
| * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>. | |
| * | |
| * 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 <stddef.h> | |
| #include <stdint.h> | |
| #include <stdlib.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <errno.h> | |
| #include <sys/types.h> | |
| #include <sys/stat.h> | |
| #include <sys/mman.h> | |
| #include <unistd.h> | |
| #include <fcntl.h> | |
| #include <getopt.h> | |
| #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; | |
| } |