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