PageRenderTime 63ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/fallback.cpp

https://github.com/psychocandy/fish-shell
C++ | 1480 lines | 1046 code | 228 blank | 206 comment | 217 complexity | 91e7d9e7c6531669253fc98c0022639d MD5 | raw file
Possible License(s): LGPL-2.0
  1. /**
  2. This file only contains fallback implementations of functions which
  3. have been found to be missing or broken by the configuration
  4. scripts.
  5. Many of these functions are more or less broken and
  6. incomplete. lrand28_r internally uses the regular (bad) rand_r
  7. function, the gettext function doesn't actually do anything, etc.
  8. */
  9. #include "config.h"
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <unistd.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <unistd.h>
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <wchar.h>
  19. #include <wctype.h>
  20. #include <string.h>
  21. #include <dirent.h>
  22. #include <stdarg.h>
  23. #include <limits.h>
  24. #include <assert.h>
  25. #if HAVE_NCURSES_H
  26. #include <ncurses.h>
  27. #else
  28. #include <curses.h>
  29. #endif
  30. #if HAVE_TERMIO_H
  31. #include <termio.h>
  32. #endif
  33. #if HAVE_TERM_H
  34. #include <term.h>
  35. #elif HAVE_NCURSES_TERM_H
  36. #include <ncurses/term.h>
  37. #endif
  38. #include "fallback.h"
  39. #include "util.h"
  40. #ifndef HAVE___ENVIRON
  41. char **__environ = 0;
  42. #endif
  43. #ifdef TPUTS_KLUDGE
  44. int tputs(const char *str, int affcnt, int (*fish_putc)(tputs_arg_t))
  45. {
  46. while( *str )
  47. {
  48. fish_putc( *str++ );
  49. }
  50. }
  51. #endif
  52. #ifdef TPARM_SOLARIS_KLUDGE
  53. #undef tparm
  54. /**
  55. Checks for known string values and maps to correct number of parameters.
  56. */
  57. char *tparm_solaris_kludge( char *str, ... )
  58. {
  59. long int param[9] = { };
  60. va_list ap;
  61. va_start( ap, str );
  62. if( ( set_a_foreground && ! strcmp( str, set_a_foreground ) )
  63. || ( set_a_background && ! strcmp( str, set_a_background ) )
  64. || ( set_foreground && ! strcmp( str, set_foreground ) )
  65. || ( set_background && ! strcmp( str, set_background ) )
  66. || ( enter_underline_mode && ! strcmp( str, enter_underline_mode ) )
  67. || ( exit_underline_mode && ! strcmp( str, exit_underline_mode ) )
  68. || ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) )
  69. || ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) )
  70. || ( flash_screen && ! strcmp( str, flash_screen ) )
  71. || ( enter_subscript_mode && ! strcmp( str, enter_subscript_mode ) )
  72. || ( exit_subscript_mode && ! strcmp( str, exit_subscript_mode ) )
  73. || ( enter_superscript_mode && ! strcmp( str, enter_superscript_mode ) )
  74. || ( exit_superscript_mode && ! strcmp( str, exit_superscript_mode ) )
  75. || ( enter_blink_mode && ! strcmp( str, enter_blink_mode ) )
  76. || ( enter_italics_mode && ! strcmp( str, enter_italics_mode ) )
  77. || ( exit_italics_mode && ! strcmp( str, exit_italics_mode ) )
  78. || ( enter_reverse_mode && ! strcmp( str, enter_reverse_mode ) )
  79. || ( enter_shadow_mode && ! strcmp( str, enter_shadow_mode ) )
  80. || ( exit_shadow_mode && ! strcmp( str, exit_shadow_mode ) )
  81. || ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) )
  82. || ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) )
  83. || ( enter_secure_mode && ! strcmp( str, enter_secure_mode ) )
  84. || ( enter_bold_mode && ! strcmp ( str, enter_bold_mode ) ) )
  85. {
  86. param[0] = va_arg( ap, long int );
  87. }
  88. else if( cursor_address && ! strcmp( str, cursor_address ) )
  89. {
  90. param[0] = va_arg( ap, long int );
  91. param[1] = va_arg( ap, long int );
  92. }
  93. va_end( ap );
  94. return tparm( str, param[0], param[1], param[2], param[3],
  95. param[4], param[5], param[6], param[7], param[8] );
  96. }
  97. // Re-defining just to make sure nothing breaks further down in this file.
  98. #define tparm tparm_solaris_kludge
  99. #endif
  100. #ifndef HAVE_FWPRINTF
  101. #define INTERNAL_FWPRINTF 1
  102. #endif
  103. #ifdef HAVE_BROKEN_FWPRINTF
  104. #define INTERNAL_FWPRINTF 1
  105. #endif
  106. #ifdef INTERNAL_FWPRINTF
  107. /**
  108. Internal function for the wprintf fallbacks. USed to write the
  109. specified number of spaces.
  110. */
  111. static void pad( void (*writer)(wchar_t), int count)
  112. {
  113. int i;
  114. if( count < 0 )
  115. return;
  116. for( i=0; i<count; i++ )
  117. {
  118. writer( L' ' );
  119. }
  120. }
  121. /**
  122. Generic formatting function. All other string formatting functions
  123. are secretly a wrapper around this function. vgprintf does not
  124. implement all the filters supported by printf, only those that are
  125. currently used by fish. vgprintf internally uses snprintf to
  126. implement the number outputs, such as %f and %x.
  127. Currently supported functionality:
  128. - precision specification, both through .* and .N
  129. - Padding through * and N
  130. - Right padding using the - prefix
  131. - long versions of all filters thorugh l and ll prefix
  132. - Character output using %c
  133. - String output through %s
  134. - Floating point number output through %f
  135. - Integer output through %d, %i, %u, %o, %x and %X
  136. For a full description on the usage of *printf, see use 'man 3 printf'.
  137. */
  138. static int vgwprintf( void (*writer)(wchar_t),
  139. const wchar_t *filter,
  140. va_list va )
  141. {
  142. const wchar_t *filter_org=filter;
  143. int count=0;
  144. for( ;*filter; filter++)
  145. {
  146. if(*filter == L'%')
  147. {
  148. int is_long=0;
  149. int width = -1;
  150. filter++;
  151. int loop=1;
  152. int precision=-1;
  153. int pad_left = 1;
  154. if( iswdigit( *filter ) )
  155. {
  156. width=0;
  157. while( (*filter >= L'0') && (*filter <= L'9'))
  158. {
  159. width=10*width+(*filter++ - L'0');
  160. }
  161. }
  162. while( loop )
  163. {
  164. switch(*filter)
  165. {
  166. case L'l':
  167. /* Long variable */
  168. is_long++;
  169. filter++;
  170. break;
  171. case L'*':
  172. /* Set minimum field width */
  173. width = va_arg( va, int );
  174. filter++;
  175. break;
  176. case L'-':
  177. filter++;
  178. pad_left=0;
  179. break;
  180. case L'.':
  181. /*
  182. Set precision.
  183. */
  184. filter++;
  185. if( *filter == L'*' )
  186. {
  187. precision = va_arg( va, int );
  188. }
  189. else
  190. {
  191. precision=0;
  192. while( (*filter >= L'0') && (*filter <= L'9'))
  193. {
  194. precision=10*precision+(*filter++ - L'0');
  195. }
  196. }
  197. break;
  198. default:
  199. loop=0;
  200. break;
  201. }
  202. }
  203. switch( *filter )
  204. {
  205. case L'c':
  206. {
  207. wchar_t c;
  208. if( (width >= 0) && pad_left )
  209. {
  210. pad( writer, width-1 );
  211. count += maxi( width-1, 0 );
  212. }
  213. c = is_long?va_arg(va, wint_t):btowc(va_arg(va, int));
  214. if( precision != 0 )
  215. writer( c );
  216. if( (width >= 0) && !pad_left )
  217. {
  218. pad( writer, width-1 );
  219. count += maxi( width-1, 0 );
  220. }
  221. count++;
  222. break;
  223. }
  224. case L's':
  225. {
  226. wchar_t *ss=0;
  227. if( is_long )
  228. {
  229. ss = va_arg(va, wchar_t *);
  230. }
  231. else
  232. {
  233. char *ns = va_arg(va, char*);
  234. if( ns )
  235. {
  236. ss = str2wcs( ns );
  237. }
  238. }
  239. if( !ss )
  240. {
  241. return -1;
  242. }
  243. if( (width >= 0) && pad_left )
  244. {
  245. pad( writer, width-wcslen(ss) );
  246. count += maxi(width-wcslen(ss), 0);
  247. }
  248. wchar_t *s=ss;
  249. int precount = count;
  250. while( *s )
  251. {
  252. if( (precision > 0) && (precision <= (count-precount) ) )
  253. break;
  254. writer( *(s++) );
  255. count++;
  256. }
  257. if( (width >= 0) && !pad_left )
  258. {
  259. pad( writer, width-wcslen(ss) );
  260. count += maxi( width-wcslen(ss), 0 );
  261. }
  262. if( !is_long )
  263. free( ss );
  264. break;
  265. }
  266. case L'd':
  267. case L'i':
  268. case L'o':
  269. case L'u':
  270. case L'x':
  271. case L'X':
  272. {
  273. char str[33];
  274. char *pos;
  275. char format[16];
  276. int len;
  277. format[0]=0;
  278. strcat( format, "%");
  279. if( precision >= 0 )
  280. strcat( format, ".*" );
  281. switch( is_long )
  282. {
  283. case 2:
  284. strcat( format, "ll" );
  285. break;
  286. case 1:
  287. strcat( format, "l" );
  288. break;
  289. }
  290. len = strlen(format);
  291. format[len++]=(char)*filter;
  292. format[len]=0;
  293. switch( *filter )
  294. {
  295. case L'd':
  296. case L'i':
  297. {
  298. switch( is_long )
  299. {
  300. case 0:
  301. {
  302. int d = va_arg( va, int );
  303. if( precision >= 0 )
  304. snprintf( str, 32, format, precision, d );
  305. else
  306. snprintf( str, 32, format, d );
  307. break;
  308. }
  309. case 1:
  310. {
  311. long d = va_arg( va, long );
  312. if( precision >= 0 )
  313. snprintf( str, 32, format, precision, d );
  314. else
  315. snprintf( str, 32, format, d );
  316. break;
  317. }
  318. case 2:
  319. {
  320. long long d = va_arg( va, long long );
  321. if( precision >= 0 )
  322. snprintf( str, 32, format, precision, d );
  323. else
  324. snprintf( str, 32, format, d );
  325. break;
  326. }
  327. default:
  328. debug( 0, L"Invalid length modifier in string %ls\n", filter_org );
  329. return -1;
  330. }
  331. break;
  332. }
  333. case L'u':
  334. case L'o':
  335. case L'x':
  336. case L'X':
  337. {
  338. switch( is_long )
  339. {
  340. case 0:
  341. {
  342. unsigned d = va_arg( va, unsigned );
  343. if( precision >= 0 )
  344. snprintf( str, 32, format, precision, d );
  345. else
  346. snprintf( str, 32, format, d );
  347. break;
  348. }
  349. case 1:
  350. {
  351. unsigned long d = va_arg( va, unsigned long );
  352. if( precision >= 0 )
  353. snprintf( str, 32, format, precision, d );
  354. else
  355. snprintf( str, 32, format, d );
  356. break;
  357. }
  358. case 2:
  359. {
  360. unsigned long long d = va_arg( va, unsigned long long );
  361. if( precision >= 0 )
  362. snprintf( str, 32, format, precision, d );
  363. else
  364. snprintf( str, 32, format, d );
  365. break;
  366. }
  367. default:
  368. debug( 0, L"Invalid length modifier in string %ls\n", filter_org );
  369. return -1;
  370. }
  371. break;
  372. }
  373. default:
  374. debug( 0, L"Invalid filter %ls in string %ls\n", *filter, filter_org );
  375. return -1;
  376. }
  377. if( (width >= 0) && pad_left )
  378. {
  379. int l = maxi(width-strlen(str), 0 );
  380. pad( writer, l );
  381. count += l;
  382. }
  383. pos = str;
  384. while( *pos )
  385. {
  386. writer( *(pos++) );
  387. count++;
  388. }
  389. if( (width >= 0) && !pad_left )
  390. {
  391. int l = maxi(width-strlen(str), 0 );
  392. pad( writer, l );
  393. count += l;
  394. }
  395. break;
  396. }
  397. case L'f':
  398. {
  399. char str[32];
  400. char *pos;
  401. double val = va_arg( va, double );
  402. if( precision>= 0 )
  403. {
  404. if( width>= 0 )
  405. {
  406. snprintf( str, 32, "%*.*f", width, precision, val );
  407. }
  408. else
  409. {
  410. snprintf( str, 32, "%.*f", precision, val );
  411. }
  412. }
  413. else
  414. {
  415. if( width>= 0 )
  416. {
  417. snprintf( str, 32, "%*f", width, val );
  418. }
  419. else
  420. {
  421. snprintf( str, 32, "%f", val );
  422. }
  423. }
  424. pos = str;
  425. while( *pos )
  426. {
  427. writer( *(pos++) );
  428. count++;
  429. }
  430. break;
  431. }
  432. case L'n':
  433. {
  434. int *n = va_arg( va, int *);
  435. *n = count;
  436. break;
  437. }
  438. case L'%':
  439. {
  440. writer('%');
  441. count++;
  442. break;
  443. }
  444. default:
  445. debug( 0, L"Unknown switch %lc in string %ls\n", *filter, filter_org );
  446. return -1;
  447. }
  448. }
  449. else
  450. {
  451. writer( *filter );
  452. count++;
  453. }
  454. }
  455. return count;
  456. }
  457. /**
  458. Holds data for swprintf writer
  459. */
  460. static struct
  461. {
  462. int count;
  463. int max;
  464. wchar_t *pos;
  465. }
  466. sw_data;
  467. /**
  468. Writers for string output
  469. */
  470. static void sw_writer( wchar_t c )
  471. {
  472. if( sw_data.count < sw_data.max )
  473. *(sw_data.pos++)=c;
  474. sw_data.count++;
  475. }
  476. int vswprintf( wchar_t *out, size_t n, const wchar_t *filter, va_list va )
  477. {
  478. int written;
  479. sw_data.pos=out;
  480. sw_data.max=n;
  481. sw_data.count=0;
  482. written=vgwprintf( &sw_writer,
  483. filter,
  484. va );
  485. if( written < n )
  486. {
  487. *sw_data.pos = 0;
  488. }
  489. else
  490. {
  491. written=-1;
  492. }
  493. return written;
  494. }
  495. int swprintf( wchar_t *out, size_t n, const wchar_t *filter, ... )
  496. {
  497. va_list va;
  498. int written;
  499. va_start( va, filter );
  500. written = vswprintf( out, n, filter, va );
  501. va_end( va );
  502. return written;
  503. }
  504. /**
  505. Holds auxiliary data for fwprintf and wprintf writer
  506. */
  507. static FILE *fw_data;
  508. static void fw_writer( wchar_t c )
  509. {
  510. putwc( c, fw_data );
  511. }
  512. /*
  513. Writers for file output
  514. */
  515. int vfwprintf( FILE *f, const wchar_t *filter, va_list va )
  516. {
  517. fw_data = f;
  518. return vgwprintf( &fw_writer, filter, va );
  519. }
  520. int fwprintf( FILE *f, const wchar_t *filter, ... )
  521. {
  522. va_list va;
  523. int written;
  524. va_start( va, filter );
  525. written = vfwprintf( f, filter, va );
  526. va_end( va );
  527. return written;
  528. }
  529. int vwprintf( const wchar_t *filter, va_list va )
  530. {
  531. return vfwprintf( stdout, filter, va );
  532. }
  533. int wprintf( const wchar_t *filter, ... )
  534. {
  535. va_list va;
  536. int written;
  537. va_start( va, filter );
  538. written=vwprintf( filter, va );
  539. va_end( va );
  540. return written;
  541. }
  542. #endif
  543. #ifndef HAVE_FGETWC
  544. wint_t fgetwc(FILE *stream)
  545. {
  546. wchar_t res=0;
  547. mbstate_t state;
  548. memset (&state, '\0', sizeof (state));
  549. while(1)
  550. {
  551. int b = fgetc( stream );
  552. char bb;
  553. int sz;
  554. if( b == EOF )
  555. return WEOF;
  556. bb=b;
  557. sz = mbrtowc( &res, &bb, 1, &state );
  558. switch( sz )
  559. {
  560. case -1:
  561. memset (&state, '\0', sizeof (state));
  562. return WEOF;
  563. case -2:
  564. break;
  565. case 0:
  566. return 0;
  567. default:
  568. return res;
  569. }
  570. }
  571. }
  572. wint_t getwc(FILE *stream)
  573. {
  574. return fgetwc( stream );
  575. }
  576. #endif
  577. #ifndef HAVE_FPUTWC
  578. wint_t fputwc(wchar_t wc, FILE *stream)
  579. {
  580. int res;
  581. char s[MB_CUR_MAX+1];
  582. memset( s, 0, MB_CUR_MAX+1 );
  583. wctomb( s, wc );
  584. res = fputs( s, stream );
  585. return res==EOF?WEOF:wc;
  586. }
  587. wint_t putwc(wchar_t wc, FILE *stream)
  588. {
  589. return fputwc( wc, stream );
  590. }
  591. #endif
  592. #ifndef HAVE_WCSTOK
  593. /*
  594. Used by fallback wcstok. Borrowed from glibc
  595. */
  596. static size_t fish_wcsspn (const wchar_t *wcs,
  597. const wchar_t *accept )
  598. {
  599. register const wchar_t *p;
  600. register const wchar_t *a;
  601. register size_t count = 0;
  602. for (p = wcs; *p != L'\0'; ++p)
  603. {
  604. for (a = accept; *a != L'\0'; ++a)
  605. if (*p == *a)
  606. break;
  607. if (*a == L'\0')
  608. return count;
  609. else
  610. ++count;
  611. }
  612. return count;
  613. }
  614. /*
  615. Used by fallback wcstok. Borrowed from glibc
  616. */
  617. static wchar_t *fish_wcspbrk (const wchar_t *wcs, const wchar_t *accept)
  618. {
  619. while (*wcs != L'\0')
  620. if (wcschr (accept, *wcs) == NULL)
  621. ++wcs;
  622. else
  623. return (wchar_t *) wcs;
  624. return NULL;
  625. }
  626. /*
  627. Fallback wcstok implementation. Borrowed from glibc.
  628. */
  629. wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **save_ptr)
  630. {
  631. wchar_t *result;
  632. if (wcs == NULL)
  633. {
  634. if (*save_ptr == NULL)
  635. {
  636. errno = EINVAL;
  637. return NULL;
  638. }
  639. else
  640. wcs = *save_ptr;
  641. }
  642. /* Scan leading delimiters. */
  643. wcs += fish_wcsspn (wcs, delim);
  644. if (*wcs == L'\0')
  645. {
  646. *save_ptr = NULL;
  647. return NULL;
  648. }
  649. /* Find the end of the token. */
  650. result = wcs;
  651. wcs = fish_wcspbrk (result, delim);
  652. if (wcs == NULL)
  653. {
  654. /* This token finishes the string. */
  655. *save_ptr = NULL;
  656. }
  657. else
  658. {
  659. /* Terminate the token and make *SAVE_PTR point past it. */
  660. *wcs = L'\0';
  661. *save_ptr = wcs + 1;
  662. }
  663. return result;
  664. }
  665. #endif
  666. /* Fallback implementations of wcsdup and wcscasecmp. On systems where these are not needed (e.g. building on Linux) these should end up just being stripped, as they are static functions that are not referenced in this file.
  667. */
  668. static wchar_t *wcsdup_fallback(const wchar_t *in)
  669. {
  670. size_t len=wcslen(in);
  671. wchar_t *out = (wchar_t *)malloc( sizeof( wchar_t)*(len+1));
  672. if( out == 0 )
  673. {
  674. return 0;
  675. }
  676. memcpy( out, in, sizeof( wchar_t)*(len+1));
  677. return out;
  678. }
  679. int wcscasecmp_fallback( const wchar_t *a, const wchar_t *b )
  680. {
  681. if( *a == 0 )
  682. {
  683. return (*b==0)?0:-1;
  684. }
  685. else if( *b == 0 )
  686. {
  687. return 1;
  688. }
  689. int diff = towlower(*a)-towlower(*b);
  690. if( diff != 0 )
  691. return diff;
  692. else
  693. return wcscasecmp_fallback( a+1,b+1);
  694. }
  695. #if __APPLE__ && __DARWIN_C_LEVEL >= 200809L
  696. /* Note parens avoid the macro expansion */
  697. wchar_t *wcsdup_use_weak(const wchar_t *a)
  698. {
  699. if (wcsdup != NULL)
  700. return (wcsdup)(a);
  701. return wcsdup_fallback(a);
  702. }
  703. int wcscasecmp_use_weak(const wchar_t *a, const wchar_t *b)
  704. {
  705. if (wcscasecmp != NULL)
  706. return (wcscasecmp)(a, b);
  707. return wcscasecmp_fallback(a, b);
  708. }
  709. #else //__APPLE__
  710. #ifndef HAVE_WCSDUP
  711. wchar_t *wcsdup( const wchar_t *in )
  712. {
  713. return wcsdup_fallback(in);
  714. }
  715. #endif
  716. #ifndef HAVE_WCSCASECMP
  717. int wcscasecmp( const wchar_t *a, const wchar_t *b )
  718. {
  719. return wcscasecmp_fallback(a, b);
  720. }
  721. #endif
  722. #endif //__APPLE__
  723. #ifndef HAVE_WCSLEN
  724. size_t wcslen(const wchar_t *in)
  725. {
  726. const wchar_t *end=in;
  727. while( *end )
  728. end++;
  729. return end-in;
  730. }
  731. #endif
  732. #ifndef HAVE_WCSNCASECMP
  733. int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count )
  734. {
  735. if( count == 0 )
  736. return 0;
  737. if( *a == 0 )
  738. {
  739. return (*b==0)?0:-1;
  740. }
  741. else if( *b == 0 )
  742. {
  743. return 1;
  744. }
  745. int diff = towlower(*a)-towlower(*b);
  746. if( diff != 0 )
  747. return diff;
  748. else
  749. return wcsncasecmp( a+1,b+1, count-1);
  750. }
  751. #endif
  752. #ifndef HAVE_WCWIDTH
  753. int wcwidth( wchar_t c )
  754. {
  755. if( c < 32 )
  756. return 0;
  757. if ( c == 127 )
  758. return 0;
  759. return 1;
  760. }
  761. #endif
  762. #ifndef HAVE_WCSNDUP
  763. wchar_t *wcsndup( const wchar_t *in, int c )
  764. {
  765. wchar_t *res = (wchar_t *)malloc( sizeof(wchar_t)*(c+1) );
  766. if( res == 0 )
  767. {
  768. return 0;
  769. }
  770. wcslcpy( res, in, c+1 );
  771. return res;
  772. }
  773. #endif
  774. long convert_digit( wchar_t d, int base )
  775. {
  776. long res=-1;
  777. if( (d <= L'9') && (d >= L'0') )
  778. {
  779. res = d - L'0';
  780. }
  781. else if( (d <= L'z') && (d >= L'a') )
  782. {
  783. res = d + 10 - L'a';
  784. }
  785. else if( (d <= L'Z') && (d >= L'A') )
  786. {
  787. res = d + 10 - L'A';
  788. }
  789. if( res >= base )
  790. {
  791. res = -1;
  792. }
  793. return res;
  794. }
  795. #ifndef HAVE_WCSTOL
  796. long wcstol(const wchar_t *nptr,
  797. wchar_t **endptr,
  798. int base)
  799. {
  800. long long res=0;
  801. int is_set=0;
  802. if( base > 36 )
  803. {
  804. errno = EINVAL;
  805. return 0;
  806. }
  807. while( 1 )
  808. {
  809. long nxt = convert_digit( *nptr, base );
  810. if( endptr != 0 )
  811. *endptr = (wchar_t *)nptr;
  812. if( nxt < 0 )
  813. {
  814. if( !is_set )
  815. {
  816. errno = EINVAL;
  817. }
  818. return res;
  819. }
  820. res = (res*base)+nxt;
  821. is_set = 1;
  822. if( res > LONG_MAX )
  823. {
  824. errno = ERANGE;
  825. return LONG_MAX;
  826. }
  827. if( res < LONG_MIN )
  828. {
  829. errno = ERANGE;
  830. return LONG_MIN;
  831. }
  832. nptr++;
  833. }
  834. }
  835. #endif
  836. #ifndef HAVE_WCSLCAT
  837. /*$OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $*/
  838. /*
  839. * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  840. *
  841. * Permission to use, copy, modify, and distribute this software for any
  842. * purpose with or without fee is hereby granted, provided that the above
  843. * copyright notice and this permission notice appear in all copies.
  844. *
  845. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  846. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  847. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  848. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  849. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  850. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  851. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  852. */
  853. size_t
  854. wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
  855. {
  856. register wchar_t *d = dst;
  857. register const wchar_t *s = src;
  858. register size_t n = siz;
  859. size_t dlen;
  860. /* Find the end of dst and adjust bytes left but don't go past end */
  861. while (n-- != 0 && *d != '\0')
  862. d++;
  863. dlen = d - dst;
  864. n = siz - dlen;
  865. if (n == 0)
  866. return(dlen + wcslen(s));
  867. while (*s != '\0')
  868. {
  869. if (n != 1)
  870. {
  871. *d++ = *s;
  872. n--;
  873. }
  874. s++;
  875. }
  876. *d = '\0';
  877. return(dlen + (s - src));
  878. /* count does not include NUL */
  879. }
  880. #endif
  881. #ifndef HAVE_WCSLCPY
  882. /*$OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $*/
  883. /*
  884. * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  885. *
  886. * Permission to use, copy, modify, and distribute this software for any
  887. * purpose with or without fee is hereby granted, provided that the above
  888. * copyright notice and this permission notice appear in all copies.
  889. *
  890. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  891. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  892. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  893. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  894. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  895. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  896. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  897. */
  898. size_t
  899. wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
  900. {
  901. register wchar_t *d = dst;
  902. register const wchar_t *s = src;
  903. register size_t n = siz;
  904. /* Copy as many bytes as will fit */
  905. if (n != 0 && --n != 0)
  906. {
  907. do
  908. {
  909. if ((*d++ = *s++) == 0)
  910. break;
  911. }
  912. while (--n != 0);
  913. }
  914. /* Not enough room in dst, add NUL and traverse rest of src */
  915. if (n == 0)
  916. {
  917. if (siz != 0)
  918. *d = '\0';
  919. /* NUL-terminate dst */
  920. while (*s++)
  921. ;
  922. }
  923. return(s - src - 1);
  924. /* count does not include NUL */
  925. }
  926. #endif
  927. #ifndef HAVE_LRAND48_R
  928. int lrand48_r(struct drand48_data *buffer, long int *result)
  929. {
  930. *result = rand_r( &buffer->seed );
  931. return 0;
  932. }
  933. int srand48_r(long int seedval, struct drand48_data *buffer)
  934. {
  935. buffer->seed = (int)seedval;
  936. return 0;
  937. }
  938. #endif
  939. #ifndef HAVE_FUTIMES
  940. int futimes(int fd, const struct timeval *times)
  941. {
  942. errno = ENOSYS;
  943. return -1;
  944. }
  945. #endif
  946. #ifndef HAVE_GETTEXT
  947. char * gettext (const char * msgid)
  948. {
  949. return (char *)msgid;
  950. }
  951. char * bindtextdomain (const char * domainname, const char * dirname)
  952. {
  953. return 0;
  954. }
  955. char * textdomain (const char * domainname)
  956. {
  957. return 0;
  958. }
  959. #endif
  960. #ifndef HAVE_DCGETTEXT
  961. char * dcgettext ( const char * domainname,
  962. const char * msgid,
  963. int category)
  964. {
  965. return (char *)msgid;
  966. }
  967. #endif
  968. #ifndef HAVE__NL_MSG_CAT_CNTR
  969. int _nl_msg_cat_cntr=0;
  970. #endif
  971. #ifndef HAVE_KILLPG
  972. int killpg( int pgr, int sig )
  973. {
  974. assert( pgr > 1 );
  975. return kill( -pgr, sig );
  976. }
  977. #endif
  978. #ifndef HAVE_WORKING_GETOPT_LONG
  979. int getopt_long( int argc,
  980. char * const argv[],
  981. const char *optstring,
  982. const struct option *longopts,
  983. int *longindex )
  984. {
  985. return getopt( argc, argv, optstring );
  986. }
  987. #endif
  988. #ifndef HAVE_BACKTRACE
  989. int backtrace (void **buffer, int size)
  990. {
  991. return 0;
  992. }
  993. #endif
  994. #ifndef HAVE_BACKTRACE_SYMBOLS
  995. char ** backtrace_symbols (void *const *buffer, int size)
  996. {
  997. return 0;
  998. }
  999. #endif
  1000. #ifndef HAVE_SYSCONF
  1001. long sysconf(int name)
  1002. {
  1003. if( name == _SC_ARG_MAX )
  1004. {
  1005. #ifdef ARG_MAX
  1006. return ARG_MAX;
  1007. #endif
  1008. }
  1009. return -1;
  1010. }
  1011. #endif
  1012. #ifndef HAVE_NAN
  1013. double nan(char *tagp)
  1014. {
  1015. return 0.0/0.0;
  1016. }
  1017. #endif
  1018. /* Big hack to use our versions of wcswidth where we know them to be broken, like on OS X */
  1019. #ifndef HAVE_BROKEN_WCWIDTH
  1020. #if __APPLE__
  1021. #define HAVE_BROKEN_WCWIDTH 1
  1022. #else
  1023. #define HAVE_BROKEN_WCWIDTH 0
  1024. #endif
  1025. #endif
  1026. #if ! HAVE_BROKEN_WCWIDTH
  1027. int fish_wcwidth(wchar_t wc)
  1028. {
  1029. return wcwidth(wc);
  1030. }
  1031. int fish_wcswidth(const wchar_t *str, size_t n)
  1032. {
  1033. return wcswidth(str, n);
  1034. }
  1035. #else
  1036. static int mk_wcwidth(wchar_t wc);
  1037. static int mk_wcswidth(const wchar_t *pwcs, size_t n);
  1038. int fish_wcwidth(wchar_t wc)
  1039. {
  1040. return mk_wcwidth(wc);
  1041. }
  1042. int fish_wcswidth(const wchar_t *str, size_t n)
  1043. {
  1044. return mk_wcswidth(str, n);
  1045. }
  1046. /*
  1047. * This is an implementation of wcwidth() and wcswidth() (defined in
  1048. * IEEE Std 1002.1-2001) for Unicode.
  1049. *
  1050. * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
  1051. * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
  1052. *
  1053. * In fixed-width output devices, Latin characters all occupy a single
  1054. * "cell" position of equal width, whereas ideographic CJK characters
  1055. * occupy two such cells. Interoperability between terminal-line
  1056. * applications and (teletype-style) character terminals using the
  1057. * UTF-8 encoding requires agreement on which character should advance
  1058. * the cursor by how many cell positions. No established formal
  1059. * standards exist at present on which Unicode character shall occupy
  1060. * how many cell positions on character terminals. These routines are
  1061. * a first attempt of defining such behavior based on simple rules
  1062. * applied to data provided by the Unicode Consortium.
  1063. *
  1064. * For some graphical characters, the Unicode standard explicitly
  1065. * defines a character-cell width via the definition of the East Asian
  1066. * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
  1067. * In all these cases, there is no ambiguity about which width a
  1068. * terminal shall use. For characters in the East Asian Ambiguous (A)
  1069. * class, the width choice depends purely on a preference of backward
  1070. * compatibility with either historic CJK or Western practice.
  1071. * Choosing single-width for these characters is easy to justify as
  1072. * the appropriate long-term solution, as the CJK practice of
  1073. * displaying these characters as double-width comes from historic
  1074. * implementation simplicity (8-bit encoded characters were displayed
  1075. * single-width and 16-bit ones double-width, even for Greek,
  1076. * Cyrillic, etc.) and not any typographic considerations.
  1077. *
  1078. * Much less clear is the choice of width for the Not East Asian
  1079. * (Neutral) class. Existing practice does not dictate a width for any
  1080. * of these characters. It would nevertheless make sense
  1081. * typographically to allocate two character cells to characters such
  1082. * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
  1083. * represented adequately with a single-width glyph. The following
  1084. * routines at present merely assign a single-cell width to all
  1085. * neutral characters, in the interest of simplicity. This is not
  1086. * entirely satisfactory and should be reconsidered before
  1087. * establishing a formal standard in this area. At the moment, the
  1088. * decision which Not East Asian (Neutral) characters should be
  1089. * represented by double-width glyphs cannot yet be answered by
  1090. * applying a simple rule from the Unicode database content. Setting
  1091. * up a proper standard for the behavior of UTF-8 character terminals
  1092. * will require a careful analysis not only of each Unicode character,
  1093. * but also of each presentation form, something the author of these
  1094. * routines has avoided to do so far.
  1095. *
  1096. * http://www.unicode.org/unicode/reports/tr11/
  1097. *
  1098. * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
  1099. *
  1100. * Permission to use, copy, modify, and distribute this software
  1101. * for any purpose and without fee is hereby granted. The author
  1102. * disclaims all warranties with regard to this software.
  1103. *
  1104. * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
  1105. */
  1106. #include <wchar.h>
  1107. struct interval {
  1108. int first;
  1109. int last;
  1110. };
  1111. /* auxiliary function for binary search in interval table */
  1112. static int bisearch(wchar_t ucs, const struct interval *table, int max) {
  1113. int min = 0;
  1114. int mid;
  1115. if (ucs < table[0].first || ucs > table[max].last)
  1116. return 0;
  1117. while (max >= min) {
  1118. mid = (min + max) / 2;
  1119. if (ucs > table[mid].last)
  1120. min = mid + 1;
  1121. else if (ucs < table[mid].first)
  1122. max = mid - 1;
  1123. else
  1124. return 1;
  1125. }
  1126. return 0;
  1127. }
  1128. /* The following two functions define the column width of an ISO 10646
  1129. * character as follows:
  1130. *
  1131. * - The null character (U+0000) has a column width of 0.
  1132. *
  1133. * - Other C0/C1 control characters and DEL will lead to a return
  1134. * value of -1.
  1135. *
  1136. * - Non-spacing and enclosing combining characters (general
  1137. * category code Mn or Me in the Unicode database) have a
  1138. * column width of 0.
  1139. *
  1140. * - SOFT HYPHEN (U+00AD) has a column width of 1.
  1141. *
  1142. * - Other format characters (general category code Cf in the Unicode
  1143. * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
  1144. *
  1145. * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
  1146. * have a column width of 0.
  1147. *
  1148. * - Spacing characters in the East Asian Wide (W) or East Asian
  1149. * Full-width (F) category as defined in Unicode Technical
  1150. * Report #11 have a column width of 2.
  1151. *
  1152. * - All remaining characters (including all printable
  1153. * ISO 8859-1 and WGL4 characters, Unicode control characters,
  1154. * etc.) have a column width of 1.
  1155. *
  1156. * This implementation assumes that wchar_t characters are encoded
  1157. * in ISO 10646.
  1158. */
  1159. static int mk_wcwidth(wchar_t ucs)
  1160. {
  1161. /* sorted list of non-overlapping intervals of non-spacing characters */
  1162. /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
  1163. static const struct interval combining[] = {
  1164. { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
  1165. { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
  1166. { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
  1167. { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
  1168. { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
  1169. { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
  1170. { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
  1171. { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
  1172. { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
  1173. { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
  1174. { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
  1175. { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
  1176. { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
  1177. { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
  1178. { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
  1179. { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
  1180. { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
  1181. { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
  1182. { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
  1183. { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
  1184. { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
  1185. { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
  1186. { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
  1187. { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
  1188. { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
  1189. { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
  1190. { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
  1191. { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
  1192. { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
  1193. { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
  1194. { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
  1195. { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
  1196. { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
  1197. { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
  1198. { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
  1199. { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
  1200. { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
  1201. { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
  1202. { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
  1203. { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
  1204. { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
  1205. { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
  1206. { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
  1207. { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
  1208. { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
  1209. { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
  1210. { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
  1211. { 0xE0100, 0xE01EF }
  1212. };
  1213. /* test for 8-bit control characters */
  1214. if (ucs == 0)
  1215. return 0;
  1216. if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
  1217. return -1;
  1218. /* binary search in table of non-spacing characters */
  1219. if (bisearch(ucs, combining,
  1220. sizeof(combining) / sizeof(struct interval) - 1))
  1221. return 0;
  1222. /* if we arrive here, ucs is not a combining or C0/C1 control character */
  1223. return 1 +
  1224. (ucs >= 0x1100 &&
  1225. (ucs <= 0x115f || /* Hangul Jamo init. consonants */
  1226. ucs == 0x2329 || ucs == 0x232a ||
  1227. (ucs >= 0x2e80 && ucs <= 0xa4cf &&
  1228. ucs != 0x303f) || /* CJK ... Yi */
  1229. (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
  1230. (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
  1231. (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
  1232. (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
  1233. (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
  1234. (ucs >= 0xffe0 && ucs <= 0xffe6) ||
  1235. (ucs >= 0x20000 && ucs <= 0x2fffd) ||
  1236. (ucs >= 0x30000 && ucs <= 0x3fffd)));
  1237. }
  1238. static int mk_wcswidth(const wchar_t *pwcs, size_t n)
  1239. {
  1240. int w, width = 0;
  1241. for (;*pwcs && n-- > 0; pwcs++)
  1242. if ((w = mk_wcwidth(*pwcs)) < 0)
  1243. return -1;
  1244. else
  1245. width += w;
  1246. return width;
  1247. }
  1248. #endif // HAVE_BROKEN_WCWIDTH