1236834Sadrian/*-
2236834Sadrian * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
3236834Sadrian * All rights reserved.
4236834Sadrian *
5236834Sadrian * Redistribution and use in source and binary forms, with or without
6236834Sadrian * modification, are permitted provided that the following conditions
7236834Sadrian * are met:
8236834Sadrian * 1. Redistributions of source code must retain the above copyright
9236834Sadrian *    notice, this list of conditions and the following disclaimer,
10236834Sadrian *    without modification.
11236834Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12236834Sadrian *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13236834Sadrian *    redistribution must be conditioned upon including a substantially
14236834Sadrian *    similar Disclaimer requirement for further binary redistribution.
15236834Sadrian *
16236834Sadrian * NO WARRANTY
17236834Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18236834Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19236834Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20236834Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21236834Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22236834Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23236834Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24236834Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25236834Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26236834Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27236834Sadrian * THE POSSIBILITY OF SUCH DAMAGES.
28236834Sadrian *
29236834Sadrian * $FreeBSD$
30236834Sadrian */
31236834Sadrian
32236834Sadrian#include <stdio.h>
33236834Sadrian#include <string.h>
34236834Sadrian
35236834Sadrian#include "statfoo.h"
36236834Sadrian
37236834Sadrianstatic void
38236834Sadrianstatfoo_setfmt(struct statfoo *sf, const char *fmt0)
39236834Sadrian{
40236834Sadrian#define	N(a)	(sizeof(a)/sizeof(a[0]))
41236834Sadrian	char fmt[4096];
42236834Sadrian	char *fp, *tok;
43236834Sadrian	int i, j;
44236834Sadrian
45236834Sadrian	j = 0;
46236834Sadrian	strlcpy(fmt, fmt0, sizeof(fmt));
47236834Sadrian	for (fp = fmt; (tok = strsep(&fp, ", ")) != NULL;) {
48236834Sadrian		for (i = 0; i < sf->nstats; i++)
49236834Sadrian			if (strcasecmp(tok, sf->stats[i].name) == 0)
50236834Sadrian				break;
51236834Sadrian		if (i >= sf->nstats) {
52236834Sadrian			fprintf(stderr, "%s: unknown statistic name \"%s\" "
53236834Sadrian				"skipped\n", sf->name, tok);
54236834Sadrian			continue;
55236834Sadrian		}
56236834Sadrian		if (j+3 > sizeof(sf->fmts)) {
57236834Sadrian			fprintf(stderr, "%s: not enough room for all stats; "
58236834Sadrian				"stopped at %s\n", sf->name, tok);
59236834Sadrian			break;
60236834Sadrian		}
61236834Sadrian		if (j != 0)
62236834Sadrian			sf->fmts[j++] = ' ';
63236834Sadrian		sf->fmts[j++] = FMTS_IS_STAT;
64236834Sadrian		sf->fmts[j++] = i & 0xff;
65236834Sadrian		sf->fmts[j++] = (i >> 8) & 0xff;
66236834Sadrian	}
67236834Sadrian	sf->fmts[j] = '\0';
68236834Sadrian#undef N
69236834Sadrian}
70236834Sadrian
71236834Sadrianstatic void
72236834Sadrianstatfoo_collect(struct statfoo *sf)
73236834Sadrian{
74236834Sadrian	fprintf(stderr, "%s: don't know how to collect data\n", sf->name);
75236834Sadrian}
76236834Sadrian
77236834Sadrianstatic void
78236834Sadrianstatfoo_update_tot(struct statfoo *sf)
79236834Sadrian{
80236834Sadrian	fprintf(stderr, "%s: don't know how to update total data\n", sf->name);
81236834Sadrian}
82236834Sadrian
83236834Sadrianstatic int
84236834Sadrianstatfoo_get(struct statfoo *sf, int s, char b[], size_t bs)
85236834Sadrian{
86236834Sadrian	fprintf(stderr, "%s: don't know how to get stat #%u\n", sf->name, s);
87236834Sadrian	return 0;
88236834Sadrian}
89236834Sadrian
90236834Sadrianstatic void
91236834Sadrianstatfoo_print_header(struct statfoo *sf, FILE *fd)
92236834Sadrian{
93236834Sadrian	const unsigned char *cp;
94236834Sadrian	int i;
95236834Sadrian	const struct fmt *f;
96236834Sadrian
97236834Sadrian	for (cp = sf->fmts; *cp != '\0'; cp++) {
98236834Sadrian		if (*cp == FMTS_IS_STAT) {
99236834Sadrian			i = *(++cp);
100236834Sadrian			i |= ((int) *(++cp)) << 8;
101236834Sadrian			f = &sf->stats[i];
102236834Sadrian			fprintf(fd, "%*s", f->width, f->label);
103236834Sadrian		} else
104236834Sadrian			putc(*cp, fd);
105236834Sadrian	}
106236834Sadrian	putc('\n', fd);
107236834Sadrian}
108236834Sadrian
109236834Sadrianstatic void
110236834Sadrianstatfoo_print_current(struct statfoo *sf, FILE *fd)
111236834Sadrian{
112236834Sadrian	char buf[32];
113236834Sadrian	const unsigned char *cp;
114236834Sadrian	int i;
115236834Sadrian	const struct fmt *f;
116236834Sadrian
117236834Sadrian	for (cp = sf->fmts; *cp != '\0'; cp++) {
118236834Sadrian		if (*cp == FMTS_IS_STAT) {
119236834Sadrian			i = *(++cp);
120236834Sadrian			i |= ((int) *(++cp)) << 8;
121236834Sadrian			f = &sf->stats[i];
122236834Sadrian			if (sf->get_curstat(sf, i, buf, sizeof(buf)))
123236834Sadrian				fprintf(fd, "%*s", f->width, buf);
124236834Sadrian		} else
125236834Sadrian			putc(*cp, fd);
126236834Sadrian	}
127236834Sadrian	putc('\n', fd);
128236834Sadrian}
129236834Sadrian
130236834Sadrianstatic void
131236834Sadrianstatfoo_print_total(struct statfoo *sf, FILE *fd)
132236834Sadrian{
133236834Sadrian	char buf[32];
134236834Sadrian	const unsigned char *cp;
135236834Sadrian	const struct fmt *f;
136236834Sadrian	int i;
137236834Sadrian
138236834Sadrian	for (cp = sf->fmts; *cp != '\0'; cp++) {
139236834Sadrian		if (*cp == FMTS_IS_STAT) {
140236834Sadrian			i = *(++cp);
141236834Sadrian			i |= ((int) *(++cp)) << 8;
142236834Sadrian			f = &sf->stats[i];
143236834Sadrian			if (sf->get_totstat(sf, i, buf, sizeof(buf)))
144236834Sadrian				fprintf(fd, "%*s", f->width, buf);
145236834Sadrian		} else
146236834Sadrian			putc(*cp, fd);
147236834Sadrian	}
148236834Sadrian	putc('\n', fd);
149236834Sadrian}
150236834Sadrian
151236834Sadrianstatic void
152236834Sadrianstatfoo_print_verbose(struct statfoo *sf, FILE *fd)
153236834Sadrian{
154236834Sadrian	const struct fmt *f;
155236834Sadrian	char s[32];
156236834Sadrian	int i, width;
157236834Sadrian
158236834Sadrian	width = 0;
159236834Sadrian	for (i = 0; i < sf->nstats; i++) {
160236834Sadrian		f = &sf->stats[i];
161236834Sadrian		if (f->width > width)
162236834Sadrian			width = f->width;
163236834Sadrian	}
164236834Sadrian	for (i = 0; i < sf->nstats; i++) {
165236834Sadrian		f = &sf->stats[i];
166236834Sadrian		if (sf->get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0"))
167236834Sadrian			fprintf(fd, "%-*s %s\n", width, s, f->desc);
168236834Sadrian	}
169236834Sadrian}
170236834Sadrian
171236834Sadrianstatic void
172236834Sadrianstatfoo_print_fields(struct statfoo *sf, FILE *fd)
173236834Sadrian{
174236834Sadrian	int i, w, width;
175236834Sadrian
176236834Sadrian	width = 0;
177236834Sadrian	for (i = 0; i < sf->nstats; i++) {
178236834Sadrian		w = strlen(sf->stats[i].name);
179236834Sadrian		if (w > width)
180236834Sadrian			width = w;
181236834Sadrian	}
182236834Sadrian	for (i = 0; i < sf->nstats; i++) {
183236834Sadrian		const struct fmt *f = &sf->stats[i];
184236834Sadrian		if (f->width != 0)
185236834Sadrian			fprintf(fd, "%-*s %s\n", width, f->name, f->desc);
186236834Sadrian	}
187236834Sadrian}
188236834Sadrian
189236834Sadrianvoid
190236834Sadrianstatfoo_init(struct statfoo *sf, const char *name, const struct fmt *stats, int nstats)
191236834Sadrian{
192236834Sadrian	sf->name = name;
193236834Sadrian	sf->stats = stats;
194236834Sadrian	sf->nstats = nstats;
195236834Sadrian	sf->setfmt = statfoo_setfmt;
196236834Sadrian	sf->collect_cur = statfoo_collect;
197236834Sadrian	sf->collect_tot = statfoo_collect;
198236834Sadrian	sf->update_tot = statfoo_update_tot;
199236834Sadrian	sf->get_curstat = statfoo_get;
200236834Sadrian	sf->get_totstat = statfoo_get;
201236834Sadrian	sf->print_header = statfoo_print_header;
202236834Sadrian	sf->print_current = statfoo_print_current;
203236834Sadrian	sf->print_total = statfoo_print_total;
204236834Sadrian	sf->print_verbose = statfoo_print_verbose;
205236834Sadrian	sf->print_fields = statfoo_print_fields;
206236834Sadrian}
207