aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-01-31 23:26:11 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-01-31 23:26:11 +0100
commit54a174eb015e786e8097d6e0fdba3ebfe3b27a9d (patch)
tree86cdf63f521161047204286491890aefecd2ccfd
parenta142926029e468ece87892e8364fe4458b12f128 (diff)
downloadbusybox-w32-54a174eb015e786e8097d6e0fdba3ebfe3b27a9d.tar.gz
busybox-w32-54a174eb015e786e8097d6e0fdba3ebfe3b27a9d.tar.bz2
busybox-w32-54a174eb015e786e8097d6e0fdba3ebfe3b27a9d.zip
gzip: "compressed_len" is unused, stop wasting code and time calculating it
function old new delta flush_block 595 523 -72 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--archival/gzip.c93
1 files changed, 31 insertions, 62 deletions
diff --git a/archival/gzip.c b/archival/gzip.c
index 6241b782a..d6737b492 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -93,7 +93,6 @@ aa: 85.1% -- replaced with aa.gz
93#include "libbb.h" 93#include "libbb.h"
94#include "bb_archive.h" 94#include "bb_archive.h"
95 95
96
97/* =========================================================================== 96/* ===========================================================================
98 */ 97 */
99//#define DEBUG 1 98//#define DEBUG 1
@@ -115,7 +114,6 @@ static int verbose;
115# define Tracecv(c,x) 114# define Tracecv(c,x)
116#endif 115#endif
117 116
118
119/* =========================================================================== 117/* ===========================================================================
120 */ 118 */
121#if CONFIG_GZIP_FAST == 0 119#if CONFIG_GZIP_FAST == 0
@@ -211,7 +209,6 @@ static int verbose;
211# define MAX_SUFFIX 30 209# define MAX_SUFFIX 30
212#endif 210#endif
213 211
214
215/* =========================================================================== 212/* ===========================================================================
216 * Compile with MEDIUM_MEM to reduce the memory requirements or 213 * Compile with MEDIUM_MEM to reduce the memory requirements or
217 * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the 214 * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the
@@ -220,15 +217,14 @@ static int verbose;
220 * affects the compression ratio. The compressed output 217 * affects the compression ratio. The compressed output
221 * is still correct, and might even be smaller in some cases. 218 * is still correct, and might even be smaller in some cases.
222 */ 219 */
223
224#ifdef SMALL_MEM 220#ifdef SMALL_MEM
225# define HASH_BITS 13 /* Number of bits used to hash strings */ 221# define HASH_BITS 13 /* Number of bits used to hash strings */
226#endif 222#endif
227#ifdef MEDIUM_MEM 223#ifdef MEDIUM_MEM
228# define HASH_BITS 14 224# define HASH_BITS 14
229#endif 225#endif
230#ifndef HASH_BITS 226#ifndef HASH_BITS
231# define HASH_BITS 15 227# define HASH_BITS 15
232 /* For portability to 16 bit machines, do not use values above 15. */ 228 /* For portability to 16 bit machines, do not use values above 15. */
233#endif 229#endif
234 230
@@ -241,7 +237,6 @@ static int verbose;
241#endif 237#endif
242/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ 238/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
243 239
244
245/* =========================================================================== 240/* ===========================================================================
246 * These types are not really 'char', 'short' and 'long' 241 * These types are not really 'char', 'short' and 'long'
247 */ 242 */
@@ -298,7 +293,6 @@ enum {
298#endif /* ENABLE_FEATURE_GZIP_LEVELS */ 293#endif /* ENABLE_FEATURE_GZIP_LEVELS */
299}; 294};
300 295
301
302struct globals { 296struct globals {
303/* =========================================================================== */ 297/* =========================================================================== */
304/* global buffers, allocated once */ 298/* global buffers, allocated once */
@@ -419,7 +413,6 @@ struct globals {
419 413
420#define G1 (*(ptr_to_globals - 1)) 414#define G1 (*(ptr_to_globals - 1))
421 415
422
423/* =========================================================================== 416/* ===========================================================================
424 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out. 417 * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
425 * (used for the compressed data only) 418 * (used for the compressed data only)
@@ -433,7 +426,6 @@ static void flush_outbuf(void)
433 G1.outcnt = 0; 426 G1.outcnt = 0;
434} 427}
435 428
436
437/* =========================================================================== 429/* ===========================================================================
438 */ 430 */
439/* put_8bit is used for the compressed output */ 431/* put_8bit is used for the compressed output */
@@ -517,7 +509,6 @@ static void updcrc(uch * s, unsigned n)
517 G1.crc = crc32_block_endian0(G1.crc, s, n, global_crc32_table /*G1.crc_32_tab*/); 509 G1.crc = crc32_block_endian0(G1.crc, s, n, global_crc32_table /*G1.crc_32_tab*/);
518} 510}
519 511
520
521/* =========================================================================== 512/* ===========================================================================
522 * Read a new buffer from the current input file, perform end-of-line 513 * Read a new buffer from the current input file, perform end-of-line
523 * translation, and update the crc and input file size. 514 * translation, and update the crc and input file size.
@@ -538,7 +529,6 @@ static unsigned file_read(void *buf, unsigned size)
538 return len; 529 return len;
539} 530}
540 531
541
542/* =========================================================================== 532/* ===========================================================================
543 * Send a value on a given number of bits. 533 * Send a value on a given number of bits.
544 * IN assertion: length <= 16 and value fits in length bits. 534 * IN assertion: length <= 16 and value fits in length bits.
@@ -578,7 +568,6 @@ static void send_bits(unsigned value, unsigned length)
578 G1.bi_valid = length; 568 G1.bi_valid = length;
579} 569}
580 570
581
582/* =========================================================================== 571/* ===========================================================================
583 * Reverse the first len bits of a code, using straightforward code (a faster 572 * Reverse the first len bits of a code, using straightforward code (a faster
584 * method would use a table) 573 * method would use a table)
@@ -596,7 +585,6 @@ static unsigned bi_reverse(unsigned code, int len)
596 } 585 }
597} 586}
598 587
599
600/* =========================================================================== 588/* ===========================================================================
601 * Write out any remaining bits in an incomplete byte. 589 * Write out any remaining bits in an incomplete byte.
602 */ 590 */
@@ -615,7 +603,6 @@ static void bi_windup(void)
615 DEBUG_bits_sent(= (G1.bits_sent + 7) & ~7); 603 DEBUG_bits_sent(= (G1.bits_sent + 7) & ~7);
616} 604}
617 605
618
619/* =========================================================================== 606/* ===========================================================================
620 * Copy a stored block to the zip file, storing first the length and its 607 * Copy a stored block to the zip file, storing first the length and its
621 * one's complement if requested. 608 * one's complement if requested.
@@ -638,7 +625,6 @@ static void copy_block(char *buf, unsigned len, int header)
638 flush_outbuf_if_32bit_optimized(); 625 flush_outbuf_if_32bit_optimized();
639} 626}
640 627
641
642/* =========================================================================== 628/* ===========================================================================
643 * Fill the window when the lookahead becomes insufficient. 629 * Fill the window when the lookahead becomes insufficient.
644 * Updates strstart and lookahead, and sets eofile if end of input file. 630 * Updates strstart and lookahead, and sets eofile if end of input file.
@@ -703,7 +689,6 @@ static void fill_window_if_needed(void)
703 fill_window(); 689 fill_window();
704} 690}
705 691
706
707/* =========================================================================== 692/* ===========================================================================
708 * Set match_start to the longest match starting at the given string and 693 * Set match_start to the longest match starting at the given string and
709 * return its length. Matches shorter or equal to prev_length are discarded, 694 * return its length. Matches shorter or equal to prev_length are discarded,
@@ -793,7 +778,6 @@ static int longest_match(IPos cur_match)
793 return best_len; 778 return best_len;
794} 779}
795 780
796
797#ifdef DEBUG 781#ifdef DEBUG
798/* =========================================================================== 782/* ===========================================================================
799 * Check that the match at match_start is indeed a match. 783 * Check that the match at match_start is indeed a match.
@@ -1072,13 +1056,12 @@ struct globals2 {
1072 ulg opt_len; /* bit length of current block with optimal trees */ 1056 ulg opt_len; /* bit length of current block with optimal trees */
1073 ulg static_len; /* bit length of current block with static trees */ 1057 ulg static_len; /* bit length of current block with static trees */
1074 1058
1075 ulg compressed_len; /* total bit length of compressed file */ 1059// ulg compressed_len; /* total bit length of compressed file */
1076}; 1060};
1077 1061
1078#define G2ptr ((struct globals2*)(ptr_to_globals)) 1062#define G2ptr ((struct globals2*)(ptr_to_globals))
1079#define G2 (*G2ptr) 1063#define G2 (*G2ptr)
1080 1064
1081
1082/* =========================================================================== 1065/* ===========================================================================
1083 */ 1066 */
1084#ifndef DEBUG 1067#ifndef DEBUG
@@ -1100,7 +1083,6 @@ struct globals2 {
1100 * The arguments must not have side effects. 1083 * The arguments must not have side effects.
1101 */ 1084 */
1102 1085
1103
1104/* =========================================================================== 1086/* ===========================================================================
1105 * Initialize a new block. 1087 * Initialize a new block.
1106 */ 1088 */
@@ -1123,7 +1105,6 @@ static void init_block(void)
1123 G2.flag_bit = 1; 1105 G2.flag_bit = 1;
1124} 1106}
1125 1107
1126
1127/* =========================================================================== 1108/* ===========================================================================
1128 * Restore the heap property by moving down the tree starting at node k, 1109 * Restore the heap property by moving down the tree starting at node k,
1129 * exchanging a node with the smallest of its two sons if necessary, stopping 1110 * exchanging a node with the smallest of its two sons if necessary, stopping
@@ -1161,7 +1142,6 @@ static void pqdownheap(ct_data * tree, int k)
1161 G2.heap[k] = v; 1142 G2.heap[k] = v;
1162} 1143}
1163 1144
1164
1165/* =========================================================================== 1145/* ===========================================================================
1166 * Compute the optimal bit lengths for a tree and update the total bit length 1146 * Compute the optimal bit lengths for a tree and update the total bit length
1167 * for the current block. 1147 * for the current block.
@@ -1259,7 +1239,6 @@ static void gen_bitlen(tree_desc * desc)
1259 } 1239 }
1260} 1240}
1261 1241
1262
1263/* =========================================================================== 1242/* ===========================================================================
1264 * Generate the codes for a given tree and bit counts (which need not be 1243 * Generate the codes for a given tree and bit counts (which need not be
1265 * optimal). 1244 * optimal).
@@ -1303,7 +1282,6 @@ static void gen_codes(ct_data * tree, int max_code)
1303 } 1282 }
1304} 1283}
1305 1284
1306
1307/* =========================================================================== 1285/* ===========================================================================
1308 * Construct one Huffman tree and assigns the code bit strings and lengths. 1286 * Construct one Huffman tree and assigns the code bit strings and lengths.
1309 * Update the total bit length for the current block. 1287 * Update the total bit length for the current block.
@@ -1410,7 +1388,6 @@ static void build_tree(tree_desc * desc)
1410 gen_codes((ct_data *) tree, max_code); 1388 gen_codes((ct_data *) tree, max_code);
1411} 1389}
1412 1390
1413
1414/* =========================================================================== 1391/* ===========================================================================
1415 * Scan a literal or distance tree to determine the frequencies of the codes 1392 * Scan a literal or distance tree to determine the frequencies of the codes
1416 * in the bit length tree. Updates opt_len to take into account the repeat 1393 * in the bit length tree. Updates opt_len to take into account the repeat
@@ -1465,7 +1442,6 @@ static void scan_tree(ct_data * tree, int max_code)
1465 } 1442 }
1466} 1443}
1467 1444
1468
1469/* =========================================================================== 1445/* ===========================================================================
1470 * Send a literal or distance tree in compressed form, using the codes in 1446 * Send a literal or distance tree in compressed form, using the codes in
1471 * bl_tree. 1447 * bl_tree.
@@ -1523,7 +1499,6 @@ static void send_tree(ct_data * tree, int max_code)
1523 } 1499 }
1524} 1500}
1525 1501
1526
1527/* =========================================================================== 1502/* ===========================================================================
1528 * Construct the Huffman tree for the bit lengths and return the index in 1503 * Construct the Huffman tree for the bit lengths and return the index in
1529 * bl_order of the last bit length code to send. 1504 * bl_order of the last bit length code to send.
@@ -1557,7 +1532,6 @@ static int build_bl_tree(void)
1557 return max_blindex; 1532 return max_blindex;
1558} 1533}
1559 1534
1560
1561/* =========================================================================== 1535/* ===========================================================================
1562 * Send the header for a block using dynamic Huffman trees: the counts, the 1536 * Send the header for a block using dynamic Huffman trees: the counts, the
1563 * lengths of the bit length codes, the literal tree and the distance tree. 1537 * lengths of the bit length codes, the literal tree and the distance tree.
@@ -1587,7 +1561,6 @@ static void send_all_trees(int lcodes, int dcodes, int blcodes)
1587 Tracev((stderr, "\ndist tree: sent %ld", (long)G1.bits_sent)); 1561 Tracev((stderr, "\ndist tree: sent %ld", (long)G1.bits_sent));
1588} 1562}
1589 1563
1590
1591/* =========================================================================== 1564/* ===========================================================================
1592 * Save the match info and tally the frequency counts. Return true if 1565 * Save the match info and tally the frequency counts. Return true if
1593 * the current block must be flushed. 1566 * the current block must be flushed.
@@ -1694,13 +1667,12 @@ static void compress_block(ct_data * ltree, ct_data * dtree)
1694 SEND_CODE(END_BLOCK, ltree); 1667 SEND_CODE(END_BLOCK, ltree);
1695} 1668}
1696 1669
1697
1698/* =========================================================================== 1670/* ===========================================================================
1699 * Determine the best encoding for the current block: dynamic trees, static 1671 * Determine the best encoding for the current block: dynamic trees, static
1700 * trees or store, and output the encoded block to the zip file. This function 1672 * trees or store, and output the encoded block to the zip file. This function
1701 * returns the total compressed length for the file so far. 1673 * returns the total compressed length for the file so far.
1702 */ 1674 */
1703static ulg flush_block(char *buf, ulg stored_len, int eof) 1675static void flush_block(char *buf, ulg stored_len, int eof)
1704{ 1676{
1705 ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ 1677 ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
1706 int max_blindex; /* index of last bit length code of non zero freq */ 1678 int max_blindex; /* index of last bit length code of non zero freq */
@@ -1740,14 +1712,17 @@ static ulg flush_block(char *buf, ulg stored_len, int eof)
1740 * and if the zip file can be seeked (to rewrite the local header), 1712 * and if the zip file can be seeked (to rewrite the local header),
1741 * the whole file is transformed into a stored file: 1713 * the whole file is transformed into a stored file:
1742 */ 1714 */
1743 if (stored_len <= opt_lenb && eof && G2.compressed_len == 0L && seekable()) { 1715// seekable() is constant FALSE in busybox, and G2.compressed_len is disabled
1744 /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */ 1716// (this was the only user)
1745 if (buf == NULL) 1717// if (stored_len <= opt_lenb && eof && G2.compressed_len == 0L && seekable()) {
1746 bb_error_msg("block vanished"); 1718// /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
1747 1719// if (buf == NULL)
1748 G2.compressed_len = stored_len << 3; 1720// bb_error_msg("block vanished");
1749 copy_block(buf, (unsigned) stored_len, 0); /* without header */ 1721//
1750 } else if (stored_len + 4 <= opt_lenb && buf != NULL) { 1722// G2.compressed_len = stored_len << 3;
1723// copy_block(buf, (unsigned) stored_len, 0); /* without header */
1724// } else
1725 if (stored_len + 4 <= opt_lenb && buf != NULL) {
1751 /* 4: two words for the lengths */ 1726 /* 4: two words for the lengths */
1752 /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. 1727 /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
1753 * Otherwise we can't have processed more than WSIZE input bytes since 1728 * Otherwise we can't have processed more than WSIZE input bytes since
@@ -1756,35 +1731,35 @@ static ulg flush_block(char *buf, ulg stored_len, int eof)
1756 * transform a block into a stored block. 1731 * transform a block into a stored block.
1757 */ 1732 */
1758 send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */ 1733 send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */
1759 G2.compressed_len = ((G2.compressed_len + 3 + 7) & ~7L) 1734// G2.compressed_len = ((G2.compressed_len + 3 + 7) & ~7L)
1760 + ((stored_len + 4) << 3); 1735// + ((stored_len + 4) << 3);
1761 copy_block(buf, (unsigned) stored_len, 1); /* with header */ 1736 copy_block(buf, (unsigned) stored_len, 1); /* with header */
1762 } else if (static_lenb == opt_lenb) { 1737 } else
1738 if (static_lenb == opt_lenb) {
1763 send_bits((STATIC_TREES << 1) + eof, 3); 1739 send_bits((STATIC_TREES << 1) + eof, 3);
1764 compress_block((ct_data *) G2.static_ltree, (ct_data *) G2.static_dtree); 1740 compress_block((ct_data *) G2.static_ltree, (ct_data *) G2.static_dtree);
1765 G2.compressed_len += 3 + G2.static_len; 1741// G2.compressed_len += 3 + G2.static_len;
1766 } else { 1742 } else {
1767 send_bits((DYN_TREES << 1) + eof, 3); 1743 send_bits((DYN_TREES << 1) + eof, 3);
1768 send_all_trees(G2.l_desc.max_code + 1, G2.d_desc.max_code + 1, 1744 send_all_trees(G2.l_desc.max_code + 1, G2.d_desc.max_code + 1,
1769 max_blindex + 1); 1745 max_blindex + 1);
1770 compress_block((ct_data *) G2.dyn_ltree, (ct_data *) G2.dyn_dtree); 1746 compress_block((ct_data *) G2.dyn_ltree, (ct_data *) G2.dyn_dtree);
1771 G2.compressed_len += 3 + G2.opt_len; 1747// G2.compressed_len += 3 + G2.opt_len;
1772 } 1748 }
1773 Assert(G2.compressed_len == G1.bits_sent, "bad compressed size"); 1749// Assert(G2.compressed_len == G1.bits_sent, "bad compressed size");
1774 init_block(); 1750 init_block();
1775 1751
1776 if (eof) { 1752 if (eof) {
1777 bi_windup(); 1753 bi_windup();
1778 G2.compressed_len += 7; /* align on byte boundary */ 1754// G2.compressed_len += 7; /* align on byte boundary */
1779 } 1755 }
1780 Tracev((stderr, "\ncomprlen %lu(%lu) ", 1756// Tracev((stderr, "\ncomprlen %lu(%lu) ",
1781 (unsigned long)G2.compressed_len >> 3, 1757// (unsigned long)G2.compressed_len >> 3,
1782 (unsigned long)G2.compressed_len - 7 * eof)); 1758// (unsigned long)G2.compressed_len - 7 * eof));
1783 1759
1784 return G2.compressed_len >> 3; 1760 return; /* was "return G2.compressed_len >> 3;" */
1785} 1761}
1786 1762
1787
1788/* =========================================================================== 1763/* ===========================================================================
1789 * Update a hash value with the given input byte 1764 * Update a hash value with the given input byte
1790 * IN assertion: all calls to UPDATE_HASH are made with consecutive 1765 * IN assertion: all calls to UPDATE_HASH are made with consecutive
@@ -1793,7 +1768,6 @@ static ulg flush_block(char *buf, ulg stored_len, int eof)
1793 */ 1768 */
1794#define UPDATE_HASH(h, c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK) 1769#define UPDATE_HASH(h, c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
1795 1770
1796
1797/* =========================================================================== 1771/* ===========================================================================
1798 * Same as above, but achieves better compression. We use a lazy 1772 * Same as above, but achieves better compression. We use a lazy
1799 * evaluation for matches: a match is finally adopted only if there is 1773 * evaluation for matches: a match is finally adopted only if there is
@@ -1828,7 +1802,7 @@ do { \
1828 head[G1.ins_h] = (s); \ 1802 head[G1.ins_h] = (s); \
1829} while (0) 1803} while (0)
1830 1804
1831static NOINLINE ulg deflate(void) 1805static NOINLINE void deflate(void)
1832{ 1806{
1833 IPos hash_head; /* head of hash chain */ 1807 IPos hash_head; /* head of hash chain */
1834 IPos prev_match; /* previous match */ 1808 IPos prev_match; /* previous match */
@@ -1929,10 +1903,9 @@ static NOINLINE ulg deflate(void)
1929 if (match_available) 1903 if (match_available)
1930 ct_tally(0, G1.window[G1.strstart - 1]); 1904 ct_tally(0, G1.window[G1.strstart - 1]);
1931 1905
1932 return FLUSH_BLOCK(1); /* eof */ 1906 FLUSH_BLOCK(1); /* eof */
1933} 1907}
1934 1908
1935
1936/* =========================================================================== 1909/* ===========================================================================
1937 * Initialize the bit string routines. 1910 * Initialize the bit string routines.
1938 */ 1911 */
@@ -1943,7 +1916,6 @@ static void bi_init(void)
1943 //DEBUG_bits_sent(= 0L); // globals are zeroed in pack_gzip() 1916 //DEBUG_bits_sent(= 0L); // globals are zeroed in pack_gzip()
1944} 1917}
1945 1918
1946
1947/* =========================================================================== 1919/* ===========================================================================
1948 * Initialize the "longest match" routines for a new file 1920 * Initialize the "longest match" routines for a new file
1949 */ 1921 */
@@ -1985,7 +1957,6 @@ static void lm_init(unsigned *flags16p)
1985 */ 1957 */
1986} 1958}
1987 1959
1988
1989/* =========================================================================== 1960/* ===========================================================================
1990 * Allocate the match buffer, initialize the various tables and save the 1961 * Allocate the match buffer, initialize the various tables and save the
1991 * location of the internal file attribute (ascii/binary) and method 1962 * location of the internal file attribute (ascii/binary) and method
@@ -1999,7 +1970,7 @@ static void ct_init(void)
1999 int code; /* code value */ 1970 int code; /* code value */
2000 int dist; /* distance index */ 1971 int dist; /* distance index */
2001 1972
2002 //G2.compressed_len = 0L; // globals are zeroed in pack_gzip() 1973// //G2.compressed_len = 0L; // globals are zeroed in pack_gzip()
2003 1974
2004#ifdef NOT_NEEDED 1975#ifdef NOT_NEEDED
2005 if (G2.static_dtree[0].Len != 0) 1976 if (G2.static_dtree[0].Len != 0)
@@ -2083,7 +2054,6 @@ static void ct_init(void)
2083 init_block(); 2054 init_block();
2084} 2055}
2085 2056
2086
2087/* =========================================================================== 2057/* ===========================================================================
2088 * Deflate in to out. 2058 * Deflate in to out.
2089 * IN assertions: the input and output buffers are cleared. 2059 * IN assertions: the input and output buffers are cleared.
@@ -2123,7 +2093,6 @@ static void zip(void)
2123 flush_outbuf(); 2093 flush_outbuf();
2124} 2094}
2125 2095
2126
2127/* ======================================================================== */ 2096/* ======================================================================== */
2128static 2097static
2129IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_state_t *xstate UNUSED_PARAM) 2098IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_state_t *xstate UNUSED_PARAM)