Bug Summary

File:src/games/cribbage/io.c
Warning:line 464, column 11
Although the value stored to 'c' is used in the enclosing expression, the value is never actually read from 'c'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name io.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/games/cribbage/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/games/cribbage/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/games/cribbage/io.c
1/* $OpenBSD: io.c,v 1.22 2016/01/10 13:35:09 mestre Exp $ */
2/* $NetBSD: io.c,v 1.9 1997/07/09 06:25:47 phil Exp $ */
3
4/*-
5 * Copyright (c) 1980, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <ctype.h>
34#include <signal.h>
35#include <stdlib.h>
36#include <string.h>
37#include <unistd.h>
38
39#include "cribbage.h"
40#include "cribcur.h"
41
42#define LINESIZE128 128
43
44#ifdef CTRL
45#undef CTRL
46#endif
47#define CTRL(X)(X - 'A' + 1) (X - 'A' + 1)
48
49char linebuf[LINESIZE128];
50
51char *rankname[RANKS13] = {
52 "ACE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
53 "EIGHT", "NINE", "TEN", "JACK", "QUEEN", "KING"
54};
55
56char *rankchar[RANKS13] = {
57 "A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"
58};
59
60char *suitname[SUITS4] = {"SPADES", "HEARTS", "DIAMONDS", "CLUBS"};
61
62char *suitchar[SUITS4] = {"S", "H", "D", "C"};
63
64/*
65 * msgcard:
66 * Call msgcrd in one of two forms
67 */
68int
69msgcard(CARD c, bool_Bool brief)
70{
71 if (brief)
72 return (msgcrd(c, TRUE1, NULL((void *)0), TRUE1));
73 else
74 return (msgcrd(c, FALSE0, " of ", FALSE0));
75}
76
77/*
78 * msgcrd:
79 * Print the value of a card in ascii
80 */
81int
82msgcrd(CARD c, bool_Bool brfrank, char *mid, bool_Bool brfsuit)
83{
84 if (c.rank == EMPTY13 || c.suit == EMPTY13)
85 return (FALSE0);
86 if (brfrank)
87 addmsg("%1.1s", rankchar[c.rank]);
88 else
89 addmsg("%s", rankname[c.rank]);
90 if (mid != NULL((void *)0))
91 addmsg("%s", mid);
92 if (brfsuit)
93 addmsg("%1.1s", suitchar[c.suit]);
94 else
95 addmsg("%s", suitname[c.suit]);
96 return (TRUE1);
97}
98
99/*
100 * printcard:
101 * Print out a card.
102 */
103void
104printcard(WINDOW *win, int cardno, CARD c, bool_Bool blank)
105{
106 prcard(win, cardno * 2, cardno, c, blank);
107}
108
109/*
110 * prcard:
111 * Print out a card on the window at the specified location
112 */
113void
114prcard(WINDOW *win, int y, int x, CARD c, bool_Bool blank)
115{
116 if (c.rank == EMPTY13)
117 return;
118
119 mvwaddstr(win, y + 0, x, "+-----+")(wmove(win,y + 0,x) == (-1) ? (-1) : waddnstr(win,"+-----+",-
1))
;
120 mvwaddstr(win, y + 1, x, "| |")(wmove(win,y + 1,x) == (-1) ? (-1) : waddnstr(win,"| |",-
1))
;
121 mvwaddstr(win, y + 2, x, "| |")(wmove(win,y + 2,x) == (-1) ? (-1) : waddnstr(win,"| |",-
1))
;
122 mvwaddstr(win, y + 3, x, "| |")(wmove(win,y + 3,x) == (-1) ? (-1) : waddnstr(win,"| |",-
1))
;
123 mvwaddstr(win, y + 4, x, "+-----+")(wmove(win,y + 4,x) == (-1) ? (-1) : waddnstr(win,"+-----+",-
1))
;
124 if (!blank) {
125 mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0])(wmove(win,y + 1,x + 1) == (-1) ? (-1) : waddch(win,rankchar[
c.rank][0]))
;
126 waddch(win, suitchar[c.suit][0]);
127 mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0])(wmove(win,y + 3,x + 4) == (-1) ? (-1) : waddch(win,rankchar[
c.rank][0]))
;
128 waddch(win, suitchar[c.suit][0]);
129 }
130}
131
132/*
133 * prhand:
134 * Print a hand of n cards
135 */
136void
137prhand(CARD h[], int n, WINDOW *win, bool_Bool blank)
138{
139 int i;
140
141 werase(win);
142 for (i = 0; i < n; i++)
143 printcard(win, i, *h++, blank);
144 wrefresh(win);
145}
146
147/*
148 * infrom:
149 * reads a card, supposedly in hand, accepting unambiguous brief
150 * input, returns the index of the card found...
151 */
152int
153infrom(CARD hand[], int n, char *prompt)
154{
155 int i, j;
156 CARD crd;
157
158 if (n < 1) {
159 bye();
160 printf("\nINFROM: %d = n < 1!!\n", n);
161 exit(74);
162 }
163 for (;;) {
164 msg("%s", prompt);
165 if (incard(&crd)) { /* if card is full card */
166 if (!isone(crd, hand, n))
167 msg("That's not in your hand");
168 else {
169 for (i = 0; i < n; i++)
170 if (hand[i].rank == crd.rank &&
171 hand[i].suit == crd.suit)
172 break;
173 if (i >= n) {
174 bye();
175 printf("\nINFROM: isone or something messed up\n");
176 exit(77);
177 }
178 return (i);
179 }
180 } else /* if not full card... */
181 if (crd.rank != EMPTY13) {
182 for (i = 0; i < n; i++)
183 if (hand[i].rank == crd.rank)
184 break;
185 if (i >= n)
186 msg("No such rank in your hand");
187 else {
188 for (j = i + 1; j < n; j++)
189 if (hand[j].rank == crd.rank)
190 break;
191 if (j < n)
192 msg("Ambiguous rank");
193 else
194 return (i);
195 }
196 } else
197 msg("Sorry, I missed that");
198 }
199}
200
201/*
202 * incard:
203 * Inputs a card in any format. It reads a line ending with a CR
204 * and then parses it.
205 */
206int
207incard(CARD *crd)
208{
209 int i;
210 int rnk, sut;
211 char *p, *p1;
212 bool_Bool retval;
213
214 retval = FALSE0;
215 rnk = sut = EMPTY13;
216 p1 = get_line();
217 if (*p1 == '\0')
218 goto gotit;
219 p = p1;
220 while (*p1 != ' ' && *p1 != '\0')
221 ++p1;
222 *p1++ = '\0';
223
224 /* IMPORTANT: no real card has 2 char first name */
225 if (p + 3 == p1) { /* check for short form */
226 for (i = 0; i < RANKS13; i++) {
227 if (*p == *rankchar[i]) {
228 rnk = i;
229 break;
230 }
231 }
232 if (rnk == EMPTY13)
233 goto gotit; /* it's nothing... */
234 ++p; /* advance to next char */
235 for (i = 0; i < SUITS4; i++) {
236 if (*p == *suitchar[i]) {
237 sut = i;
238 break;
239 }
240 }
241 if (sut != EMPTY13)
242 retval = TRUE1;
243 goto gotit;
244 }
245 for (i = 0; i < RANKS13; i++) {
246 if (!strcmp(p, rankname[i]) || !strcmp(p, rankchar[i])) {
247 rnk = i;
248 break;
249 }
250 }
251 if (rnk == EMPTY13 || *p1 == '\0')
252 goto gotit;
253 p = p1;
254 while (*p1 != ' ' && *p1 != '\0')
255 ++p1;
256 *p1++ = '\0';
257 if (!strcmp("OF", p)) {
258 if (*p1 == '\0')
259 goto gotit;
260 p = p1;
261 while (*p1 != ' ' && *p1 != '\0')
262 ++p1;
263 *p1 = '\0';
264 }
265 for (i = 0; i < SUITS4; i++) {
266 if (!strcmp(p, suitname[i]) || !strcmp(p, suitchar[i])) {
267 sut = i;
268 break;
269 }
270 }
271 if (sut != EMPTY13)
272 retval = TRUE1;
273gotit:
274 (*crd).rank = rnk;
275 (*crd).suit = sut;
276 return (retval);
277}
278
279/*
280 * getuchar:
281 * Reads and converts to upper case
282 */
283int
284getuchar(void)
285{
286 int c;
287
288 c = readchar();
289 if (islower(c))
290 c = toupper(c);
291 waddch(Msgwin, c);
292 return (c);
293}
294
295/*
296 * number:
297 * Reads in a decimal number and makes sure it is between "lo" and
298 * "hi" inclusive.
299 */
300int
301number(int lo, int hi, char *prompt)
302{
303 char *p;
304 int sum, tmp;
305
306 for (sum = 0;;) {
307 msg("%s", prompt);
308 p = get_line();
309 if (*p == '\0') {
310 msg(quiet ? "Not a number" :
311 "That doesn't look like a number");
312 continue;
313 }
314 sum = 0;
315
316 if (!isdigit((unsigned char)*p))
317 sum = lo - 1;
318 else
319 while (isdigit((unsigned char)*p)) {
320 tmp = 10 * sum + (*p - '0');
321 /* Overflow */
322 if (tmp < sum) {
323 sum = hi + 1;
324 while (isdigit((unsigned char)*p))
325 ++p;
326 break;
327 }
328 sum = tmp;
329 ++p;
330 }
331
332 if (*p != ' ' && *p != '\t' && *p != '\0')
333 sum = lo - 1;
334 if (sum >= lo && sum <= hi)
335 break;
336 if (sum == lo - 1)
337 msg(quiet ? "Not a number" :
338 "That doesn't look like a number");
339 else
340 msg("That is not between %d and %d inclusive",
341 lo, hi);
342 }
343 return (sum);
344}
345
346/*
347 * msg:
348 * Display a message at the top of the screen.
349 */
350char Msgbuf[BUFSIZ1024] = {'\0'};
351int Mpos = 0;
352static int Newpos = 0;
353
354void
355msg(const char *fmt, ...)
356{
357 va_list ap;
358
359 va_start(ap, fmt)__builtin_va_start(ap, fmt);
360 (void)vsnprintf(&Msgbuf[Newpos], sizeof Msgbuf - Newpos, fmt, ap);
361 Newpos = strlen(Msgbuf);
362 va_end(ap)__builtin_va_end(ap);
363 endmsg();
364}
365
366/*
367 * addmsg:
368 * Add things to the current message
369 */
370void
371addmsg(const char *fmt, ...)
372{
373 va_list ap;
374
375 va_start(ap, fmt)__builtin_va_start(ap, fmt);
376 (void)vsnprintf(&Msgbuf[Newpos], sizeof Msgbuf - Newpos, fmt, ap);
377 Newpos = strlen(Msgbuf);
378 va_end(ap)__builtin_va_end(ap);
379}
380
381/*
382 * endmsg:
383 * Display a new msg.
384 */
385int Lineno = 0;
386
387void
388endmsg(void)
389{
390 static int lastline = 0;
391 int len;
392 char *mp, *omp;
393
394 /* All messages should start with uppercase */
395 mvaddch(lastline + Y_MSG_START, SCORE_X, ' ')(wmove(stdscr,lastline + (9 + 1),(12 + 14 + 12)) == (-1) ? (-
1) : waddch(stdscr,' '))
;
396 if (islower((unsigned char)Msgbuf[0]) && Msgbuf[1] != ')')
397 Msgbuf[0] = toupper((unsigned char)Msgbuf[0]);
398 mp = Msgbuf;
399 len = strlen(mp);
400 if (len / MSG_X(COLS - (12 + 14 + 12) - 1) + Lineno >= MSG_Y(LINES - (9 + 1))) {
401 while (Lineno < MSG_Y(LINES - (9 + 1))) {
402 wmove(Msgwin, Lineno++, 0);
403 wclrtoeol(Msgwin);
404 }
405 Lineno = 0;
406 }
407 mvaddch(Lineno + Y_MSG_START, SCORE_X, '*')(wmove(stdscr,Lineno + (9 + 1),(12 + 14 + 12)) == (-1) ? (-1)
: waddch(stdscr,'*'))
;
408 lastline = Lineno;
409 do {
410 mvwaddstr(Msgwin, Lineno, 0, mp)(wmove(Msgwin,Lineno,0) == (-1) ? (-1) : waddnstr(Msgwin,mp,-
1))
;
411 if ((len = strlen(mp)) > MSG_X(COLS - (12 + 14 + 12) - 1)) {
412 omp = mp;
413 for (mp = &mp[MSG_X(COLS - (12 + 14 + 12) - 1) - 1]; *mp != ' '; mp--)
414 continue;
415 while (*mp == ' ')
416 mp--;
417 mp++;
418 wmove(Msgwin, Lineno, mp - omp);
419 wclrtoeol(Msgwin);
420 }
421 if (++Lineno >= MSG_Y(LINES - (9 + 1)))
422 Lineno = 0;
423 } while (len > MSG_X(COLS - (12 + 14 + 12) - 1));
424 wclrtoeol(Msgwin);
425 Mpos = len;
426 Newpos = 0;
427 wrefresh(Msgwin);
428 refresh()wrefresh(stdscr);
429 wrefresh(Msgwin);
430}
431
432/*
433 * do_wait:
434 * Wait for the user to type ' ' before doing anything else
435 */
436void
437do_wait(void)
438{
439 static char prompt[] = {'-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0'};
440
441 if (Mpos + sizeof prompt < MSG_X(COLS - (12 + 14 + 12) - 1))
442 wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y(LINES - (9 + 1)) - 1, Mpos);
443 else {
444 mvwaddch(Msgwin, Lineno, 0, ' ')(wmove(Msgwin,Lineno,0) == (-1) ? (-1) : waddch(Msgwin,' '));
445 wclrtoeol(Msgwin);
446 if (++Lineno >= MSG_Y(LINES - (9 + 1)))
447 Lineno = 0;
448 }
449 waddstr(Msgwin, prompt)waddnstr(Msgwin,prompt,-1);
450 wrefresh(Msgwin);
451 wait_for(' ');
452}
453
454/*
455 * wait_for
456 * Sit around until the guy types the right key
457 */
458void
459wait_for(int ch)
460{
461 char c;
462
463 if (ch == '\n')
464 while ((c = readchar()) != '\n')
Although the value stored to 'c' is used in the enclosing expression, the value is never actually read from 'c'
465 continue;
466 else
467 while (readchar() != ch)
468 continue;
469}
470
471/*
472 * readchar:
473 * Reads and returns a character, checking for gross input errors
474 */
475int
476readchar(void)
477{
478 int cnt;
479 char c;
480
481over:
482 cnt = 0;
483 while (read(STDIN_FILENO0, &c, sizeof(char)) <= 0)
484 if (cnt++ > 100) { /* if we are getting infinite EOFs */
485 bye(); /* quit the game */
486 exit(1);
487 }
488 if (c == CTRL('L')('L' - 'A' + 1)) {
489 wrefresh(curscr);
490 goto over;
491 }
492 if (c == '\r')
493 return ('\n');
494 else
495 return (c);
496}
497
498/*
499 * get_line:
500 * Reads the next line up to '\n' or EOF. Multiple spaces are
501 * compressed to one space; a space is inserted before a ','
502 */
503char *
504get_line(void)
505{
506 size_t pos;
507 int c, oy, ox;
508 WINDOW *oscr;
509
510 oscr = stdscr;
511 stdscr = Msgwin;
512 getyx(stdscr, oy, ox)(oy = ((stdscr) ? (stdscr)->_cury : (-1)), ox = ((stdscr) ?
(stdscr)->_curx : (-1)))
;
513 refresh()wrefresh(stdscr);
514 /* loop reading in the string, and put it in a temporary buffer */
515 for (pos = 0; (c = readchar()) != '\n'; clrtoeol()wclrtoeol(stdscr), refresh()wrefresh(stdscr)) {
516 if (c == -1)
517 continue;
518 if (c == ' ' && (pos == 0 || linebuf[pos - 1] == ' '))
519 continue;
520 if (c == erasechar()) {
521 if (pos > 0) {
522 int i;
523 pos--;
524 for (i = strlen(unctrl(linebuf[pos])); i; i--)
525 addch('\b')waddch(stdscr,'\b');
526 }
527 continue;
528 }
529 if (c == killchar()) {
530 pos = 0;
531 move(oy, ox)wmove(stdscr,oy,ox);
532 continue;
533 }
534 if (pos >= LINESIZE128 - 1 || !(isalnum(c) || c == ' ')) {
535 beep();
536 continue;
537 }
538 if (islower(c))
539 c = toupper(c);
540 linebuf[pos++] = c;
541 addstr(unctrl(c))waddnstr(stdscr,unctrl(c),-1);
542 Mpos++;
543 }
544 while (pos < sizeof(linebuf))
545 linebuf[pos++] = '\0';
546 stdscr = oscr;
547 return (linebuf);
548}
549
550void
551rintsig(int signo)
552{
553 bye();
554 exit(1);
555}
556
557/*
558 * bye:
559 * Leave the program, cleaning things up as we go.
560 */
561void
562bye(void)
563{
564 signal(SIGINT2, SIG_IGN(void (*)(int))1);
565 mvcur(0, COLS - 1, LINES - 1, 0);
566 fflush(stdout(&__sF[1]));
567 endwin();
568 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
569}