PageRenderTime 77ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Source/DOH/string.c

#
C | 1175 lines | 924 code | 120 blank | 131 comment | 252 complexity | e62fcf78d11ca6968a9bd310f10b971b MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1. /* -----------------------------------------------------------------------------
  2. * This file is part of SWIG, which is licensed as a whole under version 3
  3. * (or any later version) of the GNU General Public License. Some additional
  4. * terms also apply to certain portions of SWIG. The full details of the SWIG
  5. * license and copyrights can be found in the LICENSE and COPYRIGHT files
  6. * included with the SWIG source code as distributed by the SWIG developers
  7. * and at http://www.swig.org/legal.html.
  8. *
  9. * string.c
  10. *
  11. * Implements a string object that supports both sequence operations and
  12. * file semantics.
  13. * ----------------------------------------------------------------------------- */
  14. char cvsroot_string_c[] = "$Id: string.c 12849 2011-11-28 19:35:44Z wsfulton $";
  15. #include "dohint.h"
  16. extern DohObjInfo DohStringType;
  17. typedef struct String {
  18. DOH *file;
  19. int line;
  20. int maxsize; /* Max size allocated */
  21. int len; /* Current length */
  22. int hashkey; /* Hash key value */
  23. int sp; /* Current position */
  24. char *str; /* String data */
  25. } String;
  26. /* -----------------------------------------------------------------------------
  27. * String_data() - Return as a 'void *'
  28. * ----------------------------------------------------------------------------- */
  29. static void *String_data(DOH *so) {
  30. String *s = (String *) ObjData(so);
  31. s->str[s->len] = 0;
  32. return (void *) s->str;
  33. }
  34. /* static char *String_char(DOH *so) {
  35. return (char *) String_data(so);
  36. }
  37. */
  38. /* -----------------------------------------------------------------------------
  39. * String_dump() - Serialize a string onto out
  40. * ----------------------------------------------------------------------------- */
  41. static int String_dump(DOH *so, DOH *out) {
  42. int nsent;
  43. int ret;
  44. String *s = (String *) ObjData(so);
  45. nsent = 0;
  46. while (nsent < s->len) {
  47. ret = Write(out, s->str + nsent, (s->len - nsent));
  48. if (ret < 0)
  49. return ret;
  50. nsent += ret;
  51. }
  52. return nsent;
  53. }
  54. /* -----------------------------------------------------------------------------
  55. * CopyString() - Copy a string
  56. * ----------------------------------------------------------------------------- */
  57. static DOH *CopyString(DOH *so) {
  58. String *str;
  59. String *s = (String *) ObjData(so);
  60. str = (String *) DohMalloc(sizeof(String));
  61. str->hashkey = s->hashkey;
  62. str->sp = s->sp;
  63. str->line = s->line;
  64. str->file = s->file;
  65. if (str->file)
  66. Incref(str->file);
  67. str->str = (char *) DohMalloc(s->len + 1);
  68. memcpy(str->str, s->str, s->len);
  69. str->maxsize = s->len;
  70. str->len = s->len;
  71. str->str[str->len] = 0;
  72. return DohObjMalloc(&DohStringType, str);
  73. }
  74. /* -----------------------------------------------------------------------------
  75. * DelString() - Delete a string
  76. * ----------------------------------------------------------------------------- */
  77. static void DelString(DOH *so) {
  78. String *s = (String *) ObjData(so);
  79. DohFree(s->str);
  80. DohFree(s);
  81. }
  82. /* -----------------------------------------------------------------------------
  83. * DohString_len() - Length of a string
  84. * ----------------------------------------------------------------------------- */
  85. static int String_len(DOH *so) {
  86. String *s = (String *) ObjData(so);
  87. return s->len;
  88. }
  89. /* -----------------------------------------------------------------------------
  90. * String_cmp() - Compare two strings
  91. * ----------------------------------------------------------------------------- */
  92. static int String_cmp(DOH *so1, DOH *so2) {
  93. String *s1, *s2;
  94. char *c1, *c2;
  95. int maxlen, i;
  96. s1 = (String *) ObjData(so1);
  97. s2 = (String *) ObjData(so2);
  98. maxlen = s1->len;
  99. if (s2->len < maxlen)
  100. maxlen = s2->len;
  101. c1 = s1->str;
  102. c2 = s2->str;
  103. for (i = maxlen; i; --i, c1++, c2++) {
  104. if (*c1 != *c2)
  105. break;
  106. }
  107. if (i != 0) {
  108. if (*c1 < *c2)
  109. return -1;
  110. else
  111. return 1;
  112. }
  113. if (s1->len == s2->len)
  114. return 0;
  115. if (s1->len > s2->len)
  116. return 1;
  117. return -1;
  118. }
  119. /* -----------------------------------------------------------------------------
  120. * String_equal() - Say if two string are equal
  121. * ----------------------------------------------------------------------------- */
  122. static int String_equal(DOH *so1, DOH *so2) {
  123. String *s1 = (String *) ObjData(so1);
  124. String *s2 = (String *) ObjData(so2);
  125. register int len = s1->len;
  126. if (len != s2->len) {
  127. return 0;
  128. } else {
  129. register char *c1 = s1->str;
  130. register char *c2 = s2->str;
  131. #if 0
  132. register int mlen = len >> 2;
  133. register int i = mlen;
  134. for (; i; --i) {
  135. if (*(c1++) != *(c2++))
  136. return 0;
  137. if (*(c1++) != *(c2++))
  138. return 0;
  139. if (*(c1++) != *(c2++))
  140. return 0;
  141. if (*(c1++) != *(c2++))
  142. return 0;
  143. }
  144. for (i = len - (mlen << 2); i; --i) {
  145. if (*(c1++) != *(c2++))
  146. return 0;
  147. }
  148. return 1;
  149. #else
  150. return memcmp(c1, c2, len) == 0;
  151. #endif
  152. }
  153. }
  154. /* -----------------------------------------------------------------------------
  155. * String_hash() - Compute string hash value
  156. * ----------------------------------------------------------------------------- */
  157. static int String_hash(DOH *so) {
  158. String *s = (String *) ObjData(so);
  159. if (s->hashkey >= 0) {
  160. return s->hashkey;
  161. } else {
  162. register char *c = s->str;
  163. register int len = s->len > 50 ? 50 : s->len;
  164. register int h = 0;
  165. register int mlen = len >> 2;
  166. register int i = mlen;
  167. for (; i; --i) {
  168. h = (h << 5) + *(c++);
  169. h = (h << 5) + *(c++);
  170. h = (h << 5) + *(c++);
  171. h = (h << 5) + *(c++);
  172. }
  173. for (i = len - (mlen << 2); i; --i) {
  174. h = (h << 5) + *(c++);
  175. }
  176. h &= 0x7fffffff;
  177. s->hashkey = h;
  178. return h;
  179. }
  180. }
  181. /* -----------------------------------------------------------------------------
  182. * DohString_append() - Append to s
  183. * ----------------------------------------------------------------------------- */
  184. static void DohString_append(DOH *so, const DOHString_or_char *str) {
  185. int oldlen, newlen, newmaxsize, l, sp;
  186. char *tc;
  187. String *s = (String *) ObjData(so);
  188. char *newstr = 0;
  189. if (DohCheck(str)) {
  190. String *ss = (String *) ObjData(str);
  191. newstr = (char *) String_data((DOH *) str);
  192. l = ss->len;
  193. } else {
  194. newstr = (char *) (str);
  195. l = (int) strlen(newstr);
  196. }
  197. if (!newstr)
  198. return;
  199. s->hashkey = -1;
  200. oldlen = s->len;
  201. newlen = oldlen + l + 1;
  202. if (newlen >= s->maxsize - 1) {
  203. newmaxsize = 2 * s->maxsize;
  204. if (newlen >= newmaxsize - 1)
  205. newmaxsize = newlen + 1;
  206. s->str = (char *) DohRealloc(s->str, newmaxsize);
  207. assert(s->str);
  208. s->maxsize = newmaxsize;
  209. }
  210. tc = s->str;
  211. memcpy(tc + oldlen, newstr, l + 1);
  212. sp = s->sp;
  213. if (sp >= oldlen) {
  214. int i = oldlen + l - sp;
  215. tc += sp;
  216. for (; i; --i) {
  217. if (*(tc++) == '\n')
  218. s->line++;
  219. }
  220. s->sp = oldlen + l;
  221. }
  222. s->len += l;
  223. }
  224. /* -----------------------------------------------------------------------------
  225. * String_clear() - Clear a string
  226. * ----------------------------------------------------------------------------- */
  227. static void String_clear(DOH *so) {
  228. String *s = (String *) ObjData(so);
  229. s->hashkey = -1;
  230. s->len = 0;
  231. *(s->str) = 0;
  232. s->sp = 0;
  233. s->line = 1;
  234. }
  235. /* -----------------------------------------------------------------------------
  236. * String_insert() - Insert a string
  237. * ----------------------------------------------------------------------------- */
  238. static int String_insert(DOH *so, int pos, DOH *str) {
  239. String *s;
  240. int len;
  241. char *data;
  242. if (pos == DOH_END) {
  243. DohString_append(so, str);
  244. return 0;
  245. }
  246. s = (String *) ObjData(so);
  247. s->hashkey = -1;
  248. if (DohCheck(str)) {
  249. String *ss = (String *) ObjData(str);
  250. data = (char *) String_data(str);
  251. len = ss->len;
  252. } else {
  253. data = (char *) (str);
  254. len = (int) strlen(data);
  255. }
  256. if (pos < 0)
  257. pos = 0;
  258. else if (pos > s->len)
  259. pos = s->len;
  260. /* See if there is room to insert the new data */
  261. while (s->maxsize <= s->len + len) {
  262. int newsize = 2 * s->maxsize;
  263. s->str = (char *) DohRealloc(s->str, newsize);
  264. assert(s->str);
  265. s->maxsize = newsize;
  266. }
  267. memmove(s->str + pos + len, s->str + pos, (s->len - pos));
  268. memcpy(s->str + pos, data, len);
  269. if (s->sp >= pos) {
  270. int i;
  271. for (i = 0; i < len; i++) {
  272. if (data[i] == '\n')
  273. s->line++;
  274. }
  275. s->sp += len;
  276. }
  277. s->len += len;
  278. s->str[s->len] = 0;
  279. return 0;
  280. }
  281. /* -----------------------------------------------------------------------------
  282. * String_delitem() - Delete a character
  283. * ----------------------------------------------------------------------------- */
  284. static int String_delitem(DOH *so, int pos) {
  285. String *s = (String *) ObjData(so);
  286. s->hashkey = -1;
  287. if (pos == DOH_END)
  288. pos = s->len - 1;
  289. if (pos == DOH_BEGIN)
  290. pos = 0;
  291. if (s->len == 0)
  292. return 0;
  293. if (s->sp > pos) {
  294. s->sp--;
  295. assert(s->sp >= 0);
  296. if (s->str[pos] == '\n')
  297. s->line--;
  298. }
  299. memmove(s->str + pos, s->str + pos + 1, ((s->len - 1) - pos));
  300. s->len--;
  301. s->str[s->len] = 0;
  302. return 0;
  303. }
  304. /* -----------------------------------------------------------------------------
  305. * String_delslice() - Delete a range
  306. * ----------------------------------------------------------------------------- */
  307. static int String_delslice(DOH *so, int sindex, int eindex) {
  308. String *s = (String *) ObjData(so);
  309. int size;
  310. if (s->len == 0)
  311. return 0;
  312. s->hashkey = -1;
  313. if (eindex == DOH_END)
  314. eindex = s->len;
  315. if (sindex == DOH_BEGIN)
  316. sindex = 0;
  317. size = eindex - sindex;
  318. if (s->sp > sindex) {
  319. /* Adjust the file pointer and line count */
  320. int i, end;
  321. if (s->sp > eindex) {
  322. end = eindex;
  323. s->sp -= size;
  324. } else {
  325. end = s->sp;
  326. s->sp = sindex;
  327. }
  328. for (i = sindex; i < end; i++) {
  329. if (s->str[i] == '\n')
  330. s->line--;
  331. }
  332. assert(s->sp >= 0);
  333. }
  334. memmove(s->str + sindex, s->str + eindex, s->len - eindex);
  335. s->len -= size;
  336. s->str[s->len] = 0;
  337. return 0;
  338. }
  339. /* -----------------------------------------------------------------------------
  340. * String_str() - Returns a string (used by printing commands)
  341. * ----------------------------------------------------------------------------- */
  342. static DOH *String_str(DOH *so) {
  343. String *s = (String *) ObjData(so);
  344. s->str[s->len] = 0;
  345. return NewString(s->str);
  346. }
  347. /* -----------------------------------------------------------------------------
  348. * String_read() - Read data from a string
  349. * ----------------------------------------------------------------------------- */
  350. static int String_read(DOH *so, void *buffer, int len) {
  351. int reallen, retlen;
  352. char *cb;
  353. String *s = (String *) ObjData(so);
  354. if ((s->sp + len) > s->len)
  355. reallen = (s->len - s->sp);
  356. else
  357. reallen = len;
  358. cb = (char *) buffer;
  359. retlen = reallen;
  360. if (reallen > 0) {
  361. memmove(cb, s->str + s->sp, reallen);
  362. s->sp += reallen;
  363. }
  364. return retlen;
  365. }
  366. /* -----------------------------------------------------------------------------
  367. * String_write() - Write data to a string
  368. * ----------------------------------------------------------------------------- */
  369. static int String_write(DOH *so, const void *buffer, int len) {
  370. int newlen;
  371. String *s = (String *) ObjData(so);
  372. s->hashkey = -1;
  373. if (s->sp > s->len)
  374. s->sp = s->len;
  375. newlen = s->sp + len + 1;
  376. if (newlen > s->maxsize) {
  377. s->str = (char *) DohRealloc(s->str, newlen);
  378. assert(s->str);
  379. s->maxsize = newlen;
  380. s->len = s->sp + len;
  381. }
  382. if ((s->sp + len) > s->len)
  383. s->len = s->sp + len;
  384. memmove(s->str + s->sp, buffer, len);
  385. s->sp += len;
  386. s->str[s->len] = 0;
  387. return len;
  388. }
  389. /* -----------------------------------------------------------------------------
  390. * String_seek() - Seek to a new position
  391. * ----------------------------------------------------------------------------- */
  392. static int String_seek(DOH *so, long offset, int whence) {
  393. int pos, nsp, inc;
  394. String *s = (String *) ObjData(so);
  395. if (whence == SEEK_SET)
  396. pos = 0;
  397. else if (whence == SEEK_CUR)
  398. pos = s->sp;
  399. else if (whence == SEEK_END) {
  400. pos = s->len;
  401. offset = -offset;
  402. } else
  403. pos = s->sp;
  404. nsp = pos + offset;
  405. if (nsp < 0)
  406. nsp = 0;
  407. if (s->len > 0 && nsp > s->len)
  408. nsp = s->len;
  409. inc = (nsp > s->sp) ? 1 : -1;
  410. {
  411. #if 0
  412. register int sp = s->sp;
  413. register char *tc = s->str;
  414. register int len = s->len;
  415. while (sp != nsp) {
  416. int prev = sp + inc;
  417. if (prev >= 0 && prev <= len && tc[prev] == '\n')
  418. s->line += inc;
  419. sp += inc;
  420. }
  421. #else
  422. register int sp = s->sp;
  423. register char *tc = s->str;
  424. if (inc > 0) {
  425. while (sp != nsp) {
  426. if (tc[++sp] == '\n')
  427. ++s->line;
  428. }
  429. } else {
  430. while (sp != nsp) {
  431. if (tc[--sp] == '\n')
  432. --s->line;
  433. }
  434. }
  435. #endif
  436. s->sp = sp;
  437. }
  438. assert(s->sp >= 0);
  439. return 0;
  440. }
  441. /* -----------------------------------------------------------------------------
  442. * String_tell() - Return current position
  443. * ----------------------------------------------------------------------------- */
  444. static long String_tell(DOH *so) {
  445. String *s = (String *) ObjData(so);
  446. return (long) (s->sp);
  447. }
  448. /* -----------------------------------------------------------------------------
  449. * String_putc()
  450. * ----------------------------------------------------------------------------- */
  451. static int String_putc(DOH *so, int ch) {
  452. String *s = (String *) ObjData(so);
  453. register int len = s->len;
  454. register int sp = s->sp;
  455. s->hashkey = -1;
  456. if (sp >= len) {
  457. register int maxsize = s->maxsize;
  458. register char *tc = s->str;
  459. if (len > (maxsize - 2)) {
  460. maxsize *= 2;
  461. tc = (char *) DohRealloc(tc, maxsize);
  462. assert(tc);
  463. s->maxsize = (int) maxsize;
  464. s->str = tc;
  465. }
  466. tc += sp;
  467. *tc = (char) ch;
  468. *(++tc) = 0;
  469. s->len = s->sp = sp + 1;
  470. } else {
  471. s->str[s->sp++] = (char) ch;
  472. }
  473. if (ch == '\n')
  474. s->line++;
  475. return ch;
  476. }
  477. /* -----------------------------------------------------------------------------
  478. * String_getc()
  479. * ----------------------------------------------------------------------------- */
  480. static int String_getc(DOH *so) {
  481. int c;
  482. String *s = (String *) ObjData(so);
  483. if (s->sp >= s->len)
  484. c = EOF;
  485. else
  486. c = (int)(unsigned char) s->str[s->sp++];
  487. if (c == '\n')
  488. s->line++;
  489. return c;
  490. }
  491. /* -----------------------------------------------------------------------------
  492. * String_ungetc()
  493. * ----------------------------------------------------------------------------- */
  494. static int String_ungetc(DOH *so, int ch) {
  495. String *s = (String *) ObjData(so);
  496. if (ch == EOF)
  497. return ch;
  498. if (s->sp <= 0)
  499. return EOF;
  500. s->sp--;
  501. if (ch == '\n')
  502. s->line--;
  503. return ch;
  504. }
  505. static char *end_quote(char *s) {
  506. char *qs;
  507. char qc;
  508. char *q;
  509. char *nl;
  510. qc = *s;
  511. qs = s;
  512. while (1) {
  513. q = strpbrk(s + 1, "\"\'");
  514. nl = strchr(s + 1, '\n');
  515. if (nl && (nl < q)) {
  516. /* A new line appears before the end of the string */
  517. if (*(nl - 1) == '\\') {
  518. s = nl + 1;
  519. continue;
  520. }
  521. /* String was terminated by a newline. Wing it */
  522. return qs;
  523. }
  524. if (!q && nl) {
  525. return qs;
  526. }
  527. if (!q)
  528. return 0;
  529. if ((*q == qc) && (*(q - 1) != '\\'))
  530. return q;
  531. s = q;
  532. }
  533. }
  534. static char *match_simple(char *base, char *s, char *token, int tokenlen) {
  535. (void) base;
  536. (void) tokenlen;
  537. return strstr(s, token);
  538. }
  539. static char *match_identifier(char *base, char *s, char *token, int tokenlen) {
  540. while (s) {
  541. s = strstr(s, token);
  542. if (!s)
  543. return 0;
  544. if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) {
  545. s += tokenlen;
  546. continue;
  547. }
  548. if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) {
  549. s += tokenlen;
  550. continue;
  551. }
  552. return s;
  553. }
  554. return 0;
  555. }
  556. static char *match_identifier_begin(char *base, char *s, char *token, int tokenlen) {
  557. while (s) {
  558. s = strstr(s, token);
  559. if (!s)
  560. return 0;
  561. if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) {
  562. s += tokenlen;
  563. continue;
  564. }
  565. return s;
  566. }
  567. return 0;
  568. }
  569. static char *match_identifier_end(char *base, char *s, char *token, int tokenlen) {
  570. (void) base;
  571. while (s) {
  572. s = strstr(s, token);
  573. if (!s)
  574. return 0;
  575. if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) {
  576. s += tokenlen;
  577. continue;
  578. }
  579. return s;
  580. }
  581. return 0;
  582. }
  583. static char *match_number_end(char *base, char *s, char *token, int tokenlen) {
  584. (void) base;
  585. while (s) {
  586. s = strstr(s, token);
  587. if (!s)
  588. return 0;
  589. if (isdigit((int) *(s + tokenlen))) {
  590. s += tokenlen;
  591. continue;
  592. }
  593. return s;
  594. }
  595. return 0;
  596. }
  597. /* -----------------------------------------------------------------------------
  598. * replace_simple()
  599. *
  600. * Replaces count non-overlapping occurrences of token with rep in a string.
  601. * ----------------------------------------------------------------------------- */
  602. static int replace_simple(String *str, char *token, char *rep, int flags, int count, char *(*match) (char *, char *, char *, int)) {
  603. int tokenlen; /* Length of the token */
  604. int replen; /* Length of the replacement */
  605. int delta, expand = 0;
  606. int ic;
  607. int rcount = 0;
  608. int noquote = 0;
  609. char *c, *s, *t, *first;
  610. char *q, *q2;
  611. register char *base;
  612. int i;
  613. /* Figure out if anything gets replaced */
  614. if (!strlen(token))
  615. return 0;
  616. base = str->str;
  617. tokenlen = strlen(token);
  618. s = (*match) (base, base, token, tokenlen);
  619. if (!s)
  620. return 0; /* No matches. Who cares */
  621. str->hashkey = -1;
  622. if (flags & DOH_REPLACE_NOQUOTE)
  623. noquote = 1;
  624. /* If we are not replacing inside quotes, we need to do a little extra work */
  625. if (noquote) {
  626. q = strpbrk(base, "\"\'");
  627. if (!q) {
  628. noquote = 0; /* Well, no quotes to worry about. Oh well */
  629. } else {
  630. while (q && (q < s)) {
  631. /* First match was found inside a quote. Try to find another match */
  632. q2 = end_quote(q);
  633. if (!q2) {
  634. return 0;
  635. }
  636. if (q2 > s) {
  637. /* Find next match */
  638. s = (*match) (base, q2 + 1, token, tokenlen);
  639. }
  640. if (!s)
  641. return 0; /* Oh well, no matches */
  642. q = strpbrk(q2 + 1, "\"\'");
  643. if (!q)
  644. noquote = 0; /* No more quotes */
  645. }
  646. }
  647. }
  648. first = s;
  649. replen = strlen(rep);
  650. delta = (replen - tokenlen);
  651. if (delta <= 0) {
  652. /* String is either shrinking or staying the same size */
  653. /* In this case, we do the replacement in place without memory reallocation */
  654. ic = count;
  655. t = s; /* Target of memory copies */
  656. while (ic && s) {
  657. if (replen) {
  658. memcpy(t, rep, replen);
  659. t += replen;
  660. }
  661. rcount++;
  662. expand += delta;
  663. /* Find the next location */
  664. s += tokenlen;
  665. if (ic == 1)
  666. break;
  667. c = (*match) (base, s, token, tokenlen);
  668. if (noquote) {
  669. q = strpbrk(s, "\"\'");
  670. if (!q) {
  671. noquote = 0;
  672. } else {
  673. while (q && (q < c)) {
  674. /* First match was found inside a quote. Try to find another match */
  675. q2 = end_quote(q);
  676. if (!q2) {
  677. c = 0;
  678. break;
  679. }
  680. if (q2 > c)
  681. c = (*match) (base, q2 + 1, token, tokenlen);
  682. if (!c)
  683. break;
  684. q = strpbrk(q2 + 1, "\"\'");
  685. if (!q)
  686. noquote = 0; /* No more quotes */
  687. }
  688. }
  689. }
  690. if (delta) {
  691. if (c) {
  692. memmove(t, s, c - s);
  693. t += (c - s);
  694. } else {
  695. memmove(t, s, (str->str + str->len) - s + 1);
  696. }
  697. } else {
  698. t += (c - s);
  699. }
  700. s = c;
  701. ic--;
  702. }
  703. if (s && delta) {
  704. memmove(t, s, (str->str + str->len) - s + 1);
  705. }
  706. str->len += expand;
  707. str->str[str->len] = 0;
  708. if (str->sp >= str->len)
  709. str->sp += expand; /* Fix the end of file pointer */
  710. return rcount;
  711. }
  712. /* The string is expanding as a result of the replacement */
  713. /* Figure out how much expansion is going to occur and allocate a new string */
  714. {
  715. char *ns;
  716. int newsize;
  717. rcount++;
  718. ic = count - 1;
  719. s += tokenlen;
  720. while (ic && (c = (*match) (base, s, token, tokenlen))) {
  721. if (noquote) {
  722. q = strpbrk(s, "\"\'");
  723. if (!q) {
  724. break;
  725. } else {
  726. while (q && (q < c)) {
  727. /* First match was found inside a quote. Try to find another match */
  728. q2 = end_quote(q);
  729. if (!q2) {
  730. c = 0;
  731. break;
  732. }
  733. if (q2 > c) {
  734. c = (*match) (base, q2 + 1, token, tokenlen);
  735. if (!c)
  736. break;
  737. }
  738. q = strpbrk(q2 + 1, "\"\'");
  739. if (!q)
  740. noquote = 0;
  741. }
  742. }
  743. }
  744. if (c) {
  745. rcount++;
  746. ic--;
  747. s = c + tokenlen;
  748. } else {
  749. break;
  750. }
  751. }
  752. expand = delta * rcount; /* Total amount of expansion for the replacement */
  753. newsize = str->maxsize;
  754. while ((str->len + expand) >= newsize)
  755. newsize *= 2;
  756. ns = (char *) DohMalloc(newsize);
  757. assert(ns);
  758. t = ns;
  759. s = first;
  760. /* Copy the first part of the string */
  761. if (first > str->str) {
  762. memcpy(t, str->str, (first - str->str));
  763. t += (first - str->str);
  764. }
  765. for (i = 0; i < rcount; i++) {
  766. memcpy(t, rep, replen);
  767. t += replen;
  768. s += tokenlen;
  769. c = (*match) (base, s, token, tokenlen);
  770. if (noquote) {
  771. q = strpbrk(s, "\"\'");
  772. if (!q) {
  773. noquote = 0;
  774. } else {
  775. while (q && (q < c)) {
  776. /* First match was found inside a quote. Try to find another match */
  777. q2 = end_quote(q);
  778. if (!q2) {
  779. c = 0;
  780. break;
  781. }
  782. if (q2 > c) {
  783. c = (*match) (base, q2 + 1, token, tokenlen);
  784. if (!c)
  785. break;
  786. }
  787. q = strpbrk(q2 + 1, "\"\'");
  788. if (!q)
  789. noquote = 0; /* No more quotes */
  790. }
  791. }
  792. }
  793. if (i < (rcount - 1)) {
  794. memcpy(t, s, c - s);
  795. t += (c - s);
  796. } else {
  797. memcpy(t, s, (str->str + str->len) - s + 1);
  798. }
  799. s = c;
  800. }
  801. c = str->str;
  802. str->str = ns;
  803. if (str->sp >= str->len)
  804. str->sp += expand;
  805. str->len += expand;
  806. str->str[str->len] = 0;
  807. str->maxsize = newsize;
  808. DohFree(c);
  809. return rcount;
  810. }
  811. }
  812. /* -----------------------------------------------------------------------------
  813. * String_replace()
  814. * ----------------------------------------------------------------------------- */
  815. static int String_replace(DOH *stro, const DOHString_or_char *token, const DOHString_or_char *rep, int flags) {
  816. int count = -1;
  817. String *str = (String *) ObjData(stro);
  818. if (flags & DOH_REPLACE_FIRST)
  819. count = 1;
  820. if (flags & DOH_REPLACE_ID_END) {
  821. return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_end);
  822. } else if (flags & DOH_REPLACE_ID_BEGIN) {
  823. return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_begin);
  824. } else if (flags & DOH_REPLACE_ID) {
  825. return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier);
  826. } else if (flags & DOH_REPLACE_NUMBER_END) {
  827. return replace_simple(str, Char(token), Char(rep), flags, count, match_number_end);
  828. } else {
  829. return replace_simple(str, Char(token), Char(rep), flags, count, match_simple);
  830. }
  831. }
  832. /* -----------------------------------------------------------------------------
  833. * String_chop()
  834. * ----------------------------------------------------------------------------- */
  835. static void String_chop(DOH *so) {
  836. char *c;
  837. String *str = (String *) ObjData(so);
  838. /* Replace trailing whitespace */
  839. c = str->str + str->len - 1;
  840. while ((str->len > 0) && (isspace((int) *c))) {
  841. if (str->sp >= str->len) {
  842. str->sp--;
  843. if (*c == '\n')
  844. str->line--;
  845. }
  846. str->len--;
  847. c--;
  848. }
  849. str->str[str->len] = 0;
  850. assert(str->sp >= 0);
  851. str->hashkey = -1;
  852. }
  853. static void String_setfile(DOH *so, DOH *file) {
  854. DOH *fo;
  855. String *str = (String *) ObjData(so);
  856. if (!DohCheck(file)) {
  857. fo = NewString(file);
  858. Decref(fo);
  859. } else
  860. fo = file;
  861. Incref(fo);
  862. Delete(str->file);
  863. str->file = fo;
  864. }
  865. static DOH *String_getfile(DOH *so) {
  866. String *str = (String *) ObjData(so);
  867. return str->file;
  868. }
  869. static void String_setline(DOH *so, int line) {
  870. String *str = (String *) ObjData(so);
  871. str->line = line;
  872. }
  873. static int String_getline(DOH *so) {
  874. String *str = (String *) ObjData(so);
  875. return str->line;
  876. }
  877. static DohListMethods StringListMethods = {
  878. 0, /* doh_getitem */
  879. 0, /* doh_setitem */
  880. String_delitem, /* doh_delitem */
  881. String_insert, /* doh_insitem */
  882. String_delslice, /* doh_delslice */
  883. };
  884. static DohFileMethods StringFileMethods = {
  885. String_read,
  886. String_write,
  887. String_putc,
  888. String_getc,
  889. String_ungetc,
  890. String_seek,
  891. String_tell,
  892. 0, /* close */
  893. };
  894. static DohStringMethods StringStringMethods = {
  895. String_replace,
  896. String_chop,
  897. };
  898. DohObjInfo DohStringType = {
  899. "String", /* objname */
  900. DelString, /* doh_del */
  901. CopyString, /* doh_copy */
  902. String_clear, /* doh_clear */
  903. String_str, /* doh_str */
  904. String_data, /* doh_data */
  905. String_dump, /* doh_dump */
  906. String_len, /* doh_len */
  907. String_hash, /* doh_hash */
  908. String_cmp, /* doh_cmp */
  909. String_equal, /* doh_equal */
  910. 0, /* doh_first */
  911. 0, /* doh_next */
  912. String_setfile, /* doh_setfile */
  913. String_getfile, /* doh_getfile */
  914. String_setline, /* doh_setline */
  915. String_getline, /* doh_getline */
  916. 0, /* doh_mapping */
  917. &StringListMethods, /* doh_sequence */
  918. &StringFileMethods, /* doh_file */
  919. &StringStringMethods, /* doh_string */
  920. 0, /* doh_position */
  921. 0
  922. };
  923. #define INIT_MAXSIZE 16
  924. /* -----------------------------------------------------------------------------
  925. * NewString() - Create a new string
  926. * ----------------------------------------------------------------------------- */
  927. DOHString *DohNewString(const DOHString_or_char *so) {
  928. int l = 0, max;
  929. String *str;
  930. char *s;
  931. int hashkey = -1;
  932. if (DohCheck(so)) {
  933. str = (String *) ObjData(so);
  934. s = (char *) String_data((String *) so);
  935. l = s ? str->len : 0;
  936. hashkey = str->hashkey;
  937. } else {
  938. s = (char *) so;
  939. l = s ? (int) strlen(s) : 0;
  940. }
  941. str = (String *) DohMalloc(sizeof(String));
  942. str->hashkey = hashkey;
  943. str->sp = 0;
  944. str->line = 1;
  945. str->file = 0;
  946. max = INIT_MAXSIZE;
  947. if (s) {
  948. if ((l + 1) > max)
  949. max = l + 1;
  950. }
  951. str->str = (char *) DohMalloc(max);
  952. str->maxsize = max;
  953. if (s) {
  954. strcpy(str->str, s);
  955. str->len = l;
  956. str->sp = l;
  957. } else {
  958. str->str[0] = 0;
  959. str->len = 0;
  960. }
  961. return DohObjMalloc(&DohStringType, str);
  962. }
  963. /* -----------------------------------------------------------------------------
  964. * NewStringEmpty() - Create a new string
  965. * ----------------------------------------------------------------------------- */
  966. DOHString *DohNewStringEmpty(void) {
  967. int max = INIT_MAXSIZE;
  968. String *str = (String *) DohMalloc(sizeof(String));
  969. str->hashkey = 0;
  970. str->sp = 0;
  971. str->line = 1;
  972. str->file = 0;
  973. str->str = (char *) DohMalloc(max);
  974. str->maxsize = max;
  975. str->str[0] = 0;
  976. str->len = 0;
  977. return DohObjMalloc(&DohStringType, str);
  978. }
  979. /* -----------------------------------------------------------------------------
  980. * NewStringWithSize() - Create a new string
  981. * ----------------------------------------------------------------------------- */
  982. DOHString *DohNewStringWithSize(const DOHString_or_char *so, int len) {
  983. int l = 0, max;
  984. String *str;
  985. char *s;
  986. if (DohCheck(so)) {
  987. s = (char *) String_data((String *) so);
  988. } else {
  989. s = (char *) so;
  990. }
  991. str = (String *) DohMalloc(sizeof(String));
  992. str->hashkey = -1;
  993. str->sp = 0;
  994. str->line = 1;
  995. str->file = 0;
  996. max = INIT_MAXSIZE;
  997. if (s) {
  998. l = (int) len;
  999. if ((l + 1) > max)
  1000. max = l + 1;
  1001. }
  1002. str->str = (char *) DohMalloc(max);
  1003. str->maxsize = max;
  1004. if (s) {
  1005. strncpy(str->str, s, len);
  1006. str->len = l;
  1007. str->sp = l;
  1008. } else {
  1009. str->str[0] = 0;
  1010. str->len = 0;
  1011. }
  1012. return DohObjMalloc(&DohStringType, str);
  1013. }
  1014. /* -----------------------------------------------------------------------------
  1015. * NewStringf()
  1016. *
  1017. * Create a new string from a list of objects.
  1018. * ----------------------------------------------------------------------------- */
  1019. DOHString *DohNewStringf(const DOHString_or_char *fmt, ...) {
  1020. va_list ap;
  1021. DOH *r;
  1022. va_start(ap, fmt);
  1023. r = NewStringEmpty();
  1024. DohvPrintf(r, Char(fmt), ap);
  1025. va_end(ap);
  1026. return (DOHString *) r;
  1027. }
  1028. /* -----------------------------------------------------------------------------
  1029. * Strcmp()
  1030. * Strncmp()
  1031. * Strstr()
  1032. * Strchr()
  1033. *
  1034. * Some utility functions.
  1035. * ----------------------------------------------------------------------------- */
  1036. int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2) {
  1037. const char *c1 = Char(s1);
  1038. const char *c2 = Char(s2);
  1039. if (c1 && c2) {
  1040. return strcmp(c1, c2);
  1041. } else {
  1042. return c1 < c2;
  1043. }
  1044. }
  1045. int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n) {
  1046. return strncmp(Char(s1), Char(s2), n);
  1047. }
  1048. char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2) {
  1049. char *p1 = Char(s1);
  1050. char *p2 = Char(s2);
  1051. return p1 == 0 || p2 == 0 || *p2 == '\0' ? p1 : strstr(p1, p2);
  1052. }
  1053. char *DohStrchr(const DOHString_or_char *s1, int ch) {
  1054. return strchr(Char(s1), ch);
  1055. }