Bug Summary

File:src/usr.bin/vi/build/../common/options.c
Warning:line 854, column 20
Division by zero

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 options.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/usr.bin/vi/build/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/vi/build -I /usr/src/usr.bin/vi/build/../include -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/vi/build/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/usr.bin/vi/build/../common/options.c
1/* $OpenBSD: options.c,v 1.29 2021/04/13 15:39:21 millert Exp $ */
2
3/*-
4 * Copyright (c) 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1991, 1993, 1994, 1995, 1996
7 * Keith Bostic. All rights reserved.
8 *
9 * See the LICENSE file for redistribution information.
10 */
11
12#include "config.h"
13
14#include <sys/types.h>
15#include <sys/queue.h>
16#include <sys/stat.h>
17#include <sys/time.h>
18
19#include <bitstring.h>
20#include <ctype.h>
21#include <errno(*__errno()).h>
22#include <limits.h>
23#include <paths.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28
29#include "common.h"
30#include "../vi/vi.h"
31#include "pathnames.h"
32
33static int opts_abbcmp(const void *, const void *);
34static int opts_cmp(const void *, const void *);
35static int opts_print(SCR *, OPTLIST const *);
36
37/*
38 * O'Reilly noted options and abbreviations are from "Learning the VI Editor",
39 * Fifth Edition, May 1992. There's no way of knowing what systems they are
40 * actually from.
41 *
42 * HPUX noted options and abbreviations are from "The Ultimate Guide to the
43 * VI and EX Text Editors", 1990.
44 */
45OPTLIST const optlist[] = {
46/* O_ALTWERASE 4.4BSD */
47 {"altwerase", f_altwerase, OPT_0BOOL, 0},
48/* O_AUTOINDENT 4BSD */
49 {"autoindent", NULL((void *)0), OPT_0BOOL, 0},
50/* O_AUTOPRINT 4BSD */
51 {"autoprint", NULL((void *)0), OPT_1BOOL, 0},
52/* O_AUTOWRITE 4BSD */
53 {"autowrite", NULL((void *)0), OPT_0BOOL, 0},
54/* O_BACKUP 4.4BSD */
55 {"backup", NULL((void *)0), OPT_STR, 0},
56/* O_BEAUTIFY 4BSD */
57 {"beautify", NULL((void *)0), OPT_0BOOL, 0},
58/* O_CDPATH 4.4BSD */
59 {"cdpath", NULL((void *)0), OPT_STR, 0},
60/* O_CEDIT 4.4BSD */
61 {"cedit", NULL((void *)0), OPT_STR, 0},
62/* O_COLUMNS 4.4BSD */
63 {"columns", f_columns, OPT_NUM, OPT_NOSAVE0x008},
64/* O_COMMENT 4.4BSD */
65 {"comment", NULL((void *)0), OPT_0BOOL, 0},
66/* O_EDCOMPATIBLE 4BSD */
67 {"edcompatible",NULL((void *)0), OPT_0BOOL, 0},
68/* O_ESCAPETIME 4.4BSD */
69 {"escapetime", NULL((void *)0), OPT_NUM, 0},
70/* O_ERRORBELLS 4BSD */
71 {"errorbells", NULL((void *)0), OPT_0BOOL, 0},
72/* O_EXPANDTAB NetBSD 5.0 */
73 {"expandtab", NULL((void *)0), OPT_0BOOL, 0},
74/* O_EXRC System V (undocumented) */
75 {"exrc", NULL((void *)0), OPT_0BOOL, 0},
76/* O_EXTENDED 4.4BSD */
77 {"extended", f_recompile, OPT_0BOOL, 0},
78/* O_FILEC 4.4BSD */
79 {"filec", NULL((void *)0), OPT_STR, 0},
80/* O_FLASH HPUX */
81 {"flash", NULL((void *)0), OPT_0BOOL, 0},
82/* O_HARDTABS 4BSD */
83 {"hardtabs", NULL((void *)0), OPT_NUM, 0},
84/* O_ICLOWER 4.4BSD */
85 {"iclower", f_recompile, OPT_0BOOL, 0},
86/* O_IGNORECASE 4BSD */
87 {"ignorecase", f_recompile, OPT_0BOOL, 0},
88/* O_KEYTIME 4.4BSD */
89 {"keytime", NULL((void *)0), OPT_NUM, 0},
90/* O_LEFTRIGHT 4.4BSD */
91 {"leftright", f_reformat, OPT_0BOOL, 0},
92/* O_LINES 4.4BSD */
93 {"lines", f_lines, OPT_NUM, OPT_NOSAVE0x008},
94/* O_LIST 4BSD */
95 {"list", f_reformat, OPT_0BOOL, 0},
96/* O_LOCKFILES 4.4BSD
97 * XXX
98 * Locking isn't reliable enough over NFS to require it, in addition,
99 * it's a serious startup performance problem over some remote links.
100 */
101 {"lock", NULL((void *)0), OPT_1BOOL, 0},
102/* O_MAGIC 4BSD */
103 {"magic", NULL((void *)0), OPT_1BOOL, 0},
104/* O_MATCHTIME 4.4BSD */
105 {"matchtime", NULL((void *)0), OPT_NUM, 0},
106/* O_MESG 4BSD */
107 {"mesg", NULL((void *)0), OPT_1BOOL, 0},
108/* O_NOPRINT 4.4BSD */
109 {"noprint", f_print, OPT_STR, OPT_EARLYSET0x080},
110/* O_NUMBER 4BSD */
111 {"number", f_reformat, OPT_0BOOL, 0},
112/* O_OCTAL 4.4BSD */
113 {"octal", f_print, OPT_0BOOL, OPT_EARLYSET0x080},
114/* O_OPEN 4BSD */
115 {"open", NULL((void *)0), OPT_1BOOL, 0},
116/* O_PARAGRAPHS 4BSD */
117 {"paragraphs", f_paragraph, OPT_STR, 0},
118/* O_PATH 4.4BSD */
119 {"path", NULL((void *)0), OPT_STR, 0},
120/* O_PRINT 4.4BSD */
121 {"print", f_print, OPT_STR, OPT_EARLYSET0x080},
122/* O_PROMPT 4BSD */
123 {"prompt", NULL((void *)0), OPT_1BOOL, 0},
124/* O_READONLY 4BSD (undocumented) */
125 {"readonly", f_readonly, OPT_0BOOL, OPT_ALWAYS0x002},
126/* O_RECDIR 4.4BSD */
127 {"recdir", NULL((void *)0), OPT_STR, 0},
128/* O_REMAP 4BSD */
129 {"remap", NULL((void *)0), OPT_1BOOL, 0},
130/* O_REPORT 4BSD */
131 {"report", NULL((void *)0), OPT_NUM, 0},
132/* O_RULER 4.4BSD */
133 {"ruler", NULL((void *)0), OPT_0BOOL, 0},
134/* O_SCROLL 4BSD */
135 {"scroll", NULL((void *)0), OPT_NUM, 0},
136/* O_SEARCHINCR 4.4BSD */
137 {"searchincr", NULL((void *)0), OPT_0BOOL, 0},
138/* O_SECTIONS 4BSD */
139 {"sections", f_section, OPT_STR, 0},
140/* O_SECURE 4.4BSD */
141 {"secure", f_secure, OPT_0BOOL, OPT_NOUNSET0x020},
142/* O_SHELL 4BSD */
143 {"shell", NULL((void *)0), OPT_STR, 0},
144/* O_SHELLMETA 4.4BSD */
145 {"shellmeta", NULL((void *)0), OPT_STR, 0},
146/* O_SHIFTWIDTH 4BSD */
147 {"shiftwidth", NULL((void *)0), OPT_NUM, OPT_NOZERO0x040},
148/* O_SHOWMATCH 4BSD */
149 {"showmatch", NULL((void *)0), OPT_0BOOL, 0},
150/* O_SHOWMODE 4.4BSD */
151 {"showmode", NULL((void *)0), OPT_0BOOL, 0},
152/* O_SIDESCROLL 4.4BSD */
153 {"sidescroll", NULL((void *)0), OPT_NUM, OPT_NOZERO0x040},
154/* O_TABSTOP 4BSD */
155 {"tabstop", f_reformat, OPT_NUM, OPT_NOZERO0x040},
156/* O_TAGLENGTH 4BSD */
157 {"taglength", NULL((void *)0), OPT_NUM, 0},
158/* O_TAGS 4BSD */
159 {"tags", NULL((void *)0), OPT_STR, 0},
160/* O_TERM 4BSD
161 * !!!
162 * By default, the historic vi always displayed information about two
163 * options, redraw and term. Term seems sufficient.
164 */
165 {"term", NULL((void *)0), OPT_STR, OPT_ADISP0x001|OPT_NOSAVE0x008},
166/* O_TERSE 4BSD */
167 {"terse", NULL((void *)0), OPT_0BOOL, 0},
168/* O_TILDEOP 4.4BSD */
169 {"tildeop", NULL((void *)0), OPT_0BOOL, 0},
170/* O_TIMEOUT 4BSD (undocumented) */
171 {"timeout", NULL((void *)0), OPT_1BOOL, 0},
172/* O_TTYWERASE 4.4BSD */
173 {"ttywerase", f_ttywerase, OPT_0BOOL, 0},
174/* O_VERBOSE 4.4BSD */
175 {"verbose", NULL((void *)0), OPT_0BOOL, 0},
176/* O_W1200 4BSD */
177 {"w1200", f_w1200, OPT_NUM, OPT_NDISP0x004|OPT_NOSAVE0x008},
178/* O_W300 4BSD */
179 {"w300", f_w300, OPT_NUM, OPT_NDISP0x004|OPT_NOSAVE0x008},
180/* O_W9600 4BSD */
181 {"w9600", f_w9600, OPT_NUM, OPT_NDISP0x004|OPT_NOSAVE0x008},
182/* O_WARN 4BSD */
183 {"warn", NULL((void *)0), OPT_1BOOL, 0},
184/* O_WINDOW 4BSD */
185 {"window", f_window, OPT_NUM, OPT_NOZERO0x040},
186/* O_WINDOWNAME 4BSD */
187 {"windowname", NULL((void *)0), OPT_0BOOL, 0},
188/* O_WRAPLEN 4.4BSD */
189 {"wraplen", NULL((void *)0), OPT_NUM, 0},
190/* O_WRAPMARGIN 4BSD */
191 {"wrapmargin", NULL((void *)0), OPT_NUM, 0},
192/* O_WRAPSCAN 4BSD */
193 {"wrapscan", NULL((void *)0), OPT_1BOOL, 0},
194/* O_WRITEANY 4BSD */
195 {"writeany", NULL((void *)0), OPT_0BOOL, 0},
196 {NULL((void *)0)},
197};
198
199typedef struct abbrev {
200 char *name;
201 int offset;
202} OABBREV;
203
204static OABBREV const abbrev[] = {
205 {"ai", O_AUTOINDENT}, /* 4BSD */
206 {"ap", O_AUTOPRINT}, /* 4BSD */
207 {"aw", O_AUTOWRITE}, /* 4BSD */
208 {"bf", O_BEAUTIFY}, /* 4BSD */
209 {"co", O_COLUMNS}, /* 4.4BSD */
210 {"eb", O_ERRORBELLS}, /* 4BSD */
211 {"ed", O_EDCOMPATIBLE}, /* 4BSD */
212 {"et", O_EXPANDTAB}, /* NetBSD 5.0 */
213 {"ex", O_EXRC}, /* System V (undocumented) */
214 {"ht", O_HARDTABS}, /* 4BSD */
215 {"ic", O_IGNORECASE}, /* 4BSD */
216 {"li", O_LINES}, /* 4.4BSD */
217 {"nu", O_NUMBER}, /* 4BSD */
218 {"para", O_PARAGRAPHS}, /* 4BSD */
219 {"ro", O_READONLY}, /* 4BSD (undocumented) */
220 {"scr", O_SCROLL}, /* 4BSD (undocumented) */
221 {"sect", O_SECTIONS}, /* O'Reilly */
222 {"sh", O_SHELL}, /* 4BSD */
223 {"sm", O_SHOWMATCH}, /* 4BSD */
224 {"smd", O_SHOWMODE}, /* 4BSD */
225 {"sw", O_SHIFTWIDTH}, /* 4BSD */
226 {"tag", O_TAGS}, /* 4BSD (undocumented) */
227 {"tl", O_TAGLENGTH}, /* 4BSD */
228 {"to", O_TIMEOUT}, /* 4BSD (undocumented) */
229 {"ts", O_TABSTOP}, /* 4BSD */
230 {"tty", O_TERM}, /* 4BSD (undocumented) */
231 {"ttytype", O_TERM}, /* 4BSD (undocumented) */
232 {"w", O_WINDOW}, /* O'Reilly */
233 {"wa", O_WRITEANY}, /* 4BSD */
234 {"wi", O_WINDOW}, /* 4BSD (undocumented) */
235 {"wl", O_WRAPLEN}, /* 4.4BSD */
236 {"wm", O_WRAPMARGIN}, /* 4BSD */
237 {"ws", O_WRAPSCAN}, /* 4BSD */
238 {NULL((void *)0)},
239};
240
241/*
242 * opts_init --
243 * Initialize some of the options.
244 *
245 * PUBLIC: int opts_init(SCR *, int *);
246 */
247int
248opts_init(SCR *sp, int *oargs)
249{
250 ARGS *argv[2], a, b;
251 OPTLIST const *op;
252 u_long v;
253 int optindx;
254 char *s, b1[1024];
255
256 a.bp = b1;
257 b.bp = NULL((void *)0);
258 a.len = b.len = 0;
259 argv[0] = &a;
260 argv[1] = &b;
261
262 /* Set numeric and string default values. */
263#define OI_b1(indx) { \
264 a.len = strlen(b1); \
265 if (opts_set(sp, argv, NULL((void *)0))) { \
266 optindx = indx; \
267 goto err; \
268 } \
269}
270#define OI(indx, str) { \
271 (void)strlcpy(b1, (str), sizeof(b1)); \
272 OI_b1(indx); \
273}
274
275 /*
276 * Indirect global options to global space. Specifically, set up
277 * terminal, lines, columns first, they're used by other options.
278 * Note, don't set the flags until we've set up the indirection.
279 */
280 if (o_set(sp, O_TERM, 0, NULL((void *)0), GO_TERM3)) {
281 optindx = O_TERM;
282 goto err;
283 }
284 F_SET(&sp->opts[O_TERM], OPT_GLOBAL)(((&sp->opts[O_TERM])->flags) |= ((0x01)));
285 if (o_set(sp, O_LINES, 0, NULL((void *)0), GO_LINES1)) {
286 optindx = O_LINES;
287 goto err;
288 }
289 F_SET(&sp->opts[O_LINES], OPT_GLOBAL)(((&sp->opts[O_LINES])->flags) |= ((0x01)));
290 if (o_set(sp, O_COLUMNS, 0, NULL((void *)0), GO_COLUMNS0)) {
291 optindx = O_COLUMNS;
292 goto err;
293 }
294 F_SET(&sp->opts[O_COLUMNS], OPT_GLOBAL)(((&sp->opts[O_COLUMNS])->flags) |= ((0x01)));
295 if (o_set(sp, O_SECURE, 0, NULL((void *)0), GO_SECURE2)) {
296 optindx = O_SECURE;
297 goto err;
298 }
299 F_SET(&sp->opts[O_SECURE], OPT_GLOBAL)(((&sp->opts[O_SECURE])->flags) |= ((0x01)));
300
301 /* Initialize string values. */
302 (void)snprintf(b1, sizeof(b1),
303 "cdpath=%s", (s = getenv("CDPATH")) == NULL((void *)0) ? ":" : s);
304 OI_b1(O_CDPATH);
305 OI(O_ESCAPETIME, "escapetime=1");
306 OI(O_FILEC, "filec=\t");
307 OI(O_KEYTIME, "keytime=6");
308 OI(O_MATCHTIME, "matchtime=7");
309 OI(O_REPORT, "report=5");
310 OI(O_PARAGRAPHS, "paragraphs=IPLPPPQPP LIpplpipbpBlBdPpLpIt");
311 OI(O_PATH, "path=");
312 (void)snprintf(b1, sizeof(b1), "recdir=%s", _PATH_PRESERVE"/tmp/vi.recover");
313 OI_b1(O_RECDIR);
314 OI(O_SECTIONS, "sections=NHSHH HUnhshShSs");
315 (void)snprintf(b1, sizeof(b1),
316 "shell=%s", (s = getenv("SHELL")) == NULL((void *)0) ? _PATH_BSHELL"/bin/sh" : s);
317 OI_b1(O_SHELL);
318 OI(O_SHELLMETA, "shellmeta=~{[*?$`'\"\\");
319 OI(O_SHIFTWIDTH, "shiftwidth=8");
320 OI(O_SIDESCROLL, "sidescroll=16");
321 OI(O_TABSTOP, "tabstop=8");
322 (void)snprintf(b1, sizeof(b1), "tags=%s", _PATH_TAGS"tags");
323 OI_b1(O_TAGS);
324
325 /*
326 * XXX
327 * Initialize O_SCROLL here, after term; initializing term should
328 * have created a LINES/COLUMNS value.
329 */
330 if ((v = (O_VAL(sp, O_LINES)((((&((sp))->opts[((O_LINES))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((O_LINES))].o_cur
.val].o_cur.val : ((sp))->opts[((O_LINES))].o_cur.val)
- 1) / 2) == 0)
331 v = 1;
332 (void)snprintf(b1, sizeof(b1), "scroll=%ld", v);
333 OI_b1(O_SCROLL);
334
335 /*
336 * The default window option values are:
337 * 8 if baud rate <= 600
338 * 16 if baud rate <= 1200
339 * LINES - 1 if baud rate > 1200
340 *
341 * Note, the windows option code will correct any too-large value
342 * or when the O_LINES value is 1.
343 */
344 if (sp->gp->scr_baud(sp, &v))
345 return (1);
346 if (v <= 600)
347 v = 8;
348 else if (v <= 1200)
349 v = 16;
350 else
351 v = O_VAL(sp, O_LINES)((((&((sp))->opts[((O_LINES))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((O_LINES))].o_cur
.val].o_cur.val : ((sp))->opts[((O_LINES))].o_cur.val)
- 1;
352 (void)snprintf(b1, sizeof(b1), "window=%lu", v);
353 OI_b1(O_WINDOW);
354
355 /*
356 * Set boolean default values, and copy all settings into the default
357 * information. OS_NOFREE is set, we're copying, not replacing.
358 */
359 for (op = optlist, optindx = 0; op->name != NULL((void *)0); ++op, ++optindx)
360 switch (op->type) {
361 case OPT_0BOOL:
362 break;
363 case OPT_1BOOL:
364 O_SET(sp, optindx)o_set((sp), (optindx), 0, ((void *)0), 1);
365 O_D_SET(sp, optindx)o_set((sp), (optindx), 0x01, ((void *)0), 1);
366 break;
367 case OPT_NUM:
368 o_set(sp, optindx, OS_DEF0x01, NULL((void *)0), O_VAL(sp, optindx)((((&((sp))->opts[((optindx))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((optindx))].o_cur
.val].o_cur.val : ((sp))->opts[((optindx))].o_cur.val)
);
369 break;
370 case OPT_STR:
371 if (O_STR(sp, optindx)((((&((sp))->opts[((optindx))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((optindx))].o_cur
.val].o_cur.str : ((sp))->opts[((optindx))].o_cur.str)
!= NULL((void *)0) && o_set(sp, optindx,
372 OS_DEF0x01 | OS_NOFREE0x02 | OS_STRDUP0x08, O_STR(sp, optindx)((((&((sp))->opts[((optindx))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((optindx))].o_cur
.val].o_cur.str : ((sp))->opts[((optindx))].o_cur.str)
, 0))
373 goto err;
374 break;
375 default:
376 abort();
377 }
378
379 /*
380 * !!!
381 * Some options can be initialized by the command name or the
382 * command-line arguments. They don't set the default values,
383 * it's historic practice.
384 */
385 for (; *oargs != -1; ++oargs)
386 OI(*oargs, optlist[*oargs].name);
387 return (0);
388#undef OI
389#undef OI_b1
390
391err: msgq(sp, M_ERR,
392 "Unable to set default %s option", optlist[optindx].name);
393 return (1);
394}
395
396/*
397 * opts_set --
398 * Change the values of one or more options.
399 *
400 * PUBLIC: int opts_set(SCR *, ARGS *[], char *);
401 */
402int
403opts_set(SCR *sp, ARGS *argv[], char *usage)
404{
405 enum optdisp disp;
406 enum nresult nret;
407 OPTLIST const *op;
408 OPTION *spo;
409 u_long value, turnoff;
410 int ch, equals, nf, nf2, offset, qmark, rval;
411 char *endp, *name, *p, *sep, *t;
412
413 disp = NO_DISPLAY;
414 for (rval = 0; argv[0]->len != 0; ++argv) {
415 /*
416 * The historic vi dumped the options for each occurrence of
417 * "all" in the set list. Puhleeze.
418 */
419 if (!strcmp(argv[0]->bp, "all")) {
420 disp = ALL_DISPLAY;
421 continue;
422 }
423
424 /* Find equals sign or question mark. */
425 for (sep = NULL((void *)0), equals = qmark = 0,
426 p = name = argv[0]->bp; (ch = *p) != '\0'; ++p)
427 if (ch == '=' || ch == '?') {
428 if (p == name) {
429 if (usage != NULL((void *)0))
430 msgq(sp, M_ERR,
431 "Usage: %s", usage);
432 return (1);
433 }
434 sep = p;
435 if (ch == '=')
436 equals = 1;
437 else
438 qmark = 1;
439 break;
440 }
441
442 turnoff = 0;
443 op = NULL((void *)0);
444 if (sep != NULL((void *)0))
445 *sep++ = '\0';
446
447 /* Search for the name, then name without any leading "no". */
448 if ((op = opts_search(name)) == NULL((void *)0) &&
449 name[0] == 'n' && name[1] == 'o') {
450 turnoff = 1;
451 name += 2;
452 op = opts_search(name);
453 }
454 if (op == NULL((void *)0)) {
455 opts_nomatch(sp, name);
456 rval = 1;
457 continue;
458 }
459
460 /* Find current option values. */
461 offset = op - optlist;
462 spo = sp->opts + offset;
463
464 /*
465 * !!!
466 * Historically, the question mark could be a separate
467 * argument.
468 */
469 if (!equals && !qmark &&
470 argv[1]->len == 1 && argv[1]->bp[0] == '?') {
471 ++argv;
472 qmark = 1;
473 }
474
475 /* Set name, value. */
476 switch (op->type) {
477 case OPT_0BOOL:
478 case OPT_1BOOL:
479 /* Some options may not be reset. */
480 if (F_ISSET(op, OPT_NOUNSET)(((op)->flags) & ((0x020))) && turnoff) {
481 msgq_str(sp, M_ERR, name,
482 "set: the %s option may not be turned off");
483 rval = 1;
484 break;
485 }
486
487 if (equals) {
488 msgq_str(sp, M_ERR, name,
489 "set: [no]%s option doesn't take a value");
490 rval = 1;
491 break;
492 }
493 if (qmark) {
494 if (!disp)
495 disp = SELECT_DISPLAY;
496 F_SET(spo, OPT_SELECTED)(((spo)->flags) |= ((0x02)));
497 break;
498 }
499
500 /*
501 * Do nothing if the value is unchanged, the underlying
502 * functions can be expensive.
503 */
504 if (!F_ISSET(op, OPT_ALWAYS)(((op)->flags) & ((0x002)))) {
505 if (turnoff) {
506 if (!O_ISSET(sp, offset)((((&(((sp)))->opts[(((offset)))])->flags) & ((
0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((offset
)))].o_cur.val].o_cur.val : (((sp)))->opts[(((offset)))].o_cur
.val)
)
507 break;
508 } else {
509 if (O_ISSET(sp, offset)((((&(((sp)))->opts[(((offset)))])->flags) & ((
0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((offset
)))].o_cur.val].o_cur.val : (((sp)))->opts[(((offset)))].o_cur
.val)
)
510 break;
511 }
512 }
513
514 if (F_ISSET(op, OPT_EARLYSET)(((op)->flags) & ((0x080)))) {
515 /* Set the value. */
516 if (turnoff)
517 O_CLR(sp, offset)o_set((sp), (offset), 0, ((void *)0), 0);
518 else
519 O_SET(sp, offset)o_set((sp), (offset), 0, ((void *)0), 1);
520 }
521
522 /* Report to subsystems. */
523 if ((op->func != NULL((void *)0) &&
524 op->func(sp, spo, NULL((void *)0), &turnoff)) ||
525 ex_optchange(sp, offset, NULL((void *)0), &turnoff) ||
526 v_optchange(sp, offset, NULL((void *)0), &turnoff) ||
527 sp->gp->scr_optchange(sp, offset, NULL((void *)0), &turnoff)) {
528 rval = 1;
529 break;
530 }
531
532 if (!F_ISSET(op, OPT_EARLYSET)(((op)->flags) & ((0x080)))) {
533 /* Set the value. */
534 if (turnoff)
535 O_CLR(sp, offset)o_set((sp), (offset), 0, ((void *)0), 0);
536 else
537 O_SET(sp, offset)o_set((sp), (offset), 0, ((void *)0), 1);
538 }
539 break;
540 case OPT_NUM:
541 if (turnoff) {
542 msgq_str(sp, M_ERR, name,
543 "set: %s option isn't a boolean");
544 rval = 1;
545 break;
546 }
547 if (qmark || !equals) {
548 if (!disp)
549 disp = SELECT_DISPLAY;
550 F_SET(spo, OPT_SELECTED)(((spo)->flags) |= ((0x02)));
551 break;
552 }
553
554 if (!isdigit(sep[0]))
555 goto badnum;
556 if ((nret =
557 nget_uslong(&value, sep, &endp, 10)) != NUM_OK) {
558 p = msg_print(sp, name, &nf);
559 t = msg_print(sp, sep, &nf2);
560 switch (nret) {
561 case NUM_ERR:
562 msgq(sp, M_SYSERR,
563 "set: %s option: %s", p, t);
564 break;
565 case NUM_OVER:
566 msgq(sp, M_ERR,
567 "set: %s option: %s: value overflow", p, t);
568 break;
569 case NUM_OK:
570 case NUM_UNDER:
571 abort();
572 }
573 if (nf)
574 FREE_SPACE(sp, p, 0){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp
; if (L__gp != ((void *)0) && (p) == L__gp->tmp_bp
) (((L__gp)->flags) &= ~((0x0100))); else free(p); }
;
575 if (nf2)
576 FREE_SPACE(sp, t, 0){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp
; if (L__gp != ((void *)0) && (t) == L__gp->tmp_bp
) (((L__gp)->flags) &= ~((0x0100))); else free(t); }
;
577 rval = 1;
578 break;
579 }
580 if (*endp && !isblank(*endp)) {
581badnum: p = msg_print(sp, name, &nf);
582 t = msg_print(sp, sep, &nf2);
583 msgq(sp, M_ERR,
584 "set: %s option: %s is an illegal number", p, t);
585 if (nf)
586 FREE_SPACE(sp, p, 0){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp
; if (L__gp != ((void *)0) && (p) == L__gp->tmp_bp
) (((L__gp)->flags) &= ~((0x0100))); else free(p); }
;
587 if (nf2)
588 FREE_SPACE(sp, t, 0){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp
; if (L__gp != ((void *)0) && (t) == L__gp->tmp_bp
) (((L__gp)->flags) &= ~((0x0100))); else free(t); }
;
589 rval = 1;
590 break;
591 }
592
593 /* Some options may never be set to zero. */
594 if (F_ISSET(op, OPT_NOZERO)(((op)->flags) & ((0x040))) && value == 0) {
595 msgq_str(sp, M_ERR, name,
596 "set: the %s option may never be set to 0");
597 rval = 1;
598 break;
599 }
600
601 /*
602 * Do nothing if the value is unchanged, the underlying
603 * functions can be expensive.
604 */
605 if (!F_ISSET(op, OPT_ALWAYS)(((op)->flags) & ((0x002))) &&
606 O_VAL(sp, offset)((((&((sp))->opts[((offset))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((offset))].o_cur
.val].o_cur.val : ((sp))->opts[((offset))].o_cur.val)
== value)
607 break;
608
609 if (F_ISSET(op, OPT_EARLYSET)(((op)->flags) & ((0x080)))) {
610 /* Set the value. */
611 if (o_set(sp, offset, 0, NULL((void *)0), value)) {
612 rval = 1;
613 break;
614 }
615 }
616
617 /* Report to subsystems. */
618 if ((op->func != NULL((void *)0) &&
619 op->func(sp, spo, sep, &value)) ||
620 ex_optchange(sp, offset, sep, &value) ||
621 v_optchange(sp, offset, sep, &value) ||
622 sp->gp->scr_optchange(sp, offset, sep, &value)) {
623 rval = 1;
624 break;
625 }
626
627 if (!F_ISSET(op, OPT_EARLYSET)(((op)->flags) & ((0x080)))) {
628 /* Set the value. */
629 if (o_set(sp, offset, 0, NULL((void *)0), value))
630 rval = 1;
631 }
632 break;
633 case OPT_STR:
634 if (turnoff) {
635 msgq_str(sp, M_ERR, name,
636 "set: %s option isn't a boolean");
637 rval = 1;
638 break;
639 }
640 if (qmark || !equals) {
641 if (!disp)
642 disp = SELECT_DISPLAY;
643 F_SET(spo, OPT_SELECTED)(((spo)->flags) |= ((0x02)));
644 break;
645 }
646
647 /*
648 * Do nothing if the value is unchanged, the underlying
649 * functions can be expensive.
650 */
651 if (!F_ISSET(op, OPT_ALWAYS)(((op)->flags) & ((0x002))) &&
652 O_STR(sp, offset)((((&((sp))->opts[((offset))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((offset))].o_cur
.val].o_cur.str : ((sp))->opts[((offset))].o_cur.str)
!= NULL((void *)0) &&
653 !strcmp(O_STR(sp, offset)((((&((sp))->opts[((offset))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((offset))].o_cur
.val].o_cur.str : ((sp))->opts[((offset))].o_cur.str)
, sep))
654 break;
655
656 if (F_ISSET(op, OPT_EARLYSET)(((op)->flags) & ((0x080)))) {
657 /* Set the value. */
658 if (o_set(sp, offset, OS_STRDUP0x08, sep, 0)) {
659 rval = 1;
660 break;
661 }
662 }
663
664 /* Report to subsystems. */
665 if ((op->func != NULL((void *)0) &&
666 op->func(sp, spo, sep, NULL((void *)0))) ||
667 ex_optchange(sp, offset, sep, NULL((void *)0)) ||
668 v_optchange(sp, offset, sep, NULL((void *)0)) ||
669 sp->gp->scr_optchange(sp, offset, sep, NULL((void *)0))) {
670 rval = 1;
671 break;
672 }
673
674 if (!F_ISSET(op, OPT_EARLYSET)(((op)->flags) & ((0x080)))) {
675 /* Set the value. */
676 if (o_set(sp, offset, OS_STRDUP0x08, sep, 0))
677 rval = 1;
678 }
679 break;
680 default:
681 abort();
682 }
683 }
684 if (disp != NO_DISPLAY)
685 opts_dump(sp, disp);
686 return (rval);
687}
688
689/*
690 * o_set --
691 * Set an option's value.
692 *
693 * PUBLIC: int o_set(SCR *, int, u_int, char *, u_long);
694 */
695int
696o_set(SCR *sp, int opt, u_int flags, char *str, u_long val)
697{
698 OPTION *op;
699
700 /* Set a pointer to the options area. */
701 op = F_ISSET(&sp->opts[opt], OPT_GLOBAL)(((&sp->opts[opt])->flags) & ((0x01))) ?
702 &sp->gp->opts[sp->opts[opt].o_cur.val] : &sp->opts[opt];
703
704 /* Copy the string, if requested. */
705 if (LF_ISSET(OS_STRDUP)((flags) & ((0x08))) && (str = strdup(str)) == NULL((void *)0)) {
706 msgq(sp, M_SYSERR, NULL((void *)0));
707 return (1);
708 }
709
710 /* Free the previous string, if requested, and set the value. */
711 if (LF_ISSET(OS_DEF)((flags) & ((0x01))))
712 if (LF_ISSET(OS_STR | OS_STRDUP)((flags) & ((0x04 | 0x08)))) {
713 if (!LF_ISSET(OS_NOFREE)((flags) & ((0x02))) && op->o_def.str != NULL((void *)0))
714 free(op->o_def.str);
715 op->o_def.str = str;
716 } else
717 op->o_def.val = val;
718 else
719 if (LF_ISSET(OS_STR | OS_STRDUP)((flags) & ((0x04 | 0x08)))) {
720 if (!LF_ISSET(OS_NOFREE)((flags) & ((0x02))) && op->o_cur.str != NULL((void *)0))
721 free(op->o_cur.str);
722 op->o_cur.str = str;
723 } else
724 op->o_cur.val = val;
725 return (0);
726}
727
728/*
729 * opts_empty --
730 * Return 1 if the string option is invalid, 0 if it's OK.
731 *
732 * PUBLIC: int opts_empty(SCR *, int, int);
733 */
734int
735opts_empty(SCR *sp, int off, int silent)
736{
737 char *p;
738
739 if ((p = O_STR(sp, off)((((&((sp))->opts[((off))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((off))].o_cur.val]
.o_cur.str : ((sp))->opts[((off))].o_cur.str)
) == NULL((void *)0) || p[0] == '\0') {
740 if (!silent)
741 msgq_str(sp, M_ERR, optlist[off].name,
742 "No %s edit option specified");
743 return (1);
744 }
745 return (0);
746}
747
748/*
749 * opts_dump --
750 * List the current values of selected options.
751 *
752 * PUBLIC: void opts_dump(SCR *, enum optdisp);
753 */
754void
755opts_dump(SCR *sp, enum optdisp type)
756{
757 OPTLIST const *op;
758 int base, b_num, cnt, col, colwidth, curlen, s_num;
759 int numcols, numrows, row;
760 int b_op[O_OPTIONCOUNT], s_op[O_OPTIONCOUNT];
761 char nbuf[20];
762
763 /*
764 * Options are output in two groups -- those that fit in a column and
765 * those that don't. Output is done on 6 character "tab" boundaries
766 * for no particular reason. (Since we don't output tab characters,
767 * we can ignore the terminal's tab settings.) Ignore the user's tab
768 * setting because we have no idea how reasonable it is.
769 *
770 * Find a column width we can live with, testing from 10 columns to 1.
771 */
772 for (numcols = 10; numcols > 1; --numcols) {
1
Loop condition is true. Entering loop body
773 colwidth = sp->cols / numcols & ~(STANDARD_TAB6 - 1);
774 if (colwidth >= 10) {
2
Assuming 'colwidth' is >= 10
3
Taking true branch
775 colwidth =
776 (colwidth + STANDARD_TAB6) & ~(STANDARD_TAB6 - 1);
777 numcols = sp->cols / colwidth;
4
Value assigned to 'numcols'
778 break;
5
Execution continues on line 787
779 }
780 colwidth = 0;
781 }
782
783 /*
784 * Get the set of options to list, entering them into
785 * the column list or the overflow list.
786 */
787 for (b_num = s_num = 0, op = optlist; op->name != NULL((void *)0); ++op) {
6
Assuming field 'name' is not equal to NULL
7
Loop condition is true. Entering loop body
20
Assuming field 'name' is equal to NULL
21
Loop condition is false. Execution continues on line 851
788 cnt = op - optlist;
789
790 /* If OPT_NDISP set, it's never displayed. */
791 if (F_ISSET(op, OPT_NDISP)(((op)->flags) & ((0x004))))
8
Assuming the condition is false
9
Taking false branch
792 continue;
793
794 switch (type) {
10
Control jumps to 'case ALL_DISPLAY:' at line 795
795 case ALL_DISPLAY: /* Display all. */
796 break;
11
Execution continues on line 824
797 case CHANGED_DISPLAY: /* Display changed. */
798 /* If OPT_ADISP set, it's always "changed". */
799 if (F_ISSET(op, OPT_ADISP)(((op)->flags) & ((0x001))))
800 break;
801 switch (op->type) {
802 case OPT_0BOOL:
803 case OPT_1BOOL:
804 case OPT_NUM:
805 if (O_VAL(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.val : ((sp))->opts[((cnt))].o_cur.val)
== O_D_VAL(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_def.val : ((sp))->opts[((cnt))].o_def.val)
)
806 continue;
807 break;
808 case OPT_STR:
809 if (O_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.str : ((sp))->opts[((cnt))].o_cur.str)
== O_D_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_def.str : ((sp))->opts[((cnt))].o_def.str)
||
810 (O_D_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_def.str : ((sp))->opts[((cnt))].o_def.str)
!= NULL((void *)0) &&
811 !strcmp(O_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.str : ((sp))->opts[((cnt))].o_cur.str)
, O_D_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_def.str : ((sp))->opts[((cnt))].o_def.str)
)))
812 continue;
813 break;
814 }
815 break;
816 case SELECT_DISPLAY: /* Display selected. */
817 if (!F_ISSET(&sp->opts[cnt], OPT_SELECTED)(((&sp->opts[cnt])->flags) & ((0x02))))
818 continue;
819 break;
820 default:
821 case NO_DISPLAY:
822 abort();
823 }
824 F_CLR(&sp->opts[cnt], OPT_SELECTED)(((&sp->opts[cnt])->flags) &= ~((0x02)));
825
826 curlen = strlen(op->name);
827 switch (op->type) {
12
Control jumps to 'case OPT_1BOOL:' at line 829
828 case OPT_0BOOL:
829 case OPT_1BOOL:
830 if (!O_ISSET(sp, cnt)((((&(((sp)))->opts[(((cnt)))])->flags) & ((0x01
))) ? (((sp)))->gp->opts[(((sp)))->opts[(((cnt)))].o_cur
.val].o_cur.val : (((sp)))->opts[(((cnt)))].o_cur.val)
)
13
Assuming the condition is false
14
'?' condition is false
15
Assuming the condition is false
16
Taking false branch
831 curlen += 2;
832 break;
17
Execution continues on line 845
833 case OPT_NUM:
834 (void)snprintf(nbuf,
835 sizeof(nbuf), "%ld", O_VAL(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.val : ((sp))->opts[((cnt))].o_cur.val)
);
836 curlen += strlen(nbuf);
837 break;
838 case OPT_STR:
839 if (O_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.str : ((sp))->opts[((cnt))].o_cur.str)
!= NULL((void *)0))
840 curlen += strlen(O_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.str : ((sp))->opts[((cnt))].o_cur.str)
);
841 curlen += 3;
842 break;
843 }
844 /* Offset by 2 so there's a gap. */
845 if (curlen <= colwidth - 2)
18
Assuming the condition is true
19
Taking true branch
846 s_op[s_num++] = cnt;
847 else
848 b_op[b_num++] = cnt;
849 }
850
851 if (s_num
21.1
's_num' is > 0
> 0) {
22
Taking true branch
852 /* Figure out the number of rows. */
853 if (s_num > numcols) {
23
Assuming 's_num' is > 'numcols'
24
Taking true branch
854 numrows = s_num / numcols;
25
Division by zero
855 if (s_num % numcols)
856 ++numrows;
857 } else
858 numrows = 1;
859
860 /* Display the options in sorted order. */
861 for (row = 0; row < numrows;) {
862 for (base = row, col = 0; col < numcols; ++col) {
863 cnt = opts_print(sp, &optlist[s_op[base]]);
864 if ((base += numrows) >= s_num)
865 break;
866 (void)ex_printf(sp, "%*s",
867 (int)(colwidth - cnt), "");
868 }
869 if (++row < numrows || b_num)
870 (void)ex_puts(sp, "\n");
871 }
872 }
873
874 for (row = 0; row < b_num;) {
875 (void)opts_print(sp, &optlist[b_op[row]]);
876 if (++row < b_num)
877 (void)ex_puts(sp, "\n");
878 }
879 (void)ex_puts(sp, "\n");
880}
881
882/*
883 * opts_print --
884 * Print out an option.
885 */
886static int
887opts_print(SCR *sp, OPTLIST const *op)
888{
889 int curlen, offset;
890
891 curlen = 0;
892 offset = op - optlist;
893 switch (op->type) {
894 case OPT_0BOOL:
895 case OPT_1BOOL:
896 curlen += ex_printf(sp,
897 "%s%s", O_ISSET(sp, offset)((((&(((sp)))->opts[(((offset)))])->flags) & ((
0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((offset
)))].o_cur.val].o_cur.val : (((sp)))->opts[(((offset)))].o_cur
.val)
? "" : "no", op->name);
898 break;
899 case OPT_NUM:
900 curlen += ex_printf(sp, "%s=%ld", op->name, O_VAL(sp, offset)((((&((sp))->opts[((offset))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((offset))].o_cur
.val].o_cur.val : ((sp))->opts[((offset))].o_cur.val)
);
901 break;
902 case OPT_STR:
903 curlen += ex_printf(sp, "%s=\"%s\"", op->name,
904 O_STR(sp, offset)((((&((sp))->opts[((offset))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((offset))].o_cur
.val].o_cur.str : ((sp))->opts[((offset))].o_cur.str)
== NULL((void *)0) ? "" : O_STR(sp, offset)((((&((sp))->opts[((offset))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((offset))].o_cur
.val].o_cur.str : ((sp))->opts[((offset))].o_cur.str)
);
905 break;
906 }
907 return (curlen);
908}
909
910/*
911 * opts_save --
912 * Write the current configuration to a file.
913 *
914 * PUBLIC: int opts_save(SCR *, FILE *);
915 */
916int
917opts_save(SCR *sp, FILE *fp)
918{
919 OPTLIST const *op;
920 int ch, cnt;
921 char *p;
922
923 for (op = optlist; op->name != NULL((void *)0); ++op) {
924 if (F_ISSET(op, OPT_NOSAVE)(((op)->flags) & ((0x008))))
925 continue;
926 cnt = op - optlist;
927 switch (op->type) {
928 case OPT_0BOOL:
929 case OPT_1BOOL:
930 if (O_ISSET(sp, cnt)((((&(((sp)))->opts[(((cnt)))])->flags) & ((0x01
))) ? (((sp)))->gp->opts[(((sp)))->opts[(((cnt)))].o_cur
.val].o_cur.val : (((sp)))->opts[(((cnt)))].o_cur.val)
)
931 (void)fprintf(fp, "set %s\n", op->name);
932 else
933 (void)fprintf(fp, "set no%s\n", op->name);
934 break;
935 case OPT_NUM:
936 (void)fprintf(fp,
937 "set %s=%-3ld\n", op->name, O_VAL(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.val : ((sp))->opts[((cnt))].o_cur.val)
);
938 break;
939 case OPT_STR:
940 if (O_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.str : ((sp))->opts[((cnt))].o_cur.str)
== NULL((void *)0))
941 break;
942 (void)fprintf(fp, "set ");
943 for (p = op->name; (ch = *p) != '\0'; ++p) {
944 if (isblank(ch) || ch == '\\')
945 (void)putc('\\', fp)(!__isthreaded ? __sputc('\\', fp) : (putc)('\\', fp));
946 (void)putc(ch, fp)(!__isthreaded ? __sputc(ch, fp) : (putc)(ch, fp));
947 }
948 (void)putc('=', fp)(!__isthreaded ? __sputc('=', fp) : (putc)('=', fp));
949 for (p = O_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.str : ((sp))->opts[((cnt))].o_cur.str)
; (ch = *p) != '\0'; ++p) {
950 if (isblank(ch) || ch == '\\')
951 (void)putc('\\', fp)(!__isthreaded ? __sputc('\\', fp) : (putc)('\\', fp));
952 (void)putc(ch, fp)(!__isthreaded ? __sputc(ch, fp) : (putc)(ch, fp));
953 }
954 (void)putc('\n', fp)(!__isthreaded ? __sputc('\n', fp) : (putc)('\n', fp));
955 break;
956 }
957 if (ferror(fp)(!__isthreaded ? (((fp)->_flags & 0x0040) != 0) : (ferror
)(fp))
) {
958 msgq(sp, M_SYSERR, NULL((void *)0));
959 return (1);
960 }
961 }
962 return (0);
963}
964
965/*
966 * opts_search --
967 * Search for an option.
968 *
969 * PUBLIC: OPTLIST const *opts_search(char *);
970 */
971OPTLIST const *
972opts_search(char *name)
973{
974 OPTLIST const *op, *found;
975 OABBREV atmp, *ap;
976 OPTLIST otmp;
977 size_t len;
978
979 /* Check list of abbreviations. */
980 atmp.name = name;
981 if ((ap = bsearch(&atmp, abbrev, sizeof(abbrev) / sizeof(OABBREV) - 1,
982 sizeof(OABBREV), opts_abbcmp)) != NULL((void *)0))
983 return (optlist + ap->offset);
984
985 /* Check list of options. */
986 otmp.name = name;
987 if ((op = bsearch(&otmp, optlist, sizeof(optlist) / sizeof(OPTLIST) - 1,
988 sizeof(OPTLIST), opts_cmp)) != NULL((void *)0))
989 return (op);
990
991 /*
992 * Check to see if the name is the prefix of one (and only one)
993 * option. If so, return the option.
994 */
995 len = strlen(name);
996 for (found = NULL((void *)0), op = optlist; op->name != NULL((void *)0); ++op) {
997 if (op->name[0] < name[0])
998 continue;
999 if (op->name[0] > name[0])
1000 break;
1001 if (!memcmp(op->name, name, len)) {
1002 if (found != NULL((void *)0))
1003 return (NULL((void *)0));
1004 found = op;
1005 }
1006 }
1007 return (found);
1008}
1009
1010/*
1011 * opts_nomatch --
1012 * Standard nomatch error message for options.
1013 *
1014 * PUBLIC: void opts_nomatch(SCR *, char *);
1015 */
1016void
1017opts_nomatch(SCR *sp, char *name)
1018{
1019 msgq_str(sp, M_ERR, name,
1020 "set: no %s option: 'set all' gives all option values");
1021}
1022
1023static int
1024opts_abbcmp(const void *a, const void *b)
1025{
1026 return(strcmp(((OABBREV *)a)->name, ((OABBREV *)b)->name));
1027}
1028
1029static int
1030opts_cmp(const void *a, const void *b)
1031{
1032 return(strcmp(((OPTLIST *)a)->name, ((OPTLIST *)b)->name));
1033}
1034
1035/*
1036 * opts_copy --
1037 * Copy a screen's OPTION array.
1038 *
1039 * PUBLIC: int opts_copy(SCR *, SCR *);
1040 */
1041int
1042opts_copy(SCR *orig, SCR *sp)
1043{
1044 int cnt, rval;
1045
1046 /* Copy most everything without change. */
1047 memcpy(sp->opts, orig->opts, sizeof(orig->opts));
1048
1049 /* Copy the string edit options. */
1050 for (cnt = rval = 0; cnt < O_OPTIONCOUNT; ++cnt) {
1051 if (optlist[cnt].type != OPT_STR ||
1052 F_ISSET(&optlist[cnt], OPT_GLOBAL)(((&optlist[cnt])->flags) & ((0x01))))
1053 continue;
1054 /*
1055 * If never set, or already failed, NULL out the entries --
1056 * have to continue after failure, otherwise would have two
1057 * screens referencing the same memory.
1058 */
1059 if (rval || O_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.str : ((sp))->opts[((cnt))].o_cur.str)
== NULL((void *)0)) {
1060 o_set(sp, cnt, OS_NOFREE0x02 | OS_STR0x04, NULL((void *)0), 0);
1061 o_set(sp, cnt, OS_DEF0x01 | OS_NOFREE0x02 | OS_STR0x04, NULL((void *)0), 0);
1062 continue;
1063 }
1064
1065 /* Copy the current string. */
1066 if (o_set(sp, cnt, OS_NOFREE0x02 | OS_STRDUP0x08, O_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.str : ((sp))->opts[((cnt))].o_cur.str)
, 0)) {
1067 o_set(sp, cnt, OS_DEF0x01 | OS_NOFREE0x02 | OS_STR0x04, NULL((void *)0), 0);
1068 goto nomem;
1069 }
1070
1071 /* Copy the default string. */
1072 if (O_D_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_def.str : ((sp))->opts[((cnt))].o_def.str)
!= NULL((void *)0) && o_set(sp, cnt,
1073 OS_DEF0x01 | OS_NOFREE0x02 | OS_STRDUP0x08, O_D_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_def.str : ((sp))->opts[((cnt))].o_def.str)
, 0)) {
1074nomem: msgq(orig, M_SYSERR, NULL((void *)0));
1075 rval = 1;
1076 }
1077 }
1078 return (rval);
1079}
1080
1081/*
1082 * opts_free --
1083 * Free all option strings
1084 *
1085 * PUBLIC: void opts_free(SCR *);
1086 */
1087void
1088opts_free(SCR *sp)
1089{
1090 int cnt;
1091
1092 for (cnt = 0; cnt < O_OPTIONCOUNT; ++cnt) {
1093 if (optlist[cnt].type != OPT_STR ||
1094 F_ISSET(&optlist[cnt], OPT_GLOBAL)(((&optlist[cnt])->flags) & ((0x01))))
1095 continue;
1096 free(O_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_cur.str : ((sp))->opts[((cnt))].o_cur.str)
);
1097 free(O_D_STR(sp, cnt)((((&((sp))->opts[((cnt))])->flags) & ((0x01)))
? ((sp))->gp->opts[((sp))->opts[((cnt))].o_cur.val]
.o_def.str : ((sp))->opts[((cnt))].o_def.str)
);
1098 }
1099}