Split the huge list of else ifs which was used for parsing  'desc',
'depends', 'files' and 'deltas' files, into separate functions and move
them to a new file parse.c . This makes it possible for other backends
to share the same parse code. Also change the parsing from the giant
else if list to a single loop calling different functions as specified
in an array of parser structs (see  parse_lines() for details).

Move _alpm_delta_parse to parse.c and make it static.

Signed-off-by: Henning Garus <[email protected]>
---

I actually managed to make it longer, instead of shorter (well if you
take out comments and license headers this version is roughly as long 
as the old one), however I think it is more readable. Feel free to call
it overkill though.

I don't really like the ugets stuff I used to get the next line, but I
wanted this to work on something other than FILE*, even though this is
not used (yet), and this was the best thing I could come up with. I 
toyed around with using fopencookie, but that sucks when it comes to
portability (there is funopen on bsd, beyond that you are simply 
screwed).

I removed the memset for the line array, it should be fairly safe and I
ran valgrind with several pactests and it did not shout at me (at least
after I supressed the numerous leaks reported for bash).

Btw, is there a reason why pacman uses two different file formats (line
based in db files vs. keyword = value in .PKGINFO ?

 lib/libalpm/Makefile.am |    1 +
 lib/libalpm/be_files.c  |  222 +++++-----------------------------
 lib/libalpm/delta.c     |   56 ---------
 lib/libalpm/delta.h     |    1 -
 lib/libalpm/parse.c     |  305 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/libalpm/parse.h     |   40 ++++++
 6 files changed, 377 insertions(+), 248 deletions(-)
 create mode 100644 lib/libalpm/parse.c
 create mode 100644 lib/libalpm/parse.h

diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am
index 871855e..5ed8866 100644
--- a/lib/libalpm/Makefile.am
+++ b/lib/libalpm/Makefile.am
@@ -27,6 +27,7 @@ libalpm_la_SOURCES = \
        backup.h backup.c \
        be_files.c \
        be_package.c \
+       parse.h parse.c \
        cache.h cache.c \
        conflict.h conflict.c \
        db.h db.c \
diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c
index 21533ef..1066b60 100644
--- a/lib/libalpm/be_files.c
+++ b/lib/libalpm/be_files.c
@@ -31,7 +31,6 @@
 #include <ctype.h>
 #include <time.h>
 #include <limits.h> /* PATH_MAX */
-#include <locale.h> /* setlocale */
 
 /* libalpm */
 #include "db.h"
@@ -42,9 +41,9 @@
 #include "alpm.h"
 #include "handle.h"
 #include "package.h"
-#include "delta.h"
 #include "deps.h"
 #include "dload.h"
+#include "parse.h"
 
 
 /*
@@ -386,7 +385,8 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t 
inforeq)
 {
        FILE *fp = NULL;
        char path[PATH_MAX];
-       char line[513];
+       char *pkgname = NULL;
+       char *pkgver = NULL;
        char *pkgpath = NULL;
 
        ALPM_LOG_FUNC;
@@ -417,9 +417,6 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t 
inforeq)
        _alpm_log(PM_LOG_FUNCTION, "loading package data for %s : level=0x%x\n",
                        info->name, inforeq);
 
-       /* clear out 'line', to be certain - and to make valgrind happy */
-       memset(line, 0, 513);
-
        pkgpath = get_pkgpath(db, info);
 
        if(access(pkgpath, F_OK)) {
@@ -429,6 +426,7 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t 
inforeq)
                goto error;
        }
 
+
        /* DESC */
        if(inforeq & INFRQ_DESC) {
                snprintf(path, PATH_MAX, "%sdesc", pkgpath);
@@ -436,139 +434,26 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t 
inforeq)
                        _alpm_log(PM_LOG_ERROR, _("could not open file %s: 
%s\n"), path, strerror(errno));
                        goto error;
                }
-               while(!feof(fp)) {
-                       if(fgets(line, 256, fp) == NULL) {
-                               break;
-                       }
-                       _alpm_strtrim(line);
-                       if(strcmp(line, "%NAME%") == 0) {
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               if(strcmp(_alpm_strtrim(line), info->name) != 
0) {
-                                       _alpm_log(PM_LOG_ERROR, _("%s database 
is inconsistent: name "
-                                                               "mismatch on 
package %s\n"), db->treename, info->name);
-                               }
-                       } else if(strcmp(line, "%VERSION%") == 0) {
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               if(strcmp(_alpm_strtrim(line), info->version) 
!= 0) {
-                                       _alpm_log(PM_LOG_ERROR, _("%s database 
is inconsistent: version "
-                                                               "mismatch on 
package %s\n"), db->treename, info->name);
-                               }
-                       } else if(strcmp(line, "%FILENAME%") == 0) {
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               STRDUP(info->filename, _alpm_strtrim(line), 
goto error);
-                       } else if(strcmp(line, "%DESC%") == 0) {
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               STRDUP(info->desc, _alpm_strtrim(line), goto 
error);
-                       } else if(strcmp(line, "%GROUPS%") == 0) {
-                               while(fgets(line, 512, fp) && 
strlen(_alpm_strtrim(line))) {
-                                       char *linedup;
-                                       STRDUP(linedup, _alpm_strtrim(line), 
goto error);
-                                       info->groups = 
alpm_list_add(info->groups, linedup);
-                               }
-                       } else if(strcmp(line, "%URL%") == 0) {
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               STRDUP(info->url, _alpm_strtrim(line), goto 
error);
-                       } else if(strcmp(line, "%LICENSE%") == 0) {
-                               while(fgets(line, 512, fp) && 
strlen(_alpm_strtrim(line))) {
-                                       char *linedup;
-                                       STRDUP(linedup, _alpm_strtrim(line), 
goto error);
-                                       info->licenses = 
alpm_list_add(info->licenses, linedup);
-                               }
-                       } else if(strcmp(line, "%ARCH%") == 0) {
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               STRDUP(info->arch, _alpm_strtrim(line), goto 
error);
-                       } else if(strcmp(line, "%BUILDDATE%") == 0) {
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               _alpm_strtrim(line);
-
-                               char first = tolower(line[0]);
-                               if(first > 'a' && first < 'z') {
-                                       struct tm tmp_tm = {0}; /* initialize 
to null in case of failure */
-                                       setlocale(LC_TIME, "C");
-                                       strptime(line, "%a %b %e %H:%M:%S %Y", 
&tmp_tm);
-                                       info->builddate = mktime(&tmp_tm);
-                                       setlocale(LC_TIME, "");
-                               } else {
-                                       info->builddate = atol(line);
-                               }
-                       } else if(strcmp(line, "%INSTALLDATE%") == 0) {
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               _alpm_strtrim(line);
-
-                               char first = tolower(line[0]);
-                               if(first > 'a' && first < 'z') {
-                                       struct tm tmp_tm = {0}; /* initialize 
to null in case of failure */
-                                       setlocale(LC_TIME, "C");
-                                       strptime(line, "%a %b %e %H:%M:%S %Y", 
&tmp_tm);
-                                       info->installdate = mktime(&tmp_tm);
-                                       setlocale(LC_TIME, "");
-                               } else {
-                                       info->installdate = atol(line);
-                               }
-                       } else if(strcmp(line, "%PACKAGER%") == 0) {
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               STRDUP(info->packager, _alpm_strtrim(line), 
goto error);
-                       } else if(strcmp(line, "%REASON%") == 0) {
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               info->reason = 
(pmpkgreason_t)atol(_alpm_strtrim(line));
-                       } else if(strcmp(line, "%SIZE%") == 0 || strcmp(line, 
"%CSIZE%") == 0) {
-                               /* NOTE: the CSIZE and SIZE fields both share 
the "size" field
-                                *       in the pkginfo_t struct.  This can be 
done b/c CSIZE
-                                *       is currently only used in sync 
databases, and SIZE is
-                                *       only used in local databases.
-                                */
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               info->size = atol(_alpm_strtrim(line));
-                               /* also store this value to isize if isize is 
unset */
-                               if(info->isize == 0) {
-                                       info->isize = info->size;
-                               }
-                       } else if(strcmp(line, "%ISIZE%") == 0) {
-                               /* ISIZE (installed size) tag only appears in 
sync repositories,
-                                * not the local one. */
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               info->isize = atol(_alpm_strtrim(line));
-                       } else if(strcmp(line, "%MD5SUM%") == 0) {
-                               /* MD5SUM tag only appears in sync repositories,
-                                * not the local one. */
-                               if(fgets(line, 512, fp) == NULL) {
-                                       goto error;
-                               }
-                               STRDUP(info->md5sum, _alpm_strtrim(line), goto 
error);
-                       } else if(strcmp(line, "%REPLACES%") == 0) {
-                               while(fgets(line, 512, fp) && 
strlen(_alpm_strtrim(line))) {
-                                       char *linedup;
-                                       STRDUP(linedup, _alpm_strtrim(line), 
goto error);
-                                       info->replaces = 
alpm_list_add(info->replaces, linedup);
-                               }
-                       } else if(strcmp(line, "%FORCE%") == 0) {
-                               info->force = 1;
-                       }
+               STRDUP(pkgname, info->name, goto error);
+               STRDUP(pkgver, info->version, goto error);
+               if(_alpm_parse_desc(&_alpm_parse_from_file, fp, info) != 0) {
+                       goto error;
                }
+               if(strcmp(pkgname,info->name) != 0) {
+                       _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: 
name mismatch "
+                                       "on package %s\n"), db->treename, 
pkgname);
+               }
+               if(strcmp(pkgver,info->version) != 0) {
+                       _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: 
version mismatch "
+                               "on package %s\n"), db->treename, pkgver);
+               }
+               FREE(pkgname);
+               FREE(pkgver);
+               /* store size in isize if isize is unset */
+               if(info->isize == 0) {
+                       info->isize = info->size;
+               }
+
                fclose(fp);
                fp = NULL;
        }
@@ -580,21 +465,8 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t 
inforeq)
                        _alpm_log(PM_LOG_ERROR, _("could not open file %s: 
%s\n"), path, strerror(errno));
                        goto error;
                }
-               while(fgets(line, 256, fp)) {
-                       _alpm_strtrim(line);
-                       if(strcmp(line, "%FILES%") == 0) {
-                               while(fgets(line, 512, fp) && 
strlen(_alpm_strtrim(line))) {
-                                       char *linedup;
-                                       STRDUP(linedup, _alpm_strtrim(line), 
goto error);
-                                       info->files = 
alpm_list_add(info->files, linedup);
-                               }
-                       } else if(strcmp(line, "%BACKUP%") == 0) {
-                               while(fgets(line, 512, fp) && 
strlen(_alpm_strtrim(line))) {
-                                       char *linedup;
-                                       STRDUP(linedup, _alpm_strtrim(line), 
goto error);
-                                       info->backup = 
alpm_list_add(info->backup, linedup);
-                               }
-                       }
+               if(_alpm_parse_files(&_alpm_parse_from_file, fp, info) != 0) {
+                       goto error;
                }
                fclose(fp);
                fp = NULL;
@@ -607,33 +479,8 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t 
inforeq)
                        _alpm_log(PM_LOG_ERROR, _("could not open file %s: 
%s\n"), path, strerror(errno));
                        goto error;
                }
-               while(!feof(fp)) {
-                       fgets(line, 255, fp);
-                       _alpm_strtrim(line);
-                       if(strcmp(line, "%DEPENDS%") == 0) {
-                               while(fgets(line, 512, fp) && 
strlen(_alpm_strtrim(line))) {
-                                       pmdepend_t *dep = 
_alpm_splitdep(_alpm_strtrim(line));
-                                       info->depends = 
alpm_list_add(info->depends, dep);
-                               }
-                       } else if(strcmp(line, "%OPTDEPENDS%") == 0) {
-                               while(fgets(line, 512, fp) && 
strlen(_alpm_strtrim(line))) {
-                                       char *linedup;
-                                       STRDUP(linedup, _alpm_strtrim(line), 
goto error);
-                                       info->optdepends = 
alpm_list_add(info->optdepends, linedup);
-                               }
-                       } else if(strcmp(line, "%CONFLICTS%") == 0) {
-                               while(fgets(line, 512, fp) && 
strlen(_alpm_strtrim(line))) {
-                                       char *linedup;
-                                       STRDUP(linedup, _alpm_strtrim(line), 
goto error);
-                                       info->conflicts = 
alpm_list_add(info->conflicts, linedup);
-                               }
-                       } else if(strcmp(line, "%PROVIDES%") == 0) {
-                               while(fgets(line, 512, fp) && 
strlen(_alpm_strtrim(line))) {
-                                       char *linedup;
-                                       STRDUP(linedup, _alpm_strtrim(line), 
goto error);
-                                       info->provides = 
alpm_list_add(info->provides, linedup);
-                               }
-                       }
+               if(_alpm_parse_depends(&_alpm_parse_from_file, fp, info) != 0) {
+                       goto error;
                }
                fclose(fp);
                fp = NULL;
@@ -643,17 +490,8 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t 
inforeq)
        if(inforeq & INFRQ_DELTAS) {
                snprintf(path, PATH_MAX, "%sdeltas", pkgpath);
                if((fp = fopen(path, "r"))) {
-                       while(!feof(fp)) {
-                               fgets(line, 255, fp);
-                               _alpm_strtrim(line);
-                               if(strcmp(line, "%DELTAS%") == 0) {
-                                       while(fgets(line, 512, fp) && 
strlen(_alpm_strtrim(line))) {
-                                               pmdelta_t *delta = 
_alpm_delta_parse(line);
-                                               if(delta) {
-                                                       info->deltas = 
alpm_list_add(info->deltas, delta);
-                                               }
-                                       }
-                               }
+                       if(_alpm_parse_deltas(&_alpm_parse_from_file, fp, info) 
!= 0) {
+                               goto error;
                        }
                        fclose(fp);
                        fp = NULL;
@@ -675,6 +513,8 @@ int _alpm_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t 
inforeq)
        return(0);
 
 error:
+       free(pkgname);
+       free(pkgver);
        free(pkgpath);
        if(fp) {
                fclose(fp);
diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c
index 523968e..5202e4b 100644
--- a/lib/libalpm/delta.c
+++ b/lib/libalpm/delta.c
@@ -25,7 +25,6 @@
 #include <stdint.h> /* intmax_t */
 #include <limits.h>
 #include <sys/types.h>
-#include <regex.h>
 
 /* libalpm */
 #include "delta.h"
@@ -247,61 +246,6 @@ off_t _alpm_shortest_delta_path(alpm_list_t *deltas,
        return(bestsize);
 }
 
-/** Parses the string representation of a pmdelta_t object.
- * This function assumes that the string is in the correct format.
- * This format is as follows:
- * $deltafile $deltamd5 $deltasize $oldfile $newfile
- * @param line the string to parse
- * @return A pointer to the new pmdelta_t object
- */
-/* TODO this does not really belong here, but in a parsing lib */
-pmdelta_t *_alpm_delta_parse(char *line)
-{
-       pmdelta_t *delta;
-       char *tmp = line, *tmp2;
-       regex_t reg;
-
-       regcomp(&reg,
-                       "^[^[:space:]]* [[:xdigit:]]{32} [[:digit:]]*"
-                       " [^[:space:]]* [^[:space:]]*$",
-                       REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
-       if(regexec(&reg, line, 0, 0, 0) != 0) {
-               /* delta line is invalid, return NULL */
-               regfree(&reg);
-               return(NULL);
-       }
-       regfree(&reg);
-
-       CALLOC(delta, 1, sizeof(pmdelta_t), RET_ERR(PM_ERR_MEMORY, NULL));
-
-       tmp2 = tmp;
-       tmp = strchr(tmp, ' ');
-       *(tmp++) = '\0';
-       STRDUP(delta->delta, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
-
-       tmp2 = tmp;
-       tmp = strchr(tmp, ' ');
-       *(tmp++) = '\0';
-       STRDUP(delta->delta_md5, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
-
-       tmp2 = tmp;
-       tmp = strchr(tmp, ' ');
-       *(tmp++) = '\0';
-       delta->delta_size = atol(tmp2);
-
-       tmp2 = tmp;
-       tmp = strchr(tmp, ' ');
-       *(tmp++) = '\0';
-       STRDUP(delta->from, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
-
-       tmp2 = tmp;
-       STRDUP(delta->to, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
-
-       _alpm_log(PM_LOG_DEBUG, "delta : %s %s '%lld'\n", delta->from, 
delta->to, (long long)delta->delta_size);
-
-       return(delta);
-}
-
 void _alpm_delta_free(pmdelta_t *delta)
 {
        FREE(delta->from);
diff --git a/lib/libalpm/delta.h b/lib/libalpm/delta.h
index 4f426cb..3c4e4cf 100644
--- a/lib/libalpm/delta.h
+++ b/lib/libalpm/delta.h
@@ -39,7 +39,6 @@ struct __pmdelta_t {
        off_t download_size;
 };
 
-pmdelta_t *_alpm_delta_parse(char *line);
 void _alpm_delta_free(pmdelta_t *delta);
 off_t _alpm_shortest_delta_path(alpm_list_t *deltas,
                const char *to, alpm_list_t **path);
diff --git a/lib/libalpm/parse.c b/lib/libalpm/parse.c
new file mode 100644
index 0000000..31038fc
--- /dev/null
+++ b/lib/libalpm/parse.c
@@ -0,0 +1,305 @@
+/*
+ *  parse.c
+ *
+ *  Copyright (c) 2006-2009 Pacman Development Team <[email protected]>
+ *  Copyright (c) 2002-2006 by Judd Vinet <[email protected]>
+ *
+ *  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, see <http://www.gnu.org/licenses/>.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <locale.h> /* setlocale */
+#include <regex.h>
+#include <time.h>
+
+/* libalpm */
+#include "parse.h"
+#include "util.h"
+#include "alpm_list.h"
+#include "log.h"
+#include "package.h"
+#include "delta.h"
+#include "deps.h"
+
+enum {
+       PARSE_FINISHED   = 0,
+       PARSE_UNFINISHED = 1,
+       PARSE_ERROR      = 2
+};
+
+typedef struct parser {
+       char *keyword;
+       int (*func)(char*, void*);
+       void *saveto;
+} parser_t;
+
+/** Parses the string representation of a pmdelta_t object.
+ * This function assumes that the string is in the correct format.
+ * This format is as follows:
+ * $deltafile $deltamd5 $deltasize $oldfile $newfile
+ * @param line the string to parse
+ * @return A pointer to the new pmdelta_t object
+ */
+static pmdelta_t *delta_parse(char *line)
+{
+       pmdelta_t *delta;
+       char *tmp = line, *tmp2;
+       regex_t reg;
+
+       regcomp(&reg,
+                       "^[^[:space:]]* [[:xdigit:]]{32} [[:digit:]]*"
+                       " [^[:space:]]* [^[:space:]]*$",
+                       REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
+       if(regexec(&reg, line, 0, 0, 0) != 0) {
+               /* delta line is invalid, return NULL */
+               regfree(&reg);
+               return(NULL);
+       }
+       regfree(&reg);
+
+       CALLOC(delta, 1, sizeof(pmdelta_t), RET_ERR(PM_ERR_MEMORY, NULL));
+
+       tmp2 = tmp;
+       tmp = strchr(tmp, ' ');
+       *(tmp++) = '\0';
+       STRDUP(delta->delta, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
+
+       tmp2 = tmp;
+       tmp = strchr(tmp, ' ');
+       *(tmp++) = '\0';
+       STRDUP(delta->delta_md5, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
+
+       tmp2 = tmp;
+       tmp = strchr(tmp, ' ');
+       *(tmp++) = '\0';
+       delta->delta_size = atol(tmp2);
+
+       tmp2 = tmp;
+       tmp = strchr(tmp, ' ');
+       *(tmp++) = '\0';
+       STRDUP(delta->from, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
+
+       tmp2 = tmp;
+       STRDUP(delta->to, tmp2, RET_ERR(PM_ERR_MEMORY, NULL));
+
+       _alpm_log(PM_LOG_DEBUG, "delta : %s %s '%lld'\n", delta->from, 
delta->to, (long long)delta->delta_size);
+
+       return(delta);
+}
+
+/** Parse line based data, as found in desc, depends, files and deltas files
+ * The data is expected to be in the following format:
+ * keyword
+ * [entry]
+ * [entry]
+ * ...
+ * <newline>
+ * [keyword]
+ * ...
+ *
+ * The handling of the data for each keyword is described by the matching
+ * struct of type parser_t. This struct holds a function pointer and a void
+ * pointer for each keyword. The function is called for the lines following a
+ * keyword until it returns PARSE_FINISHED. It is expected to handle the actual
+ * parsing and store the data at the passed void pointer.
+ * @param parsers describes how to parse data for each keyword
+ * @param nparsers size of parsers
+ * @param ugets pointer to an fgets like function, which gets called to get
+ * the next line
+ * @param from describes from where to read the next line, this is passed to
+ * ugets
+ */
+static int parse_lines(parser_t parsers[], int nparsers, ugets_t ugets,
+               void *from)
+{
+       int i, ret;
+       char line[513];
+       parser_t *p = NULL;
+
+       while((*ugets)(line, sizeof(line) - 1, from) != NULL) {
+               _alpm_strtrim(line);
+               if(p == NULL && strlen(line) == 0) {
+                       continue;
+               }
+               if(p == NULL) {
+                       for(i = 0; i < nparsers; i++) {
+                               if(strcmp(line,parsers[i].keyword) == 0) {
+                                       p = &parsers[i];
+                               }
+                       }
+               }
+               else {
+                       ret = (*(p->func))(line, p->saveto);
+                       if(ret == PARSE_FINISHED) {
+                               p = NULL;
+                       }
+                       else if(ret == PARSE_ERROR) {
+                               return(ret);
+                       }
+               }
+       }
+       return(0);
+}
+
+static int copy_line(char *line, void *target) {
+       STRDUP(*(char**)target, line, return(PARSE_ERROR));
+       return(PARSE_FINISHED);
+}
+
+static int parse_off_t(char *line, void *target) {
+       *(off_t*)target = (off_t)atol(line);
+       return(PARSE_FINISHED);
+}
+
+static int parse_reason(char *line, void *target) {
+       *(pmpkgreason_t*)target = (pmpkgreason_t)atol(line);
+       return(PARSE_FINISHED);
+}
+
+static int parse_date(char *line, void *target) {
+       char first = tolower(line[0]);
+       if(first > 'a' && first < 'z') {
+               struct tm tmp_tm = {0}; /* initialize to null in case of 
failure */
+               setlocale(LC_TIME, "C");
+               strptime(line, "%a %b %e %H:%M:%S %Y", &tmp_tm);
+               *(time_t*)target = mktime(&tmp_tm);
+               setlocale(LC_TIME, "");
+       } else {
+               *(time_t*)target = atol(line);
+       }
+       return(PARSE_FINISHED);
+}
+
+static int set_flag(char *line, void *target) {
+       *(unsigned short*)target = 1;
+       return(PARSE_FINISHED);
+}
+
+static int copy_to_list(char *line, void *list) {
+       if(strlen(line) == 0) {
+               return(PARSE_FINISHED);
+       }
+       char *linedup;
+       STRDUP(linedup, line, RET_ERR(PM_ERR_MEMORY, PARSE_ERROR));
+       *(alpm_list_t**)list = alpm_list_add(*(alpm_list_t**)list, linedup);
+       return(PARSE_UNFINISHED);
+}
+
+static int deltas_to_list(char *line, void *list) {
+       if(strlen(line) == 0) {
+               return(PARSE_FINISHED);
+       }
+       pmdelta_t *delta = delta_parse(line);
+       if(delta != NULL) {
+               *(alpm_list_t**)list = alpm_list_add(*(alpm_list_t**)list, 
delta);
+       }
+       return(PARSE_UNFINISHED);
+}
+
+static int deps_to_list(char *line, void *list) {
+       if(strlen(line) == 0) {
+               return(PARSE_FINISHED);
+       }
+       pmdepend_t *dep = _alpm_splitdep(line);
+       *(alpm_list_t**)list = alpm_list_add(*(alpm_list_t**)list, dep);
+       return(PARSE_UNFINISHED);
+}
+
+char *_alpm_parse_from_file(char *buf,int size, void* fp)
+{
+       return(fgets(buf, size, (FILE*)fp));
+}
+
+char *_alpm_parse_from_archive(char *buf,int size, void* a)
+{
+       return(_alpm_archive_fgets(buf, size, (struct archive*)a));
+}
+
+
+int _alpm_parse_desc(ugets_t ugets, void *from,        pmpkg_t *pkg)
+{
+       ALPM_LOG_FUNC;
+
+       parser_t parsers[] = {
+               {"%NAME%", &copy_line, &pkg->name},
+               {"%VERSION%", &copy_line, &pkg->version},
+               {"%FILENAME%", &copy_line, &pkg->filename},
+               {"%DESC%", &copy_line, &pkg->desc},
+               {"%GROUPS%", &copy_to_list, &pkg->groups},
+               {"%URL%", &copy_line, &pkg->url},
+               {"%LICENSE%", &copy_to_list, &pkg->licenses},
+               {"%ARCH%", &copy_line, &pkg->arch},
+               {"%BUILDDATE%", &parse_date, &pkg->builddate},
+               {"%INSTALLDATE%", &parse_date, &pkg->installdate},
+               {"%PACKAGER%", &copy_line, &pkg->packager},
+               {"%REASON%", &parse_reason, &pkg->reason},
+               {"%SIZE%", &parse_off_t, &pkg->size},
+               {"%CSIZE%", &parse_off_t, &pkg->size},
+               {"%ISIZE%", &parse_off_t, &pkg->isize},
+               {"%MD5SUM%", &copy_line, &pkg->md5sum},
+               {"%REPLACES%", &copy_to_list, &pkg->replaces},
+               {"%FORCE%", &set_flag, &pkg->force}
+       };
+       int nparsers = sizeof(parsers) / sizeof(parser_t);
+
+       return(parse_lines(parsers, nparsers, ugets, from));
+}
+
+int _alpm_parse_files(ugets_t ugets, void* from,
+               pmpkg_t *pkg)
+{
+       ALPM_LOG_FUNC;
+
+       parser_t parsers[] = {
+               {"%FILES%", &copy_to_list, &pkg->files},
+               {"%BACKUP%", &copy_to_list, &pkg->backup}
+       };
+       int nparsers = sizeof(parsers) / sizeof(parser_t);
+
+       return(parse_lines(parsers, nparsers, ugets, from));
+}
+
+int _alpm_parse_depends(char* (*ugets)(char*, int, void*), void *from,
+               pmpkg_t *pkg)
+{
+       ALPM_LOG_FUNC;
+
+       parser_t parsers[] = {
+               {"%DEPENDS%", &deps_to_list, &pkg->depends},
+               {"%OPTDEPENDS%", &copy_to_list, &pkg->optdepends},
+               {"%CONFLICTS%", &copy_to_list, &pkg->conflicts},
+               {"%PROVIDES%", &copy_to_list, &pkg->provides}
+       };
+       int nparsers = sizeof(parsers) / sizeof(parser_t);
+
+       return(parse_lines(parsers, nparsers, ugets, from));
+}
+
+int _alpm_parse_deltas(ugets_t ugets, void *from,      pmpkg_t *pkg)
+{
+       ALPM_LOG_FUNC;
+
+       parser_t parsers[] = {
+               {"%DELTAS%", &deltas_to_list, &pkg->deltas}
+       };
+       int nparsers = sizeof(parsers) / sizeof(parser_t);
+
+       return(parse_lines(parsers, nparsers, ugets, from));
+}
+
+/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/parse.h b/lib/libalpm/parse.h
new file mode 100644
index 0000000..d3ef77e
--- /dev/null
+++ b/lib/libalpm/parse.h
@@ -0,0 +1,40 @@
+/*
+ *  parse.h
+ *
+ *  Copyright (c) 2006-2009 Pacman Development Team <[email protected]>
+ *  Copyright (c) 2002-2006 by Judd Vinet <[email protected]>
+ *
+ *  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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _ALPM_PARSE_H
+#define _ALPM_PARSE_H
+
+#include "package.h"
+
+/* An fgets like function, argument for the parse functions */
+typedef char *(*ugets_t)(char*, int, void*);
+
+/* arguments for the parse functions (ugets_t) */
+char *_alpm_parse_from_file(char*, int, void*);
+char *_alpm_parse_from_archive(char*, int, void*);
+
+/* parse functions */
+int _alpm_parse_desc(ugets_t, void*, pmpkg_t*);
+int _alpm_parse_files(ugets_t, void*, pmpkg_t*);
+int _alpm_parse_depends(ugets_t, void*, pmpkg_t*);
+int _alpm_parse_deltas(ugets_t, void*, pmpkg_t*);
+
+#endif /* _ALPM_PARSE_H */
+
+/* vim: set ts=2 sw=2 noet: */
-- 
1.6.4.4


Reply via email to