home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / strings / part2 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  36.6 KB

  1. Subject: strings (2 of 3)
  2. Newsgroups: mod.sources
  3. Approved: jpn@panda.UUCP
  4.  
  5. Mod.sources:  Volume 4, Issue 111
  6. Submitted by: <talcott!wjh12!maynard!campbell>
  7.  
  8. #!/bin/sh
  9. # shar:    Shell Archiver
  10. #    Run the following text with /bin/sh to create:
  11. #    str2int.c
  12. #    strcat.c
  13. #    strchr.c
  14. #    strcmp.c
  15. #    strcpack.c
  16. #    strcpbrk.c
  17. #    strcpy.c
  18. #    strcspn.c
  19. #    strctrim.c
  20. #    strend.c
  21. #    strfield.c
  22. #    strfind.c
  23. #    strings.h
  24. #    strkey.c
  25. #    strlen.c
  26. #    strmov.c
  27. #    strncat.c
  28. #    strncmp.c
  29. #    strncpy.c
  30. #    strnend.c
  31. #    strnlen.c
  32. #    strnmov.c
  33. #    strnrev.c
  34. #    strnrpt.c
  35. #    strntran.c
  36. sed 's/^X//' << 'SHAR_EOF' > str2int.c
  37. X/*  File   : str2int.c
  38. X    Author : Richard A. O'Keefe
  39. X    Updated: 27 April 1984
  40. X    Defines: str2int(), atoi(), atol()
  41. X
  42. X    str2int(src, radix, lower, upper, &val)
  43. X    converts the string pointed to by src to an integer and stores it in
  44. X    val.  It skips leading spaces and tabs (but not newlines, formfeeds,
  45. X    backspaces), then it accepts an optional sign and a sequence of digits
  46. X    in the specified radix.  The result should satisfy lower <= *val <= upper.
  47. X    The result is a pointer to the first character after the number;
  48. X    trailing spaces will NOT be skipped.
  49. X
  50. X    If an error is detected, the result will be NullS, the value put
  51. X    in val will be 0, and errno will be set to
  52. X    EDOM    if there are no digits
  53. X    ERANGE    if the result would overflow or otherwise fail to lie
  54. X        within the specified bounds.
  55. X    Check that the bounds are right for your machine.
  56. X    This looks amazingly complicated for what you probably thought was an
  57. X    easy task.  Coping with integer overflow and the asymmetric range of
  58. X    twos complement machines is anything but easy.
  59. X
  60. X    So that users of atoi and atol can check whether an error occured,
  61. X    I have taken a wholly unprecedented step: errno is CLEARED if this
  62. X    call has no problems.
  63. X*/
  64. X
  65. X#include "strings.h"
  66. X#include "ctypes.h"
  67. X#include <errno.h>
  68. Xextern int errno;
  69. X
  70. X/*    CHECK THESE CONSTANTS FOR YOUR MACHINE!!!    */
  71. X
  72. X#if    pdp11
  73. X#   define    MaxInt      0x7fffL    /* int  = 16 bits */
  74. X#   define    MinInt      0x8000L
  75. X#   define    MaxLong 0x7fffffffL    /* long = 32 bits */
  76. X#   define    MinLong 0x80000000L
  77. X#else  !pdp11
  78. X#   define    MaxInt  0x7fffffffL    /* int  = 32 bits */
  79. X#   define    MinInt  0x80000000L
  80. X#   define    MaxLong 0x7fffffffL    /* long = 32 bits */
  81. X#   define    MinLong 0x80000000L
  82. X#endif    pdp11
  83. X
  84. X
  85. Xchar *str2int(src, radix, lower, upper, val)
  86. X    register char *src;
  87. X    register int radix;
  88. X    long lower, upper, *val;
  89. X    {
  90. X    int sign;        /* is number negative (+1) or positive (-1) */
  91. X    int n;            /* number of digits yet to be converted */
  92. X    long limit;        /* "largest" possible valid input */
  93. X    long scale;        /* the amount to multiply next digit by */
  94. X    long sofar;        /* the running value */
  95. X    register int d;        /* (negative of) next digit */
  96. X    char *answer;
  97. X
  98. X    /*  Make sure *val is sensible in case of error  */
  99. X
  100. X    *val = 0;
  101. X
  102. X    /*  Check that the radix is in the range 2..36  */
  103. X
  104. X    if (radix < 2 || radix > 36) {
  105. X        errno = EDOM;
  106. X        return NullS;
  107. X    }
  108. X
  109. X    /*  The basic problem is: how do we handle the conversion of
  110. X        a number without resorting to machine-specific code to
  111. X        check for overflow?  Obviously, we have to ensure that
  112. X        no calculation can overflow.  We are guaranteed that the
  113. X        "lower" and "upper" arguments are valid machine integers.
  114. X        On sign-and-magnitude, twos-complement, and ones-complement
  115. X        machines all, if +|n| is representable, so is -|n|, but on
  116. X        twos complement machines the converse is not true.  So the
  117. X        "maximum" representable number has a negative representative.
  118. X        Limit is set to min(-|lower|,-|upper|); this is the "largest"
  119. X        number we are concerned with.    */
  120. X
  121. X    /*  Calculate Limit using Scale as a scratch variable  */
  122. X
  123. X    if ((limit = lower) > 0) limit = -limit;
  124. X    if ((scale = upper) > 0) scale = -scale;
  125. X    if (scale < limit) limit = scale;
  126. X
  127. X    /*  Skip leading spaces and check for a sign.
  128. X        Note: because on a 2s complement machine MinLong is a valid
  129. X        integer but |MinLong| is not, we have to keep the current
  130. X        converted value (and the scale!) as *negative* numbers,
  131. X        so the sign is the opposite of what you might expect.
  132. X        Should the test in the loop be isspace(*src)?
  133. X    */
  134. X    while (*src == ' ' || *src == '\t') src++;
  135. X    sign = -1;
  136. X    if (*src == '+') src++; else
  137. X    if (*src == '-') src++, sign = 1;
  138. X
  139. X    /*  Check that there is at least one digit  */
  140. X
  141. X    if (_c2type[1+ *src] >= radix) {
  142. X        errno = EDOM;
  143. X        return NullS;
  144. X    }
  145. X
  146. X    /*  Skip leading zeros so that we never compute a power of radix
  147. X        in scale that we won't have a need for.  Otherwise sticking
  148. X        enough 0s in front of a number could cause the multiplication
  149. X        to overflow when it neededn't.
  150. X    */
  151. X    while (*src == '0') src++;
  152. X
  153. X    /*  Move over the remaining digits.  We have to convert from left
  154. X        to left in order to avoid overflow.  Answer is after last digit.
  155. X    */
  156. X    for (n = 0; _c2type[1+ *src++] < radix; n++) ;
  157. X    answer = --src;
  158. X
  159. X    /*  The invariant we want to maintain is that src is just
  160. X        to the right of n digits, we've converted k digits to
  161. X        sofar, scale = -radix**k, and scale < sofar < 0.  Now
  162. X        if the final number is to be within the original
  163. X        Limit, we must have (to the left)*scale+sofar >= Limit,
  164. X        or (to the left)*scale >= Limit-sofar, i.e. the digits
  165. X        to the left of src must form an integer <= (Limit-sofar)/(scale).
  166. X        In particular, this is true of the next digit.  In our
  167. X        incremental calculation of Limit,
  168. X
  169. X        IT IS VITAL that (-|N|)/(-|D|) = |N|/|D|
  170. X    */
  171. X
  172. X    for (sofar = 0, scale = -1; --n >= 0; ) {
  173. X        d = _c2type[1+ *--src];
  174. X        if (-d < limit) {
  175. X        errno = ERANGE;
  176. X        return NullS;
  177. X        }
  178. X        limit = (limit+d)/radix, sofar += d*scale;
  179. X        if (n != 0) scale *= radix;    /* watch out for overflow!!! */
  180. X    }
  181. X    /*  Now it might still happen that sofar = -32768 or its equivalent,
  182. X        so we can't just multiply by the sign and check that the result
  183. X        is in the range lower..upper.  All of this caution is a right
  184. X        pain in the neck.  If only there were a standard routine which
  185. X        says generate thus and such a signal on integer overflow...
  186. X        But not enough machines can do it *SIGH*.
  187. X    */
  188. X    if (sign < 0 && sofar < -MaxLong /* twos-complement problem */
  189. X    ||  (sofar*=sign) < lower || sofar > upper) {
  190. X        errno = ERANGE;
  191. X        return NullS;
  192. X    }
  193. X    *val = sofar;
  194. X    errno = 0;        /* indicate that all went well */
  195. X    return answer;
  196. X    }
  197. X
  198. X
  199. Xint atoi(src)
  200. X    char *src;
  201. X    {
  202. X    long val;
  203. X    str2int(src, 10, MinInt, MaxInt, &val);
  204. X    return (int)val;
  205. X    }
  206. X
  207. X
  208. Xlong atol(src)
  209. X    char *src;
  210. X    {
  211. X    long val;
  212. X    str2int(src, 10, MinLong, MaxLong, &val);
  213. X    return val;
  214. X    }
  215. X
  216. SHAR_EOF
  217. sed 's/^X//' << 'SHAR_EOF' > strcat.c
  218. X/*  File   : strcat.c
  219. X    Author : Richard A. O'Keefe.
  220. X    Updated: 10 April 1984
  221. X    Defines: strcat()
  222. X
  223. X    strcat(s, t) concatenates t on the end of s.  There  had  better  be
  224. X    enough  room  in  the  space s points to; strcat has no way to tell.
  225. X    Note that strcat has to search for the end of s, so if you are doing
  226. X    a lot of concatenating it may be better to use strmov, e.g.
  227. X    strmov(strmov(strmov(strmov(s,a),b),c),d)
  228. X    rather than
  229. X    strcat(strcat(strcat(strcpy(s,a),b),c),d).
  230. X    strcat returns the old value of s.
  231. X*/
  232. X
  233. X#include "strings.h"
  234. X
  235. Xchar *strcat(s, t)
  236. X    register char *s, *t;
  237. X    {
  238. X    char *save;
  239. X
  240. X    for (save = s; *s++; ) ;
  241. X    for (--s; *s++ = *t++; ) ;
  242. X    return save;
  243. X    }
  244. X
  245. SHAR_EOF
  246. sed 's/^X//' << 'SHAR_EOF' > strchr.c
  247. X/*  File   : strchr.c
  248. X    Author : Richard A. O'Keefe.
  249. X    Updated: 20 April 1984
  250. X    Defines: strchr(), index()
  251. X
  252. X    strchr(s, c) returns a pointer to the  first  place  in  s  where  c
  253. X    occurs,  or  NullS if c does not occur in s. This function is called
  254. X    index in V7 and 4.?bsd systems; while not ideal the name is  clearer
  255. X    than  strchr,  so index remains in strings.h as a macro.  NB: strchr
  256. X    looks for single characters,  not for sets or strings.   To find the
  257. X    NUL character which closes s, use strchr(s, '\0') or strend(s).  The
  258. X    parameter 'c' is declared 'int' so it will go in a register; if your
  259. X    C compiler is happy with register _char_ change it to that.
  260. X*/
  261. X
  262. X#include "strings.h"
  263. X
  264. Xchar *strchr(s, c)
  265. X    register _char_ *s;
  266. X    register int c;
  267. X    {
  268. X    for (;;) {
  269. X        if (*s == c) return s;
  270. X        if (!*s++) return NullS;
  271. X    }
  272. X    }
  273. X
  274. SHAR_EOF
  275. sed 's/^X//' << 'SHAR_EOF' > strcmp.c
  276. X/*  File   : strcmp.c
  277. X    Author : Richard A. O'Keefe.
  278. X    Updated: 10 April 1984
  279. X    Defines: strcmp()
  280. X
  281. X    strcmp(s, t) returns > 0, = 0,  or < 0  when s > t, s = t,  or s < t
  282. X    according  to  the  ordinary  lexicographical  order.   To  test for
  283. X    equality, the macro streql(s,t) is clearer than  !strcmp(s,t).  Note
  284. X    that  if the string contains characters outside the range 0..127 the
  285. X    result is machine-dependent; PDP-11s and  VAXen  use  signed  bytes,
  286. X    some other machines use unsigned bytes.
  287. X*/
  288. X
  289. X#include "strings.h"
  290. X
  291. Xint strcmp(s, t)
  292. X    register char *s, *t;
  293. X    {
  294. X    while (*s == *t++) if (!*s++) return 0;
  295. X    return s[0]-t[-1];
  296. X    }
  297. X
  298. SHAR_EOF
  299. sed 's/^X//' << 'SHAR_EOF' > strcpack.c
  300. X/*  File   : strcpack.c
  301. X    Author : Richard A. O'Keefe.
  302. X    Updated: 20 April 1984
  303. X    Defines: strcpack()
  304. X
  305. X    strcpack(dst, src, set, c)
  306. X    copies characters from src to dst, stopping when it finds a NUL.  If
  307. X    c is NUL, characters not in the set are not copied to dst.  If c  is
  308. X    not  NUL,  sequences  of  characters  not in the set are copied as a
  309. X    single c. strcpack is to strpack as strcspn is to strspn.  If your C
  310. X    compiler is happy with register _char_, change the declaration of c.
  311. X    The result is the address of the NUL byte that now terminates "dst".
  312. X    Note that dst may safely be the same as src.
  313. X*/
  314. X
  315. X#include "strings.h"
  316. X#include "_str2set.h"
  317. X
  318. Xchar *strcpack(dst, src, set, c)
  319. X    register _char_ *dst, *src;
  320. X    char *set;
  321. X    register int c;
  322. X    {
  323. X    register int chr;
  324. X
  325. X    _str2set(set);
  326. X    while (chr = *src++) {
  327. X        if (_set_vec[chr] != _set_ctr) {
  328. X        while ((chr = *src++) && _set_vec[chr] != _set_ctr) ;
  329. X        if (c) *dst++ = c;    /* 1. If you don't want trailing */
  330. X        if (!chr) break;    /* 2. things turned into "c", swap */
  331. X        }                /* lines 1 and 2. */
  332. X        *dst++ = chr;
  333. X    }
  334. X    *dst = 0;
  335. X    return dst;
  336. X    }
  337. X
  338. SHAR_EOF
  339. sed 's/^X//' << 'SHAR_EOF' > strcpbrk.c
  340. X/*  File   : strcpbrk.c
  341. X    Author : Richard A. O'Keefe.
  342. X    Updated: 20 April 1984
  343. X    Defines: strcpbrk()
  344. X
  345. X    strcpbrk(s1, s2) returns a pointer to the first character of s1 which
  346. X    does not occur in s2.  It is to strpbrk as strcspn is to strspn.   It
  347. X    relies on NUL never being in a set.
  348. X*/
  349. X
  350. X#include "strings.h"
  351. X#include "_str2set.h"
  352. X
  353. Xchar *strcpbrk(str, set)
  354. X    register _char_ *str;
  355. X    char *set;
  356. X    {
  357. X    _str2set(set);
  358. X    while (_set_vec[*str++] == _set_ctr);
  359. X    return *--str ? str : NullS;
  360. X    }
  361. X
  362. SHAR_EOF
  363. sed 's/^X//' << 'SHAR_EOF' > strcpy.c
  364. X/*  File   : strcpy.c
  365. X    Author : Richard A. O'Keefe.
  366. X    Updated: 20 April 1984
  367. X    Defines: strcpy()
  368. X
  369. X    strcpy(dst, src) copies all the characters  of  src  (including  the
  370. X    closing  NUL)  to dst, and returns the old value of dst.  Maybe this
  371. X    is useful for doing i = strlen(strcpy(dst, src)); I've always  found
  372. X    strmov handier.
  373. X*/
  374. X
  375. X#include "strings.h"
  376. X
  377. Xchar *strcpy(dst, src)
  378. X    register char *dst, *src;
  379. X    {
  380. X    char *save;
  381. X
  382. X    for (save = dst; *dst++ = *src++; ) ;
  383. X    return save;
  384. X    }
  385. X
  386. SHAR_EOF
  387. sed 's/^X//' << 'SHAR_EOF' > strcspn.c
  388. X/*  File   : strcspn.c
  389. X    Author : Richard A. O'Keefe.
  390. X    Updated: 11 April 1984
  391. X    Defines: strspn()
  392. X
  393. X    strcspn(s1, s2) returns the length  of  the  longest  prefix  of  s1
  394. X    consisting  entirely  of  characters  which  are  NOT  in s2 ("c" is
  395. X    "complement").  NUL is considered to be part  of  s2.   As  _str2set
  396. X    will never include NUL in a set, we have to check for it explicitly.
  397. X*/
  398. X
  399. X#include "strings.h"
  400. X#include "_str2set.h"
  401. X
  402. Xint strcspn(str, set)
  403. X    register _char_ *str;
  404. X    char *set;
  405. X    {
  406. X    register int L;
  407. X
  408. X    _str2set(set);
  409. X    for (L = 0; *str && _set_vec[*str++] != _set_ctr; L++) ;
  410. X    return L;
  411. X    }
  412. X
  413. SHAR_EOF
  414. sed 's/^X//' << 'SHAR_EOF' > strctrim.c
  415. X/*  File   : strctrim.c
  416. X    Author : Richard A. O'Keefe.
  417. X    Updated: 20 April 1984
  418. X    Defines: strctrim()
  419. X
  420. X    strctrim(dst, src, set, ends)
  421. X    copies src to dst, but will skip leading characters not in set if
  422. X    ends <= 0 and will skip trailing characters not in set if ends >= 0.
  423. X    Thus there are three cases:
  424. X    ends < 0 :    trim a prefix
  425. X    ends = 0 :    trim a prefix and a suffix both
  426. X    ends > 0 :    trim a suffix
  427. X    This is to strtrim as strcspn is to strspn.
  428. X*/
  429. X
  430. X#include "strings.h"
  431. X#include "_str2set.h"
  432. X
  433. Xchar *strctrim(dst, src, set, ends)
  434. X    register char *dst, *src;
  435. X    char *set;
  436. X    int ends;
  437. X    {
  438. X    _str2set(set);
  439. X    if (ends <= 0) {
  440. X        register int chr;
  441. X        while ((chr = *src++) && _set_vec[chr] != _set_ctr) ;
  442. X        --src;
  443. X    }
  444. X    if (ends >= 0) {
  445. X        register int chr;
  446. X        register char *save = dst;
  447. X        while (chr = *src++) {
  448. X        *dst++ = chr;
  449. X        if (_set_vec[chr] == _set_ctr) save = dst;
  450. X        }
  451. X        dst = save, *dst = NUL;
  452. X    } else {
  453. X        while (*dst++ = *src++) ;
  454. X        --dst;
  455. X    }
  456. X    return dst;
  457. X    }
  458. X
  459. SHAR_EOF
  460. sed 's/^X//' << 'SHAR_EOF' > strend.c
  461. X/*  File   : strend.c
  462. X    Author : Richard A. O'Keefe.
  463. X    Updated: 23 April 1984
  464. X    Defines: strend()
  465. X
  466. X    strend(s) returns a character pointer to the NUL which ends s.  That
  467. X    is,  strend(s)-s  ==  strlen(s). This is useful for adding things at
  468. X    the end of strings.  It is redundant, because  strchr(s,'\0')  could
  469. X    be used instead, but this is clearer and faster.
  470. X    Beware: the asm version works only if strlen(s) < 65535.
  471. X*/
  472. X
  473. X#include "strings.h"
  474. X
  475. X#if    VaxAsm
  476. X
  477. Xchar *strend(s)
  478. X    char *s;
  479. X    {
  480. X    asm("locc $0,$65535,*4(ap)");
  481. X    asm("movl r1,r0");
  482. X    }
  483. X
  484. X#else  ~VaxAsm
  485. X
  486. Xchar *strend(s)
  487. X    register char *s;
  488. X    {
  489. X    while (*s++);
  490. X    return s-1;
  491. X    }
  492. X
  493. X#endif    VaxAsm
  494. X
  495. SHAR_EOF
  496. sed 's/^X//' << 'SHAR_EOF' > strfield.c
  497. X/*  File   : strfield.c
  498. X    Author : Richard A. O'Keefe.
  499. X    Updated: 21 April 1984
  500. X    Defines: strfield()
  501. X
  502. X    strfield(src, fields, chars, blanks, tabch)
  503. X    is based on the key specifications of the sort(1) command.
  504. X
  505. X    tabch corresponds to 'x' in -t'x'.  If it is NUL, a field
  506. X    is leading layout (spaces, tabs &c) followed by at least
  507. X    one non-layout character, and is terminated by the next
  508. X    layout character or NUL.  If it is not NUL, a field is
  509. X    terminated by tabch or NUL.
  510. X
  511. X    fields is the number of fields to skip over.  It corresponds
  512. X    to m in -m.n or +m.n .  There must be at least this many
  513. X    fields, and only the last may be terminated by NUL.
  514. X
  515. X    chars is the number of characters to skip after the fields
  516. X    have been skipped.  At least this many non-NUL characters
  517. X    must remain after the fields have been skipped.  Note that
  518. X    it is entirely possible for this skip to cross one or more
  519. X    field boundaries.  This corresponds to n in +m.n or -m.n .
  520. X
  521. X    Finally, if blanks is not 0, any layout characters will be
  522. X    skipped.  There need not be any.  This corresponds to the
  523. X    letter b in +2.0b or -0.4b .
  524. X
  525. X    The result is NullS if the source ran out of fields or ran
  526. X    out of chars.  Otherwise it is a pointer to the first
  527. X    character of src which was not skipped.  It is quite possible
  528. X    for this character to be the terminating NUL.
  529. X
  530. X    Example:
  531. X    to skip to the user-id field of /etc/passwd:
  532. X        user_id = strfield(line, 2, 0, 0, ':');
  533. X
  534. X    to check whether "line" is at least 27 characters long:
  535. X        if (strfield(line, 0, 27, 0, 0)) then-it-is;
  536. X
  537. X    to select the third blank-delimited field in a line:
  538. X        head = strfield(line, 2, 0, 1, 0);
  539. X        tail = strfield(head, 1, 0, 0, 0);
  540. X        (* the field is the tail-head characters starting at head *)
  541. X
  542. X    It's not a bug, it's a feature: "layout" means any ASCII character
  543. X    in the range '\1' .. ' ', including '\n', '\f' and so on.
  544. X*/
  545. X
  546. X#include "strings.h"
  547. X
  548. Xchar *strfield(src, fields, chars, blanks, tabch)
  549. X    register char *src;
  550. X    int fields, chars, blanks, tabch;
  551. X    {
  552. X    if (tabch <= 0) {
  553. X        while (--fields >= 0) {
  554. X        while (*src <= ' ') if (!*src++) return NullS;
  555. X        while (*++src > ' ') ;
  556. X        }
  557. X    } else
  558. X    if (fields > 0) {
  559. X        do if (!*src) return NullS;
  560. X        while (*src++ != tabch || --fields > 0);
  561. X    }
  562. X    while (--chars >= 0) if (!*src++) return NullS;
  563. X    if (blanks) while (*src && *src++ <= ' ') ;
  564. X    return src;
  565. X    }
  566. SHAR_EOF
  567. sed 's/^X//' << 'SHAR_EOF' > strfind.c
  568. X/*  File   : strfind.c
  569. X    Author : Richard A. O'Keefe.
  570. X    Updated: 23 April 1984
  571. X    Defines: strfind()
  572. X
  573. X    strfind(src, pat) looks for an instance of pat in src.  pat is not a
  574. X    regex(3) pattern, it is a literal string which must be matched exactly.
  575. X    As a special hack to prevent infinite loops, the empty string will be
  576. X    found just once, at the far end of src.  This is hard to justify.  The
  577. X    result is a pointer to the first character AFTER the located instance,
  578. X    or NullS if pat does not occur in src.  The reason for returning the
  579. X    place after the instance is so that you can count the number of instances
  580. X    by writing
  581. X    _str2pat(ToBeFound);
  582. X    for (p = src, n = 0; p = strfind(p, NullS); n++) ;
  583. X    If you want a pointer to the first character of the instance, it is up
  584. X    to you to subtract strlen(pat).
  585. X
  586. X    If there were a strnfind it wouldn't have to look at all the characters
  587. X    of src, this version does otherwise it could miss the closing NUL.
  588. X*/
  589. X
  590. X#include "strings.h"
  591. X#include "_str2pat.h"
  592. X
  593. Xchar *strfind(src, pat)
  594. X    char *src, *pat;
  595. X    {
  596. X    register char *s, *p;
  597. X    register int c, lastch;
  598. X
  599. X    pat = _str2pat(pat);
  600. X    if (_pat_lim < 0) {
  601. X        for (s = src; *s++; ) ;
  602. X        return s-1;
  603. X    }
  604. X    /*  The pattern is non-empty  */
  605. X    for (c = _pat_lim, lastch = pat[c]; ; c = _pat_vec[c]) {
  606. X        for (s = src; --c >= 0; )
  607. X        if (!*s++) return NullS;
  608. X        c = *s, src = s;
  609. X        if (c == lastch) {
  610. X        for (s -= _pat_lim, p = pat; *p; )
  611. X            if (*s++ != *p++) goto not_yet;
  612. X        return s;
  613. Xnot_yet:;   }
  614. X    }
  615. X    }
  616. X
  617. SHAR_EOF
  618. sed 's/^X//' << 'SHAR_EOF' > strings.h
  619. X/*  File   : strings.h
  620. X    Author : Richard A. O'Keefe.
  621. X    Updated: 1 June 1984
  622. X    Purpose: Header file for the "string(3C)" package.
  623. X
  624. X    All  the  routines  in  this  package  are  the  original  work   of
  625. X    R.A.O'Keefe.   Any  resemblance  between  them  and  any routines in
  626. X    licensed software is due entirely  to  these  routines  having  been
  627. X    written  using the "man 3 string" UNIX manual page, or in some cases
  628. X    the "man 1 sort" manual page as a specification.  See the READ-ME to
  629. X    find the conditions under which these routines may be used & copied.
  630. X*/
  631. X
  632. X#ifndef    NullS
  633. X#define    NullS    (char*)0
  634. X#define NUL    '\0'
  635. X
  636. X/*  MAKE SURE THE RIGHT VERSION OF THE FOLLOWING MACRO IS INSTALLED!  */
  637. X
  638. X#if    vax | pdp11 | m68000 | perq
  639. X#define CharsAreSigned 1            /* default is unsigned */
  640. X#endif    vax | pdp11 | m68000 | perq
  641. X
  642. X#if    CharsAreSigned
  643. X#define    int2char(i)    (((i)<<((sizeof (int) -1)*8))>>((sizeof (int) -1)*8))
  644. X#else  !CharsAreSigned
  645. X#define    int2char(i)    ((i)&255)
  646. X#endif    CharsAreSigned
  647. X/*  If characters are signed, but the above doesn't work,
  648. X    try    ((127-(255&~(i)))^(-128))
  649. X*/
  650. X
  651. X#ifndef    _AlphabetSize
  652. X#define    _AlphabetSize    128
  653. X#endif
  654. X
  655. X#if    _AlphabetSize == 128
  656. Xtypedef    char _char_;
  657. X#endif
  658. X#if    _AlphabetSize == 256
  659. Xtypedef    unsigned char _char_;
  660. X#endif
  661. X
  662. X/*  NullS is the "nil" character  pointer.   NULL  would  work  in  most
  663. X    cases,  but  in  some  C  compilers  pointers and integers may be of
  664. X    different sizes, so it is handy to have a nil pointer that  one  can
  665. X    pass to a function as well as compare pointers against.
  666. X
  667. X    NUL is the ASCII name for the character with code 0.  Its use to end
  668. X    strings is a convention of the C programming language.  There are in
  669. X    fact three different end of string conventions supported by routines
  670. X    in this package:
  671. X    str<opn>    : end at the first NUL character
  672. X    strn<opn>    : end at the first NUL character, or when the
  673. X              extra "len" parameter runs out.
  674. X    mem<opn>,b<opn>    : length determined solely by "len" parameter.
  675. X    Unfortunately, the VAX hardware only supports the last convention, a
  676. X    pity really.  Fortran 77 users BEWARE: Fortran 77's convention is an
  677. X    entirely different one, and there are NO routines in this package as
  678. X    yet which support it.  (But see section 3F of the 4.2 BSD manual.)
  679. X
  680. X    The routines which move characters around don't  care  whether  they
  681. X    are  signed or unsigned.  But the routines which compare a character
  682. X    in a string with an argument, or use a character from a string as an
  683. X    index into an array, do care.  I have assumed that
  684. X    _AlphabetSize = 128 => only 0..127 appear in strings
  685. X    _AlphabetSize = 256 => only 0..255 appear in strings
  686. X    The files _str2set.c and _str2map.c declare character vectors  using
  687. X    this  size.  If you don't have unsigned char, your machine may treat
  688. X    char as unsigned anyway.
  689. X
  690. X    Some string operations (*cmp, *chr) are explicitly defined in various
  691. X    UNIX manuals to use "native" comparison, so I have not used _char_ in
  692. X    them.  This package is meant to be compatible, not rational!
  693. X*/
  694. X
  695. Xextern    char    *strcat(/*char^,char^*/);
  696. Xextern    char    *strncat(/*char^,char^,int*/);
  697. X
  698. Xextern    int    strcmp(/*char^,char^*/);
  699. Xextern    int    strncmp(/*char^,char^,int*/);
  700. X
  701. X#define streql    !strcmp
  702. X#define strneql    !strncmp    /* (str-N)-eql not str-(neq-l)! */
  703. X
  704. Xextern    char    *strcpy(/*char^,char^*/);
  705. Xextern    char    *strncpy(/*char^,char^,int*/);
  706. X
  707. Xextern    int    strlen(/*char^*/);
  708. Xextern    int    strnlen(/*char^,int*/);
  709. X
  710. Xextern    char    *strchr(/*char^,_char_*/);
  711. Xextern    char    *strrchr(/*char^,_char_*/);
  712. X#define    index    strchr
  713. X#define    rindex    strrchr
  714. X
  715. Xextern    char    *strmov(/*char^,char^*/);
  716. Xextern    char    *strnmov(/*char^,char^,int*/);
  717. X
  718. Xextern    void    strrev(/*char^,char^*/);
  719. Xextern    void    strnrev(/*char^,char^,int*/);
  720. X
  721. Xextern    char    *strend(/*char^*/);
  722. Xextern    char    *strnend(/*char^*/);
  723. X
  724. Xextern    char    *strpbrk(/*char^,char^*/);
  725. Xextern    char    *strcpbrk(/*char^,char^*/);
  726. X
  727. Xextern    int    strspn(/*char^,char^*/);
  728. Xextern    int    strcspn(/*char^,char^*/);
  729. X
  730. Xextern    char    *strtok(/*char^,char^*/);
  731. Xextern    void    istrtok(/*char^,char^*/);
  732. X
  733. Xextern    char    *strpack(/*_char_^,_char_^,char^,int*/);
  734. Xextern    char    *strcpack(/*_char_^,_char_^,char^,int*/);
  735. X
  736. Xextern    int    strrpt(/*char^,char^,int*/);
  737. Xextern    int    strnrpt(/*char^,int,char^,int*/);
  738. X
  739. Xextern    void    strtrans(/*_char_^,_char_^,_char_^,_char_^*/);
  740. Xextern    void    strntrans(/*_char_^,_char_^,int,_char_^,_char_^*/);
  741. X
  742. Xextern    char    *strtrim(/*char^,char^,char^,int*/);
  743. Xextern    char    *strctrim(/*char^,char^,char^,int*/);
  744. X
  745. Xextern    char    *strfield(/*char^,int,int,int,int*/);
  746. Xextern    char    *strkey(/*char^,char^,char^,char^*/);
  747. X
  748. Xextern    char    *strfind(/*char^,char^*/);
  749. Xextern    char    *strrepl(/*char^,char^,char^,char^*/);
  750. X
  751. Xextern    void    bcopy(/*char^,char^,int*/);
  752. Xextern    void    bmove(/*char^,char^,int*/);
  753. X
  754. Xextern    void    bfill(/*char^,int,char*/);
  755. Xextern    void    bzero(/*char^,int*/);
  756. X
  757. Xextern    int    bcmp(/*char^,char^,int*/);
  758. X#define    beql    !bcmp
  759. X
  760. Xextern    int    ffs(/*int*/);
  761. Xextern    int    ffc(/*int*/);
  762. X
  763. Xextern    char    *substr(/*char^,char^,int,int*/);
  764. X
  765. Xextern    char    *strxcat(/*VARARGS*/);
  766. Xextern    char    *strxcpy(/*VARARGS*/);
  767. Xextern    char    *strxmov(/*VARARGS*/);
  768. X
  769. Xextern    char    *strxncat(/*VARARGS*/);
  770. Xextern    char    *strxncpy(/*VARARGS*/);
  771. Xextern    char    *strxnmov(/*VARARGS*/);
  772. X
  773. X#endif    NullS
  774. X
  775. X#ifndef    memeql
  776. X#include "memory.h"
  777. X#endif    memeql
  778. X
  779. SHAR_EOF
  780. sed 's/^X//' << 'SHAR_EOF' > strkey.c
  781. X/*  File   : strkey.c
  782. X    Author : Richard A. O'Keefe.
  783. X    Updated: 20 April 1984
  784. X    Defines: strkey()
  785. X
  786. X    strkey(dst, head, tail, options)
  787. X    copies tail-head characters from head to dst according to the
  788. X    options.  If tail is NullS, it copies up to the terminating
  789. X    NUL of head.  This function is meant for doing comparisons as
  790. X    by sort(1).  The options are thus a string of characters
  791. X    taken from "bdfin".  In case the options came from somewhere
  792. X    else other letters are ignored.
  793. X
  794. X    -b: leading layout characters are not copied.
  795. X
  796. X    -d: only letters, digits, and blanks are copied.
  797. X    -i: only graphic characters (32..126) are copied.
  798. X    -n: a numeric string is copied.
  799. X        These options are incompatible, and the last is taken.
  800. X
  801. X    -f: upper case letters are copied as lower case.
  802. X
  803. X    The question of what to do with a numeric string is  an  interesting
  804. X    one,  and  I  don't claim that this is a brilliant answer.  However,
  805. X    the solution used here does mean that the  caller  can  compare  two
  806. X    strings as strings without needing to know that they are numeric.  A
  807. X    number  is  copied  as  <sign><9  digits>.<remaining  digits>, where
  808. X    <sign> is '-' for a negative number and '0' for a  positive  number.
  809. X    The magic number 9 is defined to be DigitMagic.
  810. X
  811. X    The idea is that to compare two lines using the keys
  812. X    -tx +m1.n1<flags> -m2.n2
  813. X    you do
  814. X    h1 = strfield(line1, m1, n1, 0, 'x');
  815. X    t1 = strfield(h1, 1, 0, 0, 'x');
  816. X    strkey(buff1, h1, t1, "flags");
  817. X    h2 = strfield(line2, m2, n2, 0, 'x');
  818. X    t2 = strfield(h2, 1, 0, 0, 'x');
  819. X    strkey(buff2, h2, t2, "flags");
  820. X    ... strcmp(buff1, buff2) ...
  821. X
  822. X    The point of all this, of course, is to make it easier to write new
  823. X    utilities which are compatible with sort(1) than ones which are not.
  824. X*/
  825. X
  826. X#include "strings.h"
  827. X
  828. X#define    DigitMagic 9
  829. X
  830. Xchar *strkey(dst, head, tail, flags)
  831. X    register char *dst, *head, *tail;
  832. X    char *flags;
  833. X    {
  834. X    register int c;
  835. X    int b = 0;    /* b option? */
  836. X    int f = 0;    /* f option? */
  837. X    int k = 0;    /* 3->n, 2->d, 1->i, 0->none of them */
  838. X
  839. X    while (*flags) switch (*flags++|32) {
  840. X        case 'b':    b++;    break;
  841. X        case 'f':    f++;    break;
  842. X        case 'i':    k = 1;    break;
  843. X        case 'd':    k = 2;    break;
  844. X        case 'n':    k = 3;    break;
  845. X        default : /*ignore*/break;
  846. X    }
  847. X    flags = dst;    /* save return value */
  848. X
  849. X    if (tail == NullS) for (tail = head; *tail; tail++) ;
  850. X
  851. X    if (b) while (head != tail && *head <= ' ') head++;
  852. X
  853. X    switch (k) {
  854. X        case 0:
  855. X        if (f) {
  856. X            while (head != tail) {
  857. X            c = *head++;
  858. X            if (c >= 'A' && c <= 'Z') c |= 32;
  859. X            *dst++ = c;
  860. X            }
  861. X        } else {
  862. X            while (head != tail) *dst++ = *head++;
  863. X        }
  864. X        break;
  865. X        case 1:
  866. X        if (f) {
  867. X            while (head != tail) {
  868. X            c = *head++;
  869. X            if (c >= 32 && c <= 126) {
  870. X                if (c >= 'A' && c <= 'Z') c |= 32;
  871. X                *dst++ = c;
  872. X            }
  873. X            }
  874. X        } else {
  875. X            while (head != tail) {
  876. X            c = *head++;
  877. X            if (c >= 32 && c <= 126) *dst++ = c;
  878. X            }
  879. X        }
  880. X        break;
  881. X        case 2:
  882. X        if (f) f = 32;
  883. X        while (head != tail) {
  884. X            c = *head++;
  885. X            if (c >= '0' && c <= '9' ||  c >= 'a' && c <= 'z' || c == ' ') {
  886. X            *dst++ = c;
  887. X            } else
  888. X            if (c >= 'A' && c <= 'Z') {
  889. X            *dst++ = c|f;
  890. X            }
  891. X        }
  892. X        break;
  893. X        case 3:
  894. X        if (*head == '-' && head != tail) {
  895. X            *dst++ = *head++;
  896. X            head++;
  897. X        } else {
  898. X            *dst++ = '0';
  899. X        }
  900. X        b = 0;
  901. X        while (head != tail) {
  902. X            c = *head;
  903. X            if (c < '0' || c > '9') break;
  904. X            b++, head++;
  905. X        }
  906. X        f = DigitMagic-b;
  907. X        while (--f >= 0) *dst++ = '0';
  908. X        head -= b;
  909. X        while (--b >= 0) *dst++ = *head++;
  910. X        if (*head == '.' && head != tail) {
  911. X            *dst++ = *head++;
  912. X            while (head != tail) {
  913. X            c = *head++;
  914. X            if (c < '0' || c > '9') break;
  915. X            *dst++ = c;
  916. X            }
  917. X            /* now remove trailing 0s and possibly the '.' as well */
  918. X            while (*--dst == '0') ;
  919. X            if (*dst != '.') dst++;
  920. X        }
  921. X        break;
  922. X    }
  923. X    *dst = NUL;
  924. X    return flags;    /* saved initial value of dst */
  925. X    }
  926. X
  927. SHAR_EOF
  928. sed 's/^X//' << 'SHAR_EOF' > strlen.c
  929. X/*  File   : strlen.c
  930. X    Author : Richard A. O'Keefe.
  931. X    Updated: 23 April 1984
  932. X    Defines: strlen()
  933. X
  934. X    strlen(s) returns the number of characters in s, that is, the number
  935. X    of non-NUL characters found before the closing NULEosCh.  Note: some
  936. X    non-standard C compilers for 32-bit machines take int to be 16 bits,
  937. X    either put up with short strings or change int  to  long  throughout
  938. X    this package.  Better yet, BOYCOTT such shoddy compilers.
  939. X    Beware: the asm version works only if strlen(s) < 65536.
  940. X*/
  941. X
  942. X#include "strings.h"
  943. X
  944. X#if    VaxAsm
  945. X
  946. Xint strlen(s)
  947. X    char *s;
  948. X    {
  949. X    asm("locc  $0,$65535,*4(ap)");
  950. X    asm("subl3 r0,$65535,r0");
  951. X    }
  952. X
  953. X#else  ~VaxAsm
  954. X
  955. Xint strlen(s)
  956. X    register char *s;
  957. X    {
  958. X    register int L;
  959. X
  960. X    for (L = 0; *s++; L++) ;
  961. X    return L;
  962. X    }
  963. X
  964. X#endif    VaxAsm
  965. X
  966. SHAR_EOF
  967. sed 's/^X//' << 'SHAR_EOF' > strmov.c
  968. X/*  File   : strmov.c
  969. X    Author : Richard A. O'Keefe.
  970. X    Updated: 20 April 1984
  971. X    Defines: strmov()
  972. X
  973. X    strmov(dst, src) moves all the  characters  of  src  (including  the
  974. X    closing NUL) to dst, and returns a pointer to the new closing NUL in
  975. X    dst.   The similar UNIX routine strcpy returns the old value of dst,
  976. X    which I have never found useful.  strmov(strmov(dst,a),b) moves a//b
  977. X    into dst, which seems useful.
  978. X*/
  979. X
  980. X#include "strings.h"
  981. X
  982. Xchar *strmov(dst, src)
  983. X    register char *dst, *src;
  984. X    {
  985. X    while (*dst++ = *src++) ;
  986. X    return dst-1;
  987. X    }
  988. X
  989. SHAR_EOF
  990. sed 's/^X//' << 'SHAR_EOF' > strncat.c
  991. X/*  File   : strncat.c
  992. X    Author : Richard A. O'Keefe.
  993. X    Updated: 20 April 1984
  994. X    Defines: strncat()
  995. X
  996. X    strncat(dst, src, n)  copies up to n characters of src to the end of
  997. X    dst.   As with strcat, it has to search for the end of dst.  Even if
  998. X    it abandons src early because n runs out it  will  still  close  dst
  999. X    with a NUL.  See also strnmov.
  1000. X*/
  1001. X
  1002. X#include "strings.h"
  1003. X
  1004. Xchar *strncat(dst, src, n)
  1005. X    register char *dst, *src;
  1006. X    register int n;
  1007. X    {
  1008. X    char *save;
  1009. X
  1010. X    for (save = dst; *dst++; ) ;
  1011. X    for (--dst; --n >= 0; )
  1012. X        if (!(*dst++ = *src++)) return save;
  1013. X    *dst = NUL;
  1014. X    return save;
  1015. X    }
  1016. X
  1017. SHAR_EOF
  1018. sed 's/^X//' << 'SHAR_EOF' > strncmp.c
  1019. X/*  File   : strncmp.c
  1020. X    Author : Richard A. O'Keefe.
  1021. X    Updated: 10 April 1984
  1022. X    Defines: strncmp()
  1023. X
  1024. X    strncmp(s, t, n) compares the first n characters of s and t.
  1025. X    If they are the same in the first n characters it returns 0,
  1026. X    otherwise it returns the same value as strcmp(s, t) would.
  1027. X*/
  1028. X
  1029. X#include "strings.h"
  1030. X
  1031. Xint strncmp(s, t, n)
  1032. X    register char *s, *t;
  1033. X    register int n;
  1034. X    {
  1035. X    while (--n >= 0) {
  1036. X        if (*s != *t++) return s[0]-t[-1];
  1037. X        if (!*s++) return 0;
  1038. X    }
  1039. X    return 0;
  1040. X     }
  1041. X
  1042. SHAR_EOF
  1043. sed 's/^X//' << 'SHAR_EOF' > strncpy.c
  1044. X/*  File   : strncpy.c
  1045. X    Author : Richard A. O'Keefe.
  1046. X    Updated: 20 April 1984
  1047. X    Defines: strncpy()
  1048. X
  1049. X    strncpy(dst, src, n) copies up to n characters of src  to  dst.   It
  1050. X    will  pad  dst  on the right with NUL or truncate it as necessary to
  1051. X    ensure that n characters exactly are transferred.   It  returns  the
  1052. X    old value of dst as strcpy does.
  1053. X*/
  1054. X
  1055. X#include "strings.h"
  1056. X
  1057. Xchar *strncpy(dst, src, n)
  1058. X    register char *dst, *src;
  1059. X    register int n;
  1060. X    {
  1061. X    char *save;
  1062. X
  1063. X    for (save = dst;  --n >= 0; ) {
  1064. X        if (!(*dst++ = *src++)) {
  1065. X        while (--n >= 0) *dst++ = NUL;
  1066. X        return save;
  1067. X        }
  1068. X    }
  1069. X    return save;
  1070. X    }
  1071. X
  1072. SHAR_EOF
  1073. sed 's/^X//' << 'SHAR_EOF' > strnend.c
  1074. X/*  File   : strnend.c
  1075. X    Author : Richard A. O'Keefe.
  1076. X    Updated: 1 June 1984
  1077. X    Defines: strnend()
  1078. X
  1079. X    strnend(src, len)
  1080. X    returns a pointer to just after the end of the string src, which is
  1081. X    terminated by a NUL character, or by exhaustion of the length bound
  1082. X    len.  That is, strnend(s,L)-s = strnlen(s,L).  s+strnlen(s,L) could
  1083. X    of course be used instead, but this is sometimes clearer.
  1084. X    Beware: the asm version works only if 0 <= len < 65535.
  1085. X*/
  1086. X
  1087. X#include "strings.h"
  1088. X
  1089. X#if    VaxAsm
  1090. X
  1091. Xchar *strnend(src, len)
  1092. X    char *src;
  1093. X    int len;
  1094. X    {
  1095. X    asm("locc $0,8(ap),*4(ap)");
  1096. X    asm("movl r1,r0");
  1097. X    }
  1098. X
  1099. X#else  ~VaxAsm
  1100. X
  1101. Xchar *strnend(src, len)
  1102. X    register char *src;
  1103. X    register int len;
  1104. X    {
  1105. X    while (--len >= 0 && *src) src++;
  1106. X    return src;
  1107. X    }
  1108. X
  1109. X#endif    VaxAsm
  1110. X
  1111. SHAR_EOF
  1112. sed 's/^X//' << 'SHAR_EOF' > strnlen.c
  1113. X/*  File   : strnlen.c
  1114. X    Author : Richard A. O'Keefe.
  1115. X    Updated: 10 April 1984
  1116. X    Defines: strnlen()
  1117. X
  1118. X    strnlen(src, len)
  1119. X    returns the number of characters up to the first NUL in src, or len,
  1120. X    whichever is smaller.  This is the same as strnend(src,len)-src.
  1121. X
  1122. X    Beware: the VaxAsm version only works for 0 <= len < 65535.
  1123. X*/
  1124. X
  1125. X#include "strings.h"
  1126. X
  1127. X#if    VaxAsm
  1128. X
  1129. Xint strnlen(src, len)
  1130. X    char *src;
  1131. X    int len;
  1132. X    {
  1133. X    asm("locc $0,8(ap),*4(ap)");
  1134. X    asm("subl3 4(ap),r1,r0");
  1135. X    }
  1136. X
  1137. X#else  ~VaxAsm
  1138. X
  1139. Xint strnlen(s, n)
  1140. X    register char *s;
  1141. X    register int n;
  1142. X    {
  1143. X    register int L;
  1144. X
  1145. X    for (L = 0; --n >= 0 && *s++; L++) ;
  1146. X    return L;
  1147. X    }
  1148. X
  1149. X#endif    VaxAsm
  1150. X
  1151. SHAR_EOF
  1152. sed 's/^X//' << 'SHAR_EOF' > strnmov.c
  1153. X/*  File   : strnmov.c
  1154. X    Author : Richard A. O'Keefe.
  1155. X    Updated: 20 April 1984
  1156. X    Defines: strnmov()
  1157. X
  1158. X    strnmov(dst, src, n) moves up to n characters of  src  to  dst.   It
  1159. X    always  moves  exactly n characters to dst; if src is shorter than n
  1160. X    characters dst will be extended on the right with NULs, while if src
  1161. X    is longer than n characters dst will be a truncated version  of  src
  1162. X    and  will  not  have  a closing NUL.  The result is a pointer to the
  1163. X    first NUL in dst, or is dst+n if dst was truncated.
  1164. X*/
  1165. X
  1166. X#include "strings.h"
  1167. X
  1168. Xchar *strnmov(dst, src, n)
  1169. X    register char *dst, *src;
  1170. X    register int n;
  1171. X    {
  1172. X    while (--n >= 0) {
  1173. X        if (!(*dst++ = *src++)) {
  1174. X        src = dst-1;
  1175. X        while (--n >= 0) *dst++ = NUL;
  1176. X        return src;
  1177. X        }
  1178. X    }
  1179. X    return dst;
  1180. X    }
  1181. X
  1182. SHAR_EOF
  1183. sed 's/^X//' << 'SHAR_EOF' > strnrev.c
  1184. X/*  File   : strnrev.c
  1185. X    Author : Richard A. O'Keefe.
  1186. X    Updated: 1 June 1984
  1187. X    Defines: strnrev()
  1188. X
  1189. X    strnrev(dst, src, len)
  1190. X    copies all the characters of src to dst, in REVERSE order.  If src
  1191. X    was terminated by a NUL character, so will dst be, otherwise dst &
  1192. X    src are both exactly len non-NUL characters long.  This returns no
  1193. X    result.  It is to strrev as strncpy is to strcpy.
  1194. X
  1195. X    Note: this function is perfectly happy to reverse a string into the
  1196. X    same place, strnrev(x, x, L) will work.
  1197. X    It will not work for partially overlapping source and destination.
  1198. X*/
  1199. X
  1200. X#include "strings.h"
  1201. X
  1202. Xvoid strnrev(dsta, srca, len)
  1203. X    register char *dsta, *srca;
  1204. X    register int len;
  1205. X    {
  1206. X    register char *dstz, *srcz;
  1207. X    register int t;
  1208. X    /*  On a machine which doesn't supply 6 register variables,
  1209. X        you could #define t len, as the two variables don't overlap.
  1210. X    */
  1211. X
  1212. X    for (srcz = srca; --len >= 0 && *srcz; srcz++) ;
  1213. X    dstz = dsta+(srcz-srca);
  1214. X    /*  If srcz was stopped by len running out, it points just after
  1215. X        the last character of the source string, and it and dstz are
  1216. X        just right.  Otherwise, it was stopped by hitting NUL, and is
  1217. X        in the right place, but dstz should get a NUL as well.
  1218. X    */
  1219. X    if (len >= 0) *dstz = NUL;
  1220. X    /*  That was the very last use of len  */
  1221. X    while (srcz > srca) {
  1222. X        t = *--srcz;
  1223. X        *--dstz = *srca++;
  1224. X        *dsta++ = t;
  1225. X    }
  1226. X    }
  1227. X
  1228. SHAR_EOF
  1229. sed 's/^X//' << 'SHAR_EOF' > strnrpt.c
  1230. X/*  File   : strnrpt.c
  1231. X    Author : Richard A. O'Keefe.
  1232. X    Updated: 20 April 1984
  1233. X    Defines: strnrpt()
  1234. X
  1235. X    strnrpt(dst, n, src, k) "RePeaTs" the string src into dst  k  times,
  1236. X    but  will  truncate  the  result at n characters if necessary.  E.g.
  1237. X    strnrpt(dst, 7, "hack ", 2) will move "hack ha" to dst  WITHOUT  the
  1238. X    closing  NUL.   The  result  is  the number of characters moved, not
  1239. X    counting the closing NUL.  Equivalent to strrpt-ing into an infinite
  1240. X    buffer and then strnmov-ing the result.
  1241. X*/
  1242. X
  1243. X#include "strings.h"
  1244. X
  1245. Xint strnrpt(dst, n, src, k)
  1246. X    register char *dst;
  1247. X    register int n;
  1248. X    char *src;
  1249. X    int k;
  1250. X    {
  1251. X    char *save;
  1252. X
  1253. X    for (save = dst; --k >= 0; dst--) {
  1254. X        register char *p;
  1255. X        for (p = src; ; ) {
  1256. X        if (--n < 0) return dst-save;
  1257. X        if (!(*dst++ = *p++)) break;
  1258. X        }
  1259. X    }
  1260. X    return dst-save;
  1261. X    }
  1262. X
  1263. SHAR_EOF
  1264. sed 's/^X//' << 'SHAR_EOF' > strntran.c
  1265. X/*  File   : strntrans.c
  1266. X    Author : Richard A. O'Keefe.
  1267. X    Updated: 2 June 1984
  1268. X    Defines: strntrans()
  1269. X
  1270. X    strntrans(dst, src, len, from, to)
  1271. X    Moves characters from src to dst, translating characters in from[]
  1272. X    to the corresponding characters in to[], until either len characters
  1273. X    have been moved or a NUL has been moved.  If fewer than len characters
  1274. X    are moved, the remainder of dst will be filled with NULs, much like
  1275. X    strncpy and family.  No value is returned.
  1276. X
  1277. X    Apology: in the previous distribution of this package, strntrans was
  1278. X    defined the way memtrans is now defined.  This is more consistent with
  1279. X    the general naming conventions.
  1280. X*/
  1281. X
  1282. X#include "strings.h"
  1283. X#include "_str2map.h"
  1284. X
  1285. X#if    VaxAsm
  1286. X
  1287. Xvoid strntrans(dst, src, len, from, to)
  1288. X    _char_ *dst, *src, *from, *to;
  1289. X    int len;
  1290. X    {
  1291. X    _str2map(0, from, to);
  1292. X    asm("movtuc 20(ap),*8(ap),$0,__map_vec,20(ap),*4(ap)");
  1293. X    /* now pad the destination out with NUL characters */
  1294. X    asm("movc5 $0,*8(ap),$0,r4,(r5)");
  1295. X    }
  1296. X
  1297. X#else  ~VaxAsm
  1298. X
  1299. Xvoid strntrans(dst, src, len, from, to)
  1300. X    register _char_ *dst, *src;
  1301. X    register int len;
  1302. X    _char_ *from, *to;
  1303. X    {
  1304. X    _str2map(0, from, to);
  1305. X    while (--len >= 0 && (*dst++ = _map_vec[*src++])) ;
  1306. X    while (--len >= 0) *dst++ = NUL;
  1307. X    }
  1308. X
  1309. X#endif    VaxAsm
  1310. X
  1311. SHAR_EOF
  1312. exit
  1313.  
  1314.  
  1315.