1 /* $Id: maputil.h,v 6.9 2006/07/13 17:06:38 bollin Exp $ 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: $RCSfile: maputil.h,v $ 27 * 28 * Author: Jinghui Zhang 29 * 30 * Initial Version Creation Date: 03/21/97 31 * 32 * $Revision: 6.9 $ 33 * 34 * File Description: 35 * External include file for graphical alignments 36 * 37 * $Log: maputil.h,v $ 38 * Revision 6.9 2006/07/13 17:06:38 bollin 39 * use Uint4 instead of Uint2 for itemID values 40 * removed unused variables 41 * resolved compiler warnings 42 * 43 * Revision 6.8 2001/06/26 16:42:59 vakatov 44 * POINT --> BAND_POINT (to avoid conflicts with MS-Win standard headers) 45 * 46 * Revision 6.7 1998/07/22 00:02:37 zjing 47 * move SortValNode from maputil to jzmisc 48 * 49 * Revision 6.6 1997/11/14 22:13:41 vakatov 50 * [WIN32,DLL] Added NLM_EXTERN's 51 * 52 * Revision 6.5 1997/10/15 19:56:42 zjing 53 * change get_align_annot_qual parameter 54 * 55 * Revision 6.4 1997/10/10 18:32:42 zjing 56 * add support to collect OBJ_BIOSEQ_DELTA and functions to improve the alignment overview 57 * 58 * Revision 6.3 1997/10/06 14:42:39 zjing 59 * functions for the overview of blast search results 60 * 61 * Revision 6.0 1997/08/25 18:06:37 madden 62 * Revision changed to 6.0 63 * 64 * Revision 5.9 1997/07/23 13:45:29 zjing 65 * look up for the sequence index map 66 * 67 * $Revision: 6.9 $ 68 * 69 * File Description: 70 * External include file for graphical alignments 71 * 72 * $Log: maputil.h,v $ 73 * Revision 6.9 2006/07/13 17:06:38 bollin 74 * use Uint4 instead of Uint2 for itemID values 75 * removed unused variables 76 * resolved compiler warnings 77 * 78 * Revision 6.8 2001/06/26 16:42:59 vakatov 79 * POINT --> BAND_POINT (to avoid conflicts with MS-Win standard headers) 80 * 81 * Revision 6.7 1998/07/22 00:02:37 zjing 82 * move SortValNode from maputil to jzmisc 83 * 84 * Revision 6.6 1997/11/14 22:13:41 vakatov 85 * [WIN32,DLL] Added NLM_EXTERN's 86 * 87 * Revision 6.5 1997/10/15 19:56:42 zjing 88 * change get_align_annot_qual parameter 89 * 90 * Revision 6.4 1997/10/10 18:32:42 zjing 91 * add support to collect OBJ_BIOSEQ_DELTA and functions to improve the alignment overview 92 * 93 * Revision 6.3 1997/10/06 14:42:39 zjing 94 * functions for the overview of blast search results 95 * 96 * Revision 5.8 1997/06/19 18:38:23 vakatov 97 * [WIN32,MSVC++] Adopted for the "NCBIOBJ.LIB" DLL'ization 98 * 99 * Revision 5.7 1997/03/21 19:47:16 shavirin 100 * Added NCBI header started logging and added protection for usage 101 * it with C++ compiler 102 * 103 * 104 * ========================================================================== 105 */ 106 #ifndef _MAPUTIL_ 107 #define _MAPUTIL_ 108 109 /****************************************************************************/ 110 /* INCLUDES */ 111 /****************************************************************************/ 112 113 #include <ncbi.h> 114 #include <objfeat.h> 115 #include <objseq.h> 116 #include <objloc.h> 117 #include <objalign.h> 118 #include <sequtil.h> 119 #include <objfdef.h> 120 #include <lsqfetch.h> 121 #include <objmgr.h> 122 #include <gather.h> 123 124 /*local include file*/ 125 #include <jzmisc.h> 126 127 /****************************************************************************/ 128 /* TYPEDEFS */ 129 /****************************************************************************/ 130 typedef struct genedata{ 131 CharPtr symbol; 132 Boolean landmark; /*is it a landmark gene?*/ 133 Uint2 entityID; 134 Uint4 itemID; 135 Uint2 itemType; 136 Uint2 subtype; 137 Uint2 priority; 138 Int4 x, y; /*the x, y coordinates on the picture*/ 139 SeqLocPtr location; 140 SeqFeatPtr sfp; 141 ValNodePtr align_seg; 142 struct genedata PNTR next; 143 }GeneData, PNTR GeneDataPtr; 144 145 typedef ValNodePtr EnzPtr; 146 147 typedef struct enzdata{ 148 CharPtr name; 149 CharPtr pattern; 150 Uint1 cut_pos; 151 }EnzData, PNTR EnzDataPtr; 152 153 typedef struct musksep{ /*Seq-entries from musk*/ 154 SeqEntryPtr sep; 155 Boolean is_bin; /*is it loaded from a binary file?*/ 156 Char file_name[100]; /*the name for the ASN.1 Seq-entry file*/ 157 Pointer dataptr; 158 Uint2 datatype; 159 } MuskSep, PNTR MuskSepPtr; 160 161 /****************************************************************************/ 162 /* FINCTION DEFINITIONS */ 163 /****************************************************************************/ 164 165 #undef NLM_EXTERN 166 #ifdef NLM_IMPORT 167 #define NLM_EXTERN NLM_IMPORT 168 #else 169 #define NLM_EXTERN extern 170 #endif 171 172 #ifdef __cplusplus 173 extern "C" { 174 #endif 175 176 NLM_EXTERN Int2 get_seg_num PROTO((SeqLocPtr slp)); 177 178 NLM_EXTERN Int2 get_seglevels PROTO((BioseqPtr bsp)); 179 180 NLM_EXTERN Int4Ptr get_priority_order PROTO((SeqEntryPtr sep, Int4Ptr num)); 181 182 /**************************************************************** 183 * 184 * LoadLandMarkGene(sep) 185 * get the landmark gene from the User-object in the descriptor 186 * all the genes are linked to a ValNode and vnp->choice is set 187 * to 1 to indicate it is a landmark gene 188 * 189 ******************************************************************/ 190 NLM_EXTERN ValNodePtr LoadLandMarkGene PROTO((SeqEntryPtr sep)); 191 192 /***************************************************************** 193 * 194 * if sfp is a Gene-ref and contains the gene in g_list, 195 * return the string in g_list 196 * else return NULL 197 * 198 *****************************************************************/ 199 NLM_EXTERN Boolean check_landmark PROTO((SeqFeatPtr sfp, CharPtr mark)); 200 201 202 /****************************************************************** 203 * 204 * load_gdata_marks(slp, gene_list, seglevels, sep, gdp) 205 * Gather the current Seq-entry to create the corresponding list of 206 * GeneDataPtr for the list of gene symbols 207 * slp: the target Seq-local. can be set to NULL 208 * gene_list: a list of query symbols 209 * seglevels: levels of gather 210 * sep: the Seq-entry 211 * gdp: the header of GeneDataPtr 212 * 213 ********************************************************************/ 214 NLM_EXTERN Boolean load_gdata_marks PROTO((SeqLocPtr slp, 215 ValNodePtr gene_list, 216 Int2 seglevels, 217 SeqEntryPtr sep, 218 GeneDataPtr PNTR pgdp)); 219 220 NLM_EXTERN GeneDataPtr LinkGeneData PROTO((GeneDataPtr PNTR head, GeneDataPtr newgdp)); 221 222 NLM_EXTERN GeneDataPtr GeneDataFree PROTO((GeneDataPtr head)); 223 224 NLM_EXTERN GeneDataPtr make_gene_data PROTO((ValNodePtr gene_list)); 225 226 NLM_EXTERN void RefreshGeneData PROTO((GeneDataPtr gdp)); 227 228 /************************************************************************* 229 * 230 * return the best location of the gene from sep. 231 * best is defined as the Bioseq with the highest searching prioirity 232 * e_start, e_stop record the extremes of the all the presence of 233 * the gene 234 * 235 *************************************************************************/ 236 NLM_EXTERN SeqLocPtr get_location_for_query PROTO((SeqEntryPtr sep, 237 CharPtr gene, 238 Int4Ptr e_start, 239 Int4Ptr e_stop)); 240 241 /***************************************************************** 242 * 243 * Build a list of gene symbols to supply the Find Gene option in 244 * the global view 245 * 246 ******************************************************************/ 247 NLM_EXTERN ValNodePtr BuildGeneList PROTO((SeqEntryPtr sep)); 248 249 250 /**************************************************** 251 * 252 * make_enzyme_list(file_name) 253 * build a ValNodeList of EnzDataPtr from teh 254 * input file 255 * 256 ****************************************************/ 257 NLM_EXTERN EnzPtr make_enzyme_list PROTO((CharPtr file_name)); 258 259 /************************************************** 260 * 261 * free_enzyme_list(enp) 262 * Free a list of EnzDataPtr 263 * 264 **************************************************/ 265 NLM_EXTERN EnzPtr free_enzyme_list PROTO((EnzPtr enp)); 266 267 268 /********************************************************************** 269 * 270 * FreeEquivAlign(ealign_list) 271 * Free a list of Seq-annot that is of type Seq-align 272 * mostly, those are the externally loaded Seq-align for showing 273 * the Equiv map 274 * 275 ***********************************************************************/ 276 NLM_EXTERN ValNodePtr FreeEquivAlign PROTO((ValNodePtr ealign_list)); 277 278 /******************************************************************* 279 * 280 * GetEquivAlignType(annot) 281 * annot stores the alignments of markers mapped by more than 282 * one groups. if return 1, the markers are the consistent markers 283 * if return 2, the markers are inconsistent markers 284 * if return 0, the alignment simply records the mapping to 285 * the sequence map 286 * if return -1, unknown status. Will be treated the same as 1 287 * 288 *******************************************************************/ 289 NLM_EXTERN Int2 GetEquivAlignType PROTO((SeqAnnotPtr annot)); 290 291 292 /*********************************************************************** 293 * 294 * FreeMuskSep(sep_list) 295 * Free the manually loaded Seq-entries 296 * sep_list: a list of MuskSepPtr 297 * 298 ***********************************************************************/ 299 NLM_EXTERN ValNodePtr FreeMuskSep PROTO((ValNodePtr sep_list)); 300 301 /*##################################################################### 302 # 303 # functions related to BioseqDraw 304 # 305 # 306 ######################################################################*/ 307 308 /********************************************************************** 309 * 310 * get_Bioseq_type(bsp) 311 * return the subclasses of Bioseq, such as the genetic or physical map 312 * depending on its bsp->repr type and bsp->seq_ext type. 313 * 314 **********************************************************************/ 315 #define PHYSICAL_MAP 1 316 #define GENETIC_MAP 2 317 #define RESTRICTION_MAP 3 318 #define CYTO_MAP 4 319 #define VIRTUAL_SEQ 5 320 #define SEG_SEQ 6 321 #define RAW_SEQ 7 322 NLM_EXTERN Uint1 get_Bioseq_type PROTO((BioseqPtr bsp)); 323 324 325 326 327 /************************************************************************* 328 * 329 * MapLayout is an ORDERED list of MapPos, which contains the layout 330 * for each map. It is used for determine the layout of map alignment 331 * 332 **************************************************************************/ 333 typedef ValNode MapLayout, FAR *MapLayoutPtr; 334 typedef struct mappos{ /*holding the positin of each map*/ 335 SeqLocPtr slp; /*the range of the map on display*/ 336 Int2 entityID; 337 Int4 left, right; /*the left, right position on the graph*/ 338 Int4 top, bottom; /*the top, bottom position on the graph*/ 339 Int4 seq_top, seq_bottom; /*the top, bottom position of the sequence*/ 340 }MapPos, PNTR MapPosPtr; 341 NLM_EXTERN MapLayoutPtr MapLayoutFree PROTO ((MapLayoutPtr head)); 342 343 344 345 346 #define MAX_DIM 100 /*the maximal dimension of a map alignment*/ 347 typedef struct alignpos{ /*the position of each alignment mapped to the graph*/ 348 Int4 left[MAX_DIM]; 349 Int4 right[MAX_DIM]; 350 Int4 top[MAX_DIM]; 351 Int4 bottom[MAX_DIM]; 352 }AlignPos, PNTR AlignPosPtr; 353 /******************************************************************** 354 * 355 * SortAlignPosition(app, dim) 356 * Sort out the order of a multiple alignment in the vertical 357 * display mode. It is sorted to the descending order of 358 * app->top. one app correspond to one aligned segment. It can 359 * be of multiple dimensions 360 * app: alignment position 361 * dim: dimention of alignment 362 * 363 *********************************************************************/ 364 NLM_EXTERN void SortAlignPosition PROTO((AlignPosPtr app, Int2 dim)); 365 366 367 368 /*************************************************************************** 369 * 370 * getBioseqNumbering(bsp) 371 * get the numbering object from Seq_descr. If no numbering, return NULL 372 * 373 ****************************************************************************/ 374 NLM_EXTERN NumberingPtr getBioseqNumbering PROTO ((BioseqPtr bsp)); 375 376 /********************************************************************** 377 * 378 * IS_NUM_GENE(gene_label): kludge function 379 * determine if the gene_label is used as a map unit, such 380 * as the case for C.elegans physical map 381 * 382 **********************************************************************/ 383 NLM_EXTERN Boolean IS_NUM_GENE PROTO ((CharPtr gene_label)); 384 385 /*********************************************************************** 386 * 387 * map_unit_label(): create a label for the map unit 388 * if(np == NULL), use the actual position. use_kb =TRUE converts 389 * to kilobase unit 390 * 391 ***********************************************************************/ 392 NLM_EXTERN Boolean map_unit_label PROTO((Int4 pos, NumberingPtr np, CharPtr label, Boolean use_kb)); 393 394 395 #define HUMAN_CYTO 1 396 #define FLY_CYTO 2 397 /**************************************************************** 398 * 399 * ck_cyto_type() a kludge to determine if the cytogenetic map 400 * follows the band pattern of Fly or that of Human 401 * 402 ****************************************************************/ 403 NLM_EXTERN Uint1 ck_cyto_type PROTO((SeqFeatPtr sfp)); 404 405 406 /*band used for the Flybase*/ 407 #define MISC_BND 0 /*band is unknown*/ 408 409 #define BND 1 /*band*/ 410 #define HET 2 /*heterochromatin*/ 411 #define TEL 3 /*telemere*/ 412 #define CEN 4 /*centromere*/ 413 414 /*band used for Human chromosome*/ 415 #define BAND_POINT 5 /*inclue the centromere and telemere*/ 416 #define GIEMSA_POS 6 /*Giemsa positive*/ 417 #define GIEMSA_NEG 7 /*Giemsa negative*/ 418 #define ACRO_CENTRIC 8 /*Acrocentric*/ 419 #define VARIABLE_REG 9 /*VariableReg*/ 420 /********************************************************************** 421 * 422 * get_band_type(UserObjectPtr) 423 * get the band type in a Cytogenetic map 424 * 425 ***********************************************************************/ 426 NLM_EXTERN Uint1 get_band_type PROTO((UserObjectPtr uop)); 427 428 429 430 /********************************************************************* 431 * 432 * get_band_name(uop) 433 * parse the band name from a cytogenetic map 434 * 435 *********************************************************************/ 436 NLM_EXTERN CharPtr get_band_name PROTO((UserObjectPtr uop)); 437 438 439 /************************************************************************* 440 * 441 * is_label_match(obj_id, label) 442 * return TRUE if obj_id->str matches with label 443 * 444 **************************************************************************/ 445 NLM_EXTERN Boolean is_label_match PROTO((ObjectIdPtr obj_id, CharPtr label)); 446 447 448 449 450 /*********************************************************************** 451 * 452 * a set of default parameters used in drawing and layout of the 453 * sequence picture 454 * 455 ***********************************************************************/ 456 #define LABEL_SPACE 12 /*for layout the mapdata*/ 457 #define TICK_LEN 8 /*length of a tick mark*/ 458 459 #define BAND_WIDTH 6 /*the width of the band of cytogenetic map*/ 460 461 #ifdef WIN_MSWIN 462 #define ENZ_WIDTH 14 /*the width of the enzyme for Windows*/ 463 #else 464 #define ENZ_WIDTH 10 465 #endif 466 467 #define MAP_SPACE 30 /*the space separate the maps*/ 468 #define LINE_SPACE 4 /*the space among clones if drawn as line*/ 469 470 #define SIMPLE_LEN 100000 /*the min length for simple drawing*/ 471 #ifdef WIN_MSWIN 472 #define SEQ_WIDTH 14 /*the width of the enzyme for Windows*/ 473 #else 474 #define SEQ_WIDTH 10 475 #endif 476 477 #define FEAT_WIDTH 5 478 479 NLM_EXTERN ValNodePtr free_slp_list PROTO((ValNodePtr slp_list)); 480 481 NLM_EXTERN ValNodePtr get_equiv_align PROTO((SeqEntryPtr sep)); 482 483 /*check to see if the alignment is designed to be displayed as the history*/ 484 NLM_EXTERN Boolean is_annot_for_hist_alignment PROTO((SeqAnnotPtr annot)); 485 486 487 488 /************************************************************************ 489 * 490 * is_map_segment(slp) 491 * return TRUE if slp is a Seq-loc from a amp 492 * return FALSE if it is not a map or the Bioseq is not loaded to 493 * the memory yet 494 * 495 ************************************************************************/ 496 NLM_EXTERN Boolean is_map_segment PROTO((SeqLocPtr slp)); 497 498 /*************************************************************** 499 * 500 * figure_map_seqid(ext_loc) 501 * a very unreliable way to figure out the if there is a 502 * Seq-id for the map. It is dependent on the frequency of 503 * the Seq-id in a segmented sequence 504 * 505 ****************************************************************/ 506 NLM_EXTERN SeqIdPtr figure_map_seqid PROTO((SeqLocPtr ext_loc)); 507 508 NLM_EXTERN Boolean make_Bioseq_list PROTO((SeqEntryPtr sep, ValNodePtr PNTR bsp_list, ValNodePtr PNTR equiv_align)); 509 510 NLM_EXTERN Boolean start_new_stack PROTO((Int4 pre_pos, Int4 pos, Int4 scale, Int2Ptr label_width, Int2 c_width)); 511 512 NLM_EXTERN Int4 calculate_ruler PROTO((Int4 scaleX)); 513 514 #define GENE_MARK 0 515 #define CDS_MARK 1 516 517 /*********************************************************************** 518 * 519 * for each sequence in alignment stored in Seq-hist, if the aligned 520 * sequence itself contains alignment, it is temporarily loaded as 521 * a user-object in the descriptor of the bioseq. This function extract 522 * the information from the descripor and store it as a list of gi's 523 * plus the kludge offset value 524 * 525 ************************************************************************/ 526 NLM_EXTERN ValNodePtr get_seqids_with_alignment PROTO((BioseqPtr mbsp)); 527 528 /*********************************************************************** 529 * 530 * map the kludge offet factor for Unigene, RICE, MOUSE ,FlyBase, etc 531 * 532 ************************************************************************/ 533 NLM_EXTERN Int4 get_kludge_factor PROTO((SeqIdPtr sip, Int4Ptr gi)); 534 535 NLM_EXTERN Boolean BioseqHasLandMark PROTO((BioseqPtr bsp)); 536 537 538 typedef struct repeat_region{ 539 GatherRange gr; 540 Char rep_name[20]; 541 }RepeatRegion, PNTR RepeatRegionPtr; 542 543 typedef struct align_region{ 544 Char annotDB[21]; 545 Uint1 displayOrder; 546 GatherRange gr; /*extremes for the intervals*/ 547 ValNodePtr intervals; /*the intervals. more than one if there are multiple alignments for the same sequence*/ 548 Char seq_name[20]; 549 FloatHi score; 550 FloatHi p_val; 551 FloatHi e_val; 552 Int4 line; 553 Int4 g_left, g_right, g_top, g_bottom; /*the rectangle that defines the alignment*/ 554 Uint1 status; /*range from 0-4 for the lowest to the highest score*/ 555 }AlignRegion, PNTR AlignRegionPtr; 556 557 /*trying to parse the descriptor in Seq-annot for the alignment display*/ 558 #define ANNOT_BLAST 1 /*it is annotation on the Blast search*/ 559 #define ANNOT_CONSIST 2 /*annotates the consistency between a clone and 560 the genome map. For Eric Green's map*/ 561 #define ANNOT_FISH 3 /*it is the annotation on a FISH map */ 562 NLM_EXTERN Uint1 get_align_annot_qual PROTO((SeqAnnotPtr annot, CharPtr annotDB, Int4 buf_size, Uint1Ptr annot_type)); 563 564 /************************************************************************** 565 * 566 * collect_repeats_and_align(slp, rrp_list, arp_list, seglevels, sep) 567 * 568 * collect repeat features and alignment for global display 569 * rrp_list: the list of the repeat features 570 * arp_list: the list of the alignments 571 * 572 ***************************************************************************/ 573 NLM_EXTERN Boolean collect_repeats_and_align PROTO((SeqLocPtr slp, ValNodePtr PNTR rrp_list, ValNodePtr PNTR arp_list, Int2 seglevels, SeqEntryPtr sep, Uint1Ptr align_has_status)); 574 575 576 /************************************************************** 577 * 578 * get the alignment for the FISH map 579 * for the Human Cytogenetic map, if there is a 580 * Seq-annot stored as Hist-align and the intervals are 581 * aligned to the FISH map, it will return the Seq-align 582 * of the alignment to the FISH map 583 * 584 ***************************************************************/ 585 NLM_EXTERN SeqAlignPtr get_FISH_align PROTO((BioseqPtr bsp)); 586 587 /******************************************************* 588 * 589 * annot_is_user_defined(annot) 590 * 591 * determine if the Seq-annot contains the features 592 * that were defined by the user. This is to 593 * distinguish the local data from the public data 594 * set 595 * 596 ********************************************************/ 597 NLM_EXTERN Boolean annot_is_user_defined PROTO((SeqAnnotPtr annot)); 598 599 600 /************************************************************* 601 * 602 * determine if the Bioseq in the SeqEntry contains 603 * the UserObject for a Map Legend 604 * 605 **************************************************************/ 606 NLM_EXTERN UserObjectPtr BioseqHasMapLegend PROTO((BioseqPtr bsp)); 607 NLM_EXTERN Boolean SeqLocListHasLegend PROTO((ValNodePtr slp_list)); 608 609 NLM_EXTERN Boolean IsSeqIndexMap PROTO((BioseqPtr bsp)); 610 611 #define SEQINDEX_VAL 255 /*used to store as the choice in slp_list*/ 612 613 614 /*functions related to the yac2band and viewctg*/ 615 616 /*the YAC contig maps are either from Whitehead or from Eric Green's group*/ 617 #define YAC_MIT 1 618 #define YAC_NHGRI 2 619 #define GENETIC_GENETHON 4 620 #define GENETIC_CHLC 8 621 /*find a list of the seqlocs on the contig that maps to the 622 *current chromosome. For now, only the Whitehead map and the 623 *Eric Green's map is considered. return a list of Seq-locs that 624 *contains contigs within the region 625 */ 626 NLM_EXTERN Uint1 FindContigDB PROTO((SeqIdPtr sip)); 627 628 /*return a list of Seq-locs which are the contigs mapped to 629 * the current location on the genome 630 * 631 */ 632 NLM_EXTERN ValNodePtr FindContigList PROTO((SeqLocPtr chr_slp)); 633 634 635 NLM_EXTERN Boolean is_lod_score_annot PROTO((SeqAnnotPtr annot)); 636 NLM_EXTERN Int2 GetLODScoreNumber PROTO((BioseqPtr bsp)); 637 NLM_EXTERN CharPtr GetAnnotTitle PROTO((SeqAnnotPtr annot)); 638 NLM_EXTERN Uint1 GetLODScoreBitValue PROTO((SeqFeatPtr sfp)); 639 640 641 #ifdef __cplusplus 642 } 643 #endif 644 645 #undef NLM_EXTERN 646 #ifdef NLM_EXPORT 647 #define NLM_EXTERN NLM_EXPORT 648 #else 649 #define NLM_EXTERN 650 #endif 651 652 #endif 653 654