OSDN Git Service

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