1 1.19 rillig /* $NetBSD: tparm.c,v 1.19 2021/08/27 18:40:28 rillig Exp $ */ 2 1.1 roy 3 1.1 roy /* 4 1.12 roy * Copyright (c) 2009, 2011, 2013 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.19 rillig __RCSID("$NetBSD: tparm.c,v 1.19 2021/08/27 18:40:28 rillig Exp $"); 32 1.8 roy #include <sys/param.h> 33 1.1 roy 34 1.1 roy #include <assert.h> 35 1.1 roy #include <ctype.h> 36 1.1 roy #include <errno.h> 37 1.1 roy #include <stdarg.h> 38 1.1 roy #include <stdio.h> 39 1.1 roy #include <stdlib.h> 40 1.1 roy #include <string.h> 41 1.1 roy #include <term_private.h> 42 1.1 roy #include <term.h> 43 1.1 roy 44 1.11 roy #define LONG_STR_MAX ((CHAR_BIT * sizeof(long)) / 3) 45 1.19 rillig #define BUFINC 128 /* Size to increment the terminal buffer by */ 46 1.11 roy 47 1.15 roy #define VA_LONG_LONG 1 48 1.14 roy #define VA_CHAR_INT 2 49 1.15 roy //#define VA_CHAR_LONG 3 /* No need for this yet */ 50 1.14 roy 51 1.1 roy static TERMINAL *dumbterm; /* For non thread safe functions */ 52 1.1 roy 53 1.2 roy typedef struct { 54 1.11 roy long nums[20]; 55 1.1 roy char *strings[20]; 56 1.1 roy size_t offset; 57 1.1 roy } TPSTACK; 58 1.1 roy 59 1.2 roy typedef struct { 60 1.11 roy long num; 61 1.1 roy char *string; 62 1.1 roy } TPVAR; 63 1.1 roy 64 1.1 roy static int 65 1.11 roy push(long num, char *string, TPSTACK *stack) 66 1.1 roy { 67 1.9 msaitoh if (stack->offset >= sizeof(stack->nums)) { 68 1.1 roy errno = E2BIG; 69 1.1 roy return -1; 70 1.1 roy } 71 1.1 roy stack->nums[stack->offset] = num; 72 1.1 roy stack->strings[stack->offset] = string; 73 1.1 roy stack->offset++; 74 1.1 roy return 0; 75 1.1 roy } 76 1.1 roy 77 1.1 roy static int 78 1.11 roy pop(long *num, char **string, TPSTACK *stack) 79 1.1 roy { 80 1.1 roy if (stack->offset == 0) { 81 1.5 roy if (num) 82 1.5 roy *num = 0; 83 1.5 roy if (string) 84 1.5 roy *string = NULL; 85 1.1 roy errno = E2BIG; 86 1.1 roy return -1; 87 1.1 roy } 88 1.1 roy stack->offset--; 89 1.1 roy if (num) 90 1.1 roy *num = stack->nums[stack->offset]; 91 1.1 roy if (string) 92 1.1 roy *string = stack->strings[stack->offset]; 93 1.1 roy return 0; 94 1.1 roy } 95 1.1 roy 96 1.1 roy static char * 97 1.1 roy checkbuf(TERMINAL *term, size_t len) 98 1.1 roy { 99 1.1 roy char *buf; 100 1.15 roy 101 1.1 roy if (term->_bufpos + len >= term->_buflen) { 102 1.11 roy len = term->_buflen + MAX(len, BUFINC); 103 1.1 roy buf = realloc(term->_buf, len); 104 1.1 roy if (buf == NULL) 105 1.8 roy return NULL; 106 1.1 roy term->_buf = buf; 107 1.1 roy term->_buflen = len; 108 1.1 roy } 109 1.1 roy return term->_buf; 110 1.1 roy } 111 1.1 roy 112 1.1 roy static size_t 113 1.1 roy ochar(TERMINAL *term, int c) 114 1.1 roy { 115 1.1 roy if (c == 0) 116 1.1 roy c = 0200; 117 1.1 roy /* Check we have space and a terminator */ 118 1.1 roy if (checkbuf(term, 2) == NULL) 119 1.1 roy return 0; 120 1.1 roy term->_buf[term->_bufpos++] = (char)c; 121 1.1 roy return 1; 122 1.1 roy } 123 1.1 roy 124 1.1 roy static size_t 125 1.17 roy onum(TERMINAL *term, const char *fmt, int num, size_t len) 126 1.1 roy { 127 1.17 roy int l; 128 1.17 roy size_t r; 129 1.1 roy 130 1.11 roy if (len < LONG_STR_MAX) 131 1.11 roy len = LONG_STR_MAX; 132 1.11 roy if (checkbuf(term, len + 2) == NULL) 133 1.1 roy return 0; 134 1.16 christos l = snprintf(term->_buf + term->_bufpos, len + 2, fmt, num); 135 1.17 roy if (l == -1) 136 1.17 roy return 0; 137 1.17 roy r = (size_t)l; 138 1.17 roy term->_bufpos += r; 139 1.17 roy return r; 140 1.1 roy } 141 1.1 roy 142 1.12 roy /* 143 1.12 roy Make a pass through the string so we can work out 144 1.12 roy which parameters are ints and which are char *. 145 1.12 roy Basically we only use char * if %p[1-9] is followed by %l or %s. 146 1.12 roy */ 147 1.12 roy int 148 1.12 roy _ti_parm_analyse(const char *str, int *piss, int piss_len) 149 1.12 roy { 150 1.12 roy int nparm, lpop; 151 1.12 roy char c; 152 1.12 roy 153 1.12 roy nparm = 0; 154 1.12 roy lpop = -1; 155 1.12 roy while ((c = *str++) != '\0') { 156 1.12 roy if (c != '%') 157 1.12 roy continue; 158 1.12 roy c = *str++; 159 1.12 roy switch (c) { 160 1.19 rillig case 'l': 161 1.12 roy case 's': 162 1.12 roy if (lpop > 0) { 163 1.12 roy if (lpop <= piss_len) 164 1.12 roy piss[lpop - 1] = 1; 165 1.12 roy else if (piss) 166 1.12 roy errno = E2BIG; 167 1.12 roy } 168 1.12 roy break; 169 1.12 roy case 'p': 170 1.12 roy c = *str++; 171 1.12 roy if (c < '1' || c > '9') { 172 1.12 roy errno = EINVAL; 173 1.12 roy continue; 174 1.12 roy } else { 175 1.12 roy lpop = c - '0'; 176 1.12 roy if (lpop > nparm) 177 1.12 roy nparm = lpop; 178 1.12 roy } 179 1.12 roy break; 180 1.12 roy default: 181 1.12 roy lpop = -1; 182 1.12 roy } 183 1.12 roy } 184 1.12 roy 185 1.12 roy return nparm; 186 1.12 roy } 187 1.12 roy 188 1.1 roy static char * 189 1.14 roy _ti_tiparm(TERMINAL *term, const char *str, int va_type, va_list parms) 190 1.1 roy { 191 1.1 roy char c, fmt[64], *fp, *ostr; 192 1.11 roy long val, val2; 193 1.11 roy long dnums[26]; /* dynamic variables a-z, not preserved */ 194 1.17 roy size_t l, max, width, precision, olen; 195 1.1 roy TPSTACK stack; 196 1.12 roy TPVAR params[TPARM_MAX]; 197 1.17 roy unsigned int done, dot, minus; 198 1.12 roy int piss[TPARM_MAX]; /* Parameter IS String - piss ;) */ 199 1.1 roy 200 1.1 roy if (str == NULL) 201 1.1 roy return NULL; 202 1.1 roy 203 1.1 roy /* 204 1.1 roy If not passed a terminal, malloc a dummy one. 205 1.1 roy This means we can preserve buffers and variables per terminal and 206 1.1 roy still work with non thread safe functions (which sadly are still the 207 1.1 roy norm and standard). 208 1.1 roy */ 209 1.1 roy if (term == NULL) { 210 1.1 roy if (dumbterm == NULL) { 211 1.1 roy dumbterm = malloc(sizeof(*dumbterm)); 212 1.1 roy if (dumbterm == NULL) 213 1.1 roy return NULL; 214 1.1 roy dumbterm->_buflen = 0; 215 1.1 roy } 216 1.1 roy term = dumbterm; 217 1.1 roy } 218 1.1 roy 219 1.1 roy term->_bufpos = 0; 220 1.1 roy /* Ensure we have an initial buffer */ 221 1.1 roy if (term->_buflen == 0) { 222 1.11 roy term->_buf = malloc(BUFINC); 223 1.1 roy if (term->_buf == NULL) 224 1.1 roy return NULL; 225 1.11 roy term->_buflen = BUFINC; 226 1.1 roy } 227 1.1 roy 228 1.1 roy memset(&piss, 0, sizeof(piss)); 229 1.17 roy max = (size_t)_ti_parm_analyse(str, piss, TPARM_MAX); 230 1.1 roy 231 1.1 roy /* Put our parameters into variables */ 232 1.1 roy memset(¶ms, 0, sizeof(params)); 233 1.1 roy for (l = 0; l < max; l++) { 234 1.13 roy if (piss[l]) { 235 1.14 roy if (va_type == VA_LONG_LONG) { 236 1.13 roy /* This only works if char * fits into a long 237 1.13 roy * on this platform. */ 238 1.19 rillig if (sizeof(char *) <= sizeof(long)) 239 1.13 roy params[l].string = 240 1.13 roy (char *)va_arg(parms, long); 241 1.13 roy else { 242 1.13 roy errno = ENOTSUP; 243 1.13 roy return NULL; 244 1.13 roy } 245 1.13 roy } else 246 1.13 roy params[l].string = va_arg(parms, char *); 247 1.13 roy } else { 248 1.14 roy if (va_type == VA_CHAR_INT) 249 1.14 roy params[l].num = (long)va_arg(parms, int); 250 1.14 roy else 251 1.13 roy params[l].num = va_arg(parms, long); 252 1.13 roy } 253 1.1 roy } 254 1.1 roy 255 1.1 roy memset(&stack, 0, sizeof(stack)); 256 1.1 roy while ((c = *str++) != '\0') { 257 1.1 roy if (c != '%' || (c = *str++) == '%') { 258 1.1 roy if (c == '\0') 259 1.1 roy break; 260 1.1 roy if (ochar(term, c) == 0) 261 1.1 roy return NULL; 262 1.1 roy continue; 263 1.1 roy } 264 1.1 roy 265 1.1 roy /* Handle formatting. */ 266 1.1 roy fp = fmt; 267 1.1 roy *fp++ = '%'; 268 1.18 christos done = dot = minus = 0; 269 1.18 christos width = precision = 0; 270 1.1 roy val = 0; 271 1.1 roy while (done == 0 && (size_t)(fp - fmt) < sizeof(fmt)) { 272 1.1 roy switch (c) { 273 1.19 rillig case 'c': 274 1.11 roy case 's': 275 1.11 roy *fp++ = c; 276 1.11 roy done = 1; 277 1.11 roy break; 278 1.19 rillig case 'd': 279 1.19 rillig case 'o': 280 1.19 rillig case 'x': 281 1.19 rillig case 'X': 282 1.11 roy *fp++ = 'l'; 283 1.1 roy *fp++ = c; 284 1.1 roy done = 1; 285 1.1 roy break; 286 1.19 rillig case '#': 287 1.1 roy case ' ': 288 1.1 roy *fp++ = c; 289 1.1 roy break; 290 1.1 roy case '.': 291 1.1 roy *fp++ = c; 292 1.1 roy if (dot == 0) { 293 1.1 roy dot = 1; 294 1.17 roy width = (size_t)val; 295 1.1 roy } else 296 1.1 roy done = 2; 297 1.1 roy val = 0; 298 1.1 roy break; 299 1.1 roy case ':': 300 1.1 roy minus = 1; 301 1.1 roy break; 302 1.1 roy case '-': 303 1.1 roy if (minus) 304 1.1 roy *fp++ = c; 305 1.1 roy else 306 1.1 roy done = 1; 307 1.1 roy break; 308 1.1 roy default: 309 1.1 roy if (isdigit((unsigned char)c)) { 310 1.1 roy val = (val * 10) + (c - '0'); 311 1.1 roy if (val > 10000) 312 1.1 roy done = 2; 313 1.1 roy else 314 1.1 roy *fp++ = c; 315 1.1 roy } else 316 1.1 roy done = 1; 317 1.1 roy } 318 1.1 roy if (done == 0) 319 1.1 roy c = *str++; 320 1.1 roy } 321 1.1 roy if (done == 2) { 322 1.1 roy /* Found an error in the format */ 323 1.1 roy fp = fmt + 1; 324 1.1 roy *fp = *str; 325 1.1 roy olen = 0; 326 1.1 roy } else { 327 1.1 roy if (dot == 0) 328 1.17 roy width = (size_t)val; 329 1.1 roy else 330 1.17 roy precision = (size_t)val; 331 1.11 roy olen = MAX(width, precision); 332 1.1 roy } 333 1.1 roy *fp++ = '\0'; 334 1.1 roy 335 1.1 roy /* Handle commands */ 336 1.1 roy switch (c) { 337 1.1 roy case 'c': 338 1.5 roy pop(&val, NULL, &stack); 339 1.1 roy if (ochar(term, (unsigned char)val) == 0) 340 1.1 roy return NULL; 341 1.1 roy break; 342 1.1 roy case 's': 343 1.5 roy pop(NULL, &ostr, &stack); 344 1.1 roy if (ostr != NULL) { 345 1.17 roy int r; 346 1.17 roy 347 1.1 roy l = strlen(ostr); 348 1.1 roy if (l < (size_t)olen) 349 1.1 roy l = olen; 350 1.1 roy if (checkbuf(term, (size_t)(l + 1)) == NULL) 351 1.1 roy return NULL; 352 1.17 roy r = snprintf(term->_buf + term->_bufpos, l + 1, 353 1.1 roy fmt, ostr); 354 1.17 roy if (r != -1) 355 1.17 roy term->_bufpos += (size_t)r; 356 1.1 roy } 357 1.1 roy break; 358 1.1 roy case 'l': 359 1.5 roy pop(NULL, &ostr, &stack); 360 1.1 roy if (ostr == NULL) 361 1.1 roy l = 0; 362 1.1 roy else 363 1.1 roy l = strlen(ostr); 364 1.11 roy #ifdef NCURSES_COMPAT_57 365 1.11 roy if (onum(term, "%ld", (long)l, 0) == 0) 366 1.1 roy return NULL; 367 1.11 roy #else 368 1.11 roy push((long)l, NULL, &stack); 369 1.11 roy #endif 370 1.1 roy break; 371 1.19 rillig case 'd': 372 1.19 rillig case 'o': 373 1.19 rillig case 'x': 374 1.1 roy case 'X': 375 1.5 roy pop(&val, NULL, &stack); 376 1.11 roy if (onum(term, fmt, (int)val, olen) == 0) 377 1.1 roy return NULL; 378 1.1 roy break; 379 1.1 roy case 'p': 380 1.5 roy if (*str < '1' || *str > '9') 381 1.5 roy break; 382 1.17 roy l = (size_t)(*str++ - '1'); 383 1.1 roy if (push(params[l].num, params[l].string, &stack)) 384 1.1 roy return NULL; 385 1.1 roy break; 386 1.1 roy case 'P': 387 1.5 roy pop(&val, NULL, &stack); 388 1.1 roy if (*str >= 'a' && *str <= 'z') 389 1.1 roy dnums[*str - 'a'] = val; 390 1.1 roy else if (*str >= 'A' && *str <= 'Z') 391 1.1 roy term->_snums[*str - 'A'] = val; 392 1.1 roy break; 393 1.1 roy case 'g': 394 1.1 roy if (*str >= 'a' && *str <= 'z') { 395 1.1 roy if (push(dnums[*str - 'a'], NULL, &stack)) 396 1.1 roy return NULL; 397 1.1 roy } else if (*str >= 'A' && *str <= 'Z') { 398 1.1 roy if (push(term->_snums[*str - 'A'], 399 1.1 roy NULL, &stack)) 400 1.1 roy return NULL; 401 1.1 roy } 402 1.1 roy break; 403 1.1 roy case 'i': 404 1.1 roy if (piss[0] == 0) 405 1.1 roy params[0].num++; 406 1.1 roy if (piss[1] == 0) 407 1.1 roy params[1].num++; 408 1.1 roy break; 409 1.1 roy case '\'': 410 1.11 roy if (push((long)(unsigned char)*str++, NULL, &stack)) 411 1.1 roy return NULL; 412 1.1 roy while (*str != '\0' && *str != '\'') 413 1.1 roy str++; 414 1.1 roy if (*str == '\'') 415 1.1 roy str++; 416 1.1 roy break; 417 1.1 roy case '{': 418 1.1 roy val = 0; 419 1.3 roy for (; isdigit((unsigned char)*str); str++) 420 1.1 roy val = (val * 10) + (*str - '0'); 421 1.1 roy if (push(val, NULL, &stack)) 422 1.1 roy return NULL; 423 1.1 roy while (*str != '\0' && *str != '}') 424 1.1 roy str++; 425 1.1 roy if (*str == '}') 426 1.1 roy str++; 427 1.1 roy break; 428 1.19 rillig case '+': 429 1.19 rillig case '-': 430 1.19 rillig case '*': 431 1.19 rillig case '/': 432 1.19 rillig case 'm': 433 1.19 rillig case 'A': 434 1.19 rillig case 'O': 435 1.19 rillig case '&': 436 1.19 rillig case '|': 437 1.19 rillig case '^': 438 1.19 rillig case '=': 439 1.19 rillig case '<': 440 1.1 roy case '>': 441 1.5 roy pop(&val, NULL, &stack); 442 1.5 roy pop(&val2, NULL, &stack); 443 1.1 roy switch (c) { 444 1.1 roy case '+': 445 1.1 roy val = val + val2; 446 1.1 roy break; 447 1.1 roy case '-': 448 1.1 roy val = val2 - val; 449 1.1 roy break; 450 1.1 roy case '*': 451 1.1 roy val = val * val2; 452 1.1 roy break; 453 1.1 roy case '/': 454 1.1 roy val = val ? val2 / val : 0; 455 1.1 roy break; 456 1.1 roy case 'm': 457 1.1 roy val = val ? val2 % val : 0; 458 1.1 roy break; 459 1.1 roy case 'A': 460 1.1 roy val = val && val2; 461 1.1 roy break; 462 1.1 roy case 'O': 463 1.1 roy val = val || val2; 464 1.1 roy break; 465 1.1 roy case '&': 466 1.1 roy val = val & val2; 467 1.1 roy break; 468 1.1 roy case '|': 469 1.1 roy val = val | val2; 470 1.1 roy break; 471 1.1 roy case '^': 472 1.1 roy val = val ^ val2; 473 1.1 roy break; 474 1.1 roy case '=': 475 1.1 roy val = val == val2; 476 1.1 roy break; 477 1.1 roy case '<': 478 1.1 roy val = val2 < val; 479 1.1 roy break; 480 1.1 roy case '>': 481 1.1 roy val = val2 > val; 482 1.1 roy break; 483 1.1 roy } 484 1.1 roy if (push(val, NULL, &stack)) 485 1.1 roy return NULL; 486 1.1 roy break; 487 1.1 roy case '!': 488 1.1 roy case '~': 489 1.5 roy pop(&val, NULL, &stack); 490 1.11 roy switch (c) { 491 1.1 roy case '!': 492 1.1 roy val = !val; 493 1.1 roy break; 494 1.1 roy case '~': 495 1.1 roy val = ~val; 496 1.1 roy break; 497 1.1 roy } 498 1.1 roy if (push(val, NULL, &stack)) 499 1.1 roy return NULL; 500 1.1 roy break; 501 1.1 roy case '?': /* if */ 502 1.1 roy break; 503 1.1 roy case 't': /* then */ 504 1.5 roy pop(&val, NULL, &stack); 505 1.10 roy if (val == 0) { 506 1.1 roy l = 0; 507 1.1 roy for (; *str != '\0'; str++) { 508 1.1 roy if (*str != '%') 509 1.1 roy continue; 510 1.1 roy str++; 511 1.1 roy if (*str == '?') 512 1.1 roy l++; 513 1.1 roy else if (*str == ';') { 514 1.1 roy if (l > 0) 515 1.1 roy l--; 516 1.10 roy else { 517 1.10 roy str++; 518 1.1 roy break; 519 1.10 roy } 520 1.10 roy } else if (*str == 'e' && l == 0) { 521 1.10 roy str++; 522 1.1 roy break; 523 1.10 roy } 524 1.1 roy } 525 1.1 roy } 526 1.1 roy break; 527 1.1 roy case 'e': /* else */ 528 1.1 roy l = 0; 529 1.1 roy for (; *str != '\0'; str++) { 530 1.1 roy if (*str != '%') 531 1.1 roy continue; 532 1.1 roy str++; 533 1.1 roy if (*str == '?') 534 1.1 roy l++; 535 1.1 roy else if (*str == ';') { 536 1.1 roy if (l > 0) 537 1.1 roy l--; 538 1.10 roy else { 539 1.10 roy str++; 540 1.1 roy break; 541 1.10 roy } 542 1.1 roy } 543 1.1 roy } 544 1.1 roy break; 545 1.1 roy case ';': /* fi */ 546 1.1 roy break; 547 1.1 roy } 548 1.1 roy } 549 1.1 roy term->_buf[term->_bufpos] = '\0'; 550 1.1 roy return term->_buf; 551 1.1 roy } 552 1.1 roy 553 1.1 roy char * 554 1.6 roy ti_tiparm(TERMINAL *term, const char *str, ...) 555 1.1 roy { 556 1.1 roy va_list va; 557 1.1 roy char *ret; 558 1.1 roy 559 1.1 roy _DIAGASSERT(term != NULL); 560 1.1 roy _DIAGASSERT(str != NULL); 561 1.1 roy 562 1.1 roy va_start(va, str); 563 1.14 roy ret = _ti_tiparm(term, str, VA_CHAR_INT, va); 564 1.1 roy va_end(va); 565 1.1 roy return ret; 566 1.1 roy } 567 1.1 roy 568 1.1 roy char * 569 1.6 roy tiparm(const char *str, ...) 570 1.1 roy { 571 1.1 roy va_list va; 572 1.1 roy char *ret; 573 1.15 roy 574 1.1 roy _DIAGASSERT(str != NULL); 575 1.1 roy 576 1.1 roy va_start(va, str); 577 1.14 roy ret = _ti_tiparm(NULL, str, VA_CHAR_INT, va); 578 1.11 roy va_end(va); 579 1.11 roy return ret; 580 1.11 roy } 581 1.11 roy 582 1.14 roy #ifdef VA_CHAR_LONG 583 1.14 roy char * 584 1.14 roy ti_tlparm(TERMINAL *term, const char *str, ...) 585 1.14 roy { 586 1.14 roy va_list va; 587 1.14 roy char *ret; 588 1.14 roy 589 1.14 roy _DIAGASSERT(term != NULL); 590 1.14 roy _DIAGASSERT(str != NULL); 591 1.14 roy 592 1.14 roy va_start(va, str); 593 1.14 roy ret = _ti_tiparm(term, str, VA_CHAR_LONG, va); 594 1.14 roy va_end(va); 595 1.14 roy return ret; 596 1.14 roy } 597 1.14 roy 598 1.14 roy char * 599 1.14 roy tlparm(const char *str, ...) 600 1.14 roy { 601 1.14 roy va_list va; 602 1.14 roy char *ret; 603 1.15 roy 604 1.14 roy _DIAGASSERT(str != NULL); 605 1.14 roy 606 1.14 roy va_start(va, str); 607 1.14 roy ret = _ti_tiparm(NULL, str, VA_CHAR_LONG, va); 608 1.14 roy va_end(va); 609 1.14 roy return ret; 610 1.14 roy } 611 1.14 roy #endif 612 1.14 roy 613 1.11 roy static char * 614 1.14 roy _tparm(const char *str, ...) 615 1.11 roy { 616 1.11 roy va_list va; 617 1.11 roy char *ret; 618 1.15 roy 619 1.11 roy _DIAGASSERT(str != NULL); 620 1.11 roy 621 1.11 roy va_start(va, str); 622 1.14 roy ret = _ti_tiparm(NULL, str, VA_LONG_LONG, va); 623 1.1 roy va_end(va); 624 1.1 roy return ret; 625 1.1 roy } 626 1.1 roy 627 1.1 roy char * 628 1.1 roy tparm(const char *str, 629 1.11 roy long p1, long p2, long p3, long p4, long p5, 630 1.11 roy long p6, long p7, long p8, long p9) 631 1.1 roy { 632 1.7 roy 633 1.14 roy return _tparm(str, p1, p2, p3, p4, p5, p6, p7, p8, p9); 634 1.1 roy } 635