Home | History | Annotate | Line # | Download | only in sortinfo
sortinfo.c revision 1.1
      1 /*	$NetBSD: sortinfo.c,v 1.1 2015/12/18 18:56:47 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2015 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Christos Zoulas.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __RCSID("$NetBSD: sortinfo.c,v 1.1 2015/12/18 18:56:47 christos Exp $");
     34 
     35 /*
     36  * Sort a texinfo(1) directory file.
     37  */
     38 
     39 #include <stdio.h>
     40 #include <string.h>
     41 #include <stdlib.h>
     42 #include <unistd.h>
     43 #include <err.h>
     44 #include <util.h>
     45 
     46 struct line {
     47 	char *data;
     48 	struct line *next;
     49 };
     50 
     51 struct section {
     52 	const char *name;
     53 	struct line *line;
     54 };
     55 
     56 static struct section *slist;
     57 static size_t nsections, maxsections;
     58 
     59 static struct section *
     60 addsection(const char *line)
     61 {
     62 	if (nsections >= maxsections) {
     63 		maxsections += 20;
     64 		slist = erealloc(slist, maxsections * sizeof(*slist));
     65 	}
     66 	slist[nsections].name = estrdup(line);
     67 	slist[nsections].line = NULL;
     68 	return &slist[nsections++];
     69 }
     70 
     71 static struct line *
     72 addline(struct section *s, struct line *l, const char *line)
     73 {
     74 	if (l == NULL)
     75 		s->line = l = emalloc(sizeof(*l));
     76 	else {
     77 		l->next = emalloc(sizeof(*l));
     78 		l = l->next;
     79 	}
     80 	l->next = NULL;
     81 	l->data = estrdup(line);
     82 	return l;
     83 }
     84 
     85 static int
     86 compsection(const void *a, const void *b)
     87 {
     88 	const struct section *sa = a, *sb = b;
     89 	return strcmp(sa->name, sb->name);
     90 }
     91 
     92 static void
     93 printsection(const struct section *s)
     94 {
     95 	struct line *l;
     96 	fputc('\n', stdout);
     97 	printf("%s", s->name);
     98 	for (l = s->line; l; l = l->next)
     99 		printf("%s", l->data);
    100 }
    101 
    102 int
    103 main(int argc, char *argv[])
    104 {
    105 	size_t i;
    106 	char *line;
    107 	int needsection;
    108 	struct section *s = NULL;
    109 	struct line *l = NULL;
    110 
    111 	while ((line = fgetln(stdin, &i)) != NULL) {
    112 		fputs(line, stdout);
    113 		if (strcmp(line, "* Menu:\n") == 0)
    114 			break;
    115 	}
    116 
    117 	if (line == NULL)
    118 		errx(EXIT_FAILURE, "Did not find menu line");
    119 
    120 	needsection = 0;
    121 	while ((line = fgetln(stdin, &i)) != NULL)
    122 		switch (*line) {
    123 		case '\n':
    124 			needsection = 1;
    125 			continue;
    126 		case '*':
    127 			if (s == NULL)
    128 				errx(EXIT_FAILURE, "No current section");
    129 			l = addline(s, l, line);
    130 			continue;
    131 		default:
    132 			if (needsection == 0)
    133 				errx(EXIT_FAILURE, "Already in section");
    134 			s = addsection(line);
    135 			l = NULL;
    136 			needsection = 0;
    137 			continue;
    138 		}
    139 
    140 	qsort(slist, nsections, sizeof(*slist), compsection);
    141 	for (i = 0; i < nsections; i++)
    142 		printsection(&slist[i]);
    143 
    144 	return EXIT_SUCCESS;
    145 }
    146