Dump hardware config. with -verbose option.

This patch dumps the content of the hardware configuration
file when the -verbose option (or equivalent -debug-init)
is used.

This is useful to determine exactly what is launched when
debugging emulator issues.

Change-Id: I101b87cddb12c603b43420ea72bb357fc33f327d
diff --git a/Makefile.common b/Makefile.common
index 9c6d40a..15d6801 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -78,6 +78,7 @@
 	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 @@
         }
         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 */