1135446Strhodes/*- 2224092Sdougb * Copyright (c) 2007 Sam Leffler, Errno Consulting 3135446Strhodes * All rights reserved. 4135446Strhodes * 5193149Sdougb * Redistribution and use in source and binary forms, with or without 6135446Strhodes * modification, are permitted provided that the following conditions 7135446Strhodes * are met: 8135446Strhodes * 1. Redistributions of source code must retain the above copyright 9135446Strhodes * notice, this list of conditions and the following disclaimer, 10135446Strhodes * without modification. 11135446Strhodes * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12135446Strhodes * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13135446Strhodes * redistribution must be conditioned upon including a substantially 14135446Strhodes * similar Disclaimer requirement for further binary redistribution. 15135446Strhodes * 16135446Strhodes * NO WARRANTY 17135446Strhodes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18234010Sdougb * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19135446Strhodes * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20135446Strhodes * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21135446Strhodes * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22135446Strhodes * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23135446Strhodes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24135446Strhodes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25135446Strhodes * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26135446Strhodes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27135446Strhodes * THE POSSIBILITY OF SUCH DAMAGES. 28135446Strhodes * 29135446Strhodes * $FreeBSD$ 30135446Strhodes */ 31135446Strhodes 32135446Strhodes#include <stdio.h> 33135446Strhodes#include <string.h> 34135446Strhodes 35135446Strhodes#include "statfoo.h" 36135446Strhodes 37135446Strhodesstatic void 38135446Strhodesstatfoo_setfmt(struct statfoo *sf, const char *fmt0) 39135446Strhodes{ 40135446Strhodes#define N(a) (sizeof(a)/sizeof(a[0])) 41135446Strhodes char fmt[4096]; 42135446Strhodes char *fp, *tok; 43135446Strhodes int i, j; 44135446Strhodes 45135446Strhodes j = 0; 46135446Strhodes strlcpy(fmt, fmt0, sizeof(fmt)); 47135446Strhodes for (fp = fmt; (tok = strsep(&fp, ", ")) != NULL;) { 48135446Strhodes for (i = 0; i < sf->nstats; i++) 49135446Strhodes if (strcasecmp(tok, sf->stats[i].name) == 0) 50135446Strhodes break; 51135446Strhodes if (i >= sf->nstats) { 52135446Strhodes fprintf(stderr, "%s: unknown statistic name \"%s\" " 53135446Strhodes "skipped\n", sf->name, tok); 54135446Strhodes continue; 55135446Strhodes } 56135446Strhodes if (j+3 > sizeof(sf->fmts)) { 57135446Strhodes fprintf(stderr, "%s: not enough room for all stats; " 58135446Strhodes "stopped at %s\n", sf->name, tok); 59135446Strhodes break; 60135446Strhodes } 61135446Strhodes if (j != 0) 62135446Strhodes sf->fmts[j++] = ' '; 63135446Strhodes sf->fmts[j++] = 0x80 | i; 64135446Strhodes } 65135446Strhodes sf->fmts[j] = '\0'; 66135446Strhodes#undef N 67135446Strhodes} 68135446Strhodes 69135446Strhodesstatic void 70135446Strhodesstatfoo_collect(struct statfoo *sf) 71135446Strhodes{ 72135446Strhodes fprintf(stderr, "%s: don't know how to collect data\n", sf->name); 73135446Strhodes} 74135446Strhodes 75135446Strhodesstatic void 76135446Strhodesstatfoo_update_tot(struct statfoo *sf) 77135446Strhodes{ 78135446Strhodes fprintf(stderr, "%s: don't know how to update total data\n", sf->name); 79135446Strhodes} 80135446Strhodes 81135446Strhodesstatic int 82135446Strhodesstatfoo_get(struct statfoo *sf, int s, char b[], size_t bs) 83135446Strhodes{ 84135446Strhodes fprintf(stderr, "%s: don't know how to get stat #%u\n", sf->name, s); 85135446Strhodes return 0; 86135446Strhodes} 87135446Strhodes 88135446Strhodesstatic void 89135446Strhodesstatfoo_print_header(struct statfoo *sf, FILE *fd) 90135446Strhodes{ 91135446Strhodes const unsigned char *cp; 92135446Strhodes 93135446Strhodes for (cp = sf->fmts; *cp != '\0'; cp++) { 94135446Strhodes if (*cp & 0x80) { 95135446Strhodes const struct fmt *f = &sf->stats[*cp &~ 0x80]; 96135446Strhodes fprintf(fd, "%*s", f->width, f->label); 97135446Strhodes } else 98135446Strhodes putc(*cp, fd); 99135446Strhodes } 100135446Strhodes putc('\n', fd); 101135446Strhodes} 102135446Strhodes 103135446Strhodesstatic void 104135446Strhodesstatfoo_print_current(struct statfoo *sf, FILE *fd) 105135446Strhodes{ 106135446Strhodes char buf[32]; 107135446Strhodes const unsigned char *cp; 108135446Strhodes 109135446Strhodes for (cp = sf->fmts; *cp != '\0'; cp++) { 110135446Strhodes if (*cp & 0x80) { 111135446Strhodes const struct fmt *f = &sf->stats[*cp &~ 0x80]; 112135446Strhodes if (sf->get_curstat(sf, *cp &~ 0x80, buf, sizeof(buf))) 113135446Strhodes fprintf(fd, "%*s", f->width, buf); 114135446Strhodes } else 115135446Strhodes putc(*cp, fd); 116135446Strhodes } 117135446Strhodes putc('\n', fd); 118135446Strhodes} 119135446Strhodes 120135446Strhodesstatic void 121135446Strhodesstatfoo_print_total(struct statfoo *sf, FILE *fd) 122135446Strhodes{ 123135446Strhodes char buf[32]; 124135446Strhodes const unsigned char *cp; 125135446Strhodes 126135446Strhodes for (cp = sf->fmts; *cp != '\0'; cp++) { 127135446Strhodes if (*cp & 0x80) { 128135446Strhodes const struct fmt *f = &sf->stats[*cp &~ 0x80]; 129135446Strhodes if (sf->get_totstat(sf, *cp &~ 0x80, buf, sizeof(buf))) 130135446Strhodes fprintf(fd, "%*s", f->width, buf); 131135446Strhodes } else 132135446Strhodes putc(*cp, fd); 133135446Strhodes } 134135446Strhodes putc('\n', fd); 135135446Strhodes} 136135446Strhodes 137135446Strhodesstatic void 138135446Strhodesstatfoo_print_verbose(struct statfoo *sf, FILE *fd) 139135446Strhodes{ 140135446Strhodes char s[32]; 141135446Strhodes int i; 142135446Strhodes 143135446Strhodes for (i = 0; i < sf->nstats; i++) { 144135446Strhodes if (sf->get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) 145135446Strhodes fprintf(fd, "%s %s\n", s, sf->stats[i].desc); 146135446Strhodes } 147135446Strhodes} 148135446Strhodes 149135446Strhodesstatic void 150135446Strhodesstatfoo_print_fields(struct statfoo *sf, FILE *fd) 151135446Strhodes{ 152135446Strhodes int i, w, width; 153135446Strhodes 154135446Strhodes width = 0; 155135446Strhodes for (i = 0; i < sf->nstats; i++) { 156135446Strhodes w = strlen(sf->stats[i].name); 157135446Strhodes if (w > width) 158135446Strhodes width = w; 159135446Strhodes } 160135446Strhodes for (i = 0; i < sf->nstats; i++) { 161135446Strhodes const struct fmt *f = &sf->stats[i]; 162135446Strhodes if (f->width != 0) 163135446Strhodes fprintf(fd, "%-*s %s\n", width, f->name, f->desc); 164135446Strhodes } 165135446Strhodes} 166135446Strhodes 167135446Strhodesvoid 168135446Strhodesstatfoo_init(struct statfoo *sf, const char *name, const struct fmt *stats, int nstats) 169135446Strhodes{ 170135446Strhodes sf->name = name; 171135446Strhodes sf->stats = stats; 172135446Strhodes sf->nstats = nstats; 173135446Strhodes sf->setfmt = statfoo_setfmt; 174135446Strhodes sf->collect_cur = statfoo_collect; 175135446Strhodes sf->collect_tot = statfoo_collect; 176135446Strhodes sf->update_tot = statfoo_update_tot; 177135446Strhodes sf->get_curstat = statfoo_get; 178135446Strhodes sf->get_totstat = statfoo_get; 179135446Strhodes sf->print_header = statfoo_print_header; 180135446Strhodes sf->print_current = statfoo_print_current; 181135446Strhodes sf->print_total = statfoo_print_total; 182135446Strhodes sf->print_verbose = statfoo_print_verbose; 183135446Strhodes sf->print_fields = statfoo_print_fields; 184135446Strhodes} 185135446Strhodes