1 /* tofasta.h 2 * =========================================================================== 3 * 4 * PUBLIC DOMAIN NOTICE 5 * National Center for Biotechnology Information 6 * 7 * This software/database is a "United States Government Work" under the 8 * terms of the United States Copyright Act. It was written as part of 9 * the author's official duties as a United States Government employee and 10 * thus cannot be copyrighted. This software/database is freely available 11 * to the public for use. The National Library of Medicine and the U.S. 12 * Government have not placed any restriction on its use or reproduction. 13 * 14 * Although all reasonable efforts have been taken to ensure the accuracy 15 * and reliability of the software and data, the NLM and the U.S. 16 * Government do not and cannot warrant the performance or results that 17 * may be obtained by using this software or data. The NLM and the U.S. 18 * Government disclaim all warranties, express or implied, including 19 * warranties of performance, merchantability or fitness for any particular 20 * purpose. 21 * 22 * Please cite the author in any work or product based on this material. 23 * 24 * =========================================================================== 25 * 26 * File Name: tofasta.h 27 * 28 * Author: James Ostell 29 * 30 * Version Creation Date: 7/12/91 31 * 32 * $Revision: 6.48 $ 33 * 34 * File Description: various sequence objects to fasta output 35 * 36 * Modifications: 37 * -------------------------------------------------------------------------- 38 * Date Name Description of modification 39 * ------- ---------- ----------------------------------------------------- 40 * 41 * ========================================================================== 42 */ 43 44 #ifndef _NCBI_Tofasta_ 45 #define _NCBI_Tofasta_ 46 47 #include <seqport.h> 48 49 #undef NLM_EXTERN 50 #ifdef NLM_IMPORT 51 #define NLM_EXTERN NLM_IMPORT 52 #else 53 #define NLM_EXTERN extern 54 #endif 55 56 #ifdef __cplusplus 57 extern "C" { 58 #endif 59 60 /* keys returned by FastaWriteFunc */ 61 62 #define FASTA_ID ((Int2)1) /* the SeqId string */ 63 #define FASTA_DEFLINE ((Int2)2) /* the definition line */ 64 #define FASTA_SEQLINE ((Int2)3) /* a line of sequence */ 65 #define FASTA_EOS ((Int2)4) /* all the sequence has been printed */ 66 #define FASTA_FORMATDB_AMB ((Int2)5) /* make conversion to standard form for nucleotides */ 67 68 typedef Boolean (* FastaWriteFunc) PROTO ((BioseqPtr bsp, Int2 key, 69 CharPtr buf, Uint4 buflen, Pointer data)); 70 71 typedef struct iteminfo { /* struct used for defline */ 72 Uint2 entityID, 73 itemtype; 74 Uint4 itemID; 75 } ItemInfo, PNTR ItemInfoPtr; 76 77 typedef struct descrinfo { /* struct used for defline */ 78 BioseqPtr bsp; 79 ValNodePtr vnp; 80 ItemInfoPtr iip; 81 Uint1 choice; 82 } DescrInfo, PNTR DescrInfoPtr; 83 84 typedef struct myfsa { /* struct used for fasta searches */ 85 CharPtr buf; /* buffer for strings (suggest 255 minimum) */ 86 Uint4 buflen, /* length of buf */ 87 seqlen; /* length of sequence lines (must be buflen-1 or less) */ 88 Pointer mydata; /* pointer to your own data */ 89 FastaWriteFunc myfunc; /* callback to process parts of fasta file */ 90 BioseqPtr bsp; /* Bioseq being processed */ 91 Boolean bad_asn1; /* set if error in input object like mol not set */ 92 CharPtr accession; /* used internally for GenPept def lines */ 93 CharPtr organism; /* used internally for GenPept/PRF def lines */ 94 Uint1 order; /* used to order def lines for BLAST */ 95 Boolean do_virtual; /* if TRUE, instantiate virtual sequences */ 96 Uint1 tech; /* for MolInfo.tech */ 97 Boolean no_sequence; /* used to disable sequence printing */ 98 Uint1 code; /* coding of sequence */ 99 Boolean formatdb; /* TRUE, if is used in formatdb */ 100 Boolean printid_general; /* show gi and gnl for SeqId */ 101 SeqLocPtr seqloc; /* sub-sequence of interest */ 102 } MyFsa, PNTR MyFsaPtr; 103 104 typedef struct tofasta { 105 Boolean is_na; 106 Boolean got_one; 107 MyFsaPtr mfp; 108 Uint1 group_segs; 109 Int2 last_indent, 110 parts, seg; 111 } FastaDat, PNTR FastaPtr; 112 113 114 NLM_EXTERN Boolean BioseqRawToFastaExtra PROTO((BioseqPtr bsp, FILE *fp, Int2 line_length)); 115 NLM_EXTERN Boolean BioseqRawToFastaExtraEx PROTO((BioseqPtr bsp, FILE *fp, Int2 line_length, SeqLocPtr slp)); 116 NLM_EXTERN Boolean BioseqRawToFasta PROTO((BioseqPtr bsp, FILE * fp, Boolean is_na)); 117 NLM_EXTERN Boolean SeqEntryToFasta PROTO((SeqEntryPtr sep, FILE * fp, Boolean is_na)); 118 NLM_EXTERN Boolean SeqEntryToFastaEx PROTO((SeqEntryPtr sep, FILE * fp, Boolean is_na, Boolean printid_general)); 119 NLM_EXTERN Boolean BioseqToFasta PROTO((BioseqPtr bsp, FILE *fp, Boolean is_na)); 120 NLM_EXTERN Boolean BioseqToFastaDump PROTO((BioseqPtr bsp, FILE *fp, Boolean is_na)); 121 122 123 124 NLM_EXTERN void SeqEntryFasta PROTO ((SeqEntryPtr sep, Pointer data, 125 Int4 index, Int2 indent)); 126 127 128 /***************************************************************************** 129 * 130 * SeqEntrysToFasta(sep, fp, is_na, group_segs) 131 * 132 * group_segs = 0 ... take only raw Bioseqs 133 * group_segs = 1 ... group segmented seqs into single entry.. no parts 134 * group_segs = 2 ... show only parts of segmented seqs 135 * group_segs = 3 ... like 1, but also instantiate virtual sequences 136 * 137 *****************************************************************************/ 138 NLM_EXTERN Boolean SeqEntrysToFasta PROTO((SeqEntryPtr sep, FILE *fp, Boolean is_na, Uint1 group_segs)); 139 140 NLM_EXTERN Boolean SeqEntrysToFastaX PROTO((SeqEntryPtr sep, MyFsaPtr mfp, Boolean is_na, Uint1 group_segs)); 141 NLM_EXTERN Boolean SeqEntrysToDefline PROTO((SeqEntryPtr sep, 142 FILE *fp, Boolean is_na, Uint1 group_segs)); 143 NLM_EXTERN Boolean BioseqRawToFastaX PROTO((BioseqPtr bsp, MyFsaPtr mfp, Boolean is_na)); 144 NLM_EXTERN Boolean BioseqToFastaX PROTO((BioseqPtr bsp, MyFsaPtr mfp, Boolean is_na)); 145 146 /***************************************************************************** 147 * 148 * BioseqFastaStream (bsp, fp, flags, linelen, blocklen, grouplen, do_defline) 149 * BioseqFastaMemStream (bsp, bs, flags, linelen, blocklen, grouplen, do_defline) 150 * SeqLocFastaStream (slp, fp, flags, linelen, blocklen, grouplen) 151 * SeqLitFastaStream (lit, fp, flags, linelen, blocklen, grouplen) 152 * CdRegionFastaStream (sfp, fp, flags, linelen, blocklen, grouplen) 153 * TranslationFastaStream (sfp, fp, flags, linelen, blocklen, grouplen) 154 * GeneFastaStream (sfp, fp, flags, linelen, blocklen, grouplen) 155 * SeqEntryFastaStream (sep, fp, flags, linelen, blocklen, grouplen, 156 * do_na, do_aa, master_style) 157 * 158 * Rapid FASTA generators using SeqPortStream 159 * 160 *****************************************************************************/ 161 NLM_EXTERN Int4 BioseqFastaStream ( 162 BioseqPtr bsp, 163 FILE *fp, 164 StreamFlgType flags, 165 Int2 linelen, 166 Int2 blocklen, 167 Int2 grouplen, 168 Boolean do_defline 169 ); 170 171 NLM_EXTERN Int4 BioseqFastaStreamEx ( 172 BioseqPtr bsp, 173 FILE *fp, 174 StreamFlgType flags, 175 Int2 linelen, 176 Int2 blocklen, 177 Int2 grouplen, 178 Boolean do_defline, 179 Boolean substitute_ids, 180 Boolean sorted_protein 181 ); 182 183 NLM_EXTERN Int4 BioseqFastaMemStream ( 184 BioseqPtr bsp, 185 ByteStorePtr bs, 186 StreamFlgType flags, 187 Int2 linelen, 188 Int2 blocklen, 189 Int2 grouplen, 190 Boolean do_defline 191 ); 192 193 NLM_EXTERN Int4 SeqLocFastaStream ( 194 SeqLocPtr slp, 195 FILE *fp, 196 StreamFlgType flags, 197 Int2 linelen, 198 Int2 blocklen, 199 Int2 grouplen 200 ); 201 202 NLM_EXTERN Int4 SeqLitFastaStream ( 203 SeqLitPtr lit, 204 FILE *fp, 205 StreamFlgType flags, 206 Int2 linelen, 207 Int2 blocklen, 208 Int2 grouplen 209 ); 210 211 NLM_EXTERN Int4 CdRegionFastaStream ( 212 SeqFeatPtr sfp, 213 FILE *fp, 214 StreamFlgType flags, 215 Int2 linelen, 216 Int2 blocklen, 217 Int2 grouplen, 218 Boolean do_defline, 219 CharPtr idSuffix 220 ); 221 222 NLM_EXTERN Int4 CdRegionFastaStreamEx ( 223 SeqFeatPtr sfp, 224 FILE *fp, 225 StreamFlgType flags, 226 Int2 linelen, 227 Int2 blocklen, 228 Int2 grouplen, 229 Boolean do_defline, 230 CharPtr idSuffix, 231 SeqLocPtr mappedloc, 232 BioseqPtr parentbsp 233 ); 234 235 NLM_EXTERN Int4 TranslationFastaStream ( 236 SeqFeatPtr sfp, 237 FILE *fp, 238 StreamFlgType flags, 239 Int2 linelen, 240 Int2 blocklen, 241 Int2 grouplen, 242 Boolean do_defline, 243 CharPtr idSuffix 244 ); 245 246 NLM_EXTERN Int4 TranslationFastaStreamEx ( 247 SeqFeatPtr sfp, 248 FILE *fp, 249 StreamFlgType flags, 250 Int2 linelen, 251 Int2 blocklen, 252 Int2 grouplen, 253 Boolean do_defline, 254 CharPtr idSuffix, 255 SeqLocPtr mappedloc, 256 BioseqPtr parentbsp 257 ); 258 259 NLM_EXTERN Int4 GeneFastaStream ( 260 SeqFeatPtr sfp, 261 FILE *fp, 262 StreamFlgType flags, 263 Int2 linelen, 264 Int2 blocklen, 265 Int2 grouplen, 266 Boolean do_defline, 267 CharPtr idSuffix 268 ); 269 270 NLM_EXTERN Int4 GeneFastaStreamEx ( 271 SeqFeatPtr sfp, 272 FILE *fp, 273 StreamFlgType flags, 274 Int2 linelen, 275 Int2 blocklen, 276 Int2 grouplen, 277 Boolean do_defline, 278 CharPtr idSuffix, 279 SeqLocPtr mappedloc, 280 BioseqPtr parentbsp 281 ); 282 283 NLM_EXTERN Int4 SeqEntryFastaStream ( 284 SeqEntryPtr sep, 285 FILE *fp, 286 StreamFlgType flags, 287 Int2 linelen, 288 Int2 blocklen, 289 Int2 grouplen, 290 Boolean do_na, 291 Boolean do_aa, 292 Boolean master_style 293 ); 294 295 NLM_EXTERN Int4 SeqEntryFastaStreamEx ( 296 SeqEntryPtr sep, 297 FILE *fp, 298 StreamFlgType flags, 299 Int2 linelen, 300 Int2 blocklen, 301 Int2 grouplen, 302 Boolean do_na, 303 Boolean do_aa, 304 Boolean master_style, 305 Boolean substitute_ids, 306 Boolean sorted_prot 307 ); 308 309 NLM_EXTERN void MakeFastaStreamIdSuffix ( 310 SeqFeatPtr sfp, 311 Uint4 idx, 312 CharPtr prefix, 313 CharPtr buf, 314 Boolean do_product, 315 Boolean do_feat_id 316 ); 317 318 /***************************************************************************** 319 * 320 * FastaFileFunc(key, buf, data) 321 * standard "write to file" callback 322 * 323 *****************************************************************************/ 324 NLM_EXTERN Boolean FastaFileFunc PROTO((BioseqPtr bsp, Int2 key, 325 CharPtr buf, Uint4 buflen, Pointer data)); 326 327 328 /***************************************************************************** 329 * 330 * FastaDumpFileFunc(key, buf, data) 331 * standard "write to file" callback 332 * 333 * Used for BLAST (FASTA) databases. If the defline is 334 * longer than buflen, then check that an ID is not 335 * truncated in the middle. 336 * 337 *****************************************************************************/ 338 NLM_EXTERN Boolean FastaDumpFileFunc PROTO((BioseqPtr bsp, Int2 key, CharPtr buf, Uint4 buflen, Pointer data)); 339 340 /***************************************************************************** 341 * 342 * Reads a Fasta File into a SeqEntry structure 343 * Conventions: 344 * >name def 345 * agaggagagagagag 346 * agagagagagagagag 347 * 348 * "name" = string is considered SEQID_LOCAL until first white space 349 * "def" = after first white space, and before first newline will be "title" 350 * "agaga.." = sequence follows until EOF. can be upper or lower case IUPAC 351 * 352 *****************************************************************************/ 353 NLM_EXTERN SeqEntryPtr FastaToSeqEntry PROTO((FILE *fp, Boolean is_na)); 354 355 /***************************************************************************** 356 * 357 * Reads a Fasta Buffer into a SeqEntry structure 358 * Conventions: 359 * >name def 360 * agaggagagagagag 361 * agagagagagagagag 362 * 363 * "name" = string is considered SEQID_LOCAL until first white space 364 * "def" = after first white space, and before first newline will be "title" 365 * "agaga.." = sequence follows until EOF. can be upper or lower case IUPAC 366 * 367 *****************************************************************************/ 368 NLM_EXTERN SeqEntryPtr FastaToSeqBuff PROTO((CharPtr buffer, 369 CharPtr PNTR last_char,Boolean is_na)); 370 371 NLM_EXTERN SeqEntryPtr FastaToSeqBuffEx(CharPtr buffer, CharPtr PNTR last_char, 372 Boolean is_na, CharPtr PNTR errormsg, 373 Boolean parseSeqId); 374 NLM_EXTERN SeqEntryPtr FastaToSeqBuffForDb(CharPtr buffer, CharPtr PNTR last_char, 375 Boolean is_na, CharPtr PNTR errormsg, 376 Boolean parseSeqId, CharPtr prefix, Int2Ptr ctrptr, 377 SeqLocPtr PNTR mask_ptr); 378 NLM_EXTERN SeqEntryPtr FastaToSeqEntryEx (FILE *fp, Boolean is_na, 379 CharPtr PNTR errormsg, 380 Boolean parseSeqId); 381 NLM_EXTERN SeqEntryPtr FastaToSeqEntryForDb ( FILE *fp, Boolean is_na, 382 CharPtr PNTR errormsg, 383 Boolean parseSeqId, 384 CharPtr prefix, Int2Ptr ctrptr, 385 SeqLocPtr PNTR mask_ptr); 386 387 /********* DEFINES for input type *********/ 388 389 #define FASTA_MEM_IO 1 /* type of reading from buffer in memory */ 390 #define FASTA_FILE_IO 2 /* type of reading from file */ 391 392 NLM_EXTERN SeqEntryPtr FastaToSeqEntryInternalEx ( VoidPtr input, 393 Int4 type, CharPtr PNTR next_char, 394 Boolean is_na, CharPtr PNTR errormsg, 395 Boolean parseSeqId, CharPtr special_symbol, 396 CharPtr prefix, Int2Ptr ctrptr, 397 SeqLocPtr PNTR mask_ptr); 398 399 /***************************************************************************** 400 * 401 * Boolean FastaReadSequence() - read sequence from file 402 * 403 *****************************************************************************/ 404 405 Boolean FastaReadSequence 406 ( 407 FILE *fd, /* input file pointer) */ 408 Boolean is_na, /* type of sequence */ 409 Int4Ptr seq_length, /* Returned length of sequence in residues */ 410 ByteStorePtr PNTR bs_out, /* Returned pointer to sequence ByteStore */ 411 CharPtr PNTR errormsg /* error message for debugging */ 412 ); 413 414 /***************************************************************************** 415 * 416 * Boolean FastaReadSequenceMem() - read sequence from buffer 417 * 418 *****************************************************************************/ 419 420 Boolean FastaReadSequenceMem 421 ( 422 CharPtr buffer, /* input buffer with sequence */ 423 CharPtr PNTR next_char, /* returned pointer to next FASTA sequence */ 424 Boolean is_na, /* type of sequence */ 425 Int4Ptr seq_length, /* Returned length of sequence in residues */ 426 ByteStorePtr PNTR bs_out, /* Returned pointer to sequence ByteStore */ 427 CharPtr PNTR errormsg /* error message for debugging */ 428 ); 429 430 /***************************************************************************** 431 * 432 * This routines get parts needed to make FASTA format from ASN.1 433 * 434 *****************************************************************************/ 435 /***************************************************************************** 436 * 437 * FastaId(bsp, buf, buflen) 438 * Makes the string for the id part of fasta format. 439 * buf should be at least 40 bytes 440 * 441 *****************************************************************************/ 442 NLM_EXTERN Boolean FastaId PROTO((BioseqPtr bsp, CharPtr buf, Uint4 buflen)); 443 444 NLM_EXTERN CharPtr FastaGetOriginalId PROTO((BioseqPtr bsp)); 445 NLM_EXTERN Boolean ShouldUseOriginalID PROTO((BioseqPtr bsp)); 446 NLM_EXTERN Boolean FastaIdEx PROTO((BioseqPtr bsp, CharPtr buf, Uint4 buflen, Boolean prefer_original_ID)); 447 448 /***************************************************************************** 449 * 450 * FastaDefLine(bsp, buf, buflen, accession, organism) 451 * Finds or makes a FASTA format defline (just locates the string) 452 * buf should be very long if possible 453 * function truncates if buf not long enough 454 * a few deflines are longer than 255 455 * if (accession != NULL) prefixes defline with (accession) 456 * used for translated GenBank records 457 * if (organism != NULL) adds [organism] to end 458 * if (tech == MI_TECH_phase1 or phase2, adds order comment to defline) 459 * 460 *****************************************************************************/ 461 NLM_EXTERN Boolean FastaDefLine PROTO((BioseqPtr bsp, CharPtr buf, Uint4 buflen, CharPtr accession, CharPtr organism, Uint1 tech)); 462 463 NLM_EXTERN Boolean CreateDefLine PROTO((ItemInfoPtr dip, BioseqPtr bsp, CharPtr buf, Uint4 buflen, 464 Uint1 tech, CharPtr accession, CharPtr organism)); 465 NLM_EXTERN Boolean CreateDefLineEx (ItemInfoPtr iip, BioseqPtr bsp, CharPtr buf, Uint4 buflen, Uint1 tech, 466 CharPtr accession, CharPtr organism, Boolean ignoreTitle); 467 NLM_EXTERN Boolean CreateDefLineExEx (ItemInfoPtr iip, BioseqPtr bsp, CharPtr buf, Uint4 buflen, Uint1 tech, 468 CharPtr accession, CharPtr organism, Boolean ignoreTitle, Boolean extProtTitle); 469 470 /***************************************************************************** 471 * 472 * NewCreateDefLine and NewCreateDefLineBuf replace the CreateDefLine family 473 * 474 *****************************************************************************/ 475 476 NLM_EXTERN CharPtr NewCreateDefLineExEx ( 477 ItemInfoPtr iip, 478 BioseqPtr bsp, 479 Boolean ignoreTitle, 480 Boolean extProtTitle, 481 Boolean gpipeMode, 482 Boolean devMode 483 ); 484 485 NLM_EXTERN CharPtr NewCreateDefLineEx ( 486 ItemInfoPtr iip, 487 BioseqPtr bsp, 488 Boolean ignoreTitle, 489 Boolean extProtTitle, 490 Boolean gpipeMode 491 ); 492 493 NLM_EXTERN CharPtr NewCreateDefLine ( 494 ItemInfoPtr iip, 495 BioseqPtr bsp, 496 Boolean ignoreTitle, 497 Boolean extProtTitle 498 ); 499 500 NLM_EXTERN Boolean NewCreateDefLineBuf ( 501 ItemInfoPtr iip, 502 BioseqPtr bsp, 503 CharPtr buf, 504 Uint4 buflen, 505 Boolean ignoreTitle, 506 Boolean extProtTitle 507 ); 508 509 /***************************************************************************** 510 * 511 * FastaSeqPort(bsp, is_na, do_virtual) 512 * opens a SeqPort for a fasta output of bsp 513 * 514 *****************************************************************************/ 515 NLM_EXTERN SeqPortPtr FastaSeqPort PROTO((BioseqPtr bsp, Boolean is_na, 516 Boolean do_virtual, Uint1 code)); 517 NLM_EXTERN SeqPortPtr FastaSeqPortEx PROTO((BioseqPtr bsp, Boolean is_na, 518 Boolean do_virtual, Uint1 code, SeqLocPtr slp)); 519 520 /***************************************************************************** 521 * 522 * FastaSeqLine(spp, buf, linelen) 523 * an open seqport is passed in. 524 * fills buf with linelen bases 525 * assumes buf[linelen] = '\0' 526 * returns FALSE when no more residues to print 527 * here for backward compatibility. Is the same as calling 528 * FastaSeqLineEx() with do_virtual = FALSE; 529 * 530 *****************************************************************************/ 531 NLM_EXTERN Boolean FastaSeqLine PROTO((SeqPortPtr spp, CharPtr buf, Int2 linelen, Boolean is_na)); 532 533 /**************************************************************************** 534 * 535 * FastaSeqLineEx(spp, buf, linelen, is_na, do_virtual) 536 * 537 * adds a parameter to indicate if virtual sequences should be shown 538 * this is necessary in order to avoid showing SEQPORT_VIRT return 539 * (gap of 0 length) as '-', when do_virtual is TRUE. 540 * 541 *****************************************************************************/ 542 NLM_EXTERN Boolean FastaSeqLineEx(SeqPortPtr spp, CharPtr buf, Int2 linelen, Boolean is_na, Boolean 543 do_virtual); 544 545 Int4 GetOrderBySeqId(Int4 choice, Boolean is_prot); 546 547 /***************************************************************************** 548 * 549 * NC_Cleanup (entityID, ptr) and ClearGenBankKeywords (entityID, ptr) 550 * internal functions for genome RefSeq processing 551 * 552 *****************************************************************************/ 553 NLM_EXTERN void NC_Cleanup (Uint2 entityID, Pointer ptr); 554 NLM_EXTERN void ClearGenBankKeywords (Uint2 entityID, Pointer ptr); 555 556 /***************************************************************************** 557 * 558 * InstantiateNCTitle (entityID, ptr) and InstantiateNMTitles (entityID, ptr) 559 * allows NC and NM titles to be kept as Seq_descr_title rather than always 560 * being generated on the fly 561 * 562 *****************************************************************************/ 563 NLM_EXTERN void InstantiateNCTitle (Uint2 entityID, Pointer ptr); 564 NLM_EXTERN void InstantiateNMTitles (Uint2 entityID, Pointer ptr); 565 566 /***************************************************************************** 567 * 568 * InstantiateProteinTitles (entityID, ptr) and ClearProteinTitles (entityID, ptr) 569 * allows proteins titles to be kept as Seq_descr_title rather than always 570 * being generated on the fly 571 * 572 *****************************************************************************/ 573 NLM_EXTERN void InstantiateProteinTitles (Uint2 entityID, Pointer ptr); 574 NLM_EXTERN void UpdateProteinTitle (BioseqPtr bsp); 575 NLM_EXTERN void ClearProteinTitlesInNucProts (Uint2 entityID, Pointer ptr); 576 577 NLM_EXTERN CharPtr MakeCompleteChromTitle (BioseqPtr bsp, Uint1 biomol, Uint1 completeness); 578 579 580 #ifdef __cplusplus 581 } 582 #endif 583 584 #undef NLM_EXTERN 585 #ifdef NLM_EXPORT 586 #define NLM_EXTERN NLM_EXPORT 587 #else 588 #define NLM_EXTERN 589 #endif 590 591 #endif 592