complete reorg of reading scheme
authorroot <devnull@localhost>
Tue, 12 Dec 1995 17:53:17 +0000 (17:53 +0000)
committerroot <devnull@localhost>
Tue, 12 Dec 1995 17:53:17 +0000 (17:53 +0000)
added %else handling
no regexp stuff
nice big table of tags and keywords :-)

CVS patchset: 11
CVS date: 1995/12/12 17:53:17

build/spec.c

index 6505c58..c906fcd 100644 (file)
@@ -3,17 +3,36 @@
  * spec.c - routines for parsing a spec file
  */
 
+/*****************************
+TODO:
+
+. multiline descriptions (general backslash processing)
+. real arch/os checking
+. %exclude
+. %doc
+. %config
+. %setup
+. %patch
+. %dir and real directory handling
+. root: option
+
+******************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+
 #include "header.h"
 #include "spec.h"
 #include "rpmerr.h"
 #include "messages.h"
-#include <stdlib.h>
-#include <string.h>
-#include <regex.h>
+#include "rpmlib.h"
 
 #define LINE_BUF_SIZE 1024
+#define FREE(x) { if (x) free(x); }
 
 struct SpecRec {
+    char *name;      /* package base name */
     char *prep;
     char *build;
     char *install;
@@ -22,6 +41,8 @@ struct SpecRec {
 };
 
 struct PackageRec {
+    char *subname;   /* If both of these are NULL, then this is      */
+    char *newname;   /* the main package.  subname concats with name */
     Header header;
     char *filelist;
     struct PackageRec *next;
@@ -31,12 +52,16 @@ static int read_line(FILE *f, char *line);
 static int match_arch(char *s);
 static int match_os(char *s);
 static void free_packagerec(struct PackageRec *p);
-static void init_spec(void);
+static void reset_spec(void);
+static int find_preamble_line(char *line, char **s);
+static int check_part(char *line, char **s);
 
 void free_packagerec(struct PackageRec *p)
 {
     freeHeader(p->header);
-    free(p->filelist);
+    FREE(p->filelist);
+    FREE(p->subname);
+    FREE(p->newname);
     if (p->next) {
         free_packagerec(p->next);
     }
@@ -45,10 +70,11 @@ void free_packagerec(struct PackageRec *p)
 
 void freeSpec(Spec s)
 {
-    free(s->prep);
-    free(s->build);
-    free(s->install);
-    free(s->clean);
+    FREE(s->name);
+    FREE(s->prep);
+    FREE(s->build);
+    FREE(s->install);
+    FREE(s->clean);
     free_packagerec(s->packages);
     free(s);
 }
@@ -71,122 +97,204 @@ static int match_os(char *s)
     }
 }
 
-static int reading = 0;
-static int iflevels = 0;
-static int skiplevels = 0;
-static int skip = 0;
+static struct read_level_entry {
+    int reading;  /* 1 if we are reading at this level */
+    struct read_level_entry *next;
+} *read_level = NULL;
 
 static int read_line(FILE *f, char *line)
 {
-    char *r = fgets(line, LINE_BUF_SIZE, f);
+    static struct read_level_entry *rl;
+    int gotline;
+    char *r;
 
-    if (! r) {
-       /* the end */
-       if (iflevels) return RPMERR_UNMATCHEDIF;
-       return 0;
+    do {
+        gotline = 0;
+       if (! fgets(line, LINE_BUF_SIZE, f)) {
+           /* the end */
+           if (read_level->next) {
+               return RPMERR_UNMATCHEDIF;
+           } else {
+               return 0;
+           }
+       }
+       if (! strncmp("%ifarch", line, 7)) {
+           rl = malloc(sizeof(struct read_level_entry));
+           rl->next = read_level;
+           rl->reading = read_level->reading && match_arch(line);
+           read_level = rl;
+       } else if (! strncmp("%ifos", line, 5)) {
+           rl = malloc(sizeof(struct read_level_entry));
+           rl->next = read_level;
+           rl->reading = read_level->reading && match_os(line);
+           read_level = rl;
+       } else if (! strncmp("%else", line, 5)) {
+           if (! read_level->next) {
+               /* Got an else with no %if ! */
+               return RPMERR_UNMATCHEDIF;
+           }
+           read_level->reading =
+               read_level->next->reading && ! read_level->reading;
+       } else if (! strncmp("%endif", line, 6)) {
+           rl = read_level;
+           read_level = rl->next;
+           free(rl);
+       } else {
+            gotline = 1;
+        }
+    } while (! (gotline && read_level->reading));
+    
+    r = line + (strlen(line)) - 1;
+    if (*r == '\n') {
+        *r = '\0';
     }
+    return 1;
+}
 
-    skip = 0;
+struct preamble_line {
+    int tag;
+    int len;
+    char *token;
+} preamble_spec[] = {
+    {RPMTAG_NAME,         0, "name"},
+    {RPMTAG_VERSION,      0, "version"},
+    {RPMTAG_RELEASE,      0, "release"},
+    {RPMTAG_SERIAL,       0, "serial"},
+    {RPMTAG_DESCRIPTION,  0, "description"},
+    {RPMTAG_SUMMARY,      0, "summary"},
+    {RPMTAG_COPYRIGHT,    0, "copyright"},
+    {RPMTAG_DISTRIBUTION, 0, "distribution"},
+    {RPMTAG_VENDOR,       0, "vendor"},
+    {RPMTAG_GROUP,        0, "group"},
+    {RPMTAG_PACKAGER,     0, "packager"},
+    {0, 0, 0}
+};
 
-    if (! strncmp("%ifarch", line, 7)) {
-       iflevels++;
-       skip = 1;
-       if (! match_arch(line)) {
-           reading = 0;
-           skiplevels++;
-       }
-    }
-    if (! strncmp("%ifos", line, 5)) {
-       iflevels++;
-       skip = 1;
-       if (! match_os(line)) {
-           reading = 0;
-           skiplevels++;
-       }
-    }
+static int find_preamble_line(char *line, char **s)
+{
+    struct preamble_line *p = preamble_spec;
 
-    if (! strncmp("%endif", line, 6)) {
-       iflevels--;
-       skip = 1;
-       if (skiplevels) {
-           if (! --skiplevels) reading = 1;
-       }
+    while (p->token && strncasecmp(line, p->token, p->len)) {
+        p++;
     }
-    
-    return 1;
+    if (!p) return 0;
+    *s = line + p->len;
+    *s += strspn(*s, ": \t");
+    return p->tag;
 }
 
-static regex_t name_regex;
-static regex_t description_regex;
-static regex_t package_regex;
-static regex_t version_regex;
-static regex_t release_regex;
-static regex_t copyright_regex;
-static regex_t icon_regex;
-static regex_t group_regex;
-
-struct regentry {
-    regex_t *p;
+/* None of these can be 0 !! */
+#define PREAMBLE_PART 1
+#define PREP_PART     2
+#define BUILD_PART    3
+#define INSTALL_PART  4
+#define CLEAN_PART    5
+#define PREIN_PART    6
+#define POSTIN_PART   7
+#define PREUN_PART    8
+#define POSTUN_PART   9
+#define FILES_PART    10
+
+static struct part_rec {
+    int part;
+    int len;
     char *s;
-} regexps[] = {
-    {&package_regex,     "^package[[:space:]]*:[[:space:]]*"},
-    {&name_regex,        "^name[[:space:]]*:[[:space:]]*"},
-    {&description_regex, "^description[[:space:]]*:[[:space:]]*"},
-    {&version_regex,     "^version[[:space:]]*:[[:space:]]*"},
-    {&release_regex,     "^release[[:space:]]*:[[:space:]]*"},
-    {&copyright_regex,   "^copyright[[:space:]]*:[[:space:]]*"},
-    {&group_regex,       "^group[[:space:]]*:[[:space:]]*"},
-    {&icon_regex,        "^icon[[:space:]]*:[[:space:]]*"},
-    {0, 0}
+} part_list[] = {
+    {PREAMBLE_PART, 0, "%package"},
+    {PREP_PART,     0, "%prep"},
+    {BUILD_PART,    0, "%build"},
+    {INSTALL_PART,  0, "%install"},
+    {CLEAN_PART,    0, "%clean"},
+    {PREIN_PART,    0, "%prein"},
+    {POSTIN_PART,   0, "%postin"},
+    {PREUN_PART,    0, "%preun"},
+    {POSTUN_PART,   0, "%postun"},
+    {FILES_PART,    0, "%files"},
+    {0, 0, 0}
 };
 
-static void init_spec()
+static int check_part(char *line, char **s)
 {
-    static done = 0;
-    struct regentry *r = regexps;
-    int opts = REG_ICASE | REG_EXTENDED;
-    
-    if (! done) {
-        while(r->p) {
-           regcomp(r->p, r->s, opts);
-           r++;
-       }
-       done = 1;
+    struct part_rec *p = part_list;
+
+    while (p->s && strncasecmp(line, p->s, p->len)) {
+        p++;
+    }
+    if (!p) return 0;
+    *s = line + p->len;
+    *s += strspn(*s, " \t");
+    if (**s == '\0') {
+        *s = NULL;
     }
+    return p->part;
 }
 
-#define PACKAGE_PART 0
-#define PREP_PART    1
-#define BUILD_PART   2
-#define INSTALL_PART 3
-#define CLEAN_PART   4
-#define PREIN_PART   5
-#define POSTIN_PART  6
-#define PREUN_PART   7
-#define POSTUN_PART  8
-#define FILES_PART   9
-
 Spec parseSpec(FILE *f)
 {
     char line[LINE_BUF_SIZE];
-    Spec s = (struct SpecRec *) malloc(sizeof(struct SpecRec));
-    int part = PACKAGE_PART;
+    char *s;
+    int cur_part = PREAMBLE_PART;
+    struct PackageRec *cur_package = NULL;
+
+    int x, tag;
 
-    int x;
-    regmatch_t match;
+    Spec spec = (struct SpecRec *) malloc(sizeof(struct SpecRec));
+    spec->name = NULL;
 
-    init_spec();
+    reset_spec();
     
-    reading = 1;
-    while ((x = read_line(f, line))) {
-       if (!reading) continue;
-       if (skip) continue;
-       /* If we get here, this line is for us */
-       printf(line);
-       if (! regexec(&description_regex, line, 1, &match, 0)) {
-           message(MESS_DEBUG, "description: %s", line + match.rm_eo);
-       } else if (! regexec(&name_regex, line, 1, &match, 0)) {
-           message(MESS_DEBUG, "name       : %s", line + match.rm_eo);
+    while ((x = read_line(f, line)) > 0) {
+        if ((tag = check_part(line, &s))) {
+           cur_part = tag;
+           printf("Switching to: %d\n", cur_part);
+           if (s) {
+               printf("Subname: %s\n", s);
+           }
+           continue;
+        }
+      
+        switch (cur_part) {
+         case PREAMBLE_PART:
+           if ((tag = find_preamble_line(line, &s))) {
+               switch (tag) {
+                 case RPMTAG_NAME:
+                 case RPMTAG_VERSION:
+                 case RPMTAG_RELEASE:
+                 case RPMTAG_SERIAL:
+                 case RPMTAG_SUMMARY:
+                 case RPMTAG_DESCRIPTION:
+                 case RPMTAG_INSTALLTIME:
+                 case RPMTAG_DISTRIBUTION:
+                 case RPMTAG_VENDOR:
+                 case RPMTAG_COPYRIGHT:
+                 case RPMTAG_PACKAGER:
+                 case RPMTAG_GROUP:
+                 case RPMTAG_URL:
+                   printf("%d: %s\n", tag, s);
+                   break;
+                 default:
+                   printf("Skipping: %s\n", line);
+               }               
+           } else {
+               /* Not a recognized preamble part */
+               printf("Unknown: %s\n", line);
+           }
+           break;
+         case PREP_PART:
+         case BUILD_PART:
+         case INSTALL_PART:
+         case CLEAN_PART:
+           break;
+         case PREIN_PART:
+         case POSTIN_PART:
+         case PREUN_PART:
+         case POSTUN_PART:
+           break;
+         case FILES_PART:
+           break;
+         default:
+           /* error(RPMERR_INTERNALBADPART, "Internal error"); */
+           printf("%s\n", line);
        }
     }
     if (x < 0) {
@@ -195,5 +303,36 @@ Spec parseSpec(FILE *f)
        return NULL;
     }
     
-    return s;
+    return spec;
+}
+
+static void reset_spec()
+{
+    static done = 0;
+    struct read_level_entry *rl;
+    struct preamble_line *p = preamble_spec;
+    struct part_rec *p1 = part_list;
+
+    while (read_level) {
+       rl = read_level;
+        read_level = read_level->next;
+       free(rl);
+    }
+    read_level = malloc(sizeof(struct read_level_entry));
+    read_level->next = NULL;
+    read_level->reading = 1;
+    
+    if (! done) {
+        /* Put one time only things in here */
+        while (p->tag) {
+           p->len = strlen(p->token);
+           p++;
+       }
+        while (p1->part) {
+           p1->len = strlen(p1->s);
+           p1++;
+       }
+
+       done = 1;
+    }
 }