1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2018 Chelsio Communications, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 #include "tcb_common.h" 31 32 /***:----------------------------------------------------------------------- 33 ***: externals 34 ***:----------------------------------------------------------------------- 35 */ 36 37 extern _TCBVAR g_tcb_info4[]; 38 extern _TCBVAR g_scb_info4[]; 39 extern _TCBVAR g_fcb_info4[]; 40 extern void t4_display_tcb_aux_0(_TCBVAR *tvp,int aux); 41 extern void t4_display_tcb_aux_1(_TCBVAR *tvp,int aux); 42 extern void t4_display_tcb_aux_2(_TCBVAR *tvp,int aux); 43 extern void t4_display_tcb_aux_3(_TCBVAR *tvp,int aux); 44 45 extern _TCBVAR g_tcb_info5[]; 46 extern _TCBVAR g_scb_info5[]; 47 extern _TCBVAR g_fcb_info5[]; 48 extern void t5_display_tcb_aux_0(_TCBVAR *tvp,int aux); 49 extern void t5_display_tcb_aux_1(_TCBVAR *tvp,int aux); 50 extern void t5_display_tcb_aux_2(_TCBVAR *tvp,int aux); 51 extern void t5_display_tcb_aux_3(_TCBVAR *tvp,int aux); 52 53 extern _TCBVAR g_tcb_info6[]; 54 extern _TCBVAR g_scb_info6[]; 55 extern _TCBVAR g_fcb_info6[]; 56 extern void t6_display_tcb_aux_0(_TCBVAR *tvp,int aux); 57 extern void t6_display_tcb_aux_1(_TCBVAR *tvp,int aux); 58 extern void t6_display_tcb_aux_2(_TCBVAR *tvp,int aux); 59 extern void t6_display_tcb_aux_3(_TCBVAR *tvp,int aux); 60 extern void t6_display_tcb_aux_4(_TCBVAR *tvp,int aux); 61 62 /***:----------------------------------------------------------------------- 63 ***: globals 64 ***:----------------------------------------------------------------------- 65 */ 66 67 _TCBVAR *g_tcb_info=g_tcb_info5; 68 _TCBVAR *g_scb_info=g_scb_info5; 69 _TCBVAR *g_fcb_info=g_fcb_info5; 70 static int g_tN=0; 71 72 static int g_prntstyl=PRNTSTYL_COMP; 73 74 static int g_got_scb=0; 75 static int g_got_fcb=0; 76 77 78 /***:----------------------------------------------------------------------- 79 ***: error exit functions 80 ***:----------------------------------------------------------------------- 81 */ 82 83 /**: err_exit functions 84 *: ------------------ 85 */ 86 87 void tcb_prflush(void) 88 { 89 fflush(stdout); 90 fflush(stderr); 91 } 92 93 94 void tcb_code_err_exit(char *fmt, ...) 95 { 96 va_list args; 97 va_start(args, fmt); 98 printf("Coding Error in: "); 99 vprintf(fmt, args); 100 printf("\n"); 101 tcb_prflush(); 102 va_end(args); 103 exit(1); 104 } 105 106 /***:----------------------------------------------------------------------- 107 ***: tcb_hexdump functions 108 ***:----------------------------------------------------------------------- 109 */ 110 111 void 112 tcb_hexdump(unsigned base, unsigned char *buf, unsigned int size) 113 { 114 unsigned offset; 115 116 for (offset = 0; offset < size; ++offset) { 117 if (!(offset % 16)) printf("\n0x%4.4x: ", base + offset); 118 else if (!(offset % 8)) printf(" "); 119 printf("%2.2x ", (unsigned char)buf[offset]); 120 } 121 } 122 123 int tcb_strmatch_nc(char *cs, char *ct) { 124 while (*cs) 125 if (tolower(*cs++) != tolower(*ct++)) return (FALSE); 126 return (!(*ct)); /*return TRUE if *ct NULL at same time as *cs==NULL*/ 127 } 128 129 130 /*: ------------------------------------------------------------------------- 131 string functions 132 tcb_strmatch_nc: Similar to exact match, but case insensitive. 133 */ 134 135 136 int 137 tcb_strncmp_nc(char *cs, char *ct, int n) 138 { 139 /*case insensitive version of the standard strncmp() function */ 140 int i = 0; 141 int ret; 142 143 144 ret = 0; 145 for (i = 0; i < n && 0 == ret && !(EOS == *cs && EOS == *ct); ++i) { 146 /* this is weird, but it matched GCC linux when strings don't 147 * have any upper case characters. 148 */ 149 ret = tolower(*cs++) - tolower(*ct++); 150 } 151 return ret; 152 } 153 154 int 155 tcb_startswith_nc(char *cs, char *ct) 156 { /* return true if cs start with ct */ 157 return (0 == tcb_strncmp_nc(cs, ct, (int)strlen(ct))); 158 } 159 160 161 162 163 /***:----------------------------------------------------------------------- 164 ***: START OF WINDOWS FUNCTIONS 165 ***:----------------------------------------------------------------------- 166 */ 167 168 169 /***:----------------------------------------------------------------------- 170 ***: print utilities 171 ***:----------------------------------------------------------------------- 172 */ 173 174 static int g_PR_indent=1; 175 176 void PR(char *fmt, ...) 177 { 178 int fmt_len; 179 va_list args; 180 va_start(args,fmt); 181 182 if (g_PR_indent) printf(" "); 183 g_PR_indent=0; 184 fmt_len=(int) strlen(fmt); 185 if (fmt_len>0 && fmt[fmt_len-1]=='\n') g_PR_indent=1; 186 187 vprintf(fmt,args); 188 tcb_prflush(); 189 va_end(args); 190 } 191 192 193 /***:----------------------------------------------------------------------- 194 ***: val() 195 ***:----------------------------------------------------------------------- 196 */ 197 198 _TCBVAR * 199 lu_tcbvar(char *name) 200 { 201 _TCBVAR *tvp=g_tcb_info; 202 203 while (tvp->name!=NULL) { 204 if (tcb_strmatch_nc(name,tvp->name)) return tvp; 205 else if (tcb_strmatch_nc(name,tvp->aka )) return tvp; 206 tvp+=1; 207 } 208 tcb_code_err_exit("lu_tcbvar: bad name %s\n",name); 209 return NULL; 210 } 211 212 unsigned 213 val(char *name) 214 { 215 _TCBVAR *tvp; 216 217 tvp=lu_tcbvar(name); 218 return tvp->val; 219 } 220 221 ui64 222 val64(char *name) 223 { 224 _TCBVAR *tvp; 225 226 tvp=lu_tcbvar(name); 227 return tvp->rawval; 228 } 229 230 231 232 /***:----------------------------------------------------------------------- 233 ***: get_tcb_bits 234 ***:----------------------------------------------------------------------- 235 */ 236 237 238 static int 239 get_tcb_bit(unsigned char *A, int bit) 240 { 241 int ret=0; 242 int ix,shift; 243 244 ix = 127 - (bit>>3); 245 shift=bit&0x7; 246 /* prdbg(" ix: %u, shift=%u\n",ix,shift); */ 247 ret=(A[ix] >> shift) & 1; 248 return ret; 249 } 250 251 static ui64 252 get_tcb_bits (unsigned char *A, int hi, int lo) 253 { 254 ui64 ret=0; 255 256 if (lo>hi) { 257 int temp=lo; 258 lo=hi; 259 hi=temp; 260 } 261 262 while (hi>=lo) { 263 ret = (ret<<1) | get_tcb_bit(A,hi); 264 --hi; 265 } 266 267 return ret; 268 } 269 270 271 void 272 decompress_val(_TCBVAR *tvp,unsigned ulp_type,unsigned tx_max, 273 unsigned rcv_nxt,unsigned rx_frag0_start_idx_raw) 274 { 275 unsigned rawval=(unsigned) tvp->rawval; 276 277 switch(tvp->comp) { 278 case COMP_NONE: tvp->val=rawval; break; 279 case COMP_ULP: tvp->val=rawval; break; 280 case COMP_TX_MAX: 281 tvp->val=(tx_max - rawval) & 0xFFFFFFFF; 282 break; 283 case COMP_RCV_NXT: 284 if (tcb_startswith_nc(tvp->name,"rx_frag")) { 285 unsigned fragx=0; 286 if (!tcb_strmatch_nc(tvp->name,"rx_frag0_start_idx_raw")) 287 fragx=rawval; 288 tvp->val=(rcv_nxt+rx_frag0_start_idx_raw+fragx) & 0xFFFFFFFF; 289 } else { 290 tvp->val=(rcv_nxt - rawval) & 0xFFFFFFFF; 291 } 292 break; 293 case COMP_PTR: tvp->val=rawval; break; 294 case COMP_LEN: 295 { 296 tvp->val=rawval; 297 if (PM_MODE_RDDP==ulp_type || PM_MODE_DDP==ulp_type || 298 PM_MODE_IANDP==ulp_type) { 299 /* TP does this internally. Not sure if I should show the 300 * unaltered value or the raw value. For now I 301 * will display the raw value. For now I've added the code 302 * mainly to stop windows compiler from warning about ulp_type 303 * being an unreferenced parameter. 304 */ 305 tvp->val=0; 306 tvp->val=rawval; /* comment this out to display altered value */ 307 } 308 } 309 break; 310 default: 311 tcb_code_err_exit("decompress_val, bad switch: %d",tvp->comp); 312 break; 313 } 314 315 316 317 } 318 319 320 void 321 get_tcb_field(_TCBVAR *tvp,unsigned char *buf) 322 { 323 assert(tvp->hi-tvp->lo+1<=64); 324 assert(tvp->hi>=tvp->lo); 325 326 tvp->rawval=get_tcb_bits(buf,tvp->lo,tvp->hi); 327 /* assume no compression and 32-bit value for now */ 328 tvp->val=(unsigned) (tvp->rawval & 0xFFFFFFFF); 329 330 331 } 332 333 334 /***:----------------------------------------------------------------------- 335 ***: spr_* functions 336 ***:----------------------------------------------------------------------- 337 */ 338 339 char * 340 spr_tcp_state (unsigned state) 341 { 342 char *ret="UNKNOWN"; 343 344 if ( 0 == state) {ret = "CLOSED";} 345 else if ( 1 == state) {ret = "LISTEN";} 346 else if ( 2 == state) {ret = "SYN_SENT";} 347 else if ( 3 == state) {ret = "SYN_RCVD";} 348 else if ( 4 == state) {ret = "ESTABLISHED";} 349 else if ( 5 == state) {ret = "CLOSE_WAIT";} 350 else if ( 6 == state) {ret = "FIN_WAIT_1";} 351 else if ( 7 == state) {ret = "CLOSING";} 352 else if ( 8 == state) {ret = "LAST_ACK";} 353 else if ( 9 == state) {ret = "FIN_WAIT_2";} 354 else if (10 == state) {ret = "TIME_WAIT";} 355 else if (11 == state) {ret = "ESTABLISHED_RX";} 356 else if (12 == state) {ret = "ESTABLISHED_TX";} 357 else if (13 == state) {ret = "SYN_PEND";} 358 else if (14 == state) {ret = "ESC_1_STATE";} 359 else if (15 == state) {ret = "ESC_2_STATE";} 360 361 return ret; 362 } 363 364 char * 365 spr_cctrl_sel(unsigned sel0,unsigned sel1) 366 { 367 unsigned sel=(sel1<<1) | sel0; 368 char *ret="UNKNOWN"; 369 370 if ( 0 == sel) {ret = "Reno";} 371 else if ( 1 == sel) {ret = "Tahoe";} 372 else if ( 2 == sel) {ret = "NewReno";} 373 else if ( 3 == sel) {ret = "HighSpeed";} 374 375 return ret; 376 } 377 378 379 char * 380 spr_ulp_type(unsigned ulp_type) 381 { 382 char *ret="UNKNOWN"; 383 384 /*The tp.h PM_MODE_XXX call 1 DDP and 5 IANDP, but external 385 * documentation (tcb.h" calls 5 ddp, and doesn't mention 1 or 3. 386 */ 387 388 if ( PM_MODE_PASS == ulp_type) {ret = "TOE";} 389 else if ( PM_MODE_DDP == ulp_type) {ret = "DDP";} 390 else if ( PM_MODE_ISCSI == ulp_type) {ret = "ISCSI";} 391 else if ( PM_MODE_IWARP == ulp_type) {ret = "IWARP";} 392 else if ( PM_MODE_RDDP == ulp_type) {ret = "RDMA";} 393 else if ( PM_MODE_IANDP == ulp_type) {ret = "IANDP_DDP";} 394 else if ( PM_MODE_FCOE == ulp_type) {ret = "FCoE";} 395 else if ( PM_MODE_USER == ulp_type) {ret = "USER";} 396 else if ( PM_MODE_TLS == ulp_type) {ret = "TLS";} 397 else if ( PM_MODE_DTLS == ulp_type) {ret = "DTLS";} 398 399 return ret; 400 } 401 402 char * 403 spr_ip_version(unsigned ip_version) 404 { 405 char *ret="UNKNOWN"; 406 407 if ( 0 == ip_version) {ret = "IPv4";} 408 else if ( 1 == ip_version) {ret = "IPv6";} 409 410 return ret; 411 } 412 413 414 415 /***:----------------------------------------------------------------------- 416 ***: display_tcb() 417 ***:----------------------------------------------------------------------- 418 */ 419 420 void 421 display_tcb_compressed(_TCBVAR *tvp,int aux) 422 { 423 424 if (g_tN==4) { 425 t4_display_tcb_aux_0(tvp,aux); 426 if (1==aux) t4_display_tcb_aux_1(tvp,aux); 427 else if (2==aux) t4_display_tcb_aux_2(tvp,aux); 428 else if (3==aux) t4_display_tcb_aux_3(tvp,aux); 429 430 } else if (g_tN==5) { 431 t5_display_tcb_aux_0(tvp,aux); 432 if (1==aux) t5_display_tcb_aux_1(tvp,aux); 433 else if (2==aux) t5_display_tcb_aux_2(tvp,aux); 434 else if (3==aux) t5_display_tcb_aux_3(tvp,aux); 435 } else if (g_tN==6) { 436 t6_display_tcb_aux_0(tvp,aux); 437 if (1==aux) t6_display_tcb_aux_1(tvp,aux); 438 else if (2==aux) t6_display_tcb_aux_2(tvp,aux); 439 else if (3==aux) t6_display_tcb_aux_3(tvp,aux); 440 else if (4==aux) t6_display_tcb_aux_4(tvp,aux); 441 } 442 } 443 444 445 446 447 /***:----------------------------------------------------------------------- 448 ***: parse_n_decode_tcb 449 ***:----------------------------------------------------------------------- 450 */ 451 452 453 unsigned 454 parse_tcb( _TCBVAR *base_tvp, unsigned char *buf) 455 { /* parse the TCB */ 456 _TCBVAR *tvp=base_tvp; 457 unsigned ulp_type; 458 int aux=1; /* assume TOE or iSCSI */ 459 unsigned tx_max=0, rcv_nxt=0, rx_frag0_start_idx_raw=0; 460 int got_tx_max=0, got_rcv_nxt=0, got_rx_frag0_start_idx_raw=0; 461 462 463 /* parse the TCB */ 464 while (tvp->name!=NULL) { 465 get_tcb_field(tvp,buf); 466 if (!got_tx_max && tcb_strmatch_nc("tx_max",tvp->name)) { 467 tx_max=tvp->val; 468 got_tx_max=1; 469 } 470 if (!got_rcv_nxt && tcb_strmatch_nc("rcv_nxt",tvp->name)) { 471 rcv_nxt=tvp->val; 472 got_rcv_nxt=1; 473 } 474 if (!got_rx_frag0_start_idx_raw && 475 tcb_strmatch_nc("rx_frag0_start_idx_raw",tvp->name)) { 476 rx_frag0_start_idx_raw=tvp->val; 477 got_rx_frag0_start_idx_raw=1; 478 } 479 tvp+=1; 480 } 481 482 tvp=base_tvp; 483 ulp_type=tvp->val; /* ULP type is always first variable in TCB */ 484 if (PM_MODE_IANDP==ulp_type || PM_MODE_FCOE==ulp_type) aux=3; 485 else if (PM_MODE_RDDP==ulp_type) aux=2; 486 else if (6==g_tN && (PM_MODE_TLS==ulp_type || PM_MODE_DTLS==ulp_type)) aux=4; 487 else aux=1; 488 489 assert(got_tx_max && got_rcv_nxt && got_rx_frag0_start_idx_raw); 490 491 /* decompress the compressed values */ 492 tvp=base_tvp; 493 while (tvp->name!=NULL) { 494 decompress_val(tvp,ulp_type,tx_max,rcv_nxt,rx_frag0_start_idx_raw); 495 tvp+=1; 496 } 497 498 return aux; 499 } 500 501 502 503 void 504 parse_scb( _TCBVAR *base_tvp, unsigned char *buf) 505 { /* parse the SCB */ 506 _TCBVAR *tvp=base_tvp; 507 508 while (tvp->name!=NULL) { 509 if (tcb_strmatch_nc("scb_slush",tvp->name)) { 510 /* the scb_slush field is all of remaining memory */ 511 tvp->rawval=0; 512 tvp->val=0; 513 } else { 514 get_tcb_field(tvp,buf); 515 } 516 tvp+=1; 517 } 518 } 519 520 521 void 522 parse_fcb( _TCBVAR *base_tvp, unsigned char *buf) 523 { /* parse the FCB */ 524 _TCBVAR *tvp=base_tvp; 525 526 while (tvp->name!=NULL) { 527 get_tcb_field(tvp,buf); 528 tvp+=1; 529 } 530 } 531 532 533 void 534 display_list_tcb(_TCBVAR *base_tvp,int aux) 535 { 536 _TCBVAR *tvp=base_tvp; 537 while (tvp->name!=NULL) { 538 if (tvp->aux==0 || tvp->aux==aux) { 539 if (tvp->hi-tvp->lo+1<=32) { 540 printf(" %4d:%4d %31s: %10u (0x%1x)",tvp->lo,tvp->hi,tvp->name, 541 (unsigned) tvp->rawval,(unsigned) tvp->rawval); 542 if (COMP_TX_MAX==tvp->comp || COMP_RCV_NXT==tvp->comp) 543 printf(" -> %1u (0x%x)", tvp->val,tvp->val); 544 } else { 545 printf(" %4d:%4d %31s: 0x%1llx",tvp->lo,tvp->hi,tvp->name, 546 tvp->rawval); 547 } 548 printf("\n"); 549 } 550 tvp+=1; 551 } 552 } 553 554 void 555 display_tcb(_TCBVAR *tvp,unsigned char *buf,int aux) 556 { 557 if (g_prntstyl==PRNTSTYL_VERBOSE || 558 g_prntstyl==PRNTSTYL_RAW) { 559 tcb_hexdump(0,buf,128); 560 printf("\n"); 561 } 562 563 if (g_prntstyl==PRNTSTYL_VERBOSE || 564 g_prntstyl==PRNTSTYL_LIST) { 565 display_list_tcb(tvp,aux); 566 } 567 568 if (g_prntstyl==PRNTSTYL_VERBOSE || 569 g_prntstyl==PRNTSTYL_COMP) { 570 display_tcb_compressed(tvp,aux); 571 } 572 573 } 574 575 void 576 parse_n_display_tcb(unsigned char *buf) 577 { 578 _TCBVAR *tvp=g_tcb_info; 579 int aux; 580 581 aux=parse_tcb(tvp,buf); 582 display_tcb(tvp,buf,aux); 583 } 584 585 void 586 parse_n_display_scb(unsigned char *buf) 587 { 588 _TCBVAR *tvp=g_scb_info; 589 590 parse_scb(tvp,buf); 591 if (g_prntstyl==PRNTSTYL_VERBOSE || 592 g_prntstyl==PRNTSTYL_RAW) { 593 tcb_hexdump(0,buf,128); 594 printf("\n"); 595 } 596 if (g_prntstyl==PRNTSTYL_VERBOSE || 597 g_prntstyl==PRNTSTYL_LIST || 598 g_prntstyl==PRNTSTYL_COMP) { 599 display_list_tcb(tvp,0); 600 } 601 } 602 603 void 604 parse_n_display_fcb(unsigned char *buf) 605 { 606 _TCBVAR *tvp=g_fcb_info; 607 608 parse_fcb(tvp,buf); 609 if (g_prntstyl==PRNTSTYL_VERBOSE || 610 g_prntstyl==PRNTSTYL_RAW) { 611 tcb_hexdump(0,buf,128); 612 printf("\n"); 613 } 614 615 if (g_prntstyl==PRNTSTYL_VERBOSE || 616 g_prntstyl==PRNTSTYL_LIST || 617 g_prntstyl==PRNTSTYL_COMP) { 618 display_list_tcb(tvp,0); 619 } 620 } 621 622 void 623 parse_n_display_xcb(unsigned char *buf) 624 { 625 if (g_got_scb) parse_n_display_scb(buf); 626 else if (g_got_fcb) parse_n_display_fcb(buf); 627 else parse_n_display_tcb(buf); 628 } 629 630 /***:----------------------------------------------------------------------- 631 ***: swizzle_tcb 632 ***:----------------------------------------------------------------------- 633 */ 634 635 void 636 swizzle_tcb(unsigned char *buf) 637 { 638 int i,j,k; 639 640 for (i=0, j=128-16 ; i<j ; i+=16, j-=16) { 641 unsigned char temp; 642 for (k=0; k<16; ++k) { 643 temp=buf[i+k]; 644 buf[i+k]=buf[j+k]; 645 buf[j+k]=temp; 646 } 647 } 648 } 649 650 651 /***:----------------------------------------------------------------------- 652 ***: END OF WINDOWS FUNCTIONS 653 ***:----------------------------------------------------------------------- 654 */ 655 656 void set_tidtype(unsigned int tidtype) 657 { 658 if (tidtype == TIDTYPE_SCB) 659 { 660 g_got_scb = 1; 661 } 662 else if (tidtype == TIDTYPE_FCB) 663 { 664 g_got_fcb = 1; 665 } 666 else 667 { 668 g_got_scb = 0; 669 g_got_fcb = 0; 670 } 671 672 } 673 674 void 675 set_tcb_info(unsigned int tidtype, unsigned int cardtype) 676 { 677 set_tidtype(tidtype); 678 679 g_tN = cardtype; 680 if (4 == g_tN) { 681 g_tcb_info = g_tcb_info4; 682 g_scb_info = g_scb_info4; 683 g_fcb_info = g_fcb_info4; 684 } 685 else if (5 == g_tN) { 686 g_tcb_info = g_tcb_info5; 687 g_scb_info = g_scb_info5; 688 g_fcb_info = g_fcb_info5; 689 } 690 else if (6 == g_tN) { 691 g_tcb_info = g_tcb_info6; 692 g_scb_info = g_scb_info6; 693 g_fcb_info = g_fcb_info6; 694 } 695 } 696 697 void 698 set_print_style(unsigned int prntstyl) 699 { 700 g_prntstyl=prntstyl; 701 } 702