1 1.1 rumble /* $NetBSD: util.c,v 1.1 2026/06/11 08:29:49 rumble Exp $ */ 2 1.1 rumble 3 1.1 rumble /* 4 1.1 rumble * Cribbed from 4.4BSD/Net2 and NetBSD 4.99.42 with some stuff ripped out and 5 1.1 rumble * cleaned up. 6 1.1 rumble */ 7 1.1 rumble 8 1.1 rumble /*- 9 1.1 rumble * Copyright (c) 1991, 1993 10 1.1 rumble * The Regents of the University of California. All rights reserved. 11 1.1 rumble * 12 1.1 rumble * Redistribution and use in source and binary forms, with or without 13 1.1 rumble * modification, are permitted provided that the following conditions 14 1.1 rumble * are met: 15 1.1 rumble * 1. Redistributions of source code must retain the above copyright 16 1.1 rumble * notice, this list of conditions and the following disclaimer. 17 1.1 rumble * 2. Redistributions in binary form must reproduce the above copyright 18 1.1 rumble * notice, this list of conditions and the following disclaimer in the 19 1.1 rumble * documentation and/or other materials provided with the distribution. 20 1.1 rumble * 3. Neither the name of the University nor the names of its contributors 21 1.1 rumble * may be used to endorse or promote products derived from this software 22 1.1 rumble * without specific prior written permission. 23 1.1 rumble * 24 1.1 rumble * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 1.1 rumble * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 1.1 rumble * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 1.1 rumble * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 1.1 rumble * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 1.1 rumble * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 1.1 rumble * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 1.1 rumble * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 1.1 rumble * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 1.1 rumble * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 1.1 rumble * SUCH DAMAGE. 35 1.1 rumble */ 36 1.1 rumble 37 1.1 rumble #include <sys/types.h> 38 1.1 rumble #include <stdint.h> 39 1.1 rumble #include <stdio.h> 40 1.1 rumble #include <unistd.h> 41 1.1 rumble 42 1.1 rumble #include "util.h" 43 1.1 rumble 44 1.1 rumble /* 'thecrc' must initially be 0. */ 45 1.1 rumble int 46 1.1 rumble sum1(int thecrc, u_char *buf, uint32_t len) 47 1.1 rumble { 48 1.1 rumble /* 49 1.1 rumble * 16-bit checksum, rotating right before each addition; 50 1.1 rumble * overflow is discarded. 51 1.1 rumble */ 52 1.1 rumble for (u_char *p = buf; p < &buf[len]; ++p) { 53 1.1 rumble if (thecrc & 1) 54 1.1 rumble thecrc |= 0x10000; 55 1.1 rumble thecrc = ((thecrc >> 1) + *p) & 0xffff; 56 1.1 rumble } 57 1.1 rumble 58 1.1 rumble return (thecrc); 59 1.1 rumble } 60 1.1 rumble 61 1.1 rumble /* 62 1.1 rumble * Copyright (c) 1985, 1986 The Regents of the University of California. 63 1.1 rumble * All rights reserved. 64 1.1 rumble * 65 1.1 rumble * This code is derived from software contributed to Berkeley by 66 1.1 rumble * James A. Woods, derived from original work by Spencer Thomas 67 1.1 rumble * and Joseph Orost. 68 1.1 rumble * 69 1.1 rumble * Redistribution and use in source and binary forms, with or without 70 1.1 rumble * modification, are permitted provided that the following conditions 71 1.1 rumble * are met: 72 1.1 rumble * 1. Redistributions of source code must retain the above copyright 73 1.1 rumble * notice, this list of conditions and the following disclaimer. 74 1.1 rumble * 2. Redistributions in binary form must reproduce the above copyright 75 1.1 rumble * notice, this list of conditions and the following disclaimer in the 76 1.1 rumble * documentation and/or other materials provided with the distribution. 77 1.1 rumble * 3. All advertising materials mentioning features or use of this software 78 1.1 rumble * must display the following acknowledgement: 79 1.1 rumble * This product includes software developed by the University of 80 1.1 rumble * California, Berkeley and its contributors. 81 1.1 rumble * 4. Neither the name of the University nor the names of its contributors 82 1.1 rumble * may be used to endorse or promote products derived from this software 83 1.1 rumble * without specific prior written permission. 84 1.1 rumble * 85 1.1 rumble * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 86 1.1 rumble * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 87 1.1 rumble * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 88 1.1 rumble * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 89 1.1 rumble * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 90 1.1 rumble * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 91 1.1 rumble * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 92 1.1 rumble * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 93 1.1 rumble * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 94 1.1 rumble * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 95 1.1 rumble * SUCH DAMAGE. 96 1.1 rumble */ 97 1.1 rumble 98 1.1 rumble /* 99 1.1 rumble * compress.c - File compression ala IEEE Computer, June 1984. 100 1.1 rumble * 101 1.1 rumble * Authors: Spencer W. Thomas (decvax!utah-cs!thomas) 102 1.1 rumble * Jim McKie (decvax!mcvax!jim) 103 1.1 rumble * Steve Davies (decvax!vax135!petsd!peora!srd) 104 1.1 rumble * Ken Turkowski (decvax!decwrl!turtlevax!ken) 105 1.1 rumble * James A. Woods (decvax!ihnp4!ames!jaw) 106 1.1 rumble * Joe Orost (decvax!vax135!petsd!joe) 107 1.1 rumble */ 108 1.1 rumble 109 1.1 rumble #include <sys/param.h> 110 1.1 rumble #include <sys/stat.h> 111 1.1 rumble #include <signal.h> 112 1.1 rumble #include <utime.h> 113 1.1 rumble #include <errno.h> 114 1.1 rumble #include <unistd.h> 115 1.1 rumble #include <stdio.h> 116 1.1 rumble #include <ctype.h> 117 1.1 rumble #include <stdlib.h> 118 1.1 rumble #include <string.h> 119 1.1 rumble 120 1.1 rumble #define BITS 16 121 1.1 rumble #define HSIZE 69001 /* 95% occupancy */ 122 1.1 rumble 123 1.1 rumble /* 124 1.1 rumble * a code_int must be able to hold 2**BITS values of type int, and also -1 125 1.1 rumble */ 126 1.1 rumble typedef long int code_int; 127 1.1 rumble typedef long int count_int; 128 1.1 rumble 129 1.1 rumble static const unsigned char magic_header[] = { "\037\235" }; /* 1F 9D */ 130 1.1 rumble 131 1.1 rumble /* Defines for third byte of header */ 132 1.1 rumble #define BIT_MASK 0x1f 133 1.1 rumble #define BLOCK_MASK 0x80 134 1.1 rumble /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is 135 1.1 rumble a fourth header byte (for expansion). 136 1.1 rumble */ 137 1.1 rumble 138 1.1 rumble #define INIT_BITS 9 /* initial number of bits/code */ 139 1.1 rumble 140 1.1 rumble static int n_bits; /* number of bits/code */ 141 1.1 rumble static int maxbits = BITS; /* user settable max # bits/code */ 142 1.1 rumble static code_int maxcode; /* maximum code, given n_bits */ 143 1.1 rumble static code_int maxmaxcode = 1 << BITS; /* should NEVER generate this code */ 144 1.1 rumble #define MAXCODE(n_bits) ((1 << (n_bits)) - 1) 145 1.1 rumble 146 1.1 rumble static count_int htab [HSIZE]; 147 1.1 rumble static unsigned short codetab [HSIZE]; 148 1.1 rumble 149 1.1 rumble #define codetabof(i) codetab[i] 150 1.1 rumble 151 1.1 rumble /* 152 1.1 rumble * To save much memory, we overlay the table used by compress() with those 153 1.1 rumble * used by decompress(). The tab_prefix table is the same size and type 154 1.1 rumble * as the codetab. The tab_suffix table needs 2**BITS characters. We 155 1.1 rumble * get this from the beginning of htab. The output stack uses the rest 156 1.1 rumble * of htab, and contains characters. There is plenty of room for any 157 1.1 rumble * possible stack (stack used to be 8000 characters). 158 1.1 rumble */ 159 1.1 rumble 160 1.1 rumble #define tab_prefixof(i) codetabof(i) 161 1.1 rumble #define tab_suffixof(i) ((unsigned char *)(htab))[i] 162 1.1 rumble #define de_stack ((unsigned char *)&tab_suffixof(1<<BITS)) 163 1.1 rumble 164 1.1 rumble static code_int free_ent = 0; /* first unused entry */ 165 1.1 rumble 166 1.1 rumble static code_int getcode(FILE *); 167 1.1 rumble 168 1.1 rumble /* 169 1.1 rumble * block compression parameters -- after all codes are used up, 170 1.1 rumble * and compression rate changes, start over. 171 1.1 rumble */ 172 1.1 rumble static int block_compress = BLOCK_MASK; 173 1.1 rumble static int clear_flg = 0; 174 1.1 rumble 175 1.1 rumble /* 176 1.1 rumble * the next two codes should not be changed lightly, as they must not 177 1.1 rumble * lie within the contiguous general code space. 178 1.1 rumble */ 179 1.1 rumble #define FIRST 257 /* first free entry */ 180 1.1 rumble #define CLEAR 256 /* table clear output code */ 181 1.1 rumble 182 1.1 rumble /*- 183 1.1 rumble * Algorithm from "A Technique for High Performance Data Compression", 184 1.1 rumble * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19. 185 1.1 rumble * 186 1.1 rumble * Algorithm: 187 1.1 rumble * Modified Lempel-Ziv method (LZW). Basically finds common 188 1.1 rumble * substrings and replaces them with a variable size code. This is 189 1.1 rumble * deterministic, and can be done on the fly. Thus, the decompression 190 1.1 rumble * procedure needs no input table, but tracks the way the table was built. 191 1.1 rumble */ 192 1.1 rumble 193 1.1 rumble static const unsigned char rmask[9] = { 194 1.1 rumble 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff 195 1.1 rumble }; 196 1.1 rumble 197 1.1 rumble #ifndef BUFFER_SIZE 198 1.1 rumble #define BUFFER_SIZE 16384 199 1.1 rumble #endif 200 1.1 rumble 201 1.1 rumble /* maximum number of bytes to return from getcode(). if 0, no limit. */ 202 1.1 rumble static uint32_t getcode_maxreadbytes; 203 1.1 rumble 204 1.1 rumble /* number of bytes getcode has returned since decompress() was called */ 205 1.1 rumble static uint32_t getcode_readbytes; 206 1.1 rumble 207 1.1 rumble /* this shouldn't be here, but it's faster to just do it on the fly */ 208 1.1 rumble static int output_checksum; 209 1.1 rumble 210 1.1 rumble /* 211 1.1 rumble * Decompress 'input' to 'output'. This routine adapts to the codes in 212 1.1 rumble * the file building the "string" table on-the-fly; requiring no table to 213 1.1 rumble * be stored in the compressed file. See the definitions above. 214 1.1 rumble * 215 1.1 rumble * Returns the number of bytes written to 'output'. 216 1.1 rumble */ 217 1.1 rumble static uint32_t 218 1.1 rumble do_decompression(FILE *input, FILE *output) { 219 1.1 rumble unsigned char *stackp; 220 1.1 rumble int finchar; 221 1.1 rumble code_int code, oldcode, incode; 222 1.1 rumble int n, nwritten, offset; /* Variables for buffered write */ 223 1.1 rumble char buff[BUFFER_SIZE]; /* Buffer for buffered write */ 224 1.1 rumble uint32_t byteswritten; 225 1.1 rumble 226 1.1 rumble byteswritten = 0; 227 1.1 rumble 228 1.1 rumble /* 229 1.1 rumble * As above, initialize the first 256 entries in the table. 230 1.1 rumble */ 231 1.1 rumble maxcode = MAXCODE(n_bits = INIT_BITS); 232 1.1 rumble for ( code = 255; code >= 0; code-- ) { 233 1.1 rumble tab_prefixof(code) = 0; 234 1.1 rumble tab_suffixof(code) = (unsigned char)code; 235 1.1 rumble } 236 1.1 rumble free_ent = ((block_compress) ? FIRST : 256 ); 237 1.1 rumble 238 1.1 rumble finchar = oldcode = getcode(input); 239 1.1 rumble if(oldcode == -1) /* EOF already? */ 240 1.1 rumble return (0); 241 1.1 rumble 242 1.1 rumble /* first code must be 8 bits = char */ 243 1.1 rumble n=0; 244 1.1 rumble buff[n++] = (char)finchar; 245 1.1 rumble 246 1.1 rumble stackp = de_stack; 247 1.1 rumble 248 1.1 rumble while ( (code = getcode(input)) > -1 ) { 249 1.1 rumble 250 1.1 rumble if ( (code == CLEAR) && block_compress ) { 251 1.1 rumble for ( code = 255; code >= 0; code-- ) 252 1.1 rumble tab_prefixof(code) = 0; 253 1.1 rumble clear_flg = 1; 254 1.1 rumble free_ent = FIRST - 1; 255 1.1 rumble if ( (code = getcode(input)) == -1 ) /* O, untimely death! */ 256 1.1 rumble break; 257 1.1 rumble } 258 1.1 rumble incode = code; 259 1.1 rumble /* 260 1.1 rumble * Special case for KwKwK string. 261 1.1 rumble */ 262 1.1 rumble if ( code >= free_ent ) { 263 1.1 rumble *stackp++ = finchar; 264 1.1 rumble code = oldcode; 265 1.1 rumble } 266 1.1 rumble 267 1.1 rumble /* 268 1.1 rumble * Generate output characters in reverse order 269 1.1 rumble */ 270 1.1 rumble while ( code >= 256 ) { 271 1.1 rumble *stackp++ = tab_suffixof(code); 272 1.1 rumble code = tab_prefixof(code); 273 1.1 rumble } 274 1.1 rumble *stackp++ = finchar = tab_suffixof(code); 275 1.1 rumble 276 1.1 rumble /* 277 1.1 rumble * And put them out in forward order 278 1.1 rumble */ 279 1.1 rumble do { 280 1.1 rumble /* 281 1.1 rumble * About 60% of the time is spent in the putchar() call 282 1.1 rumble * that appeared here. It was originally 283 1.1 rumble * putchar ( *--stackp ); 284 1.1 rumble * If we buffer the writes ourselves, we can go faster (about 285 1.1 rumble * 30%). 286 1.1 rumble * 287 1.1 rumble * At this point, the next line is the next *big* time 288 1.1 rumble * sink in the code. It takes up about 10% of the time. 289 1.1 rumble */ 290 1.1 rumble buff[n++] = *--stackp; 291 1.1 rumble if (n == BUFFER_SIZE) { 292 1.1 rumble offset = 0; 293 1.1 rumble do { 294 1.1 rumble output_checksum = sum1(output_checksum, 295 1.1 rumble (u_char *)&buff[offset], n); 296 1.1 rumble if (output == NULL) 297 1.1 rumble nwritten = n; 298 1.1 rumble else 299 1.1 rumble nwritten = write(fileno(output), &buff[offset], n); 300 1.1 rumble if (nwritten < 0) 301 1.1 rumble return (0); 302 1.1 rumble offset += nwritten; 303 1.1 rumble byteswritten += nwritten; 304 1.1 rumble } while ((n -= nwritten) > 0); 305 1.1 rumble } 306 1.1 rumble } while ( stackp > de_stack ); 307 1.1 rumble 308 1.1 rumble /* 309 1.1 rumble * Generate the new entry. 310 1.1 rumble */ 311 1.1 rumble if ( (code=free_ent) < maxmaxcode ) { 312 1.1 rumble tab_prefixof(code) = (unsigned short)oldcode; 313 1.1 rumble tab_suffixof(code) = finchar; 314 1.1 rumble free_ent = code+1; 315 1.1 rumble } 316 1.1 rumble /* 317 1.1 rumble * Remember previous code. 318 1.1 rumble */ 319 1.1 rumble oldcode = incode; 320 1.1 rumble } 321 1.1 rumble /* 322 1.1 rumble * Flush the stuff remaining in our buffer... 323 1.1 rumble */ 324 1.1 rumble offset = 0; 325 1.1 rumble while (n > 0) { 326 1.1 rumble output_checksum = sum1(output_checksum, (u_char *)&buff[offset], n); 327 1.1 rumble if (output == NULL) 328 1.1 rumble nwritten = n; 329 1.1 rumble else 330 1.1 rumble nwritten = write(fileno(output), &buff[offset], n); 331 1.1 rumble if (nwritten < 0) 332 1.1 rumble return (0); 333 1.1 rumble offset += nwritten; 334 1.1 rumble n -= nwritten; 335 1.1 rumble byteswritten += nwritten; 336 1.1 rumble } 337 1.1 rumble 338 1.1 rumble return (byteswritten); 339 1.1 rumble } 340 1.1 rumble 341 1.1 rumble /*- 342 1.1 rumble * Read one code from the standard input. If EOF, return -1. 343 1.1 rumble * Inputs: 344 1.1 rumble * FILE stream. 345 1.1 rumble * Outputs: 346 1.1 rumble * code or -1 is returned. 347 1.1 rumble */ 348 1.1 rumble static code_int 349 1.1 rumble getcode(FILE *input) 350 1.1 rumble { 351 1.1 rumble code_int code; 352 1.1 rumble static int offset = 0, size = 0; 353 1.1 rumble static unsigned char buf[BITS]; 354 1.1 rumble int r_off, bits; 355 1.1 rumble size_t readbytes; 356 1.1 rumble unsigned char *bp = buf; 357 1.1 rumble 358 1.1 rumble if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) { 359 1.1 rumble /* 360 1.1 rumble * If the next entry will be too big for the current code 361 1.1 rumble * size, then we must increase the size. This implies reading 362 1.1 rumble * a new buffer full, too. 363 1.1 rumble * 364 1.1 rumble * Bail immediately if we've read in our maximum. 365 1.1 rumble */ 366 1.1 rumble if (getcode_maxreadbytes != 0 && 367 1.1 rumble getcode_readbytes == getcode_maxreadbytes) 368 1.1 rumble return (-1); 369 1.1 rumble 370 1.1 rumble 371 1.1 rumble if ( free_ent > maxcode ) { 372 1.1 rumble n_bits++; 373 1.1 rumble if ( n_bits == maxbits ) 374 1.1 rumble maxcode = maxmaxcode; /* won't get any bigger now */ 375 1.1 rumble else 376 1.1 rumble maxcode = MAXCODE(n_bits); 377 1.1 rumble } 378 1.1 rumble if ( clear_flg > 0) { 379 1.1 rumble maxcode = MAXCODE (n_bits = INIT_BITS); 380 1.1 rumble clear_flg = 0; 381 1.1 rumble } 382 1.1 rumble 383 1.1 rumble if (getcode_maxreadbytes != 0 && 384 1.1 rumble n_bits > (getcode_maxreadbytes - getcode_readbytes)) 385 1.1 rumble readbytes = getcode_maxreadbytes - getcode_readbytes; 386 1.1 rumble else 387 1.1 rumble readbytes = n_bits; 388 1.1 rumble 389 1.1 rumble size = fread( buf, 1, readbytes, input ); 390 1.1 rumble if ( size <= 0 ) 391 1.1 rumble return -1; /* end of file */ 392 1.1 rumble getcode_readbytes += size; 393 1.1 rumble offset = 0; 394 1.1 rumble /* Round size down to integral number of codes */ 395 1.1 rumble size = (size << 3) - (n_bits - 1); 396 1.1 rumble } 397 1.1 rumble r_off = offset; 398 1.1 rumble bits = n_bits; 399 1.1 rumble /* 400 1.1 rumble * Get to the first byte. 401 1.1 rumble */ 402 1.1 rumble bp += (r_off >> 3); 403 1.1 rumble r_off &= 7; 404 1.1 rumble /* Get first part (low order bits) */ 405 1.1 rumble code = (*bp++ >> r_off); 406 1.1 rumble bits -= (8 - r_off); 407 1.1 rumble r_off = 8 - r_off; /* now, offset into code word */ 408 1.1 rumble /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ 409 1.1 rumble if ( bits >= 8 ) { 410 1.1 rumble code |= *bp++ << r_off; 411 1.1 rumble r_off += 8; 412 1.1 rumble bits -= 8; 413 1.1 rumble } 414 1.1 rumble /* high order bits. */ 415 1.1 rumble code |= (*bp & rmask[bits]) << r_off; 416 1.1 rumble offset += n_bits; 417 1.1 rumble 418 1.1 rumble return code; 419 1.1 rumble } 420 1.1 rumble 421 1.1 rumble /* 422 1.1 rumble * Decompress from stream 'input' into stream 'output', reading at most 423 1.1 rumble * 'maxinput' bytes from 'input'. 424 1.1 rumble * 425 1.1 rumble * The special value 0 for maxinput indicates no limit. 426 1.1 rumble * 427 1.1 rumble * Returns the number of bytes outputted. 428 1.1 rumble */ 429 1.1 rumble uint32_t 430 1.1 rumble decompress(FILE *input, FILE *output, uint32_t maxinput, int *cksum) 431 1.1 rumble { 432 1.1 rumble uint32_t ret; 433 1.1 rumble 434 1.1 rumble if (maxinput != 0 && maxinput < 4) 435 1.1 rumble return (0); 436 1.1 rumble 437 1.1 rumble if ((getc(input) & 0xff) != magic_header[0] || 438 1.1 rumble (getc(input) & 0xff) != magic_header[1]) 439 1.1 rumble return (0); 440 1.1 rumble 441 1.1 rumble clear_flg = 0; 442 1.1 rumble maxbits = getc(input); 443 1.1 rumble block_compress = maxbits & BLOCK_MASK; 444 1.1 rumble maxbits &= BIT_MASK; 445 1.1 rumble maxmaxcode = 1 << maxbits; 446 1.1 rumble if (maxbits > BITS) 447 1.1 rumble return (0); 448 1.1 rumble 449 1.1 rumble getcode_maxreadbytes = (maxinput == 0) ? 0 : maxinput - 3; 450 1.1 rumble getcode_readbytes = 0; 451 1.1 rumble output_checksum = 0; 452 1.1 rumble ret = do_decompression(input, output); 453 1.1 rumble *cksum = output_checksum; 454 1.1 rumble 455 1.1 rumble return (ret); 456 1.1 rumble } 457