Move the C INI reader and its OCaml binding from builder to mllib, so it
can be used also elsewhere.
---
.gitignore | 6 +-
builder/Makefile.am | 40 ++++-------
builder/index-parse.y | 176 -----------------------------------------------
builder/index-parser-c.c | 121 --------------------------------
builder/index-scan.l | 144 --------------------------------------
builder/index-struct.c | 60 ----------------
builder/index-struct.h | 67 ------------------
builder/ini_reader.ml | 40 -----------
builder/ini_reader.mli | 24 -------
mllib/Makefile.am | 16 ++++-
mllib/index-parse.y | 176 +++++++++++++++++++++++++++++++++++++++++++++++
mllib/index-parser-c.c | 121 ++++++++++++++++++++++++++++++++
mllib/index-scan.l | 144 ++++++++++++++++++++++++++++++++++++++
mllib/index-struct.c | 60 ++++++++++++++++
mllib/index-struct.h | 67 ++++++++++++++++++
mllib/ini_reader.ml | 40 +++++++++++
mllib/ini_reader.mli | 24 +++++++
po/POTFILES | 8 +--
po/POTFILES-ml | 2 +-
19 files changed, 668 insertions(+), 668 deletions(-)
delete mode 100644 builder/index-parse.y
delete mode 100644 builder/index-parser-c.c
delete mode 100644 builder/index-scan.l
delete mode 100644 builder/index-struct.c
delete mode 100644 builder/index-struct.h
delete mode 100644 builder/ini_reader.ml
delete mode 100644 builder/ini_reader.mli
create mode 100644 mllib/index-parse.y
create mode 100644 mllib/index-parser-c.c
create mode 100644 mllib/index-scan.l
create mode 100644 mllib/index-struct.c
create mode 100644 mllib/index-struct.h
create mode 100644 mllib/ini_reader.ml
create mode 100644 mllib/ini_reader.mli
diff --git a/.gitignore b/.gitignore
index 6089122..8aded3b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,9 +55,6 @@ Makefile.in
/bash/virt-sparsify
/build-aux
/builder/.depend
-/builder/index-parse.c
-/builder/index-parse.h
-/builder/index-scan.c
/builder/libguestfs.conf
/builder/*.qcow2
/builder/stamp-virt-builder.pod
@@ -312,6 +309,9 @@ Makefile.in
/mllib/common_utils_tests
/mllib/config.ml
/mllib/dummy
+/mllib/index-parse.c
+/mllib/index-parse.h
+/mllib/index-scan.c
/mllib/JSON_tests
/mllib/libdir.ml
/mllib/oUnit-*
diff --git a/builder/Makefile.am b/builder/Makefile.am
index d69e25f..1d9ad54 100644
--- a/builder/Makefile.am
+++ b/builder/Makefile.am
@@ -17,8 +17,6 @@
include $(top_srcdir)/subdir-rules.mk
-AM_YFLAGS = -d
-
EXTRA_DIST = \
$(SOURCES_MLI) $(SOURCES_ML) $(SOURCES_C) \
libguestfs.gpg \
@@ -40,7 +38,6 @@ SOURCES_MLI = \
cache.mli \
downloader.mli \
index_parser.mli \
- ini_reader.mli \
languages.mli \
list_entries.mli \
pxzcat.mli \
@@ -52,7 +49,6 @@ SOURCES_ML = \
utils.ml \
pxzcat.ml \
setlocale.ml \
- ini_reader.ml \
paths.ml \
languages.ml \
cache.ml \
@@ -68,14 +64,14 @@ SOURCES_C = \
$(top_srcdir)/mllib/fsync-c.c \
$(top_srcdir)/mllib/uri-c.c \
$(top_srcdir)/mllib/mkdtemp-c.c \
+ $(top_srcdir)/mllib/index-parse.c \
+ $(top_srcdir)/mllib/index-parser-c.c \
+ $(top_srcdir)/mllib/index-scan.c \
+ $(top_srcdir)/mllib/index-struct.c \
$(top_srcdir)/customize/perl_edit-c.c \
$(top_srcdir)/customize/crypt-c.c \
$(top_srcdir)/fish/uri.c \
$(top_srcdir)/fish/file-edit.c \
- index-scan.c \
- index-struct.c \
- index-parse.c \
- index-parser-c.c \
pxzcat-c.c \
setlocale-c.c
@@ -95,7 +91,8 @@ virt_builder_CPPFLAGS = \
-I$(shell $(OCAMLC) -where) \
-I$(top_srcdir)/gnulib/lib \
-I$(top_srcdir)/src \
- -I$(top_srcdir)/fish
+ -I$(top_srcdir)/fish \
+ -I$(top_srcdir)/mllib
virt_builder_CFLAGS = \
-pthread \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
@@ -115,6 +112,7 @@ BOBJECTS = \
$(top_builddir)/mllib/JSON.cmo \
$(top_builddir)/mllib/uRI.cmo \
$(top_builddir)/mllib/mkdtemp.cmo \
+ $(top_builddir)/mllib/ini_reader.cmo \
$(top_builddir)/customize/customize_utils.cmo \
$(top_builddir)/customize/urandom.cmo \
$(top_builddir)/customize/random_seed.cmo \
@@ -273,10 +271,10 @@ install-exec-hook:
bin_PROGRAMS += virt-index-validate
virt_index_validate_SOURCES = \
- index-parse.y \
- index-scan.l \
- index-struct.h \
- index-struct.c \
+ $(top_srcdir)/mllib/index-parse.c \
+ $(top_srcdir)/mllib/index-scan.c \
+ $(top_srcdir)/mllib/index-struct.h \
+ $(top_srcdir)/mllib/index-struct.c \
index-validate.c
virt_index_validate_CPPFLAGS = \
@@ -284,7 +282,8 @@ virt_index_validate_CPPFLAGS = \
-I. \
-I$(top_builddir) \
-I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
- -I$(top_srcdir)/src
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/mllib
virt_index_validate_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
-Wno-unused-macros
@@ -306,21 +305,8 @@ stamp-virt-index-validate.pod: virt-index-validate.pod
touch $@
CLEANFILES += \
- index-parse.c \
- index-parse.h \
- index-scan.c \
stamp-virt-index-validate.pod
-if HAVE_OCAML
-# Automake-generated makefile has a rule ".y.c" but lacks a rule
".y.h".
-index-parse.h: index-parse.y
- touch $(srcdir)/index-parse.y
- $(MAKE) index-parse.c
-# Also it doesn't generate dependencies for the C files that include
-# index-parse.h.
-index-parser-c.c index-scan.c index-validate.c: index-parse.h
-endif
-
# Apparently there's no clean way with Automake to not have them
# in the distribution, so just remove them from the distdir.
dist-hook:
diff --git a/builder/index-parse.y b/builder/index-parse.y
deleted file mode 100644
index 82ea9d2..0000000
--- a/builder/index-parse.y
+++ /dev/null
@@ -1,176 +0,0 @@
-/* libguestfs virt-builder tool -*- fundamental -*-
- * Copyright (C) 2013 Red Hat Inc.
- *
- * 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
- * (at your option) 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 <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "index-struct.h"
-#include "index-parse.h"
-
-#define YY_EXTRA_TYPE struct parse_context *
-
-extern void yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context,
const char *msg);
-extern int yylex (YYSTYPE * yylval, YYLTYPE * yylloc, yyscan_t scanner);
-
-extern int do_parse (struct parse_context *context, FILE *in);
-extern void scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in);
-extern void scanner_destroy (yyscan_t scanner);
-
-/* Join two strings with \n */
-static char *
-concat_newline (const char *str1, const char *str2)
-{
- size_t len1, len2, len;
- char *ret;
-
- if (str2 == NULL)
- return strdup (str1);
-
- len1 = strlen (str1);
- len2 = strlen (str2);
- len = len1 + 1 /* \n */ + len2 + 1 /* \0 */;
- ret = malloc (len);
- memcpy (ret, str1, len1);
- ret[len1] = '\n';
- memcpy (ret + len1 + 1, str2, len2);
- ret[len-1] = '\0';
-
- return ret;
-}
-
-%}
-
-%code requires {
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void *yyscan_t;
-#endif
-}
-
-%locations
-
-%union {
- struct section *section;
- struct field *field;
- char *str;
-}
-
-%token <str> SECTION_HEADER
-%token <field> FIELD
-%token <str> VALUE_CONT
-%token EMPTY_LINE
-%token PGP_PROLOGUE
-%token PGP_EPILOGUE
-%token UNKNOWN_LINE
-
-%type <section> sections section
-%type <field> fields field
-%type <str> continuations
-
-%pure-parser
-
-%lex-param { yyscan_t scanner }
-%parse-param { yyscan_t scanner }
-%parse-param { struct parse_context *context }
-
-%destructor { section_free ($$); } <section>
-%destructor { field_free ($$); } <field>
-
-%%
-
-index:
- sections
- { context->parsed_index = $1; }
- | PGP_PROLOGUE sections PGP_EPILOGUE
- { context->parsed_index = $2; }
-
-sections:
- emptylines section emptylines
- { $$ = $2; }
- | emptylines section EMPTY_LINE emptylines sections
- { $$ = $2; $$->next = $5; }
- | emptylines
- { $$ = NULL; }
-
-section:
- SECTION_HEADER fields
- { $$ = malloc (sizeof (struct section));
- $$->next = NULL;
- $$->name = $1;
- $$->fields = $2; }
-
-fields:
- /* empty */
- { $$ = NULL; }
- | field fields
- { $$ = $1; $$->next = $2; }
-
-field: FIELD continuations
- { $$ = $1;
- char *old_value = $$->value;
- $$->value = concat_newline (old_value, $2);
- free (old_value);
- free ($2); }
-
-continuations:
- /* empty */
- { $$ = NULL; }
- | VALUE_CONT continuations
- { $$ = concat_newline ($1, $2);
- free ($1);
- free ($2); }
-
-emptylines:
- /* empty */
- {}
- | EMPTY_LINE emptylines
- {}
-
-%%
-
-void
-yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context, const char
*msg)
-{
- int has_suffix = context->error_suffix != NULL &&
context->error_suffix[0] != 0;
-
- fprintf (stderr, "%s%s%s%ssyntax error at line %d: %s%s%s\n",
- context->progname ? context->progname : "",
- context->progname ? ": " : "",
- context->input_file ? context->input_file : "",
- context->input_file ? ": " : "",
- yylloc->first_line, msg,
- has_suffix ? " " : "",
- has_suffix ? context->error_suffix : "");
-}
-
-int
-do_parse (struct parse_context *context, FILE *in)
-{
- yyscan_t scanner;
- int res;
-
- scanner_init (&scanner, context, in);
- res = yyparse (scanner, context);
- scanner_destroy (scanner);
-
- return res;
-}
diff --git a/builder/index-parser-c.c b/builder/index-parser-c.c
deleted file mode 100644
index 52c8b86..0000000
--- a/builder/index-parser-c.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* virt-builder
- * Copyright (C) 2013 Red Hat Inc.
- *
- * 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
- * (at your option) 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.
- */
-
-/* This file handles the interface between the C/lex/yacc index file
- * parser, and the OCaml world. See index_parser.ml for the OCaml
- * type definition.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <caml/alloc.h>
-#include <caml/fail.h>
-#include <caml/memory.h>
-#include <caml/mlvalues.h>
-
-#ifdef HAVE_CAML_UNIXSUPPORT_H
-#include <caml/unixsupport.h>
-#else
-#define Nothing ((value) 0)
-extern void unix_error (int errcode, char * cmdname, value arg) Noreturn;
-#endif
-
-#include "index-struct.h"
-#include "index-parse.h"
-
-extern int do_parse (struct parse_context *context, FILE *in);
-
-extern value virt_builder_parse_index (value progv, value error_suffixv, value
filenamev);
-
-value
-virt_builder_parse_index (value progv, value error_suffixv, value filenamev)
-{
- CAMLparam2 (progv, filenamev);
- CAMLlocal5 (rv, v, sv, sv2, fv);
- struct section *sections;
- size_t i, nr_sections;
- struct parse_context context;
- FILE *in;
-
- parse_context_init (&context);
- context.progname = String_val (progv);
- context.input_file = String_val (filenamev);
- context.error_suffix = String_val (error_suffixv);
-
- in = fopen (String_val (filenamev), "r");
- if (in == NULL)
- unix_error (errno, (char *) "fopen", filenamev);
-
- if (do_parse (&context, in) != 0) {
- fclose (in);
- caml_invalid_argument ("parse error");
- }
-
- if (fclose (in) == EOF)
- unix_error (errno, (char *) "fclose", filenamev);
-
- /* Convert the parsed data to OCaml structures. */
- nr_sections = 0;
- for (sections = context.parsed_index; sections != NULL; sections = sections->next)
- nr_sections++;
- rv = caml_alloc (nr_sections, 0);
-
- for (i = 0, sections = context.parsed_index; sections != NULL;
- i++, sections = sections->next) {
- struct field *fields;
- size_t j, nr_fields;
-
- nr_fields = 0;
- for (fields = sections->fields; fields != NULL; fields = fields->next)
- nr_fields++;
- fv = caml_alloc (nr_fields, 0);
-
- for (j = 0, fields = sections->fields; fields != NULL;
- j++, fields = fields->next) {
- v = caml_alloc_tuple (3);
- sv = caml_copy_string (fields->key);
- Store_field (v, 0, sv); /* (key, Some subkey, value) */
- if (fields->subkey) {
- sv2 = caml_copy_string (fields->subkey);
- sv = caml_alloc (1, 0);
- Store_field (sv, 0, sv2);
- } else
- sv = Val_int (0);
- Store_field (v, 1, sv);
- sv = caml_copy_string (fields->value);
- Store_field (v, 2, sv);
- Store_field (fv, j, v); /* assign to return array of fields */
- }
-
- v = caml_alloc_tuple (2);
- sv = caml_copy_string (sections->name);
- Store_field (v, 0, sv); /* (name, fields) */
- Store_field (v, 1, fv);
- Store_field (rv, i, v); /* assign to return array of sections */
- }
-
- /* Free parsed data. */
- parse_context_free (&context);
-
- CAMLreturn (rv);
-}
diff --git a/builder/index-scan.l b/builder/index-scan.l
deleted file mode 100644
index 7125913..0000000
--- a/builder/index-scan.l
+++ /dev/null
@@ -1,144 +0,0 @@
-/* libguestfs virt-builder tool -*- fundamental -*-
- * Copyright (C) 2013 Red Hat Inc.
- *
- * 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
- * (at your option) 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.
- */
-
-%top{
-#include <config.h>
-}
-
-%{
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* Silence gcc warnings from the generated code. */
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-/* flex creates macros that it doesn't use */
-#pragma GCC diagnostic ignored "-Wunused-macros"
-/* on aarch64, flex doesn't know that char is unsigned */
-#pragma GCC diagnostic ignored "-Wsign-compare"
-/* on debian-mipsel, flex doesn't create prototypes for all functions */
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-#endif
-
-#include "index-struct.h"
-#include "index-parse.h"
-
-#define YY_EXTRA_TYPE struct parse_context *
-#define YY_USER_ACTION yylloc->first_line = yylloc->last_line = yylineno;
-
-extern void scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in);
-extern void scanner_destroy (yyscan_t scanner);
-
-%}
-
-%option nounput
-%option noyywrap
-%option yylineno
-%option reentrant
-%option bison-bridge
-%option bison-locations
-
-%%
-
- /* Apart from the PGP prologue/epilogue which is a hack, the
- * scanning strategy is to deal with the file strictly line by
- * line, and pass those lines up to the parser which deals with
- * whether they appear in the right order to be meaningful.
- * Note that flex does longest-match.
- */
-
- /* Ignore comments - '#' MUST appear at the start of a line. */
-^"#".*\n { yyextra->seen_comments++; }
-
- /* An empty line is significant. */
-^\n { return EMPTY_LINE; }
-
- /* [...] marks beginning of a section. */
-^"["[-A-Za-z0-9._]+"]"\n {
- yylval->str = strndup (yytext+1, yyleng-3);
- return SECTION_HEADER;
- }
-
- /* field=value or field[subfield]=value */
-^[A-Za-z0-9_.]+("["[A-Za-z0-9_,.]+"]")?"=".*\n {
- size_t i = strcspn (yytext, "=[");
- yylval->field = malloc (sizeof (struct field));
- yylval->field->next = NULL;
- yylval->field->key = strndup (yytext, i);
- if (yytext[i] == '[') {
- size_t j = strcspn (yytext+i+1, "]");
- yylval->field->subkey = strndup (yytext+i+1, j);
- i += 1+j+1;
- } else {
- yylval->field->subkey = NULL;
- }
- /* Note we chop the final \n off here. */
- yylval->field->value = strndup (yytext+i+1, yyleng-(i+2));
- return FIELD;
- }
-
- /* Continuation line for multi-line values. */
-^[[:blank:]].*\n {
- yylval->str = strndup (yytext+1, yyleng-2);
- return VALUE_CONT;
- }
-
- /* Hack to eat the PGP prologue. */
-^"-----BEGIN PGP SIGNED MESSAGE-----\n" {
- int c, prevnl = 0;
-
- /* Eat everything to the first blank line. */
- while ((c = input (yyscanner)) != EOF) {
- if (c == '\n' && prevnl)
- break;
- prevnl = c == '\n';
- }
-
- return PGP_PROLOGUE;
-}
-
- /* Hack to eat the PGP epilogue. */
-^"-----BEGIN PGP SIGNATURE-----\n" {
- /* Eat everything to the end of the file. */
- while (input (yyscanner) != EOF)
- ;
-
- return PGP_EPILOGUE;
-}
-
- /* anything else is an error */
-. {
- return UNKNOWN_LINE;
-}
-
-%%
-
-void
-scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in)
-{
- yylex_init (scanner);
- yyset_extra (context, *scanner);
- yyset_in (in, *scanner);
-}
-
-void
-scanner_destroy (yyscan_t scanner)
-{
- yylex_destroy (scanner);
-}
diff --git a/builder/index-struct.c b/builder/index-struct.c
deleted file mode 100644
index eacca6c..0000000
--- a/builder/index-struct.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* libguestfs virt-builder tool
- * Copyright (C) 2013 Red Hat Inc.
- *
- * 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
- * (at your option) 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 <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "index-struct.h"
-
-void
-parse_context_init (struct parse_context *context)
-{
- memset (context, 0, sizeof *context);
-}
-
-void
-parse_context_free (struct parse_context *context)
-{
- section_free (context->parsed_index);
-}
-
-void
-section_free (struct section *section)
-{
- if (section) {
- section_free (section->next);
- free (section->name);
- field_free (section->fields);
- free (section);
- }
-}
-
-void
-field_free (struct field *field)
-{
- if (field) {
- field_free (field->next);
- free (field->key);
- free (field->subkey);
- free (field->value);
- free (field);
- }
-}
diff --git a/builder/index-struct.h b/builder/index-struct.h
deleted file mode 100644
index ada35e3..0000000
--- a/builder/index-struct.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* libguestfs virt-builder tool
- * Copyright (C) 2013 Red Hat Inc.
- *
- * 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
- * (at your option) 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.
- */
-
-/* The data structures produced when parsing the index file. */
-
-#ifndef INDEX_STRUCT_H
-#define INDEX_STRUCT_H
-
-/* A section or list of sections. */
-struct section {
- struct section *next;
- char *name;
- struct field *fields;
-};
-
-/* A field or list of fields. */
-struct field {
- struct field *next;
- char *key;
- char *subkey;
- char *value;
-};
-
-/* A struct holding the data needed during the parsing. */
-struct parse_context {
- struct section *parsed_index; /* The result of the parsing. */
- /* yyparse sets this if any comments were seen. Required for checking
- * compatibility with virt-builder 1.24.
- */
- int seen_comments;
- const char *input_file;
- const char *progname;
- const char *error_suffix;
-};
-
-/* Initialize the content of a parse_context. */
-extern void parse_context_init (struct parse_context *state);
-
-/* Free the content of a parse_context. The actual pointer is not freed. */
-extern void parse_context_free (struct parse_context *state);
-
-/* Free the content of a section, recursively freeing also its fields.
- * The actual pointer is not freed.
- */
-extern void section_free (struct section *section);
-
-/* Free the content of a field, recursively freeing also its next field.
- * The actual pointer is not freed.
- */
-extern void field_free (struct field *field);
-
-#endif /* INDEX_STRUCT_H */
diff --git a/builder/ini_reader.ml b/builder/ini_reader.ml
deleted file mode 100644
index 50a06f9..0000000
--- a/builder/ini_reader.ml
+++ /dev/null
@@ -1,40 +0,0 @@
-(* virt-builder
- * Copyright (C) 2013-2015 Red Hat Inc.
- *
- * 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
- * (at your option) 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.
- *)
-
-open Common_utils
-
-type sections = section list
-and section = string * fields (* [name] + fields *)
-and fields = field list
-and field = string * string option * string (* key + subkey + value *)
-
-(* Types returned by the C index parser. *)
-type c_sections = c_section array
-and c_section = string * c_fields (* [name] + fields *)
-and c_fields = field array
-
-(* Calls yyparse in the C code. *)
-external parse_index : prog:string -> error_suffix:string -> string ->
c_sections = "virt_builder_parse_index"
-
-let read_ini ?(error_suffix = "") file =
- let sections = parse_index ~prog ~error_suffix file in
- let sections = Array.to_list sections in
- List.map (
- fun (n, fields) ->
- n, Array.to_list fields
- ) sections
diff --git a/builder/ini_reader.mli b/builder/ini_reader.mli
deleted file mode 100644
index 62567e8..0000000
--- a/builder/ini_reader.mli
+++ /dev/null
@@ -1,24 +0,0 @@
-(* virt-builder
- * Copyright (C) 2013-2015 Red Hat Inc.
- *
- * 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
- * (at your option) 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.
- *)
-
-type sections = section list
-and section = string * fields (* [name] + fields *)
-and fields = field list
-and field = string * string option * string (* key + subkey + value *)
-
-val read_ini : ?error_suffix:string -> string -> sections
diff --git a/mllib/Makefile.am b/mllib/Makefile.am
index 272c981..f7f3a66 100644
--- a/mllib/Makefile.am
+++ b/mllib/Makefile.am
@@ -17,6 +17,8 @@
include $(top_srcdir)/subdir-rules.mk
+AM_YFLAGS = -d
+
EXTRA_DIST = \
$(SOURCES_MLI) \
$(filter-out config.ml libdir.ml,$(SOURCES_ML)) \
@@ -29,6 +31,7 @@ CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o
SOURCES_MLI = \
common_utils.mli \
fsync.mli \
+ ini_reader.mli \
JSON.mli \
mkdtemp.mli \
planner.mli \
@@ -42,6 +45,7 @@ SOURCES_ML = \
common_gettext.ml \
common_utils.ml \
fsync.ml \
+ ini_reader.ml \
progress.ml \
uRI.ml \
mkdtemp.ml \
@@ -53,6 +57,10 @@ SOURCES_C = \
$(top_srcdir)/fish/progress.c \
$(top_srcdir)/fish/uri.c \
fsync-c.c \
+ index-scan.l \
+ index-struct.c \
+ index-parse.y \
+ index-parser-c.c \
mkdtemp-c.c \
progress-c.c \
uri-c.c
@@ -74,7 +82,8 @@ dummy_CPPFLAGS = \
-I$(top_srcdir)/fish
dummy_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(LIBVIRT_CFLAGS) $(LIBXML2_CFLAGS)
+ $(LIBVIRT_CFLAGS) $(LIBXML2_CFLAGS) \
+ -Wno-unused-macros
BOBJECTS = $(SOURCES_ML:.ml=.cmo)
XOBJECTS = $(BOBJECTS:.cmo=.cmx)
@@ -213,6 +222,11 @@ depend: .depend
endif
+CLEANFILES += \
+ index-parse.c \
+ index-parse.h \
+ index-scan.c
+
DISTCLEANFILES = .depend
.PHONY: depend docs
diff --git a/mllib/index-parse.y b/mllib/index-parse.y
new file mode 100644
index 0000000..82ea9d2
--- /dev/null
+++ b/mllib/index-parse.y
@@ -0,0 +1,176 @@
+/* libguestfs virt-builder tool -*- fundamental -*-
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * 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
+ * (at your option) 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "index-struct.h"
+#include "index-parse.h"
+
+#define YY_EXTRA_TYPE struct parse_context *
+
+extern void yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context,
const char *msg);
+extern int yylex (YYSTYPE * yylval, YYLTYPE * yylloc, yyscan_t scanner);
+
+extern int do_parse (struct parse_context *context, FILE *in);
+extern void scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in);
+extern void scanner_destroy (yyscan_t scanner);
+
+/* Join two strings with \n */
+static char *
+concat_newline (const char *str1, const char *str2)
+{
+ size_t len1, len2, len;
+ char *ret;
+
+ if (str2 == NULL)
+ return strdup (str1);
+
+ len1 = strlen (str1);
+ len2 = strlen (str2);
+ len = len1 + 1 /* \n */ + len2 + 1 /* \0 */;
+ ret = malloc (len);
+ memcpy (ret, str1, len1);
+ ret[len1] = '\n';
+ memcpy (ret + len1 + 1, str2, len2);
+ ret[len-1] = '\0';
+
+ return ret;
+}
+
+%}
+
+%code requires {
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void *yyscan_t;
+#endif
+}
+
+%locations
+
+%union {
+ struct section *section;
+ struct field *field;
+ char *str;
+}
+
+%token <str> SECTION_HEADER
+%token <field> FIELD
+%token <str> VALUE_CONT
+%token EMPTY_LINE
+%token PGP_PROLOGUE
+%token PGP_EPILOGUE
+%token UNKNOWN_LINE
+
+%type <section> sections section
+%type <field> fields field
+%type <str> continuations
+
+%pure-parser
+
+%lex-param { yyscan_t scanner }
+%parse-param { yyscan_t scanner }
+%parse-param { struct parse_context *context }
+
+%destructor { section_free ($$); } <section>
+%destructor { field_free ($$); } <field>
+
+%%
+
+index:
+ sections
+ { context->parsed_index = $1; }
+ | PGP_PROLOGUE sections PGP_EPILOGUE
+ { context->parsed_index = $2; }
+
+sections:
+ emptylines section emptylines
+ { $$ = $2; }
+ | emptylines section EMPTY_LINE emptylines sections
+ { $$ = $2; $$->next = $5; }
+ | emptylines
+ { $$ = NULL; }
+
+section:
+ SECTION_HEADER fields
+ { $$ = malloc (sizeof (struct section));
+ $$->next = NULL;
+ $$->name = $1;
+ $$->fields = $2; }
+
+fields:
+ /* empty */
+ { $$ = NULL; }
+ | field fields
+ { $$ = $1; $$->next = $2; }
+
+field: FIELD continuations
+ { $$ = $1;
+ char *old_value = $$->value;
+ $$->value = concat_newline (old_value, $2);
+ free (old_value);
+ free ($2); }
+
+continuations:
+ /* empty */
+ { $$ = NULL; }
+ | VALUE_CONT continuations
+ { $$ = concat_newline ($1, $2);
+ free ($1);
+ free ($2); }
+
+emptylines:
+ /* empty */
+ {}
+ | EMPTY_LINE emptylines
+ {}
+
+%%
+
+void
+yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context, const char
*msg)
+{
+ int has_suffix = context->error_suffix != NULL &&
context->error_suffix[0] != 0;
+
+ fprintf (stderr, "%s%s%s%ssyntax error at line %d: %s%s%s\n",
+ context->progname ? context->progname : "",
+ context->progname ? ": " : "",
+ context->input_file ? context->input_file : "",
+ context->input_file ? ": " : "",
+ yylloc->first_line, msg,
+ has_suffix ? " " : "",
+ has_suffix ? context->error_suffix : "");
+}
+
+int
+do_parse (struct parse_context *context, FILE *in)
+{
+ yyscan_t scanner;
+ int res;
+
+ scanner_init (&scanner, context, in);
+ res = yyparse (scanner, context);
+ scanner_destroy (scanner);
+
+ return res;
+}
diff --git a/mllib/index-parser-c.c b/mllib/index-parser-c.c
new file mode 100644
index 0000000..52c8b86
--- /dev/null
+++ b/mllib/index-parser-c.c
@@ -0,0 +1,121 @@
+/* virt-builder
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * 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
+ * (at your option) 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.
+ */
+
+/* This file handles the interface between the C/lex/yacc index file
+ * parser, and the OCaml world. See index_parser.ml for the OCaml
+ * type definition.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <caml/alloc.h>
+#include <caml/fail.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+
+#ifdef HAVE_CAML_UNIXSUPPORT_H
+#include <caml/unixsupport.h>
+#else
+#define Nothing ((value) 0)
+extern void unix_error (int errcode, char * cmdname, value arg) Noreturn;
+#endif
+
+#include "index-struct.h"
+#include "index-parse.h"
+
+extern int do_parse (struct parse_context *context, FILE *in);
+
+extern value virt_builder_parse_index (value progv, value error_suffixv, value
filenamev);
+
+value
+virt_builder_parse_index (value progv, value error_suffixv, value filenamev)
+{
+ CAMLparam2 (progv, filenamev);
+ CAMLlocal5 (rv, v, sv, sv2, fv);
+ struct section *sections;
+ size_t i, nr_sections;
+ struct parse_context context;
+ FILE *in;
+
+ parse_context_init (&context);
+ context.progname = String_val (progv);
+ context.input_file = String_val (filenamev);
+ context.error_suffix = String_val (error_suffixv);
+
+ in = fopen (String_val (filenamev), "r");
+ if (in == NULL)
+ unix_error (errno, (char *) "fopen", filenamev);
+
+ if (do_parse (&context, in) != 0) {
+ fclose (in);
+ caml_invalid_argument ("parse error");
+ }
+
+ if (fclose (in) == EOF)
+ unix_error (errno, (char *) "fclose", filenamev);
+
+ /* Convert the parsed data to OCaml structures. */
+ nr_sections = 0;
+ for (sections = context.parsed_index; sections != NULL; sections = sections->next)
+ nr_sections++;
+ rv = caml_alloc (nr_sections, 0);
+
+ for (i = 0, sections = context.parsed_index; sections != NULL;
+ i++, sections = sections->next) {
+ struct field *fields;
+ size_t j, nr_fields;
+
+ nr_fields = 0;
+ for (fields = sections->fields; fields != NULL; fields = fields->next)
+ nr_fields++;
+ fv = caml_alloc (nr_fields, 0);
+
+ for (j = 0, fields = sections->fields; fields != NULL;
+ j++, fields = fields->next) {
+ v = caml_alloc_tuple (3);
+ sv = caml_copy_string (fields->key);
+ Store_field (v, 0, sv); /* (key, Some subkey, value) */
+ if (fields->subkey) {
+ sv2 = caml_copy_string (fields->subkey);
+ sv = caml_alloc (1, 0);
+ Store_field (sv, 0, sv2);
+ } else
+ sv = Val_int (0);
+ Store_field (v, 1, sv);
+ sv = caml_copy_string (fields->value);
+ Store_field (v, 2, sv);
+ Store_field (fv, j, v); /* assign to return array of fields */
+ }
+
+ v = caml_alloc_tuple (2);
+ sv = caml_copy_string (sections->name);
+ Store_field (v, 0, sv); /* (name, fields) */
+ Store_field (v, 1, fv);
+ Store_field (rv, i, v); /* assign to return array of sections */
+ }
+
+ /* Free parsed data. */
+ parse_context_free (&context);
+
+ CAMLreturn (rv);
+}
diff --git a/mllib/index-scan.l b/mllib/index-scan.l
new file mode 100644
index 0000000..7125913
--- /dev/null
+++ b/mllib/index-scan.l
@@ -0,0 +1,144 @@
+/* libguestfs virt-builder tool -*- fundamental -*-
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * 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
+ * (at your option) 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.
+ */
+
+%top{
+#include <config.h>
+}
+
+%{
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Silence gcc warnings from the generated code. */
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+/* flex creates macros that it doesn't use */
+#pragma GCC diagnostic ignored "-Wunused-macros"
+/* on aarch64, flex doesn't know that char is unsigned */
+#pragma GCC diagnostic ignored "-Wsign-compare"
+/* on debian-mipsel, flex doesn't create prototypes for all functions */
+#pragma GCC diagnostic ignored "-Wmissing-prototypes"
+#endif
+
+#include "index-struct.h"
+#include "index-parse.h"
+
+#define YY_EXTRA_TYPE struct parse_context *
+#define YY_USER_ACTION yylloc->first_line = yylloc->last_line = yylineno;
+
+extern void scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in);
+extern void scanner_destroy (yyscan_t scanner);
+
+%}
+
+%option nounput
+%option noyywrap
+%option yylineno
+%option reentrant
+%option bison-bridge
+%option bison-locations
+
+%%
+
+ /* Apart from the PGP prologue/epilogue which is a hack, the
+ * scanning strategy is to deal with the file strictly line by
+ * line, and pass those lines up to the parser which deals with
+ * whether they appear in the right order to be meaningful.
+ * Note that flex does longest-match.
+ */
+
+ /* Ignore comments - '#' MUST appear at the start of a line. */
+^"#".*\n { yyextra->seen_comments++; }
+
+ /* An empty line is significant. */
+^\n { return EMPTY_LINE; }
+
+ /* [...] marks beginning of a section. */
+^"["[-A-Za-z0-9._]+"]"\n {
+ yylval->str = strndup (yytext+1, yyleng-3);
+ return SECTION_HEADER;
+ }
+
+ /* field=value or field[subfield]=value */
+^[A-Za-z0-9_.]+("["[A-Za-z0-9_,.]+"]")?"=".*\n {
+ size_t i = strcspn (yytext, "=[");
+ yylval->field = malloc (sizeof (struct field));
+ yylval->field->next = NULL;
+ yylval->field->key = strndup (yytext, i);
+ if (yytext[i] == '[') {
+ size_t j = strcspn (yytext+i+1, "]");
+ yylval->field->subkey = strndup (yytext+i+1, j);
+ i += 1+j+1;
+ } else {
+ yylval->field->subkey = NULL;
+ }
+ /* Note we chop the final \n off here. */
+ yylval->field->value = strndup (yytext+i+1, yyleng-(i+2));
+ return FIELD;
+ }
+
+ /* Continuation line for multi-line values. */
+^[[:blank:]].*\n {
+ yylval->str = strndup (yytext+1, yyleng-2);
+ return VALUE_CONT;
+ }
+
+ /* Hack to eat the PGP prologue. */
+^"-----BEGIN PGP SIGNED MESSAGE-----\n" {
+ int c, prevnl = 0;
+
+ /* Eat everything to the first blank line. */
+ while ((c = input (yyscanner)) != EOF) {
+ if (c == '\n' && prevnl)
+ break;
+ prevnl = c == '\n';
+ }
+
+ return PGP_PROLOGUE;
+}
+
+ /* Hack to eat the PGP epilogue. */
+^"-----BEGIN PGP SIGNATURE-----\n" {
+ /* Eat everything to the end of the file. */
+ while (input (yyscanner) != EOF)
+ ;
+
+ return PGP_EPILOGUE;
+}
+
+ /* anything else is an error */
+. {
+ return UNKNOWN_LINE;
+}
+
+%%
+
+void
+scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in)
+{
+ yylex_init (scanner);
+ yyset_extra (context, *scanner);
+ yyset_in (in, *scanner);
+}
+
+void
+scanner_destroy (yyscan_t scanner)
+{
+ yylex_destroy (scanner);
+}
diff --git a/mllib/index-struct.c b/mllib/index-struct.c
new file mode 100644
index 0000000..eacca6c
--- /dev/null
+++ b/mllib/index-struct.c
@@ -0,0 +1,60 @@
+/* libguestfs virt-builder tool
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * 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
+ * (at your option) 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "index-struct.h"
+
+void
+parse_context_init (struct parse_context *context)
+{
+ memset (context, 0, sizeof *context);
+}
+
+void
+parse_context_free (struct parse_context *context)
+{
+ section_free (context->parsed_index);
+}
+
+void
+section_free (struct section *section)
+{
+ if (section) {
+ section_free (section->next);
+ free (section->name);
+ field_free (section->fields);
+ free (section);
+ }
+}
+
+void
+field_free (struct field *field)
+{
+ if (field) {
+ field_free (field->next);
+ free (field->key);
+ free (field->subkey);
+ free (field->value);
+ free (field);
+ }
+}
diff --git a/mllib/index-struct.h b/mllib/index-struct.h
new file mode 100644
index 0000000..ada35e3
--- /dev/null
+++ b/mllib/index-struct.h
@@ -0,0 +1,67 @@
+/* libguestfs virt-builder tool
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * 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
+ * (at your option) 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.
+ */
+
+/* The data structures produced when parsing the index file. */
+
+#ifndef INDEX_STRUCT_H
+#define INDEX_STRUCT_H
+
+/* A section or list of sections. */
+struct section {
+ struct section *next;
+ char *name;
+ struct field *fields;
+};
+
+/* A field or list of fields. */
+struct field {
+ struct field *next;
+ char *key;
+ char *subkey;
+ char *value;
+};
+
+/* A struct holding the data needed during the parsing. */
+struct parse_context {
+ struct section *parsed_index; /* The result of the parsing. */
+ /* yyparse sets this if any comments were seen. Required for checking
+ * compatibility with virt-builder 1.24.
+ */
+ int seen_comments;
+ const char *input_file;
+ const char *progname;
+ const char *error_suffix;
+};
+
+/* Initialize the content of a parse_context. */
+extern void parse_context_init (struct parse_context *state);
+
+/* Free the content of a parse_context. The actual pointer is not freed. */
+extern void parse_context_free (struct parse_context *state);
+
+/* Free the content of a section, recursively freeing also its fields.
+ * The actual pointer is not freed.
+ */
+extern void section_free (struct section *section);
+
+/* Free the content of a field, recursively freeing also its next field.
+ * The actual pointer is not freed.
+ */
+extern void field_free (struct field *field);
+
+#endif /* INDEX_STRUCT_H */
diff --git a/mllib/ini_reader.ml b/mllib/ini_reader.ml
new file mode 100644
index 0000000..50a06f9
--- /dev/null
+++ b/mllib/ini_reader.ml
@@ -0,0 +1,40 @@
+(* virt-builder
+ * Copyright (C) 2013-2015 Red Hat Inc.
+ *
+ * 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
+ * (at your option) 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.
+ *)
+
+open Common_utils
+
+type sections = section list
+and section = string * fields (* [name] + fields *)
+and fields = field list
+and field = string * string option * string (* key + subkey + value *)
+
+(* Types returned by the C index parser. *)
+type c_sections = c_section array
+and c_section = string * c_fields (* [name] + fields *)
+and c_fields = field array
+
+(* Calls yyparse in the C code. *)
+external parse_index : prog:string -> error_suffix:string -> string ->
c_sections = "virt_builder_parse_index"
+
+let read_ini ?(error_suffix = "") file =
+ let sections = parse_index ~prog ~error_suffix file in
+ let sections = Array.to_list sections in
+ List.map (
+ fun (n, fields) ->
+ n, Array.to_list fields
+ ) sections
diff --git a/mllib/ini_reader.mli b/mllib/ini_reader.mli
new file mode 100644
index 0000000..62567e8
--- /dev/null
+++ b/mllib/ini_reader.mli
@@ -0,0 +1,24 @@
+(* virt-builder
+ * Copyright (C) 2013-2015 Red Hat Inc.
+ *
+ * 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
+ * (at your option) 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.
+ *)
+
+type sections = section list
+and section = string * fields (* [name] + fields *)
+and fields = field list
+and field = string * string option * string (* key + subkey + value *)
+
+val read_ini : ?error_suffix:string -> string -> sections
diff --git a/po/POTFILES b/po/POTFILES
index 7f1580c..d1115a0 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -1,8 +1,4 @@
align/scan.c
-builder/index-parse.c
-builder/index-parser-c.c
-builder/index-scan.c
-builder/index-struct.c
builder/index-validate.c
builder/pxzcat-c.c
builder/setlocale-c.c
@@ -259,6 +255,10 @@ lua/lua-guestfs.c
make-fs/make-fs.c
mllib/dummy.c
mllib/fsync-c.c
+mllib/index-parse.c
+mllib/index-parser-c.c
+mllib/index-scan.c
+mllib/index-struct.c
mllib/mkdtemp-c.c
mllib/progress-c.c
mllib/uri-c.c
diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index 8725385..ee0294c 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -3,7 +3,6 @@ builder/cache.ml
builder/cmdline.ml
builder/downloader.ml
builder/index_parser.ml
-builder/ini_reader.ml
builder/languages.ml
builder/list_entries.ml
builder/paths.ml
@@ -33,6 +32,7 @@ mllib/common_utils.ml
mllib/common_utils_tests.ml
mllib/config.ml
mllib/fsync.ml
+mllib/ini_reader.ml
mllib/libdir.ml
mllib/mkdtemp.ml
mllib/planner.ml
--
2.1.0