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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1988 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include "codeset.h" 31 #include "mbextern.h" 32 #include "iso2022.h" 33 34 #define TO_MULTI 2 35 #define TO_SINGLE 1 36 37 #define BIT7ENV 7 /* 7bit enviornment */ 38 #define BIT8ENV 8 /* 8bit environment */ 39 #define NUM_OF_STATES 4 /* G0, G1, G2, G3 */ 40 #define BIT8(_ch) (_ch & 0x80) 41 #define MAXSIZE 100 /* ESC LOCK upper lower */ 42 43 #define USE_STATE 0 /* use the actual _state info */ 44 #define USE_CONTROL 1 /* use C0 or C1 */ 45 #define USE_SS2 2 /* use Single shift 2 */ 46 #define USE_SS3 3 /* use Single shift 3 */ 47 48 #define G0MASK 0x0000 49 #define G1MASK 0x0080 50 #define G2MASK 0x8000 51 #define G3MASK 0x8080 52 #define FINAL 0x33 /* Temporary final character */ 53 54 #define MMB_CUR_MAX 128 55 56 /* 57 * Keep state informations 58 */ 59 struct state { 60 char width; /* 1 or 2 */ 61 char final; /* final character */ 62 }; 63 64 static char _my_env = BIT7ENV; /* default 7bits environment */ 65 static struct state Invoked_G0, Invoked_G1; 66 static char _currentG0 = G0; 67 static char _currentG1 = G1; 68 static struct state _des_states[NUM_OF_STATES] = { 69 {-1, 0}, {-1, 0}, {-1, 0}, {01, 0} 70 }; 71 72 void _savestates(void); /* save states */ 73 void _restorestates(void); /* restore states */ 74 void _initializestates(void);/* Initialize states */ 75 76 77 /* 78 * Variables for wc*tomb*() 79 */ 80 static char _currentOUT = G0; /* G0, G1, G2 or G3 */ 81 static int prevcsize = 1; 82 83 /* 84 * mbtowc - subroutine for most iso codeset sequences 85 */ 86 int 87 _mbtowc_iso(wchar_t *pwc, char *s, size_t n) 88 { 89 unsigned char ch; 90 unsigned char tch; /* temporary use */ 91 unsigned char *us = (unsigned char *)s; 92 int gen_wide_state = USE_STATE; /* used in gen_wide: */ 93 int length = 0; 94 int len = 0; 95 wchar_t wide; 96 int mask; 97 int i; 98 99 isowidth_t * isoinfo = (isowidth_t *) _code_set_info.code_info; 100 101 /* 102 * initialize _g0_stuff 103 */ 104 if (_des_states[G0].width == -1) { 105 _des_states[G0].width = isoinfo->g0_len; 106 _des_states[G1].width = isoinfo->g1_len; 107 _des_states[G2].width = isoinfo->g2_len; 108 _des_states[G3].width = isoinfo->g3_len; 109 _my_env = isoinfo->bit_env; 110 111 Invoked_G0 = _des_states[G0]; 112 Invoked_G1 = _des_states[G1]; 113 } 114 115 /* 116 * get character and proceed 117 */ 118 loop: 119 ch = *us++; 120 if (++length > n) return (-1); /* too long */ 121 switch (ch) { /* get a character */ 122 /* escape sequence or locking shifts */ 123 case ESC: /* escape sequence */ 124 gen_wide_state = USE_STATE; /* used in gen_wide: */ 125 ch = *us++; 126 if (++length > n) return (-1); /* too long */ 127 switch (ch) { 128 /* DESIGNATE */ 129 case 0x24: /* designate */ 130 ch = *us++; 131 if (++length > n) return (-1); /* too long */ 132 switch (ch) { 133 case 0x28: case 0x29: 134 case 0x2A: case 0x2B: 135 case 0x2D: case 0x2E: 136 case 0x2F: 137 tch = ch; /* save this to decide _des_state */ 138 /* Skip intermidiates */ 139 do { 140 ch = *us++; 141 if (++length > n) return (-1); /* too long */ 142 } while (ch >= 0x20 && ch <= 0x2F); 143 if (ch < 0x30) /* ch should be a final character */ 144 return (-1); /* error */ 145 if (tch == 0x28) 146 i = G0; 147 else if (tch == 0x29 || tch == 0x2D) 148 i = G1; 149 else if (tch == 0x2A || tch == 0x2E) 150 i = G2; 151 else /* (tch == 0x2B || tch == 0x2F) */ 152 i = G3; 153 /* updates state info */ 154 _des_states[i].width = TO_MULTI; 155 _des_states[i].final = ch; 156 157 goto loop; 158 break; 159 default: 160 /* This is an illegal sequence */ 161 return (-1); 162 break; 163 } 164 break; 165 case 0x28: /* designate */ 166 case 0x29: case 0x2A: case 0x2B: 167 case 0x2D: case 0x2E: case 0x2F: 168 tch = ch; /* save this to decide _des_state */ 169 /* Skip intermidiates */ 170 do { 171 ch = *us++; 172 if (++length > n) return (-1); /* too long */ 173 } while (ch >= 0x20 && ch <= 0x2F); 174 if (ch < 0x30) /* ch should be a final character */ 175 return (-1); /* error */ 176 if (tch == 0x28) 177 i = G0; 178 else if (tch == 0x29 || tch == 0x2D) 179 i = G1; 180 else if (tch == 0x2A || tch == 0x2E) 181 i = G2; 182 else /* (tch == 0x2B || tch == 0x2F) */ 183 i = G3; 184 /* updates state info */ 185 _des_states[i].width = TO_SINGLE; 186 _des_states[i].final = ch; 187 188 goto loop; 189 break; 190 191 /* LOCKING SHIFTS */ 192 case LS1R: /* locking shift LS1R */; 193 Invoked_G1 = _des_states[G1]; 194 _currentG1 = G1; 195 goto loop; 196 break; 197 case LS2: /* locking shift LS2 */ 198 Invoked_G0 = _des_states[G2]; 199 _currentG0 = G2; 200 goto loop; 201 break; 202 case LS2R: /* locking shift LS2R */ 203 Invoked_G1 = _des_states[G2]; 204 _currentG1 = G2; 205 goto loop; 206 break; 207 case LS3: /* locking shift LS3 */ 208 Invoked_G0 = _des_states[G3]; 209 _currentG0 = G3; 210 goto loop; 211 break; 212 case LS3R: /* locking shift LS3R */ 213 Invoked_G1 = _des_states[G3]; 214 _currentG1 = G3; 215 goto loop; 216 break; 217 218 /* CONTROL FUNCTIONS */ 219 case 0x21: /* C0 sets */ 220 case 0x22: /* C1 sets */ 221 do { 222 ch = *us++; 223 if (++length > n) return (-1); /* too long */ 224 } while (ch >= 0x20 && ch <= 0x2F); 225 if (ch < 0x30) /* ch should be a final character */ 226 return (-1); /* error */ 227 goto loop; 228 break; 229 230 /* SINGLE SHIFT for 7bit environment */ 231 case SS2_7B: /* Single shift SS2 for 7bits */ 232 case SS3_7B: /* Single shoft SS3 for 7bits */ 233 if (ch == SS2_7B) 234 gen_wide_state = USE_SS2; 235 else 236 gen_wide_state = USE_SS3; 237 goto loop; 238 break; 239 240 default: /* should be an error */ 241 return (-1); 242 break; 243 } 244 /* locking shifts */ 245 case LS0: 246 gen_wide_state = USE_STATE; /* used in gen_wide: */ 247 Invoked_G0 = _des_states[G0]; 248 _currentG0 = G0; 249 goto loop; 250 break; 251 252 case LS1: 253 gen_wide_state = USE_STATE; /* used in gen_wide: */ 254 Invoked_G0 = _des_states[G1]; 255 _currentG0 = G1; 256 goto loop; 257 break; 258 259 /* Single shift SS3 and SS2 for 8bits */ 260 case SS2_8B: 261 case SS3_8B: 262 if (ch == SS2_8B) 263 gen_wide_state = USE_SS2; 264 else 265 gen_wide_state = USE_SS3; 266 goto loop; 267 break; 268 269 /* This character is not any special character/ 270 * It does not change any state. 271 * Goto where it generates wide character. 272 */ 273 default: 274 /* 275 * Use this ch to generate pwc. 276 */ 277 if (ch == 0) { /* end of string or 0 */ 278 wide = 0; 279 mask = 0; 280 goto gen_wide; 281 } 282 break; 283 } 284 285 286 /* 287 * Generate pwc here. 288 * The information here is 289 * current state and length. If the length is two, you need to 290 * read one more character. 291 */ 292 switch (gen_wide_state) { 293 case USE_STATE: 294 if (BIT8(ch)) { /* 8bit environment ? */ 295 /* current mode is G1 mode */ 296 if (Invoked_G1.width == 2) { 297 tch = *us++; 298 if (++length > n) return (-1); 299 wide = ch; 300 wide = (wide << 8 | tch); 301 } 302 else { 303 wide = ch; 304 } 305 if (_currentG1 == G0) mask = G0MASK; 306 else if (_currentG1 == G1) mask = G1MASK; 307 else if (_currentG1 == G2) mask = G2MASK; 308 else mask = G3MASK; 309 } 310 else { 311 /* current mode is G0 mode */ 312 if (Invoked_G0.width == 2) { 313 tch = *us++; 314 if (++length > n) return (-1); 315 wide = ch; 316 wide = (wide << 8 | tch); 317 } 318 else { 319 wide = ch; 320 } 321 if (_currentG0 == G0) mask = G0MASK; 322 else if (_currentG0 == G1) mask = G1MASK; 323 else if (_currentG0 == G2) mask = G2MASK; 324 else mask = G3MASK; 325 } 326 break; 327 case USE_SS2: 328 if (_des_states[G2].width == 2) { 329 tch = *us++; 330 if (++length > n) return (-1); 331 wide = ch; 332 wide = (wide << 8 | tch); 333 } 334 else { 335 wide = ch; 336 } 337 mask = G2MASK; 338 break; 339 case USE_SS3: 340 if (_des_states[G3].width == 2) { 341 tch = *us++; 342 if (++length > n) return (-1); 343 wide = ch; 344 wide = (wide << 8 | tch); 345 } 346 else { 347 wide = ch; 348 } 349 mask = G3MASK; 350 break; 351 default: 352 /* shoult be internal error */ 353 return (-1); 354 break; 355 } 356 gen_wide: 357 wide &= 0x7F7F; /* strip off the top bit */ 358 wide = wide | mask; 359 if (pwc != NULL) 360 *pwc = wide; 361 return (length); 362 } 363 364 365 #define MAXMBSIZE 128 366 /* 367 * mbstowcs() 368 */ 369 size_t 370 _mbstowcs_iso(wchar_t *pwcs, unsigned char *s, size_t n) 371 { 372 int ret1; 373 int accsum = 0; 374 wchar_t pwc; 375 376 /* 377 * If pwcs == 0, do nothing. 378 */ 379 if (pwcs == 0) 380 return (0); 381 /* 382 * States things 383 */ 384 _savestates(); _initializestates(); 385 while (accsum < n) { 386 ret1 = _mbtowc_iso (&pwc, (char *)s, MAXMBSIZE); 387 if (ret1 < 0) 388 return (-1); /* error */ 389 if (ret1 == 0 || pwc == 0) { 390 if (pwcs == 0) 391 *pwcs = 0; 392 /* 393 * Restore states 394 */ 395 _restorestates(); 396 return (accsum); 397 } 398 s = s + ret1; /* increment the pointer */ 399 *pwcs++ = pwc; 400 ++accsum; 401 } 402 /* 403 * Restore states 404 */ 405 _restorestates(); 406 return (accsum); 407 } 408 409 /* 410 * wctomb - 411 */ 412 int 413 _wctomb_iso(unsigned char *s, wchar_t pwc) 414 { 415 unsigned char ch; 416 unsigned char tch; /* temporary use */ 417 unsigned char *us = (unsigned char *)s; 418 int gen_wide_state = USE_STATE; /* used in gen_wide: */ 419 int length = 0; 420 int len = 0; 421 wchar_t wide; 422 unsigned short mode; 423 unsigned char buf[MAXSIZE]; 424 unsigned char *bp; 425 int csize, i; 426 int n = MMB_CUR_MAX; 427 428 isowidth_t * isoinfo = (isowidth_t *) _code_set_info.code_info; 429 430 /* 431 * If pwc is 0, do this first. 432 */ 433 if (pwc == 0) { 434 if (s != 0) { 435 *s = 0; 436 return (1); 437 } 438 else { 439 return (0); 440 } 441 } 442 443 mode = pwc & G3MASK; /* The mode of this character */ 444 if (((pwc >> 8) & 0x007f) == 0) 445 csize = 1; 446 else 447 csize = 2; 448 bp = buf; 449 length = 0; 450 #ifdef DDDebug 451 if (_my_env == BIT7ENV) 452 printf ("7b "); 453 else 454 printf ("8b "); 455 printf ("csize = %d, prevcsize = %d, (%x,%x) ",csize, prevcsize, (pwc>>8)&0x00ff, pwc&0x00ff); 456 switch (mode) { 457 case G0MASK: 458 printf ("G0"); break; 459 case G1MASK: 460 printf ("G1"); break; 461 case G2MASK: 462 printf ("G2"); break; 463 case G3MASK: 464 printf ("G3"); break; 465 default: 466 printf ("XXXX"); break; 467 } 468 #endif 469 470 switch (_my_env) { 471 case BIT7ENV: /* 7 bit environment */ 472 switch (mode) { 473 case G0MASK: 474 if (_currentOUT != G0 || prevcsize != csize) { 475 _currentOUT = G0; 476 if (csize == 2) { 477 /* 478 * Emit escape sequences 479 */ 480 *bp++ = ESC; 481 *bp++ = 0x24; 482 *bp++ = 0x28; 483 *bp++ = FINAL; 484 length += 4; 485 } 486 else { 487 /* 488 * Emit escape sequences 489 */ 490 *bp++ = ESC; 491 *bp++ = 0x28; 492 *bp++ = FINAL; 493 length += 3; 494 } 495 *bp++ = SI; 496 ++length; 497 } 498 if (csize == 1) { 499 *bp++ = pwc & 0x007f; 500 ++length; 501 } 502 else { 503 *bp++ = (pwc & 0x7f00) >> 8; 504 ++length; 505 *bp++ = pwc & 0x007f; 506 ++length; 507 } 508 break; 509 case G1MASK: 510 if (_currentOUT != G1 || prevcsize != csize) { 511 _currentOUT = G1; 512 if (csize == 2) { 513 /* 514 * Emit escape sequences 515 */ 516 *bp++ = ESC; 517 *bp++ = 0x24; 518 *bp++ = 0x29; 519 *bp++ = FINAL; 520 length += 4; 521 } 522 else { 523 /* 524 * Emit escape sequences 525 */ 526 *bp++ = ESC; 527 *bp++ = 0x29; 528 *bp++ = FINAL; 529 length += 3; 530 } 531 *bp++ = SO; 532 ++length; 533 } 534 if (csize == 1) { 535 *bp++ = pwc & 0x007f; 536 ++length; 537 } 538 else { 539 *bp++ = (pwc & 0x7f00) >> 8; 540 ++length; 541 *bp++ = pwc & 0x007f; 542 ++length; 543 } 544 break; 545 case G2MASK: 546 if (_currentOUT != G2 || prevcsize != csize) { 547 _currentOUT = G2; 548 if (csize == 2) { 549 /* 550 * Emit escape sequences 551 */ 552 *bp++ = ESC; 553 *bp++ = 0x24; 554 *bp++ = 0x2A; 555 *bp++ = FINAL; 556 length += 4; 557 } 558 else { 559 /* 560 * Emit escape sequences 561 */ 562 *bp++ = ESC; 563 *bp++ = 0x2A; 564 *bp++ = FINAL; 565 length += 3; 566 } 567 *bp++ = ESC; *bp++ = LS2; 568 length += 2; 569 } 570 if (csize == 1) { 571 *bp++ = pwc & 0x007f; 572 ++length; 573 } 574 else { 575 *bp++ = (pwc & 0x7f00) >> 8; 576 ++length; 577 *bp++ = pwc & 0x007f; 578 ++length; 579 } 580 break; 581 case G3MASK: 582 if (_currentOUT != G3 || prevcsize != csize) { 583 _currentOUT = G3; 584 if (csize == 2) { 585 /* 586 * Emit escape sequences 587 */ 588 *bp++ = ESC; 589 *bp++ = 0x24; 590 *bp++ = 0x2B; 591 *bp++ = FINAL; 592 length += 4; 593 } 594 else { 595 /* 596 * Emit escape sequences 597 */ 598 *bp++ = ESC; 599 *bp++ = 0x2B; 600 *bp++ = FINAL; 601 length += 3; 602 } 603 *bp++ = ESC; *bp++ = LS3; 604 length += 2; 605 } 606 if (csize == 1) { 607 *bp++ = pwc & 0x007f; 608 ++length; 609 } 610 else { 611 *bp++ = (pwc & 0x7f00) >> 8; 612 ++length; 613 *bp++ = pwc & 0x007f; 614 ++length; 615 } 616 break; 617 } 618 break; 619 case BIT8ENV: /* 8 bit environment */ 620 switch (mode) { 621 case G0MASK: 622 if (_currentOUT != G0 || prevcsize != csize) { 623 _currentOUT = G0; 624 if (csize == 2) { 625 /* 626 * Emit escape sequences 627 */ 628 *bp++ = ESC; 629 *bp++ = 0x24; 630 *bp++ = 0x28; 631 *bp++ = FINAL; 632 length += 4; 633 } 634 else { 635 /* 636 * Emit escape sequences 637 */ 638 *bp++ = ESC; 639 *bp++ = 0x28; 640 *bp++ = FINAL; 641 length += 3; 642 } 643 *bp++ = LS0; 644 ++length; 645 } 646 if (csize == 1) { 647 *bp++ = pwc & 0x007f; 648 ++length; 649 } 650 else { 651 *bp++ = (pwc & 0x7f00) >> 8; 652 ++length; 653 *bp++ = pwc & 0x007f; 654 ++length; 655 } 656 break; 657 case G1MASK: 658 if (_currentOUT != G1 || prevcsize != csize) { 659 _currentOUT = G1; 660 if (csize == 2) { 661 /* 662 * Emit escape sequences 663 */ 664 *bp++ = ESC; 665 *bp++ = 0x24; 666 *bp++ = 0x29; 667 *bp++ = FINAL; 668 length += 4; 669 } 670 else { 671 /* 672 * Emit escape sequences 673 */ 674 *bp++ = ESC; 675 *bp++ = 0x29; 676 *bp++ = FINAL; 677 length += 3; 678 } 679 *bp++ = ESC; *bp++ = LS1R; 680 length += 2; 681 } 682 683 /* 684 * If state is G1 or G2, or G3, assume that 685 * this is 8bit characters. To do this more 686 * accurately, wide character needs to be 687 * larger than 16 bits to keep more information. 688 */ 689 pwc |= 0x8080; 690 if (csize == 1) { 691 *bp++ = pwc & 0x00ff; 692 ++length; 693 } 694 else { 695 *bp++ = (pwc & 0xff00) >> 8; 696 ++length; 697 *bp++ = pwc & 0x00ff; 698 ++length; 699 } 700 break; 701 case G2MASK: 702 if (_currentOUT != G2 || prevcsize != csize) { 703 _currentOUT = G2; 704 if (csize == 2) { 705 /* 706 * Emit escape sequences 707 */ 708 *bp++ = ESC; 709 *bp++ = 0x24; 710 *bp++ = 0x2A; 711 *bp++ = FINAL; 712 length += 4; 713 } 714 else { 715 /* 716 * Emit escape sequences 717 */ 718 *bp++ = ESC; 719 *bp++ = 0x2A; 720 *bp++ = FINAL; 721 length += 3; 722 } 723 *bp++ = ESC; *bp++ = LS2R; 724 length += 2; 725 } 726 /* 727 * If state is G1 or G2, or G3, assume that 728 * this is 8bit characters. To do this more 729 * accurately, wide character needs to be 730 * larger than 16 bits to keep more information. 731 */ 732 pwc |= 0x8080; 733 if (csize == 1) { 734 *bp++ = pwc & 0x00ff; 735 ++length; 736 } 737 else { 738 *bp++ = (pwc & 0xff00) >> 8; 739 ++length; 740 *bp++ = pwc & 0x00ff; 741 ++length; 742 } 743 break; 744 case G3MASK: 745 if (_currentOUT != G3 || prevcsize != csize) { 746 _currentOUT = G3; 747 if (csize == 2) { 748 /* 749 * Emit escape sequences 750 */ 751 *bp++ = ESC; 752 *bp++ = 0x24; 753 *bp++ = 0x2B; 754 *bp++ = FINAL; 755 length += 4; 756 } 757 else { 758 /* 759 * Emit escape sequences 760 */ 761 *bp++ = ESC; 762 *bp++ = 0x2B; 763 *bp++ = FINAL; 764 length += 3; 765 } 766 *bp++ = ESC; *bp++ = LS3R; 767 length += 2; 768 } 769 /* 770 * If state is G1 or G2, or G3, assume that 771 * this is 8bit characters. To do this more 772 * accurately, wide character needs to be 773 * larger than 16 bits to keep more information. 774 */ 775 pwc |= 0x8080; 776 if (csize == 1) { 777 *bp++ = pwc & 0x00ff; 778 ++length; 779 } 780 else { 781 *bp++ = (pwc & 0xff00) >> 8; 782 ++length; 783 *bp++ = pwc & 0x00ff; 784 ++length; 785 } 786 break; 787 } 788 break; 789 default: /* Should never happens */ 790 return (-1); 791 break; 792 } 793 794 prevcsize = csize; 795 796 if (length > n) { 797 return (-1); /* buffer too small */ 798 } 799 for (i = 0; i < length; i++) { 800 *s++ = buf[i]; 801 } 802 #ifdef DDDebug 803 printf ("\t("); 804 for (i = 0; i < length; i++) { 805 printf ("%x,", buf[i]); 806 } 807 printf (")\n"); 808 #endif 809 return (length); 810 } 811 812 /* 813 * wcstombs 814 */ 815 size_t 816 _wcstombs_iso(char *s, wchar_t *pwcs, int n) 817 { 818 int acclen = 0; 819 char buf[MMB_CUR_MAX]; 820 int ret1; 821 int i; 822 823 if (n < 0) 824 return (-1); 825 /* 826 * Initialize State 827 */ 828 _savestates(); _initializestates(); 829 while (acclen < n) { 830 ret1 = _wctomb_iso ((unsigned char *)buf, *pwcs); 831 /* 832 * end of string ? 833 */ 834 if (ret1 == 1 && buf[0] == 0) { 835 *s = 0; 836 /* 837 * restore states 838 */ 839 _restorestates(); 840 return (acclen); 841 } 842 /* 843 * Error ? 844 */ 845 if (ret1 < 0) 846 return (-1); 847 acclen += ret1; 848 for (i = 0; i < ret1; i++) 849 *s++ = buf[i]; 850 ++pwcs; 851 } 852 853 /* 854 * restore states 855 */ 856 _restorestates(); 857 858 /* 859 * return the length 860 */ 861 return (acclen); 862 } 863 864 865 /* 866 * Supplementary routines 867 */ 868 869 void 870 _initializestates(void) 871 { 872 _currentG0 = G0; 873 _currentG1 = G1; 874 875 _des_states[G0].width = -1; /* This makes it Initialize */ 876 877 _currentOUT = G0; 878 prevcsize = 1; 879 } 880 881 static char SAVED_currentG0; 882 static char SAVED_currentG1; 883 static struct state SAVED_des_states[NUM_OF_STATES]; 884 static struct state SAVED_Invoked_G0, SAVED_Invoked_G1; 885 static char SAVED_currentOUT = G0; /* G0, G1, G2 or G3 */ 886 static int SAVED_prevcsize = 1; 887 888 void 889 _savestates(void) 890 { 891 892 SAVED_currentG0 = _currentG0; 893 SAVED_currentG1 = _currentG1; 894 895 SAVED_des_states[G0] = _des_states[G0]; 896 SAVED_des_states[G1] = _des_states[G1]; 897 SAVED_des_states[G2] = _des_states[G2]; 898 SAVED_des_states[G3] = _des_states[G3]; 899 900 SAVED_Invoked_G0 = Invoked_G0; 901 SAVED_Invoked_G1 = Invoked_G1; 902 903 SAVED_currentOUT = _currentOUT; 904 SAVED_prevcsize = prevcsize; 905 } 906 907 void 908 _restorestates(void) 909 { 910 _currentG0 = SAVED_currentG0; 911 _currentG1 = SAVED_currentG1; 912 913 _des_states[G0] = SAVED_des_states[G0]; 914 _des_states[G1] = SAVED_des_states[G1]; 915 _des_states[G2] = SAVED_des_states[G2]; 916 _des_states[G3] = SAVED_des_states[G3]; 917 918 Invoked_G0 = SAVED_Invoked_G0; 919 Invoked_G1 = SAVED_Invoked_G1; 920 921 _currentOUT = SAVED_currentOUT; 922 prevcsize = SAVED_prevcsize; 923 } 924