+++ /dev/null
-/* -*-c-*-
- *
- * Progress indicators for command-line tools
- *
- * (c) 2011 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of Catacomb.
- *
- * Catacomb is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * Catacomb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with Catacomb; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _FILE_OFFSET_BITS 64
-
-#include "config.h"
-
-#include "cc.h"
-
-#ifndef PATHSEP
-# if defined(__riscos)
-# define PATHSEP '.'
-# elif defined(__unix) || defined(unix)
-# define PATHSEP '/'
-# else
-# define PATHSEP '\\'
-# endif
-#endif
-
-/*----- Static data -------------------------------------------------------*/
-
-static const char baton[] = "-\\|/";
-
-/*----- Human-friendly unit printing --------------------------------------*/
-
-struct unit {
- const char *name;
- int m;
-};
-
-/* --- @prhuman_time@ --- *
- *
- * Arguments: @FILE *fp@ = stream to print on
- * @unsigned long n@ = time in seconds to print
- *
- * Returns: ---
- *
- * Use: Prints a time in some reasonable format. The time takes up
- * PRHUMAN_TIMEWD character spaces.
- */
-
-#define PRHUMAN_TIMEWD 7
-
-static void prhuman_time(FILE *fp, unsigned long n)
-{
- const static struct unit utime[] = {
- { "s", 60 }, { "m", 60 }, { "h", 24 }, { "d", 0 }
- };
-
- unsigned long m = 0;
- const struct unit *u = utime;
-
- while (u[1].m && n > u[0].m*u[1].m) { n /= u->m; u++; }
- m = n / u[1].m; n %= u[0].m;
- if (m) fprintf(fp, "%3lu%s%02lu%s", m, u[1].name, n, u[0].name);
- else fprintf(fp, " %2lu%s", n, u[0].name);
-}
-
-/* --- @prhuman_data@ --- *
- *
- * Arguments: @FILE *fp@ = file to print on
- * @off_t n@ = size to be printed
- *
- * Returns: ---
- *
- * Use: Prints a data size in some reasonable format. The data size
- * takes up PRHUMAN_DATAWD character spaces.
- */
-
-#define PRHUMAN_DATAWD 7
-
-static void prhuman_data(FILE *fp, off_t n)
-{
- const static struct unit udata[] = {
- { " ", 1024 }, { "k", 1024 }, { "M", 1024 }, { "G", 1024 },
- { "T", 1024 }, { "P", 1024 }, { "E", 1024 }, { "Z", 1024 },
- { "Y", 0 }
- };
-
- double x = n;
- const struct unit *u = udata;
-
- while (u->m && x >= u->m) { x /= u->m; u++; }
- fprintf(fp, "%6.1f%s", x, u->name);
-}
-
-/*----- Main code ---------------------------------------------------------*/
-
-#define BARWD 16
-
-/* --- @fprogress_init@ --- *
- *
- * Arguments: @fprogress *f@ = progress context to be initialized
- * @const char *name@ = file name string to show
- * @FILE *fp@ = file we're reading from
- *
- * Returns: Zero on success, nonzero if the file's state is now broken.
- *
- * Use: Initializes a progress context. Nothing is actually
- * displayed yet.
- */
-
-int fprogress_init(fprogress *f, const char *name, FILE *fp)
-{
- const char *p;
- off_t o, sz = -1;
- size_t n;
-
- /* --- Set up the offset --- */
-
- if ((o = ftello(fp)) >= 0 &&
- fseeko(fp, 0, SEEK_END) >= 0 &&
- (sz = ftello(fp),
- fseeko(fp, o, SEEK_SET) < 0))
- return (-1);
- if (o != -1 && sz != -1) sz -= o;
- f->o = f->olast = 0; f->sz = sz;
-
- /* --- Set up the file name --- */
-
- n = strlen(name);
- if (n < sizeof(f->name))
- strcpy(f->name, name);
- else if ((p = strchr(name + n - sizeof(f->name) + 4, PATHSEP)) != 0)
- sprintf(f->name, "...%s", p);
- else {
- p = strrchr(name, PATHSEP);
- if (!p) sprintf(f->name, "%.*s...", (int)sizeof(f->name) - 4, name);
- else sprintf(f->name, "...%.*s...", (int)sizeof(f->name) - 7, p);
- }
-
- /* --- Set up some other stuff --- */
-
- f->start = f->last = time(0);
- f->bp = baton;
-
- /* --- Done --- */
-
- return (0);
-}
-
-/* --- @fprogress_clear@ --- *
- *
- * Arguments: @fprogress *f@ = progress context
- *
- * Returns: ---
- *
- * Use: Clears the progress display from the screen.
- */
-
-void fprogress_clear(fprogress *f)
-{
- fprintf(stderr, "\r%*s\r",
- sizeof(f->name) + 2*PRHUMAN_DATAWD + PRHUMAN_TIMEWD + BARWD + 16,
- "");
-}
-
-/* --- @fprogress_update@ --- *
- *
- * Arguments: @fprogress *f@ = progress context
- * @size_t n@ = how much progress has been made
- *
- * Returns: ---
- *
- * Use: Maybe updates the display to show that some progress has been
- * made.
- */
-
-void fprogress_update(fprogress *f, size_t sz)
-{
- time_t now = time(0);
- int i, n;
-
- /* --- See if there's anything to do --- */
-
- f->o += sz;
- if (difftime(now, f->last) < 1) return;
- f->last = now;
-
- /* --- See if we're going to lose the ETA and percentage indicators --- */
-
- if (f->olast < f->sz && f->o > f->sz) fprogress_clear(f);
- f->olast = f->o;
-
- /* --- Do the initial display --- */
-
- fprintf(stderr, "\r%-*s%c ",
- (int)sizeof(f->name), f->name,
- *f->bp++);
- if (!*f->bp) f->bp = baton;
- prhuman_data(stderr, f->o);
-
- /* --- More complicated display if we have a set size --- */
-
- if (f->sz > f->o) {
- fputc('/', stderr);
- prhuman_data(stderr, f->sz);
- fputs(" [", stderr);
- n = (f->o*BARWD + f->sz/2)/f->sz;
- for (i = 0; i < n; i++) fputc('.', stderr);
- fprintf(stderr, "%*s] %3d%% ETA ", BARWD - n, "",
- (int)((f->o*100 + 50)/f->sz));
- prhuman_time(stderr, difftime(now, f->start)*(f->sz - f->o)/f->o);
- }
-}
-
-/* --- @fprogress_done@ --- *
- *
- * Arguments: @fprogress *f@ = progress context
- *
- * Returns: ---
- *
- * Use: Clear up the progress context and removes any display.
- */
-
-void fprogress_done(fprogress *f) { fprogress_clear(f); }
-
-/*----- That's all, folks -------------------------------------------------*/