sfeed

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

commit 369350956a08b2f2fd987a463c74608b6d289271
parent 2c564512516f88b09993b2e92637440441650bcc
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Sun, 21 Jun 2015 00:12:13 +0200

remove legacy man pages, remove queue.h, remove sfeed_stats

Diffstat:
Ddoc/man/sfeed.1 | 57---------------------------------------------------------
Ddoc/man/sfeed_frames.1 | 44--------------------------------------------
Ddoc/man/sfeed_html.1 | 21---------------------
Ddoc/man/sfeed_opml_export.1 | 24------------------------
Ddoc/man/sfeed_opml_import.1 | 16----------------
Ddoc/man/sfeed_plain.1 | 22----------------------
Ddoc/man/sfeed_stats.1 | 22----------------------
Ddoc/man/sfeed_update.1 | 101-------------------------------------------------------------------------------
Ddoc/man/sfeed_web.1 | 40----------------------------------------
Ddoc/man/sfeed_xmlenc.1 | 25-------------------------
Dqueue.h | 648-------------------------------------------------------------------------------
Dsfeed_stats.1 | 21---------------------
Dsfeed_stats.c | 76----------------------------------------------------------------------------
13 files changed, 0 insertions(+), 1117 deletions(-)

diff --git a/doc/man/sfeed.1 b/doc/man/sfeed.1 @@ -1,57 +0,0 @@ -.TH "SFEED" "1" "December 25, 2014" "" "General Commands Manual" -.nh -.if n .ad l -.SH "NAME" -\fBsfeed\fR -\- simple RSS and Atom parser -.SH "SYNOPSIS" -.HP 6n -\fBsfeed\fR -[\fIsuffix\ string\fR\ |\ \fB\-\fR\fIv\fR] -.SH "DESCRIPTION" -\fBsfeed\fR -reads RSS or Atom feed data (XML) from stdin. It writes the feed data in a -tab-separated format to stdout. -.SH "OPTIONS" -.TP 19n -\fB\-v\fR -show program version -.SH "TAB-SEPARATED FORMAT FIELDS" -The items are saved in a TSV-like format except newlines, tabs and -backslash are escaped with \\ (\\n, \\t and \\\\). Carriage returns (\\r) are -removed. -.PP -The order and format of the fields are: -.TP 19n -\fIitem timestamp\fR -string, UNIX timestamp in GMT+0 -.TP 19n -\fIitem timestamp\fR -string, date and time in the format: YYYY-mm-dd HH:MM:SS tzname[[+-][HHMM]] -.TP 19n -\fIitem title\fR -string -.TP 19n -\fIitem link\fR -string -.TP 19n -\fIitem content\fR -string -.TP 19n -\fIitem content\-type\fR -.br -string, "html" or "plain" -.TP 19n -\fIitem id\fR -string -.TP 19n -\fIitem author\fR -string -.TP 19n -\fIfeed type\fR -string, "rss" or "atom" -.SH "SEE ALSO" -sfeed_update(1), -sh(1) -.SH "AUTHORS" -Hiltjo Posthuma <\fIhiltjo@codemadness.org\fR> diff --git a/doc/man/sfeed_frames.1 b/doc/man/sfeed_frames.1 @@ -1,44 +0,0 @@ -.TH "SFEED_FRAMES" "1" "December 25, 2014" "" "General Commands Manual" -.nh -.if n .ad l -.SH "NAME" -\fBsfeed_frames\fR -\- formats a feeds file to HTML with frames -.SH "SYNOPSIS" -.HP 13n -\fBsfeed_frames\fR -[\fIdirectory\ path\fR] -.SH "DESCRIPTION" -\fBsfeed_frames\fR -formats a feeds file (TSV) from -sfeed_update(1) -to HTML. It reads TSV data from stdin and writes HTML to the specified -directory. For the exact TSV format see -sfeed_update(1). -.SH "OPTIONS" -.TP 16n -\fIdirectory path\fR -Path to write files to, default is ".". On success the specified directory will -contain the files: -.TP 15n -\fIindex.html:\fR -this is the main HTML file referencing to the frames (items.html and -menu.html). -.TP 15n -\fIitems.html:\fR -this contains all the items as HTML links to the local content. -.TP 15n -\fImenu.html:\fR -menu frame which contains navigation "anchor" links to the feed names -(in items.html). -.SH "FILE STRUCTURE" -Directory for each feed category in the format: path/feedname/itemname.html. -The feedname and item names are normalized, whitespace characters are replaced -with a \-, multiple whitespaces are replaced by a single \- and trailing -whitespace will be removed. -.SH "SEE ALSO" -sfeed(1), -sfeed_plain(1), -sfeed_update(1) -.SH "AUTHORS" -Hiltjo Posthuma <\fIhiltjo@codemadness.org\fR> diff --git a/doc/man/sfeed_html.1 b/doc/man/sfeed_html.1 @@ -1,21 +0,0 @@ -.TH "SFEED_HTML" "1" "December 25, 2014" "" "General Commands Manual" -.nh -.if n .ad l -.SH "NAME" -\fBsfeed_html\fR -\- formats a feeds file to HTML -.SH "SYNOPSIS" -.HP 11n -\fBsfeed_html\fR -.SH "DESCRIPTION" -\fBsfeed_html\fR -formats a feeds file (TSV) from -sfeed_update(1) -to HTML. It reads TSV data from stdin and writes HTML to stdout. For the exact TSV format see -sfeed_update(1). -.SH "SEE ALSO" -sfeed(1), -sfeed_plain(1), -sfeed_update(1) -.SH "AUTHORS" -Hiltjo Posthuma <\fIhiltjo@codemadness.org\fR> diff --git a/doc/man/sfeed_opml_export.1 b/doc/man/sfeed_opml_export.1 @@ -1,24 +0,0 @@ -.TH "SFEED_OPML_EXPORT" "1" "December 25, 2014" "" "General Commands Manual" -.nh -.if n .ad l -.SH "NAME" -\fBsfeed_opml_export\fR -\- generate an OPML file based on a sfeedrc config file -.SH "SYNOPSIS" -.HP 18n -\fBsfeed_opml_export\fR -[\fIconfig\ file\fR] -.SH "DESCRIPTION" -\fBsfeed_opml_export\fR -parses the specified config file and output OPML XML data to stdout. -.SH "OPTIONS" -.TP 19n -[config file] -default: "$HOME/.sfeed/sfeedrc", see the -sfeed_update(1) -\fIFILES READ\fR -section for more information. -.SH "SEE ALSO" -sfeed_update(1) -.SH "AUTHORS" -Hiltjo Posthuma <\fIhiltjo@codemadness.org\fR> diff --git a/doc/man/sfeed_opml_import.1 b/doc/man/sfeed_opml_import.1 @@ -1,16 +0,0 @@ -.TH "SFEED_OPML_IMPORT" "1" "December 25, 2014" "" "General Commands Manual" -.nh -.if n .ad l -.SH "NAME" -\fBsfeed_opml_import\fR -\- generate a sfeedrc config file based on an OPML file -.SH "SYNOPSIS" -.HP 18n -\fBsfeed_opml_import\fR -.SH "DESCRIPTION" -\fBsfeed_opml_import\fR -reads the OPML XML data from stdin and writes the config file text to stdout. -.SH "SEE ALSO" -sfeed_update(1) -.SH "AUTHORS" -Hiltjo Posthuma <\fIhiltjo@codemadness.org\fR> diff --git a/doc/man/sfeed_plain.1 b/doc/man/sfeed_plain.1 @@ -1,22 +0,0 @@ -.TH "SFEED_PLAIN" "1" "December 25, 2014" "" "General Commands Manual" -.nh -.if n .ad l -.SH "NAME" -\fBsfeed_plain\fR -\- formats a feeds file to plain text -.SH "SYNOPSIS" -.HP 12n -\fBsfeed_plain\fR -.SH "DESCRIPTION" -\fBsfeed_plain\fR -formats a feeds file (TSV) from -sfeed_update(1) -to plain text. It reads TSV data from stdin and writes formatted plain text to -stdout. For the exact TSV format see -sfeed_update(1). -.SH "SEE ALSO" -sfeed(1), -sfeed_html(1), -sfeed_update(1) -.SH "AUTHORS" -Hiltjo Posthuma <\fIhiltjo@codemadness.org\fR> diff --git a/doc/man/sfeed_stats.1 b/doc/man/sfeed_stats.1 @@ -1,22 +0,0 @@ -.TH "SFEED_STATS" "1" "January 3, 2015" "" "General Commands Manual" -.nh -.if n .ad l -.SH "NAME" -\fBsfeed_stats\fR -\- formats a feeds file to show a summary in plain text -.SH "SYNOPSIS" -.HP 12n -\fBsfeed_stats\fR -.SH "DESCRIPTION" -\fBsfeed_stats\fR -formats a feeds file (TSV) from -sfeed_update(1) -to a summary in plain text containing: the total amount of items, amount of new -items, the timestamp of the last item per feed. It reads TSV data from stdin -and writes formatted plain text to stdout. For the exact TSV format see -sfeed_update(1). -.SH "SEE ALSO" -sfeed(1), -sfeed_update(1) -.SH "AUTHORS" -Hiltjo Posthuma <\fIhiltjo@codemadness.org\fR> diff --git a/doc/man/sfeed_update.1 b/doc/man/sfeed_update.1 @@ -1,101 +0,0 @@ -.TH "SFEED_UPDATE" "1" "December 25, 2014" "" "General Commands Manual" -.nh -.if n .ad l -.SH "NAME" -\fBsfeed_update\fR -\- update feeds and merge with old feeds -.SH "SYNOPSIS" -.HP 13n -\fBsfeed_update\fR -[\fIconfigfile\fR] -.SH "DESCRIPTION" -\fBsfeed_update\fR -updates feeds and merges the new data with the previous feeds. This is the file -$HOME/.sfeed/feeds by default. -.SH "OPTIONS" -.TP 19n -\fIconfigfile\fR -config file, if not specified uses the location $HOME/.sfeed/sfeedrc by default -see the -\fIFILES READ\fR -section for more information. -.SH "TAB-SEPARATED FORMAT FIELDS" -The items are saved in a TSV-like format except newlines, tabs and -backslash are escaped with \\ (\\n, \\t and \\\\). Carriage returns (\\r) are -removed. -.PP -The order and format of the fields are: -.TP 19n -\fIitem timestamp\fR -string, UNIX timestamp in GMT+0 -.TP 19n -\fIitem timestamp\fR -string, date and time in the format: YYYY-mm-dd HH:MM:SS tzname[[+-][HHMM]] -.TP 19n -\fIitem title\fR -string -.TP 19n -\fIitem link\fR -string -.TP 19n -\fIitem content\fR -string -.TP 19n -\fIitem content\-type\fR -.br -string, "html" or "plain" -.TP 19n -\fIitem id\fR -string -.TP 19n -\fIitem author\fR -string -.TP 19n -\fIfeed type\fR -string, "rss" or "atom" -.SH "EXTRA FIELDS" -Extra fields added by sfeed_update: -.TP 19n -\fIfeed name\fR -string -.TP 19n -\fIfeed url\fR -string -.TP 19n -\fIitem baseurl site\fR -string -.SH "FILES READ" -.TP 19n -\fIsfeedrc\fR -Config file, see the sfeedrc.example file for an example. -This file is evaluated as a shellscript in sfeed_update. -You can for example override the fetchfeed() function to -use wget, fetch or an other download program or you can -override the merge() function to change the merge logic. -The function feeds() is called to fetch the feeds. By -default the function feed() is executed as a parallel -job to speedup updating. -.SH "FILES WRITTEN" -.TP 19n -\fIfeeds\fR -Tab-separated format containing all feeds. -The sfeed_update script merges new items with this file. -.TP 19n -\fIfeeds.new\fR -Temporary file used by sfeed_update to merge items. -.SH "EXAMPLES" -To update feeds and format the feeds file: -.nf -.sp -.RS 0n -sfeed_update "configfile" -sfeed_plain < $HOME/.sfeed/feeds > $HOME/.sfeed/feeds.txt -sfeed_html < $HOME/.sfeed/feeds > $HOME/.sfeed/feeds.html -.RE -.fi -.SH "SEE ALSO" -sfeed_html(1), -sfeed_plain(1), -sh(1) -.SH "AUTHORS" -Hiltjo Posthuma <\fIhiltjo@codemadness.org\fR> diff --git a/doc/man/sfeed_web.1 b/doc/man/sfeed_web.1 @@ -1,40 +0,0 @@ -.TH "SFEED_WEB" "1" "December 25, 2014" "" "General Commands Manual" -.nh -.if n .ad l -.SH "NAME" -\fBsfeed_web\fR -\- finds urls to feeds from a HTML webpage -.SH "SYNOPSIS" -.HP 10n -\fBsfeed_web\fR -[\fIbaseurl\fR] -.SH "DESCRIPTION" -\fBsfeed_web\fR -reads the HTML website as XML or HTML data from stdin and writes the found -urls to stdout. -.SH "OPTIONS" -.TP 10n -\fIbaseurl\fR -optional base url to use for found feed urls that are relative. -.SH "OUTPUT FORMAT" -content\-type<space>url<newline> -.TP 15n -\fIcontent\-type\fR -Usually application/atom+xml or application/rss+xml. -.TP 15n -\fIurl\fR -Found url to the feed. If the url is relative and the baseurl option is -specified then the url is changed accordingly. -.SH "EXAMPLES" -Get urls from xkcd website: -.nf -.sp -.RS 0n -wget http://www.xkcd.com -q -O - | sfeed_web "http://www.xkcd.com/" -.RE -.fi -.SH "SEE ALSO" -sfeed_update(1), -sh(1) -.SH "AUTHORS" -Hiltjo Posthuma <\fIhiltjo@codemadness.org\fR> diff --git a/doc/man/sfeed_xmlenc.1 b/doc/man/sfeed_xmlenc.1 @@ -1,25 +0,0 @@ -.TH "SFEED_XMLENC" "1" "December 25, 2014" "" "General Commands Manual" -.nh -.if n .ad l -.SH "NAME" -\fBsfeed_xmlenc\fR -\- get text\-encoding from XML -.SH "SYNOPSIS" -.HP 13n -\fBsfeed_xmlenc\fR -.SH "DESCRIPTION" -\fBsfeed_xmlenc\fR -reads XML data from stdin and writes the found text\-encoding to stdout. -.SH "EXAMPLES" -Get text\-encoding from xkcd Atom feed: -.nf -.sp -.RS 0n -wget http://www.xkcd.com/atom.xml -q -O - | sfeed_xmlenc -.RE -.fi -.SH "SEE ALSO" -sfeed_update(1), -sh(1) -.SH "AUTHORS" -Hiltjo Posthuma <\fIhiltjo@codemadness.org\fR> diff --git a/queue.h b/queue.h @@ -1,648 +0,0 @@ -/* $OpenBSD: queue.h,v 1.38 2013/07/03 15:05:21 fgsch Exp $ */ -/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * This file defines five types of data structures: singly-linked lists, - * lists, simple queues, tail queues, and circular queues. - * - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so elements can only be removed from the - * head of the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) -#define _Q_INVALIDATE(a) (a) = ((void *)-1) -#else -#define _Q_INVALIDATE(a) -#endif - -/* - * Singly-linked List definitions. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List access methods. - */ -#define SLIST_FIRST(head) ((head)->slh_first) -#define SLIST_END(head) NULL -#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_FOREACH(var, head, field) \ - for((var) = SLIST_FIRST(head); \ - (var) != SLIST_END(head); \ - (var) = SLIST_NEXT(var, field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST(head); \ - (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ - (var) = (tvar)) - -/* - * Singly-linked List functions. - */ -#define SLIST_INIT(head) { \ - SLIST_FIRST(head) = SLIST_END(head); \ -} - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (0) - -#define SLIST_REMOVE_AFTER(elm, field) do { \ - (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if ((head)->slh_first == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } else { \ - struct type *curelm = (head)->slh_first; \ - \ - while (curelm->field.sle_next != (elm)) \ - curelm = curelm->field.sle_next; \ - curelm->field.sle_next = \ - curelm->field.sle_next->field.sle_next; \ - _Q_INVALIDATE((elm)->field.sle_next); \ - } \ -} while (0) - -/* - * List definitions. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List access methods - */ -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_END(head) NULL -#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_FOREACH(var, head, field) \ - for((var) = LIST_FIRST(head); \ - (var)!= LIST_END(head); \ - (var) = LIST_NEXT(var, field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST(head); \ - (var) && ((tvar) = LIST_NEXT(var, field), 1); \ - (var) = (tvar)) - -/* - * List functions. - */ -#define LIST_INIT(head) do { \ - LIST_FIRST(head) = LIST_END(head); \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (0) - -#define LIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ -} while (0) - -#define LIST_REPLACE(elm, elm2, field) do { \ - if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ - (elm2)->field.le_next->field.le_prev = \ - &(elm2)->field.le_next; \ - (elm2)->field.le_prev = (elm)->field.le_prev; \ - *(elm2)->field.le_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ -} while (0) - -/* - * Simple queue definitions. - */ -#define SIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define SIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define SIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} - -/* - * Simple queue access methods. - */ -#define SIMPLEQ_FIRST(head) ((head)->sqh_first) -#define SIMPLEQ_END(head) NULL -#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) -#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - -#define SIMPLEQ_FOREACH(var, head, field) \ - for((var) = SIMPLEQ_FIRST(head); \ - (var) != SIMPLEQ_END(head); \ - (var) = SIMPLEQ_NEXT(var, field)) - -#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SIMPLEQ_FIRST(head); \ - (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ - (var) = (tvar)) - -/* - * Simple queue functions. - */ -#define SIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (0) - -#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (0) - -#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (0) - -#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ - if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ - == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (0) - -/* - * XOR Simple queue definitions. - */ -#define XSIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqx_first; /* first element */ \ - struct type **sqx_last; /* addr of last next element */ \ - unsigned long sqx_cookie; \ -} - -#define XSIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqx_next; /* next element */ \ -} - -/* - * XOR Simple queue access methods. - */ -#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ - (unsigned long)(ptr))) -#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) -#define XSIMPLEQ_END(head) NULL -#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) -#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) - - -#define XSIMPLEQ_FOREACH(var, head, field) \ - for ((var) = XSIMPLEQ_FIRST(head); \ - (var) != XSIMPLEQ_END(head); \ - (var) = XSIMPLEQ_NEXT(head, var, field)) - -#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = XSIMPLEQ_FIRST(head); \ - (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ - (var) = (tvar)) - -/* - * XOR Simple queue functions. - */ -#define XSIMPLEQ_INIT(head) do { \ - arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ - (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ -} while (0) - -#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqx_next = (head)->sqx_first) == \ - XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ - (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ -} while (0) - -#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ - *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ -} while (0) - -#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ - XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ - (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ -} while (0) - -#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ - (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ -} while (0) - -#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ - if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ - (elm)->field.sqx_next)->field.sqx_next) \ - == XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = \ - XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ -} while (0) - - -/* - * Tail queue definitions. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} - -/* - * tail queue access methods - */ -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_END(head) NULL -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -/* XXX */ -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_EMPTY(head) \ - (TAILQ_FIRST(head) == TAILQ_END(head)) - -#define TAILQ_FOREACH(var, head, field) \ - for((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_NEXT(var, field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head) && \ - ((tvar) = TAILQ_NEXT(var, field), 1); \ - (var) = (tvar)) - - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_PREV(var, headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head) && \ - ((tvar) = TAILQ_PREV(var, headname, field), 1); \ - (var) = (tvar)) - -/* - * Tail queue functions. - */ -#define TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ -} while (0) - -#define TAILQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ - (elm2)->field.tqe_next->field.tqe_prev = \ - &(elm2)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm2)->field.tqe_next; \ - (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ - *(elm2)->field.tqe_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ -} while (0) - -/* - * Circular queue definitions. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue access methods - */ -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) -#define CIRCLEQ_LAST(head) ((head)->cqh_last) -#define CIRCLEQ_END(head) ((void *)(head)) -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) -#define CIRCLEQ_EMPTY(head) \ - (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for((var) = CIRCLEQ_FIRST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_NEXT(var, field)) - -#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = CIRCLEQ_FIRST(head); \ - (var) != CIRCLEQ_END(head) && \ - ((tvar) = CIRCLEQ_NEXT(var, field), 1); \ - (var) = (tvar)) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for((var) = CIRCLEQ_LAST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_PREV(var, field)) - -#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = CIRCLEQ_LAST(head, headname); \ - (var) != CIRCLEQ_END(head) && \ - ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \ - (var) = (tvar)) - -/* - * Circular queue functions. - */ -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = CIRCLEQ_END(head); \ - (head)->cqh_last = CIRCLEQ_END(head); \ -} while (0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (listelm)->field.cqe_next->field.cqe_prev = (elm); \ - (listelm)->field.cqe_next = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (listelm)->field.cqe_prev->field.cqe_next = (elm); \ - (listelm)->field.cqe_prev = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = CIRCLEQ_END(head); \ - if ((head)->cqh_last == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (head)->cqh_first->field.cqe_prev = (elm); \ - (head)->cqh_first = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = CIRCLEQ_END(head); \ - (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (head)->cqh_last->field.cqe_next = (elm); \ - (head)->cqh_last = (elm); \ -} while (0) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ - _Q_INVALIDATE((elm)->field.cqe_prev); \ - _Q_INVALIDATE((elm)->field.cqe_next); \ -} while (0) - -#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ - CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm2); \ - else \ - (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ - if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ - CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm2); \ - else \ - (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ - _Q_INVALIDATE((elm)->field.cqe_prev); \ - _Q_INVALIDATE((elm)->field.cqe_next); \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ diff --git a/sfeed_stats.1 b/sfeed_stats.1 @@ -1,21 +0,0 @@ -.Dd January 3, 2015 -.Dt SFEED_STATS 1 -.Os -.Sh NAME -.Nm sfeed_stats -.Nd formats a feeds file to show a summary in plain text -.Sh SYNOPSIS -.Nm sfeed_stats -.Sh DESCRIPTION -.Nm -formats a feeds file (TSV) from -.Xr sfeed_update 1 -to a summary in plain text containing: the total amount of items, amount of new -items, the timestamp of the last item per feed. It reads TSV data from stdin -and writes formatted plain text to stdout. For the exact TSV format see -.Xr sfeed_update 1 . -.Sh SEE ALSO -.Xr sfeed 1 , -.Xr sfeed_update 1 -.Sh AUTHORS -.An Hiltjo Posthuma Aq Mt hiltjo@codemadness.org diff --git a/sfeed_stats.c b/sfeed_stats.c @@ -1,76 +0,0 @@ -#include <ctype.h> -#include <err.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include "queue.h" -#include "util.h" - -static SLIST_HEAD(fhead, feed) fhead = SLIST_HEAD_INITIALIZER(fhead); -static char *line = NULL; - -int -main(void) -{ - char *fields[FieldLast], timenewestformat[64] = ""; - unsigned long totalfeeds = 0, totalnew = 0, totalitems = 0; - unsigned int isnew; - struct feed *f, *fcur = NULL; - time_t parsedtime, comparetime, timenewest = 0; - size_t size = 0; - int r; - - /* 1 day is old news */ - comparetime = time(NULL) - 86400; - - if(!(fcur = calloc(1, sizeof(struct feed)))) - err(1, "calloc"); - SLIST_INSERT_HEAD(&fhead, fcur, entry); - - while(parseline(&line, &size, fields, FieldLast, '\t', stdin) > 0) { - r = strtotime(fields[FieldUnixTimestamp], &parsedtime); - isnew = (r != -1 && parsedtime >= comparetime) ? 1 : 0; - /* first of feed section or new feed section. */ - if(!totalfeeds || strcmp(fcur->name, fields[FieldFeedName])) { - if(!(f = calloc(1, sizeof(struct feed)))) - err(1, "calloc"); - if(!(f->name = strdup(fields[FieldFeedName]))) - err(1, "strdup"); - - SLIST_INSERT_AFTER(fcur, f, entry); - fcur = f; - - if(r != -1 && parsedtime > timenewest) { - timenewest = parsedtime; - strlcpy(timenewestformat, fields[FieldTimeFormatted], - sizeof(timenewestformat)); - } - if(r != -1 && parsedtime > fcur->timenewest) { - fcur->timenewest = parsedtime; - strlcpy(fcur->timenewestformat, fields[FieldTimeFormatted], - sizeof(fcur->timenewestformat)); - } - totalfeeds++; - } - totalnew += isnew; - fcur->totalnew += isnew; - fcur->total++; - totalitems++; - } - SLIST_FOREACH(f, &fhead, entry) { - if(!f->name || f->name[0] == '\0') - continue; - fprintf(stdout, "%c %-20.20s [%4lu/%-4lu]", - f->totalnew > 0 ? 'N' : ' ', - f->name, f->totalnew, f->total); - if(f->timenewestformat && f->timenewestformat[0]) - fprintf(stdout, " %s", f->timenewestformat); - putchar('\n'); - } - printf(" ================================\n"); - printf("%c %-20.20s [%4lu/%-4lu] %s\n", totalnew > 0 ? 'N' : ' ', "Total:", - totalnew, totalitems, timenewestformat); - return 0; -}