blob: 016fc77806cadb534616c9e79b65233fec608438 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
John Beppuabb47722000-01-06 00:48:21 +00002/*
Erik Andersen0b874ed2000-01-06 01:14:56 +00003 * Mini uniq implementation for busybox
John Beppuabb47722000-01-06 00:48:21 +00004 *
5 *
Erik Andersen61677fe2000-04-13 01:18:56 +00006 * Copyright (C) 1999,2000 by Lineo, inc.
John Beppuabb47722000-01-06 00:48:21 +00007 * 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>
John Beppu96f1f332000-01-06 23:49:21 +000027#include <string.h>
28#include <errno.h>
John Beppuabb47722000-01-06 00:48:21 +000029
John Beppuabb47722000-01-06 00:48:21 +000030/* max chars in line */
31#define UNIQ_MAX 4096
32
Erik Andersene49d5ec2000-02-08 19:58:47 +000033typedef void (Print) (FILE *, const char *);
John Beppuabb47722000-01-06 00:48:21 +000034
Erik Andersene49d5ec2000-02-08 19:58:47 +000035typedef int (Decide) (const char *, const char *);
John Beppuabb47722000-01-06 00:48:21 +000036
37/* container for two lines to be compared */
38typedef struct {
Erik Andersene49d5ec2000-02-08 19:58:47 +000039 char *a;
40 char *b;
41 int recurrence;
42 FILE *in;
43 FILE *out;
44 void *func;
John Beppuabb47722000-01-06 00:48:21 +000045} Subject;
46
47/* set up all the variables of a uniq operation */
Erik Andersene49d5ec2000-02-08 19:58:47 +000048static Subject *subject_init(Subject * self, FILE * in, FILE * out,
49 void *func)
John Beppuabb47722000-01-06 00:48:21 +000050{
Erik Andersene49d5ec2000-02-08 19:58:47 +000051 self->a = NULL;
52 self->b = NULL;
53 self->in = in;
54 self->out = out;
55 self->func = func;
56 self->recurrence = 0;
57 return self;
John Beppuabb47722000-01-06 00:48:21 +000058}
59
60/* point a and b to the appropriate lines;
61 * count the recurrences (if any) of a string;
62 */
Erik Andersene49d5ec2000-02-08 19:58:47 +000063static Subject *subject_next(Subject * self)
John Beppuabb47722000-01-06 00:48:21 +000064{
Erik Andersene49d5ec2000-02-08 19:58:47 +000065 /* tmp line holders */
66 static char line[2][UNIQ_MAX];
67 static int alternator = 0;
John Beppuabb47722000-01-06 00:48:21 +000068
Erik Andersene49d5ec2000-02-08 19:58:47 +000069 if (fgets(line[alternator], UNIQ_MAX, self->in)) {
70 self->a = self->b;
71 self->b = line[alternator];
72 alternator ^= 1;
73 return self;
74 }
75
76 return NULL;
77}
78
79static Subject *subject_last(Subject * self)
80{
John Beppuabb47722000-01-06 00:48:21 +000081 self->a = self->b;
Erik Andersene49d5ec2000-02-08 19:58:47 +000082 self->b = NULL;
John Beppuabb47722000-01-06 00:48:21 +000083 return self;
John Beppuabb47722000-01-06 00:48:21 +000084}
85
Erik Andersene49d5ec2000-02-08 19:58:47 +000086static Subject *subject_study(Subject * self)
John Beppuabb47722000-01-06 00:48:21 +000087{
Erik Andersene49d5ec2000-02-08 19:58:47 +000088 if (self->a == NULL) {
89 return self;
90 }
91 if (self->b == NULL) {
92 fprintf(self->out, "%s", self->a);
93 return self;
94 }
95 if (strcmp(self->a, self->b) == 0) {
96 self->recurrence++;
97 } else {
98 fprintf(self->out, "%s", self->a);
99 self->recurrence = 0;
100 }
John Beppuabb47722000-01-06 00:48:21 +0000101 return self;
John Beppuabb47722000-01-06 00:48:21 +0000102}
103
John Beppu96f1f332000-01-06 23:49:21 +0000104static int
Erik Andersene49d5ec2000-02-08 19:58:47 +0000105set_file_pointers(int schema, FILE ** in, FILE ** out, char **argv)
John Beppu96f1f332000-01-06 23:49:21 +0000106{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000107 switch (schema) {
John Beppu96f1f332000-01-06 23:49:21 +0000108 case 0:
Erik Andersene49d5ec2000-02-08 19:58:47 +0000109 *in = stdin;
110 *out = stdout;
111 break;
John Beppu96f1f332000-01-06 23:49:21 +0000112 case 1:
Erik Andersene49d5ec2000-02-08 19:58:47 +0000113 *in = fopen(argv[0], "r");
114 *out = stdout;
115 break;
John Beppu96f1f332000-01-06 23:49:21 +0000116 case 2:
Erik Andersene49d5ec2000-02-08 19:58:47 +0000117 *in = fopen(argv[0], "r");
118 *out = fopen(argv[1], "w");
119 break;
120 }
121 if (*in == NULL) {
Matt Kraaid537a952000-07-14 01:51:25 +0000122 errorMsg("%s: %s\n", argv[0], strerror(errno));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000123 return errno;
124 }
125 if (*out == NULL) {
Matt Kraaid537a952000-07-14 01:51:25 +0000126 errorMsg("%s: %s\n", argv[1], strerror(errno));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000127 return errno;
128 }
129 return 0;
John Beppu96f1f332000-01-06 23:49:21 +0000130}
131
132
John Beppuabb47722000-01-06 00:48:21 +0000133/* one variable is the decision algo */
134/* another variable is the printing algo */
135
136/* I don't think I have to have more than a 1 line memory
137 this is the one constant */
138
139/* it seems like GNU/uniq only takes one or two files as an option */
140
141/* ________________________________________________________________________ */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000142int uniq_main(int argc, char **argv)
John Beppuabb47722000-01-06 00:48:21 +0000143{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000144 int i;
145 char opt;
146 FILE *in, *out;
147 Subject s;
John Beppuabb47722000-01-06 00:48:21 +0000148
Erik Andersene49d5ec2000-02-08 19:58:47 +0000149 /* parse argv[] */
150 for (i = 1; i < argc; i++) {
151 if (argv[i][0] == '-') {
152 opt = argv[i][1];
153 switch (opt) {
154 case '-':
155 case 'h':
156 usage(uniq_usage);
157 default:
158 usage(uniq_usage);
159 }
160 } else {
161 break;
162 }
John Beppuabb47722000-01-06 00:48:21 +0000163 }
John Beppuabb47722000-01-06 00:48:21 +0000164
Erik Andersene49d5ec2000-02-08 19:58:47 +0000165 /* 0 src: stdin; dst: stdout */
166 /* 1 src: file; dst: stdout */
167 /* 2 src: file; dst: file */
168 if (set_file_pointers((argc - 1), &in, &out, &argv[i])) {
169 exit(1);
170 }
John Beppu96f1f332000-01-06 23:49:21 +0000171
Erik Andersene49d5ec2000-02-08 19:58:47 +0000172 subject_init(&s, in, out, NULL);
173 while (subject_next(&s)) {
174 subject_study(&s);
175 }
176 subject_last(&s);
John Beppu96f1f332000-01-06 23:49:21 +0000177 subject_study(&s);
John Beppu96f1f332000-01-06 23:49:21 +0000178
Eric Andersenb6106152000-06-19 17:25:40 +0000179 return(0);
John Beppuabb47722000-01-06 00:48:21 +0000180}
181
Matt Kraaibf181b92000-07-16 20:57:15 +0000182/* $Id: uniq.c,v 1.13 2000/07/16 20:57:15 kraai Exp $ */