1 1.25 andvar /* $NetBSD: termcap.c,v 1.25 2023/01/31 21:11:24 andvar Exp $ */ 2 1.1 roy 3 1.1 roy /* 4 1.1 roy * Copyright (c) 2009 The NetBSD Foundation, Inc. 5 1.1 roy * 6 1.1 roy * This code is derived from software contributed to The NetBSD Foundation 7 1.1 roy * by Roy Marples. 8 1.1 roy * 9 1.1 roy * Redistribution and use in source and binary forms, with or without 10 1.1 roy * modification, are permitted provided that the following conditions 11 1.1 roy * are met: 12 1.1 roy * 1. Redistributions of source code must retain the above copyright 13 1.1 roy * notice, this list of conditions and the following disclaimer. 14 1.1 roy * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 roy * notice, this list of conditions and the following disclaimer in the 16 1.1 roy * documentation and/or other materials provided with the distribution. 17 1.1 roy * 18 1.1 roy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.1 roy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.1 roy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.1 roy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.1 roy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 1.1 roy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.1 roy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.1 roy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.1 roy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 1.1 roy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 roy */ 29 1.1 roy 30 1.1 roy #include <sys/cdefs.h> 31 1.25 andvar __RCSID("$NetBSD: termcap.c,v 1.25 2023/01/31 21:11:24 andvar Exp $"); 32 1.1 roy 33 1.1 roy #include <assert.h> 34 1.3 roy #include <ctype.h> 35 1.3 roy #include <errno.h> 36 1.22 roy #include <stdbool.h> 37 1.2 roy #include <stdint.h> 38 1.1 roy #include <string.h> 39 1.1 roy #include <term_private.h> 40 1.1 roy #include <term.h> 41 1.1 roy #include <termcap.h> 42 1.1 roy #include <unistd.h> 43 1.1 roy #include <stdio.h> 44 1.1 roy 45 1.1 roy #include "termcap_map.c" 46 1.1 roy #include "termcap_hash.c" 47 1.1 roy 48 1.1 roy char *UP; 49 1.1 roy char *BC; 50 1.1 roy 51 1.1 roy /* ARGSUSED */ 52 1.1 roy int 53 1.1 roy tgetent(__unused char *bp, const char *name) 54 1.1 roy { 55 1.1 roy int errret; 56 1.1 roy static TERMINAL *last = NULL; 57 1.1 roy 58 1.1 roy _DIAGASSERT(name != NULL); 59 1.1 roy 60 1.1 roy /* Free the old term */ 61 1.19 christos if (cur_term != NULL) { 62 1.19 christos if (last != NULL && cur_term != last) 63 1.19 christos del_curterm(last); 64 1.19 christos last = cur_term; 65 1.1 roy } 66 1.1 roy errret = -1; 67 1.1 roy if (setupterm(name, STDOUT_FILENO, &errret) != 0) 68 1.1 roy return errret; 69 1.19 christos 70 1.19 christos if (last == NULL) 71 1.19 christos last = cur_term; 72 1.1 roy 73 1.1 roy if (pad_char != NULL) 74 1.1 roy PC = pad_char[0]; 75 1.1 roy UP = __UNCONST(cursor_up); 76 1.1 roy BC = __UNCONST(cursor_left); 77 1.1 roy return 1; 78 1.1 roy } 79 1.1 roy 80 1.1 roy int 81 1.15 christos tgetflag(const char *id2) 82 1.1 roy { 83 1.1 roy uint32_t ind; 84 1.1 roy size_t i; 85 1.1 roy TERMUSERDEF *ud; 86 1.17 christos const char id[] = { id2[0], id2[0] ? id2[1] : '\0', '\0' }; 87 1.1 roy 88 1.1 roy if (cur_term == NULL) 89 1.1 roy return 0; 90 1.1 roy 91 1.1 roy ind = _t_flaghash((const unsigned char *)id, strlen(id)); 92 1.20 roy if (ind < __arraycount(_ti_cap_flagids)) { 93 1.1 roy if (strcmp(id, _ti_cap_flagids[ind].id) == 0) 94 1.1 roy return cur_term->flags[_ti_cap_flagids[ind].ti]; 95 1.1 roy } 96 1.1 roy for (i = 0; i < cur_term->_nuserdefs; i++) { 97 1.1 roy ud = &cur_term->_userdefs[i]; 98 1.1 roy if (ud->type == 'f' && strcmp(ud->id, id) == 0) 99 1.1 roy return ud->flag; 100 1.1 roy } 101 1.1 roy return 0; 102 1.1 roy } 103 1.1 roy 104 1.1 roy int 105 1.15 christos tgetnum(const char *id2) 106 1.1 roy { 107 1.1 roy uint32_t ind; 108 1.1 roy size_t i; 109 1.1 roy TERMUSERDEF *ud; 110 1.1 roy const TENTRY *te; 111 1.17 christos const char id[] = { id2[0], id2[0] ? id2[1] : '\0', '\0' }; 112 1.1 roy 113 1.1 roy if (cur_term == NULL) 114 1.1 roy return -1; 115 1.1 roy 116 1.1 roy ind = _t_numhash((const unsigned char *)id, strlen(id)); 117 1.20 roy if (ind < __arraycount(_ti_cap_numids)) { 118 1.1 roy te = &_ti_cap_numids[ind]; 119 1.1 roy if (strcmp(id, te->id) == 0) { 120 1.1 roy if (!VALID_NUMERIC(cur_term->nums[te->ti])) 121 1.1 roy return ABSENT_NUMERIC; 122 1.1 roy return cur_term->nums[te->ti]; 123 1.1 roy } 124 1.1 roy } 125 1.1 roy for (i = 0; i < cur_term->_nuserdefs; i++) { 126 1.1 roy ud = &cur_term->_userdefs[i]; 127 1.1 roy if (ud->type == 'n' && strcmp(ud->id, id) == 0) { 128 1.1 roy if (!VALID_NUMERIC(ud->num)) 129 1.1 roy return ABSENT_NUMERIC; 130 1.1 roy return ud->num; 131 1.1 roy } 132 1.1 roy } 133 1.1 roy return -1; 134 1.1 roy } 135 1.1 roy 136 1.1 roy char * 137 1.15 christos tgetstr(const char *id2, char **area) 138 1.1 roy { 139 1.1 roy uint32_t ind; 140 1.1 roy size_t i; 141 1.1 roy TERMUSERDEF *ud; 142 1.1 roy const char *str; 143 1.17 christos const char id[] = { id2[0], id2[0] ? id2[1] : '\0', '\0' }; 144 1.1 roy 145 1.1 roy if (cur_term == NULL) 146 1.1 roy return NULL; 147 1.1 roy 148 1.1 roy str = NULL; 149 1.1 roy ind = _t_strhash((const unsigned char *)id, strlen(id)); 150 1.20 roy if (ind < __arraycount(_ti_cap_strids)) { 151 1.1 roy if (strcmp(id, _ti_cap_strids[ind].id) == 0) { 152 1.1 roy str = cur_term->strs[_ti_cap_strids[ind].ti]; 153 1.1 roy if (str == NULL) 154 1.1 roy return NULL; 155 1.1 roy } 156 1.1 roy } 157 1.1 roy if (str != NULL) 158 1.1 roy for (i = 0; i < cur_term->_nuserdefs; i++) { 159 1.1 roy ud = &cur_term->_userdefs[i]; 160 1.1 roy if (ud->type == 's' && strcmp(ud->id, id) == 0) 161 1.1 roy str = ud->str; 162 1.1 roy } 163 1.1 roy 164 1.25 andvar /* XXX: FIXME 165 1.1 roy * We should fix sgr0(me) as it has a slightly different meaning 166 1.1 roy * for termcap. */ 167 1.1 roy 168 1.1 roy if (str != NULL && area != NULL && *area != NULL) { 169 1.1 roy char *s; 170 1.1 roy s = *area; 171 1.1 roy strcpy(*area, str); 172 1.1 roy *area += strlen(*area) + 1; 173 1.1 roy return s; 174 1.1 roy } 175 1.1 roy 176 1.1 roy return __UNCONST(str); 177 1.1 roy } 178 1.1 roy 179 1.1 roy char * 180 1.1 roy tgoto(const char *cm, int destcol, int destline) 181 1.1 roy { 182 1.1 roy _DIAGASSERT(cm != NULL); 183 1.16 roy return tiparm(cm, destline, destcol); 184 1.1 roy } 185 1.3 roy 186 1.24 martin #ifdef TERMINFO_COMPILE 187 1.3 roy static const char * 188 1.3 roy flagname(const char *key) 189 1.3 roy { 190 1.3 roy uint32_t idx; 191 1.3 roy 192 1.3 roy idx = _t_flaghash((const unsigned char *)key, strlen(key)); 193 1.20 roy if (idx < __arraycount(_ti_cap_flagids) && 194 1.3 roy strcmp(key, _ti_cap_flagids[idx].id) == 0) 195 1.3 roy return _ti_flagid(_ti_cap_flagids[idx].ti); 196 1.3 roy return key; 197 1.3 roy } 198 1.3 roy 199 1.3 roy static const char * 200 1.3 roy numname(const char *key) 201 1.3 roy { 202 1.3 roy uint32_t idx; 203 1.3 roy 204 1.3 roy idx = _t_numhash((const unsigned char *)key, strlen(key)); 205 1.21 roy if (idx < __arraycount(_ti_cap_numids) && 206 1.3 roy strcmp(key, _ti_cap_numids[idx].id) == 0) 207 1.3 roy return _ti_numid(_ti_cap_numids[idx].ti); 208 1.3 roy return key; 209 1.3 roy } 210 1.3 roy 211 1.3 roy static const char * 212 1.3 roy strname(const char *key) 213 1.3 roy { 214 1.3 roy uint32_t idx; 215 1.3 roy 216 1.3 roy idx = _t_strhash((const unsigned char *)key, strlen(key)); 217 1.20 roy if (idx < __arraycount(_ti_cap_strids) && 218 1.3 roy strcmp(key, _ti_cap_strids[idx].id) == 0) 219 1.3 roy return _ti_strid(_ti_cap_strids[idx].ti); 220 1.3 roy 221 1.3 roy if (strcmp(key, "tc") == 0) 222 1.3 roy return "use"; 223 1.3 roy 224 1.3 roy return key; 225 1.3 roy } 226 1.3 roy 227 1.14 roy /* Print a parameter if needed */ 228 1.22 roy static size_t 229 1.22 roy printparam(char **dst, char p, bool *nop) 230 1.14 roy { 231 1.22 roy if (*nop) { 232 1.22 roy *nop = false; 233 1.14 roy return 0; 234 1.14 roy } 235 1.14 roy 236 1.14 roy *(*dst)++ = '%'; 237 1.14 roy *(*dst)++ = 'p'; 238 1.14 roy *(*dst)++ = '0' + p; 239 1.14 roy return 3; 240 1.14 roy } 241 1.14 roy 242 1.12 roy /* Convert a termcap character into terminfo equivalents */ 243 1.22 roy static size_t 244 1.12 roy printchar(char **dst, const char **src) 245 1.12 roy { 246 1.22 roy char v; 247 1.22 roy size_t l; 248 1.12 roy 249 1.12 roy l = 4; 250 1.22 roy v = *++(*src); 251 1.12 roy if (v == '\\') { 252 1.22 roy v = *++(*src); 253 1.12 roy switch (v) { 254 1.12 roy case '0': 255 1.12 roy case '1': 256 1.12 roy case '2': 257 1.12 roy case '3': 258 1.12 roy v = 0; 259 1.21 roy while (isdigit((unsigned char) **src)) 260 1.22 roy v = 8 * v + (*(*src)++ - '0'); 261 1.12 roy (*src)--; 262 1.12 roy break; 263 1.12 roy case '\0': 264 1.12 roy v = '\\'; 265 1.12 roy break; 266 1.12 roy } 267 1.12 roy } else if (v == '^') 268 1.22 roy v = *++(*src) & 0x1f; 269 1.12 roy *(*dst)++ = '%'; 270 1.22 roy if (isgraph((unsigned char )v) && 271 1.22 roy v != ',' && v != '\'' && v != '\\' && v != ':') 272 1.22 roy { 273 1.12 roy *(*dst)++ = '\''; 274 1.12 roy *(*dst)++ = v; 275 1.12 roy *(*dst)++ = '\''; 276 1.12 roy } else { 277 1.12 roy *(*dst)++ = '{'; 278 1.12 roy if (v > 99) { 279 1.12 roy *(*dst)++ = '0'+ v / 100; 280 1.12 roy l++; 281 1.12 roy } 282 1.12 roy if (v > 9) { 283 1.12 roy *(*dst)++ = '0' + ((int) (v / 10)) % 10; 284 1.12 roy l++; 285 1.12 roy } 286 1.12 roy *(*dst)++ = '0' + v % 10; 287 1.12 roy *(*dst)++ = '}'; 288 1.12 roy } 289 1.12 roy return l; 290 1.12 roy } 291 1.12 roy 292 1.12 roy /* Convert termcap commands into terminfo commands */ 293 1.14 roy static const char fmtB[] = "%p0%{10}%/%{16}%*%p0%{10}%m%+"; 294 1.14 roy static const char fmtD[] = "%p0%p0%{2}%*%-"; 295 1.14 roy static const char fmtIf[] = "%p0%p0%?"; 296 1.14 roy static const char fmtThen[] = "%>%t"; 297 1.14 roy static const char fmtElse[] = "%+%;"; 298 1.14 roy 299 1.3 roy static char * 300 1.3 roy strval(const char *val) 301 1.3 roy { 302 1.22 roy char *info, *ip, c, p; 303 1.6 roy const char *ps, *pe; 304 1.22 roy bool nop; 305 1.10 christos size_t len, l; 306 1.3 roy 307 1.3 roy len = 1024; /* no single string should be bigger */ 308 1.3 roy info = ip = malloc(len); 309 1.3 roy if (info == NULL) 310 1.3 roy return 0; 311 1.3 roy 312 1.6 roy /* Move the = */ 313 1.6 roy *ip++ = *val++; 314 1.6 roy 315 1.6 roy /* Set ps and pe to point to the start and end of the padding */ 316 1.6 roy if (isdigit((unsigned char)*val)) { 317 1.6 roy for (ps = pe = val; 318 1.6 roy isdigit((unsigned char)*val) || *val == '.'; 319 1.6 roy val++) 320 1.6 roy pe++; 321 1.6 roy if (*val == '*') { 322 1.6 roy val++; 323 1.6 roy pe++; 324 1.6 roy } 325 1.6 roy } else 326 1.6 roy ps = pe = NULL; 327 1.6 roy 328 1.22 roy nop = false; 329 1.22 roy l = 0; 330 1.3 roy p = 1; 331 1.3 roy for (; *val != '\0'; val++) { 332 1.3 roy if (l + 2 > len) 333 1.3 roy goto elen; 334 1.3 roy if (*val != '%') { 335 1.4 roy if (*val == ',') { 336 1.4 roy if (l + 3 > len) 337 1.4 roy goto elen; 338 1.4 roy *ip++ = '\\'; 339 1.4 roy l++; 340 1.4 roy } 341 1.3 roy *ip++ = *val; 342 1.3 roy l++; 343 1.3 roy continue; 344 1.3 roy } 345 1.12 roy switch (c = *++(val)) { 346 1.12 roy case 'B': 347 1.14 roy if (l + sizeof(fmtB) > len) 348 1.12 roy goto elen; 349 1.14 roy memcpy(ip, fmtB, sizeof(fmtB) - 1); 350 1.14 roy /* Replace the embedded parameters with real ones */ 351 1.14 roy ip[2] += p; 352 1.14 roy ip[19] += p; 353 1.14 roy ip += sizeof(fmtB) - 1; 354 1.14 roy l += sizeof(fmtB) - 1; 355 1.22 roy nop = true; 356 1.12 roy continue; 357 1.12 roy case 'D': 358 1.14 roy if (l + sizeof(fmtD) > len) 359 1.12 roy goto elen; 360 1.14 roy memcpy(ip, fmtD, sizeof(fmtD) - 1); 361 1.14 roy /* Replace the embedded parameters with real ones */ 362 1.14 roy ip[2] += p; 363 1.14 roy ip[5] += p; 364 1.14 roy ip += sizeof(fmtD) - 1; 365 1.14 roy l += sizeof(fmtD) - 1; 366 1.22 roy nop = true; 367 1.12 roy continue; 368 1.12 roy case 'r': 369 1.12 roy /* non op as switched below */ 370 1.12 roy break; 371 1.12 roy case '2': /* FALLTHROUGH */ 372 1.12 roy case '3': /* FALLTHROUGH */ 373 1.3 roy case 'd': 374 1.12 roy if (l + 7 > len) 375 1.12 roy goto elen; 376 1.14 roy l += printparam(&ip, p, &nop); 377 1.12 roy *ip++ = '%'; 378 1.12 roy if (c != 'd') { 379 1.12 roy *ip++ = c; 380 1.12 roy l++; 381 1.12 roy } 382 1.12 roy *ip++ = 'd'; 383 1.12 roy l += 2; 384 1.12 roy break; 385 1.12 roy case '+': 386 1.12 roy if (l + 13 > len) 387 1.12 roy goto elen; 388 1.14 roy l += printparam(&ip, p, &nop); 389 1.12 roy l += printchar(&ip, &val); 390 1.12 roy *ip++ = '%'; 391 1.12 roy *ip++ = c; 392 1.12 roy *ip++ = '%'; 393 1.12 roy *ip++ = 'c'; 394 1.12 roy l += 7; 395 1.12 roy break; 396 1.12 roy case '>': 397 1.14 roy if (l + sizeof(fmtIf) + sizeof(fmtThen) + 398 1.14 roy sizeof(fmtElse) + (6 * 2) > len) 399 1.3 roy goto elen; 400 1.14 roy 401 1.14 roy memcpy(ip, fmtIf, sizeof(fmtIf) - 1); 402 1.14 roy /* Replace the embedded parameters with real ones */ 403 1.14 roy ip[2] += p; 404 1.14 roy ip[5] += p; 405 1.14 roy ip += sizeof(fmtIf) - 1; 406 1.14 roy l += sizeof(fmtIf) - 1; 407 1.12 roy l += printchar(&ip, &val); 408 1.14 roy memcpy(ip, fmtThen, sizeof(fmtThen) - 1); 409 1.14 roy ip += sizeof(fmtThen) - 1; 410 1.14 roy l += sizeof(fmtThen) - 1; 411 1.12 roy l += printchar(&ip, &val); 412 1.14 roy memcpy(ip, fmtElse, sizeof(fmtElse) - 1); 413 1.14 roy ip += sizeof(fmtElse) - 1; 414 1.14 roy l += sizeof(fmtElse) - 1; 415 1.12 roy l += 16; 416 1.22 roy nop = true; 417 1.12 roy continue; 418 1.12 roy case '.': 419 1.12 roy if (l + 6 > len) 420 1.12 roy goto elen; 421 1.14 roy l += printparam(&ip, p, &nop); 422 1.12 roy *ip++ = '%'; 423 1.12 roy *ip++ = 'c'; 424 1.12 roy l += 2; 425 1.3 roy break; 426 1.3 roy default: 427 1.3 roy /* Hope it matches a terminfo command. */ 428 1.3 roy *ip++ = '%'; 429 1.3 roy *ip++ = c; 430 1.3 roy l += 2; 431 1.12 roy if (c == 'i') 432 1.12 roy continue; 433 1.3 roy break; 434 1.3 roy } 435 1.12 roy /* Swap p1 and p2 */ 436 1.12 roy p = 3 - p; 437 1.3 roy } 438 1.3 roy 439 1.5 roy /* \E\ is valid termcap. 440 1.5 roy * We need to escape the final \ for terminfo. */ 441 1.5 roy if (l > 2 && info[l - 1] == '\\' && 442 1.5 roy (info[l - 2] != '\\' && info[l - 2] != '^')) 443 1.5 roy { 444 1.5 roy if (l + 1 > len) 445 1.5 roy goto elen; 446 1.5 roy *ip++ = '\\'; 447 1.5 roy } 448 1.5 roy 449 1.6 roy /* Add our padding at the end. */ 450 1.6 roy if (ps != NULL) { 451 1.22 roy size_t n = (size_t)(pe - ps); 452 1.6 roy if (l + n + 4 > len) 453 1.6 roy goto elen; 454 1.6 roy *ip++ = '$'; 455 1.6 roy *ip++ = '<'; 456 1.6 roy strncpy(ip, ps, n); 457 1.6 roy ip += n; 458 1.6 roy *ip++ = '/'; 459 1.6 roy *ip++ = '>'; 460 1.6 roy } 461 1.6 roy 462 1.3 roy *ip = '\0'; 463 1.3 roy return info; 464 1.3 roy 465 1.3 roy elen: 466 1.3 roy free(info); 467 1.3 roy errno = ENOMEM; 468 1.3 roy return NULL; 469 1.3 roy } 470 1.3 roy 471 1.9 roy typedef struct { 472 1.6 roy const char *name; 473 1.6 roy const char *cap; 474 1.9 roy } DEF_INFO; 475 1.9 roy 476 1.9 roy static DEF_INFO def_infos[] = { 477 1.6 roy { "bel", "^G" }, 478 1.6 roy { "cr", "^M" }, 479 1.6 roy { "cud1", "^J" }, 480 1.6 roy { "ht", "^I" }, 481 1.6 roy { "ind", "^J" }, 482 1.6 roy { "kbs", "^H" }, 483 1.6 roy { "kcub1", "^H" }, 484 1.6 roy { "kcud1", "^J" }, 485 1.6 roy { "nel", "^M^J" } 486 1.6 roy }; 487 1.6 roy 488 1.3 roy char * 489 1.3 roy captoinfo(char *cap) 490 1.3 roy { 491 1.3 roy char *info, *ip, *token, *val, *p, tok[3]; 492 1.3 roy const char *name; 493 1.3 roy size_t len, lp, nl, vl, rl; 494 1.7 roy int defs[__arraycount(def_infos)], fv; 495 1.3 roy 496 1.3 roy _DIAGASSERT(cap != NULL); 497 1.3 roy 498 1.3 roy len = strlen(cap) * 2; 499 1.6 roy len += __arraycount(def_infos) * (5 + 4 + 3); /* reserve for defs */ 500 1.3 roy info = ip = malloc(len); 501 1.3 roy if (info == NULL) 502 1.3 roy return NULL; 503 1.3 roy 504 1.6 roy memset(defs, 0, sizeof(defs)); 505 1.3 roy lp = 0; 506 1.3 roy tok[2] = '\0'; 507 1.5 roy for (token = _ti_get_token(&cap, ':'); 508 1.5 roy token != NULL; 509 1.5 roy token = _ti_get_token(&cap, ':')) 510 1.5 roy { 511 1.3 roy if (token[0] == '\0') 512 1.3 roy continue; 513 1.3 roy name = token; 514 1.7 roy val = p = NULL; 515 1.23 christos fv = 0; 516 1.23 christos nl = 0; 517 1.3 roy if (token[1] != '\0') { 518 1.3 roy tok[0] = token[0]; 519 1.3 roy tok[1] = token[1]; 520 1.7 roy nl = 1; 521 1.3 roy if (token[2] == '\0') { 522 1.3 roy name = flagname(tok); 523 1.3 roy val = NULL; 524 1.3 roy } else if (token[2] == '#') { 525 1.3 roy name = numname(tok); 526 1.3 roy val = token + 2; 527 1.3 roy } else if (token[2] == '=') { 528 1.3 roy name = strname(tok); 529 1.3 roy val = strval(token + 2); 530 1.7 roy fv = 1; 531 1.7 roy } else 532 1.7 roy nl = 0; 533 1.7 roy } 534 1.7 roy /* If not matched we may need to convert padding still. */ 535 1.7 roy if (nl == 0) { 536 1.7 roy p = strchr(name, '='); 537 1.7 roy if (p != NULL) { 538 1.7 roy val = strval(p); 539 1.7 roy *p = '\0'; 540 1.7 roy fv = 1; 541 1.3 roy } 542 1.3 roy } 543 1.6 roy 544 1.6 roy /* See if this sets a default. */ 545 1.6 roy for (nl = 0; nl < __arraycount(def_infos); nl++) { 546 1.6 roy if (strcmp(name, def_infos[nl].name) == 0) { 547 1.6 roy defs[nl] = 1; 548 1.6 roy break; 549 1.6 roy } 550 1.6 roy } 551 1.6 roy 552 1.3 roy nl = strlen(name); 553 1.3 roy if (val == NULL) 554 1.3 roy vl = 0; 555 1.3 roy else 556 1.3 roy vl = strlen(val); 557 1.3 roy rl = nl + vl + 3; /* , \0 */ 558 1.3 roy 559 1.3 roy if (lp + rl > len) { 560 1.3 roy if (rl < 256) 561 1.3 roy len += 256; 562 1.3 roy else 563 1.3 roy len += rl; 564 1.3 roy p = realloc(info, len); 565 1.18 christos if (p == NULL) { 566 1.18 christos if (fv == 1) 567 1.18 christos free(val); 568 1.3 roy return NULL; 569 1.18 christos } 570 1.3 roy info = p; 571 1.3 roy } 572 1.3 roy 573 1.3 roy if (ip != info) { 574 1.3 roy *ip++ = ','; 575 1.3 roy *ip++ = ' '; 576 1.3 roy } 577 1.3 roy 578 1.3 roy strcpy(ip, name); 579 1.3 roy ip += nl; 580 1.3 roy if (val != NULL) { 581 1.3 roy strcpy(ip, val); 582 1.3 roy ip += vl; 583 1.7 roy if (fv == 1) 584 1.3 roy free(val); 585 1.3 roy } 586 1.3 roy } 587 1.3 roy 588 1.6 roy /* Add any defaults not set above. */ 589 1.6 roy for (nl = 0; nl < __arraycount(def_infos); nl++) { 590 1.6 roy if (defs[nl] == 0) { 591 1.6 roy *ip++ = ','; 592 1.6 roy *ip++ = ' '; 593 1.6 roy strcpy(ip, def_infos[nl].name); 594 1.6 roy ip += strlen(def_infos[nl].name); 595 1.6 roy *ip++ = '='; 596 1.6 roy strcpy(ip, def_infos[nl].cap); 597 1.6 roy ip += strlen(def_infos[nl].cap); 598 1.6 roy } 599 1.6 roy } 600 1.6 roy 601 1.3 roy *ip = '\0'; 602 1.3 roy return info; 603 1.3 roy } 604 1.24 martin #endif 605