The following commit has been merged in the master branch:
commit 645a9e329f874a470ae837d93525c769a0df4ec8
Author: Guillem Jover <[email protected]>
Date:   Thu Jul 2 11:24:08 2009 +0200

    libdpkg: Refactor parsedb_state into a new structure
    
    Move state variables into a new struct and pass that instead of each of
    them to the error, warning and field parsing functions. This is cleaner,
    and should be “marginally” faster.

diff --git a/TODO b/TODO
index 77760d3..be9a8e0 100644
--- a/TODO
+++ b/TODO
@@ -37,7 +37,6 @@ squeeze + 1
    - Coalesce admindir / infodir / foodir generation.
    - Get rid of setjmp (at least in the general case, keep for dpkg itself?)
    - Coalesce hash and checksum functions.
-   - Move parseerr arguments into a struct (need to push the patch).
    - Split modstatdb_rw into mode and flags.
    - Move fd and block function out of mlib.
    - Cleanup status chars -> strings hardcoded mappings all over the place.
diff --git a/lib/fields.c b/lib/fields.c
index 3d1331d..8840710 100644
--- a/lib/fields.c
+++ b/lib/fields.c
@@ -34,7 +34,7 @@
 #include "parsedump.h"
 
 static int
-convert_string(const char *filename, int lno, const char *what, int otherwise,
+convert_string(struct parsedb_state *ps, const char *what, int otherwise,
                const struct pkginfo *pigp,
                const char *startp, const struct namevalue *ivip,
                const char **endpp)
@@ -43,7 +43,7 @@ convert_string(const char *filename, int lno, const char 
*what, int otherwise,
   const struct namevalue *nvip = ivip;
 
   if (!*startp)
-    parse_error(filename, lno, pigp, _("%s is missing"), what);
+    parse_error(ps, pigp, _("%s is missing"), what);
   while (nvip->name) {
     if (strncasecmp(nvip->name, startp, nvip->length))
       nvip++;
@@ -52,7 +52,7 @@ convert_string(const char *filename, int lno, const char 
*what, int otherwise,
   }
   if (!nvip->name) {
     if (otherwise != -1) return otherwise;
-    parse_error(filename, lno, pigp, _("`%.*s' is not allowed for %s"),
+    parse_error(ps, pigp, _("`%.*s' is not allowed for %s"),
                 strnlen(startp, 50), startp, what);
   }
 
@@ -60,17 +60,19 @@ convert_string(const char *filename, int lno, const char 
*what, int otherwise,
   while (isspace(*ep))
     ep++;
   if (*ep && !endpp)
-    parse_error(filename, lno, pigp, _("junk after %s"), what);
+    parse_error(ps, pigp, _("junk after %s"), what);
   if (endpp) *endpp= ep;
   return nvip->value;
 }
 
-void f_name(struct pkginfo *pigp, struct pkginfoperfile *pifp, enum 
parsedbflags flags,
-            const char *filename, int lno, FILE *warnto, int *warncount,
-            const char *value, const struct fieldinfo *fip) {
+void
+f_name(struct pkginfo *pigp, struct pkginfoperfile *pifp,
+       struct parsedb_state *ps,
+       const char *value, const struct fieldinfo *fip)
+{
   const char *e;
   if ((e= illegal_packagename(value,NULL)) != NULL)
-    parse_error(filename, lno, pigp, _("invalid package name (%.250s)"), e);
+    parse_error(ps, pigp, _("invalid package name (%.250s)"), e);
   pigp->name= findpackage(value)->name;
   /* We use the new name, as findpackage() may have
      done a tolower for us.
@@ -78,17 +80,16 @@ void f_name(struct pkginfo *pigp, struct pkginfoperfile 
*pifp, enum parsedbflags
 }
 
 void f_filecharf(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-                 enum parsedbflags flags,
-                 const char *filename, int lno, FILE *warnto, int *warncount,
+                 struct parsedb_state *ps,
                  const char *value, const struct fieldinfo *fip) {
   struct filedetails *fdp, **fdpp;
   char *cpos, *space;
   int allowextend;
 
   if (!*value)
-    parse_error(filename, lno, pigp, _("empty file details field `%s'"), 
fip->name);
-  if (!(flags & pdb_recordavailable))
-    parse_error(filename, lno, pigp,
+    parse_error(ps, pigp, _("empty file details field `%s'"), fip->name);
+  if (!(ps->flags & pdb_recordavailable))
+    parse_error(ps, pigp,
                 _("file details field `%s' not allowed in status file"),
                fip->name);
   allowextend= !pigp->files;
@@ -101,7 +102,7 @@ void f_filecharf(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
     fdp= *fdpp;
     if (!fdp) {
       if (!allowextend)
-        parse_error(filename, lno, pigp,
+        parse_error(ps, pigp,
                     _("too many values in file details field `%s' "
                       "(compared to others)"), fip->name);
       fdp= nfmalloc(sizeof(struct filedetails));
@@ -115,94 +116,86 @@ void f_filecharf(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
     cpos= space;
   }
   if (*fdpp)
-    parse_error(filename, lno, pigp,
+    parse_error(ps, pigp,
                 _("too few values in file details field `%s' "
                   "(compared to others)"), fip->name);
 }
 
 void f_charfield(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-                 enum parsedbflags flags,
-                 const char *filename, int lno, FILE *warnto, int *warncount,
+                 struct parsedb_state *ps,
                  const char *value, const struct fieldinfo *fip) {
   if (*value) PKGPFIELD(pifp,fip->integer,char*)= nfstrsave(value);
 }
 
 void f_boolean(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-               enum parsedbflags flags,
-               const char *filename, int lno, FILE *warnto, int *warncount,
+               struct parsedb_state *ps,
                const char *value, const struct fieldinfo *fip) {
   int boolean;
 
   if (!*value)
     return;
 
-  boolean = convert_string(filename, lno, _("yes/no in boolean field"),
+  boolean = convert_string(ps, _("yes/no in boolean field"),
                            -1, pigp, value, booleaninfos, NULL);
   PKGPFIELD(pifp, fip->integer, int) = boolean;
 }
 
 void f_section(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-               enum parsedbflags flags,
-               const char *filename, int lno, FILE *warnto, int *warncount,
+               struct parsedb_state *ps,
                const char *value, const struct fieldinfo *fip) {
   if (!*value) return;
   pigp->section= nfstrsave(value);
 }
 
 void f_priority(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-                enum parsedbflags flags,
-                const char *filename, int lno, FILE *warnto, int *warncount,
+                struct parsedb_state *ps,
                 const char *value, const struct fieldinfo *fip) {
   if (!*value) return;
-  pigp->priority = convert_string(filename, lno, _("word in `priority' field"),
+  pigp->priority = convert_string(ps, _("word in `priority' field"),
                                   pri_other, pigp, value, priorityinfos, NULL);
   if (pigp->priority == pri_other) pigp->otherpriority= nfstrsave(value);
 }
 
 void f_status(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-              enum parsedbflags flags,
-              const char *filename, int lno, FILE *warnto, int *warncount,
+              struct parsedb_state *ps,
               const char *value, const struct fieldinfo *fip) {
   const char *ep;
 
-  if (flags & pdb_rejectstatus)
-    parse_error(filename, lno, pigp,
+  if (ps->flags & pdb_rejectstatus)
+    parse_error(ps, pigp,
                 _("value for `status' field not allowed in this context"));
-  if (flags & pdb_recordavailable) return;
+  if (ps->flags & pdb_recordavailable)
+    return;
   
-  pigp->want = convert_string(filename, lno,
-                            _("first (want) word in `status' field"), -1,
-                              pigp, value, wantinfos, &ep);
-  pigp->eflag = convert_string(filename, lno,
-                             _("second (error) word in `status' field"), -1,
-                               pigp, ep, eflaginfos, &ep);
+  pigp->want = convert_string(ps, _("first (want) word in `status' field"),
+                              -1, pigp, value, wantinfos, &ep);
+  pigp->eflag = convert_string(ps, _("second (error) word in `status' field"),
+                               -1, pigp, ep, eflaginfos, &ep);
   if (pigp->eflag & eflagf_obsoletehold) {
     pigp->want= want_hold;
     pigp->eflag &= ~eflagf_obsoletehold;
   }
-  pigp->status= convert_string(filename,lno,_("third (status) word in `status' 
field"), -1,
-                               pigp, ep, statusinfos, NULL);
+  pigp->status = convert_string(ps, _("third (status) word in `status' field"),
+                                -1, pigp, ep, statusinfos, NULL);
 }
 
 void f_version(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-               enum parsedbflags flags,
-               const char *filename, int lno, FILE *warnto, int *warncount,
+               struct parsedb_state *ps,
                const char *value, const struct fieldinfo *fip) {
   const char *emsg;
   
   emsg= parseversion(&pifp->version,value);
   if (emsg)
-    parse_error(filename, lno, pigp,
+    parse_error(ps, pigp,
                 _("error in Version string `%.250s': %.250s"), value, emsg);
 }  
 
 void f_revision(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-                enum parsedbflags flags,
-                const char *filename, int lno, FILE *warnto, int *warncount,
+                struct parsedb_state *ps,
                 const char *value, const struct fieldinfo *fip) {
   char *newversion;
 
-  parse_warn(filename, lno, warnto, warncount, pigp,
+  parse_warn(ps, pigp,
              _("obsolete `Revision' or `Package-Revision' field used"));
   if (!*value) return;
   if (pifp->version.revision && *pifp->version.revision) {
@@ -214,19 +207,19 @@ void f_revision(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
 }  
 
 void f_configversion(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-                     enum parsedbflags flags,
-                     const char *filename, int lno, FILE *warnto, int 
*warncount,
+                     struct parsedb_state *ps,
                      const char *value, const struct fieldinfo *fip) {
   const char *emsg;
   
-  if (flags & pdb_rejectstatus)
-    parse_error(filename, lno, pigp,
+  if (ps->flags & pdb_rejectstatus)
+    parse_error(ps, pigp,
                 _("value for `config-version' field not allowed in this 
context"));
-  if (flags & pdb_recordavailable) return;
+  if (ps->flags & pdb_recordavailable)
+    return;
 
   emsg= parseversion(&pigp->configversion,value);
   if (emsg)
-    parse_error(filename, lno, pigp,
+    parse_error(ps, pigp,
                 _("error in Config-Version string `%.250s': %.250s"),
                 value, emsg);
 }
@@ -235,7 +228,7 @@ static void conffvalue_lastword(const char *value, const 
char *from,
                                 const char *endent,
                                 const char **word_start_r, int *word_len_r,
                                 const char **new_from_r,
-                                const char *filename, int lno,
+                                struct parsedb_state *ps,
                                 struct pkginfo *pigp)
 {
   /* the code in f_conffiles ensures that value[-1]==' ', which is helpful */
@@ -251,14 +244,13 @@ static void conffvalue_lastword(const char *value, const 
char *from,
   return;
 
 malformed:
-  parse_error(filename, lno, pigp,
+  parse_error(ps, pigp,
               _("value for `conffiles' has malformatted line `%.*s'"),
               (int)min(endent - value, 250), value);
 }
 
 void f_conffiles(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-                 enum parsedbflags flags,
-                 const char *filename, int lno, FILE *warnto, int *warncount,
+                 struct parsedb_state *ps,
                  const char *value, const struct fieldinfo *fip) {
   static const char obsolete_str[]= "obsolete";
   struct conffile **lastp, *newlink;
@@ -271,24 +263,24 @@ void f_conffiles(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
     c= *value++;
     if (c == '\n') continue;
     if (c != ' ')
-      parse_error(filename, lno, pigp,
+      parse_error(ps, pigp,
                   _("value for `conffiles' has line starting with non-space 
`%c'"),
                   c);
     for (endent = value; (c = *endent) != '\0' && c != '\n'; endent++) ;
     conffvalue_lastword(value, endent, endent,
                        &hashstart, &hashlen, &endfn,
-                        filename, lno, pigp);
+                        ps, pigp);
     obsolete= (hashlen == sizeof(obsolete_str)-1 &&
               !memcmp(hashstart, obsolete_str, hashlen));
     if (obsolete)
       conffvalue_lastword(value, endfn, endent,
                          &hashstart, &hashlen, &endfn,
-                          filename, lno, pigp);
+                         ps, pigp);
     newlink= nfmalloc(sizeof(struct conffile));
     value = path_skip_slash_dotslash(value);
     namelen= (int)(endfn-value);
     if (namelen <= 0)
-      parse_error(filename, lno, pigp,
+      parse_error(ps, pigp,
                   _("root or null directory is listed as a conffile"));
     newptr = nfmalloc(namelen+2);
     newptr[0]= '/';
@@ -308,8 +300,7 @@ void f_conffiles(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
 }
 
 void f_dependency(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-                  enum parsedbflags flags,
-                  const char *filename, int lno, FILE *warnto, int *warncount,
+                  struct parsedb_state *ps,
                   const char *value, const struct fieldinfo *fip) {
   char c1, c2;
   const char *p, *emsg;
@@ -346,12 +337,12 @@ void f_dependency(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
       strncpy(depname, depnamestart, depnamelength);
       *(depname + depnamelength) = '\0';
       if (!*depname)
-        parse_error(filename, lno, pigp,
+        parse_error(ps, pigp,
                     _("`%s' field, missing package name, or garbage where "
                       "package name expected"), fip->name);
       emsg= illegal_packagename(depname,NULL);
       if (emsg)
-        parse_error(filename, lno, pigp,
+        parse_error(ps, pigp,
                     _("`%s' field, invalid package name `%.255s': %s"),
                     fip->name, depname, emsg);
       dop= nfmalloc(sizeof(struct deppossi));
@@ -381,13 +372,13 @@ void f_dependency(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
             dop->verrel |= (dvrf_strict | dvrf_builtup);
             p++;
           } else if (c2 == '<' || c2 == '>') {
-            parse_error(filename, lno, pigp,
+            parse_error(ps, pigp,
                         _("`%s' field, reference to `%.255s':\n"
                           " bad version relationship %c%c"),
                         fip->name, depname, c1, c2);
             dop->verrel= dvr_none;
           } else {
-            parse_warn(filename, lno, warnto, warncount, pigp,
+            parse_warn(ps, pigp,
                        _("`%s' field, reference to `%.255s':\n"
                          " `%c' is obsolete, use `%c=' or `%c%c' instead"),
                        fip->name, depname, c1, c1, c1, c1);
@@ -397,7 +388,7 @@ void f_dependency(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
           dop->verrel= dvr_exact;
           p++;
         } else {
-          parse_warn(filename, lno, warnto, warncount, pigp,
+          parse_warn(ps, pigp,
                      _("`%s' field, reference to `%.255s':\n"
                        " implicit exact match on version number, "
                        "suggest using `=' instead"),
@@ -405,11 +396,11 @@ void f_dependency(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
           dop->verrel= dvr_exact;
         }
        if ((dop->verrel!=dvr_exact) && (fip->integer==dep_provides))
-          parse_warn(filename, lno, warnto, warncount, pigp,
+          parse_warn(ps, pigp,
                      _("Only exact versions may be used for Provides"));
 
         if (!isspace(*p) && !isalnum(*p)) {
-          parse_warn(filename, lno, warnto, warncount, pigp,
+          parse_warn(ps, pigp,
                      _("`%s' field, reference to `%.255s':\n"
                        " version value starts with non-alphanumeric, "
                        "suggest adding a space"),
@@ -426,15 +417,15 @@ void f_dependency(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
        versionlength= p - versionstart;
         while (isspace(*p)) p++;
         if (*p == '(')
-          parse_error(filename, lno, pigp,
+          parse_error(ps, pigp,
                       _("`%s' field, reference to `%.255s': "
                         "version contains `%c'"), fip->name,depname, ')');
         else if (*p != ')')
-          parse_error(filename, lno, pigp,
+          parse_error(ps, pigp,
                       _("`%s' field, reference to `%.255s': "
                         "version contains `%c'"), fip->name,depname, ' ');
         else if (*p == '\0')
-          parse_error(filename, lno, pigp,
+          parse_error(ps, pigp,
                       _("`%s' field, reference to `%.255s': "
                         "version unterminated"), fip->name, depname);
        if (versionlength >=  versionused) {
@@ -445,7 +436,7 @@ void f_dependency(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
         *(version + versionlength) = '\0';
         emsg= parseversion(&dop->version,version);
         if (emsg)
-          parse_error(filename, lno, pigp,
+          parse_error(ps, pigp,
                       _("`%s' field, reference to `%.255s': "
                         "error in version: %.255s"), fip->name, depname, emsg);
         p++; while (isspace(*p)) p++;
@@ -455,14 +446,14 @@ void f_dependency(struct pkginfo *pigp, struct 
pkginfoperfile *pifp,
       }
       if (!*p || *p == ',') break;
       if (*p != '|')
-        parse_error(filename, lno, pigp,
+        parse_error(ps, pigp,
                     _("`%s' field, syntax error after reference to package 
`%.255s'"),
                     fip->name, dop->ed->name);
       if (fip->integer == dep_conflicts ||
           fip->integer == dep_breaks ||
           fip->integer == dep_provides ||
           fip->integer == dep_replaces)
-        parse_error(filename, lno, pigp,
+        parse_error(ps, pigp,
                     _("alternatives (`|') not allowed in %s field"), 
fip->name);
       p++; while (isspace(*p)) p++;
     }
@@ -515,53 +506,51 @@ scan_word(const char **valp)
 
 void
 f_trigpend(struct pkginfo *pend, struct pkginfoperfile *pifp,
-           enum parsedbflags flags,
-           const char *filename, int lno, FILE *warnto, int *warncount,
+           struct parsedb_state *ps,
            const char *value, const struct fieldinfo *fip)
 {
   const char *word, *emsg;
 
-  if (flags & pdb_rejectstatus)
-    parse_error(filename, lno, pend,
+  if (ps->flags & pdb_rejectstatus)
+    parse_error(ps, pend,
                 _("value for `triggers-pending' field not allowed in "
                   "this context"));
 
   while ((word = scan_word(&value))) {
     emsg = illegal_triggername(word);
     if (emsg)
-      parse_error(filename, lno, pend,
+      parse_error(ps, pend,
                   _("illegal pending trigger name `%.255s': %s"), word, emsg);
 
     if (!trig_note_pend_core(pend, nfstrsave(word)))
-      parse_error(filename, lno, pend,
+      parse_error(ps, pend,
                   _("duplicate pending trigger `%.255s'"), word);
   }
 }
 
 void
 f_trigaw(struct pkginfo *aw, struct pkginfoperfile *pifp,
-         enum parsedbflags flags,
-         const char *filename, int lno, FILE *warnto, int *warncount,
+         struct parsedb_state *ps,
          const char *value, const struct fieldinfo *fip)
 {
   const char *word, *emsg;
   struct pkginfo *pend;
 
-  if (flags & pdb_rejectstatus)
-    parse_error(filename, lno, aw,
+  if (ps->flags & pdb_rejectstatus)
+    parse_error(ps, aw,
                 _("value for `triggers-awaited' field not allowed in "
                   "this context"));
 
   while ((word = scan_word(&value))) {
     emsg = illegal_packagename(word, NULL);
     if (emsg)
-      parse_error(filename, lno, aw,
+      parse_error(ps, aw,
                   _("illegal package name in awaited trigger `%.255s': %s"),
                   word, emsg);
     pend = findpackage(word);
 
     if (!trig_note_aw(pend, aw))
-      parse_error(filename, lno, aw,
+      parse_error(ps, aw,
                   _("duplicate awaited trigger package `%.255s'"), word);
 
     trig_enqueue_awaited_pend(pend);
diff --git a/lib/parse.c b/lib/parse.c
index b0b64fe..a61c8c7 100644
--- a/lib/parse.c
+++ b/lib/parse.c
@@ -95,7 +95,6 @@ int parsedb(const char *filename, enum parsedbflags flags,
   struct pkginfoperfile *newpifp, *pifp;
   struct arbitraryfield *arp, **larpp;
   struct trigaw *ta;
-  int lno;
   int pdone;
   int fieldencountered[sizeof_array(fieldinfos)];
   const struct fieldinfo *fip;
@@ -106,8 +105,14 @@ int parsedb(const char *filename, enum parsedbflags flags,
   int fieldlen= 0, valuelen= 0;
   int *ip, c;
   struct stat stat;
+  struct parsedb_state ps;
+
+  ps.filename = filename;
+  ps.flags = flags;
+  ps.lno = 0;
+  ps.warnto = warnto;
+  ps.warncount = 0;
 
-  if (warncount) *warncount= 0;
   newpifp= (flags & pdb_recordavailable) ? &newpig.available : 
&newpig.installed;
   fd= open(filename, O_RDONLY);
   if (fd == -1) ohshite(_("failed to open package info file `%.255s' for 
reading"),filename);
@@ -132,7 +137,6 @@ int parsedb(const char *filename, enum parsedbflags flags,
     data= dataptr= endptr= NULL;
   }
 
-  lno = 0;
   pdone= 0;
 #define EOF_mmap(dataptr, endptr)      (dataptr >= endptr)
 #define getc_mmap(dataptr)             *dataptr++;
@@ -145,7 +149,7 @@ int parsedb(const char *filename, enum parsedbflags flags,
 /* Skip adjacent new lines */
     while(!EOF_mmap(dataptr, endptr)) {
       c= getc_mmap(dataptr); if (c!='\n' && c!=MSDOS_EOF_CHAR ) break;
-      lno++;
+      ps.lno++;
     }
     if (EOF_mmap(dataptr, endptr)) break;
     for (;;) { /* loop per field */
@@ -155,17 +159,17 @@ int parsedb(const char *filename, enum parsedbflags flags,
       fieldlen= dataptr - fieldstart - 1;
       while (!EOF_mmap(dataptr, endptr) && c != '\n' && isspace(c)) c= 
getc_mmap(dataptr);
       if (EOF_mmap(dataptr, endptr))
-        parse_error(filename, lno, &newpig,
+        parse_error(&ps, &newpig,
                     _("EOF after field name `%.*s'"), fieldlen, fieldstart);
       if (c == '\n')
-        parse_error(filename, lno, &newpig,
+        parse_error(&ps, &newpig,
                     _("newline in field name `%.*s'"), fieldlen, fieldstart);
       if (c == MSDOS_EOF_CHAR)
-        parse_error(filename, lno, &newpig,
+        parse_error(&ps, &newpig,
                     _("MSDOS EOF (^Z) in field name `%.*s'"),
                     fieldlen, fieldstart);
       if (c != ':')
-        parse_error(filename, lno, &newpig,
+        parse_error(&ps, &newpig,
                     _("field name `%.*s' must be followed by colon"),
                     fieldlen, fieldstart);
 /* Skip space after ':' but before value and eol */
@@ -174,17 +178,17 @@ int parsedb(const char *filename, enum parsedbflags flags,
         if (c == '\n' || !isspace(c)) break;
       }
       if (EOF_mmap(dataptr, endptr))
-        parse_error(filename, lno, &newpig,
+        parse_error(&ps, &newpig,
                     _("EOF before value of field `%.*s' (missing final 
newline)"),
                  fieldlen,fieldstart);
       if (c == MSDOS_EOF_CHAR)
-        parse_error(filename, lno, &newpig,
+        parse_error(&ps, &newpig,
                     _("MSDOS EOF char in value of field `%.*s' (missing 
newline?)"),
                     fieldlen,fieldstart);
       valuestart= dataptr - 1;
       for (;;) {
         if (c == '\n' || c == MSDOS_EOF_CHAR) {
-          lno++;
+          ps.lno++;
          if (EOF_mmap(dataptr, endptr)) break;
           c= getc_mmap(dataptr);
 /* Found double eol, or start of new field */
@@ -192,7 +196,7 @@ int parsedb(const char *filename, enum parsedbflags flags,
           ungetc_mmap(c,dataptr, data);
           c= '\n';
         } else if (EOF_mmap(dataptr, endptr)) {
-          parse_error(filename, lno, &newpig,
+          parse_error(&ps, &newpig,
                       _("EOF during value of field `%.*s' (missing final 
newline)"),
                       fieldlen,fieldstart);
         }
@@ -217,18 +221,18 @@ int parsedb(const char *filename, enum parsedbflags flags,
        memcpy(value,valuestart,valuelen);
         *(value + valuelen) = '\0';
         if (*ip++)
-          parse_error(filename, lno, &newpig,
+          parse_error(&ps, &newpig,
                       _("duplicate value for `%s' field"), fip->name);
-        
fip->rcall(&newpig,newpifp,flags,filename,lno,warnto,warncount,value,fip);
+        fip->rcall(&newpig, newpifp, &ps, value, fip);
       } else {
         if (fieldlen<2)
-          parse_error(filename, lno, &newpig,
+          parse_error(&ps, &newpig,
                       _("user-defined field name `%.*s' too short"),
                       fieldlen, fieldstart);
         larpp= &newpifp->arbs;
         while ((arp= *larpp) != NULL) {
           if (!strncasecmp(arp->name,fieldstart,fieldlen))
-            parse_error(filename, lno, &newpig,
+            parse_error(&ps, &newpig,
                        _("duplicate value for user-defined field `%.*s'"),
                        fieldlen, fieldstart);
           larpp= &arp->next;
@@ -242,20 +246,20 @@ int parsedb(const char *filename, enum parsedbflags flags,
       if (EOF_mmap(dataptr, endptr) || c == '\n' || c == MSDOS_EOF_CHAR) break;
     } /* loop per field */
     if (pdone && donep)
-      parse_error(filename, lno, &newpig,
+      parse_error(&ps, &newpig,
                   _("several package info entries found, only one allowed"));
-    parse_must_have_field(filename, lno, &newpig, newpig.name, "package name");
+    parse_must_have_field(&ps, &newpig, newpig.name, "package name");
     if ((flags & pdb_recordavailable) || newpig.status != stat_notinstalled) {
-      parse_ensure_have_field(filename, lno, warnto, warncount, &newpig,
+      parse_ensure_have_field(&ps, &newpig,
                               &newpifp->description, "description");
-      parse_ensure_have_field(filename, lno, warnto, warncount, &newpig,
+      parse_ensure_have_field(&ps, &newpig,
                               &newpifp->maintainer, "maintainer");
       if (newpig.status != stat_halfinstalled)
-        parse_must_have_field(filename, lno, &newpig,
+        parse_must_have_field(&ps, &newpig,
                               newpifp->version.version, "version");
     }
     if (flags & pdb_recordavailable)
-      parse_ensure_have_field(filename, lno, warnto, warncount, &newpig,
+      parse_ensure_have_field(&ps, &newpig,
                               &newpifp->architecture, "architecture");
 
     /* Check the Config-Version information:
@@ -267,7 +271,7 @@ int parsedb(const char *filename, enum parsedbflags flags,
     if (!(flags & pdb_recordavailable)) {
       if (newpig.configversion.version) {
         if (newpig.status == stat_installed || newpig.status == 
stat_notinstalled)
-          parse_error(filename, lno, &newpig,
+          parse_error(&ps, &newpig,
                       _("Configured-Version for package with inappropriate 
Status"));
       } else {
         if (newpig.status == stat_installed) newpig.configversion= 
newpifp->version;
@@ -277,22 +281,22 @@ int parsedb(const char *filename, enum parsedbflags flags,
     if (newpig.trigaw.head &&
         (newpig.status <= stat_configfiles ||
          newpig.status >= stat_triggerspending))
-      parse_error(filename, lno, &newpig,
+      parse_error(&ps, &newpig,
                   _("package has status %s but triggers are awaited"),
                   statusinfos[newpig.status].name);
     else if (newpig.status == stat_triggersawaited && !newpig.trigaw.head)
-      parse_error(filename, lno, &newpig,
+      parse_error(&ps, &newpig,
                   _("package has status triggers-awaited but no triggers "
                     "awaited"));
 
     if (!(newpig.status == stat_triggerspending ||
           newpig.status == stat_triggersawaited) &&
         newpig.trigpend_head)
-      parse_error(filename, lno, &newpig,
+      parse_error(&ps, &newpig,
                   _("package has status %s but triggers are pending"),
                   statusinfos[newpig.status].name);
     else if (newpig.status == stat_triggerspending && !newpig.trigpend_head)
-      parse_error(filename, lno, &newpig,
+      parse_error(&ps, &newpig,
                   _("package has status triggers-pending but no triggers "
                     "pending"));
 
@@ -303,7 +307,7 @@ int parsedb(const char *filename, enum parsedbflags flags,
     if (!(flags & pdb_recordavailable) &&
         newpig.status == stat_notinstalled &&
         newpifp->conffiles) {
-      parse_warn(filename, lno, warnto, warncount, &newpig,
+      parse_warn(&ps, &newpig,
                  _("Package which in state not-installed has conffiles, "
                    "forgetting them"));
       newpifp->conffiles= NULL;
@@ -361,7 +365,8 @@ int parsedb(const char *filename, enum parsedbflags flags,
     if (donep) *donep= pigp;
     pdone++;
     if (EOF_mmap(dataptr, endptr)) break;
-    if (c == '\n') lno++;
+    if (c == '\n')
+      ps.lno++;
   }
   if (data != NULL) {
 #ifdef HAVE_MMAP
@@ -375,6 +380,9 @@ int parsedb(const char *filename, enum parsedbflags flags,
   if (close(fd)) ohshite(_("failed to close after read: `%.255s'"),filename);
   if (donep && !pdone) ohshit(_("no package information in 
`%.255s'"),filename);
 
+  if (warncount)
+    *warncount = ps.warncount;
+
   return pdone;
 }
 
diff --git a/lib/parsedump.h b/lib/parsedump.h
index 636a4d2..10d2d97 100644
--- a/lib/parsedump.h
+++ b/lib/parsedump.h
@@ -25,6 +25,14 @@
 
 struct fieldinfo;
 
+struct parsedb_state {
+       enum parsedbflags flags;
+       const char *filename;
+       int lno;
+       FILE *warnto;
+       int warncount;
+};
+
 #define PKGIFPOFF(f) (offsetof(struct pkginfoperfile, f))
 #define PKGPFIELD(pifp,of,type) (*(type*)((char*)(pifp)+(of)))
 
@@ -32,8 +40,7 @@ struct fieldinfo;
 #define FILEFFIELD(filedetail,of,type) (*(type*)((char*)(filedetail)+(of)))
 
 typedef void freadfunction(struct pkginfo *pigp, struct pkginfoperfile *pifp,
-                           enum parsedbflags flags,
-                           const char *filename, int lno, FILE *warnto, int 
*warncount,
+                           struct parsedb_state *ps,
                            const char *value, const struct fieldinfo *fip);
 freadfunction f_name, f_charfield, f_priority, f_section, f_status, 
f_filecharf;
 freadfunction f_boolean, f_dependency, f_conffiles, f_version, f_revision;
@@ -59,16 +66,14 @@ struct fieldinfo {
   size_t integer;
 };
 
-void parse_error(const char *filename, int lno, const struct pkginfo *pigp,
-                 const char *fmt, ...) PRINTFFORMAT(4,5);
-void parse_warn(const char *filename, int lno, FILE *warnto, int *warncount,
-                const struct pkginfo *pigp,
-                const char *fmt, ...) PRINTFFORMAT(6,7);
-void parse_must_have_field(const char *filename, int lno,
+void parse_error(struct parsedb_state *ps, const struct pkginfo *pigp,
+                 const char *fmt, ...) PRINTFFORMAT(3,4);
+void parse_warn(struct parsedb_state *ps, const struct pkginfo *pigp,
+                const char *fmt, ...) PRINTFFORMAT(3,4);
+void parse_must_have_field(struct parsedb_state *ps,
                            const struct pkginfo *pigp,
                            const char *value, const char *what);
-void parse_ensure_have_field(const char *filename, int lno,
-                             FILE *warnto, int *warncount,
+void parse_ensure_have_field(struct parsedb_state *ps,
                              const struct pkginfo *pigp,
                              const char **value, const char *what);
 
diff --git a/lib/parsehelp.c b/lib/parsehelp.c
index c850132..af2fd1f 100644
--- a/lib/parsehelp.c
+++ b/lib/parsehelp.c
@@ -35,25 +35,25 @@
 #include "parsedump.h"
 
 static void
-parse_error_msg(const char *filename, int lno, const struct pkginfo *pigp,
+parse_error_msg(struct parsedb_state *ps, const struct pkginfo *pigp,
                 const char *type, char *buf)
 {
   if (pigp && pigp->name)
     sprintf(buf, _("%s, in file '%.255s' near line %d package '%.255s':\n "),
-            type, filename, lno, pigp->name);
+            type, ps->filename, ps->lno, pigp->name);
   else
     sprintf(buf, _("%s, in file '%.255s' near line %d:\n "),
-            type, filename, lno);
+            type, ps->filename, ps->lno);
 }
 
 void
-parse_error(const char *filename, int lno,
+parse_error(struct parsedb_state *ps,
             const struct pkginfo *pigp, const char *fmt, ...)
 {
   va_list al;
   char buf1[768], buf2[1000], *q;
 
-  parse_error_msg(filename, lno, pigp, _("parse error"), buf1);
+  parse_error_msg(ps, pigp, _("parse error"), buf1);
   q = str_escape_fmt(buf2, buf1);
   strcat(q,fmt);
 
@@ -62,21 +62,21 @@ parse_error(const char *filename, int lno,
 }
 
 void
-parse_warn(const char *filename, int lno, FILE *warnto, int *warncount,
+parse_warn(struct parsedb_state *ps,
            const struct pkginfo *pigp, const char *fmt, ...)
 {
   va_list al;
   char buf1[768], buf2[1000], *q;
 
-  parse_error_msg(filename, lno, pigp, _("warning"), buf1);
+  parse_error_msg(ps, pigp, _("warning"), buf1);
   q = str_escape_fmt(buf2, buf1);
   strcat(q, fmt);
 
   va_start(al, fmt);
-  if (warncount) (*warncount)++;
-  if (warnto) {
+  ps->warncount++;
+  if (ps->warnto) {
     strcat(q,"\n");
-    if (vfprintf(warnto,buf2,al) == EOF)
+    if (vfprintf(ps->warnto, buf2, al) == EOF)
       ohshite(_("failed to write parsing warning"));
   }
   va_end(al);
@@ -251,29 +251,28 @@ const char *parseversion(struct versionrevision 
*rversion, const char *string) {
 }
 
 void
-parse_must_have_field(const char *filename, int lno,
+parse_must_have_field(struct parsedb_state *ps,
                       const struct pkginfo *pigp,
                       const char *value, const char *what)
 {
   if (!value)
-    parse_error(filename, lno, pigp, _("missing %s"), what);
+    parse_error(ps, pigp, _("missing %s"), what);
   else if (!*value)
-    parse_error(filename, lno, pigp, _("empty value for %s"), what);
+    parse_error(ps, pigp, _("empty value for %s"), what);
 }
 
 void
-parse_ensure_have_field(const char *filename, int lno,
-                        FILE *warnto, int *warncount,
+parse_ensure_have_field(struct parsedb_state *ps,
                         const struct pkginfo *pigp,
                         const char **value, const char *what)
 {
   static const char *empty = "";
 
   if (!*value) {
-    parse_warn(filename, lno, warnto, warncount, pigp, _("missing %s"), what);
+    parse_warn(ps, pigp, _("missing %s"), what);
     *value = empty;
   } else if (!**value) {
-    parse_warn(filename, lno, warnto, warncount, pigp, _("empty value for 
%s"), what);
+    parse_warn(ps, pigp, _("empty value for %s"), what);
   }
 }
 

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to