home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume20 / perl3.0 / part13 < prev    next >
Encoding:
Internet Message Format  |  1989-11-03  |  49.5 KB

  1. Path: bbn.com!rsalz
  2. From: rsalz@uunet.uu.net (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v20i096:  Perl, a language with features of C/sed/awk/shell/etc, Part13/24
  5. Message-ID: <2116@papaya.bbn.com>
  6. Date: 31 Oct 89 20:13:20 GMT
  7. Lines: 2173
  8. Approved: rsalz@uunet.UU.NET
  9.  
  10. Submitted-by: Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
  11. Posting-number: Volume 20, Issue 96
  12. Archive-name: perl3.0/part13
  13.  
  14. #! /bin/sh
  15.  
  16. # Make a new directory for the perl sources, cd to it, and run kits 1
  17. # thru 24 through sh.  When all 24 kits have been run, read README.
  18.  
  19. echo "This is perl 3.0 kit 13 (of 24).  If kit 13 is complete, the line"
  20. echo '"'"End of kit 13 (of 24)"'" will echo at the end.'
  21. echo ""
  22. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  23. mkdir t 2>/dev/null
  24. echo Extracting str.c
  25. sed >str.c <<'!STUFFY!FUNK!' -e 's/X//'
  26. X/* $Header: str.c,v 3.0 89/10/18 15:23:38 lwall Locked $
  27. X *
  28. X *    Copyright (c) 1989, Larry Wall
  29. X *
  30. X *    You may distribute under the terms of the GNU General Public License
  31. X *    as specified in the README file that comes with the perl 3.0 kit.
  32. X *
  33. X * $Log:    str.c,v $
  34. X * Revision 3.0  89/10/18  15:23:38  lwall
  35. X * 3.0 baseline
  36. X * 
  37. X */
  38. X
  39. X#include "EXTERN.h"
  40. X#include "perl.h"
  41. X#include "perly.h"
  42. X
  43. Xextern char **environ;
  44. X
  45. X#ifndef str_get
  46. Xchar *
  47. Xstr_get(str)
  48. XSTR *str;
  49. X{
  50. X#ifdef TAINT
  51. X    tainted |= str->str_tainted;
  52. X#endif
  53. X    return str->str_pok ? str->str_ptr : str_2ptr(str);
  54. X}
  55. X#endif
  56. X
  57. X/* dlb ... guess we have a "crippled cc".
  58. X * dlb the following functions are usually macros.
  59. X */
  60. X#ifndef str_true
  61. Xstr_true(Str)
  62. XSTR *Str;
  63. X{
  64. X    if (Str->str_pok) {
  65. X        if (*Str->str_ptr > '0' ||
  66. X          Str->str_cur > 1 ||
  67. X          (Str->str_cur && *Str->str_ptr != '0'))
  68. X        return 1;
  69. X        return 0;
  70. X    }
  71. X    if (Str->str_nok)
  72. X        return (Str->str_u.str_nval != 0.0);
  73. X    return 0;
  74. X}
  75. X#endif /* str_true */
  76. X
  77. X#ifndef str_gnum
  78. Xdouble str_gnum(Str)
  79. XSTR *Str;
  80. X{
  81. X#ifdef TAINT
  82. X    tainted |= Str->str_tainted;
  83. X#endif /* TAINT*/
  84. X    if (Str->str_nok)
  85. X        return Str->str_u.str_nval;
  86. X    return str_2num(Str);
  87. X}
  88. X#endif /* str_gnum */
  89. X/* dlb ... end of crutch */
  90. X
  91. Xchar *
  92. Xstr_grow(str,newlen)
  93. Xregister STR *str;
  94. Xregister int newlen;
  95. X{
  96. X    register char *s = str->str_ptr;
  97. X
  98. X    if (str->str_state == SS_INCR) {        /* data before str_ptr? */
  99. X    str->str_len += str->str_u.str_useful;
  100. X    str->str_ptr -= str->str_u.str_useful;
  101. X    str->str_u.str_useful = 0L;
  102. X    bcopy(s, str->str_ptr, str->str_cur+1);
  103. X    s = str->str_ptr;
  104. X    str->str_state = SS_NORM;            /* normal again */
  105. X    if (newlen > str->str_len)
  106. X        newlen += 10 * (newlen - str->str_cur); /* avoid copy each time */
  107. X    }
  108. X    if (newlen > str->str_len) {        /* need more room? */
  109. X        if (str->str_len)
  110. X        Renew(s,newlen,char);
  111. X        else
  112. X        New(703,s,newlen,char);
  113. X    str->str_ptr = s;
  114. X        str->str_len = newlen;
  115. X    }
  116. X    return s;
  117. X}
  118. X
  119. Xstr_numset(str,num)
  120. Xregister STR *str;
  121. Xdouble num;
  122. X{
  123. X    str->str_u.str_nval = num;
  124. X    str->str_state = SS_NORM;
  125. X    str->str_pok = 0;    /* invalidate pointer */
  126. X    str->str_nok = 1;            /* validate number */
  127. X#ifdef TAINT
  128. X    str->str_tainted = tainted;
  129. X#endif
  130. X}
  131. X
  132. Xextern int errno;
  133. X
  134. Xchar *
  135. Xstr_2ptr(str)
  136. Xregister STR *str;
  137. X{
  138. X    register char *s;
  139. X    int olderrno;
  140. X
  141. X    if (!str)
  142. X    return "";
  143. X    if (str->str_nok) {
  144. X    STR_GROW(str, 24);
  145. X    s = str->str_ptr;
  146. X    olderrno = errno;    /* some Xenix systems wipe out errno here */
  147. X#if defined(scs) && defined(ns32000)
  148. X    gcvt(str->str_u.str_nval,20,s);
  149. X#else
  150. X#ifdef apollo
  151. X    if (str->str_u.str_nval == 0.0)
  152. X        (void)strcpy(s,"0");
  153. X    else
  154. X#endif /*apollo*/
  155. X    (void)sprintf(s,"%.20g",str->str_u.str_nval);
  156. X#endif /*scs*/
  157. X    errno = olderrno;
  158. X    while (*s) s++;
  159. X    }
  160. X    else {
  161. X    if (str == &str_undef)
  162. X        return No;
  163. X    if (dowarn)
  164. X        warn("Use of uninitialized variable");
  165. X    STR_GROW(str, 24);
  166. X    s = str->str_ptr;
  167. X    }
  168. X    *s = '\0';
  169. X    str->str_cur = s - str->str_ptr;
  170. X    str->str_pok = 1;
  171. X#ifdef DEBUGGING
  172. X    if (debug & 32)
  173. X    fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);
  174. X#endif
  175. X    return str->str_ptr;
  176. X}
  177. X
  178. Xdouble
  179. Xstr_2num(str)
  180. Xregister STR *str;
  181. X{
  182. X    if (!str)
  183. X    return 0.0;
  184. X    str->str_state = SS_NORM;
  185. X    if (str->str_len && str->str_pok)
  186. X    str->str_u.str_nval = atof(str->str_ptr);
  187. X    else  {
  188. X    if (str == &str_undef)
  189. X        return 0.0;
  190. X    if (dowarn)
  191. X        warn("Use of uninitialized variable");
  192. X    str->str_u.str_nval = 0.0;
  193. X    }
  194. X    str->str_nok = 1;
  195. X#ifdef DEBUGGING
  196. X    if (debug & 32)
  197. X    fprintf(stderr,"0x%lx num(%g)\n",str,str->str_u.str_nval);
  198. X#endif
  199. X    return str->str_u.str_nval;
  200. X}
  201. X
  202. Xstr_sset(dstr,sstr)
  203. XSTR *dstr;
  204. Xregister STR *sstr;
  205. X{
  206. X#ifdef TAINT
  207. X    tainted |= sstr->str_tainted;
  208. X#endif
  209. X    if (!sstr)
  210. X    dstr->str_pok = dstr->str_nok = 0;
  211. X    else if (sstr->str_pok) {
  212. X    str_nset(dstr,sstr->str_ptr,sstr->str_cur);
  213. X    if (sstr->str_nok) {
  214. X        dstr->str_u.str_nval = sstr->str_u.str_nval;
  215. X        dstr->str_nok = 1;
  216. X        dstr->str_state = SS_NORM;
  217. X    }
  218. X    else if (sstr->str_cur == sizeof(STBP)) {
  219. X        char *tmps = sstr->str_ptr;
  220. X
  221. X        if (*tmps == 'S' && bcmp(tmps,"Stab",4) == 0) {
  222. X        dstr->str_magic = str_smake(sstr->str_magic);
  223. X        dstr->str_magic->str_rare = 'X';
  224. X        }
  225. X    }
  226. X    }
  227. X    else if (sstr->str_nok)
  228. X    str_numset(dstr,sstr->str_u.str_nval);
  229. X    else
  230. X    dstr->str_pok = dstr->str_nok = 0;
  231. X}
  232. X
  233. Xstr_nset(str,ptr,len)
  234. Xregister STR *str;
  235. Xregister char *ptr;
  236. Xregister int len;
  237. X{
  238. X    STR_GROW(str, len + 1);
  239. X    (void)bcopy(ptr,str->str_ptr,len);
  240. X    str->str_cur = len;
  241. X    *(str->str_ptr+str->str_cur) = '\0';
  242. X    str->str_nok = 0;        /* invalidate number */
  243. X    str->str_pok = 1;        /* validate pointer */
  244. X#ifdef TAINT
  245. X    str->str_tainted = tainted;
  246. X#endif
  247. X}
  248. X
  249. Xstr_set(str,ptr)
  250. Xregister STR *str;
  251. Xregister char *ptr;
  252. X{
  253. X    register int len;
  254. X
  255. X    if (!ptr)
  256. X    ptr = "";
  257. X    len = strlen(ptr);
  258. X    STR_GROW(str, len + 1);
  259. X    (void)bcopy(ptr,str->str_ptr,len+1);
  260. X    str->str_cur = len;
  261. X    str->str_nok = 0;        /* invalidate number */
  262. X    str->str_pok = 1;        /* validate pointer */
  263. X#ifdef TAINT
  264. X    str->str_tainted = tainted;
  265. X#endif
  266. X}
  267. X
  268. Xstr_chop(str,ptr)    /* like set but assuming ptr is in str */
  269. Xregister STR *str;
  270. Xregister char *ptr;
  271. X{
  272. X    register int delta;
  273. X
  274. X    if (!(str->str_pok))
  275. X    fatal("str_chop: internal inconsistency");
  276. X    delta = ptr - str->str_ptr;
  277. X    str->str_len -= delta;
  278. X    str->str_cur -= delta;
  279. X    str->str_ptr += delta;
  280. X    if (str->str_state == SS_INCR)
  281. X    str->str_u.str_useful += delta;
  282. X    else {
  283. X    str->str_u.str_useful = delta;
  284. X    str->str_state = SS_INCR;
  285. X    }
  286. X    str->str_nok = 0;        /* invalidate number */
  287. X    str->str_pok = 1;        /* validate pointer (and unstudy str) */
  288. X}
  289. X
  290. Xstr_ncat(str,ptr,len)
  291. Xregister STR *str;
  292. Xregister char *ptr;
  293. Xregister int len;
  294. X{
  295. X    if (!(str->str_pok))
  296. X    (void)str_2ptr(str);
  297. X    STR_GROW(str, str->str_cur + len + 1);
  298. X    (void)bcopy(ptr,str->str_ptr+str->str_cur,len);
  299. X    str->str_cur += len;
  300. X    *(str->str_ptr+str->str_cur) = '\0';
  301. X    str->str_nok = 0;        /* invalidate number */
  302. X    str->str_pok = 1;        /* validate pointer */
  303. X#ifdef TAINT
  304. X    str->str_tainted |= tainted;
  305. X#endif
  306. X}
  307. X
  308. Xstr_scat(dstr,sstr)
  309. XSTR *dstr;
  310. Xregister STR *sstr;
  311. X{
  312. X#ifdef TAINT
  313. X    tainted |= sstr->str_tainted;
  314. X#endif
  315. X    if (!sstr)
  316. X    return;
  317. X    if (!(sstr->str_pok))
  318. X    (void)str_2ptr(sstr);
  319. X    if (sstr)
  320. X    str_ncat(dstr,sstr->str_ptr,sstr->str_cur);
  321. X}
  322. X
  323. Xstr_cat(str,ptr)
  324. Xregister STR *str;
  325. Xregister char *ptr;
  326. X{
  327. X    register int len;
  328. X
  329. X    if (!ptr)
  330. X    return;
  331. X    if (!(str->str_pok))
  332. X    (void)str_2ptr(str);
  333. X    len = strlen(ptr);
  334. X    STR_GROW(str, str->str_cur + len + 1);
  335. X    (void)bcopy(ptr,str->str_ptr+str->str_cur,len+1);
  336. X    str->str_cur += len;
  337. X    str->str_nok = 0;        /* invalidate number */
  338. X    str->str_pok = 1;        /* validate pointer */
  339. X#ifdef TAINT
  340. X    str->str_tainted |= tainted;
  341. X#endif
  342. X}
  343. X
  344. Xchar *
  345. Xstr_append_till(str,from,fromend,delim,keeplist)
  346. Xregister STR *str;
  347. Xregister char *from;
  348. Xregister char *fromend;
  349. Xregister int delim;
  350. Xchar *keeplist;
  351. X{
  352. X    register char *to;
  353. X    register int len;
  354. X
  355. X    if (!from)
  356. X    return Nullch;
  357. X    len = fromend - from;
  358. X    STR_GROW(str, str->str_cur + len + 1);
  359. X    str->str_nok = 0;        /* invalidate number */
  360. X    str->str_pok = 1;        /* validate pointer */
  361. X    to = str->str_ptr+str->str_cur;
  362. X    for (; from < fromend; from++,to++) {
  363. X    if (*from == '\\' && from+1 < fromend && delim != '\\') {
  364. X        if (!keeplist) {
  365. X        if (from[1] == delim || from[1] == '\\')
  366. X            from++;
  367. X        else
  368. X            *to++ = *from++;
  369. X        }
  370. X        else if (from[1] && index(keeplist,from[1]))
  371. X        *to++ = *from++;
  372. X        else
  373. X        from++;
  374. X    }
  375. X    else if (*from == delim)
  376. X        break;
  377. X    *to = *from;
  378. X    }
  379. X    *to = '\0';
  380. X    str->str_cur = to - str->str_ptr;
  381. X    return from;
  382. X}
  383. X
  384. XSTR *
  385. X#ifdef LEAKTEST
  386. Xstr_new(x,len)
  387. Xint x;
  388. X#else
  389. Xstr_new(len)
  390. X#endif
  391. Xint len;
  392. X{
  393. X    register STR *str;
  394. X    
  395. X    if (freestrroot) {
  396. X    str = freestrroot;
  397. X    freestrroot = str->str_magic;
  398. X    str->str_magic = Nullstr;
  399. X    str->str_state = SS_NORM;
  400. X    }
  401. X    else {
  402. X    Newz(700+x,str,1,STR);
  403. X    }
  404. X    if (len)
  405. X    STR_GROW(str, len + 1);
  406. X    return str;
  407. X}
  408. X
  409. Xvoid
  410. Xstr_magic(str, stab, how, name, namlen)
  411. Xregister STR *str;
  412. XSTAB *stab;
  413. Xint how;
  414. Xchar *name;
  415. Xint namlen;
  416. X{
  417. X    if (str->str_magic)
  418. X    return;
  419. X    str->str_magic = Str_new(75,namlen);
  420. X    str = str->str_magic;
  421. X    str->str_u.str_stab = stab;
  422. X    str->str_rare = how;
  423. X    if (name)
  424. X    str_nset(str,name,namlen);
  425. X}
  426. X
  427. Xvoid
  428. Xstr_insert(bigstr,offset,len,little,littlelen)
  429. XSTR *bigstr;
  430. Xint offset;
  431. Xint len;
  432. Xchar *little;
  433. Xint littlelen;
  434. X{
  435. X    register char *big;
  436. X    register char *mid;
  437. X    register char *midend;
  438. X    register char *bigend;
  439. X    register int i;
  440. X
  441. X    i = littlelen - len;
  442. X    if (i > 0) {            /* string might grow */
  443. X    STR_GROW(bigstr, bigstr->str_cur + i + 1);
  444. X    big = bigstr->str_ptr;
  445. X    mid = big + offset + len;
  446. X    midend = bigend = big + bigstr->str_cur;
  447. X    bigend += i;
  448. X    *bigend = '\0';
  449. X    while (midend > mid)        /* shove everything down */
  450. X        *--bigend = *--midend;
  451. X    (void)bcopy(little,big+offset,littlelen);
  452. X    bigstr->str_cur += i;
  453. X    return;
  454. X    }
  455. X    else if (i == 0) {
  456. X    (void)bcopy(little,bigstr->str_ptr+offset,len);
  457. X    return;
  458. X    }
  459. X
  460. X    big = bigstr->str_ptr;
  461. X    mid = big + offset;
  462. X    midend = mid + len;
  463. X    bigend = big + bigstr->str_cur;
  464. X
  465. X    if (midend > bigend)
  466. X    fatal("panic: str_insert");
  467. X
  468. X    bigstr->str_pok = SP_VALID;    /* disable possible screamer */
  469. X
  470. X    if (mid - big > bigend - midend) {    /* faster to shorten from end */
  471. X    if (littlelen) {
  472. X        (void)bcopy(little, mid, littlelen);
  473. X        mid += littlelen;
  474. X    }
  475. X    i = bigend - midend;
  476. X    if (i > 0) {
  477. X        (void)bcopy(midend, mid, i);
  478. X        mid += i;
  479. X    }
  480. X    *mid = '\0';
  481. X    bigstr->str_cur = mid - big;
  482. X    }
  483. X    else if (i = mid - big) {    /* faster from front */
  484. X    midend -= littlelen;
  485. X    mid = midend;
  486. X    str_chop(bigstr,midend-i);
  487. X    big += i;
  488. X    while (i--)
  489. X        *--midend = *--big;
  490. X    if (littlelen)
  491. X        (void)bcopy(little, mid, littlelen);
  492. X    }
  493. X    else if (littlelen) {
  494. X    midend -= littlelen;
  495. X    str_chop(bigstr,midend);
  496. X    (void)bcopy(little,midend,littlelen);
  497. X    }
  498. X    else {
  499. X    str_chop(bigstr,midend);
  500. X    }
  501. X    STABSET(bigstr);
  502. X}
  503. X
  504. X/* make str point to what nstr did */
  505. X
  506. Xvoid
  507. Xstr_replace(str,nstr)
  508. Xregister STR *str;
  509. Xregister STR *nstr;
  510. X{
  511. X    if (str->str_state == SS_INCR)
  512. X    str_grow(str,0);    /* just force copy down */
  513. X    if (nstr->str_state == SS_INCR)
  514. X    str_grow(nstr,0);
  515. X    if (str->str_ptr)
  516. X    Safefree(str->str_ptr);
  517. X    str->str_ptr = nstr->str_ptr;
  518. X    str->str_len = nstr->str_len;
  519. X    str->str_cur = nstr->str_cur;
  520. X    str->str_pok = nstr->str_pok;
  521. X    str->str_nok = nstr->str_nok;
  522. X#ifdef STRUCTCOPY
  523. X    str->str_u = nstr->str_u;
  524. X#else
  525. X    str->str_u.str_nval = nstr->str_u.str_nval;
  526. X#endif
  527. X#ifdef TAINT
  528. X    str->str_tainted = nstr->str_tainted;
  529. X#endif
  530. X    Safefree(nstr);
  531. X}
  532. X
  533. Xvoid
  534. Xstr_free(str)
  535. Xregister STR *str;
  536. X{
  537. X    if (!str)
  538. X    return;
  539. X    if (str->str_state) {
  540. X    if (str->str_state == SS_FREE)    /* already freed */
  541. X        return;
  542. X    if (str->str_state == SS_INCR && !(str->str_pok & 2)) {
  543. X        str->str_ptr -= str->str_u.str_useful;
  544. X        str->str_len += str->str_u.str_useful;
  545. X    }
  546. X    }
  547. X    if (str->str_magic)
  548. X    str_free(str->str_magic);
  549. X#ifdef LEAKTEST
  550. X    if (str->str_len)
  551. X    Safefree(str->str_ptr);
  552. X    if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
  553. X    arg_free(str->str_u.str_args);
  554. X    Safefree(str);
  555. X#else /* LEAKTEST */
  556. X    if (str->str_len) {
  557. X    if (str->str_len > 127) {    /* next user not likely to want more */
  558. X        Safefree(str->str_ptr);    /* so give it back to malloc */
  559. X        str->str_ptr = Nullch;
  560. X        str->str_len = 0;
  561. X    }
  562. X    else
  563. X        str->str_ptr[0] = '\0';
  564. X    }
  565. X    if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
  566. X    arg_free(str->str_u.str_args);
  567. X    str->str_cur = 0;
  568. X    str->str_nok = 0;
  569. X    str->str_pok = 0;
  570. X    str->str_state = SS_FREE;
  571. X#ifdef TAINT
  572. X    str->str_tainted = 0;
  573. X#endif
  574. X    str->str_magic = freestrroot;
  575. X    freestrroot = str;
  576. X#endif /* LEAKTEST */
  577. X}
  578. X
  579. Xstr_len(str)
  580. Xregister STR *str;
  581. X{
  582. X    if (!str)
  583. X    return 0;
  584. X    if (!(str->str_pok))
  585. X    (void)str_2ptr(str);
  586. X    if (str->str_ptr)
  587. X    return str->str_cur;
  588. X    else
  589. X    return 0;
  590. X}
  591. X
  592. Xstr_eq(str1,str2)
  593. Xregister STR *str1;
  594. Xregister STR *str2;
  595. X{
  596. X    if (!str1)
  597. X    return str2 == Nullstr;
  598. X    if (!str2)
  599. X    return 0;
  600. X
  601. X    if (!str1->str_pok)
  602. X    (void)str_2ptr(str1);
  603. X    if (!str2->str_pok)
  604. X    (void)str_2ptr(str2);
  605. X
  606. X    if (str1->str_cur != str2->str_cur)
  607. X    return 0;
  608. X
  609. X    return !bcmp(str1->str_ptr, str2->str_ptr, str1->str_cur);
  610. X}
  611. X
  612. Xstr_cmp(str1,str2)
  613. Xregister STR *str1;
  614. Xregister STR *str2;
  615. X{
  616. X    int retval;
  617. X
  618. X    if (!str1)
  619. X    return str2 == Nullstr;
  620. X    if (!str2)
  621. X    return 0;
  622. X
  623. X    if (!str1->str_pok)
  624. X    (void)str_2ptr(str1);
  625. X    if (!str2->str_pok)
  626. X    (void)str_2ptr(str2);
  627. X
  628. X    if (str1->str_cur < str2->str_cur) {
  629. X    if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
  630. X        return retval;
  631. X    else
  632. X        return 1;
  633. X    }
  634. X    else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
  635. X    return retval;
  636. X    else if (str1->str_cur == str2->str_cur)
  637. X    return 0;
  638. X    else
  639. X    return -1;
  640. X}
  641. X
  642. Xchar *
  643. Xstr_gets(str,fp,append)
  644. Xregister STR *str;
  645. Xregister FILE *fp;
  646. Xint append;
  647. X{
  648. X#ifdef STDSTDIO        /* Here is some breathtakingly efficient cheating */
  649. X
  650. X    register char *bp;        /* we're going to steal some values */
  651. X    register int cnt;        /*  from the stdio struct and put EVERYTHING */
  652. X    register STDCHAR *ptr;    /*   in the innermost loop into registers */
  653. X    register char newline = record_separator;/* (assuming >= 6 registers) */
  654. X    int i;
  655. X    int bpx;
  656. X    int obpx;
  657. X    register int get_paragraph;
  658. X    register char *oldbp;
  659. X
  660. X    if (get_paragraph = !rslen) {    /* yes, that's an assignment */
  661. X    newline = '\n';
  662. X    oldbp = Nullch;            /* remember last \n position (none) */
  663. X    }
  664. X    cnt = fp->_cnt;            /* get count into register */
  665. X    str->str_nok = 0;            /* invalidate number */
  666. X    str->str_pok = 1;            /* validate pointer */
  667. X    if (str->str_len <= cnt + 1)    /* make sure we have the room */
  668. X    STR_GROW(str, append+cnt+2);    /* (remembering cnt can be -1) */
  669. X    bp = str->str_ptr + append;        /* move these two too to registers */
  670. X    ptr = fp->_ptr;
  671. X    for (;;) {
  672. X      screamer:
  673. X    while (--cnt >= 0) {            /* this */    /* eat */
  674. X        if ((*bp++ = *ptr++) == newline)    /* really */    /* dust */
  675. X        goto thats_all_folks;        /* screams */    /* sed :-) */ 
  676. X    }
  677. X    
  678. X    fp->_cnt = cnt;            /* deregisterize cnt and ptr */
  679. X    fp->_ptr = ptr;
  680. X    i = _filbuf(fp);        /* get more characters */
  681. X    cnt = fp->_cnt;
  682. X    ptr = fp->_ptr;            /* reregisterize cnt and ptr */
  683. X
  684. X    bpx = bp - str->str_ptr;    /* prepare for possible relocation */
  685. X    if (get_paragraph && oldbp)
  686. X        obpx = oldbp - str->str_ptr;
  687. X    STR_GROW(str, bpx + cnt + 2);
  688. X    bp = str->str_ptr + bpx;    /* reconstitute our pointer */
  689. X    if (get_paragraph && oldbp)
  690. X        oldbp = str->str_ptr + obpx;
  691. X
  692. X    if (i == newline) {        /* all done for now? */
  693. X        *bp++ = i;
  694. X        goto thats_all_folks;
  695. X    }
  696. X    else if (i == EOF)        /* all done for ever? */
  697. X        goto thats_really_all_folks;
  698. X    *bp++ = i;            /* now go back to screaming loop */
  699. X    }
  700. X
  701. Xthats_all_folks:
  702. X    if (get_paragraph && bp - 1 != oldbp) {
  703. X    oldbp = bp;    /* remember where this newline was */
  704. X    goto screamer;    /* and go back to the fray */
  705. X    }
  706. Xthats_really_all_folks:
  707. X    fp->_cnt = cnt;            /* put these back or we're in trouble */
  708. X    fp->_ptr = ptr;
  709. X    *bp = '\0';
  710. X    str->str_cur = bp - str->str_ptr;    /* set length */
  711. X
  712. X#else /* !STDSTDIO */    /* The big, slow, and stupid way */
  713. X
  714. X    static char buf[8192];
  715. X
  716. X    if (fgets(buf, sizeof buf, fp) != Nullch) {
  717. X    if (append)
  718. X        str_cat(str, buf);
  719. X    else
  720. X        str_set(str, buf);
  721. X    }
  722. X    else
  723. X    str_set(str, No);
  724. X
  725. X#endif /* STDSTDIO */
  726. X
  727. X    return str->str_cur - append ? str->str_ptr : Nullch;
  728. X}
  729. X
  730. XARG *
  731. Xparselist(str)
  732. XSTR *str;
  733. X{
  734. X    register CMD *cmd;
  735. X    register ARG *arg;
  736. X    line_t oldline = line;
  737. X    int retval;
  738. X
  739. X    str_sset(linestr,str);
  740. X    in_eval++;
  741. X    oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
  742. X    bufend = bufptr + linestr->str_cur;
  743. X    if (setjmp(eval_env)) {
  744. X    in_eval = 0;
  745. X    fatal("%s\n",stab_val(stabent("@",TRUE))->str_ptr);
  746. X    }
  747. X    error_count = 0;
  748. X    retval = yyparse();
  749. X    in_eval--;
  750. X    if (retval || error_count)
  751. X    fatal("Invalid component in string or format");
  752. X    cmd = eval_root;
  753. X    arg = cmd->c_expr;
  754. X    if (cmd->c_type != C_EXPR || cmd->c_next || arg->arg_type != O_LIST)
  755. X    fatal("panic: error in parselist %d %x %d", cmd->c_type,
  756. X      cmd->c_next, arg ? arg->arg_type : -1);
  757. X    line = oldline;
  758. X    Safefree(cmd);
  759. X    return arg;
  760. X}
  761. X
  762. Xvoid
  763. Xintrpcompile(src)
  764. XSTR *src;
  765. X{
  766. X    register char *s = str_get(src);
  767. X    register char *send = s + src->str_cur;
  768. X    register STR *str;
  769. X    register char *t;
  770. X    STR *toparse;
  771. X    int len;
  772. X    register int brackets;
  773. X    register char *d;
  774. X    STAB *stab;
  775. X    char *checkpoint;
  776. X
  777. X    toparse = Str_new(76,0);
  778. X    str = Str_new(77,0);
  779. X
  780. X    str_nset(str,"",0);
  781. X    str_nset(toparse,"",0);
  782. X    t = s;
  783. X    while (s < send) {
  784. X    if (*s == '\\' && s[1] && index("$@[{\\]}",s[1])) {
  785. X        str_ncat(str, t, s - t);
  786. X        ++s;
  787. X        if (*nointrp && s+1 < send)
  788. X        if (*s != '@' && (*s != '$' || index(nointrp,s[1])))
  789. X            str_ncat(str,s-1,1);
  790. X        str_ncat(str, "$b", 2);
  791. X        str_ncat(str, s, 1);
  792. X        ++s;
  793. X        t = s;
  794. X    }
  795. X    else if ((*s == '@' || (*s == '$' && !index(nointrp,s[1]))) &&
  796. X      s+1 < send) {
  797. X        str_ncat(str,t,s-t);
  798. X        t = s;
  799. X        if (*s == '$' && s[1] == '#' && isalpha(s[2]) || s[2] == '_')
  800. X        s++;
  801. X        s = scanreg(s,send,tokenbuf);
  802. X        if (*t == '@' &&
  803. X          (!(stab = stabent(tokenbuf,FALSE)) || !stab_xarray(stab)) ) {
  804. X        str_ncat(str,"@",1);
  805. X        s = ++t;
  806. X        continue;    /* grandfather @ from old scripts */
  807. X        }
  808. X        str_ncat(str,"$a",2);
  809. X        str_ncat(toparse,",",1);
  810. X        if (t[1] != '{' && (*s == '['  || *s == '{' /* }} */ ) &&
  811. X          (stab = stabent(tokenbuf,FALSE)) &&
  812. X          ((*s == '[') ? (stab_xarray(stab) != 0) : (stab_xhash(stab) != 0)) ) {
  813. X        brackets = 0;
  814. X        checkpoint = s;
  815. X        do {
  816. X            switch (*s) {
  817. X            case '[': case '{':
  818. X            brackets++;
  819. X            break;
  820. X            case ']': case '}':
  821. X            brackets--;
  822. X            break;
  823. X            case '\'':
  824. X            case '"':
  825. X            if (s[-1] != '$') {
  826. X                s = cpytill(tokenbuf,s+1,send,*s,&len);
  827. X                if (s >= send)
  828. X                fatal("Unterminated string");
  829. X            }
  830. X            break;
  831. X            }
  832. X            s++;
  833. X        } while (brackets > 0 && s < send);
  834. X        if (s > send)
  835. X            fatal("Unmatched brackets in string");
  836. X        if (*nointrp) {        /* we're in a regular expression */
  837. X            d = checkpoint;
  838. X            if (*d == '{' && s[-1] == '}') {    /* maybe {n,m} */
  839. X            ++d;
  840. X            if (isdigit(*d)) {    /* matches /^{\d,?\d*}$/ */
  841. X                if (*++d == ',')
  842. X                ++d;
  843. X                while (isdigit(*d))
  844. X                d++;
  845. X                if (d == s - 1)
  846. X                s = checkpoint;        /* Is {n,m}! Backoff! */
  847. X            }
  848. X            }
  849. X            else if (*d == '[' && s[-1] == ']') { /* char class? */
  850. X            int weight = 2;        /* let's weigh the evidence */
  851. X            char seen[256];
  852. X            unsigned char uchar = 0, lastuchar;
  853. X
  854. X            Zero(seen,256,char);
  855. X            *--s = '\0';
  856. X            if (d[1] == '^')
  857. X                weight += 150;
  858. X            else if (d[1] == '$')
  859. X                weight -= 3;
  860. X            if (isdigit(d[1])) {
  861. X                if (d[2]) {
  862. X                if (isdigit(d[2]) && !d[3])
  863. X                    weight -= 10;
  864. X                }
  865. X                else
  866. X                weight -= 100;
  867. X            }
  868. X            for (d++; d < s; d++) {
  869. X                lastuchar = uchar;
  870. X                uchar = (unsigned char)*d;
  871. X                switch (*d) {
  872. X                case '&':
  873. X                case '$':
  874. X                weight -= seen[uchar] * 10;
  875. X                if (isalpha(d[1]) || isdigit(d[1]) ||
  876. X                  d[1] == '_') {
  877. X                    d = scanreg(d,s,tokenbuf);
  878. X                    if (stabent(tokenbuf,FALSE))
  879. X                    weight -= 100;
  880. X                    else
  881. X                    weight -= 10;
  882. X                }
  883. X                else if (*d == '$' && d[1] &&
  884. X                  index("[#!%*<>()-=",d[1])) {
  885. X                    if (!d[2] || /*{*/ index("])} =",d[2]))
  886. X                    weight -= 10;
  887. X                    else
  888. X                    weight -= 1;
  889. X                }
  890. X                break;
  891. X                case '\\':
  892. X                uchar = 254;
  893. X                if (d[1]) {
  894. X                    if (index("wds",d[1]))
  895. X                    weight += 100;
  896. X                    else if (seen['\''] || seen['"'])
  897. X                    weight += 1;
  898. X                    else if (index("rnftb",d[1]))
  899. X                    weight += 40;
  900. X                    else if (isdigit(d[1])) {
  901. X                    weight += 40;
  902. X                    while (d[1] && isdigit(d[1]))
  903. X                        d++;
  904. X                    }
  905. X                }
  906. X                else
  907. X                    weight += 100;
  908. X                break;
  909. X                case '-':
  910. X                if (lastuchar < d[1] || d[1] == '\\') {
  911. X                    if (index("aA01! ",lastuchar))
  912. X                    weight += 30;
  913. X                    if (index("zZ79~",d[1]))
  914. X                    weight += 30;
  915. X                }
  916. X                else
  917. X                    weight -= 1;
  918. X                default:
  919. X                if (isalpha(*d) && d[1] && isalpha(d[1])) {
  920. X                    bufptr = d;
  921. X                    if (yylex() != WORD)
  922. X                    weight -= 150;
  923. X                    d = bufptr;
  924. X                }
  925. X                if (uchar == lastuchar + 1)
  926. X                    weight += 5;
  927. X                weight -= seen[uchar];
  928. X                break;
  929. X                }
  930. X                seen[uchar]++;
  931. X            }
  932. X#ifdef DEBUGGING
  933. X            if (debug & 512)
  934. X                fprintf(stderr,"[%s] weight %d\n",
  935. X                  checkpoint+1,weight);
  936. X#endif
  937. X            *s++ = ']';
  938. X            if (weight >= 0)    /* probably a character class */
  939. X                s = checkpoint;
  940. X            }
  941. X        }
  942. X        }
  943. X        if (*t == '@')
  944. X        str_ncat(toparse, "join($\",", 8);
  945. X        if (t[1] == '{' && s[-1] == '}') {
  946. X        str_ncat(toparse, t, 1);
  947. X        str_ncat(toparse, t+2, s - t - 3);
  948. X        }
  949. X        else
  950. X        str_ncat(toparse, t, s - t);
  951. X        if (*t == '@')
  952. X        str_ncat(toparse, ")", 1);
  953. X        t = s;
  954. X    }
  955. X    else
  956. X        s++;
  957. X    }
  958. X    str_ncat(str,t,s-t);
  959. X    if (toparse->str_ptr && *toparse->str_ptr == ',') {
  960. X    *toparse->str_ptr = '(';
  961. X    str_ncat(toparse,",$$);",5);
  962. X    str->str_u.str_args = parselist(toparse);
  963. X    str->str_u.str_args->arg_len--;        /* ignore $$ reference */
  964. X    }
  965. X    else
  966. X    str->str_u.str_args = Nullarg;
  967. X    str_free(toparse);
  968. X    str->str_pok |= SP_INTRP;
  969. X    str->str_nok = 0;
  970. X    str_replace(src,str);
  971. X}
  972. X
  973. XSTR *
  974. Xinterp(str,src,sp)
  975. Xregister STR *str;
  976. XSTR *src;
  977. Xint sp;
  978. X{
  979. X    register char *s;
  980. X    register char *t;
  981. X    register char *send;
  982. X    register STR **elem;
  983. X
  984. X    if (!(src->str_pok & SP_INTRP)) {
  985. X    int oldsave = savestack->ary_fill;
  986. X
  987. X    (void)savehptr(&curstash);
  988. X    curstash = src->str_u.str_hash;    /* so stabent knows right package */
  989. X    intrpcompile(src);
  990. X    restorelist(oldsave);
  991. X    }
  992. X    s = src->str_ptr;        /* assumed valid since str_pok set */
  993. X    t = s;
  994. X    send = s + src->str_cur;
  995. X
  996. X    if (src->str_u.str_args) {
  997. X    (void)eval(src->str_u.str_args,G_ARRAY,sp);
  998. X    /* Assuming we have correct # of args */
  999. X    elem = stack->ary_array + sp;
  1000. X    }
  1001. X
  1002. X    str_nset(str,"",0);
  1003. X    while (s < send) {
  1004. X    if (*s == '$' && s+1 < send) {
  1005. X        str_ncat(str,t,s-t);
  1006. X        switch(*++s) {
  1007. X        case 'a':
  1008. X        str_scat(str,*++elem);
  1009. X        break;
  1010. X        case 'b':
  1011. X        str_ncat(str,++s,1);
  1012. X        break;
  1013. X        }
  1014. X        t = ++s;
  1015. X    }
  1016. X    else
  1017. X        s++;
  1018. X    }
  1019. X    str_ncat(str,t,s-t);
  1020. X    return str;
  1021. X}
  1022. X
  1023. Xvoid
  1024. Xstr_inc(str)
  1025. Xregister STR *str;
  1026. X{
  1027. X    register char *d;
  1028. X
  1029. X    if (!str)
  1030. X    return;
  1031. X    if (str->str_nok) {
  1032. X    str->str_u.str_nval += 1.0;
  1033. X    str->str_pok = 0;
  1034. X    return;
  1035. X    }
  1036. X    if (!str->str_pok || !*str->str_ptr) {
  1037. X    str->str_u.str_nval = 1.0;
  1038. X    str->str_nok = 1;
  1039. X    str->str_pok = 0;
  1040. X    return;
  1041. X    }
  1042. X    d = str->str_ptr;
  1043. X    while (isalpha(*d)) d++;
  1044. X    while (isdigit(*d)) d++;
  1045. X    if (*d) {
  1046. X        str_numset(str,atof(str->str_ptr) + 1.0);  /* punt */
  1047. X    return;
  1048. X    }
  1049. X    d--;
  1050. X    while (d >= str->str_ptr) {
  1051. X    if (isdigit(*d)) {
  1052. X        if (++*d <= '9')
  1053. X        return;
  1054. X        *(d--) = '0';
  1055. X    }
  1056. X    else {
  1057. X        ++*d;
  1058. X        if (isalpha(*d))
  1059. X        return;
  1060. X        *(d--) -= 'z' - 'a' + 1;
  1061. X    }
  1062. X    }
  1063. X    /* oh,oh, the number grew */
  1064. X    STR_GROW(str, str->str_cur + 2);
  1065. X    str->str_cur++;
  1066. X    for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--)
  1067. X    *d = d[-1];
  1068. X    if (isdigit(d[1]))
  1069. X    *d = '1';
  1070. X    else
  1071. X    *d = d[1];
  1072. X}
  1073. X
  1074. Xvoid
  1075. Xstr_dec(str)
  1076. Xregister STR *str;
  1077. X{
  1078. X    if (!str)
  1079. X    return;
  1080. X    if (str->str_nok) {
  1081. X    str->str_u.str_nval -= 1.0;
  1082. X    str->str_pok = 0;
  1083. X    return;
  1084. X    }
  1085. X    if (!str->str_pok) {
  1086. X    str->str_u.str_nval = -1.0;
  1087. X    str->str_nok = 1;
  1088. X    return;
  1089. X    }
  1090. X    str_numset(str,atof(str->str_ptr) - 1.0);
  1091. X}
  1092. X
  1093. X/* Make a string that will exist for the duration of the expression
  1094. X * evaluation.  Actually, it may have to last longer than that, but
  1095. X * hopefully cmd_exec won't free it until it has been assigned to a
  1096. X * permanent location. */
  1097. X
  1098. Xstatic long tmps_size = -1;
  1099. X
  1100. XSTR *
  1101. Xstr_static(oldstr)
  1102. XSTR *oldstr;
  1103. X{
  1104. X    register STR *str = Str_new(78,0);
  1105. X
  1106. X    str_sset(str,oldstr);
  1107. X    if (++tmps_max > tmps_size) {
  1108. X    tmps_size = tmps_max;
  1109. X    if (!(tmps_size & 127)) {
  1110. X        if (tmps_size)
  1111. X        Renew(tmps_list, tmps_size + 128, STR*);
  1112. X        else
  1113. X        New(702,tmps_list, 128, STR*);
  1114. X    }
  1115. X    }
  1116. X    tmps_list[tmps_max] = str;
  1117. X    return str;
  1118. X}
  1119. X
  1120. X/* same thing without the copying */
  1121. X
  1122. XSTR *
  1123. Xstr_2static(str)
  1124. Xregister STR *str;
  1125. X{
  1126. X    if (++tmps_max > tmps_size) {
  1127. X    tmps_size = tmps_max;
  1128. X    if (!(tmps_size & 127)) {
  1129. X        if (tmps_size)
  1130. X        Renew(tmps_list, tmps_size + 128, STR*);
  1131. X        else
  1132. X        New(704,tmps_list, 128, STR*);
  1133. X    }
  1134. X    }
  1135. X    tmps_list[tmps_max] = str;
  1136. X    return str;
  1137. X}
  1138. X
  1139. XSTR *
  1140. Xstr_make(s,len)
  1141. Xchar *s;
  1142. Xint len;
  1143. X{
  1144. X    register STR *str = Str_new(79,0);
  1145. X
  1146. X    if (!len)
  1147. X    len = strlen(s);
  1148. X    str_nset(str,s,len);
  1149. X    return str;
  1150. X}
  1151. X
  1152. XSTR *
  1153. Xstr_nmake(n)
  1154. Xdouble n;
  1155. X{
  1156. X    register STR *str = Str_new(80,0);
  1157. X
  1158. X    str_numset(str,n);
  1159. X    return str;
  1160. X}
  1161. X
  1162. X/* make an exact duplicate of old */
  1163. X
  1164. XSTR *
  1165. Xstr_smake(old)
  1166. Xregister STR *old;
  1167. X{
  1168. X    register STR *new = Str_new(81,0);
  1169. X
  1170. X    if (!old)
  1171. X    return Nullstr;
  1172. X    if (old->str_state == SS_FREE) {
  1173. X    warn("semi-panic: attempt to dup freed string");
  1174. X    return Nullstr;
  1175. X    }
  1176. X    if (old->str_state == SS_INCR && !(old->str_pok & 2))
  1177. X    str_grow(old,0);
  1178. X    if (new->str_ptr)
  1179. X    Safefree(new->str_ptr);
  1180. X    Copy(old,new,1,STR);
  1181. X    if (old->str_ptr)
  1182. X    new->str_ptr = nsavestr(old->str_ptr,old->str_len);
  1183. X    return new;
  1184. X}
  1185. X
  1186. Xstr_reset(s,stash)
  1187. Xregister char *s;
  1188. XHASH *stash;
  1189. X{
  1190. X    register HENT *entry;
  1191. X    register STAB *stab;
  1192. X    register STR *str;
  1193. X    register int i;
  1194. X    register SPAT *spat;
  1195. X    register int max;
  1196. X
  1197. X    if (!*s) {        /* reset ?? searches */
  1198. X    for (spat = stash->tbl_spatroot;
  1199. X      spat != Nullspat;
  1200. X      spat = spat->spat_next) {
  1201. X        spat->spat_flags &= ~SPAT_USED;
  1202. X    }
  1203. X    return;
  1204. X    }
  1205. X
  1206. X    /* reset variables */
  1207. X
  1208. X    while (*s) {
  1209. X    i = *s;
  1210. X    if (s[1] == '-') {
  1211. X        s += 2;
  1212. X    }
  1213. X    max = *s++;
  1214. X    for ( ; i <= max; i++) {
  1215. X        for (entry = stash->tbl_array[i];
  1216. X          entry;
  1217. X          entry = entry->hent_next) {
  1218. X        stab = (STAB*)entry->hent_val;
  1219. X        str = stab_val(stab);
  1220. X        str->str_cur = 0;
  1221. X        str->str_nok = 0;
  1222. X#ifdef TAINT
  1223. X        str->str_tainted = tainted;
  1224. X#endif
  1225. X        if (str->str_ptr != Nullch)
  1226. X            str->str_ptr[0] = '\0';
  1227. X        if (stab_xarray(stab)) {
  1228. X            aclear(stab_xarray(stab));
  1229. X        }
  1230. X        if (stab_xhash(stab)) {
  1231. X            hclear(stab_xhash(stab));
  1232. X            if (stab == envstab)
  1233. X            environ[0] = Nullch;
  1234. X        }
  1235. X        }
  1236. X    }
  1237. X    }
  1238. X}
  1239. X
  1240. X#ifdef TAINT
  1241. Xtaintproper(s)
  1242. Xchar *s;
  1243. X{
  1244. X#ifdef DEBUGGING
  1245. X    if (debug & 2048)
  1246. X    fprintf(stderr,"%s %d %d %d\n",s,tainted,uid, euid);
  1247. X#endif
  1248. X    if (tainted && (!euid || euid != uid)) {
  1249. X    if (!unsafe)
  1250. X        fatal("%s", s);
  1251. X    else if (dowarn)
  1252. X        warn("%s", s);
  1253. X    }
  1254. X}
  1255. X
  1256. Xtaintenv()
  1257. X{
  1258. X    register STR *envstr;
  1259. X
  1260. X    envstr = hfetch(stab_hash(envstab),"PATH",4,FALSE);
  1261. X    if (!envstr || envstr->str_tainted) {
  1262. X    tainted = 1;
  1263. X    taintproper("Insecure PATH");
  1264. X    }
  1265. X    envstr = hfetch(stab_hash(envstab),"IFS",3,FALSE);
  1266. X    if (envstr && envstr->str_tainted) {
  1267. X    tainted = 1;
  1268. X    taintproper("Insecure IFS");
  1269. X    }
  1270. X}
  1271. X#endif /* TAINT */
  1272. !STUFFY!FUNK!
  1273. echo Extracting regexec.c
  1274. sed >regexec.c <<'!STUFFY!FUNK!' -e 's/X//'
  1275. X/* NOTE: this is derived from Henry Spencer's regexp code, and should not
  1276. X * confused with the original package (see point 3 below).  Thanks, Henry!
  1277. X */
  1278. X
  1279. X/* Additional note: this code is very heavily munged from Henry's version
  1280. X * in places.  In some spots I've traded clarity for efficiency, so don't
  1281. X * blame Henry for some of the lack of readability.
  1282. X */
  1283. X
  1284. X/* $Header: regexec.c,v 3.0 89/10/18 15:22:53 lwall Locked $
  1285. X *
  1286. X * $Log:    regexec.c,v $
  1287. X * Revision 3.0  89/10/18  15:22:53  lwall
  1288. X * 3.0 baseline
  1289. X * 
  1290. X */
  1291. X
  1292. X/*
  1293. X * regcomp and regexec -- regsub and regerror are not used in perl
  1294. X *
  1295. X *    Copyright (c) 1986 by University of Toronto.
  1296. X *    Written by Henry Spencer.  Not derived from licensed software.
  1297. X *
  1298. X *    Permission is granted to anyone to use this software for any
  1299. X *    purpose on any computer system, and to redistribute it freely,
  1300. X *    subject to the following restrictions:
  1301. X *
  1302. X *    1. The author is not responsible for the consequences of use of
  1303. X *        this software, no matter how awful, even if they arise
  1304. X *        from defects in it.
  1305. X *
  1306. X *    2. The origin of this software must not be misrepresented, either
  1307. X *        by explicit claim or by omission.
  1308. X *
  1309. X *    3. Altered versions must be plainly marked as such, and must not
  1310. X *        be misrepresented as being the original software.
  1311. X *
  1312. X ****    Alterations to Henry's code are...
  1313. X ****
  1314. X ****    Copyright (c) 1989, Larry Wall
  1315. X ****
  1316. X ****    You may distribute under the terms of the GNU General Public License
  1317. X ****    as specified in the README file that comes with the perl 3.0 kit.
  1318. X *
  1319. X * Beware that some of this code is subtly aware of the way operator
  1320. X * precedence is structured in regular expressions.  Serious changes in
  1321. X * regular-expression syntax might require a total rethink.
  1322. X */
  1323. X#include "EXTERN.h"
  1324. X#include "perl.h"
  1325. X#include "regcomp.h"
  1326. X
  1327. X#ifndef STATIC
  1328. X#define    STATIC    static
  1329. X#endif
  1330. X
  1331. X#ifdef DEBUGGING
  1332. Xint regnarrate = 0;
  1333. X#endif
  1334. X
  1335. X/*
  1336. X * regexec and friends
  1337. X */
  1338. X
  1339. X/*
  1340. X * Global work variables for regexec().
  1341. X */
  1342. Xstatic char *regprecomp;
  1343. Xstatic char *reginput;        /* String-input pointer. */
  1344. Xstatic char *regbol;        /* Beginning of input, for ^ check. */
  1345. Xstatic char *regeol;        /* End of input, for $ check. */
  1346. Xstatic char **regstartp;    /* Pointer to startp array. */
  1347. Xstatic char **regendp;        /* Ditto for endp. */
  1348. Xstatic char *reglastparen;    /* Similarly for lastparen. */
  1349. Xstatic char *regtill;
  1350. X
  1351. Xstatic char *regmystartp[10];    /* For remembering backreferences. */
  1352. Xstatic char *regmyendp[10];
  1353. X
  1354. X/*
  1355. X * Forwards.
  1356. X */
  1357. XSTATIC int regtry();
  1358. XSTATIC int regmatch();
  1359. XSTATIC int regrepeat();
  1360. X
  1361. Xextern int multiline;
  1362. X
  1363. X/*
  1364. X - regexec - match a regexp against a string
  1365. X */
  1366. Xint
  1367. Xregexec(prog, stringarg, strend, strbeg, minend, screamer, safebase)
  1368. Xregister regexp *prog;
  1369. Xchar *stringarg;
  1370. Xregister char *strend;    /* pointer to null at end of string */
  1371. Xchar *strbeg;    /* real beginning of string */
  1372. Xint minend;    /* end of match must be at least minend after stringarg */
  1373. XSTR *screamer;
  1374. Xint safebase;    /* no need to remember string in subbase */
  1375. X{
  1376. X    register char *s;
  1377. X    register int i;
  1378. X    register char *c;
  1379. X    register char *string = stringarg;
  1380. X    register int tmp;
  1381. X    int minlen = 0;        /* must match at least this many chars */
  1382. X    int dontbother = 0;    /* how many characters not to try at end */
  1383. X    int beginning = (string == strbeg);    /* is ^ valid at stringarg? */
  1384. X
  1385. X    /* Be paranoid... */
  1386. X    if (prog == NULL || string == NULL) {
  1387. X        fatal("NULL regexp parameter");
  1388. X        return(0);
  1389. X    }
  1390. X
  1391. X    regprecomp = prog->precomp;
  1392. X    /* Check validity of program. */
  1393. X    if (UCHARAT(prog->program) != MAGIC) {
  1394. X        FAIL("corrupted regexp program");
  1395. X    }
  1396. X
  1397. X    if (prog->do_folding) {
  1398. X        safebase = FALSE;
  1399. X        i = strend - string;
  1400. X        New(1101,c,i+1,char);
  1401. X        (void)bcopy(string, c, i+1);
  1402. X        string = c;
  1403. X        strend = string + i;
  1404. X        for (s = string; s < strend; s++)
  1405. X            if (isupper(*s))
  1406. X                *s = tolower(*s);
  1407. X    }
  1408. X
  1409. X    /* If there is a "must appear" string, look for it. */
  1410. X    s = string;
  1411. X    if (prog->regmust != Nullstr) {
  1412. X        if (beginning && screamer) {
  1413. X            if (screamfirst[prog->regmust->str_rare] >= 0)
  1414. X                s = screaminstr(screamer,prog->regmust);
  1415. X            else
  1416. X                s = Nullch;
  1417. X        }
  1418. X#ifndef lint
  1419. X        else
  1420. X            s = fbminstr((unsigned char*)s, (unsigned char*)strend,
  1421. X                prog->regmust);
  1422. X#endif
  1423. X        if (!s) {
  1424. X            ++prog->regmust->str_u.str_useful;    /* hooray */
  1425. X            goto phooey;    /* not present */
  1426. X        }
  1427. X        else if (prog->regback >= 0) {
  1428. X            s -= prog->regback;
  1429. X            if (s < string)
  1430. X                s = string;
  1431. X            minlen = prog->regback + prog->regmust->str_cur;
  1432. X        }
  1433. X        else if (--prog->regmust->str_u.str_useful < 0) { /* boo */
  1434. X            str_free(prog->regmust);
  1435. X            prog->regmust = Nullstr;    /* disable regmust */
  1436. X            s = string;
  1437. X        }
  1438. X        else {
  1439. X            s = string;
  1440. X            minlen = prog->regmust->str_cur;
  1441. X        }
  1442. X    }
  1443. X
  1444. X    /* Mark beginning of line for ^ . */
  1445. X    if (beginning)
  1446. X        regbol = string;
  1447. X    else
  1448. X        regbol = NULL;
  1449. X
  1450. X    /* Mark end of line for $ (and such) */
  1451. X    regeol = strend;
  1452. X
  1453. X    /* see how far we have to get to not match where we matched before */
  1454. X    regtill = string+minend;
  1455. X
  1456. X    /* Simplest case:  anchored match need be tried only once. */
  1457. X    /*  [unless multiline is set] */
  1458. X    if (prog->reganch) {
  1459. X        if (regtry(prog, string))
  1460. X            goto got_it;
  1461. X        else if (multiline) {
  1462. X            if (minlen)
  1463. X                dontbother = minlen - 1;
  1464. X            strend -= dontbother;
  1465. X            /* for multiline we only have to try after newlines */
  1466. X            if (s > string)
  1467. X                s--;
  1468. X            for (; s < strend; s++) {
  1469. X                if (*s == '\n') {
  1470. X                if (++s < strend && regtry(prog, s))
  1471. X                    goto got_it;
  1472. X                }
  1473. X            }
  1474. X        }
  1475. X        goto phooey;
  1476. X    }
  1477. X
  1478. X    /* Messy cases:  unanchored match. */
  1479. X    if (prog->regstart) {
  1480. X        /* We know what string it must start with. */
  1481. X        if (prog->regstart->str_pok == 3) {
  1482. X#ifndef lint
  1483. X            while ((s = fbminstr((unsigned char*)s,
  1484. X              (unsigned char*)strend, prog->regstart)) != NULL)
  1485. X#else
  1486. X            while (s = Nullch)
  1487. X#endif
  1488. X            {
  1489. X                if (regtry(prog, s))
  1490. X                    goto got_it;
  1491. X                s++;
  1492. X            }
  1493. X        }
  1494. X        else {
  1495. X            c = prog->regstart->str_ptr;
  1496. X            while ((s = ninstr(s, strend,
  1497. X              c, c + prog->regstart->str_cur )) != NULL) {
  1498. X                if (regtry(prog, s))
  1499. X                    goto got_it;
  1500. X                s++;
  1501. X            }
  1502. X        }
  1503. X        goto phooey;
  1504. X    }
  1505. X    if (c = prog->regstclass) {
  1506. X        if (minlen)
  1507. X            dontbother = minlen - 1;
  1508. X        strend -= dontbother;    /* don't bother with what can't match */
  1509. X        /* We know what class it must start with. */
  1510. X        switch (OP(c)) {
  1511. X        case ANYOF: case ANYBUT:
  1512. X            c = OPERAND(c);
  1513. X            while (s < strend) {
  1514. X                i = *s;
  1515. X                if (!(c[i >> 3] & (1 << (i&7))))
  1516. X                    if (regtry(prog, s))
  1517. X                        goto got_it;
  1518. X                s++;
  1519. X            }
  1520. X            break;
  1521. X        case BOUND:
  1522. X            if (minlen)
  1523. X            dontbother++,strend--;
  1524. X            if (s != string) {
  1525. X            i = s[-1];
  1526. X            tmp = (isalpha(i) || isdigit(i) || i == '_');
  1527. X            }
  1528. X            else
  1529. X            tmp = 0;    /* assume not alphanumeric */
  1530. X            while (s < strend) {
  1531. X                i = *s;
  1532. X                if (tmp != (isalpha(i) || isdigit(i) || i == '_')) {
  1533. X                    tmp = !tmp;
  1534. X                    if (regtry(prog, s))
  1535. X                        goto got_it;
  1536. X                }
  1537. X                s++;
  1538. X            }
  1539. X            if (tmp && regtry(prog,s))
  1540. X                goto got_it;
  1541. X            break;
  1542. X        case NBOUND:
  1543. X            if (minlen)
  1544. X            dontbother++,strend--;
  1545. X            if (s != string) {
  1546. X            i = s[-1];
  1547. X            tmp = (isalpha(i) || isdigit(i) || i == '_');
  1548. X            }
  1549. X            else
  1550. X            tmp = 0;    /* assume not alphanumeric */
  1551. X            while (s < strend) {
  1552. X                i = *s;
  1553. X                if (tmp != (isalpha(i) || isdigit(i) || i == '_'))
  1554. X                    tmp = !tmp;
  1555. X                else if (regtry(prog, s))
  1556. X                    goto got_it;
  1557. X                s++;
  1558. X            }
  1559. X            if (!tmp && regtry(prog,s))
  1560. X                goto got_it;
  1561. X            break;
  1562. X        case ALNUM:
  1563. X            while (s < strend) {
  1564. X                i = *s;
  1565. X                if (isalpha(i) || isdigit(i) || i == '_')
  1566. X                    if (regtry(prog, s))
  1567. X                        goto got_it;
  1568. X                s++;
  1569. X            }
  1570. X            break;
  1571. X        case NALNUM:
  1572. X            while (s < strend) {
  1573. X                i = *s;
  1574. X                if (!isalpha(i) && !isdigit(i) && i != '_')
  1575. X                    if (regtry(prog, s))
  1576. X                        goto got_it;
  1577. X                s++;
  1578. X            }
  1579. X            break;
  1580. X        case SPACE:
  1581. X            while (s < strend) {
  1582. X                if (isspace(*s))
  1583. X                    if (regtry(prog, s))
  1584. X                        goto got_it;
  1585. X                s++;
  1586. X            }
  1587. X            break;
  1588. X        case NSPACE:
  1589. X            while (s < strend) {
  1590. X                if (!isspace(*s))
  1591. X                    if (regtry(prog, s))
  1592. X                        goto got_it;
  1593. X                s++;
  1594. X            }
  1595. X            break;
  1596. X        case DIGIT:
  1597. X            while (s < strend) {
  1598. X                if (isdigit(*s))
  1599. X                    if (regtry(prog, s))
  1600. X                        goto got_it;
  1601. X                s++;
  1602. X            }
  1603. X            break;
  1604. X        case NDIGIT:
  1605. X            while (s < strend) {
  1606. X                if (!isdigit(*s))
  1607. X                    if (regtry(prog, s))
  1608. X                        goto got_it;
  1609. X                s++;
  1610. X            }
  1611. X            break;
  1612. X        }
  1613. X    }
  1614. X    else {
  1615. X        dontbother = minend;
  1616. X        strend -= dontbother;
  1617. X        /* We don't know much -- general case. */
  1618. X        do {
  1619. X            if (regtry(prog, s))
  1620. X                goto got_it;
  1621. X        } while (s++ < strend);
  1622. X    }
  1623. X
  1624. X    /* Failure. */
  1625. X    goto phooey;
  1626. X
  1627. X    got_it:
  1628. X    if ((!safebase && (prog->nparens || sawampersand)) || prog->do_folding){
  1629. X        strend += dontbother;    /* uncheat */
  1630. X        if (safebase)            /* no need for $digit later */
  1631. X            s = strbeg;
  1632. X        else if (strbeg != prog->subbase) {
  1633. X            i = strend - string + (stringarg - strbeg);
  1634. X            s = nsavestr(strbeg,i);    /* so $digit will work later */
  1635. X            if (prog->subbase)
  1636. X                Safefree(prog->subbase);
  1637. X            prog->subbase = s;
  1638. X        }
  1639. X        else
  1640. X            s = prog->subbase;
  1641. X        s += (stringarg - strbeg);
  1642. X        for (i = 0; i <= prog->nparens; i++) {
  1643. X            if (prog->endp[i]) {
  1644. X                prog->startp[i] = s + (prog->startp[i] - string);
  1645. X                prog->endp[i] = s + (prog->endp[i] - string);
  1646. X            }
  1647. X        }
  1648. X        if (prog->do_folding)
  1649. X            Safefree(string);
  1650. X    }
  1651. X    return(1);
  1652. X
  1653. X    phooey:
  1654. X    if (prog->do_folding)
  1655. X        Safefree(string);
  1656. X    return(0);
  1657. X}
  1658. X
  1659. X/*
  1660. X - regtry - try match at specific point
  1661. X */
  1662. Xstatic int            /* 0 failure, 1 success */
  1663. Xregtry(prog, string)
  1664. Xregexp *prog;
  1665. Xchar *string;
  1666. X{
  1667. X    register int i;
  1668. X    register char **sp;
  1669. X    register char **ep;
  1670. X
  1671. X    reginput = string;
  1672. X    regstartp = prog->startp;
  1673. X    regendp = prog->endp;
  1674. X    reglastparen = &prog->lastparen;
  1675. X    prog->lastparen = 0;
  1676. X
  1677. X    sp = prog->startp;
  1678. X    ep = prog->endp;
  1679. X    if (prog->nparens) {
  1680. X        for (i = NSUBEXP; i > 0; i--) {
  1681. X            *sp++ = NULL;
  1682. X            *ep++ = NULL;
  1683. X        }
  1684. X    }
  1685. X    if (regmatch(prog->program + 1) && reginput >= regtill) {
  1686. X        prog->startp[0] = string;
  1687. X        prog->endp[0] = reginput;
  1688. X        return(1);
  1689. X    } else
  1690. X        return(0);
  1691. X}
  1692. X
  1693. X/*
  1694. X - regmatch - main matching routine
  1695. X *
  1696. X * Conceptually the strategy is simple:  check to see whether the current
  1697. X * node matches, call self recursively to see whether the rest matches,
  1698. X * and then act accordingly.  In practice we make some effort to avoid
  1699. X * recursion, in particular by going through "ordinary" nodes (that don't
  1700. X * need to know whether the rest of the match failed) by a loop instead of
  1701. X * by recursion.
  1702. X */
  1703. X/* [lwall] I've hoisted the register declarations to the outer block in order to
  1704. X * maybe save a little bit of pushing and popping on the stack.  It also takes
  1705. X * advantage of machines that use a register save mask on subroutine entry.
  1706. X */
  1707. Xstatic int            /* 0 failure, 1 success */
  1708. Xregmatch(prog)
  1709. Xchar *prog;
  1710. X{
  1711. X    register char *scan;    /* Current node. */
  1712. X    char *next;        /* Next node. */
  1713. X    register int nextchar;
  1714. X    register int n;        /* no or next */
  1715. X    register int ln;        /* len or last */
  1716. X    register char *s;    /* operand or save */
  1717. X    register char *locinput = reginput;
  1718. X
  1719. X    nextchar = *locinput;
  1720. X    scan = prog;
  1721. X#ifdef DEBUGGING
  1722. X    if (scan != NULL && regnarrate)
  1723. X        fprintf(stderr, "%s(\n", regprop(scan));
  1724. X#endif
  1725. X    while (scan != NULL) {
  1726. X#ifdef DEBUGGING
  1727. X        if (regnarrate)
  1728. X            fprintf(stderr, "%s...\n", regprop(scan));
  1729. X#endif
  1730. X
  1731. X#ifdef REGALIGN
  1732. X        next = scan + NEXT(scan);
  1733. X        if (next == scan)
  1734. X            next = NULL;
  1735. X#else
  1736. X        next = regnext(scan);
  1737. X#endif
  1738. X
  1739. X        switch (OP(scan)) {
  1740. X        case BOL:
  1741. X            if (locinput == regbol ||
  1742. X                ((nextchar || locinput < regeol) &&
  1743. X                  locinput[-1] == '\n') )
  1744. X            {
  1745. X                regtill--;
  1746. X                break;
  1747. X            }
  1748. X            return(0);
  1749. X        case EOL:
  1750. X            if ((nextchar || locinput < regeol) && nextchar != '\n')
  1751. X                return(0);
  1752. X            regtill--;
  1753. X            break;
  1754. X        case ANY:
  1755. X            if ((nextchar == '\0' && locinput >= regeol) ||
  1756. X              nextchar == '\n')
  1757. X                return(0);
  1758. X            nextchar = *++locinput;
  1759. X            break;
  1760. X        case EXACTLY:
  1761. X            s = OPERAND(scan);
  1762. X            ln = *s++;
  1763. X            /* Inline the first character, for speed. */
  1764. X            if (*s != nextchar)
  1765. X                return(0);
  1766. X            if (locinput + ln > regeol)
  1767. X                return 0;
  1768. X            if (ln > 1 && bcmp(s, locinput, ln) != 0)
  1769. X                return(0);
  1770. X            locinput += ln;
  1771. X            nextchar = *locinput;
  1772. X            break;
  1773. X        case ANYOF:
  1774. X        case ANYBUT:
  1775. X            s = OPERAND(scan);
  1776. X            if (nextchar < 0)
  1777. X                nextchar = UCHARAT(locinput);
  1778. X            if (s[nextchar >> 3] & (1 << (nextchar&7)))
  1779. X                return(0);
  1780. X            nextchar = *++locinput;
  1781. X            if (!nextchar && locinput > regeol)
  1782. X                return 0;
  1783. X            break;
  1784. X        case ALNUM:
  1785. X            if (!nextchar)
  1786. X                return(0);
  1787. X            if (!isalpha(nextchar) && !isdigit(nextchar) &&
  1788. X              nextchar != '_')
  1789. X                return(0);
  1790. X            nextchar = *++locinput;
  1791. X            break;
  1792. X        case NALNUM:
  1793. X            if (!nextchar && locinput >= regeol)
  1794. X                return(0);
  1795. X            if (isalpha(nextchar) || isdigit(nextchar) ||
  1796. X              nextchar == '_')
  1797. X                return(0);
  1798. X            nextchar = *++locinput;
  1799. X            break;
  1800. X        case NBOUND:
  1801. X        case BOUND:
  1802. X            if (locinput == regbol)    /* was last char in word? */
  1803. X                ln = 0;
  1804. X            else 
  1805. X                ln = (isalpha(locinput[-1]) ||
  1806. X                     isdigit(locinput[-1]) ||
  1807. X                     locinput[-1] == '_' );
  1808. X            n = (isalpha(nextchar) || isdigit(nextchar) ||
  1809. X                nextchar == '_' );    /* is next char in word? */
  1810. X            if ((ln == n) == (OP(scan) == BOUND))
  1811. X                return(0);
  1812. X            break;
  1813. X        case SPACE:
  1814. X            if (!nextchar && locinput >= regeol)
  1815. X                return(0);
  1816. X            if (!isspace(nextchar))
  1817. X                return(0);
  1818. X            nextchar = *++locinput;
  1819. X            break;
  1820. X        case NSPACE:
  1821. X            if (!nextchar)
  1822. X                return(0);
  1823. X            if (isspace(nextchar))
  1824. X                return(0);
  1825. X            nextchar = *++locinput;
  1826. X            break;
  1827. X        case DIGIT:
  1828. X            if (!isdigit(nextchar))
  1829. X                return(0);
  1830. X            nextchar = *++locinput;
  1831. X            break;
  1832. X        case NDIGIT:
  1833. X            if (!nextchar && locinput >= regeol)
  1834. X                return(0);
  1835. X            if (isdigit(nextchar))
  1836. X                return(0);
  1837. X            nextchar = *++locinput;
  1838. X            break;
  1839. X        case REF:
  1840. X        case REF+1:
  1841. X        case REF+2:
  1842. X        case REF+3:
  1843. X        case REF+4:
  1844. X        case REF+5:
  1845. X        case REF+6:
  1846. X        case REF+7:
  1847. X        case REF+8:
  1848. X        case REF+9:
  1849. X            n = OP(scan) - REF;
  1850. X            s = regmystartp[n];
  1851. X            if (!s)
  1852. X                return(0);
  1853. X            if (!regmyendp[n])
  1854. X                return(0);
  1855. X            if (s == regmyendp[n])
  1856. X                break;
  1857. X            /* Inline the first character, for speed. */
  1858. X            if (*s != nextchar)
  1859. X                return(0);
  1860. X            ln = regmyendp[n] - s;
  1861. X            if (locinput + ln > regeol)
  1862. X                return 0;
  1863. X            if (ln > 1 && bcmp(s, locinput, ln) != 0)
  1864. X                return(0);
  1865. X            locinput += ln;
  1866. X            nextchar = *locinput;
  1867. X            break;
  1868. X
  1869. X        case NOTHING:
  1870. X            break;
  1871. X        case BACK:
  1872. X            break;
  1873. X        case OPEN+1:
  1874. X        case OPEN+2:
  1875. X        case OPEN+3:
  1876. X        case OPEN+4:
  1877. X        case OPEN+5:
  1878. X        case OPEN+6:
  1879. X        case OPEN+7:
  1880. X        case OPEN+8:
  1881. X        case OPEN+9:
  1882. X            n = OP(scan) - OPEN;
  1883. X            reginput = locinput;
  1884. X
  1885. X            regmystartp[n] = locinput;    /* for REF */
  1886. X            if (regmatch(next)) {
  1887. X                /*
  1888. X                 * Don't set startp if some later
  1889. X                 * invocation of the same parentheses
  1890. X                 * already has.
  1891. X                 */
  1892. X                if (regstartp[n] == NULL)
  1893. X                    regstartp[n] = locinput;
  1894. X                return(1);
  1895. X            } else
  1896. X                return(0);
  1897. X            /* NOTREACHED */
  1898. X        case CLOSE+1:
  1899. X        case CLOSE+2:
  1900. X        case CLOSE+3:
  1901. X        case CLOSE+4:
  1902. X        case CLOSE+5:
  1903. X        case CLOSE+6:
  1904. X        case CLOSE+7:
  1905. X        case CLOSE+8:
  1906. X        case CLOSE+9: {
  1907. X                n = OP(scan) - CLOSE;
  1908. X                reginput = locinput;
  1909. X
  1910. X                regmyendp[n] = locinput;    /* for REF */
  1911. X                if (regmatch(next)) {
  1912. X                    /*
  1913. X                     * Don't set endp if some later
  1914. X                     * invocation of the same parentheses
  1915. X                     * already has.
  1916. X                     */
  1917. X                    if (regendp[n] == NULL) {
  1918. X                        regendp[n] = locinput;
  1919. X                        if (n > *reglastparen)
  1920. X                            *reglastparen = n;
  1921. X                    }
  1922. X                    return(1);
  1923. X                } else
  1924. X                    return(0);
  1925. X            }
  1926. X            /*NOTREACHED*/
  1927. X        case BRANCH: {
  1928. X                if (OP(next) != BRANCH)        /* No choice. */
  1929. X                    next = NEXTOPER(scan);    /* Avoid recursion. */
  1930. X                else {
  1931. X                    do {
  1932. X                        reginput = locinput;
  1933. X                        if (regmatch(NEXTOPER(scan)))
  1934. X                            return(1);
  1935. X#ifdef REGALIGN
  1936. X                        if (n = NEXT(scan))
  1937. X                            scan += n;
  1938. X                        else
  1939. X                            scan = NULL;
  1940. X#else
  1941. X                        scan = regnext(scan);
  1942. X#endif
  1943. X                    } while (scan != NULL && OP(scan) == BRANCH);
  1944. X                    return(0);
  1945. X                    /* NOTREACHED */
  1946. X                }
  1947. X            }
  1948. X            break;
  1949. X        case STAR:
  1950. X        case PLUS:
  1951. X            /*
  1952. X             * Lookahead to avoid useless match attempts
  1953. X             * when we know what character comes next.
  1954. X             */
  1955. X            if (OP(next) == EXACTLY)
  1956. X                nextchar = *(OPERAND(next)+1);
  1957. X            else
  1958. X                nextchar = -1000;
  1959. X            ln = (OP(scan) == STAR) ? 0 : 1;
  1960. X            reginput = locinput;
  1961. X            n = regrepeat(NEXTOPER(scan));
  1962. X            while (n >= ln) {
  1963. X                /* If it could work, try it. */
  1964. X                if (nextchar == -1000 || *reginput == nextchar)
  1965. X                    if (regmatch(next))
  1966. X                        return(1);
  1967. X                /* Couldn't or didn't -- back up. */
  1968. X                n--;
  1969. X                reginput = locinput + n;
  1970. X            }
  1971. X            return(0);
  1972. X        case END:
  1973. X            reginput = locinput; /* put where regtry can find it */
  1974. X            return(1);    /* Success! */
  1975. X        default:
  1976. X            printf("%x %d\n",scan,scan[1]);
  1977. X            FAIL("regexp memory corruption");
  1978. X        }
  1979. X
  1980. X        scan = next;
  1981. X    }
  1982. X
  1983. X    /*
  1984. X     * We get here only if there's trouble -- normally "case END" is
  1985. X     * the terminating point.
  1986. X     */
  1987. X    FAIL("corrupted regexp pointers");
  1988. X    /*NOTREACHED*/
  1989. X#ifdef lint
  1990. X    return 0;
  1991. X#endif
  1992. X}
  1993. X
  1994. X/*
  1995. X - regrepeat - repeatedly match something simple, report how many
  1996. X */
  1997. X/*
  1998. X * [This routine now assumes that it will only match on things of length 1.
  1999. X * That was true before, but now we assume scan - reginput is the count,
  2000. X * rather than incrementing count on every character.]
  2001. X */
  2002. Xstatic int
  2003. Xregrepeat(p)
  2004. Xchar *p;
  2005. X{
  2006. X    register char *scan;
  2007. X    register char *opnd;
  2008. X    register int c;
  2009. X    register char *loceol = regeol;
  2010. X
  2011. X    scan = reginput;
  2012. X    opnd = OPERAND(p);
  2013. X    switch (OP(p)) {
  2014. X    case ANY:
  2015. X        while (scan < loceol && *scan != '\n')
  2016. X            scan++;
  2017. X        break;
  2018. X    case EXACTLY:        /* length of string is 1 */
  2019. X        opnd++;
  2020. X        while (scan < loceol && *opnd == *scan)
  2021. X            scan++;
  2022. X        break;
  2023. X    case ANYOF:
  2024. X    case ANYBUT:
  2025. X        c = UCHARAT(scan);
  2026. X        while (scan < loceol && !(opnd[c >> 3] & (1 << (c & 7)))) {
  2027. X            scan++;
  2028. X            c = UCHARAT(scan);
  2029. X        }
  2030. X        break;
  2031. X    case ALNUM:
  2032. X        while (isalpha(*scan) || isdigit(*scan) || *scan == '_')
  2033. X            scan++;
  2034. X        break;
  2035. X    case NALNUM:
  2036. X        while (scan < loceol && (!isalpha(*scan) && !isdigit(*scan) &&
  2037. X          *scan != '_'))
  2038. X            scan++;
  2039. X        break;
  2040. X    case SPACE:
  2041. X        while (scan < loceol && isspace(*scan))
  2042. X            scan++;
  2043. X        break;
  2044. X    case NSPACE:
  2045. X        while (scan < loceol && !isspace(*scan))
  2046. X            scan++;
  2047. X        break;
  2048. X    case DIGIT:
  2049. X        while (isdigit(*scan))
  2050. X            scan++;
  2051. X        break;
  2052. X    case NDIGIT:
  2053. X        while (scan < loceol && !isdigit(*scan))
  2054. X            scan++;
  2055. X        break;
  2056. X    default:        /* Oh dear.  Called inappropriately. */
  2057. X        FAIL("internal regexp foulup");
  2058. X        /* NOTREACHED */
  2059. X    }
  2060. X
  2061. X    c = scan - reginput;
  2062. X    reginput = scan;
  2063. X
  2064. X    return(c);
  2065. X}
  2066. X
  2067. X/*
  2068. X - regnext - dig the "next" pointer out of a node
  2069. X *
  2070. X * [Note, when REGALIGN is defined there are two places in regmatch()
  2071. X * that bypass this code for speed.]
  2072. X */
  2073. Xchar *
  2074. Xregnext(p)
  2075. Xregister char *p;
  2076. X{
  2077. X    register int offset;
  2078. X
  2079. X    if (p == ®dummy)
  2080. X        return(NULL);
  2081. X
  2082. X    offset = NEXT(p);
  2083. X    if (offset == 0)
  2084. X        return(NULL);
  2085. X
  2086. X#ifdef REGALIGN
  2087. X    return(p+offset);
  2088. X#else
  2089. X    if (OP(p) == BACK)
  2090. X        return(p-offset);
  2091. X    else
  2092. X        return(p+offset);
  2093. X#endif
  2094. X}
  2095. !STUFFY!FUNK!
  2096. echo Extracting t/op.split
  2097. sed >t/op.split <<'!STUFFY!FUNK!' -e 's/X//'
  2098. X#!./perl
  2099. X
  2100. X# $Header: op.split,v 3.0 89/10/18 15:31:24 lwall Locked $
  2101. X
  2102. Xprint "1..12\n";
  2103. X
  2104. X$FS = ':';
  2105. X
  2106. X$_ = 'a:b:c';
  2107. X
  2108. X($a,$b,$c) = split($FS,$_);
  2109. X
  2110. Xif (join(';',$a,$b,$c) eq 'a;b;c') {print "ok 1\n";} else {print "not ok 1\n";}
  2111. X
  2112. X@ary = split(/:b:/);
  2113. Xif (join("$_",@ary) eq 'aa:b:cc') {print "ok 2\n";} else {print "not ok 2\n";}
  2114. X
  2115. X$_ = "abc\n";
  2116. X@xyz = (@ary = split(//));
  2117. Xif (join(".",@ary) eq "a.b.c.\n") {print "ok 3\n";} else {print "not ok 3\n";}
  2118. X
  2119. X$_ = "a:b:c::::";
  2120. X@ary = split(/:/);
  2121. Xif (join(".",@ary) eq "a.b.c") {print "ok 4\n";} else {print "not ok 4\n";}
  2122. X
  2123. X$_ = join(':',split(' ',"    a b\tc \t d "));
  2124. Xif ($_ eq 'a:b:c:d') {print "ok 5\n";} else {print "not ok 5 #$_#\n";}
  2125. X
  2126. X$_ = join(':',split(/ */,"foo  bar bie\tdoll"));
  2127. Xif ($_ eq "f:o:o:b:a:r:b:i:e:\t:d:o:l:l")
  2128. X    {print "ok 6\n";} else {print "not ok 6\n";}
  2129. X
  2130. X$_ = join(':', 'foo', split(/ /,'a b  c'), 'bar');
  2131. Xif ($_ eq "foo:a:b::c:bar") {print "ok 7\n";} else {print "not ok 7 $_\n";}
  2132. X
  2133. X# Can we say how many fields to split to?
  2134. X$_ = join(':', split(' ','1 2 3 4 5 6', 3));
  2135. Xprint $_ eq '1:2:3 4 5 6' ? "ok 8\n" : "not ok 8 $_\n";
  2136. X
  2137. X# Can we do it as a variable?
  2138. X$x = 4;
  2139. X$_ = join(':', split(' ','1 2 3 4 5 6', $x));
  2140. Xprint $_ eq '1:2:3:4 5 6' ? "ok 9\n" : "not ok 9 $_\n";
  2141. X
  2142. X# Does the 999 suppress null field chopping?
  2143. X$_ = join(':', split(/:/,'1:2:3:4:5:6:::', 999));
  2144. Xprint $_ eq '1:2:3:4:5:6:::' ? "ok 10\n" : "not ok 10 $_\n";
  2145. X
  2146. X# Does assignment to a list imply split to one more field than that?
  2147. X$foo = `./perl -D1024 -e '(\$a,\$b) = split;' 2>&1`;
  2148. Xprint $foo eq '' || $foo =~ /num\(3\)/ ? "ok 11\n" : "not ok 11\n";
  2149. X
  2150. X# Can we say how many fields to split to when assigning to a list?
  2151. X($a,$b) = split(' ','1 2 3 4 5 6', 2);
  2152. X$_ = join(':',$a,$b);
  2153. Xprint $_ eq '1:2 3 4 5 6' ? "ok 12\n" : "not ok 12 $_\n";
  2154. X
  2155. !STUFFY!FUNK!
  2156. echo ""
  2157. echo "End of kit 13 (of 24)"
  2158. cat /dev/null >kit13isdone
  2159. run=''
  2160. config=''
  2161. for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24; do
  2162.     if test -f kit${iskit}isdone; then
  2163.     run="$run $iskit"
  2164.     else
  2165.     todo="$todo $iskit"
  2166.     fi
  2167. done
  2168. case $todo in
  2169.     '')
  2170.     echo "You have run all your kits.  Please read README and then type Configure."
  2171.     chmod 755 Configure
  2172.     ;;
  2173.     *)  echo "You have run$run."
  2174.     echo "You still need to run$todo."
  2175.     ;;
  2176. esac
  2177. : Someone might mail this, so...
  2178. exit
  2179.  
  2180. -- 
  2181. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  2182. Use a domain-based address or give alternate paths, or you may lose out.
  2183.