/mawk-1.3.4-20100625/print.c

# · C · 810 lines · 601 code · 91 blank · 118 comment · 144 complexity · be8a2d8e3b571dfa90b6640f677a512d MD5 · raw file

  1. /********************************************
  2. print.c
  3. copyright 1991-1993. Michael D. Brennan
  4. This is a source file for mawk, an implementation of
  5. the AWK programming language.
  6. Mawk is distributed without warranty under the terms of
  7. the GNU General Public License, version 2, 1991.
  8. ********************************************/
  9. /*
  10. * $MawkId: print.c,v 1.21 2010/05/07 22:01:46 tom Exp $
  11. * @Log: print.c,v @
  12. * Revision 1.7 1996/09/18 01:04:36 mike
  13. * Check ferror() after print and printf.
  14. *
  15. * Revision 1.6 1995/10/13 16:56:45 mike
  16. * Some assumptions that int==long were still in do_printf -- now removed.
  17. *
  18. * Revision 1.5 1995/06/18 19:17:50 mike
  19. * Create a type Int which on most machines is an int, but on machines
  20. * with 16bit ints, i.e., the PC is a long. This fixes implicit assumption
  21. * that int==long.
  22. *
  23. * Revision 1.4 1994/10/08 19:15:50 mike
  24. * remove SM_DOS
  25. *
  26. * Revision 1.3 1993/07/15 23:38:19 mike
  27. * SIZE_T and indent
  28. *
  29. * Revision 1.2 1993/07/07 00:07:50 mike
  30. * more work on 1.2
  31. *
  32. * Revision 1.1.1.1 1993/07/03 18:58:18 mike
  33. * move source to cvs
  34. *
  35. * Revision 5.6 1993/02/13 21:57:30 mike
  36. * merge patch3
  37. *
  38. * Revision 5.5 1993/01/01 21:30:48 mike
  39. * split new_STRING() into new_STRING and new_STRING0
  40. *
  41. * Revision 5.4.1.2 1993/01/20 12:53:11 mike
  42. * d_to_l()
  43. *
  44. * Revision 5.4.1.1 1993/01/15 03:33:47 mike
  45. * patch3: safer double to int conversion
  46. *
  47. * Revision 5.4 1992/11/29 18:03:11 mike
  48. * when printing integers, convert doubles to
  49. * longs so output is the same on 16bit systems as 32bit systems
  50. *
  51. * Revision 5.3 1992/08/17 14:23:21 brennan
  52. * patch2: After parsing, only bi_sprintf() uses string_buff.
  53. *
  54. * Revision 5.2 1992/02/24 10:52:16 brennan
  55. * printf and sprintf() can now have more args than % conversions
  56. * removed HAVE_PRINTF_HD -- it was too obscure
  57. *
  58. * Revision 5.1 91/12/05 07:56:22 brennan
  59. * 1.1 pre-release
  60. *
  61. */
  62. #include "mawk.h"
  63. #include "bi_vars.h"
  64. #include "bi_funct.h"
  65. #include "memory.h"
  66. #include "field.h"
  67. #include "scan.h"
  68. #include "files.h"
  69. #include "init.h"
  70. static void write_error(void);
  71. /* this can be moved and enlarged by -W sprintf=num */
  72. char *sprintf_buff = string_buff;
  73. char *sprintf_limit = string_buff + SPRINTF_SZ;
  74. /* Once execute() starts the sprintf code is (belatedly) the only
  75. code allowed to use string_buff */
  76. static void
  77. print_cell(CELL * p, FILE *fp)
  78. {
  79. size_t len;
  80. switch (p->type) {
  81. case C_NOINIT:
  82. break;
  83. case C_MBSTRN:
  84. case C_STRING:
  85. case C_STRNUM:
  86. switch (len = string(p)->len) {
  87. case 0:
  88. break;
  89. case 1:
  90. putc(string(p)->str[0], fp);
  91. break;
  92. default:
  93. fwrite(string(p)->str, (size_t) 1, len, fp);
  94. }
  95. break;
  96. case C_DOUBLE:
  97. {
  98. Int ival = d_to_I(p->dval);
  99. /* integers print as "%[l]d" */
  100. if ((double) ival == p->dval)
  101. fprintf(fp, INT_FMT, ival);
  102. else
  103. fprintf(fp, string(OFMT)->str, p->dval);
  104. }
  105. break;
  106. default:
  107. bozo("bad cell passed to print_cell");
  108. }
  109. }
  110. /* on entry to bi_print or bi_printf the stack is:
  111. sp[0] = an integer k
  112. if ( k < 0 ) output is to a file with name in sp[-1]
  113. { so open file and sp -= 2 }
  114. sp[0] = k >= 0 is the number of print args
  115. sp[-k] holds the first argument
  116. */
  117. CELL *
  118. bi_print(
  119. CELL * sp) /* stack ptr passed in */
  120. {
  121. register CELL *p;
  122. register int k;
  123. FILE *fp;
  124. k = sp->type;
  125. if (k < 0) {
  126. /* k holds redirection */
  127. if ((--sp)->type < C_STRING)
  128. cast1_to_s(sp);
  129. fp = (FILE *) file_find(string(sp), k);
  130. free_STRING(string(sp));
  131. k = (--sp)->type;
  132. /* k now has number of arguments */
  133. } else
  134. fp = stdout;
  135. if (k) {
  136. p = sp - k; /* clear k variables off the stack */
  137. sp = p - 1;
  138. k--;
  139. while (k > 0) {
  140. print_cell(p, fp);
  141. print_cell(OFS, fp);
  142. cell_destroy(p);
  143. p++;
  144. k--;
  145. }
  146. print_cell(p, fp);
  147. cell_destroy(p);
  148. } else { /* print $0 */
  149. sp--;
  150. print_cell(&field[0], fp);
  151. }
  152. print_cell(ORS, fp);
  153. if (ferror(fp))
  154. write_error();
  155. return sp;
  156. }
  157. /*---------- types and defs for doing printf and sprintf----*/
  158. typedef enum {
  159. PF_C = 0, /* %c */
  160. PF_S, /* %s */
  161. PF_D, /* int conversion */
  162. PF_F, /* float conversion */
  163. PF_U, /* unsigned conversion */
  164. PF_last
  165. } PF_enum;
  166. /* for switch on number of '*' and type */
  167. #define AST(num,type) ((PF_last)*(num)+(type))
  168. /* some picky ANSI compilers go berserk without this */
  169. typedef int (*PRINTER) (PTR, const char *,...);
  170. /*-------------------------------------------------------*/
  171. static void
  172. bad_conversion(int cnt, const char *who, const char *format)
  173. {
  174. rt_error("improper conversion(number %d) in %s(\"%s\")",
  175. cnt, who, format);
  176. }
  177. typedef enum {
  178. sfmtSPACE = 1,
  179. sfmtMINUS = 2,
  180. sfmtZEROS = 4,
  181. sfmtWIDTH = 8,
  182. sfmtPREC = 16
  183. } enumSFMT;
  184. /*
  185. * nawk pads leading 0's if it sees a format such as "%06s".
  186. * C's printf/sprintf do not do that.
  187. * So we decode the format and interpret it according to nawk.
  188. */
  189. static int
  190. make_sfmt(const char *format,
  191. int *fill_in,
  192. int *width,
  193. int *prec,
  194. int *flags)
  195. {
  196. int ch;
  197. int parts = 0;
  198. int digits = 0;
  199. int value = 0;
  200. int used = 0;
  201. int success = 1;
  202. int ok_flag = 1;
  203. *width = 0;
  204. *prec = 0;
  205. *flags = 0;
  206. ++format;
  207. while (*format != '\0' && ok_flag) {
  208. switch (*format++) {
  209. case ' ':
  210. *flags |= sfmtSPACE;
  211. break;
  212. case '-':
  213. *flags |= sfmtMINUS;
  214. break;
  215. case '0':
  216. *flags |= sfmtZEROS;
  217. break;
  218. case '+':
  219. /* FALLTHRU */
  220. case '#':
  221. /* ignore for %s */
  222. break;
  223. default:
  224. ok_flag = 0;
  225. --format;
  226. break;
  227. }
  228. }
  229. while (*format != '\0' && success) {
  230. switch (ch = *format++) {
  231. case '0':
  232. case '1':
  233. case '2':
  234. case '3':
  235. case '4':
  236. case '5':
  237. case '6':
  238. case '7':
  239. case '8':
  240. case '9':
  241. if (digits < 0) {
  242. success = 0;
  243. } else if (digits++ == 0) {
  244. value = (ch - '0');
  245. } else {
  246. value = (10 * value) + (ch - '0');
  247. }
  248. break;
  249. case '.':
  250. if (parts) {
  251. success = 0;
  252. } else {
  253. if (digits) {
  254. *width = value;
  255. *flags |= sfmtWIDTH;
  256. digits = 0;
  257. value = 0;
  258. }
  259. parts = 1;
  260. }
  261. break;
  262. case '*':
  263. if (digits == 0) {
  264. value = fill_in[used++];
  265. digits = -1;
  266. } else {
  267. success = 0;
  268. }
  269. break;
  270. case 'c':
  271. /* FALLTHRU */
  272. case 's':
  273. if (digits) {
  274. if (parts) {
  275. *prec = value;
  276. *flags |= sfmtPREC;
  277. } else {
  278. *width = value;
  279. *flags |= sfmtWIDTH;
  280. }
  281. }
  282. if (*format != '\0')
  283. success = 0;
  284. break;
  285. default:
  286. success = 0;
  287. break;
  288. }
  289. }
  290. return success;
  291. }
  292. #define SprintfOverflow(buffer, need) \
  293. if (buffer + need + 1 >= sprintf_limit) { \
  294. rt_overflow("sprintf buffer", \
  295. (unsigned) (sprintf_limit - sprintf_buff)); \
  296. }
  297. static char *
  298. SprintfChar(char *buffer, int ch)
  299. {
  300. SprintfOverflow(buffer, 1);
  301. *buffer++ = (char) ch;
  302. return buffer;
  303. }
  304. static char *
  305. SprintfFill(char *buffer, int ch, int fill)
  306. {
  307. SprintfOverflow(buffer, fill);
  308. memset(buffer, ch, (size_t) fill);
  309. return buffer + fill;
  310. }
  311. static char *
  312. SprintfBlock(char *buffer, char *source, int length)
  313. {
  314. SprintfOverflow(buffer, length);
  315. memcpy(buffer, source, (size_t) length);
  316. return buffer + length;
  317. }
  318. /*
  319. * Write the s-format text.
  320. */
  321. static PTR
  322. puts_sfmt(PTR target,
  323. FILE *fp,
  324. CELL * source,
  325. STRING * onechr,
  326. int width,
  327. int prec,
  328. int flags)
  329. {
  330. char *src_str = onechr ? onechr->str : string(source)->str;
  331. int src_len = onechr ? 1 : (int) string(source)->len;
  332. if (width < 0) {
  333. width = -width;
  334. flags |= sfmtMINUS;
  335. }
  336. if (fp != 0) {
  337. if (flags & sfmtSPACE) {
  338. if (src_len == 0)
  339. fputc(' ', fp);
  340. }
  341. if (flags & sfmtPREC) {
  342. if (src_len > prec)
  343. src_len = prec;
  344. }
  345. if (!(flags & sfmtWIDTH)) {
  346. width = src_len;
  347. }
  348. if (!(flags & sfmtMINUS)) {
  349. while (src_len < width) {
  350. fputc(' ', fp);
  351. --width;
  352. }
  353. }
  354. fwrite(src_str, sizeof(char), (size_t) src_len, fp);
  355. while (src_len < width) {
  356. fputc(' ', fp);
  357. --width;
  358. }
  359. } else {
  360. char *buffer = (char *) target; /* points into sprintf_buff */
  361. if (flags & sfmtSPACE) {
  362. if (src_len == 0) {
  363. buffer = SprintfChar(buffer, ' ');
  364. }
  365. }
  366. if (flags & sfmtPREC) {
  367. if (src_len > prec)
  368. src_len = prec;
  369. }
  370. if (!(flags & sfmtWIDTH)) {
  371. width = src_len;
  372. }
  373. if (!(flags & sfmtMINUS)) {
  374. if (src_len < width) {
  375. buffer = SprintfFill(buffer, ' ', width - src_len);
  376. width = src_len;
  377. }
  378. }
  379. buffer = SprintfBlock(buffer, src_str, src_len);
  380. if (src_len < width) {
  381. buffer = SprintfFill(buffer, ' ', width - src_len);
  382. }
  383. target = buffer;
  384. }
  385. return target;
  386. }
  387. /*
  388. * Note: caller must do CELL cleanup.
  389. * The format parameter is modified, but restored.
  390. *
  391. * This routine does both printf and sprintf (if fp==0)
  392. */
  393. static STRING *
  394. do_printf(
  395. FILE *fp,
  396. char *format,
  397. unsigned argcnt, /* number of args on eval stack */
  398. CELL * cp) /* ptr to an array of arguments
  399. (on the eval stack) */
  400. {
  401. char save;
  402. char *p;
  403. register char *q = format;
  404. register char *target;
  405. int l_flag, h_flag; /* seen %ld or %hd */
  406. int ast_cnt;
  407. int ast[2];
  408. UInt Uval = 0;
  409. Int Ival = 0;
  410. int sfmt_width, sfmt_prec, sfmt_flags, s_format;
  411. int num_conversion = 0; /* for error messages */
  412. const char *who; /*ditto */
  413. int pf_type = 0; /* conversion type */
  414. PRINTER printer; /* pts at fprintf() or sprintf() */
  415. STRING onechr;
  416. #ifdef SHORT_INTS
  417. char xbuff[256]; /* splice in l qualifier here */
  418. #endif
  419. if (fp == (FILE *) 0) { /* doing sprintf */
  420. target = sprintf_buff;
  421. printer = (PRINTER) sprintf;
  422. who = "sprintf";
  423. } else { /* doing printf */
  424. target = (char *) fp; /* will never change */
  425. printer = (PRINTER) fprintf;
  426. who = "printf";
  427. }
  428. while (1) {
  429. if (fp) { /* printf */
  430. while (*q != '%') {
  431. if (*q == 0) {
  432. if (ferror(fp))
  433. write_error();
  434. /* return is ignored */
  435. return (STRING *) 0;
  436. } else {
  437. putc(*q, fp);
  438. q++;
  439. }
  440. }
  441. } else { /* sprintf */
  442. while (*q != '%') {
  443. if (*q == 0) {
  444. if (target > sprintf_limit) /* damaged */
  445. {
  446. /* hope this works */
  447. rt_overflow("sprintf buffer",
  448. (unsigned) (sprintf_limit - sprintf_buff));
  449. } else { /* really done */
  450. return new_STRING1(sprintf_buff,
  451. (size_t) (target - sprintf_buff));
  452. }
  453. } else {
  454. *target++ = *q++;
  455. }
  456. }
  457. }
  458. /* *q == '%' */
  459. num_conversion++;
  460. if (*++q == '%') { /* %% */
  461. if (fp)
  462. putc(*q, fp);
  463. else
  464. *target++ = *q;
  465. q++;
  466. continue;
  467. }
  468. /* mark the '%' with p */
  469. p = q - 1;
  470. /* eat the flags */
  471. while (*q == '-' || *q == '+' || *q == ' ' ||
  472. *q == '#' || *q == '0')
  473. q++;
  474. ast_cnt = 0;
  475. if (*q == '*') {
  476. if (cp->type != C_DOUBLE)
  477. cast1_to_d(cp);
  478. ast[ast_cnt++] = d_to_i(cp++->dval);
  479. argcnt--;
  480. q++;
  481. } else
  482. while (scan_code[*(unsigned char *) q] == SC_DIGIT)
  483. q++;
  484. /* width is done */
  485. if (*q == '.') { /* have precision */
  486. q++;
  487. if (*q == '*') {
  488. if (cp->type != C_DOUBLE)
  489. cast1_to_d(cp);
  490. ast[ast_cnt++] = d_to_i(cp++->dval);
  491. argcnt--;
  492. q++;
  493. } else {
  494. while (scan_code[*(unsigned char *) q] == SC_DIGIT)
  495. q++;
  496. }
  497. }
  498. if (argcnt <= 0)
  499. rt_error("not enough arguments passed to %s(\"%s\")",
  500. who, format);
  501. l_flag = h_flag = 0;
  502. if (*q == 'l') {
  503. q++;
  504. l_flag = 1;
  505. } else if (*q == 'h') {
  506. q++;
  507. h_flag = 1;
  508. }
  509. switch (*q++) {
  510. case 's':
  511. if (l_flag + h_flag)
  512. bad_conversion(num_conversion, who, format);
  513. if (cp->type < C_STRING)
  514. cast1_to_s(cp);
  515. pf_type = PF_S;
  516. break;
  517. case 'c':
  518. if (l_flag + h_flag)
  519. bad_conversion(num_conversion, who, format);
  520. switch (cp->type) {
  521. case C_NOINIT:
  522. Ival = 0;
  523. break;
  524. case C_STRNUM:
  525. case C_DOUBLE:
  526. Ival = d_to_I(cp->dval);
  527. break;
  528. case C_STRING:
  529. Ival = string(cp)->str[0];
  530. break;
  531. case C_MBSTRN:
  532. check_strnum(cp);
  533. Ival = ((cp->type == C_STRING)
  534. ? string(cp)->str[0]
  535. : d_to_I(cp->dval));
  536. break;
  537. default:
  538. bozo("printf %c");
  539. }
  540. onechr.len = 1;
  541. onechr.str[0] = (char) Ival;
  542. pf_type = PF_C;
  543. break;
  544. case 'd':
  545. case 'i':
  546. if (cp->type != C_DOUBLE)
  547. cast1_to_d(cp);
  548. Ival = d_to_I(cp->dval);
  549. pf_type = PF_D;
  550. break;
  551. case 'o':
  552. case 'x':
  553. case 'X':
  554. case 'u':
  555. if (cp->type != C_DOUBLE)
  556. cast1_to_d(cp);
  557. Uval = d_to_U(cp->dval);
  558. pf_type = PF_U;
  559. break;
  560. case 'e':
  561. case 'g':
  562. case 'f':
  563. case 'E':
  564. case 'G':
  565. if (h_flag + l_flag)
  566. bad_conversion(num_conversion, who, format);
  567. if (cp->type != C_DOUBLE)
  568. cast1_to_d(cp);
  569. pf_type = PF_F;
  570. break;
  571. default:
  572. bad_conversion(num_conversion, who, format);
  573. }
  574. save = *q;
  575. *q = 0;
  576. #ifdef SHORT_INTS
  577. if (pf_type == PF_D) {
  578. /* need to splice in long modifier */
  579. strcpy(xbuff, p);
  580. if (l_flag) /* do nothing */ ;
  581. else {
  582. int k = q - p;
  583. if (h_flag) {
  584. Ival = (short) Ival;
  585. /* replace the 'h' with 'l' (really!) */
  586. xbuff[k - 2] = 'l';
  587. if (xbuff[k - 1] != 'd' && xbuff[k - 1] != 'i')
  588. Ival &= 0xffff;
  589. } else {
  590. /* the usual case */
  591. xbuff[k] = xbuff[k - 1];
  592. xbuff[k - 1] = 'l';
  593. xbuff[k + 1] = 0;
  594. }
  595. }
  596. }
  597. #endif
  598. #define PUTS_C_ARGS target, fp, 0, &onechr, sfmt_width, sfmt_prec, sfmt_flags
  599. #define PUTS_S_ARGS target, fp, cp, 0, sfmt_width, sfmt_prec, sfmt_flags
  600. /* ready to call printf() */
  601. s_format = 0;
  602. switch (AST(ast_cnt, pf_type)) {
  603. case AST(0, PF_C):
  604. /* FALLTHRU */
  605. case AST(1, PF_C):
  606. /* FALLTHRU */
  607. case AST(2, PF_C):
  608. s_format = 1;
  609. make_sfmt(p, ast, &sfmt_width, &sfmt_prec, &sfmt_flags);
  610. target = puts_sfmt(PUTS_C_ARGS);
  611. break;
  612. case AST(0, PF_S):
  613. /* FALLTHRU */
  614. case AST(1, PF_S):
  615. /* FALLTHRU */
  616. case AST(2, PF_S):
  617. s_format = 1;
  618. make_sfmt(p, ast, &sfmt_width, &sfmt_prec, &sfmt_flags);
  619. target = puts_sfmt(PUTS_S_ARGS);
  620. break;
  621. #ifdef SHORT_INTS
  622. #define FMT xbuff /* format in xbuff */
  623. #else
  624. #define FMT p /* p -> format */
  625. #endif
  626. case AST(0, PF_D):
  627. (*printer) ((PTR) target, FMT, Ival);
  628. break;
  629. case AST(1, PF_D):
  630. (*printer) ((PTR) target, FMT, ast[0], Ival);
  631. break;
  632. case AST(2, PF_D):
  633. (*printer) ((PTR) target, FMT, ast[0], ast[1], Ival);
  634. break;
  635. case AST(0, PF_U):
  636. (*printer) ((PTR) target, FMT, Uval);
  637. break;
  638. case AST(1, PF_U):
  639. (*printer) ((PTR) target, FMT, ast[0], Uval);
  640. break;
  641. case AST(2, PF_U):
  642. (*printer) ((PTR) target, FMT, ast[0], ast[1], Uval);
  643. break;
  644. #undef FMT
  645. case AST(0, PF_F):
  646. (*printer) ((PTR) target, p, cp->dval);
  647. break;
  648. case AST(1, PF_F):
  649. (*printer) ((PTR) target, p, ast[0], cp->dval);
  650. break;
  651. case AST(2, PF_F):
  652. (*printer) ((PTR) target, p, ast[0], ast[1], cp->dval);
  653. break;
  654. }
  655. if (fp == (FILE *) 0 && !s_format) {
  656. while (*target)
  657. target++;
  658. }
  659. *q = save;
  660. argcnt--;
  661. cp++;
  662. }
  663. }
  664. CELL *
  665. bi_printf(CELL * sp)
  666. {
  667. register int k;
  668. register CELL *p;
  669. FILE *fp;
  670. k = sp->type;
  671. if (k < 0) {
  672. /* k has redirection */
  673. if ((--sp)->type < C_STRING)
  674. cast1_to_s(sp);
  675. fp = (FILE *) file_find(string(sp), k);
  676. free_STRING(string(sp));
  677. k = (--sp)->type;
  678. /* k is now number of args including format */
  679. } else
  680. fp = stdout;
  681. sp -= k; /* sp points at the format string */
  682. k--;
  683. if (sp->type < C_STRING)
  684. cast1_to_s(sp);
  685. do_printf(fp, string(sp)->str, (unsigned) k, sp + 1);
  686. free_STRING(string(sp));
  687. /* cleanup arguments on eval stack */
  688. for (p = sp + 1; k; k--, p++)
  689. cell_destroy(p);
  690. return --sp;
  691. }
  692. CELL *
  693. bi_sprintf(CELL * sp)
  694. {
  695. CELL *p;
  696. int argcnt = sp->type;
  697. STRING *sval;
  698. sp -= argcnt; /* sp points at the format string */
  699. argcnt--;
  700. if (sp->type != C_STRING)
  701. cast1_to_s(sp);
  702. sval = do_printf((FILE *) 0, string(sp)->str, (unsigned) argcnt, sp + 1);
  703. free_STRING(string(sp));
  704. sp->ptr = (PTR) sval;
  705. /* cleanup */
  706. for (p = sp + 1; argcnt; argcnt--, p++)
  707. cell_destroy(p);
  708. return sp;
  709. }
  710. static void
  711. write_error(void)
  712. {
  713. errmsg(errno, "write failure");
  714. mawk_exit(2);
  715. }