OSDN Git Service

use const
[jnethack/source.git] / src / version.c
1 /* NetHack 3.6  version.c       $NHDT-Date: 1524693365 2018/04/25 21:56:05 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Michael Allison, 2018. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2018            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 #include "hack.h"
12 #include "dlb.h"
13 #include "date.h"
14 /*
15  * All the references to the contents of patchlevel.h have been moved
16  * into makedefs....
17  */
18 #ifdef SHORT_FILENAMES
19 #include "patchlev.h"
20 #include "../japanese/jpatchle.h"
21 #else
22 #include "patchlevel.h"
23 #include "../japanese/jpatchlevel.h"
24 #endif
25
26 #if defined(NETHACK_GIT_SHA)
27 const char * NetHack_git_sha = NETHACK_GIT_SHA;
28 #endif
29 #if defined(NETHACK_GIT_BRANCH)
30 const char * NetHack_git_branch = NETHACK_GIT_BRANCH;
31 #endif
32
33 STATIC_DCL void FDECL(insert_rtoption, (char *));
34
35 /* fill buffer with short version (so caller can avoid including date.h) */
36 char *
37 version_string(buf)
38 char *buf;
39 {
40     return strcpy(buf, VERSION_STRING);
41 }
42
43 /* fill and return the given buffer with the long nethack version string */
44 char *
45 getversionstring(buf)
46 char *buf;
47 {
48     boolean details = FALSE;
49
50     Strcpy(buf, VERSION_ID);
51 #if defined(RUNTIME_PORT_ID) || \
52     defined(NETHACK_GIT_SHA) || defined(NETHACK_GIT_BRANCH)
53     details = TRUE;
54 #endif
55
56     if (details) {
57 #if defined(RUNTIME_PORT_ID) || defined(NETHACK_GIT_SHA) || defined(NETHACK_GIT_BRANCH)
58         int c = 0;
59 #endif
60 #if defined(RUNTIME_PORT_ID)
61         char tmpbuf[BUFSZ];
62         char *tmp = (char *)0;
63 #endif
64
65         Sprintf(eos(buf), " (");
66 #if defined(RUNTIME_PORT_ID)
67         tmp = get_port_id(tmpbuf);        
68         if (tmp)
69             Sprintf(eos(buf), "%s%s", c++ ? "," : "", tmp);
70 #endif
71 #if defined(NETHACK_GIT_SHA)
72         if (NetHack_git_sha)
73             Sprintf(eos(buf), "%s%s", c++ ? "," : "", NetHack_git_sha);
74 #endif
75 #if defined(NETHACK_GIT_BRANCH)
76 #if defined(BETA)
77         if (NetHack_git_branch)
78             Sprintf(eos(buf), "%sbranch:%s", c++ ? "," : "", NetHack_git_branch);
79 #endif
80 #endif
81         Sprintf(eos(buf), ")");
82     }
83     return buf;
84 }
85
86 /* the 'v' command */
87 int
88 doversion()
89 {
90     char buf[BUFSZ];
91
92     pline("%s", getversionstring(buf));
93 #if 1 /*JP*/
94     pline("%s", JVERSION_ID);
95 #endif
96     return 0;
97 }
98
99 /* the '#version' command; also a choice for '?' */
100 int
101 doextversion()
102 {
103     dlb *f;
104     char buf[BUFSZ];
105     winid win = create_nhwindow(NHW_TEXT);
106
107     /* instead of using ``display_file(OPTIONS_USED,TRUE)'' we handle
108        the file manually so we can include dynamic version info */
109     putstr(win, 0, getversionstring(buf));
110
111     f = dlb_fopen(OPTIONS_USED, "r");
112     if (!f) {
113         putstr(win, 0, "");
114         Sprintf(buf, "[Configuration '%s' not available?]", OPTIONS_USED);
115         putstr(win, 0, buf);
116     } else {
117         /*
118          * already inserted above:
119          * + outdented program name and version plus build date and time
120          * dat/options; display contents with lines prefixed by '-' deleted:
121          * - blank-line
122          * -     indented program name and version
123          *   blank-line
124          *   outdented feature header
125          * - blank-line
126          *       indented feature list
127          *       spread over multiple lines
128          *   blank-line
129          *   outdented windowing header
130          * - blank-line
131          *       indented windowing choices with
132          *       optional second line for default
133          * - blank-line
134          * - EOF
135          */
136         boolean prolog = TRUE; /* to skip indented program name */
137
138         while (dlb_fgets(buf, BUFSZ, f)) {
139             (void) strip_newline(buf);
140             if (index(buf, '\t') != 0)
141                 (void) tabexpand(buf);
142
143             if (*buf && *buf != ' ') {
144                 /* found outdented header; insert a separator since we'll
145                    have skipped corresponding blank line inside the file */
146                 putstr(win, 0, "");
147                 prolog = FALSE;
148             }
149             /* skip blank lines and prolog (progame name plus version) */
150             if (prolog || !*buf)
151                 continue;
152
153             if (index(buf, ':'))
154                 insert_rtoption(buf);
155
156             if (*buf)
157                 putstr(win, 0, buf);
158         }
159         (void) dlb_fclose(f);
160         display_nhwindow(win, FALSE);
161         destroy_nhwindow(win);
162     }
163     return 0;
164 }
165
166 void early_version_info(pastebuf)
167 boolean pastebuf;
168 {
169     char buf[BUFSZ], buf2[BUFSZ];
170     char *tmp = getversionstring(buf);
171
172     /* this is early enough that we have to do
173        our own line-splitting */
174     if (tmp) {
175         tmp = strstri(buf," (");
176         if (tmp) *tmp++ = '\0';
177     }
178
179     Sprintf(buf2, "%s\n", buf);
180     if (tmp) Sprintf(eos(buf2), "%s\n", tmp);
181     raw_printf("%s", buf2);
182
183     if (pastebuf) {
184 #ifdef RUNTIME_PASTEBUF_SUPPORT
185         /*
186          * Call a platform/port-specific routine to insert the
187          * version information into a paste buffer. Useful for
188          * easy inclusion in bug reports.
189          */
190         port_insert_pastebuf(buf2);
191 #else
192         raw_printf("%s", "Paste buffer copy is not available.\n");
193 #endif
194     }
195 }
196
197 extern const char regex_id[];
198
199 /*
200  * makedefs should put the first token into dat/options; we'll substitute
201  * the second value for it.  The token must contain at least one colon
202  * so that we can spot it, and should not contain spaces so that makedefs
203  * won't split it across lines.  Ideally the length should be close to
204  * that of the substituted value since we don't do phrase-splitting/line-
205  * wrapping when displaying it.
206  */
207 static struct rt_opt {
208     const char *token, *value;
209 } rt_opts[] = {
210     { ":PATMATCH:", regex_id },
211 };
212
213 /*
214  * 3.6.0
215  * Some optional stuff is no longer available to makedefs because
216  * it depends which of several object files got linked into the
217  * game image, so we insert those options here.
218  */
219 STATIC_OVL void
220 insert_rtoption(buf)
221 char *buf;
222 {
223     int i;
224
225     for (i = 0; i < SIZE(rt_opts); ++i) {
226         if (strstri(buf, rt_opts[i].token))
227             (void) strsubst(buf, rt_opts[i].token, rt_opts[i].value);
228         /* we don't break out of the loop after a match; there might be
229            other matches on the same line */
230     }
231 }
232
233 #ifdef MICRO
234 boolean
235 comp_times(filetime)
236 long filetime;
237 {
238     /* BUILD_TIME is constant but might have L suffix rather than UL;
239        'filetime' is historically signed but ought to have been unsigned */
240     return (boolean) ((unsigned long) filetime < (unsigned long) BUILD_TIME);
241 }
242 #endif
243
244 boolean
245 check_version(version_data, filename, complain)
246 struct version_info *version_data;
247 const char *filename;
248 boolean complain;
249 {
250     if (
251 #ifdef VERSION_COMPATIBILITY
252         version_data->incarnation < VERSION_COMPATIBILITY
253         || version_data->incarnation > VERSION_NUMBER
254 #else
255         version_data->incarnation != VERSION_NUMBER
256 #endif
257         ) {
258         if (complain)
259             pline("Version mismatch for file \"%s\".", filename);
260         return FALSE;
261     } else if (
262 #ifndef IGNORED_FEATURES
263         version_data->feature_set != VERSION_FEATURES
264 #else
265         (version_data->feature_set & ~IGNORED_FEATURES)
266             != (VERSION_FEATURES & ~IGNORED_FEATURES)
267 #endif
268         || version_data->entity_count != VERSION_SANITY1
269         || version_data->struct_sizes1 != VERSION_SANITY2
270         || version_data->struct_sizes2 != VERSION_SANITY3) {
271         if (complain)
272             pline("Configuration incompatibility for file \"%s\".", filename);
273         return FALSE;
274     }
275     return TRUE;
276 }
277
278 /* this used to be based on file date and somewhat OS-dependant,
279    but now examines the initial part of the file's contents */
280 boolean
281 uptodate(fd, name)
282 int fd;
283 const char *name;
284 {
285     int rlen;
286     struct version_info vers_info;
287     boolean verbose = name ? TRUE : FALSE;
288
289     rlen = read(fd, (genericptr_t) &vers_info, sizeof vers_info);
290     minit(); /* ZEROCOMP */
291     if (rlen == 0) {
292         if (verbose) {
293             pline("File \"%s\" is empty?", name);
294             wait_synch();
295         }
296         return FALSE;
297     }
298     if (!check_version(&vers_info, name, verbose)) {
299         if (verbose)
300             wait_synch();
301         return FALSE;
302     }
303     return TRUE;
304 }
305
306 void
307 store_version(fd)
308 int fd;
309 {
310     static const struct version_info version_data = {
311         VERSION_NUMBER, VERSION_FEATURES,
312         VERSION_SANITY1, VERSION_SANITY2, VERSION_SANITY3
313     };
314
315     bufoff(fd);
316     /* bwrite() before bufon() uses plain write() */
317     bwrite(fd, (genericptr_t) &version_data,
318            (unsigned) (sizeof version_data));
319     bufon(fd);
320     return;
321 }
322
323 #ifdef AMIGA
324 const char amiga_version_string[] = AMIGA_VERSION_STRING;
325 #endif
326
327 unsigned long
328 get_feature_notice_ver(str)
329 char *str;
330 {
331     char buf[BUFSZ];
332     int ver_maj, ver_min, patch;
333     char *istr[3];
334     int j = 0;
335
336     if (!str)
337         return 0L;
338     str = strcpy(buf, str);
339     istr[j] = str;
340     while (*str) {
341         if (*str == '.') {
342             *str++ = '\0';
343             j++;
344             istr[j] = str;
345             if (j == 2)
346                 break;
347         } else if (index("0123456789", *str) != 0) {
348             str++;
349         } else
350             return 0L;
351     }
352     if (j != 2)
353         return 0L;
354     ver_maj = atoi(istr[0]);
355     ver_min = atoi(istr[1]);
356     patch = atoi(istr[2]);
357     return FEATURE_NOTICE_VER(ver_maj, ver_min, patch);
358     /* macro from hack.h */
359 }
360
361 unsigned long
362 get_current_feature_ver()
363 {
364     return FEATURE_NOTICE_VER(VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
365 }
366
367 /*ARGUSED*/
368 const char *
369 copyright_banner_line(indx)
370 int indx;
371 {
372 #ifdef COPYRIGHT_BANNER_A
373     if (indx == 1)
374         return COPYRIGHT_BANNER_A;
375 #endif
376 #ifdef COPYRIGHT_BANNER_B
377     if (indx == 2)
378         return COPYRIGHT_BANNER_B;
379 #endif
380 #ifdef COPYRIGHT_BANNER_C
381     if (indx == 3)
382         return COPYRIGHT_BANNER_C;
383 #endif
384 #ifdef COPYRIGHT_BANNER_D
385     if (indx == 4)
386         return COPYRIGHT_BANNER_D;
387 #endif
388     return "";
389 }
390
391 /*version.c*/