bLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:21k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* bLib.c - buffer manipulation library */
  2. /* Copyright 1984-1998 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02z,11nov01,dee  Add CPU_FAMILY==COLDFIRE
  8. 02y,01dec98,cdp  make ARM CPUs with ARM_THUMB==TRUE use portable routines;
  9.     jpd  improve swab for ARM.
  10. 02y,03mar00,zl   merged SH support from T1
  11. 02x,22apr97,jpd  added support for ARM optimised routines.
  12. 02w,19mar95,dvs  removing tron references.
  13. 02v,06mar95,jdi  doc addition to swab() and uswab().
  14. 02u,11feb95,jdi  doc tweak.
  15. 02u,21mar95,caf  added PPC support.
  16. 02t,20jul94,dvs  fixed documentation for return values of bcmp (SPR #2493).
  17. 02s,09jun93,hdn  added a support for I80X86
  18. 02r,17oct94,rhp  delete obsolete doc references to strLib, spr#3712
  19. 02q,20jan93,jdi  documentation cleanup for 5.1.
  20. 02p,14sep92,smb  changed prototype of bcopy to include const.
  21. 02o,23aug92,jcf  fixed uswab to swap all of buffer.  removed memcmp call.
  22. 02n,30jul92,jwt  fixed error in bcopy() backwards overrunning dest address.
  23. 02m,08jul92,smb  removed string library ANSI routines.  added index and rindex.
  24. 02l,08jun92,ajm  added mips to list of optimized cpu's
  25. 02k,26may92,rrr  the tree shuffle
  26. 02j,09dec91,rrr  removed memcpy for 960, already in i960/bALib.s
  27. 02i,26nov91,llk  fixed error with placement of bLib_PORTABLE.
  28. 02h,25nov91,llk  changed bfillBytes() parameter from unsigned char to int.
  29.  added ansi routines:  memcpy(), memmove(), memcmp(),
  30.    strcoll(), strxfrm(), strchr(), strcspn(), strpbrk(),
  31.    strrchr(), strspn(), strstr(), strtok(), memset()
  32. 02g,04oct91,rrr  passed through the ansification filter
  33.                   -changed functions to ansi style
  34.   -fixed #else and #endif
  35.   -changed VOID to void
  36.   -changed copyright notice
  37. 02f,30jul91,hdn  added conditional macro for optimized TRON codes.
  38. 02e,29jul91,del  fixed comment.
  39. 02d,16jul91,ajm/del  added uswab for unaligned byte swaps (see dosFsLib.c)
  40. 02c,09jun91,del  mods to allow using gnu960 library functions.
  41. 02b,26apr91,hdn  added defines and macros for TRON architecture,
  42.  modified bcopy(), bcopyBytes(), bfill().
  43. 02a,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  44.  doc review by dnw.
  45. 01z,24mar91,del  added I960 to check for portable version.
  46. 01y,24jan91,jaa  documentation.
  47. 01x,20dec90,gae  added forward declaration of bfill, ALIGNMENT set to 1 for 020.
  48.            +shl  fixed bug in bfill of (occasionally) filling too far.
  49. 01w,20sep90,dab  changed ALIGNMENT value to be 3 across architectures.
  50. 01v,19jul90,dnw  fixed mangen problem
  51. 01u,10may90,jcf  fixed PORTABLE definition.
  52. 01t,14mar90,jdi  documentation cleanup.
  53. 01s,07aug89,gae  added C versions of bcopy,bfill,etc.
  54. 01r,30aug88,gae  more documentation tweaks.
  55. 01q,20aug88,gae  documentation.
  56. 01p,05jun88,dnw  changed from bufLib to bLib.
  57. 01o,30may88,dnw  changed to v4 names.
  58. 01n,19mar87,gae  oops in 01m!
  59. 01m,19mar87,gae  fixed swab to work right when from/to are the same.
  60.  made swab type void.
  61. 01l,16feb87,llk  added swab().
  62. 01k,21dec86,dnw  changed to not get include files from default directories.
  63. 01j,01jul86,jlf  minor documentation cleanup.
  64. 01i,06aug85,jlf  removed cpybuf,movbuf, and filbuf, which are now in
  65.  asm language.  Made the remaining routines accept ints instead
  66.  of shorts, and removed the screwy loop constructs.
  67. 01h,06sep84,jlf  Added copyright notice.
  68. 01g,29jun84,ecs  changed cmpbuf to return -1, 0, 1.
  69. 01f,18jun84,dnw  Added LINTLIBRARY for lint.
  70. 01e,17nov83,jlf  Added movbuf
  71. 01d,09jun83,ecs  added some commentary
  72. 01c,07may83,dnw  enabled filbuf to fill more than 64K bytes
  73. 01b,04apr83,dnw  added invbuf.
  74. 01a,15mar83,dnw  created from old utillb.c
  75. */
  76. /*
  77. DESCRIPTION
  78. This library contains routines to manipulate buffers of variable-length
  79. byte arrays.  Operations are performed on long words when possible, even
  80. though the buffer lengths are specified in bytes.  This occurs only when
  81. source and destination buffers start on addresses that are both odd or both
  82. even.  If one buffer is even and the other is odd, operations must be done
  83. one byte at a time (because of alignment problems inherent in the MC68000),
  84. thereby slowing down the process.
  85. Certain applications, such as byte-wide memory-mapped peripherals, may
  86. require that only byte operations be performed.  For this purpose, the
  87. routines bcopyBytes() and bfillBytes() provide the same functions as bcopy()
  88. and bfill(), but use only byte-at-a-time operations.  These routines do
  89. not check for null termination.
  90. INCLUDE FILES: string.h
  91. SEE ALSO: ansiString
  92. */
  93. /* LINTLIBRARY */
  94. #include "vxWorks.h"
  95. #include "string.h"
  96. /*
  97.  * optimized version available for 680X0, I960, MIPS, I80X86, PPC, SH and ARM,
  98.  * but not yet Thumb.
  99.  */
  100. #if (defined(PORTABLE) || 
  101.      ((CPU_FAMILY != MC680X0) && 
  102.       (CPU_FAMILY!=I960) && 
  103.       (CPU_FAMILY != MIPS) && 
  104.       (CPU_FAMILY != I80X86) && 
  105.       (CPU_FAMILY != PPC) && 
  106.       (CPU_FAMILY != SH) && 
  107.       (CPU_FAMILY != COLDFIRE) && 
  108.       (CPU_FAMILY != ARM)) || 
  109.      ((CPU_FAMILY == ARM) && ARM_THUMB))
  110. #define bLib_PORTABLE
  111. #endif /* defined(PORTABLE) */
  112. /* optimized swab() available for PPC */
  113. #if (defined(PORTABLE) || (CPU_FAMILY != PPC))
  114. #define swab_PORTABLE
  115. #endif /* defined(PORTABLE) */
  116. #if (CPU==MC68020) || (CPU_FAMILY==I80X86) || (CPU_FAMILY == COLDFIRE)
  117. #define ALIGNMENT 1 /* 2-byte */
  118. #else
  119. #define ALIGNMENT 3 /* quad */
  120. #endif /* (CPU==MC68020) || (CPU_FAMILY==I80X86) */
  121. #undef bcmp /* so routine gets built for those who don't include header files */
  122. /*******************************************************************************
  123. *
  124. * bcmp - compare one buffer to another
  125. *
  126. * This routine compares the first <nbytes> characters of <buf1> to <buf2>.
  127. *
  128. * RETURNS:
  129. *   0 if the first <nbytes> of <buf1> and <buf2> are identical,
  130. *   less than 0 if <buf1> is less than <buf2>, or
  131. *   greater than 0 if <buf1> is greater than <buf2>.
  132. */
  133. int bcmp
  134.     (
  135.     FAST char *buf1,            /* pointer to first buffer    */
  136.     FAST char *buf2,            /* pointer to second buffer   */
  137.     FAST int nbytes             /* number of bytes to compare */
  138.     )
  139.     {
  140.     const unsigned char *p1;
  141.     const unsigned char *p2;
  142.     /* size of memory is zero */
  143.     if (nbytes == 0)
  144. return (0);
  145.     /* compare array 2 into array 1 */
  146.     p1 = (const unsigned char *)buf1;
  147.     p2 = (const unsigned char *)buf2;
  148.     while (*p1++ == *p2++)
  149. {
  150. if (--nbytes == 0)
  151.     return (0);
  152.         }
  153.     return ((*--p1) - (*--p2));
  154.     }
  155. /*******************************************************************************
  156. *
  157. * binvert - invert the order of bytes in a buffer
  158. *
  159. * This routine inverts an entire buffer, byte by byte.  For example,
  160. * the buffer {1, 2, 3, 4, 5} would become {5, 4, 3, 2, 1}.
  161. *
  162. * RETURNS: N/A
  163. */
  164. void binvert
  165.     (
  166.     FAST char *buf,             /* pointer to buffer to invert  */
  167.     int nbytes                  /* number of bytes in buffer    */
  168.     )
  169.     {
  170.     FAST char *buf_end = buf + nbytes - 1;
  171.     FAST char temp;
  172.     while (buf < buf_end)
  173. {
  174. temp       = *buf;
  175. *buf       = *buf_end;
  176. *buf_end   = temp;
  177. buf_end--;
  178. buf++;
  179. }
  180.     }
  181. /*******************************************************************************
  182. *
  183. * bswap - swap buffers
  184. *
  185. * This routine exchanges the first <nbytes> of the two specified buffers.
  186. *
  187. * RETURNS: N/A
  188. */
  189. void bswap
  190.     (
  191.     FAST char *buf1,            /* pointer to first buffer  */
  192.     FAST char *buf2,            /* pointer to second buffer */
  193.     FAST int nbytes             /* number of bytes to swap  */
  194.     )
  195.     {
  196.     FAST char temp;
  197.     while (--nbytes >= 0)
  198. {
  199. temp = *buf1;
  200. *buf1++ = *buf2;
  201. *buf2++ = temp;
  202. }
  203.     }
  204. #ifdef swab_PORTABLE
  205. /*******************************************************************************
  206. *
  207. * swab - swap bytes
  208. *
  209. * This routine gets the specified number of bytes from <source>,
  210. * exchanges the adjacent even and odd bytes, and puts them in <destination>.
  211. * The buffers <source> and <destination> should not overlap.
  212. *
  213. * &NOTE:  On some CPUs, swab() will cause an exception if the buffers are
  214. * unaligned.  In such cases, use uswab() for unaligned swaps.  On ARM
  215. * family CPUs, swab() may reorder the bytes incorrectly without causing
  216. * an exception if the buffers are unaligned.  Again, use uswab() for
  217. * unaligned swaps.
  218. *
  219. * It is an error for <nbytes> to be odd.
  220. *
  221. * RETURNS: N/A
  222. *
  223. * SEE ALSO: uswab()
  224. */
  225. void swab
  226.     (
  227.     char *source,               /* pointer to source buffer      */
  228.     char *destination,          /* pointer to destination buffer */
  229.     int nbytes                  /* number of bytes to exchange   */
  230.     )
  231. #if (CPU_FAMILY == ARM)
  232.     {
  233.     /*
  234.      * This generates much better code for the ARM, and might well be
  235.      * faster on gcc-based compilers for other architectures.
  236.      */
  237.     FAST unsigned short *src = (unsigned short *) source;
  238.     FAST unsigned short *dst = (unsigned short *) destination;
  239.     FAST unsigned short *dst_end = (unsigned short *) (destination + nbytes);
  240.     for (; dst < dst_end; dst++, src++)
  241. {
  242. *dst = ((*src & 0x00ff) << 8) | ((*src & 0xff00) >> 8);
  243. }
  244.     }
  245. #else /* (CPU_FAMILY == ARM) */
  246.     {
  247.     FAST short *src = (short *) source;
  248.     FAST short *dst = (short *) destination;
  249.     FAST short *dst_end = dst + (nbytes / 2);
  250.     for (; dst < dst_end; dst++, src++)
  251. {
  252. *dst = ((*src & 0x00ff) << 8) | ((*src & 0xff00) >> 8);
  253. }
  254.     }
  255. #endif /* (CPU_FAMILY == ARM) */
  256. #endif /* swab_PORTABLE */
  257. #if (CPU_FAMILY != I960) || !defined(__GNUC__) || defined(VX_IGNORE_GNU_LIBS)
  258. /*******************************************************************************
  259. *
  260. * uswab - swap bytes with buffers that are not necessarily aligned
  261. *
  262. * This routine gets the specified number of bytes from <source>,
  263. * exchanges the adjacent even and odd bytes, and puts them in <destination>.
  264. *
  265. * &NOTE:  Due to speed considerations, this routine should only be used when
  266. * absolutely necessary.  Use swab() for aligned swaps.
  267. *
  268. * It is an error for <nbytes> to be odd.
  269. *
  270. * RETURNS: N/A
  271. *
  272. * SEE ALSO: swab()
  273. */
  274. void uswab
  275.     (
  276.     char *source,               /* pointer to source buffer      */
  277.     char *destination,          /* pointer to destination buffer */
  278.     int nbytes                  /* number of bytes to exchange   */
  279.     )
  280.     {
  281.     FAST char *dst = (char *) destination;
  282.     FAST char *dst_end = dst + nbytes;
  283.     FAST char byte1;
  284.     FAST char byte2;
  285.     while (dst < dst_end)
  286. {
  287. byte1 = *source++;
  288. byte2 = *source++;
  289. *dst++ = byte2;
  290. *dst++ = byte1;
  291. }
  292.     }
  293. /*******************************************************************************
  294. *
  295. * bzero - zero out a buffer
  296. *
  297. * This routine fills the first <nbytes> characters of the
  298. * specified buffer with 0.
  299. *
  300. * RETURNS: N/A
  301. */
  302. void bzero
  303.     (
  304.     char *buffer,               /* buffer to be zeroed       */
  305.     int nbytes                  /* number of bytes in buffer */
  306.     )
  307.     {
  308.     bfill (buffer, nbytes, 0);
  309.     }
  310. #endif /* IGNORE GNU LIBS */
  311. #ifdef bLib_PORTABLE
  312. #if (CPU_FAMILY != I960) || !defined(__GNUC__) || defined(VX_IGNORE_GNU_LIBS)
  313. /*******************************************************************************
  314. *
  315. * bcopy - copy one buffer to another
  316. *
  317. * This routine copies the first <nbytes> characters from <source> to
  318. * <destination>.  Overlapping buffers are handled correctly.  Copying is done
  319. * in the most efficient way possible, which may include long-word, or even
  320. * multiple-long-word moves on some architectures.  In general, the copy
  321. * will be significantly faster if both buffers are long-word aligned.
  322. * (For copying that is restricted to byte, word, or long-word moves, see
  323. * the manual entries for bcopyBytes(), bcopyWords(), and bcopyLongs().)
  324. *
  325. * RETURNS: N/A
  326. *
  327. * SEE ALSO: bcopyBytes(), bcopyWords(), bcopyLongs()
  328. */
  329. void bcopy
  330.     (
  331.     const char *source,        /* pointer to source buffer      */
  332.     char *destination,   /* pointer to destination buffer */
  333.     int nbytes           /* number of bytes to copy       */
  334.     )
  335.     {
  336.     FAST char *dstend;
  337.     FAST long *src;
  338.     FAST long *dst;
  339.     int tmp = destination - source;
  340.     if (tmp <= 0 || tmp >= nbytes)
  341. {
  342. /* forward copy */
  343. dstend = destination + nbytes;
  344. /* do byte copy if less than ten or alignment mismatch */
  345. if (nbytes < 10 || (((int)destination ^ (int)source) & ALIGNMENT))
  346.     goto byte_copy_fwd;
  347. /* if odd-aligned copy byte */
  348. while ((int)destination & ALIGNMENT)
  349.     *destination++ = *source++;
  350. src = (long *) source;
  351. dst = (long *) destination;
  352. do
  353.     {
  354.     *dst++ = *src++;
  355.     }
  356. while (((char *)dst + sizeof (long)) <= dstend);
  357. destination = (char *)dst;
  358. source      = (char *)src;
  359. byte_copy_fwd:
  360. while (destination < dstend)
  361.     *destination++ = *source++;
  362. }
  363.     else
  364. {
  365. /* backward copy */
  366. dstend       = destination;
  367. destination += nbytes - sizeof (char);
  368. source      += nbytes - sizeof (char);
  369. /* do byte copy if less than ten or alignment mismatch */
  370. if (nbytes < 10 || (((int)destination ^ (int)source) & ALIGNMENT))
  371.     goto byte_copy_bwd;
  372. /* if odd-aligned copy byte */
  373. while ((int)destination & ALIGNMENT)
  374.     *destination-- = *source--;
  375. src = (long *) source;
  376. dst = (long *) destination;
  377. do
  378.     {
  379.     *dst-- = *src--;
  380.     }
  381. while (((char *)dst + sizeof(long)) >= dstend);
  382. destination = (char *)dst + sizeof (long);
  383. source      = (char *)src + sizeof (long);
  384. byte_copy_bwd:
  385. while (destination >= dstend)
  386.     *destination-- = *source--;
  387. }
  388.     }
  389. #endif /* IGNORE GNU LIBS */
  390. /*******************************************************************************
  391. *
  392. * bcopyBytes - copy one buffer to another one byte at a time
  393. *
  394. * This routine copies the first <nbytes> characters from <source> to
  395. * <destination> one byte at a time.  This may be desirable if a buffer can
  396. * only be accessed with byte instructions, as in certain byte-wide
  397. * memory-mapped peripherals.
  398. *
  399. * RETURNS: N/A
  400. *
  401. * SEE ALSO: bcopy()
  402. */
  403. void bcopyBytes
  404.     (
  405.     char *source,       /* pointer to source buffer      */
  406.     char *destination,  /* pointer to destination buffer */
  407.     int nbytes          /* number of bytes to copy       */
  408.     )
  409.     {
  410.     FAST char *dstend;
  411.     int tmp = destination - source;   /* XXX does it work if MSB was 1 ? */
  412.     if (tmp == 0)
  413.         return;
  414.     else if (tmp < 0 || tmp >= nbytes)
  415.      {
  416. /* forward copy */
  417. dstend = destination + nbytes;
  418. while (destination < dstend)
  419.     *destination++ = *source++;
  420. }
  421.     else
  422. {
  423. /* backward copy */
  424. dstend       = destination;
  425. destination += nbytes - 1;
  426. source      += nbytes - 1;
  427. while (destination >= dstend)
  428.     *destination-- = *source--;
  429. }
  430.     }
  431. /*******************************************************************************
  432. *
  433. * bcopyWords - copy one buffer to another one word at a time
  434. *
  435. * This routine copies the first <nwords> words from <source> to <destination>
  436. * one word at a time.  This may be desirable if a buffer can only be accessed
  437. * with word instructions, as in certain word-wide memory-mapped peripherals.
  438. * The source and destination must be word-aligned.
  439. *
  440. * RETURNS: N/A
  441. *
  442. * SEE ALSO: bcopy()
  443. */
  444. void bcopyWords
  445.     (
  446.     char *source,       /* pointer to source buffer      */
  447.     char *destination,  /* pointer to destination buffer */
  448.     int nwords          /* number of words to copy       */
  449.     )
  450.     {
  451.     FAST short *dstend;
  452.     FAST short *src = (short *) source;
  453.     FAST short *dst = (short *) destination;
  454.     int tmp = destination - source;   /* XXX does it work if MSB was 1 ? */
  455.     int nbytes = nwords << 1;           /* convert to bytes */
  456.     if (tmp == 0)
  457.     return;
  458.     else if (tmp < 0 || tmp >= nbytes)
  459. {
  460. /* forward copy */
  461. dstend = dst + nwords;
  462. while (dst < dstend)
  463.     *dst++ = *src++;
  464. }
  465.     else
  466. {
  467. /* backward copy */
  468. dstend = dst;
  469.         dst   += nwords - 1;
  470. src   += nwords - 1;
  471. while (dst >= dstend)
  472.     *dst-- = *src--;
  473. }
  474.     }
  475. /*******************************************************************************
  476. *
  477. * bcopyLongs - copy one buffer to another one long word at a time
  478. *
  479. * This routine copies the first <nlongs> characters from <source> to
  480. * <destination> one long word at a time.  This may be desirable if a buffer
  481. * can only be accessed with long instructions, as in certain long-word-wide
  482. * memory-mapped peripherals.  The source and destination must be
  483. * long-aligned.
  484. *
  485. * RETURNS: N/A
  486. *
  487. * SEE ALSO: bcopy()
  488. */
  489. void bcopyLongs
  490.     (
  491.     char *source,       /* pointer to source buffer      */
  492.     char *destination,  /* pointer to destination buffer */
  493.     int nlongs          /* number of longs to copy       */
  494.     )
  495.     {
  496.     FAST long *dstend;
  497.     FAST long *src = (long *) source;
  498.     FAST long *dst = (long *) destination;
  499.     int tmp = destination - source;     /* XXX does it work if MSB was 1 ? */
  500.     int nbytes = nlongs << 2;           /* convert to bytes */
  501.     if (tmp == 0)
  502.         return;
  503.     else if (tmp < 0 || tmp >= nbytes)
  504. {
  505. /* forward copy */
  506. dstend = dst + nlongs;
  507. while (dst < dstend)
  508.     *dst++ = *src++;
  509. }
  510.     else
  511. {
  512. /* backward copy */
  513.         dstend = dst;
  514. dst   += nlongs - 1;
  515. src   += nlongs - 1;
  516. while (dst >= dstend)
  517.     *dst-- = *src--;
  518. }
  519.     }
  520. #undef bfill /* so bfill gets built for those who don't include header files */
  521. /*******************************************************************************
  522. *
  523. * bfill - fill a buffer with a specified character
  524. *
  525. * This routine fills the first <nbytes> characters of a buffer with the
  526. * character <ch>.  Filling is done in the most efficient way possible,
  527. * which may be long-word, or even multiple-long-word stores, on some
  528. * architectures.  In general, the fill will be significantly faster if
  529. * the buffer is long-word aligned.  (For filling that is restricted to
  530. * byte stores, see the manual entry for bfillBytes().)
  531. *
  532. * RETURNS: N/A
  533. *
  534. * SEE ALSO: bfillBytes()
  535. */
  536. void bfill
  537.     (
  538.     FAST char *buf,           /* pointer to buffer              */
  539.     int nbytes,               /* number of bytes to fill        */
  540.     FAST int ch            /* char with which to fill buffer */
  541.     )
  542.     {
  543. #if (CPU_FAMILY != I960) || !defined(__GNUC__) || defined(VX_IGNORE_GNU_LIBS)
  544.     FAST long *pBuf;
  545.     char *bufend = buf + nbytes;
  546.     FAST char *buftmp;
  547.     FAST long val;
  548.     if (nbytes < 10)
  549. goto byte_fill;
  550.     val = (ch << 24) | (ch << 16) | (ch << 8) | ch;
  551.     /* start on necessary alignment */
  552.     while ((int)buf & ALIGNMENT)
  553. *buf++ = ch;
  554.     buftmp = bufend - sizeof (long); /* last word boundary before bufend */
  555.     pBuf = (long *)buf;
  556.     /* fill 4 bytes at a time; don't exceed buf endpoint */
  557.     do
  558. {
  559. *pBuf++ = val;
  560. }
  561.     while ((char *)pBuf < buftmp);
  562.     buf = (char *)pBuf - sizeof (long);
  563.     /* fill remaining bytes one at a time */
  564. byte_fill:
  565.     while (buf < bufend)
  566. *buf++ = ch;
  567. #else /* IGNORE GNU LIBS */
  568.     (void) memset ((void *)buf, (int) ch, (size_t) nbytes);
  569. #endif /* IGNORE GNU LIBS */
  570.     }
  571. /*******************************************************************************
  572. *
  573. * bfillBytes - fill buffer with a specified character one byte at a time
  574. *
  575. * This routine fills the first <nbytes> characters of the specified buffer
  576. * with the character <ch> one byte at a time.  This may be desirable if a
  577. * buffer can only be accessed with byte instructions, as in certain
  578. * byte-wide memory-mapped peripherals.
  579. *
  580. * RETURNS: N/A
  581. *
  582. * SEE ALSO: bfill()
  583. */
  584. void bfillBytes
  585.     (
  586.     FAST char *buf,        /* pointer to buffer              */
  587.     int nbytes,            /* number of bytes to fill        */
  588.     FAST int ch    /* char with which to fill buffer */
  589.     )
  590.     {
  591.     FAST char *bufend = buf + nbytes;
  592.     while (buf < bufend)
  593. *buf++ = ch;
  594.     }
  595. #endif /* bLib_PORTABLE */
  596. #undef index /* so index gets built for those who don't include header files */
  597. /*******************************************************************************
  598. *
  599. * index - find the first occurrence of a character in a string
  600. *
  601. * This routine finds the first occurrence of character <c>
  602. * in string <s>.
  603. *
  604. * RETURNS:
  605. * A pointer to the located character, or
  606. * NULL if <c> is not found.
  607. *
  608. * SEE ALSO: strchr().
  609. */
  610. char *index
  611.     (
  612.     FAST const char *s,      /* string in which to find character */
  613.     FAST int c               /* character to find in string       */
  614.     )
  615.     {
  616.     FAST char ch;
  617.     while (((ch = *(s++)) != c) && (ch != EOS))
  618. ;
  619.     return (((ch == EOS) && c != EOS) ? NULL : (char *) --s);
  620.     }
  621. #undef rindex /* so rindex is built for those who don't include header files */
  622. /*******************************************************************************
  623. *
  624. * rindex - find the last occurrence of a character in a string
  625. *
  626. * This routine finds the last occurrence of character <c>
  627. * in string <s>.
  628. *
  629. * RETURNS:
  630. * A pointer to <c>, or
  631. * NULL if <c> is not found.
  632. */
  633. char *rindex
  634.     (
  635.     FAST const char *s,        /* string in which to find character */
  636.     int c               /* character to find in string       */
  637.     )
  638.     {
  639.     int i; /* must be signed! */
  640.     i = (int) strlen (s); /* point to null terminator of s */
  641.     while (i >= 0)
  642. {
  643. if (s [i] == c)
  644.     return ((char *) &s [i]);
  645. i--;
  646. }
  647.     return ((char *) NULL);
  648.     }