Updates to a number of apps to remove warnings/compile errors under libc5.
[platform/upstream/busybox.git] / coreutils / uniq.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini uniq implementation for busybox
4  *
5  *
6  * Copyright (C) 1999,2000 by Lineo, inc.
7  * Written by John Beppu <beppu@lineo.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  *
23  */
24
25 #include "internal.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <errno.h>
29
30 static const char uniq_usage[] =
31         "uniq [OPTION]... [INPUT [OUTPUT]]\n"
32 #ifndef BB_FEATURE_TRIVIAL_HELP
33         "\nDiscard all but one of successive identical lines from INPUT\n"
34         "(or standard input), writing to OUTPUT (or standard output).\n"
35 #endif
36         ;
37
38 /* max chars in line */
39 #define UNIQ_MAX 4096
40
41 typedef void (Print) (FILE *, const char *);
42
43 typedef int (Decide) (const char *, const char *);
44
45 /* container for two lines to be compared */
46 typedef struct {
47         char *a;
48         char *b;
49         int recurrence;
50         FILE *in;
51         FILE *out;
52         void *func;
53 } Subject;
54
55 /* set up all the variables of a uniq operation */
56 static Subject *subject_init(Subject * self, FILE * in, FILE * out,
57                                                          void *func)
58 {
59         self->a = NULL;
60         self->b = NULL;
61         self->in = in;
62         self->out = out;
63         self->func = func;
64         self->recurrence = 0;
65         return self;
66 }
67
68 /* point a and b to the appropriate lines;
69  * count the recurrences (if any) of a string;
70  */
71 static Subject *subject_next(Subject * self)
72 {
73         /* tmp line holders */
74         static char line[2][UNIQ_MAX];
75         static int alternator = 0;
76
77         if (fgets(line[alternator], UNIQ_MAX, self->in)) {
78                 self->a = self->b;
79                 self->b = line[alternator];
80                 alternator ^= 1;
81                 return self;
82         }
83
84         return NULL;
85 }
86
87 static Subject *subject_last(Subject * self)
88 {
89         self->a = self->b;
90         self->b = NULL;
91         return self;
92 }
93
94 static Subject *subject_study(Subject * self)
95 {
96         if (self->a == NULL) {
97                 return self;
98         }
99         if (self->b == NULL) {
100                 fprintf(self->out, "%s", self->a);
101                 return self;
102         }
103         if (strcmp(self->a, self->b) == 0) {
104                 self->recurrence++;
105         } else {
106                 fprintf(self->out, "%s", self->a);
107                 self->recurrence = 0;
108         }
109         return self;
110 }
111
112 static int
113 set_file_pointers(int schema, FILE ** in, FILE ** out, char **argv)
114 {
115         switch (schema) {
116         case 0:
117                 *in = stdin;
118                 *out = stdout;
119                 break;
120         case 1:
121                 *in = fopen(argv[0], "r");
122                 *out = stdout;
123                 break;
124         case 2:
125                 *in = fopen(argv[0], "r");
126                 *out = fopen(argv[1], "w");
127                 break;
128         }
129         if (*in == NULL) {
130                 fprintf(stderr, "uniq: %s: %s\n", argv[0], strerror(errno));
131                 return errno;
132         }
133         if (*out == NULL) {
134                 fprintf(stderr, "uniq: %s: %s\n", argv[1], strerror(errno));
135                 return errno;
136         }
137         return 0;
138 }
139
140
141 /* one variable is the decision algo */
142 /* another variable is the printing algo */
143
144 /* I don't think I have to have more than a 1 line memory 
145    this is the one constant */
146
147 /* it seems like GNU/uniq only takes one or two files as an option */
148
149 /* ________________________________________________________________________ */
150 int uniq_main(int argc, char **argv)
151 {
152         int i;
153         char opt;
154         FILE *in, *out;
155         Subject s;
156
157         /* parse argv[] */
158         for (i = 1; i < argc; i++) {
159                 if (argv[i][0] == '-') {
160                         opt = argv[i][1];
161                         switch (opt) {
162                         case '-':
163                         case 'h':
164                                 usage(uniq_usage);
165                         default:
166                                 usage(uniq_usage);
167                         }
168                 } else {
169                         break;
170                 }
171         }
172
173         /* 0 src: stdin; dst: stdout */
174         /* 1 src: file;  dst: stdout */
175         /* 2 src: file;  dst: file   */
176         if (set_file_pointers((argc - 1), &in, &out, &argv[i])) {
177                 exit(1);
178         }
179
180         subject_init(&s, in, out, NULL);
181         while (subject_next(&s)) {
182                 subject_study(&s);
183         }
184         subject_last(&s);
185         subject_study(&s);
186
187         return(0);
188 }
189
190 /* $Id: uniq.c,v 1.11 2000/06/19 17:25:40 andersen Exp $ */