t* sacc + cursorline and uri preview
       
   URI git clone git://git.codevoid.de/sacc-sdk
   DIR Log
   DIR Files
   DIR Refs
   DIR LICENSE
       ---
   DIR commit 4691af5361b43138f257b19b23c89199cff210dc
   DIR parent 8a7bc011a62ba737e6fb1fe7c84ca2fa1a20eb31
   URI Author: Quentin Rameau <quinq@fifth.space>
       Date:   Fri, 23 Jun 2017 20:37:27 +0200
       
       Better error handling, add an item parsing function
       
       Diffstat:
         M sacc.c                              |      99 +++++++++++++++++++++-----------
       
       1 file changed, 66 insertions(+), 33 deletions(-)
       ---
   DIR diff --git a/sacc.c b/sacc.c
       t@@ -189,34 +189,63 @@ display(Item *item)
        }
        
        char *
       -pickfield(char **s)
       +pickfield(char **raw, char sep)
        {
       -        char *c, *f = *s;
       +        char *c, *f = *raw;
        
       -        /* loop until we reach the end of the string, or a tab, or CRLF */
       -        for (c = *s; *c; ++c) {
       +        for (c = *raw; *c != sep; ++c) {
                        switch (*c) {
                        case '\t':
       -                        break;
       -                case '\r': /* FALLTHROUGH */
       -                        if (*(c+1) == '\n') {
       -                                *c++ = '\0';
       -                                break;
       -                        }
       +                        if (sep == '\r')
       +                                *c = '\0';
       +                case '\n':
       +                case '\r':
       +                case '\0':
       +                        return NULL;
                        default:
                                continue;
                        }
                        break;
                }
        
       -        if (!*c)
       -                die("Can't parse directory item: %s", f);
                *c = '\0';
       -        *s = c+1;
       +        *raw = c+1;
        
                return f;
        }
        
       +Item *
       +molditem(char **raw)
       +{
       +        Item *item;
       +        char type, *username, *selector, *host, *port;
       +
       +        if (!*raw)
       +                return NULL;
       +
       +        if (!(type = *raw[0]++) ||
       +            !(username = pickfield(raw, '\t')) ||
       +            !(selector = pickfield(raw, '\t')) ||
       +            !(host = pickfield(raw, '\t')) ||
       +            !(port = pickfield(raw, '\r')) ||
       +            *raw[0]++ != '\n')
       +                return NULL;
       +
       +        item = xmalloc(sizeof(Item));
       +
       +        item->type = type;
       +        item->username = username;
       +        item->selector = selector;
       +        item->host = host;
       +        item->port = port;
       +        item->raw = NULL;
       +        item->dir = NULL;
       +        item->entry = NULL;
       +        item->printoff = 0;
       +
       +        return item;
       +}
       +
        Dir *
        molddiritem(char *raw)
        {
       t@@ -230,27 +259,25 @@ molddiritem(char *raw)
                if (--nitems < 1)
                        return NULL;
                if (strcmp(crlf-3, ".\r\n"))
       -                return NULL;
       +                fprintf(stderr, "Parsing error: missing .\\r\\n last line\n");
        
                dir = xmalloc(sizeof(Dir));
                items = xreallocarray(items, nitems, sizeof(Item*));
        
                for (i = 0; i < nitems; ++i) {
       -                item = xmalloc(sizeof(Item));
       -
       -                item->type = *raw++;
       -                item->username = pickfield(&raw);
       -                item->selector = pickfield(&raw);
       -                item->host = pickfield(&raw);
       -                item->port = pickfield(&raw);
       -                item->printoff = 0;
       -                item->raw = NULL;
       -                item->entry = NULL;
       -                item->dir = NULL;
       -
       -                items[i] = item;
       +                if (item = molditem(&raw)) {
       +                        items[i] = item;
       +                } else {
       +                        fprintf(stderr, "Parsing error: dir entity: %d\n", i+1);
       +                        items = xreallocarray(items, i, sizeof(Item*));
       +                        nitems = i;
       +                        break;
       +                }
                }
        
       +        if (!items)
       +                return NULL;
       +
                dir->items = items;
                dir->nitems = nitems;
        
       t@@ -344,29 +371,35 @@ dig(Item *entry, Item *item)
        {
                int sock;
        
       -        if (item->raw)     /* already in cache */
       +        if (item->raw) /* already in cache */
                        return 1;
        
                if (!item->entry)
                        item->entry = entry;
        
       -        if (item->type > '1') /* not supported */
       +        if (item->type > '1') {
       +                fprintf(stderr, "Type %c not supported\n", item->type);
                        return 0;
       +        }
        
                sock = connectto(item->host, item->port);
                sendselector(sock, item->selector);
                item->raw = getrawitem(sock);
                close(sock);
        
       -        if (!*item->raw) {    /* empty read */
       +        if (!*item->raw) {
       +                fputs("Empty response from server\n", stderr);
                        free(item->raw);
                        item->raw = NULL;
                        return 0;
                }
        
       -        if (item->type == '1' &&
       -            !(item->dir = molddiritem(item->raw)))
       -                return 0;
       +        if (item->type == '1') {
       +                if (!(item->dir = molddiritem(item->raw))) {
       +                        fputs("Couldn't parse dir item\n", stderr);
       +                        return 0;
       +                }
       +        }
                return 1;
        }