Imported from ../bash-2.0.tar.gz.
[platform/upstream/bash.git] / support / mkversion.c
1 /* Simple program to make new version numbers for the shell.
2    Big deal, but it was getting out of hand to do everything
3    in the makefile. */
4
5 /* Copyright (C) 1989 Free Software Foundation, Inc.
6
7 This file is part of GNU Bash, the Bourne Again SHell.
8
9 Bash is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 1, or (at your option) any later
12 version.
13
14 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License along
20 with Bash; see the file COPYING.  If not, write to the Free Software
21 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 #include "config.h"
24
25 #include <sys/types.h>
26 #include "posixstat.h"
27 #include <stdio.h>
28 #include "bashansi.h"
29
30 char *progname;
31 char *dir;
32 char *status;
33
34 FILE *must_open ();
35
36 main (argc, argv)
37      int argc;
38      char **argv;
39 {
40   FILE *file;
41   float distver = 0.0;
42   int buildver = 0, patchlevel = 0;
43   int dist = 0, build = 0, patch = 0;
44   int dist_inc = 0, build_inc = 0, patch_inc = 0;
45   int dot_dist_needs_making = 0;
46   int arg_index = 1;
47   struct stat sb;
48
49   progname = argv[0];
50
51   status = dir = (char *)0;
52   while (arg_index < argc && argv[arg_index][0] == '-')
53     {
54       if (strcmp (argv[arg_index], "-dist") == 0)
55         {
56           dist++;
57           dist_inc++;
58         }
59       else if (strcmp (argv[arg_index], "-build") == 0)
60         {
61           build++;
62           build_inc++;
63         }
64       else if (strcmp (argv[arg_index], "-patch") == 0)
65         {
66           patch++;
67           patch_inc++;
68         }
69       else if (strcmp (argv[arg_index], "-dir") == 0)
70         {
71           dir = argv[++arg_index];
72           if (dir == 0)
73             {
74               fprintf (stderr, "%s: `-dir' requires an argument\n", progname);
75               exit (1);
76             }
77           if (stat (dir, &sb) < 0)
78             {
79               fprintf (stderr, "%s: cannot stat %s\n", progname, dir);
80               exit (1);
81             }
82           if ((sb.st_mode & S_IFMT) != S_IFDIR)
83             {
84               fprintf (stderr, "%s: not a directory\n", progname);
85               exit (1);
86             }
87         }
88       else if (strcmp (argv[arg_index], "-status") == 0)
89         {
90           status = argv[++arg_index];
91           if (status == 0)
92             {
93               fprintf (stderr, "%s: `-status' requires an argument\n", progname);
94               exit (1);
95             }
96         }
97       else
98         {
99           fprintf (stderr, "%s: unknown option: %s\n", progname, argv[arg_index]);
100           fprintf (stderr, "usage: %s [-dist|-patch|-build] [-dir directory]\n", progname);
101           exit (1);
102         }
103       arg_index++;
104     }
105
106   if (get_float_from_file (".distribution", &distver, 1) == 0)
107     dot_dist_needs_making++;
108
109   if (get_int_from_file (".patchlevel", &patchlevel, 1) == 0)
110     {
111       patchlevel = 0;
112       patch_inc = 0;
113     }
114
115   if (get_int_from_file (".build", &buildver, 0) == 0)
116     buildver = 0;
117
118   /* Setting distribution version. */
119   if (dist && arg_index < argc)
120     if (sscanf (argv[arg_index], "%f", &distver) != 1)
121       {
122         fprintf (stderr, "%s: Bad input `%s'.  Expected float value for -dist.\n",
123                  progname, argv[arg_index]);
124         exit (1);
125       }
126     else
127       {
128         arg_index++;
129         dist_inc = 0;
130       }
131
132   /* Setting patchlevel via argument. */
133   if (patch && arg_index < argc)
134     if (sscanf (argv[arg_index], "%d", &patchlevel) != 1)
135       {
136         fprintf (stderr, "%s: Bad input `%s'.  Expected int value for -patch.\n",
137                  progname, argv[arg_index]);
138         exit (1);
139       }
140     else
141       {
142         arg_index++;
143         patch_inc = 0;
144       }
145     
146   if (build && arg_index < argc)
147     if (sscanf (argv[arg_index], "%d", &buildver) != 1)
148       {
149         fprintf (stderr, "%s: Bad input `%s'.  Expected int value for -build.\n",
150                  progname, argv[arg_index]);
151         exit (1);
152       }
153     else
154       {
155         arg_index++;
156         build_inc = 0;
157       }
158
159   if (dot_dist_needs_making && !distver)
160     {
161       fprintf (stderr, "%s: There is no `.distribution' file to infer from.\n", progname);
162       exit (1);
163     }
164
165   if (dist_inc)
166     distver = distver + 0.01;
167
168   if (patch_inc)
169     patchlevel++;
170
171   if (build_inc)
172     buildver++;
173
174   file = must_open ("newversion.h", "w");
175
176   /* Output the leading comment. */
177   fprintf (file, 
178 "/* Version control for the shell.  This file gets changed when you say\n\
179    `make newversion' to the Makefile.  It is created by mkversion. */\n");
180
181   fprintf (file, "\n/* The distribution version number of this shell. */\n");
182   fprintf (file, "#define DISTVERSION \"%.2f\"\n", distver);
183
184   fprintf (file, "\n/* The patch level of this version of the shell. */\n");
185   fprintf (file, "#define PATCHLEVEL %d\n", patchlevel);
186
187   fprintf (file, "\n/* The last built version of this shell. */\n");
188   fprintf (file, "#define BUILDVERSION %d\n", buildver);
189
190   if (status)
191     {
192       fprintf (file, "\n/* The release status of this shell. */\n");
193       fprintf (file, "#define RELSTATUS \"%s\"\n", status);
194     }
195
196   fprintf (file, "\n/* A version string for use by sccs and the what command. */\n\n");
197   if (status)
198     fprintf (file, "#define SCCSVERSION \"@(#)Bash version %.2f.%d(%d) %s GNU\"\n\n",
199       distver, patchlevel, buildver, status);
200   else
201     fprintf (file, "#define SCCSVERSION \"@(#)Bash version %.2f.%d(%d) GNU\"\n\n",
202       distver, patchlevel, buildver);
203
204   fclose (file);
205
206   file = must_open (".build", "w");
207   fprintf (file, "%d\n", buildver);
208   fclose (file);
209
210   /* Making a new distribution. */
211   if (dist)
212     {
213       file = must_open (".distribution", "w");
214       fprintf (file, "%.2f\n", distver);
215       fclose (file);
216     }
217
218   /* Releasing a new patch level. */
219   if (patch)
220     {
221       file = must_open (".patchlevel", "w");
222       fprintf (file, "%d\n", patchlevel);
223       fclose (file);
224     }
225
226   exit (0);
227 }
228
229 char *
230 makename (fn, from_srcdir)
231      char *fn;
232 {
233   char *ret;
234   int dlen;
235
236   dlen = (from_srcdir && dir) ? strlen (dir) + 1 : 0;
237   ret = (char *)malloc (dlen + strlen (fn) + 1);
238   if (ret == 0)
239     {
240       fprintf (stderr, "%s: malloc failed\n", progname);
241       exit (1);
242     }
243   if (from_srcdir && dir)
244     sprintf (ret, "%s/%s", dir, fn);
245   else
246     (void)strcpy (ret, fn);
247
248   return ret;
249 }
250
251 get_float_from_file (filename, var, from_srcdir)
252      char *filename;
253      float *var;
254      int from_srcdir;
255 {
256   FILE *stream;
257   int result;
258   char *name;
259
260   name = makename (filename, from_srcdir);
261   stream = fopen (name, "r");
262   free (name);
263   if (stream == (FILE *)NULL)
264     return (0);
265   result = fscanf (stream, "%f\n", var);
266   fclose (stream);
267   return (result == 1);
268 }
269
270 get_int_from_file (filename, var, from_srcdir)
271      char *filename;
272      int *var, from_srcdir;
273 {
274   FILE *stream;
275   int result;
276   char *name;
277
278   name = makename (filename, from_srcdir);
279   stream = fopen (name, "r");
280   free (name);
281   if (stream == (FILE *)NULL)
282     return (0);
283   result = fscanf (stream, "%d\n", var);
284   fclose (stream);
285   return (result == 1);
286 }
287
288 FILE *
289 must_open (name, mode)
290      char *name, *mode;
291 {
292   FILE *temp = fopen (name, mode);
293
294   if (!temp)
295     {
296       fprintf (stderr, "%s: Cannot open `%s' for mode `%s'.\n",
297                progname, name, mode);
298       fprintf
299         (stderr,
300          "Perhaps you don't have %s permission to the file or directory.\n",
301          (strcmp (mode, "w") == 0) ? "write" : "read");
302       exit (3);
303     }
304   return (temp);
305 }