diff options
-rw-r--r-- | Makefile.common | 1 | ||||
-rw-r--r-- | android/main.c | 20 | ||||
-rw-r--r-- | android/utils/lineinput.c | 244 | ||||
-rw-r--r-- | android/utils/lineinput.h | 56 |
4 files changed, 321 insertions, 0 deletions
diff --git a/Makefile.common b/Makefile.common index 9c6d40a..15d6801 100644 --- a/Makefile.common +++ b/Makefile.common @@ -78,6 +78,7 @@ LOCAL_SRC_FILES += \ android/utils/filelock.c \ android/utils/ini.c \ android/utils/intmap.c \ + android/utils/lineinput.c \ android/utils/mapfile.c \ android/utils/misc.c \ android/utils/panic.c \ diff --git a/android/main.c b/android/main.c index aa3ee46..37bf34a 100644 --- a/android/main.c +++ b/android/main.c @@ -39,6 +39,7 @@ #include "android/user-config.h" #include "android/utils/bufprint.h" #include "android/utils/filelock.h" +#include "android/utils/lineinput.h" #include "android/utils/path.h" #include "android/utils/tempfile.h" @@ -1089,6 +1090,25 @@ int main(int argc, char **argv) } args[n++] = "-android-hw"; args[n++] = strdup(coreHwIniPath); + + /* In verbose mode, dump the file's content */ + if (VERBOSE_CHECK(init)) { + FILE* file = fopen(coreHwIniPath, "rt"); + if (file == NULL) { + derror("Could not open hardware configuration file: %s\n", + coreHwIniPath); + } else { + LineInput* input = lineInput_newFromStdFile(file); + const char* line; + printf("Content of hardware configuration file:\n"); + while ((line = lineInput_getLine(input)) != NULL) { + printf(" %s\n", line); + } + printf(".\n"); + lineInput_free(input); + fclose(file); + } + } } if(VERBOSE_CHECK(init)) { diff --git a/android/utils/lineinput.c b/android/utils/lineinput.c new file mode 100644 index 0000000..18e8a1c --- /dev/null +++ b/android/utils/lineinput.c @@ -0,0 +1,244 @@ +/* Copyright (C) 2011 The Android Open Source Project +** +** This software is licensed under the terms of the GNU General Public +** License version 2, as published by the Free Software Foundation, and +** may be copied, distributed, and modified under those terms. +** +** 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. +*/ +#include <errno.h> +#include "android/utils/system.h" +#include "android/utils/assert.h" +#include "android/utils/lineinput.h" + +struct LineInput { + char* line; + size_t line_size; + int line_num; + int error; + int eof; + + struct { + FILE* file; + } std; + + char line0[128]; +}; + +/* Error codes returned by the internal line reading function(s) */ +enum { + LINEINPUT_ERROR = -1, + LINEINPUT_EOF = -2, +}; + + +static LineInput* +_lineInput_new( void ) +{ + LineInput* input; + + ANEW0(input); + input->line = input->line0; + input->line_size = sizeof(input->line0); + + return input; +} + +/* Create a LineInput object that reads from a FILE* object */ +LineInput* +lineInput_newFromStdFile( FILE* file ) +{ + LineInput* input = _lineInput_new(); + + input->std.file = file; + return input; +} + +/* Grow the line buffer a bit */ +static void +_lineInput_grow( LineInput* input ) +{ + char* line; + + input->line_size += input->line_size >> 1; + line = input->line; + if (line == input->line0) + line = NULL; + + AARRAY_RENEW(line, input->line_size); + input->line = line; +} + +/* Forward declaration */ +static int _lineInput_getLineFromStdFile( LineInput* input, FILE* file ); + +const char* +lineInput_getLine( LineInput* input ) +{ + return lineInput_getLineAndSize(input, NULL); +} + +const char* +lineInput_getLineAndSize( LineInput* input, size_t *pSize ) +{ + int ret; + + /* be safe */ + if (pSize) + *pSize = 0; + + /* check parameters */ + if (input == NULL) { + errno = EINVAL; + return NULL; + } + + /* check state */ + if (input->error) { + return NULL; + } + if (input->eof) { + return NULL; + } + + ret = _lineInput_getLineFromStdFile(input, input->std.file); + if (ret >= 0) { + input->line_num += 1; + if (pSize != NULL) { + *pSize = ret; + return input->line; + } + return input->line; + } + if (ret == LINEINPUT_EOF) { + input->line_num += 1; + input->eof = 1; + return NULL; + } + if (ret == LINEINPUT_ERROR) { + input->error = errno; + return NULL; + } + AASSERT_UNREACHED(); + return NULL; +} + +/* Returns the number of the last line read by lineInput_getLine */ +int +lineInput_getLineNumber( LineInput* input ) +{ + return input->line_num; +} + +/* Returns TRUE iff the end of file was reached */ +int +lineInput_isEof( LineInput* input ) +{ + return (input->eof != 0); +} + +/* Return the error condition of a LineInput object. + * These are standard errno code for the last operation. + * Note: EOF corresponds to 0 here. + */ +int +lineInput_getError( LineInput* input ) +{ + return input->error; +} + +void +lineInput_free( LineInput* input ) +{ + if (input != NULL) { + if (input->line != NULL) { + if (input->line != input->line0) + AFREE(input->line); + input->line = NULL; + input->line_size = 0; + } + AFREE(input); + } +} + + +/* Internal function used to read a new line from a FILE* using fgets(). + * We assume that this is more efficient than calling fgetc() in a loop. + * + * Return length of line, or either LINEINPUT_EOF / LINEINPUT_ERROR + */ +static int +_lineInput_getLineFromStdFile( LineInput* input, FILE* file ) +{ + int offset = 0; + char* p; + + input->line[0] = '\0'; + + for (;;) { + char* buffer = input->line + offset; + int avail = input->line_size - offset; + + if (!fgets(buffer, avail, file)) { + /* We either reached the end of file or an i/o error occured. + * If we already read line data, just return it this time. + */ + if (offset > 0) { + return offset; + } + goto INPUT_ERROR; + } + + /* Find the terminating zero */ + p = memchr(buffer, '\0', avail); + AASSERT(p != NULL); + + if (p == buffer) { + /* This happens when the file has an embedded '\0', treat it + * as an eof, or bad things usually happen after that. */ + input->eof = 1; + if (offset > 0) + return offset; + else + return LINEINPUT_EOF; + } + + if (p[-1] != '\n' && p[-1] != '\r') { + /* This happens when the line is longer than our current buffer, + * so grow its size and try again. */ + offset = p - input->line; + _lineInput_grow(input); + continue; + } + + break; + } + + /* Get rid of trailing newline(s). Consider: \n, \r, and \r\n */ + if (p[-1] == '\n') { + p -= 1; + if (p > input->line && p[-1] == '\r') { + p -= 1; + } + p[0] = '\0'; + } + else if (p[-1] == '\r') { + p -= 1; + p[0] = '\0'; + } + + /* We did it */ + return (p - input->line); + +INPUT_ERROR: + if (feof(file)) { + input->eof = 1; + return LINEINPUT_EOF; + } + input->error = errno; + return LINEINPUT_ERROR; +} + diff --git a/android/utils/lineinput.h b/android/utils/lineinput.h new file mode 100644 index 0000000..1870285 --- /dev/null +++ b/android/utils/lineinput.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2011 The Android Open Source Project +** +** This software is licensed under the terms of the GNU General Public +** License version 2, as published by the Free Software Foundation, and +** may be copied, distributed, and modified under those terms. +** +** 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. +*/ +#ifndef _ANDROID_UTILS_LINEINPUT_H +#define _ANDROID_UTILS_LINEINPUT_H + +#include <stdio.h> + +/* A LineInput is used to read input text, one line at a time, + * into a temporary buffer owner by the LineInput object. + */ +typedef struct LineInput LineInput; + +/* Create a LineInput object that reads from a FILE* object */ +LineInput* lineInput_newFromStdFile( FILE* file ); + +/* Read next line from input. The result is zero-terminated with + * all newlines removed (\n, \r or \r\n) automatically. + * + * Returns NULL in case of error, or when the end of file is reached. + * See lineInput_isEof() and lineInput_getError() + * + * The returned string is owned by the LineInput object and its + * value will not persist any other call to any LineInput functions. + */ +const char* lineInput_getLine( LineInput* input ); + +/* Same as lineInput_getLine(), but also returns the line size into + * '*pSize' to save you a strlen() call. + */ +const char* lineInput_getLineAndSize( LineInput* input, size_t *pSize ); + +/* Returns the number of the last line read by lineInput_getLine */ +int lineInput_getLineNumber( LineInput* input ); + +/* Returns TRUE iff the end of file was reached */ +int lineInput_isEof( LineInput* input ); + +/* Return the error condition of a LineInput object. + * These are standard errno code for the last operation. + * Note: EOF corresponds to 0 here. + */ +int lineInput_getError( LineInput* input ); + +/* Free a LineInput object. */ +void lineInput_free( LineInput* input ); + +#endif /* _ANDROID_UTILS_LINEINPUT_H */ |