PageRenderTime 35ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/cmd/awk/lib.c

https://bitbucket.org/a3217055/illumos-joyent
C | 795 lines | 662 code | 76 blank | 57 comment | 270 complexity | f7f41439fc25c60fb355e1f41b63747c MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, GPL-2.0, GPL-3.0, 0BSD, BSD-2-Clause, BSD-3-Clause-No-Nuclear-License-2014, MPL-2.0-no-copyleft-exception, AGPL-1.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License (the "License").
  6. * You may not use this file except in compliance with the License.
  7. *
  8. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  9. * or http://www.opensolaris.org/os/licensing.
  10. * See the License for the specific language governing permissions
  11. * and limitations under the License.
  12. *
  13. * When distributing Covered Code, include this CDDL HEADER in each
  14. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15. * If applicable, add the following below this CDDL HEADER, with the
  16. * fields enclosed by brackets "[]" replaced with your own identifying
  17. * information: Portions Copyright [yyyy] [name of copyright owner]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  23. * Use is subject to license terms.
  24. */
  25. /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  26. /* All Rights Reserved */
  27. #pragma ident "%Z%%M% %I% %E% SMI"
  28. #include <errno.h>
  29. #include "awk.h"
  30. #include "y.tab.h"
  31. uchar *record;
  32. size_t record_size;
  33. int donefld; /* 1 = implies rec broken into fields */
  34. int donerec; /* 1 = record is valid (no flds have changed) */
  35. static struct fldtab_chunk {
  36. struct fldtab_chunk *next;
  37. Cell fields[FLD_INCR];
  38. } *fldtab_head, *fldtab_tail;
  39. static size_t fldtab_maxidx;
  40. static FILE *infile = NULL;
  41. static uchar *file = (uchar*) "";
  42. static uchar *fields;
  43. static size_t fields_size = LINE_INCR;
  44. static int maxfld = 0; /* last used field */
  45. static int argno = 1; /* current input argument number */
  46. static uchar *getargv(int);
  47. static void cleanfld(int, int);
  48. static int refldbld(uchar *, uchar *);
  49. static void bcheck2(int, int, int);
  50. static void eprint(void);
  51. static void bclass(int);
  52. static void
  53. initgetrec(void)
  54. {
  55. int i;
  56. uchar *p;
  57. for (i = 1; i < *ARGC; i++) {
  58. if (!isclvar(p = getargv(i))) /* find 1st real filename */
  59. return;
  60. setclvar(p); /* a commandline assignment before filename */
  61. argno++;
  62. }
  63. infile = stdin; /* no filenames, so use stdin */
  64. /* *FILENAME = file = (uchar*) "-"; */
  65. }
  66. int
  67. getrec(uchar **bufp, size_t *bufsizep)
  68. {
  69. int c;
  70. static int firsttime = 1;
  71. uchar_t *buf, *nbuf;
  72. size_t len;
  73. if (firsttime) {
  74. firsttime = 0;
  75. initgetrec();
  76. }
  77. dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n",
  78. *RS, *FS, *ARGC, *FILENAME));
  79. donefld = 0;
  80. donerec = 1;
  81. while (argno < *ARGC || infile == stdin) {
  82. dprintf(("argno=%d, file=|%s|\n", argno, file));
  83. if (infile == NULL) { /* have to open a new file */
  84. file = getargv(argno);
  85. if (*file == '\0') { /* it's been zapped */
  86. argno++;
  87. continue;
  88. }
  89. if (isclvar(file)) { /* a var=value arg */
  90. setclvar(file);
  91. argno++;
  92. continue;
  93. }
  94. *FILENAME = file;
  95. dprintf(("opening file %s\n", file));
  96. if (*file == '-' && *(file+1) == '\0')
  97. infile = stdin;
  98. else if ((infile = fopen((char *)file, "r")) == NULL)
  99. ERROR "can't open file %s", file FATAL;
  100. (void) setfval(fnrloc, 0.0);
  101. }
  102. c = readrec(&nbuf, &len, infile);
  103. expand_buf(bufp, bufsizep, len);
  104. buf = *bufp;
  105. (void) memcpy(buf, nbuf, len);
  106. buf[len] = '\0';
  107. free(nbuf);
  108. if (c != 0 || buf[0] != '\0') { /* normal record */
  109. if (bufp == &record) {
  110. if (!(recloc->tval & DONTFREE))
  111. xfree(recloc->sval);
  112. recloc->sval = record;
  113. recloc->tval = REC | STR | DONTFREE;
  114. if (is_number(recloc->sval)) {
  115. recloc->fval =
  116. atof((const char *)recloc->sval);
  117. recloc->tval |= NUM;
  118. }
  119. }
  120. (void) setfval(nrloc, nrloc->fval+1);
  121. (void) setfval(fnrloc, fnrloc->fval+1);
  122. return (1);
  123. }
  124. /* EOF arrived on this file; set up next */
  125. if (infile != stdin)
  126. (void) fclose(infile);
  127. infile = NULL;
  128. argno++;
  129. }
  130. return (0); /* true end of file */
  131. }
  132. int
  133. readrec(uchar **bufp, size_t *sizep, FILE *inf) /* read one record into buf */
  134. {
  135. int sep, c;
  136. uchar *buf;
  137. int count;
  138. size_t bufsize;
  139. init_buf(&buf, &bufsize, LINE_INCR);
  140. if ((sep = **RS) == 0) {
  141. sep = '\n';
  142. /* skip leading \n's */
  143. while ((c = getc(inf)) == '\n' && c != EOF)
  144. ;
  145. if (c != EOF)
  146. (void) ungetc(c, inf);
  147. }
  148. count = 0;
  149. for (;;) {
  150. while ((c = getc(inf)) != sep && c != EOF) {
  151. expand_buf(&buf, &bufsize, count);
  152. buf[count++] = c;
  153. }
  154. if (**RS == sep || c == EOF)
  155. break;
  156. if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
  157. break;
  158. expand_buf(&buf, &bufsize, count + 1);
  159. buf[count++] = '\n';
  160. buf[count++] = c;
  161. }
  162. buf[count] = '\0';
  163. dprintf(("readrec saw <%s>, returns %d\n",
  164. buf, c == EOF && count == 0 ? 0 : 1));
  165. *bufp = buf;
  166. *sizep = count;
  167. return (c == EOF && count == 0 ? 0 : 1);
  168. }
  169. /* get ARGV[n] */
  170. static uchar *
  171. getargv(int n)
  172. {
  173. Cell *x;
  174. uchar *s, temp[11];
  175. extern Array *ARGVtab;
  176. (void) sprintf((char *)temp, "%d", n);
  177. x = setsymtab(temp, (uchar *)"", 0.0, STR, ARGVtab);
  178. s = getsval(x);
  179. dprintf(("getargv(%d) returns |%s|\n", n, s));
  180. return (s);
  181. }
  182. void
  183. setclvar(uchar *s) /* set var=value from s */
  184. {
  185. uchar *p;
  186. Cell *q;
  187. for (p = s; *p != '='; p++)
  188. ;
  189. *p++ = 0;
  190. p = qstring(p, '\0');
  191. q = setsymtab(s, p, 0.0, STR, symtab);
  192. (void) setsval(q, p);
  193. if (is_number(q->sval)) {
  194. q->fval = atof((const char *)q->sval);
  195. q->tval |= NUM;
  196. }
  197. dprintf(("command line set %s to |%s|\n", s, p));
  198. free(p);
  199. }
  200. void
  201. fldbld(void)
  202. {
  203. uchar *r, *fr, sep;
  204. Cell *p;
  205. int i;
  206. size_t len;
  207. if (donefld)
  208. return;
  209. if (!(recloc->tval & STR))
  210. (void) getsval(recloc);
  211. r = recloc->sval; /* was record! */
  212. /* make sure fields is always allocated */
  213. adjust_buf(&fields, fields_size);
  214. /*
  215. * make sure fields has enough size. We don't expand the buffer
  216. * in the middle of the loop, since p->sval has already pointed
  217. * the address in the fields.
  218. */
  219. len = strlen((char *)r) + 1;
  220. expand_buf(&fields, &fields_size, len);
  221. fr = fields;
  222. i = 0; /* number of fields accumulated here */
  223. if (strlen((char *)*FS) > 1) { /* it's a regular expression */
  224. i = refldbld(r, *FS);
  225. } else if ((sep = **FS) == ' ') {
  226. for (i = 0; ; ) {
  227. while (*r == ' ' || *r == '\t' || *r == '\n')
  228. r++;
  229. if (*r == 0)
  230. break;
  231. i++;
  232. p = getfld(i);
  233. if (!(p->tval & DONTFREE))
  234. xfree(p->sval);
  235. p->sval = fr;
  236. p->tval = FLD | STR | DONTFREE;
  237. do
  238. *fr++ = *r++;
  239. while (*r != ' ' && *r != '\t' && *r != '\n' &&
  240. *r != '\0')
  241. ;
  242. *fr++ = 0;
  243. }
  244. *fr = 0;
  245. } else if (*r != 0) { /* if 0, it's a null field */
  246. for (;;) {
  247. i++;
  248. p = getfld(i);
  249. if (!(p->tval & DONTFREE))
  250. xfree(p->sval);
  251. p->sval = fr;
  252. p->tval = FLD | STR | DONTFREE;
  253. /* \n always a separator */
  254. while (*r != sep && *r != '\n' && *r != '\0')
  255. *fr++ = *r++;
  256. *fr++ = 0;
  257. if (*r++ == 0)
  258. break;
  259. }
  260. *fr = 0;
  261. }
  262. /* clean out junk from previous record */
  263. cleanfld(i, maxfld);
  264. maxfld = i;
  265. donefld = 1;
  266. for (i = 1; i <= maxfld; i++) {
  267. p = getfld(i);
  268. if (is_number(p->sval)) {
  269. p->fval = atof((const char *)p->sval);
  270. p->tval |= NUM;
  271. }
  272. }
  273. (void) setfval(nfloc, (Awkfloat) maxfld);
  274. if (dbg) {
  275. for (i = 0; i <= maxfld; i++) {
  276. p = getfld(i);
  277. (void) printf("field %d: |%s|\n", i, p->sval);
  278. }
  279. }
  280. }
  281. static void
  282. cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */
  283. {
  284. static uchar *nullstat = (uchar *) "";
  285. Cell *p;
  286. int i;
  287. for (i = n2; i > n1; i--) {
  288. p = getfld(i);
  289. if (!(p->tval & DONTFREE))
  290. xfree(p->sval);
  291. p->tval = FLD | STR | DONTFREE;
  292. p->sval = nullstat;
  293. }
  294. }
  295. void
  296. newfld(int n) /* add field n (after end) */
  297. {
  298. if (n < 0)
  299. ERROR "accessing invalid field", record FATAL;
  300. (void) getfld(n);
  301. cleanfld(maxfld, n);
  302. maxfld = n;
  303. (void) setfval(nfloc, (Awkfloat) n);
  304. }
  305. /*
  306. * allocate field table. We don't reallocate the table since there
  307. * might be somewhere recording the address of the table.
  308. */
  309. static void
  310. morefld(void)
  311. {
  312. int i;
  313. struct fldtab_chunk *fldcp;
  314. Cell *newfld;
  315. if ((fldcp = calloc(sizeof (struct fldtab_chunk), 1)) == NULL)
  316. ERROR "out of space in morefld" FATAL;
  317. newfld = &fldcp->fields[0];
  318. for (i = 0; i < FLD_INCR; i++) {
  319. newfld[i].ctype = OCELL;
  320. newfld[i].csub = CFLD;
  321. newfld[i].nval = NULL;
  322. newfld[i].sval = (uchar *)"";
  323. newfld[i].fval = 0.0;
  324. newfld[i].tval = FLD|STR|DONTFREE;
  325. newfld[i].cnext = NULL;
  326. }
  327. /*
  328. * link this field chunk
  329. */
  330. if (fldtab_head == NULL)
  331. fldtab_head = fldcp;
  332. else
  333. fldtab_tail->next = fldcp;
  334. fldtab_tail = fldcp;
  335. fldcp->next = NULL;
  336. fldtab_maxidx += FLD_INCR;
  337. }
  338. Cell *
  339. getfld(int idx)
  340. {
  341. struct fldtab_chunk *fldcp;
  342. int cbase;
  343. if (idx < 0)
  344. ERROR "trying to access field %d", idx FATAL;
  345. while (idx >= fldtab_maxidx)
  346. morefld();
  347. cbase = 0;
  348. for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) {
  349. if (idx < (cbase + FLD_INCR))
  350. return (&fldcp->fields[idx - cbase]);
  351. cbase += FLD_INCR;
  352. }
  353. /* should never happen */
  354. ERROR "trying to access invalid field %d", idx FATAL;
  355. return (NULL);
  356. }
  357. int
  358. fldidx(Cell *vp)
  359. {
  360. struct fldtab_chunk *fldcp;
  361. Cell *tbl;
  362. int cbase;
  363. cbase = 0;
  364. for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) {
  365. tbl = &fldcp->fields[0];
  366. if (vp >= tbl && vp < (tbl + FLD_INCR))
  367. return (cbase + (vp - tbl));
  368. cbase += FLD_INCR;
  369. }
  370. /* should never happen */
  371. ERROR "trying to access unknown field" FATAL;
  372. return (0);
  373. }
  374. static int
  375. refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */
  376. {
  377. uchar *fr;
  378. int i, tempstat;
  379. fa *pfa;
  380. Cell *p;
  381. size_t len;
  382. /* make sure fields is allocated */
  383. adjust_buf(&fields, fields_size);
  384. fr = fields;
  385. *fr = '\0';
  386. if (*rec == '\0')
  387. return (0);
  388. len = strlen((char *)rec) + 1;
  389. expand_buf(&fields, &fields_size, len);
  390. fr = fields;
  391. pfa = makedfa(fs, 1);
  392. dprintf(("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs));
  393. tempstat = pfa->initstat;
  394. for (i = 1; ; i++) {
  395. p = getfld(i);
  396. if (!(p->tval & DONTFREE))
  397. xfree(p->sval);
  398. p->tval = FLD | STR | DONTFREE;
  399. p->sval = fr;
  400. dprintf(("refldbld: i=%d\n", i));
  401. if (nematch(pfa, rec)) {
  402. pfa->initstat = 2;
  403. dprintf(("match %s (%d chars)\n", patbeg, patlen));
  404. (void) strncpy((char *)fr, (char *)rec, patbeg-rec);
  405. fr += patbeg - rec + 1;
  406. *(fr-1) = '\0';
  407. rec = patbeg + patlen;
  408. } else {
  409. dprintf(("no match %s\n", rec));
  410. (void) strcpy((char *)fr, (char *)rec);
  411. pfa->initstat = tempstat;
  412. break;
  413. }
  414. }
  415. return (i);
  416. }
  417. void
  418. recbld(void)
  419. {
  420. int i;
  421. uchar *p;
  422. size_t cnt, len, olen;
  423. if (donerec == 1)
  424. return;
  425. cnt = 0;
  426. olen = strlen((char *)*OFS);
  427. for (i = 1; i <= *NF; i++) {
  428. p = getsval(getfld(i));
  429. len = strlen((char *)p);
  430. expand_buf(&record, &record_size, cnt + len + olen);
  431. (void) memcpy(&record[cnt], p, len);
  432. cnt += len;
  433. if (i < *NF) {
  434. (void) memcpy(&record[cnt], *OFS, olen);
  435. cnt += olen;
  436. }
  437. }
  438. record[cnt] = '\0';
  439. dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc));
  440. if (!(recloc->tval & DONTFREE))
  441. xfree(recloc->sval);
  442. recloc->tval = REC | STR | DONTFREE;
  443. recloc->sval = record;
  444. dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc));
  445. dprintf(("recbld = |%s|\n", record));
  446. donerec = 1;
  447. }
  448. Cell *
  449. fieldadr(int n)
  450. {
  451. if (n < 0)
  452. ERROR "trying to access field %d", n FATAL;
  453. return (getfld(n));
  454. }
  455. int errorflag = 0;
  456. char errbuf[200];
  457. void
  458. yyerror(char *s)
  459. {
  460. extern uchar *cmdname, *curfname;
  461. static int been_here = 0;
  462. if (been_here++ > 2)
  463. return;
  464. (void) fprintf(stderr, "%s: %s", cmdname, s);
  465. (void) fprintf(stderr, gettext(" at source line %lld"), lineno);
  466. if (curfname != NULL)
  467. (void) fprintf(stderr, gettext(" in function %s"), curfname);
  468. (void) fprintf(stderr, "\n");
  469. errorflag = 2;
  470. eprint();
  471. }
  472. /*ARGSUSED*/
  473. void
  474. fpecatch(int sig)
  475. {
  476. ERROR "floating point exception" FATAL;
  477. }
  478. extern int bracecnt, brackcnt, parencnt;
  479. void
  480. bracecheck(void)
  481. {
  482. int c;
  483. static int beenhere = 0;
  484. if (beenhere++)
  485. return;
  486. while ((c = input()) != EOF && c != '\0')
  487. bclass(c);
  488. bcheck2(bracecnt, '{', '}');
  489. bcheck2(brackcnt, '[', ']');
  490. bcheck2(parencnt, '(', ')');
  491. }
  492. /*ARGSUSED*/
  493. static void
  494. bcheck2(int n, int c1, int c2)
  495. {
  496. if (n == 1)
  497. (void) fprintf(stderr, gettext("\tmissing %c\n"), c2);
  498. else if (n > 1)
  499. (void) fprintf(stderr, gettext("\t%d missing %c's\n"), n, c2);
  500. else if (n == -1)
  501. (void) fprintf(stderr, gettext("\textra %c\n"), c2);
  502. else if (n < -1)
  503. (void) fprintf(stderr, gettext("\t%d extra %c's\n"), -n, c2);
  504. }
  505. void
  506. error(int f, char *s)
  507. {
  508. extern Node *curnode;
  509. extern uchar *cmdname;
  510. (void) fflush(stdout);
  511. (void) fprintf(stderr, "%s: ", cmdname);
  512. (void) fprintf(stderr, "%s", s);
  513. (void) fprintf(stderr, "\n");
  514. if (compile_time != 2 && NR && *NR > 0) {
  515. (void) fprintf(stderr,
  516. gettext(" input record number %g"), *FNR);
  517. if (strcmp((char *)*FILENAME, "-") != 0)
  518. (void) fprintf(stderr, gettext(", file %s"), *FILENAME);
  519. (void) fprintf(stderr, "\n");
  520. }
  521. if (compile_time != 2 && curnode)
  522. (void) fprintf(stderr, gettext(" source line number %lld\n"),
  523. curnode->lineno);
  524. else if (compile_time != 2 && lineno) {
  525. (void) fprintf(stderr,
  526. gettext(" source line number %lld\n"), lineno);
  527. }
  528. eprint();
  529. if (f) {
  530. if (dbg)
  531. abort();
  532. exit(2);
  533. }
  534. }
  535. static void
  536. eprint(void) /* try to print context around error */
  537. {
  538. uchar *p, *q;
  539. int c;
  540. static int been_here = 0;
  541. extern uchar ebuf[300], *ep;
  542. if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
  543. return;
  544. p = ep - 1;
  545. if (p > ebuf && *p == '\n')
  546. p--;
  547. for (; p > ebuf && *p != '\n' && *p != '\0'; p--)
  548. ;
  549. while (*p == '\n')
  550. p++;
  551. (void) fprintf(stderr, gettext(" context is\n\t"));
  552. for (q = ep-1; q >= p && *q != ' ' && *q != '\t' && *q != '\n'; q--)
  553. ;
  554. for (; p < q; p++)
  555. if (*p)
  556. (void) putc(*p, stderr);
  557. (void) fprintf(stderr, " >>> ");
  558. for (; p < ep; p++)
  559. if (*p)
  560. (void) putc(*p, stderr);
  561. (void) fprintf(stderr, " <<< ");
  562. if (*ep)
  563. while ((c = input()) != '\n' && c != '\0' && c != EOF) {
  564. (void) putc(c, stderr);
  565. bclass(c);
  566. }
  567. (void) putc('\n', stderr);
  568. ep = ebuf;
  569. }
  570. static void
  571. bclass(int c)
  572. {
  573. switch (c) {
  574. case '{': bracecnt++; break;
  575. case '}': bracecnt--; break;
  576. case '[': brackcnt++; break;
  577. case ']': brackcnt--; break;
  578. case '(': parencnt++; break;
  579. case ')': parencnt--; break;
  580. }
  581. }
  582. double
  583. errcheck(double x, char *s)
  584. {
  585. extern int errno;
  586. if (errno == EDOM) {
  587. errno = 0;
  588. ERROR "%s argument out of domain", s WARNING;
  589. x = 1;
  590. } else if (errno == ERANGE) {
  591. errno = 0;
  592. ERROR "%s result out of range", s WARNING;
  593. x = 1;
  594. }
  595. return (x);
  596. }
  597. void
  598. PUTS(uchar *s)
  599. {
  600. dprintf(("%s\n", s));
  601. }
  602. int
  603. isclvar(uchar *s) /* is s of form var=something? */
  604. {
  605. if (s != NULL) {
  606. /* Must begin with an underscore or alphabetic character */
  607. if (isalpha(*s) || (*s == '_')) {
  608. for (s++; *s; s++) {
  609. /*
  610. * followed by a sequence of underscores,
  611. * digits, and alphabetics
  612. */
  613. if (!(isalnum(*s) || *s == '_')) {
  614. break;
  615. }
  616. }
  617. return (*s == '=' && *(s + 1) != '=');
  618. }
  619. }
  620. return (0);
  621. }
  622. #define MAXEXPON 38 /* maximum exponent for fp number */
  623. int
  624. is_number(uchar *s)
  625. {
  626. int d1, d2;
  627. int point;
  628. uchar *es;
  629. extern char radixpoint;
  630. d1 = d2 = point = 0;
  631. while (*s == ' ' || *s == '\t' || *s == '\n')
  632. s++;
  633. if (*s == '\0')
  634. return (0); /* empty stuff isn't number */
  635. if (*s == '+' || *s == '-')
  636. s++;
  637. if (!isdigit(*s) && *s != radixpoint)
  638. return (0);
  639. if (isdigit(*s)) {
  640. do {
  641. d1++;
  642. s++;
  643. } while (isdigit(*s));
  644. }
  645. if (d1 >= MAXEXPON)
  646. return (0); /* too many digits to convert */
  647. if (*s == radixpoint) {
  648. point++;
  649. s++;
  650. }
  651. if (isdigit(*s)) {
  652. d2++;
  653. do {
  654. s++;
  655. } while (isdigit(*s));
  656. }
  657. if (!(d1 || point && d2))
  658. return (0);
  659. if (*s == 'e' || *s == 'E') {
  660. s++;
  661. if (*s == '+' || *s == '-')
  662. s++;
  663. if (!isdigit(*s))
  664. return (0);
  665. es = s;
  666. do {
  667. s++;
  668. } while (isdigit(*s));
  669. if (s - es > 2) {
  670. return (0);
  671. } else if (s - es == 2 &&
  672. (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON) {
  673. return (0);
  674. }
  675. }
  676. while (*s == ' ' || *s == '\t' || *s == '\n')
  677. s++;
  678. if (*s == '\0')
  679. return (1);
  680. else
  681. return (0);
  682. }
  683. void
  684. init_buf(uchar **optr, size_t *sizep, size_t amt)
  685. {
  686. uchar *nptr = NULL;
  687. if ((nptr = malloc(amt)) == NULL)
  688. ERROR "out of space in init_buf" FATAL;
  689. /* initial buffer should have NULL terminated */
  690. *nptr = '\0';
  691. if (sizep != NULL)
  692. *sizep = amt;
  693. *optr = nptr;
  694. }
  695. void
  696. r_expand_buf(uchar **optr, size_t *sizep, size_t req)
  697. {
  698. uchar *nptr;
  699. size_t amt, size = *sizep;
  700. if (size != 0 && req < (size - 1))
  701. return;
  702. amt = req + 1 - size;
  703. amt = (amt / LINE_INCR + 1) * LINE_INCR;
  704. if ((nptr = realloc(*optr, size + amt)) == NULL)
  705. ERROR "out of space in expand_buf" FATAL;
  706. /* initial buffer should have NULL terminated */
  707. if (size == 0)
  708. *nptr = '\0';
  709. *sizep += amt;
  710. *optr = nptr;
  711. }
  712. void
  713. adjust_buf(uchar **optr, size_t size)
  714. {
  715. uchar *nptr;
  716. if ((nptr = realloc(*optr, size)) == NULL)
  717. ERROR "out of space in adjust_buf" FATAL;
  718. *optr = nptr;
  719. }