build/parseChangelog.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #include "rpmbuild.h"
00009 #include "debug.h"
00010 
00011 void addChangelogEntry(Header h, time_t time, const char *name, const char *text)
00012 {
00013     int_32 mytime = time;       /* XXX convert to header representation */
00014     if (headerIsEntry(h, RPMTAG_CHANGELOGTIME)) {
00015         (void) headerAppendEntry(h, RPMTAG_CHANGELOGTIME, RPM_INT32_TYPE,
00016                           &mytime, 1);
00017         (void) headerAppendEntry(h, RPMTAG_CHANGELOGNAME, RPM_STRING_ARRAY_TYPE,
00018                           &name, 1);
00019         (void) headerAppendEntry(h, RPMTAG_CHANGELOGTEXT, RPM_STRING_ARRAY_TYPE,
00020                          &text, 1);
00021     } else {
00022         (void) headerAddEntry(h, RPMTAG_CHANGELOGTIME, RPM_INT32_TYPE,
00023                        &mytime, 1);
00024         (void) headerAddEntry(h, RPMTAG_CHANGELOGNAME, RPM_STRING_ARRAY_TYPE,
00025                        &name, 1);
00026         (void) headerAddEntry(h, RPMTAG_CHANGELOGTEXT, RPM_STRING_ARRAY_TYPE,
00027                        &text, 1);
00028     }
00029 }
00030 
00037 /*@-boundswrite@*/
00038 static int dateToTimet(const char * datestr, /*@out@*/ time_t * secs)
00039         /*@modifies *secs @*/
00040 {
00041     struct tm time;
00042     char * p, * pe, * q, ** idx;
00043     char * date = strcpy(alloca(strlen(datestr) + 1), datestr);
00044 /*@observer@*/ static char * days[] =
00045         { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL };
00046 /*@observer@*/ static char * months[] =
00047         { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00048           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
00049 /*@observer@*/ static char lengths[] =
00050         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00051     
00052     memset(&time, 0, sizeof(time));
00053 
00054     pe = date;
00055 
00056     /* day of week */
00057     p = pe; SKIPSPACE(p);
00058     if (*p == '\0') return -1;
00059     pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
00060     for (idx = days; *idx && strcmp(*idx, p); idx++)
00061         {};
00062     if (*idx == NULL) return -1;
00063 
00064     /* month */
00065     p = pe; SKIPSPACE(p);
00066     if (*p == '\0') return -1;
00067     pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
00068     for (idx = months; *idx && strcmp(*idx, p); idx++)
00069         {};
00070     if (*idx == NULL) return -1;
00071     time.tm_mon = idx - months;
00072 
00073     /* day */
00074     p = pe; SKIPSPACE(p);
00075     if (*p == '\0') return -1;
00076     pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
00077 
00078     /* make this noon so the day is always right (as we make this UTC) */
00079     time.tm_hour = 12;
00080 
00081     time.tm_mday = strtol(p, &q, 10);
00082     if (!(q && *q == '\0')) return -1;
00083     if (time.tm_mday < 0 || time.tm_mday > lengths[time.tm_mon]) return -1;
00084 
00085     /* year */
00086     p = pe; SKIPSPACE(p);
00087     if (*p == '\0') return -1;
00088     pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
00089     time.tm_year = strtol(p, &q, 10);
00090     if (!(q && *q == '\0')) return -1;
00091     if (time.tm_year < 1990 || time.tm_year >= 3000) return -1;
00092     time.tm_year -= 1900;
00093 
00094     *secs = mktime(&time);
00095     if (*secs == -1) return -1;
00096 
00097     /* adjust to GMT */
00098     *secs += timezone;
00099 
00100     return 0;
00101 }
00102 /*@=boundswrite@*/
00103 
00110 /*@-boundswrite@*/
00111 static int addChangelog(Header h, StringBuf sb)
00112         /*@modifies h @*/
00113 {
00114     char *s;
00115     int i;
00116     time_t time;
00117     time_t lastTime = 0;
00118     char *date, *name, *text, *next;
00119 
00120     s = getStringBuf(sb);
00121 
00122     /* skip space */
00123     SKIPSPACE(s);
00124 
00125     while (*s != '\0') {
00126         if (*s != '*') {
00127             rpmError(RPMERR_BADSPEC,
00128                         _("%%changelog entries must start with *\n"));
00129             return RPMERR_BADSPEC;
00130         }
00131 
00132         /* find end of line */
00133         date = s;
00134         while(*s && *s != '\n') s++;
00135         if (! *s) {
00136             rpmError(RPMERR_BADSPEC, _("incomplete %%changelog entry\n"));
00137             return RPMERR_BADSPEC;
00138         }
00139         /*@-modobserver@*/
00140         *s = '\0';
00141         /*@=modobserver@*/
00142         text = s + 1;
00143         
00144         /* 4 fields of date */
00145         date++;
00146         s = date;
00147         for (i = 0; i < 4; i++) {
00148             SKIPSPACE(s);
00149             SKIPNONSPACE(s);
00150         }
00151         SKIPSPACE(date);
00152         if (dateToTimet(date, &time)) {
00153             rpmError(RPMERR_BADSPEC, _("bad date in %%changelog: %s\n"), date);
00154             return RPMERR_BADSPEC;
00155         }
00156         if (lastTime && lastTime < time) {
00157             rpmError(RPMERR_BADSPEC,
00158                      _("%%changelog not in descending chronological order\n"));
00159             return RPMERR_BADSPEC;
00160         }
00161         lastTime = time;
00162 
00163         /* skip space to the name */
00164         SKIPSPACE(s);
00165         if (! *s) {
00166             rpmError(RPMERR_BADSPEC, _("missing name in %%changelog\n"));
00167             return RPMERR_BADSPEC;
00168         }
00169 
00170         /* name */
00171         name = s;
00172         while (*s != '\0') s++;
00173         while (s > name && xisspace(*s)) {
00174             *s-- = '\0';
00175         }
00176         if (s == name) {
00177             rpmError(RPMERR_BADSPEC, _("missing name in %%changelog\n"));
00178             return RPMERR_BADSPEC;
00179         }
00180 
00181         /* text */
00182         SKIPSPACE(text);
00183         if (! *text) {
00184             rpmError(RPMERR_BADSPEC, _("no description in %%changelog\n"));
00185             return RPMERR_BADSPEC;
00186         }
00187             
00188         /* find the next leading '*' (or eos) */
00189         s = text;
00190         do {
00191            s++;
00192         } while (*s && (*(s-1) != '\n' || *s != '*'));
00193         next = s;
00194         s--;
00195 
00196         /* backup to end of description */
00197         while ((s > text) && xisspace(*s)) {
00198             *s-- = '\0';
00199         }
00200         
00201         addChangelogEntry(h, time, name, text);
00202         s = next;
00203     }
00204 
00205     return 0;
00206 }
00207 /*@=boundswrite@*/
00208 
00209 int parseChangelog(Spec spec)
00210 {
00211     int nextPart, res, rc;
00212     StringBuf sb = newStringBuf();
00213     
00214     /* There are no options to %changelog */
00215     if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) {
00216         sb = freeStringBuf(sb);
00217         return PART_NONE;
00218     }
00219     if (rc)
00220         return rc;
00221     
00222     while (! (nextPart = isPart(spec->line))) {
00223         appendStringBuf(sb, spec->line);
00224         if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) {
00225             nextPart = PART_NONE;
00226             break;
00227         }
00228         if (rc)
00229             return rc;
00230     }
00231 
00232     res = addChangelog(spec->packages->header, sb);
00233     sb = freeStringBuf(sb);
00234 
00235     return (res) ? res : nextPart;
00236 }

Generated on Fri Oct 12 08:44:53 2007 for rpm by  doxygen 1.5.2