(main): Declare to be of type int, not void.
[platform/upstream/coreutils.git] / src / factor.c
1 /* factor -- print factors of n.  lose if n > 2^32.
2    Copyright (C) 86, 1995 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
17
18 /* Written by Paul Rubin <phr@ocf.berkeley.edu>.
19    Adapted for GNU, fixed to factor UINT_MAX by Jim Meyering.  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <sys/types.h>
25
26 #include <assert.h>
27 #define NDEBUG 1
28
29 #ifdef HAVE_LIMITS_H
30 #include <limits.h>
31 #endif /* HAVE_LIMITS_H */
32
33 #ifndef UINT_MAX
34 # define UINT_MAX ((unsigned int) ~(unsigned int) 0)
35 #endif
36
37 #ifndef INT_MAX
38 # define INT_MAX ((int) (UINT_MAX >> 1))
39 #endif
40
41 #include "system.h"
42 #include "long-options.h"
43 #include "error.h"
44 #include "xstrtoul.h"
45 #include "readtokens.h"
46
47 /* Token delimiters when reading from a file.  */
48 #define DELIM "\n\t "
49
50 /* FIXME: if this program is ever modified to factor integers larger
51    than 2^128, this constant (and the algorithm :-) will have to change.  */
52 #define MAX_N_FACTORS 128
53
54 /* The name this program was run with. */
55 char *program_name;
56
57 static void
58 usage (int status)
59 {
60   if (status != 0)
61     fprintf (stderr, _("Try `%s --help' for more information.\n"),
62              program_name);
63   else
64     {
65       printf (_("\
66 Usage: %s [NUMBER...]\n\
67   or:  %s OPTION\n\
68 "),
69               program_name, program_name);
70       printf (_("\
71 \n\
72   --help      display this help and exit\n\
73   --version   output version information and exit\n\
74 "));
75     }
76   exit (status);
77 }
78
79 /* FIXME: comment */
80
81 static int
82 factor (long unsigned int n0, int max_n_factors, long unsigned int *factors)
83 {
84   register unsigned long n = n0, d;
85   int n_factors = 0;
86   unsigned int sqrt_n;
87
88   if (n < 1)
89     return n_factors;
90
91   while (n % 2 == 0)
92     {
93       assert (n_factors < max_n_factors);
94       factors[n_factors++] = 2;
95       n /= 2;
96     }
97
98   /* The exit condition in the following loop is correct because
99      any time it is tested one of these 3 conditions holds:
100       (1) d divides n
101       (2) n is prime
102       (3) n is composite but has no factors less than d.
103      If (1) or (2) obviously the right thing happens.
104      If (3), then since n is composite it is >= d^2. */
105   sqrt_n = (unsigned int) sqrt ((double) n);
106   for (d = 3; d <= sqrt_n; d += 2)
107     {
108       while (n % d == 0)
109         {
110           assert (n_factors < max_n_factors);
111           factors[n_factors++] = d;
112           n /= d;
113         }
114     }
115   if (n != 1 || n0 == 1)
116     {
117       assert (n_factors < max_n_factors);
118       factors[n_factors++] = n;
119     }
120
121   return n_factors;
122 }
123
124 /* FIXME: comment */
125
126 static int
127 print_factors (const char *s)
128 {
129   unsigned long int factors[MAX_N_FACTORS];
130   unsigned long n;
131   int n_factors;
132   int i;
133
134   if (xstrtoul (s, NULL, 10, &n, NULL) != LONGINT_OK)
135     {
136       error (0, 0, _("%s: invalid argument"), s);
137       return 1;
138     }
139   n_factors = factor (n, MAX_N_FACTORS, factors);
140   printf ("%lu:", n);
141   for (i = 0; i < n_factors; i++)
142     printf (" %lu", factors[i]);
143   putchar ('\n');
144   return 0;
145 }
146
147 static int
148 do_stdin (void)
149 {
150   int fail = 0;
151   token_buffer tokenbuffer;
152
153   init_tokenbuffer (&tokenbuffer);
154
155   for (;;)
156     {
157       long int token_length;
158
159       token_length = readtoken (stdin, DELIM, sizeof (DELIM) - 1,
160                                 &tokenbuffer);
161       if (token_length < 0)
162         break;
163       fail |= print_factors (tokenbuffer.buffer);
164     }
165   free (tokenbuffer.buffer);
166
167   return fail;
168 }
169
170 int
171 main (int argc, char **argv)
172 {
173   int fail;
174
175   program_name = argv[0];
176   setlocale (LC_ALL, "");
177   bindtextdomain (PACKAGE, LOCALEDIR);
178   textdomain (PACKAGE);
179
180   parse_long_options (argc, argv, "factor", PACKAGE_VERSION, usage);
181
182   fail = 0;
183   if (argc == 1)
184     fail = do_stdin ();
185   else
186     {
187       int i;
188       for (i = 1; i < argc; i++)
189         fail |= print_factors (argv[i]);
190     }
191
192   exit (fail);
193 }