home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / reviewed / volume02 / malloclb / part05 < prev    next >
Encoding:
Internet Message Format  |  1992-03-31  |  44.3 KB

  1. From: Conor P. Cahill <cpcahil%virtech@uunet.UU.NET>
  2. Subject: v02i006: malloclib - Malloc Debugging Library, Part05/05
  3. Newsgroups: comp.sources.reviewed
  4. Approved: csr@calvin.dgbt.doc.ca
  5.  
  6. Submitted-by: Conor P. Cahill <cpcahil%virtech@uunet.UU.NET>
  7. Posting-number: Volume 2, Issue 6
  8. Archive-name: malloclib/part05
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 5 (of 5)."
  17. # Contents:  string.c testmalloc.c testmem.c
  18. # Wrapped by cpcahil@virtech on Tue Jan 28 16:46:34 1992
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'string.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'string.c'\"
  22. else
  23. echo shar: Extracting \"'string.c'\" \(16008 characters\)
  24. sed "s/^X//" >'string.c' <<'END_OF_FILE'
  25. X/*
  26. X * (c) Copyright 1990, 1991 Conor P. Cahill (uunet!virtech!cpcahil).  
  27. X * You may copy, distribute, and use this software as long as this
  28. X * copyright statement is not removed.
  29. X */
  30. X
  31. X/*
  32. X * NOTE: if you have problems compiling this file, the first thing to try is
  33. X * to take out the include of string.h.  This is due to the fact that some
  34. X * systems (like ultrix) have conflicting definitions and some (like aix)
  35. X * even set up some of these functions to be in-lined.
  36. X */
  37. X
  38. X#include <stdio.h>
  39. X#if ! defined(_IBMR2) && ! defined(ultrix)
  40. X#include <string.h>
  41. X#endif
  42. X#include <sys/types.h>
  43. X
  44. X#include "mallocint.h"
  45. X
  46. X#ifndef lint
  47. Xstatic
  48. Xchar rcs_hdr[] = "$Id: string.c,v 1.14 1991/12/04 09:23:44 cpcahil Exp $";
  49. X#endif
  50. X
  51. Xstatic int    in_string_code = 0;
  52. X
  53. X/*
  54. X * strcat - concatenate a string onto the end of another string
  55. X */
  56. Xchar *
  57. Xstrcat(str1,str2)
  58. X    char        * str1;
  59. X    const char    * str2;
  60. X{
  61. X    return( DBstrcat((char *)NULL,0,str1,str2) );
  62. X}
  63. X
  64. Xchar *
  65. XDBstrcat(file,line,str1,str2)
  66. X    const char        * file;
  67. X    int              line;
  68. X    register char        * str1;
  69. X    register const char    * str2;
  70. X{
  71. X    char            * rtn;
  72. X    int              len;
  73. X
  74. X    /* 
  75. X     * check pointers agains malloc region.  The malloc* functions
  76. X     * will properly handle the case where a pointer does not
  77. X     * point into malloc space.
  78. X     */
  79. X    in_string_code = 1;
  80. X
  81. X    len = strlen(str2);
  82. X    malloc_check_str("strcat", file, line, str2);
  83. X
  84. X    len += strlen(str1) + 1;
  85. X    in_string_code = 0;
  86. X
  87. X    malloc_check_data("strcat", file, line, str1, len);
  88. X
  89. X    rtn = str1;
  90. X
  91. X    while( *str1 )
  92. X    {
  93. X        str1++;
  94. X    }
  95. X    
  96. X    while( (*str1 = *str2) != '\0' )
  97. X    {
  98. X        str1++;
  99. X        str2++;
  100. X    }
  101. X    
  102. X    return(rtn);
  103. X}
  104. X
  105. X/*
  106. X * strdup - duplicate a string
  107. X */
  108. Xchar *
  109. Xstrdup(str1)
  110. X    const char    * str1;
  111. X{
  112. X    return( DBstrdup((char *)NULL, 0, str1) );
  113. X}
  114. X
  115. Xchar *
  116. XDBstrdup(file, line, str1)
  117. X    const char        * file;
  118. X    int              line;
  119. X    register const char    * str1;
  120. X{
  121. X    char            * rtn;
  122. X    register char        * str2;
  123. X
  124. X    malloc_check_str("strdup", file, line, str1);
  125. X
  126. X    in_string_code = 1;
  127. X    rtn = str2 = malloc((SIZETYPE)strlen(str1)+1);
  128. X    in_string_code = 0;
  129. X
  130. X    if( rtn != (char *) 0)
  131. X    {
  132. X        while( (*str2 = *str1) != '\0' )
  133. X        {
  134. X            str1++;
  135. X            str2++;
  136. X        }
  137. X    }
  138. X
  139. X    return(rtn);
  140. X}
  141. X
  142. X/*
  143. X * strncat - concatenate a string onto the end of another up to a specified len
  144. X */
  145. Xchar *
  146. Xstrncat(str1,str2,len)
  147. X    char        * str1;
  148. X    const char    * str2;
  149. X    SIZETYPE      len;
  150. X{
  151. X    return( DBstrncat((char *)NULL, 0, str1, str2, len) );
  152. X}
  153. X
  154. Xchar *
  155. XDBstrncat(file, line, str1, str2, len)
  156. X    const char        * file;
  157. X    int              line;
  158. X    register char        * str1;
  159. X    register const char    * str2;
  160. X    register SIZETYPE      len;
  161. X{
  162. X    int           len1;
  163. X    int           len2;
  164. X    char        * rtn;
  165. X
  166. X    malloc_check_strn("strncat", file, line, str2, len);
  167. X
  168. X    in_string_code = 1;
  169. X
  170. X    len2 = strlen(str2) + 1;
  171. X    len1 = strlen(str1);
  172. X
  173. X    in_string_code = 0;
  174. X
  175. X
  176. X    if( (len+1) < len2 )
  177. X    {
  178. X        len1 += len + 1;
  179. X    }
  180. X    else
  181. X    {
  182. X        len1 += len2;
  183. X    }
  184. X    malloc_check_data("strncat", file, line, str1, len1);
  185. X
  186. X    rtn = str1;
  187. X
  188. X    while( *str1 )
  189. X    {
  190. X        str1++;
  191. X    }
  192. X
  193. X    while( len && ((*str1++ = *str2++) != '\0') )
  194. X    {
  195. X        len--;
  196. X    }
  197. X    
  198. X    if( ! len )
  199. X    {
  200. X        *str1 = '\0';
  201. X    }
  202. X
  203. X    return(rtn);
  204. X}
  205. X
  206. X/*
  207. X * strcmp - compare two strings
  208. X */
  209. Xint
  210. Xstrcmp(str1,str2)
  211. X    register const char    * str1;
  212. X    register const char    * str2;
  213. X{
  214. X    return( DBstrcmp((char *) NULL, 0, str1, str2) );
  215. X}
  216. X
  217. Xint
  218. XDBstrcmp(file, line, str1, str2)
  219. X    const char        * file;
  220. X    int              line;
  221. X    register const char    * str1;
  222. X    register const char    * str2;
  223. X{
  224. X    malloc_check_str("strcmp", file, line, str1);
  225. X    malloc_check_str("strcmp", file, line, str2);
  226. X
  227. X    while( *str1 && (*str1 == *str2) )
  228. X    {
  229. X        str1++;
  230. X        str2++;
  231. X    }
  232. X
  233. X
  234. X    /*
  235. X     * in order to deal with the case of a negative last char of either
  236. X     * string when the other string has a null
  237. X     */
  238. X    if( (*str2 == '\0') && (*str1 == '\0') )
  239. X    {
  240. X        return(0);
  241. X    }
  242. X    else if( *str2 == '\0' )
  243. X    {
  244. X        return(1);
  245. X    }
  246. X    else if( *str1 == '\0' )
  247. X    {
  248. X        return(-1);
  249. X    }
  250. X    
  251. X    return( *str1 - *str2 );
  252. X}
  253. X
  254. X/*
  255. X * strncmp - compare two strings up to a specified length
  256. X */
  257. Xint
  258. Xstrncmp(str1,str2,len)
  259. X    register const char    * str1;
  260. X    register const char    * str2;
  261. X    register SIZETYPE      len;
  262. X{
  263. X    return( DBstrncmp((char *)NULL, 0, str1, str2, len) );
  264. X}
  265. X
  266. Xint
  267. XDBstrncmp(file, line, str1,str2,len)
  268. X    const char        * file;
  269. X    int              line;
  270. X    register const char    * str1;
  271. X    register const char    * str2;
  272. X    register SIZETYPE      len;
  273. X{
  274. X    malloc_check_strn("strncmp", file, line, str1, len);
  275. X    malloc_check_strn("strncmp", file, line, str2, len);
  276. X
  277. X    while( len > 0 && *str1 && (*str1 == *str2) )
  278. X    {
  279. X        len--;
  280. X        str1++;
  281. X        str2++;
  282. X    }
  283. X
  284. X    if( len == 0 )
  285. X    {
  286. X        return(0);
  287. X    }
  288. X    /*
  289. X     * in order to deal with the case of a negative last char of either
  290. X     * string when the other string has a null
  291. X     */
  292. X    if( (*str2 == '\0') && (*str1 == '\0') )
  293. X    {
  294. X        return(0);
  295. X    }
  296. X    else if( *str2 == '\0' )
  297. X    {
  298. X        return(1);
  299. X    }
  300. X    else if( *str1 == '\0' )
  301. X    {
  302. X        return(-1);
  303. X    }
  304. X    
  305. X    return( *str1 - *str2 );
  306. X}
  307. X
  308. X/*
  309. X * strcpy - copy a string somewhere else
  310. X */
  311. Xchar *
  312. Xstrcpy(str1,str2)
  313. X    register char        * str1;
  314. X    register const char    * str2;
  315. X{
  316. X    return( DBstrcpy((char *)NULL, 0, str1, str2) );
  317. X}
  318. X
  319. Xchar *
  320. XDBstrcpy(file, line, str1, str2)
  321. X    const char        * file;
  322. X    int              line;
  323. X    register char        * str1;
  324. X    register const char    * str2;
  325. X{
  326. X    char        * rtn;
  327. X    int          len;
  328. X
  329. X    in_string_code = 1;
  330. X    len = strlen(str2) + 1;
  331. X    in_string_code = 0;
  332. X
  333. X    malloc_check_data("strcpy", file, line, str1, len);
  334. X    malloc_check_data("strcpy", file, line, str2, len);
  335. X
  336. X    rtn = str1;
  337. X
  338. X    while( (*str1++ = *str2++) != '\0')
  339. X    {
  340. X    }
  341. X
  342. X    return(rtn);
  343. X}
  344. X
  345. X/*
  346. X * strncpy - copy a string upto a specified number of chars somewhere else
  347. X */
  348. Xchar *
  349. Xstrncpy(str1,str2,len)
  350. X    register char        * str1;
  351. X    register const char    * str2;
  352. X    register SIZETYPE      len;
  353. X{
  354. X    return( DBstrncpy((char *)NULL, 0, str1, str2, len) );
  355. X}
  356. X
  357. Xchar *
  358. XDBstrncpy(file,line,str1,str2,len)
  359. X    const char        * file;
  360. X    int              line;
  361. X    register char        * str1;
  362. X    register const char    * str2;
  363. X    register SIZETYPE      len;
  364. X{
  365. X    char        * rtn;
  366. X
  367. X    malloc_check_data("strncpy", file, line, str1, len);
  368. X    malloc_check_strn("strncpy", file, line, str2, len);
  369. X
  370. X    rtn = str1;
  371. X
  372. X    while((len > 0) && (*str1 = *str2) != '\0')
  373. X    {
  374. X        str1++;
  375. X        str2++;
  376. X        len--;
  377. X    }
  378. X    while( (len > 0) )
  379. X    {
  380. X        *str1++ = '\0';
  381. X        len--;
  382. X    }
  383. X
  384. X    return(rtn);
  385. X}
  386. X
  387. X/*
  388. X * strlen - determine length of a string
  389. X */
  390. XSIZETYPE
  391. Xstrlen(str1)
  392. X    const char    * str1;
  393. X{
  394. X    return( DBstrlen((char *) NULL, 0, str1) );
  395. X}
  396. X
  397. XSIZETYPE
  398. XDBstrlen(file, line, str1)
  399. X    const char        * file;
  400. X    int              line;
  401. X    register const char    * str1;
  402. X{
  403. X    register const char    * s;
  404. X
  405. X    if(! in_string_code )
  406. X    {
  407. X        malloc_check_str("strlen", file, line, str1);
  408. X    }
  409. X
  410. X    for( s = str1; *s; s++)
  411. X    {
  412. X    }
  413. X
  414. X    return( s - str1 );
  415. X}
  416. X
  417. X/*
  418. X * strchr - find location of a character in a string
  419. X */
  420. Xchar *
  421. Xstrchr(str1,c)
  422. X    const char    * str1;
  423. X    int          c;
  424. X{
  425. X    return( DBstrchr((char *)NULL,0,str1,c) );
  426. X}
  427. X
  428. Xchar *
  429. XDBstrchr(file, line, str1,c)
  430. X    const char        * file;
  431. X    int              line;
  432. X    const char        * str1;
  433. X    int              c;
  434. X{
  435. X    return( DBFstrchr("strchr",file,line,str1,c) );
  436. X}
  437. X
  438. Xchar *
  439. XDBFstrchr(func,file, line, str1,c)
  440. X    const char        * func;
  441. X    const char        * file;
  442. X    int              line;
  443. X    register const char    * str1;
  444. X    register int          c;
  445. X{
  446. X    malloc_check_str(func, file, line, str1);
  447. X
  448. X    while( *str1 && (*str1 != (char) c) )
  449. X    {
  450. X        str1++;
  451. X    }
  452. X
  453. X    if(*str1 != (char) c)
  454. X    {
  455. X        str1 = (char *) 0;
  456. X    }
  457. X
  458. X    return((char *)str1);
  459. X}
  460. X
  461. X/*
  462. X * strrchr - find rightmost location of a character in a string
  463. X */
  464. X
  465. Xchar *
  466. Xstrrchr(str1,c)
  467. X    const char    * str1;
  468. X    int          c;
  469. X{
  470. X    return( DBstrrchr( (char *)NULL, 0, str1, c) );
  471. X}
  472. X
  473. Xchar *
  474. XDBstrrchr(file,line,str1,c)
  475. X    const char        * file;
  476. X    int              line;
  477. X    const char        * str1;
  478. X    int              c;
  479. X{
  480. X    return( DBFstrrchr("strchr",file,line,str1,c) );
  481. X}
  482. X
  483. Xchar *
  484. XDBFstrrchr(func,file,line,str1,c)
  485. X    const char        * func;
  486. X    const char        * file;
  487. X    int              line;
  488. X    register const char    * str1;
  489. X    register int          c;
  490. X{
  491. X    register const char    * rtn = (char *) 0;
  492. X
  493. X    malloc_check_str(func, file, line, str1);
  494. X
  495. X    while( *str1 )
  496. X    {
  497. X        if(*str1 == (char) c )
  498. X        {
  499. X            rtn = str1;
  500. X        }
  501. X        str1++;
  502. X    }
  503. X
  504. X    if( *str1 == (char) c)
  505. X    {
  506. X        rtn = str1;
  507. X    }
  508. X
  509. X    return((char *)rtn);
  510. X}
  511. X
  512. X/*
  513. X * index - find location of character within string
  514. X */
  515. Xchar *
  516. Xindex(str1,c)
  517. X    const char        * str1;
  518. X    char          c;
  519. X{
  520. X    return( DBindex((char *) NULL, 0, str1, c) );
  521. X}
  522. Xchar *
  523. XDBindex(file, line, str1, c)
  524. X    const char    * file;
  525. X    int          line;
  526. X    const char    * str1;
  527. X    char          c;
  528. X{
  529. X    return( DBFstrchr("index",file,line,str1,c) );
  530. X}
  531. X
  532. X/*
  533. X * rindex - find rightmost location of character within string
  534. X */
  535. Xchar *
  536. Xrindex(str1,c)
  537. X    const char    * str1;
  538. X    char          c;
  539. X{
  540. X    return( DBrindex((char *)NULL, 0, str1, c) );
  541. X}
  542. X
  543. Xchar *
  544. XDBrindex(file, line, str1, c)
  545. X    const char    * file;
  546. X    int          line;
  547. X    const char    * str1;
  548. X    char          c;
  549. X{
  550. X    return( DBFstrrchr("rindex",file,line,str1,c) );
  551. X}
  552. X
  553. X/*
  554. X * strpbrk - find the first occurance of any character from str2 in str1
  555. X */
  556. Xchar *
  557. Xstrpbrk(str1,str2)
  558. X    const char    * str1;
  559. X    const char    * str2;
  560. X{
  561. X    return( DBstrpbrk((char *)NULL, 0, str1, str2) );
  562. X}
  563. X
  564. Xchar *
  565. XDBstrpbrk(file, line, str1,str2)
  566. X    const char        * file;
  567. X    int              line;
  568. X    register const char    * str1;
  569. X    register const char    * str2;
  570. X{
  571. X    register const char    * tmp;
  572. X
  573. X    malloc_check_str("strpbrk", file, line, str1);
  574. X    malloc_check_str("strpbrk", file, line, str2);
  575. X
  576. X    while(*str1)
  577. X    {
  578. X        for( tmp=str2; *tmp && *tmp != *str1; tmp++)
  579. X        {
  580. X        }
  581. X        if( *tmp )
  582. X        {
  583. X            break;
  584. X        }
  585. X        str1++;
  586. X    }
  587. X
  588. X    if( ! *str1 )
  589. X    {
  590. X        str1 = (char *) 0;
  591. X    }
  592. X
  593. X    return( (char *) str1);
  594. X}
  595. X
  596. X/*
  597. X * strspn - get length of str1 that consists totally of chars from str2
  598. X */
  599. XSIZETYPE
  600. Xstrspn(str1,str2)
  601. X    const char    * str1;
  602. X    const char    * str2;
  603. X{
  604. X    return( DBstrspn((char *)NULL, 0, str1, str2) );
  605. X}
  606. X
  607. XSIZETYPE
  608. XDBstrspn(file, line, str1,str2)
  609. X    const char        * file;
  610. X    int              line;
  611. X    register const char    * str1;
  612. X    register const char    * str2;
  613. X{
  614. X    register const char    * tmp;
  615. X    const char        * orig = str1;
  616. X
  617. X    malloc_check_str("strspn", file, line, str1);
  618. X    malloc_check_str("strspn", file, line, str2);
  619. X
  620. X    while(*str1)
  621. X    {
  622. X        for( tmp=str2; *tmp && *tmp != *str1; tmp++)
  623. X        {
  624. X        }
  625. X        if(! *tmp )
  626. X        {
  627. X            break;
  628. X        }
  629. X        str1++;
  630. X    }
  631. X
  632. X    return( (SIZETYPE) (str1 - orig) );
  633. X}
  634. X
  635. X/*
  636. X * strcspn - get lenght of str1 that consists of no chars from str2
  637. X */
  638. XSIZETYPE
  639. Xstrcspn(str1,str2)
  640. X    const char    * str1;
  641. X    const char    * str2;
  642. X{
  643. X    return( DBstrcspn((char *)NULL,0,str1,str2) );
  644. X}
  645. X
  646. XSIZETYPE
  647. XDBstrcspn(file, line, str1,str2)
  648. X    const char        * file;
  649. X    int              line;
  650. X    register const char    * str1;
  651. X    register const char    * str2;
  652. X{
  653. X    register const char    * tmp;
  654. X    const char    * orig = str1;
  655. X
  656. X    malloc_check_str("strcspn", file, line, str1);
  657. X    malloc_check_str("strcspn", file, line, str2);
  658. X
  659. X    while(*str1)
  660. X    {
  661. X        for( tmp=str2; *tmp && *tmp != *str1; tmp++)
  662. X        {
  663. X        }
  664. X        if( *tmp )
  665. X        {
  666. X            break;
  667. X        }
  668. X        str1++;
  669. X    }
  670. X
  671. X    return( (int) (str1 - orig) );
  672. X}
  673. X
  674. X/*
  675. X * strstr - locate string within another string
  676. X */
  677. Xchar *
  678. Xstrstr(str1, str2)
  679. X    const char    * str1;
  680. X    const char    * str2;
  681. X{
  682. X    return( DBstrstr((char *)NULL, 0, str1, str2) );
  683. X}
  684. X
  685. Xchar *
  686. XDBstrstr(file, line, str1, str2)
  687. X    const char    * file;
  688. X    int          line;
  689. X    const char    * str1;
  690. X    const char    * str2;
  691. X{
  692. X    register const char    * s;
  693. X    register const char    * t;
  694. X    
  695. X    malloc_check_str("strstr", file, line, str1);
  696. X    malloc_check_str("strstr", file, line, str2);
  697. X
  698. X    /*
  699. X     * until we run out of room in str1
  700. X     */
  701. X    while( *str1 != '\0' )
  702. X    {
  703. X        /*
  704. X         * get tmp pointers to both strings
  705. X         */
  706. X        s = str2;
  707. X        t = str1;
  708. X
  709. X        /*
  710. X         * see if they match
  711. X         */
  712. X        while( *s &&  (*s == *t) )
  713. X        {
  714. X            s++;
  715. X            t++;
  716. X        }
  717. X
  718. X        /*
  719. X         * if we ran out of str2, we found the match,
  720. X         * so return the pointer within str1.
  721. X         */
  722. X        if( ! *s )
  723. X        {
  724. X            return( (char *) str1);
  725. X        }
  726. X        str1++;
  727. X    }
  728. X
  729. X    if( *str2 == '\0' )
  730. X    {
  731. X        return( (char *) str1);
  732. X    }
  733. X    return(NULL);
  734. X}
  735. X
  736. X/*
  737. X * strtok() source taken from that posted to comp.lang.c by Chris Torek
  738. X * in Jan 1990.
  739. X */
  740. X
  741. X/*
  742. X * Copyright (c) 1989 The Regents of the University of California.
  743. X * All rights reserved.
  744. X *
  745. X * Redistribution and use in source and binary forms are permitted
  746. X * provided that the above copyright notice and this paragraph are
  747. X * duplicated in all such forms and that any documentation,
  748. X * advertising materials, and other materials related to such
  749. X * distribution and use acknowledge that the software was developed
  750. X * by the University of California, Berkeley.  The name of the
  751. X * University may not be used to endorse or promote products derived
  752. X * from this software without specific prior written permission.
  753. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  754. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  755. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  756. X */
  757. X
  758. X/*
  759. X * Get next token from string s (NULL on 2nd, 3rd, etc. calls),
  760. X * where tokens are nonempty strings separated by runs of
  761. X * chars from delim.  Writes NULs into s to end tokens.  delim need not
  762. X * remain constant from call to call.
  763. X *
  764. X * Modified by cpc:     changed variable names to conform with naming
  765. X *            conventions used in rest of code.  Added malloc pointer
  766. X *            check calls.
  767. X */
  768. X
  769. Xchar *
  770. Xstrtok(str1, str2)
  771. X    char         * str1;
  772. X    const char    * str2;
  773. X{
  774. X    return( DBstrtok( (char *)NULL, 0, str1, str2) );
  775. X}
  776. X
  777. Xchar *
  778. XDBstrtok(file, line, str1, str2)
  779. X    const char    * file;
  780. X    int          line;
  781. X    char         * str1;
  782. X    const char    * str2;
  783. X{
  784. X    static char     * last;
  785. X    char        * strtoken();
  786. X
  787. X    if( str1 )
  788. X    {
  789. X        malloc_check_str("strtok", file, line, str1);
  790. X        last = str1;
  791. X    }
  792. X    malloc_check_str("strtok", file, line, str2);
  793. X
  794. X    return (strtoken(&last, str2, 1));
  795. X}
  796. X
  797. X
  798. X/*
  799. X * Get next token from string *stringp, where tokens are (possibly empty)
  800. X * strings separated by characters from delim.  Tokens are separated
  801. X * by exactly one delimiter iff the skip parameter is false; otherwise
  802. X * they are separated by runs of characters from delim, because we
  803. X * skip over any initial `delim' characters.
  804. X *
  805. X * Writes NULs into the string at *stringp to end tokens.
  806. X * delim will usually, but need not, remain constant from call to call.
  807. X * On return, *stringp points past the last NUL written (if there might
  808. X * be further tokens), or is NULL (if there are definitely no more tokens).
  809. X *
  810. X * If *stringp is NULL, strtoken returns NULL.
  811. X */
  812. Xchar *
  813. Xstrtoken(stringp, delim, skip)
  814. X    register char **stringp;
  815. X    register const char *delim;
  816. X    int skip;
  817. X{
  818. X    register char *s;
  819. X    register const char *spanp;
  820. X    register int c, sc;
  821. X    char *tok;
  822. X
  823. X    if ((s = *stringp) == NULL)
  824. X        return (NULL);
  825. X
  826. X    if (skip) {
  827. X        /*
  828. X         * Skip (span) leading delimiters (s += strspn(s, delim)).
  829. X         */
  830. X    cont:
  831. X        c = *s;
  832. X        for (spanp = delim; (sc = *spanp++) != 0;) {
  833. X            if (c == sc) {
  834. X                s++;
  835. X                goto cont;
  836. X            }
  837. X        }
  838. X        if (c == 0) {        /* no token found */
  839. X            *stringp = NULL;
  840. X            return (NULL);
  841. X        }
  842. X    }
  843. X
  844. X    /*
  845. X     * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
  846. X     * Note that delim must have one NUL; we stop if we see that, too.
  847. X     */
  848. X    for (tok = s;;) {
  849. X        c = *s++;
  850. X        spanp = delim;
  851. X        do {
  852. X            if ((sc = *spanp++) == c) {
  853. X                if (c == 0)
  854. X                    s = NULL;
  855. X                else
  856. X                    s[-1] = 0;
  857. X                *stringp = s;
  858. X                return( (char *) tok );
  859. X            }
  860. X        } while (sc != 0);
  861. X    }
  862. X    /* NOTREACHED */
  863. X}
  864. X
  865. X/*
  866. X * $Log: string.c,v $
  867. X * Revision 1.14  1991/12/04  09:23:44  cpcahil
  868. X * several performance enhancements including addition of free list
  869. X *
  870. X * Revision 1.13  91/12/02  19:10:14  cpcahil
  871. X * changes for patch release 5
  872. X * 
  873. X * Revision 1.12  91/11/25  14:42:05  cpcahil
  874. X * Final changes in preparation for patch 4 release
  875. X * 
  876. X * Revision 1.11  91/11/24  16:56:43  cpcahil
  877. X * porting changes for patch level 4
  878. X * 
  879. X * Revision 1.10  91/11/24  00:49:32  cpcahil
  880. X * first cut at patch 4
  881. X * 
  882. X * Revision 1.9  91/11/20  11:54:11  cpcahil
  883. X * interim checkin
  884. X * 
  885. X * Revision 1.8  91/05/30  12:07:04  cpcahil
  886. X * added fix to get the stuff to compile correctly on ultirx and aix systems.
  887. X * 
  888. X * Revision 1.7  90/08/29  22:24:19  cpcahil
  889. X * added new function to check on strings up to a specified length 
  890. X * and used it within several strn* functions.
  891. X * 
  892. X * Revision 1.6  90/07/16  20:06:56  cpcahil
  893. X * fixed several minor bugs found with Henry Spencer's string/mem function
  894. X * tester program.
  895. X * 
  896. X * Revision 1.5  90/06/10  14:59:49  cpcahil
  897. X * Fixed a couple of bugs in strncpy & strdup
  898. X * 
  899. X * Revision 1.4  90/05/11  00:13:10  cpcahil
  900. X * added copyright statment
  901. X * 
  902. X * Revision 1.3  90/02/24  21:50:32  cpcahil
  903. X * lots of lint fixes
  904. X * 
  905. X * Revision 1.2  90/02/24  17:29:40  cpcahil
  906. X * changed $Header to $Id so full path wouldnt be included as part of rcs 
  907. X * id string
  908. X * 
  909. X * Revision 1.1  90/02/22  23:17:44  cpcahil
  910. X * Initial revision
  911. X * 
  912. X */
  913. END_OF_FILE
  914. if test 16008 -ne `wc -c <'string.c'`; then
  915.     echo shar: \"'string.c'\" unpacked with wrong size!
  916. fi
  917. # end of 'string.c'
  918. fi
  919. if test -f 'testmalloc.c' -a "${1}" != "-c" ; then 
  920.   echo shar: Will not clobber existing file \"'testmalloc.c'\"
  921. else
  922. echo shar: Extracting \"'testmalloc.c'\" \(4122 characters\)
  923. sed "s/^X//" >'testmalloc.c' <<'END_OF_FILE'
  924. X/* NOT copyright by SoftQuad Inc. -- msb, 1988 */
  925. X#ifndef lint
  926. Xstatic char *SQ_SccsId = "@(#)mtest3.c    1.2 88/08/25";
  927. X#endif
  928. X#include <stdio.h>
  929. X#include "malloc.h"
  930. X/*
  931. X** looptest.c -- intensive allocator tester 
  932. X**
  933. X** Usage:  looptest
  934. X**
  935. X** History:
  936. X**    4-Feb-1987 rtech!daveb 
  937. X*/
  938. X
  939. X#ifndef HAS_VADVISE
  940. X# define random    rand
  941. X#else
  942. X# include <sys/vadvise.h>
  943. X#endif
  944. X
  945. X# include <stdio.h>
  946. X# include <signal.h>
  947. X# include <setjmp.h>
  948. X
  949. X# define MAXITER    1000000        /* main loop iterations */
  950. X# define MAXOBJS    1000        /* objects in pool */
  951. X# define BIGOBJ        90000        /* max size of a big object */
  952. X# define TINYOBJ    80        /* max size of a small object */
  953. X# define BIGMOD        100        /* 1 in BIGMOD is a BIGOBJ */
  954. X# define STATMOD    10000        /* interation interval for status */
  955. X
  956. Xmain( argc, argv )
  957. Xint argc;
  958. Xchar **argv;
  959. X{
  960. X    register int **objs;        /* array of objects */
  961. X    register int *sizes;        /* array of object sizes */
  962. X    register int n;            /* iteration counter */
  963. X    register int i;            /* object index */
  964. X    register int size;        /* object size */
  965. X    register int r;            /* random number */
  966. X
  967. X    int objmax;            /* max size this iteration */
  968. X    int cnt;            /* number of allocated objects */
  969. X    int nm = 0;            /* number of mallocs */
  970. X    int nre = 0;            /* number of reallocs */
  971. X    int nal;            /* number of allocated objects */
  972. X    int nfre;            /* number of free list objects */
  973. X    long alm;            /* memory in allocated objects */
  974. X    long frem;            /* memory in free list */
  975. X    long startsize;            /* size at loop start */
  976. X    long endsize;            /* size at loop exit */
  977. X    long maxiter = 0;        /* real max # iterations */
  978. X
  979. X    extern char end;        /* memory before heap */
  980. X    char *sbrk();
  981. X    long atol();
  982. X
  983. X#ifdef HAS_VADVISE
  984. X    /* your milage may vary... */
  985. X    vadvise( VA_ANOM );
  986. X#endif
  987. X
  988. X    if (argc > 1)
  989. X        maxiter = atol (argv[1]);
  990. X    if (maxiter <= 0)
  991. X        maxiter = MAXITER;
  992. X
  993. X    printf("MAXITER %d MAXOBJS %d ", maxiter, MAXOBJS );
  994. X    printf("BIGOBJ %d, TINYOBJ %d, nbig/ntiny 1/%d\n",
  995. X    BIGOBJ, TINYOBJ, BIGMOD );
  996. X    fflush( stdout );
  997. X
  998. X    if( NULL == (objs = (int **)calloc( MAXOBJS, sizeof( *objs ) ) ) )
  999. X    {
  1000. X        fprintf(stderr, "Can't allocate memory for objs array\n");
  1001. X        exit(1);
  1002. X    }
  1003. X
  1004. X    if( NULL == ( sizes = (int *)calloc( MAXOBJS, sizeof( *sizes ) ) ) )
  1005. X    {
  1006. X        fprintf(stderr, "Can't allocate memory for sizes array\n");
  1007. X        exit(1);
  1008. X    }
  1009. X
  1010. X    /* as per recent discussion on net.lang.c, calloc does not 
  1011. X    ** necessarily fill in NULL pointers...
  1012. X    */
  1013. X    for( i = 0; i < MAXOBJS; i++ )
  1014. X        objs[ i ] = NULL;
  1015. X
  1016. X    startsize = sbrk(0) - &end;
  1017. X    printf( "Memory use at start: %d bytes\n", startsize );
  1018. X    fflush(stdout);
  1019. X
  1020. X    printf("Starting the test...\n");
  1021. X    fflush(stdout);
  1022. X    for( n = 0; n < maxiter ; n++ )
  1023. X    {
  1024. X        if( !(n % STATMOD) )
  1025. X        {
  1026. X            printf("%d iterations\n", n);
  1027. X            fflush(stdout);
  1028. X        }
  1029. X
  1030. X        /* determine object of interst and it's size */
  1031. X
  1032. X        r = random();
  1033. X        objmax = ( r % BIGMOD ) ? TINYOBJ : BIGOBJ;
  1034. X        size = r % objmax;
  1035. X        i = r % (MAXOBJS - 1);
  1036. X
  1037. X        /* either replace the object of get a new one */
  1038. X
  1039. X        if( objs[ i ] == NULL )
  1040. X        {
  1041. X            objs[ i ] = (int *)malloc( size );
  1042. X            nm++;
  1043. X        }
  1044. X        else
  1045. X        {
  1046. X            /* don't keep bigger objects around */
  1047. X            if( size > sizes[ i ] )
  1048. X            {
  1049. X                objs[ i ] = (int *)realloc( (DATATYPE *) objs[ i ], size );
  1050. X                nre++;
  1051. X            }
  1052. X            else
  1053. X            {
  1054. X                free( (DATATYPE *) objs[ i ] );
  1055. X                objs[ i ] = (int *)malloc( size );
  1056. X                nm++;
  1057. X            }
  1058. X        }
  1059. X
  1060. X        sizes[ i ] = size;
  1061. X        if( objs[ i ] == NULL )
  1062. X        {
  1063. X            printf("\nCouldn't allocate %d byte object!\n", 
  1064. X                size );
  1065. X            break;
  1066. X        }
  1067. X    } /* for() */
  1068. X
  1069. X    printf( "\n" );
  1070. X    cnt = 0;
  1071. X    for( i = 0; i < MAXOBJS; i++ )
  1072. X        if( objs[ i ] )
  1073. X            cnt++;
  1074. X
  1075. X    printf( "Did %d iterations, %d objects, %d mallocs, %d reallocs\n",
  1076. X        n, cnt, nm, nre );
  1077. X    printf( "Memory use at end: %d bytes\n", sbrk(0) - &end );
  1078. X    fflush( stdout );
  1079. X
  1080. X    /* free all the objects */
  1081. X    for( i = 0; i < MAXOBJS; i++ )
  1082. X        if( objs[ i ] != NULL )
  1083. X            free( (DATATYPE *) objs[ i ] );
  1084. X
  1085. X    endsize = sbrk(0) - &end;
  1086. X    printf( "Memory use after free: %d bytes\n", endsize );
  1087. X    fflush( stdout );
  1088. X
  1089. X    if( startsize != endsize )
  1090. X        printf("startsize %d != endsize %d\n", startsize, endsize );
  1091. X
  1092. X    free( (DATATYPE *) objs );
  1093. X    free( (DATATYPE *) sizes );
  1094. X
  1095. X#ifdef USE_SETENV
  1096. X    setenv("MALLOC_DETAIL","y",1);
  1097. X#else
  1098. X    putenv("MALLOC_DETAIL=y");
  1099. X#endif
  1100. X    malloc_dump(2);
  1101. X    exit( 0 );
  1102. X}
  1103. X
  1104. END_OF_FILE
  1105. if test 4122 -ne `wc -c <'testmalloc.c'`; then
  1106.     echo shar: \"'testmalloc.c'\" unpacked with wrong size!
  1107. fi
  1108. # end of 'testmalloc.c'
  1109. fi
  1110. if test -f 'testmem.c' -a "${1}" != "-c" ; then 
  1111.   echo shar: Will not clobber existing file \"'testmem.c'\"
  1112. else
  1113. echo shar: Extracting \"'testmem.c'\" \(21125 characters\)
  1114. sed "s/^X//" >'testmem.c' <<'END_OF_FILE'
  1115. X/* 
  1116. X * This stuff is all stolen (with permission, since it was in the public
  1117. X * domain) from Henry Spencer's string and memory library.  Thanks Henry.
  1118. X */
  1119. X
  1120. X/*
  1121. X * Test program for string(3) routines.
  1122. X * 
  1123. X * Note that at least one Bell Labs implementation of the string
  1124. X * routines flunks a couple of these tests -- the ones which test
  1125. X * behavior on "negative" characters.
  1126. X */
  1127. X
  1128. X#include <stdio.h>
  1129. X#include "malloc.h"
  1130. X
  1131. X#ifndef index
  1132. Xchar * index();
  1133. Xchar * rindex();
  1134. X#endif
  1135. X
  1136. X#define    STREQ(a, b)    (strcmp((a), (b)) == 0)
  1137. X
  1138. Xchar *it = "<UNSET>";        /* Routine name for message routines. */
  1139. Xint waserror = 0;        /* For exit status. */
  1140. X
  1141. Xchar uctest[] = "\004\203";    /* For testing signedness of chars. */
  1142. Xint charsigned;            /* Result. */
  1143. X
  1144. X/*
  1145. X - check - complain if condition is not true
  1146. X */
  1147. XVOIDTYPE
  1148. Xcheck(thing, number)
  1149. Xint thing;
  1150. Xint number;            /* Test number for error message. */
  1151. X{
  1152. X    if (!thing) {
  1153. X        printf("%s flunked test %d\n", it, number);
  1154. X        waserror = 1;
  1155. X    }
  1156. X}
  1157. X
  1158. X/*
  1159. X - equal - complain if first two args don't strcmp as equal
  1160. X */
  1161. XVOIDTYPE
  1162. Xequal(a, b, number)
  1163. Xchar *a;
  1164. Xchar *b;
  1165. Xint number;            /* Test number for error message. */
  1166. X{
  1167. X    check(a != NULL && b != NULL && STREQ(a, b), number);
  1168. X}
  1169. X
  1170. Xchar one[50];
  1171. Xchar two[50];
  1172. X
  1173. X#ifdef UNIXERR
  1174. X#define ERR 1
  1175. X#endif
  1176. X#ifdef BERKERR
  1177. X#define ERR 1
  1178. X#endif
  1179. X#ifdef ERR
  1180. Xint f;
  1181. Xextern char *sys_errlist[];
  1182. Xextern int sys_nerr;
  1183. Xextern int errno;
  1184. X#endif
  1185. X
  1186. X/* ARGSUSED */
  1187. Xmain(argc, argv)
  1188. Xint argc;
  1189. Xchar *argv[];
  1190. X{
  1191. X    /*
  1192. X     * First, establish whether chars are signed.
  1193. X     */
  1194. X    if (uctest[0] < uctest[1])
  1195. X        charsigned = 0;
  1196. X    else
  1197. X        charsigned = 1;
  1198. X
  1199. X    /*
  1200. X     * Then, do the rest of the work.  Split into two functions because
  1201. X     * some compilers get unhappy about a single immense function.
  1202. X     */
  1203. X    first();
  1204. X    second();
  1205. X
  1206. X    exit((waserror) ? 1 : 0);
  1207. X}
  1208. X
  1209. Xfirst()
  1210. X{
  1211. X    /*
  1212. X     * Test strcmp first because we use it to test other things.
  1213. X     */
  1214. X    it = "strcmp";
  1215. X    check(strcmp("", "") == 0, 1);        /* Trivial case. */
  1216. X    check(strcmp("a", "a") == 0, 2);    /* Identity. */
  1217. X    check(strcmp("abc", "abc") == 0, 3);    /* Multicharacter. */
  1218. X    check(strcmp("abc", "abcd") < 0, 4);    /* Length mismatches. */
  1219. X    check(strcmp("abcd", "abc") > 0, 5);
  1220. X    check(strcmp("abcd", "abce") < 0, 6);    /* Honest miscompares. */
  1221. X    check(strcmp("abce", "abcd") > 0, 7);
  1222. X    check(strcmp("a\203", "a") > 0, 8);    /* Tricky if char signed. */
  1223. X    if (charsigned)                /* Sign-bit comparison. */
  1224. X        check(strcmp("a\203", "a\003") < 0, 9);
  1225. X    else
  1226. X        check(strcmp("a\203", "a\003") > 0, 9);
  1227. X    check(strcmp("a", "a\203") < 0, 10);    /* Tricky if char signed. */
  1228. X
  1229. X    /*
  1230. X     * Test strcpy next because we need it to set up other tests.
  1231. X     */
  1232. X    it = "strcpy";
  1233. X    check(strcpy(one, "abcd") == one, 1);    /* Returned value. */
  1234. X    equal(one, "abcd", 2);            /* Basic test. */
  1235. X
  1236. X    VOIDCAST strcpy(one, "x");
  1237. X    equal(one, "x", 3);            /* Writeover. */
  1238. X    equal(one+2, "cd", 4);            /* Wrote too much? */
  1239. X
  1240. X    VOIDCAST strcpy(two, "hi there");
  1241. X    VOIDCAST strcpy(one, two);
  1242. X    equal(one, "hi there", 5);        /* Basic test encore. */
  1243. X    equal(two, "hi there", 6);        /* Stomped on source? */
  1244. X
  1245. X    VOIDCAST strcpy(one, "");
  1246. X    equal(one, "", 7);            /* Boundary condition. */
  1247. X
  1248. X    /*
  1249. X     * strcat
  1250. X     */
  1251. X    it = "strcat";
  1252. X    VOIDCAST strcpy(one, "ijk");
  1253. X    check(strcat(one, "lmn") == one, 1);    /* Returned value. */
  1254. X    equal(one, "ijklmn", 2);        /* Basic test. */
  1255. X
  1256. X    VOIDCAST strcpy(one, "x");
  1257. X    VOIDCAST strcat(one, "yz");
  1258. X    equal(one, "xyz", 3);            /* Writeover. */
  1259. X    equal(one+4, "mn", 4);            /* Wrote too much? */
  1260. X
  1261. X    VOIDCAST strcpy(one, "gh");
  1262. X    VOIDCAST strcpy(two, "ef");
  1263. X    VOIDCAST strcat(one, two);
  1264. X    equal(one, "ghef", 5);            /* Basic test encore. */
  1265. X    equal(two, "ef", 6);            /* Stomped on source? */
  1266. X
  1267. X    VOIDCAST strcpy(one, "");
  1268. X    VOIDCAST strcat(one, "");
  1269. X    equal(one, "", 7);            /* Boundary conditions. */
  1270. X    VOIDCAST strcpy(one, "ab");
  1271. X    VOIDCAST strcat(one, "");
  1272. X    equal(one, "ab", 8);
  1273. X    VOIDCAST strcpy(one, "");
  1274. X    VOIDCAST strcat(one, "cd");
  1275. X    equal(one, "cd", 9);
  1276. X
  1277. X    /*
  1278. X     * strncat - first test it as strcat, with big counts, then
  1279. X     * test the count mechanism.
  1280. X     */
  1281. X    it = "strncat";
  1282. X    VOIDCAST strcpy(one, "ijk");
  1283. X    check(strncat(one, "lmn", 99) == one, 1);    /* Returned value. */
  1284. X    equal(one, "ijklmn", 2);        /* Basic test. */
  1285. X
  1286. X    VOIDCAST strcpy(one, "x");
  1287. X    VOIDCAST strncat(one, "yz", 99);
  1288. X    equal(one, "xyz", 3);            /* Writeover. */
  1289. X    equal(one+4, "mn", 4);            /* Wrote too much? */
  1290. X
  1291. X    VOIDCAST strcpy(one, "gh");
  1292. X    VOIDCAST strcpy(two, "ef");
  1293. X    VOIDCAST strncat(one, two, 99);
  1294. X    equal(one, "ghef", 5);            /* Basic test encore. */
  1295. X    equal(two, "ef", 6);            /* Stomped on source? */
  1296. X
  1297. X    VOIDCAST strcpy(one, "");
  1298. X    VOIDCAST strncat(one, "", 99);
  1299. X    equal(one, "", 7);            /* Boundary conditions. */
  1300. X    VOIDCAST strcpy(one, "ab");
  1301. X    VOIDCAST strncat(one, "", 99);
  1302. X    equal(one, "ab", 8);
  1303. X    VOIDCAST strcpy(one, "");
  1304. X    VOIDCAST strncat(one, "cd", 99);
  1305. X    equal(one, "cd", 9);
  1306. X
  1307. X    VOIDCAST strcpy(one, "ab");
  1308. X    VOIDCAST strncat(one, "cdef", 2);
  1309. X    equal(one, "abcd", 10);            /* Count-limited. */
  1310. X
  1311. X    VOIDCAST strncat(one, "gh", 0);
  1312. X    equal(one, "abcd", 11);            /* Zero count. */
  1313. X
  1314. X    VOIDCAST strncat(one, "gh", 2);
  1315. X    equal(one, "abcdgh", 12);        /* Count and length equal. */
  1316. X
  1317. X    /*
  1318. X     * strncmp - first test as strcmp with big counts, then test
  1319. X     * count code.
  1320. X     */
  1321. X    it = "strncmp";
  1322. X    check(strncmp("", "", 99) == 0, 1);    /* Trivial case. */
  1323. X    check(strncmp("a", "a", 99) == 0, 2);    /* Identity. */
  1324. X    check(strncmp("abc", "abc", 99) == 0, 3);    /* Multicharacter. */
  1325. X    check(strncmp("abc", "abcd", 99) < 0, 4);    /* Length unequal. */
  1326. X    check(strncmp("abcd", "abc", 99) > 0, 5);
  1327. X    check(strncmp("abcd", "abce", 99) < 0, 6);    /* Honestly unequal. */
  1328. X    check(strncmp("abce", "abcd", 99) > 0, 7);
  1329. X    check(strncmp("a\203", "a", 2) > 0, 8);    /* Tricky if '\203' < 0 */
  1330. X    if (charsigned)                /* Sign-bit comparison. */
  1331. X        check(strncmp("a\203", "a\003", 2) < 0, 9);
  1332. X    else
  1333. X        check(strncmp("a\203", "a\003", 2) > 0, 9);
  1334. X    check(strncmp("abce", "abcd", 3) == 0, 10);    /* Count limited. */
  1335. X    check(strncmp("abce", "abc", 3) == 0, 11);    /* Count == length. */
  1336. X    check(strncmp("abcd", "abce", 4) < 0, 12);    /* Nudging limit. */
  1337. X    check(strncmp("abc", "def", 0) == 0, 13);    /* Zero count. */
  1338. X
  1339. X    /*
  1340. X     * strncpy - testing is a bit different because of odd semantics
  1341. X     */
  1342. X    it = "strncpy";
  1343. X    check(strncpy(one, "abc", 4) == one, 1);    /* Returned value. */
  1344. X    equal(one, "abc", 2);            /* Did the copy go right? */
  1345. X
  1346. X    VOIDCAST strcpy(one, "abcdefgh");
  1347. X    VOIDCAST strncpy(one, "xyz", 2);
  1348. X    equal(one, "xycdefgh", 3);        /* Copy cut by count. */
  1349. X
  1350. X    VOIDCAST strcpy(one, "abcdefgh");
  1351. X    VOIDCAST strncpy(one, "xyz", 3);    /* Copy cut just before NUL. */
  1352. X    equal(one, "xyzdefgh", 4);
  1353. X
  1354. X    VOIDCAST strcpy(one, "abcdefgh");
  1355. X    VOIDCAST strncpy(one, "xyz", 4);    /* Copy just includes NUL. */
  1356. X    equal(one, "xyz", 5);
  1357. X    equal(one+4, "efgh", 6);        /* Wrote too much? */
  1358. X
  1359. X    VOIDCAST strcpy(one, "abcdefgh");
  1360. X    VOIDCAST strncpy(one, "xyz", 5);    /* Copy includes padding. */
  1361. X    equal(one, "xyz", 7);
  1362. X    equal(one+4, "", 8);
  1363. X    equal(one+5, "fgh", 9);
  1364. X
  1365. X    VOIDCAST strcpy(one, "abc");
  1366. X    VOIDCAST strncpy(one, "xyz", 0);    /* Zero-length copy. */
  1367. X    equal(one, "abc", 10);    
  1368. X
  1369. X    VOIDCAST strncpy(one, "", 2);        /* Zero-length source. */
  1370. X    equal(one, "", 11);
  1371. X    equal(one+1, "", 12);    
  1372. X    equal(one+2, "c", 13);
  1373. X
  1374. X    VOIDCAST strcpy(one, "hi there");
  1375. X    VOIDCAST strncpy(two, one, 9);
  1376. X    equal(two, "hi there", 14);        /* Just paranoia. */
  1377. X    equal(one, "hi there", 15);        /* Stomped on source? */
  1378. X
  1379. X    /*
  1380. X     * strlen
  1381. X     */
  1382. X    it = "strlen";
  1383. X    check(strlen("") == 0, 1);        /* Empty. */
  1384. X    check(strlen("a") == 1, 2);        /* Single char. */
  1385. X    check(strlen("abcd") == 4, 3);        /* Multiple chars. */
  1386. X
  1387. X    /*
  1388. X     * strchr
  1389. X     */
  1390. X    it = "strchr";
  1391. X    check(strchr("abcd", 'z') == NULL, 1);    /* Not found. */
  1392. X    VOIDCAST strcpy(one, "abcd");
  1393. X    check(strchr(one, 'c') == one+2, 2);    /* Basic test. */
  1394. X    check(strchr(one, 'd') == one+3, 3);    /* End of string. */
  1395. X    check(strchr(one, 'a') == one, 4);    /* Beginning. */
  1396. X    check(strchr(one, '\0') == one+4, 5);    /* Finding NUL. */
  1397. X    VOIDCAST strcpy(one, "ababa");
  1398. X    check(strchr(one, 'b') == one+1, 6);    /* Finding first. */
  1399. X    VOIDCAST strcpy(one, "");
  1400. X    check(strchr(one, 'b') == NULL, 7);    /* Empty string. */
  1401. X    check(strchr(one, '\0') == one, 8);    /* NUL in empty string. */
  1402. X
  1403. X    /*
  1404. X     * strstr (minimal testing added by cpc)
  1405. X     */
  1406. X    it = "strstr";
  1407. X    check(strstr("abcd", "z") == NULL, 1);    /* Not found. */
  1408. X    VOIDCAST strcpy(one, "abcd");
  1409. X    check(strstr(one, "c") == one+2, 2);    /* Basic test. */
  1410. X    check(strstr(one, "cd") == one+2, 3);    /* Basic test. */
  1411. X    check(strstr(one, "d") == one+3, 4);    /* End of string. */
  1412. X    check(strstr(one, "a") == one, 5);    /* Beginning. */
  1413. X    check(strstr(one, "") == one, 6);    /* Finding NUL. */
  1414. X    VOIDCAST strcpy(one, "ababa");
  1415. X    check(strstr(one, "b") == one+1, 7);    /* Finding first. */
  1416. X    VOIDCAST strcpy(one, "");
  1417. X    check(strstr(one, "b") == NULL, 8);    /* Empty string. */
  1418. X    check(strstr(one, "") == one, 9);    /* NUL in empty string. */
  1419. X
  1420. X    /*
  1421. X     * index - just like strchr
  1422. X     */
  1423. X    it = "index";
  1424. X    check(index("abcd", 'z') == NULL, 1);    /* Not found. */
  1425. X    VOIDCAST strcpy(one, "abcd");
  1426. X    check(index(one, 'c') == one+2, 2);    /* Basic test. */
  1427. X    check(index(one, 'd') == one+3, 3);    /* End of string. */
  1428. X    check(index(one, 'a') == one, 4);    /* Beginning. */
  1429. X    check(index(one, '\0') == one+4, 5);    /* Finding NUL. */
  1430. X    VOIDCAST strcpy(one, "ababa");
  1431. X    check(index(one, 'b') == one+1, 6);    /* Finding first. */
  1432. X    VOIDCAST strcpy(one, "");
  1433. X    check(index(one, 'b') == NULL, 7);    /* Empty string. */
  1434. X    check(index(one, '\0') == one, 8);    /* NUL in empty string. */
  1435. X
  1436. X    /*
  1437. X     * strrchr
  1438. X     */
  1439. X    it = "strrchr";
  1440. X    check(strrchr("abcd", 'z') == NULL, 1);    /* Not found. */
  1441. X    VOIDCAST strcpy(one, "abcd");
  1442. X    check(strrchr(one, 'c') == one+2, 2);    /* Basic test. */
  1443. X    check(strrchr(one, 'd') == one+3, 3);    /* End of string. */
  1444. X    check(strrchr(one, 'a') == one, 4);    /* Beginning. */
  1445. X    check(strrchr(one, '\0') == one+4, 5);    /* Finding NUL. */
  1446. X    VOIDCAST strcpy(one, "ababa");
  1447. X    check(strrchr(one, 'b') == one+3, 6);    /* Finding last. */
  1448. X    VOIDCAST strcpy(one, "");
  1449. X    check(strrchr(one, 'b') == NULL, 7);    /* Empty string. */
  1450. X    check(strrchr(one, '\0') == one, 8);    /* NUL in empty string. */
  1451. X
  1452. X    /*
  1453. X     * rindex - just like strrchr
  1454. X     */
  1455. X    it = "rindex";
  1456. X    check(rindex("abcd", 'z') == NULL, 1);    /* Not found. */
  1457. X    VOIDCAST strcpy(one, "abcd");
  1458. X    check(rindex(one, 'c') == one+2, 2);    /* Basic test. */
  1459. X    check(rindex(one, 'd') == one+3, 3);    /* End of string. */
  1460. X    check(rindex(one, 'a') == one, 4);    /* Beginning. */
  1461. X    check(rindex(one, '\0') == one+4, 5);    /* Finding NUL. */
  1462. X    VOIDCAST strcpy(one, "ababa");
  1463. X    check(rindex(one, 'b') == one+3, 6);    /* Finding last. */
  1464. X    VOIDCAST strcpy(one, "");
  1465. X    check(rindex(one, 'b') == NULL, 7);    /* Empty string. */
  1466. X    check(rindex(one, '\0') == one, 8);    /* NUL in empty string. */
  1467. X}
  1468. X
  1469. Xsecond()
  1470. X{
  1471. X    /*
  1472. X     * strpbrk - somewhat like strchr
  1473. X     */
  1474. X    it = "strpbrk";
  1475. X    check(strpbrk("abcd", "z") == NULL, 1);    /* Not found. */
  1476. X    VOIDCAST strcpy(one, "abcd");
  1477. X    check(strpbrk(one, "c") == one+2, 2);    /* Basic test. */
  1478. X    check(strpbrk(one, "d") == one+3, 3);    /* End of string. */
  1479. X    check(strpbrk(one, "a") == one, 4);    /* Beginning. */
  1480. X    check(strpbrk(one, "") == NULL, 5);    /* Empty search list. */
  1481. X    check(strpbrk(one, "cb") == one+1, 6);    /* Multiple search. */
  1482. X    VOIDCAST strcpy(one, "abcabdea");
  1483. X    check(strpbrk(one, "b") == one+1, 7);    /* Finding first. */
  1484. X    check(strpbrk(one, "cb") == one+1, 8);    /* With multiple search. */
  1485. X    check(strpbrk(one, "db") == one+1, 9);    /* Another variant. */
  1486. X    VOIDCAST strcpy(one, "");
  1487. X    check(strpbrk(one, "bc") == NULL, 10);    /* Empty string. */
  1488. X    check(strpbrk(one, "") == NULL, 11);    /* Both strings empty. */
  1489. X
  1490. X#if 0
  1491. X    /*
  1492. X     * strstr - somewhat like strchr
  1493. X     */
  1494. X    it = "strstr";
  1495. X    check(strstr("abcd", "z") == NULL, 1);    /* Not found. */
  1496. X    check(strstr("abcd", "abx") == NULL, 2);    /* Dead end. */
  1497. X    VOIDCAST strcpy(one, "abcd");
  1498. X    check(strstr(one, "c") == one+2, 3);    /* Basic test. */
  1499. X    check(strstr(one, "bc") == one+1, 4);    /* Multichar. */
  1500. X    check(strstr(one, "d") == one+3, 5);    /* End of string. */
  1501. X    check(strstr(one, "cd") == one+2, 6);    /* Tail of string. */
  1502. X    check(strstr(one, "abc") == one, 7);    /* Beginning. */
  1503. X    check(strstr(one, "abcd") == one, 8);    /* Exact match. */
  1504. X    check(strstr(one, "abcde") == NULL, 9);    /* Too long. */
  1505. X    check(strstr(one, "de") == NULL, 10);    /* Past end. */
  1506. X    check(strstr(one, "") == one+4, 11);    /* Finding empty. */
  1507. X    VOIDCAST strcpy(one, "ababa");
  1508. X    check(strstr(one, "ba") == one+1, 12);    /* Finding first. */
  1509. X    VOIDCAST strcpy(one, "");
  1510. X    check(strstr(one, "b") == NULL, 13);    /* Empty string. */
  1511. X    check(strstr(one, "") == one, 14);    /* Empty in empty string. */
  1512. X    VOIDCAST strcpy(one, "bcbca");
  1513. X    check(strstr(one, "bca") == one+2, 15);    /* False start. */
  1514. X    VOIDCAST strcpy(one, "bbbcabbca");
  1515. X    check(strstr(one, "bbca") == one+1, 16);    /* With overlap. */
  1516. X#endif
  1517. X
  1518. X    /*
  1519. X     * strspn
  1520. X     */
  1521. X    it = "strspn";
  1522. X    check(strspn("abcba", "abc") == 5, 1);    /* Whole string. */
  1523. X    check(strspn("abcba", "ab") == 2, 2);    /* Partial. */
  1524. X    check(strspn("abc", "qx") == 0, 3);    /* None. */
  1525. X    check(strspn("", "ab") == 0, 4);    /* Null string. */
  1526. X    check(strspn("abc", "") == 0, 5);    /* Null search list. */
  1527. X
  1528. X    /*
  1529. X     * strcspn
  1530. X     */
  1531. X    it = "strcspn";
  1532. X    check(strcspn("abcba", "qx") == 5, 1);    /* Whole string. */
  1533. X    check(strcspn("abcba", "cx") == 2, 2);    /* Partial. */
  1534. X    check(strcspn("abc", "abc") == 0, 3);    /* None. */
  1535. X    check(strcspn("", "ab") == 0, 4);    /* Null string. */
  1536. X    check(strcspn("abc", "") == 3, 5);    /* Null search list. */
  1537. X
  1538. X    /*
  1539. X     * strtok - the hard one
  1540. X     */
  1541. X    it = "strtok";
  1542. X    VOIDCAST strcpy(one, "first, second, third");
  1543. X    equal(strtok(one, ", "), "first", 1);    /* Basic test. */
  1544. X    equal(one, "first", 2);
  1545. X    equal(strtok((char *)NULL, ", "), "second", 3);
  1546. X    equal(strtok((char *)NULL, ", "), "third", 4);
  1547. X    check(strtok((char *)NULL, ", ") == NULL, 5);
  1548. X    VOIDCAST strcpy(one, ", first, ");
  1549. X    equal(strtok(one, ", "), "first", 6);    /* Extra delims, 1 tok. */
  1550. X    check(strtok((char *)NULL, ", ") == NULL, 7);
  1551. X    VOIDCAST strcpy(one, "1a, 1b; 2a, 2b");
  1552. X    equal(strtok(one, ", "), "1a", 8);    /* Changing delim lists. */
  1553. X    equal(strtok((char *)NULL, "; "), "1b", 9);
  1554. X    equal(strtok((char *)NULL, ", "), "2a", 10);
  1555. X    VOIDCAST strcpy(two, "x-y");
  1556. X    equal(strtok(two, "-"), "x", 11);    /* New string before done. */
  1557. X    equal(strtok((char *)NULL, "-"), "y", 12);
  1558. X    check(strtok((char *)NULL, "-") == NULL, 13);
  1559. X    VOIDCAST strcpy(one, "a,b, c,, ,d");
  1560. X    equal(strtok(one, ", "), "a", 14);    /* Different separators. */
  1561. X    equal(strtok((char *)NULL, ", "), "b", 15);
  1562. X    equal(strtok((char *)NULL, " ,"), "c", 16);    /* Permute list too. */
  1563. X    equal(strtok((char *)NULL, " ,"), "d", 17);
  1564. X    check(strtok((char *)NULL, ", ") == NULL, 18);
  1565. X    check(strtok((char *)NULL, ", ") == NULL, 19);    /* Persistence. */
  1566. X    VOIDCAST strcpy(one, ", ");
  1567. X    check(strtok(one, ", ") == NULL, 20);    /* No tokens. */
  1568. X    VOIDCAST strcpy(one, "");
  1569. X    check(strtok(one, ", ") == NULL, 21);    /* Empty string. */
  1570. X    VOIDCAST strcpy(one, "abc");
  1571. X    equal(strtok(one, ", "), "abc", 22);    /* No delimiters. */
  1572. X    check(strtok((char *)NULL, ", ") == NULL, 23);
  1573. X    VOIDCAST strcpy(one, "abc");
  1574. X    equal(strtok(one, ""), "abc", 24);    /* Empty delimiter list. */
  1575. X    check(strtok((char *)NULL, "") == NULL, 25);
  1576. X    VOIDCAST strcpy(one, "abcdefgh");
  1577. X    VOIDCAST strcpy(one, "a,b,c");
  1578. X    equal(strtok(one, ","), "a", 26);    /* Basics again... */
  1579. X    equal(strtok((char *)NULL, ","), "b", 27);
  1580. X    equal(strtok((char *)NULL, ","), "c", 28);
  1581. X    check(strtok((char *)NULL, ",") == NULL, 29);
  1582. X    equal(one+6, "gh", 30);            /* Stomped past end? */
  1583. X    equal(one, "a", 31);            /* Stomped old tokens? */
  1584. X    equal(one+2, "b", 32);
  1585. X    equal(one+4, "c", 33);
  1586. X
  1587. X    /*
  1588. X     * memcmp
  1589. X     */
  1590. X    it = "memcmp";
  1591. X    check(memcmp("a", "a", 1) == 0, 1);    /* Identity. */
  1592. X    check(memcmp("abc", "abc", 3) == 0, 2);    /* Multicharacter. */
  1593. X    check(memcmp("abcd", "abce", 4) < 0, 3);    /* Honestly unequal. */
  1594. X    check(memcmp("abce", "abcd", 4) > 0, 4);
  1595. X    check(memcmp("alph", "beta", 4) < 0, 5);
  1596. X    if (charsigned)                /* Sign-bit comparison. */
  1597. X        check(memcmp("a\203", "a\003", 2) < 0, 6);
  1598. X    else
  1599. X        check(memcmp("a\203", "a\003", 2) > 0, 6);
  1600. X    check(memcmp("abce", "abcd", 3) == 0, 7);    /* Count limited. */
  1601. X    check(memcmp("abc", "def", 0) == 0, 8);    /* Zero count. */
  1602. X
  1603. X    /*
  1604. X     * memchr
  1605. X     */
  1606. X    it = "memchr";
  1607. X    check(memchr("abcd", 'z', 4) == NULL, 1);    /* Not found. */
  1608. X    VOIDCAST strcpy(one, "abcd");
  1609. X    check(memchr(one, 'c', 4) == one+2, 2);    /* Basic test. */
  1610. X    check(memchr(one, 'd', 4) == one+3, 3);    /* End of string. */
  1611. X    check(memchr(one, 'a', 4) == one, 4);    /* Beginning. */
  1612. X    check(memchr(one, '\0', 5) == one+4, 5);    /* Finding NUL. */
  1613. X    VOIDCAST strcpy(one, "ababa");
  1614. X    check(memchr(one, 'b', 5) == one+1, 6);    /* Finding first. */
  1615. X    check(memchr(one, 'b', 0) == NULL, 7);    /* Zero count. */
  1616. X    check(memchr(one, 'a', 1) == one, 8);    /* Singleton case. */
  1617. X    VOIDCAST strcpy(one, "a\203b");
  1618. X    check(memchr(one, 0203, 3) == one+1, 9);    /* Unsignedness. */
  1619. X
  1620. X    /*
  1621. X     * memcpy
  1622. X     *
  1623. X     * Note that X3J11 says memcpy must work regardless of overlap.
  1624. X     * The SVID says it might fail.
  1625. X     */
  1626. X    it = "memcpy";
  1627. X    check(memcpy(one, "abc", 4) == one, 1);    /* Returned value. */
  1628. X    equal(one, "abc", 2);            /* Did the copy go right? */
  1629. X
  1630. X    VOIDCAST strcpy(one, "abcdefgh");
  1631. X    VOIDCAST memcpy(one+1, "xyz", 2);
  1632. X    equal(one, "axydefgh", 3);        /* Basic test. */
  1633. X
  1634. X    VOIDCAST strcpy(one, "abc");
  1635. X    VOIDCAST memcpy(one, "xyz", 0);
  1636. X    equal(one, "abc", 4);            /* Zero-length copy. */
  1637. X
  1638. X    VOIDCAST strcpy(one, "hi there");
  1639. X    VOIDCAST strcpy(two, "foo");
  1640. X    VOIDCAST memcpy(two, one, 9);
  1641. X    equal(two, "hi there", 5);        /* Just paranoia. */
  1642. X    equal(one, "hi there", 6);        /* Stomped on source? */
  1643. X
  1644. X    VOIDCAST strcpy(one, "abcdefgh");
  1645. X    VOIDCAST memcpy(one+1, one, 9);
  1646. X    equal(one, "aabcdefgh", 7);        /* Overlap, right-to-left. */
  1647. X
  1648. X    VOIDCAST strcpy(one, "abcdefgh");
  1649. X    VOIDCAST memcpy(one+1, one+2, 7);
  1650. X    equal(one, "acdefgh", 8);        /* Overlap, left-to-right. */
  1651. X
  1652. X    VOIDCAST strcpy(one, "abcdefgh");
  1653. X    VOIDCAST memcpy(one, one, 9);
  1654. X    equal(one, "abcdefgh", 9);        /* 100% overlap. */
  1655. X
  1656. X    /*
  1657. X     * memccpy - first test like memcpy, then the search part
  1658. X     *
  1659. X     * The SVID, the only place where memccpy is mentioned, says
  1660. X     * overlap might fail, so we don't try it.  Besides, it's hard
  1661. X     * to see the rationale for a non-left-to-right memccpy.
  1662. X     */
  1663. X    it = "memccpy";
  1664. X    check(memccpy(one, "abc", 'q', 4) == NULL, 1);    /* Returned value. */
  1665. X    equal(one, "abc", 2);            /* Did the copy go right? */
  1666. X
  1667. X    VOIDCAST strcpy(one, "abcdefgh");
  1668. X    VOIDCAST memccpy(one+1, "xyz", 'q', 2);
  1669. X    equal(one, "axydefgh", 3);        /* Basic test. */
  1670. X
  1671. X    VOIDCAST strcpy(one, "abc");
  1672. X    VOIDCAST memccpy(one, "xyz", 'q', 0);
  1673. X    equal(one, "abc", 4);            /* Zero-length copy. */
  1674. X
  1675. X    VOIDCAST strcpy(one, "hi there");
  1676. X    VOIDCAST strcpy(two, "foo");
  1677. X    VOIDCAST memccpy(two, one, 'q', 9);
  1678. X    equal(two, "hi there", 5);        /* Just paranoia. */
  1679. X    equal(one, "hi there", 6);        /* Stomped on source? */
  1680. X
  1681. X    VOIDCAST strcpy(one, "abcdefgh");
  1682. X    VOIDCAST strcpy(two, "horsefeathers");
  1683. X    check(memccpy(two, one, 'f', 9) == two+6, 7);    /* Returned value. */
  1684. X    equal(one, "abcdefgh", 8);        /* Source intact? */
  1685. X    equal(two, "abcdefeathers", 9);        /* Copy correct? */
  1686. X
  1687. X    VOIDCAST strcpy(one, "abcd");
  1688. X    VOIDCAST strcpy(two, "bumblebee");
  1689. X    check(memccpy(two, one, 'a', 4) == two+1, 10);    /* First char. */
  1690. X    equal(two, "aumblebee", 11);
  1691. X    check(memccpy(two, one, 'd', 4) == two+4, 12);    /* Last char. */
  1692. X    equal(two, "abcdlebee", 13);
  1693. X    VOIDCAST strcpy(one, "xyz");
  1694. X    check(memccpy(two, one, 'x', 1) == two+1, 14);    /* Singleton. */
  1695. X    equal(two, "xbcdlebee", 15);
  1696. X
  1697. X    /*
  1698. X     * memset
  1699. X     */
  1700. X    it = "memset";
  1701. X    VOIDCAST strcpy(one, "abcdefgh");
  1702. X    check(memset(one+1, 'x', 3) == one+1, 1);    /* Return value. */
  1703. X    equal(one, "axxxefgh", 2);        /* Basic test. */
  1704. X
  1705. X    VOIDCAST memset(one+2, 'y', 0);
  1706. X    equal(one, "axxxefgh", 3);        /* Zero-length set. */
  1707. X
  1708. X    VOIDCAST memset(one+5, 0, 1);
  1709. X    equal(one, "axxxe", 4);            /* Zero fill. */
  1710. X    equal(one+6, "gh", 5);            /* And the leftover. */
  1711. X
  1712. X    VOIDCAST memset(one+2, 010045, 1);
  1713. X    equal(one, "ax\045xe", 6);        /* Unsigned char convert. */
  1714. X
  1715. X    /*
  1716. X     * bcopy - much like memcpy
  1717. X     *
  1718. X     * Berklix manual is silent about overlap, so don't test it.
  1719. X     */
  1720. X    it = "bcopy";
  1721. X    VOIDCAST bcopy("abc", one, 4);
  1722. X    equal(one, "abc", 1);            /* Simple copy. */
  1723. X
  1724. X    VOIDCAST strcpy(one, "abcdefgh");
  1725. X    VOIDCAST bcopy("xyz", one+1, 2);
  1726. X    equal(one, "axydefgh", 2);        /* Basic test. */
  1727. X
  1728. X    VOIDCAST strcpy(one, "abc");
  1729. X    VOIDCAST bcopy("xyz", one, 0);
  1730. X    equal(one, "abc", 3);            /* Zero-length copy. */
  1731. X
  1732. X    VOIDCAST strcpy(one, "hi there");
  1733. X    VOIDCAST strcpy(two, "foo");
  1734. X    VOIDCAST bcopy(one, two, 9);
  1735. X    equal(two, "hi there", 4);        /* Just paranoia. */
  1736. X    equal(one, "hi there", 5);        /* Stomped on source? */
  1737. X
  1738. X    /*
  1739. X     * bzero
  1740. X     */
  1741. X    it = "bzero";
  1742. X    VOIDCAST strcpy(one, "abcdef");
  1743. X    bzero(one+2, 2);
  1744. X    equal(one, "ab", 1);            /* Basic test. */
  1745. X    equal(one+3, "", 2);
  1746. X    equal(one+4, "ef", 3);
  1747. X
  1748. X    VOIDCAST strcpy(one, "abcdef");
  1749. X    bzero(one+2, 0);
  1750. X    equal(one, "abcdef", 4);        /* Zero-length copy. */
  1751. X
  1752. X    /*
  1753. X     * bcmp - somewhat like memcmp
  1754. X     */
  1755. X    it = "bcmp";
  1756. X    check(bcmp("a", "a", 1) == 0, 1);    /* Identity. */
  1757. X    check(bcmp("abc", "abc", 3) == 0, 2);    /* Multicharacter. */
  1758. X    check(bcmp("abcd", "abce", 4) != 0, 3);    /* Honestly unequal. */
  1759. X    check(bcmp("abce", "abcd", 4) != 0, 4);
  1760. X    check(bcmp("alph", "beta", 4) != 0, 5);
  1761. X    check(bcmp("abce", "abcd", 3) == 0, 6);    /* Count limited. */
  1762. X    check(bcmp("abc", "def", 0) == 0, 8);    /* Zero count. */
  1763. X
  1764. X#ifdef ERR
  1765. X    /*
  1766. X     * strerror - VERY system-dependent
  1767. X     */
  1768. X    it = "strerror";
  1769. X    f = open("/", 1);    /* Should always fail. */
  1770. X    check(f < 0 && errno > 0 && errno < sys_nerr, 1);
  1771. X    equal(strerror(errno), sys_errlist[errno], 2);
  1772. X#ifdef UNIXERR
  1773. X    equal(strerror(errno), "Is a directory", 3);
  1774. X#endif
  1775. X#ifdef BERKERR
  1776. X    equal(strerror(errno), "Permission denied", 3);
  1777. X#endif
  1778. X#endif
  1779. X}
  1780. END_OF_FILE
  1781. if test 21125 -ne `wc -c <'testmem.c'`; then
  1782.     echo shar: \"'testmem.c'\" unpacked with wrong size!
  1783. fi
  1784. # end of 'testmem.c'
  1785. fi
  1786. echo shar: End of archive 5 \(of 5\).
  1787. cp /dev/null ark5isdone
  1788. MISSING=""
  1789. for I in 1 2 3 4 5 ; do
  1790.     if test ! -f ark${I}isdone ; then
  1791.     MISSING="${MISSING} ${I}"
  1792.     fi
  1793. done
  1794. if test "${MISSING}" = "" ; then
  1795.     echo You have unpacked all 5 archives.
  1796.     rm -f ark[1-9]isdone
  1797. else
  1798.     echo You still need to unpack the following archives:
  1799.     echo "        " ${MISSING}
  1800. fi
  1801. ##  End of shell archive.
  1802. exit 0
  1803.  
  1804. exit 0 # Just in case...
  1805.