File: | src/usr.bin/vi/build/../common/options.c |
Warning: | line 854, column 20 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
33 | static int opts_abbcmp(const void *, const void *); | |||
34 | static int opts_cmp(const void *, const void *); | |||
35 | static 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 | */ | |||
45 | OPTLIST 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 | ||||
199 | typedef struct abbrev { | |||
200 | char *name; | |||
201 | int offset; | |||
202 | } OABBREV; | |||
203 | ||||
204 | static 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 | */ | |||
247 | int | |||
248 | opts_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 | ||||
391 | err: 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 | */ | |||
402 | int | |||
403 | opts_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)) { | |||
581 | badnum: 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 | */ | |||
695 | int | |||
696 | o_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 | */ | |||
734 | int | |||
735 | opts_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 | */ | |||
754 | void | |||
755 | opts_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) { | |||
| ||||
773 | colwidth = sp->cols / numcols & ~(STANDARD_TAB6 - 1); | |||
774 | if (colwidth >= 10) { | |||
775 | colwidth = | |||
776 | (colwidth + STANDARD_TAB6) & ~(STANDARD_TAB6 - 1); | |||
777 | numcols = sp->cols / colwidth; | |||
778 | break; | |||
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) { | |||
788 | cnt = op - optlist; | |||
789 | ||||
790 | /* If OPT_NDISP set, it's never displayed. */ | |||
791 | if (F_ISSET(op, OPT_NDISP)(((op)->flags) & ((0x004)))) | |||
792 | continue; | |||
793 | ||||
794 | switch (type) { | |||
795 | case ALL_DISPLAY: /* Display all. */ | |||
796 | break; | |||
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) { | |||
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)) | |||
831 | curlen += 2; | |||
832 | break; | |||
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) | |||
846 | s_op[s_num++] = cnt; | |||
847 | else | |||
848 | b_op[b_num++] = cnt; | |||
849 | } | |||
850 | ||||
851 | if (s_num
| |||
852 | /* Figure out the number of rows. */ | |||
853 | if (s_num > numcols) { | |||
854 | numrows = s_num / numcols; | |||
| ||||
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 | */ | |||
886 | static int | |||
887 | opts_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 | */ | |||
916 | int | |||
917 | opts_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 | */ | |||
971 | OPTLIST const * | |||
972 | opts_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 | */ | |||
1016 | void | |||
1017 | opts_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 | ||||
1023 | static int | |||
1024 | opts_abbcmp(const void *a, const void *b) | |||
1025 | { | |||
1026 | return(strcmp(((OABBREV *)a)->name, ((OABBREV *)b)->name)); | |||
1027 | } | |||
1028 | ||||
1029 | static int | |||
1030 | opts_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 | */ | |||
1041 | int | |||
1042 | opts_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)) { | |||
1074 | nomem: 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 | */ | |||
1087 | void | |||
1088 | opts_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 | } |