sfeed

Simple RSS and Atom feed parser
git clone https://git.sinitax.com/codemadness/sfeed
Log | Files | Refs | README | LICENSE | Upstream | sfeed.txt

commit c334bcf1862a48ebb37e80aca319d4aa5baad061
parent c3b5da658eeef51b1444060aa107fc413ea0f436
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Tue, 13 May 2014 10:07:52 +0000

cleanup, tested with tcc

Signed-off-by: Hiltjo Posthuma <hiltjo@codemadness.org>

Diffstat:
MREADME | 2+-
MTODO | 8+++++---
Msfeed.c | 59+++++++++++++----------------------------------------------
Msfeed_frames.c | 12++++--------
Msfeed_html.c | 19+++++--------------
Msfeed_plain.c | 1+
Msfeed_stats.c | 10++++------
Msfeed_xmlenc.c | 2+-
Mutil.c | 8+++++---
Mutil.h | 1-
10 files changed, 39 insertions(+), 83 deletions(-)

diff --git a/README b/README @@ -27,7 +27,7 @@ Optional dependencies Platforms tested ---------------- -- Linux (glibc+gcc, musl-gcc, clang). +- Linux (glibc+gcc, musl-gcc, clang, tcc). - OpenBSD - Windows (cygwin gcc, mingw). diff --git a/TODO b/TODO @@ -1,14 +1,16 @@ [ ] test again on: - - Linux (glibc+gcc, musl-gcc, clang). + - Linux (glibc+gcc, musl-gcc, clang, tcc). - OpenBSD - Windows (cygwin gcc, mingw). -[ ] test with ubase/sbase tools. +[ ] test shellscripts with ubase/sbase tools. + [ ] sfeed_update + [ ] sfeed_opml_export [ ] remove sfeed_stats ? [ ] dogfood sfeed_frames, html content. [ ] in links browsers: items are centered in the table for some reason. [ ] feeds file: empty tab (encoding can't be detected?) [ ] optimize - [ ] afgets() [ ] gettag() lookup. [ ] namedentitytostr lookup. [ ] xml parser, etc. +[ ] cleanup code. diff --git a/sfeed.c b/sfeed.c @@ -216,11 +216,11 @@ entitytostr(const char *e, char *buffer, size_t bufsiz) { return 0; } +/* clear string only; don't free, prevents unnecessary reallocation */ static void string_clear(String *s) { if(s->data) - s->data[0] = '\0'; /* clear string only; don't free, prevents - unnecessary reallocation */ + s->data[0] = '\0'; s->len = 0; } @@ -258,7 +258,7 @@ static void string_append(String *s, const char *data, size_t len) { if(!len || *data == '\0') return; - /* check if allocation is necesary, dont shrink buffer + /* check if allocation is necesary, don't shrink buffer should be more than bufsiz ofcourse */ if(s->len + len > s->bufsiz) string_buffer_realloc(s, s->len + len); @@ -281,9 +281,7 @@ cleanup(void) { /* print error message to stderr */ static void die(const char *s) { - fputs("sfeed: ", stderr); - fputs(s, stderr); - fputc('\n', stderr); + fprintf(stderr, "sfeed: %s\n", s); exit(EXIT_FAILURE); } @@ -307,7 +305,7 @@ gettimetz(const char *s, char *buf, size_t bufsiz) { /* TODO: cleanup / simplify */ if(isalpha((int)*p)) { if(*p == 'Z' || *p == 'z') { - memcpy(buf, "GMT+00:00", strlen("GMT+00:00") + 1); + strlcpy(buf, "GMT+00:00", sizeof(buf)); return 0; } else { for(i = 0, t = &tzname[0]; i < (sizeof(tzname) - 1) && @@ -316,7 +314,7 @@ gettimetz(const char *s, char *buf, size_t bufsiz) { *t = '\0'; } } else - memcpy(tzname, "GMT", strlen("GMT") + 1); + strlcpy(tzname, "GMT", sizeof(tzname)); if(!(*p)) { strlcpy(buf, tzname, bufsiz); return 0; @@ -325,7 +323,7 @@ gettimetz(const char *s, char *buf, size_t bufsiz) { else if(sscanf(p, "%c%02d%02d", &c, &tzhour, &tzmin) > 0); else if(sscanf(p, "%c%d", &c, &tzhour) > 0) tzmin = 0; - sprintf(buf, "%s%c%02d%02d", tzname, c, tzhour, tzmin); + snprintf(buf, sizeof(buf) - 1, "%s%c%02d%02d", tzname, c, tzhour, tzmin); /* TODO: test + or - offset */ return (tzhour * 3600) + (tzmin * 60) * (c == '-' ? -1 : 1); } @@ -335,7 +333,7 @@ parsetime(const char *s, char *buf, size_t bufsiz) { time_t t = -1; /* can't parse */ char tz[64] = ""; struct tm tm; - char *formats[] = { + const char *formats[] = { "%a, %d %b %Y %H:%M:%S", "%Y-%m-%d %H:%M:%S", "%Y-%m-%dT%H:%M:%S", @@ -344,7 +342,7 @@ parsetime(const char *s, char *buf, size_t bufsiz) { char *p; unsigned int i; - if(buf) + if(buf && bufsiz > 0) buf[0] = '\0'; memset(&tm, 0, sizeof(tm)); for(i = 0; formats[i]; i++) { @@ -367,11 +365,7 @@ parsetime(const char *s, char *buf, size_t bufsiz) { static void string_print(String *s) { const char *p; -/* char buffer[BUFSIZ + 4]; - size_t i;*/ - if(!s->len) - return; /* skip leading whitespace */ for(p = s->data; *p && isspace((int)*p); p++); for(; *p; p++) { @@ -385,32 +379,6 @@ string_print(String *s) { } else putchar(*p); } -#if 0 - /* NOTE: optimized string output, re-test this later */ - for(i = 0; *p; p++) { - if(ISWSNOSPACE(*p)) { /* isspace(c) && c != ' ' */ - if(*p == '\n') { /* escape newline */ - buffer[i++] = '\\'; - buffer[i++] = 'n'; - } else if(*p == '\\') { /* escape \ */ - buffer[i++] = '\\'; - buffer[i++] = '\\'; - } else if(*p == '\t') { /* tab */ - buffer[i++] = '\\'; - buffer[i++] = 't'; - } - /* ignore other whitespace chars, except space */ - } else { - buffer[i++] = *p; - } - if(i >= BUFSIZ) { /* align write size with BUFSIZ */ - fwrite(buffer, 1, BUFSIZ, stdout); - i -= BUFSIZ; - } - } - if(i) /* write remaining */ - fwrite(buffer, 1, i, stdout); -#endif } static int @@ -545,9 +513,7 @@ xml_handler_start_element(XMLParser *p, const char *name, size_t namelen) { if(ctx.tag[0] != '\0') return; /* in item */ - if(namelen >= sizeof(ctx.tag) - 2) /* check overflow */ - return; - memcpy(ctx.tag, name, namelen + 1); /* copy including nul byte */ + strlcpy(ctx.tag, name, sizeof(ctx.tag)); ctx.taglen = namelen; ctx.tagid = gettag(ctx.item.feedtype, ctx.tag, ctx.taglen); if(ctx.tagid == TagUnknown) @@ -649,7 +615,7 @@ xml_handler_end_element(XMLParser *p, const char *name, size_t namelen, int issh istag(name, namelen, "item", strlen("item")))) /* RSS */ { printf("%ld", (long)parsetime((&ctx.item.timestamp)->data, - timebuf, sizeof(timebuf))); + timebuf, sizeof(timebuf))); putchar(FieldSeparator); fputs(timebuf, stdout); putchar(FieldSeparator); @@ -688,7 +654,8 @@ xml_handler_end_element(XMLParser *p, const char *name, size_t namelen, int issh /* not sure if needed */ ctx.iscontenttag = 0; ctx.iscontent = 0; - } else if(!strcmp(ctx.tag, name)) { /* clear */ + } else if(ctx.taglen == namelen && !strcmp(ctx.tag, name)) { + /* clear */ /* XXX: optimize ? */ ctx.field = NULL; ctx.tag[0] = '\0'; /* unset tag */ diff --git a/sfeed_frames.c b/sfeed_frames.c @@ -13,18 +13,15 @@ #include "util.h" static unsigned int showsidebar = 1; /* show sidebar ? */ - static FILE *fpindex = NULL, *fpitems = NULL, *fpmenu = NULL; static FILE *fpcontent = NULL; static char *line = NULL; static struct feed *feeds = NULL; -/* print string to stderr and exit program with EXIT_FAILURE */ +/* print error message to stderr */ static void die(const char *s) { - fputs("sfeed_frames: ", stderr); - fputs(s, stderr); - fputc('\n', stderr); + fprintf(stderr, "sfeed_frames: %s\n", s); exit(EXIT_FAILURE); } @@ -98,10 +95,9 @@ main(int argc, char **argv) { struct feed *f, *fcur = NULL; char *fields[FieldLast]; char name[64]; /* TODO: bigger size? */ - char *basepath = "."; char dirpath[PATH_MAX], filepath[PATH_MAX]; char reldirpath[PATH_MAX], relfilepath[PATH_MAX]; - char *feedname = ""; + char *feedname = "", *basepath = "."; unsigned long totalfeeds = 0, totalnew = 0; unsigned int isnew; time_t parsedtime, comparetime; @@ -226,7 +222,7 @@ main(int argc, char **argv) { contenttime.modtime = parsedtime; utime(filepath, &contenttime); - isnew = (parsedtime >= comparetime); + isnew = (parsedtime >= comparetime) ? 1 : 0; totalnew += isnew; fcur->totalnew += isnew; fcur->total++; diff --git a/sfeed_html.c b/sfeed_html.c @@ -7,7 +7,6 @@ #include "util.h" static int showsidebar = 1; /* show sidebar ? */ - static struct feed *feeds = NULL; /* start of feeds linked-list. */ static char *line = NULL; @@ -18,11 +17,10 @@ cleanup(void) { feedsfree(feeds); /* free feeds linked-list */ } -static void /* print error message to stderr */ +/* print error message to stderr */ +static void die(const char *s) { - fputs("sfeed_html: ", stderr); - fputs(s, stderr); - fputc('\n', stderr); + fprintf(stderr, "sfeed_html: %s\n", s); exit(EXIT_FAILURE); } @@ -53,10 +51,9 @@ main(void) { while(parseline(&line, &size, fields, FieldLast, '\t', stdin) > 0) { parsedtime = (time_t)strtol(fields[FieldUnixTimestamp], NULL, 10); - isnew = (parsedtime >= comparetime); - islink = (fields[FieldLink][0] != '\0'); + isnew = (parsedtime >= comparetime) ? 1 : 0; + islink = (fields[FieldLink][0] != '\0') ? 1 : 0; /* first of feed section or new feed section. */ - /* TODO: allocate fcur before here, fcur can be NULL */ if(!totalfeeds || (fcur && strcmp(fcur->name, fields[FieldFeedName]))) { if(!(f = calloc(1, sizeof(struct feed)))) die("can't allocate enough memory"); @@ -80,12 +77,6 @@ main(void) { if(!(fcur->name = strdup(fields[FieldFeedName]))) die("can't allocate enough memory"); - - /* - fcur->totalnew = 0; - fcur->total = 0; - fcur->next = NULL;*/ - if(fields[FieldFeedName][0] != '\0') { fputs("<h2 id=\"", stdout); printfeednameid(fcur->name, stdout); diff --git a/sfeed_plain.c b/sfeed_plain.c @@ -43,5 +43,6 @@ main(void) { putchar('\n'); } free(line); + line = NULL; return EXIT_SUCCESS; } diff --git a/sfeed_stats.c b/sfeed_stats.c @@ -15,11 +15,10 @@ cleanup(void) { feedsfree(feeds); /* free feeds linked-list */ } -static void /* print error message to stderr */ +/* print error message to stderr */ +static void die(const char *s) { - fputs("sfeed_stats: ", stderr); - fputs(s, stderr); - fputc('\n', stderr); + fprintf(stderr, "sfeed_stats: %s\n", s); exit(EXIT_FAILURE); } @@ -41,9 +40,8 @@ main(void) { while(parseline(&line, &size, fields, FieldLast, '\t', stdin) > 0) { parsedtime = (time_t)strtol(fields[FieldUnixTimestamp], NULL, 10); - isnew = (parsedtime >= comparetime); + isnew = (parsedtime >= comparetime) ? 1 : 0; /* first of feed section or new feed section. */ - /* TODO: allocate fcur before here, fcur can be NULL */ if(!totalfeeds || (fcur && strcmp(fcur->name, fields[FieldFeedName]))) { if(!(f = calloc(1, sizeof(struct feed)))) die("can't allocate enough memory"); diff --git a/sfeed_xmlenc.c b/sfeed_xmlenc.c @@ -34,7 +34,7 @@ xmlattr(XMLParser *p, const char *tag, size_t taglen, const char *name, size_t n } int -main(int argc, char **argv) { +main(void) { XMLParser x; xmlparser_init(&x, stdin); diff --git a/util.c b/util.c @@ -43,7 +43,8 @@ printlink(const char *link, const char *baseurl, FILE *fp) { int isrelative; /* protocol part */ - for(p = link; *p && (isalpha((int)*p) || isdigit((int)*p) || *p == '+' || *p == '-' || *p == '.'); p++); + for(p = link; *p && (isalpha((int)*p) || isdigit((int)*p) || + *p == '+' || *p == '-' || *p == '.'); p++); /* relative link (baseurl is used). */ isrelative = strncmp(p, "://", strlen("://")); if(isrelative) { @@ -82,7 +83,7 @@ parseline(char **line, size_t *size, char **fields, unsigned int i = 0; char *prev, *s; - if(afgets(line, size, fp)) { + if(getline(line, size, fp) > 0) { for(prev = *line; (s = strchr(prev, separator)) && i <= maxfields; i++) { *s = '\0'; fields[i] = prev; @@ -95,7 +96,8 @@ parseline(char **line, size_t *size, char **fields, return i; } -/* print feed name for id; spaces and tabs in string as "-" (spaces in anchors are not valid). */ +/* print feed name for id; spaces and tabs in string as "-" + * (spaces in anchors are not valid). */ void printfeednameid(const char *s, FILE *fp) { for(; *s; s++) diff --git a/util.h b/util.h @@ -17,7 +17,6 @@ enum { FieldUnixTimestamp = 0, FieldTimeFormatted, FieldTitle, FieldLink, #undef strlcpy size_t strlcpy(char *, const char *, size_t); -char * afgets(char **p, size_t *size, FILE *fp); void feedsfree(struct feed *f); unsigned int parseline(char **line, size_t *size, char **fields, unsigned int maxfields, int separator, FILE *fp);