Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

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

Generated on Wed Mar 13 15:34:46 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002