Imported Upstream version 4.5.14
[platform/upstream/findutils.git] / locate / bigram.c
1 /* bigram -- list bigrams for locate
2    Copyright (C) 1994, 2007, 2009, 2010, 2011 Free Software Foundation,
3    Inc.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /* Usage: bigram < text > bigrams
20    Use `code' to encode a file using this output.
21
22    Read a file from stdin and write out the bigrams (pairs of
23    adjacent characters), one bigram per line, to stdout.  To reduce
24    needless duplication in the output, it starts finding the
25    bigrams on each input line at the character where that line
26    first differs from the previous line (i.e., in the ASCII
27    remainder).  Therefore, the input should be sorted in order to
28    get the least redundant output.
29
30    Written by James A. Woods <jwoods@adobe.com>.
31    Modified by David MacKenzie <djm@gnu.ai.mit.edu>.  */
32
33 /* config.h must always be included first. */
34 #include <config.h>
35
36 /* system headers. */
37 #include <errno.h>
38 #include <stdio.h>
39 #include <locale.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <sys/types.h>
43
44 /* gnulib headers. */
45 #include "closeout.h"
46 #include "gettext.h"
47 #include "progname.h"
48 #include "xalloc.h"
49 #include "error.h"
50
51 /* find headers would go here but we don't need any. */
52
53
54 /* We use gettext because for example xmalloc may issue an error message. */
55 #if ENABLE_NLS
56 # include <libintl.h>
57 # define _(Text) gettext (Text)
58 #else
59 # define _(Text) Text
60 #define textdomain(Domain)
61 #define bindtextdomain(Package, Directory)
62 #endif
63 #ifdef gettext_noop
64 # define N_(String) gettext_noop(String)
65 #else
66 /* See locate.c for explanation as to why not use (String) */
67 # define N_(String) String
68 #endif
69
70
71 /* Return the length of the longest common prefix of strings S1 and S2. */
72
73 static int
74 prefix_length (char *s1, char *s2)
75 {
76   register char *start;
77
78   for (start = s1; *s1 == *s2 && *s1 != '\0'; s1++, s2++)
79     ;
80   return s1 - start;
81 }
82
83 int
84 main (int argc, char **argv)
85 {
86   char *path;                   /* The current input entry.  */
87   char *oldpath;                /* The previous input entry.  */
88   size_t pathsize, oldpathsize; /* Amounts allocated for them.  */
89   int line_len;                 /* Length of input line.  */
90
91   if (argv[0])
92     set_program_name (argv[0]);
93   else
94     set_program_name ("bigram");
95
96 #ifdef HAVE_SETLOCALE
97   setlocale (LC_ALL, "");
98 #endif
99   bindtextdomain (PACKAGE, LOCALEDIR);
100   textdomain (PACKAGE);
101
102   (void) argc;
103   if (atexit (close_stdout))
104     {
105       error (EXIT_FAILURE, errno, _("The atexit library function failed"));
106     }
107
108   pathsize = oldpathsize = 1026; /* Increased as necessary by getline.  */
109   path = xmalloc (pathsize);
110   oldpath = xmalloc (oldpathsize);
111
112   /* Set to empty string, to force the first prefix count to 0.  */
113   oldpath[0] = '\0';
114
115   while ((line_len = getline (&path, &pathsize, stdin)) > 0)
116     {
117       register int count;       /* The prefix length.  */
118       register int j;           /* Index into input line.  */
119
120       path[line_len - 1] = '\0'; /* Remove the newline. */
121
122       /* Output bigrams in the remainder only. */
123       count = prefix_length (oldpath, path);
124       for (j = count; path[j] != '\0' && path[j + 1] != '\0'; j += 2)
125         {
126           putchar (path[j]);
127           putchar (path[j + 1]);
128           putchar ('\n');
129         }
130
131       {
132         /* Swap path and oldpath and their sizes.  */
133         char *tmppath = oldpath;
134         size_t tmppathsize = oldpathsize;
135         oldpath = path;
136         oldpathsize = pathsize;
137         path = tmppath;
138         pathsize = tmppathsize;
139       }
140     }
141
142   free (path);
143   free (oldpath);
144
145   return 0;
146 }