[Dctrl-tools-devel] CVS dctrl-tools

CVS User ajk ajk at haydn.debian.org
Thu Jul 21 09:53:18 UTC 2005


Update of /cvsroot/dctrl-tools/dctrl-tools
In directory haydn:/tmp/cvs-serv18832

Modified Files:
	Makefile fsaf.c fsaf.h grep-dctrl.c para_bundle.c 
Added Files:
	tbl-dctrl.c 
Log Message:
new program tbl-dctrl and assorted fixes

--- /cvsroot/dctrl-tools/dctrl-tools/Makefile	2005/06/08 21:33:54	1.25
+++ /cvsroot/dctrl-tools/dctrl-tools/Makefile	2005/07/21 09:53:18	1.26
@@ -19,7 +19,7 @@
          fieldtrie.o rc.o strutil.o getaline.o fnutil.o para_pool.o \
 	 ifile.o para_bundle.o sorter.o version.o
 
-obj = $(libobj) grep-dctrl.o sort-dctrl.o
+obj = $(libobj) grep-dctrl.o sort-dctrl.o tbl-dctrl.o
 src = $(obj:.o=.c)
 
 LDLIBS = -L. -ldctrl
@@ -27,7 +27,8 @@
 # List of translated languages is given in langs.mk
 include langs.mk
 
-all : grep-dctrl sort-dctrl sync-available grep-dctrl.1 sort-dctrl.1 mo
+all :	grep-dctrl sort-dctrl tbl-dctrl sync-available \
+	grep-dctrl.1 sort-dctrl.1 mo
 
 pot : po/dctrl-tools.pot
 
@@ -39,6 +40,8 @@
 
 sort-dctrl : sort-dctrl.o libdctrl.a
 
+tbl-dctrl : tbl-dctrl.o libdctrl.a
+
 % : %.o
 	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS)
 
--- /cvsroot/dctrl-tools/dctrl-tools/fsaf.c	2004/07/15 17:07:57	1.5
+++ /cvsroot/dctrl-tools/dctrl-tools/fsaf.c	2005/07/21 09:53:18	1.6
@@ -1,5 +1,5 @@
 /*  dctrl-tools - Debian control file inspection tools
-    Copyright (C) 2003 Antti-Juhani Kaijanaho
+    Copyright (C) 2003, 2005 Antti-Juhani Kaijanaho
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -35,11 +35,13 @@
 
 #define READAHEAD 1
 
-FSAF * fsaf_fdopen(int fd)
+FSAF * fsaf_fdopen(int fd, char const *fname)
 {
 	FSAF * rv = malloc(sizeof *rv);
 	if (rv == 0) { errno = ENOMEM; return 0; }
 
+	rv->fname = strdup(fname);
+	if (rv->fname == NULL) { errno = ENOMEM; free(rv); return 0; }
 	rv->fd = fd;
 	rv->eof_mark = (size_t)(-1);
 	rv->buf = 0;
@@ -91,6 +93,7 @@
 		return;
 	}
 #endif
+	free(fp->fname);
 	free(fp->buf);
 	free(fp);
 }
--- /cvsroot/dctrl-tools/dctrl-tools/fsaf.h	2004/07/15 17:07:57	1.5
+++ /cvsroot/dctrl-tools/dctrl-tools/fsaf.h	2005/07/21 09:53:18	1.6
@@ -1,5 +1,5 @@
 /*  dctrl-tools - Debian control file inspection tools
-    Copyright (C) 2003 Antti-Juhani Kaijanaho
+    Copyright (C) 2003, 2005 Antti-Juhani Kaijanaho
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
 /* FAST (MOSTLY) SEQUENTIAL-ACCESS FILE LAYER */
 
 struct fsaf_private {
+	char *fname;
 	int fd;
 	char * buf;
 	size_t buf_capacity;
@@ -44,7 +45,7 @@
 
 /* Open a FSAF for the given fd. Only read access is supported for
  * now.  The whole file is initially valid.  */
-FSAF * fsaf_fdopen(int fd);
+FSAF * fsaf_fdopen(int fd, char const *fname);
 
 /* Close the given FSAF.  This DOES NOT close the underlying fd.  */
 void fsaf_close(FSAF *);
--- /cvsroot/dctrl-tools/dctrl-tools/grep-dctrl.c	2005/06/08 18:13:29	1.31
+++ /cvsroot/dctrl-tools/dctrl-tools/grep-dctrl.c	2005/07/21 09:53:18	1.32
@@ -770,7 +770,7 @@
 
 		if (!chk_ifile(fname, fd)) break;
 
-		FSAF * fp = fsaf_fdopen(fd);
+		FSAF * fp = fsaf_fdopen(fd, fname.s);
 		para_parser_t pp;
 		para_parser_init(&pp, fp, true);
 		para_t para;
--- /cvsroot/dctrl-tools/dctrl-tools/para_bundle.c	2004/08/02 04:19:57	1.2
+++ /cvsroot/dctrl-tools/dctrl-tools/para_bundle.c	2005/07/21 09:53:18	1.3
@@ -22,12 +22,12 @@
 void bundle_slurp(struct para_bundle * pb, struct ifile ifi)
 {
 	int fd = open_ifile(ifi);
-	if (fd == 0) {
+	if (fd == -1) {
 		record_error();
 		return;
 	}
 	
-	FSAF * f = fsaf_fdopen(fd);
+	FSAF * f = fsaf_fdopen(fd, ifi.s);
 	if (f == 0) fatal_enomem(0);
 
 	struct srcfile * sf = malloc(sizeof *sf);

--- /cvsroot/dctrl-tools/dctrl-tools/tbl-dctrl.c	2005/07/21 09:53:18	NONE
+++ /cvsroot/dctrl-tools/dctrl-tools/tbl-dctrl.c	2005/07/21 09:53:18	1.1
/*  dctrl-tools - Debian control file inspection tools
    Copyright (C) 2005 Antti-Juhani Kaijanaho

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <argp.h>
#include <locale.h>
#include <stdlib.h>
#include "misc.h"
#include "msg.h"
#include "i18n.h"
#include "ifile.h"
#include "para_bundle.h"
#include "sorter.h"

#define OPT_SILENT 256

const char * argp_program_version = "tbl-dctrl (dctrl-tools) " VERSION;
const char * argp_program_bug_address = MAINTAINER;

static struct argp_option options[] = {
	{ "delimiter",         'd', N_("DELIM"),    0, N_("Specify a delimiter.") },
	{ "column",            'c', N_("SPEC"),     0, N_("Append the specified column.") },
	{ "copying",	       'C', 0,		    0, N_("Print out the copyright license.") },
	{ "errorlevel",	       'l', N_("LEVEL"),    0, N_("Set debugging level to LEVEL.") },
	{ "quiet",	       'q', 0,		    0, N_("Do no output to stdout.") },
	{ "silent",	       OPT_SILENT, 0,	    0, N_("Do no output to stdout.") },
	{ 0 }
};

#define MAX_FNAMES 4096
#define MAX_COLUMNS 4096

struct arguments {
	char *delim; // NULL if not specced
	/* True iff some column lengths are unknown and need to be
	 * calculated. */
	_Bool need_preprocessing;
	/* Number of columns specified */
	size_t num_columns;
	/* Number of file names seen.  */
	size_t num_fnames;
	/* Columns specified on the command line. */
	struct column {
		char *heading;
		size_t field_inx;
		size_t column_width;
	} columns[MAX_COLUMNS];
	/* File names seen on the command line.  */
	struct ifile fname[MAX_FNAMES];
};

#define INSERT(c) do { \
	if (len >= max) { \
		max *= 2; \
		rv = realloc(rv, max); \
		if (rv == NULL) fatal_enomem(NULL); \
	} \
	rv[len++] = (c); \
} while (0)

size_t linewrap(char **res, char const *orig, size_t orig_len,
		size_t col_width)
{
	assert(col_width > 0);

	size_t max = 16;
	char *rv = malloc(max);
	size_t len = 0;

	size_t ll = 0;
	size_t bpo = 0, bpr = 0;

	size_t num_lines = 1;

	mblen(NULL, 0);
	for (size_t i = 0; i < orig_len; /**/) {
		if (ll == col_width) {
			if (rv[bpr] == '\n') {
				// no suitable breakpoint on this line,
				// break here
			} else {
				assert(bpr < len);
				len = bpr;
				assert(bpo < i);
				i = bpo;
			}
			ll = 0;
			INSERT('\n');
			num_lines++;
			continue;
		}
		if (orig[i] == ' ' || orig[i] == '\t') {
			// record this breakpoint
			bpo = i;
			bpr = len;
		}
		int n = mblen(orig + i, orig_len - i);
		if (n <= 0) break;
		for (size_t j = 0; j < n; j++) INSERT(orig[i+j]);
		i += n;
		ll++;
	}
	INSERT('\0');
	*res = rv;
	return num_lines;
}


void print_line(struct arguments *args,
		struct fsaf_read_rv const columns[/*args->num_columns*/])
{
	struct print_line_data {
		char *wrapped;
		size_t wrapped_len;
		size_t inx;
	} data[args->num_columns];
	size_t num_lines = 0;
	for (size_t i = 0; i < args->num_columns; i++) {
		size_t n = linewrap(&data[i].wrapped,
				    columns[i].b, columns[i].len,
				    args->columns[i].column_width);
		if (n > num_lines) num_lines = n;
		data[i].inx = 0;
		data[i].wrapped_len = strlen(data[i].wrapped);
	}
	for (size_t i = 0; i < num_lines; i++) {
		for (size_t j = 0; j < args->num_columns; j++) {
			if (args->delim == NULL) {
				fputs("| ", stdout);
			} else if (j > 0) {
				fputs(args->delim, stdout);
			}
			mblen(NULL, 0);
			size_t k;
			size_t m = 0;
			for (k = data[j].inx;
			     k < data[j].wrapped_len;
			     /**/) {
				if (data[j].wrapped[k] == '\n') {
					k++;
					break;
				}
				int n = mblen(data[j].wrapped + k,
					      data[j].wrapped_len - k);
				for (int l = 0; l < n; l++) {
					putchar(data[j].wrapped[k+l]);
				}
				if (n <= 0) n = 1;
				k += n;
				m++;
			}

			if (args->delim == NULL) {
				while (m < args->columns[j].column_width) {
					m++;
					putchar(' ');
				}
				putchar(' ');
			}
			data[j].inx = k;
		}
		if (args->delim == NULL) fputs("|", stdout);
		putchar('\n');
	}
	for (size_t i = 0; i < args->num_columns; i++) free(data[i].wrapped);
}

void print_head(struct arguments *args)
{
	if (args->delim == NULL) {
		for (size_t i = 0; i < args->num_columns; i++) {
			putchar('+');
			for (size_t j = 0; 
			     j < args->columns[i].column_width + 2;
			     j++) {
				putchar('=');
			}
		}
		putchar('+');
		putchar('\n');
	}
		
	struct fsaf_read_rv columns[args->num_columns];
	for (size_t i = 0; i < args->num_columns; i++) {
		columns[i].b = args->columns[i].heading;
		columns[i].len = strlen(columns[i].b);
	}
	print_line(args, columns);

	if (args->delim == NULL) {
		for (size_t i = 0; i < args->num_columns; i++) {
			putchar('+');
			for (size_t j = 0; j < args->columns[i].column_width + 2; j++) {
				putchar('-');
			}
		}
		putchar('+');
		putchar('\n');
	}
}

void print_foot(struct arguments *args)
{
	if (args->delim != NULL) return;
	for (size_t i = 0; i < args->num_columns; i++) {
		putchar('+');
		for (size_t j = 0; j < args->columns[i].column_width + 2; j++) {
			putchar('=');
		}
	}
	putchar('+');
	putchar('\n');
}

void handle_para(struct arguments *args, struct paragraph *para)
{
	struct fsaf_read_rv columns[args->num_columns];
	for (size_t i = 0; i < args->num_columns; i++) {	
		columns[i] = get_field(para, args->columns[i].field_inx);
	}
	print_line(args, columns);
}

static error_t parse_opt (int key, char * arg, struct argp_state * state)
{
	struct arguments * args = state->input;
	switch (key) {
	case 'C':
		if (!to_stdout (COPYING)) fail();
		exit(0);
	case 'c': {
		char *carg = strdup(arg);
		if (carg == NULL) fatal_enomem(0);
		char *lens = strrchr(carg, ':');
		if (lens != NULL) *(lens++) = '\0'; else lens = "";
		char *fn = strchr(carg, '=');
		if (fn != NULL) *(fn++) = '\0';
		struct column *col = &args->columns[args->num_columns];
		col->heading = carg;
		col->field_inx = fieldtrie_insert(fn == NULL ? carg : fn);
		size_t n = 0;
		_Bool err = 0;
		for (char const *p = lens; *p != '\0'; p++) {
			if (!('0' <= *p && *p <= '9')) {
				err = 1;
				continue;
			}
			n = n * 10 + (*p - '0');
		}
		if (err) message(L_IMPORTANT, _("invalid column length"), NULL);
		col->column_width = n > 0 ? n : -1;
		if (n == 0) args->need_preprocessing = 1;
		args->num_columns++;
	}
		break;
	case 'd':
		args->delim = strdup(arg);
		if (args->delim == NULL) fatal_enomem(NULL);
		break;
	case 'l': {
		int ll = str2loglevel(arg);
		if (ll < 0)
		{
			message(L_FATAL, _("no such log level"), arg);
			fail();
		}
		set_loglevel(ll);
		debug_message("parse_opt: l", 0);
	}
		break;
	case ARGP_KEY_ARG:
		debug_message("parse_opt: argument", 0);
		{
			char const * s;
			if (args->num_fnames >= MAX_FNAMES) {
				message(L_FATAL, _("too many file names"), 0);
				fail();
			}
			s = strdup(arg);
			if (s == 0) fatal_enomem(0);
			args->fname[args->num_fnames++] =
				(struct ifile){ .mode = m_read, .s = s };
		}
		break;
	case ARGP_KEY_END:
	case ARGP_KEY_ARGS:  case ARGP_KEY_INIT: case  ARGP_KEY_SUCCESS:
	case ARGP_KEY_ERROR: case ARGP_KEY_FINI: case ARGP_KEY_NO_ARGS:
		debug_message("parse_opt: ignored", 0);
		break;
	default:
		return ARGP_ERR_UNKNOWN;
	}
	return 0;
}

static char progdoc [] =
N_("tbl-dctrl -- tabularize Debian control files");

static struct argp argp = { options, parse_opt, 0, progdoc };

static size_t mbs_len(char const *mbs, size_t n, char const *fname)
{
	if (n == (size_t)(-1)) n = strlen(mbs);
	size_t len = 0;
	mblen(NULL, 0);
	for (size_t k = 0; k < n;/**/) {
		if (mbs[k] == '\n') break;
		len++;
		int delta = mblen(mbs + k, n - k);
		if (delta <= 0) {
			message(L_IMPORTANT, _("bad multibyte character"),
				fname);
			k++;
		} else {
			k += delta;
		}
	}
	return len;
}

int main(int argc, char * argv[])
{
	setlocale(LC_ALL, "");
	bindtextdomain (PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	fieldtrie_init();

	static struct arguments args;

	//keys_init(&args.keys);
	msg_set_progname(argv[0]);
	argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, &args);

	if (args.num_fnames == 0) {
		args.fname[args.num_fnames++] = (struct ifile){
			.mode = m_read, .s = "-"
		};
	}

	if (args.need_preprocessing) {
		struct para_bundle pb;

		bundle_init(&pb);
		
		for (size_t i = 0; i < args.num_fnames; i++) {
			bundle_slurp(&pb, args.fname[i]);
		}

		size_t n = fieldtrie_count();
		size_t lens[n];
		for (size_t i = 0; i < n; i++) lens[i] = 0;

		for (size_t i = 0; i < pb.num_paras; i++) {
			struct paragraph *p = pb.paras[i];
			assert(p->nfields == n);
			for (size_t j = 0; j < p->nfields; j++) {
				struct fsaf_read_rv r = get_field(p, j);
				size_t len = mbs_len(r.b, r.len,
						     p->common->fp->fname);
				if (len > lens[j]) lens[j] = len;
			}
		}
		for (size_t i = 0; i < args.num_columns; i++) {
			size_t width = args.columns[i].column_width;
			size_t headw = mbs_len(args.columns[i].heading, -1, 0);
			if (width == (size_t)(-1)) width = lens[i];
			if (headw > width) width = headw;
			args.columns[i].column_width = width;

[37 lines skipped]



More information about the Dctrl-tools-devel mailing list