1 /*  objalign.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:  objalign.h
27 *
28 * Author:  James Ostell
29 *
30 * Version Creation Date: 4/1/91
31 *
32 * $Revision: 6.11 $
33 *
34 * File Description:  Object manager interface for module NCBI-Seqalign
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * Date	   Name        Description of modification
39 * -------  ----------  -----------------------------------------------------
40 *
41 * $Log: objalign.h,v $
42 * Revision 6.11  2008/10/09 18:43:56  kans
43 * splice_5_prime and splice_3_prime changed to acceptor_before_exon and donor_after_exon
44 *
45 * Revision 6.10  2007/05/12 21:03:32  kans
46 * Spliced-seg code recompiled with -Z so product_length 0 is not always written
47 *
48 * Revision 6.9  2007/04/09 20:25:47  kans
49 * added support for sparse alignment type
50 *
51 * Revision 6.8  2006/07/28 16:07:48  kans
52 * added new fields due to spec change
53 *
54 * Revision 6.7  2002/01/10 14:35:18  dondosha
55 * Added GenericSeqAlignSetAsnWrite to allow writing seqalign set without a parent asn type
56 *
57 * Revision 6.6  1999/09/28 12:09:56  kans
58 * added alignID field
59 *
60 * Revision 6.5  1999/09/27 17:48:37  kans
61 * using GatherIndex structure
62 *
63 * Revision 6.4  1999/09/24 23:09:23  kans
64 * adds EXTRA_OBJMGR_FIELDS to several objects
65 *
66 * Revision 6.3  1999/09/07 17:00:26  kans
67 * added entityID, itemID, itemtype fields for new Alignment Indexing functions
68 *
69 * Revision 6.2  1999/07/29 15:49:58  ostell
70 * added pointer and free for a SeqAlignIndex
71 *
72 * Revision 6.1  1999/07/26 20:41:01  ostell
73 * added SAT_ and SAS_ defines, added master to SeqAlign
74 *
75 * Revision 6.0  1997/08/25 18:49:14  madden
76 * Revision changed to 6.0
77 *
78 * Revision 4.1  1997/06/19 18:40:41  vakatov
79 * [WIN32,MSVC++]  Adopted for the "NCBIOBJ.LIB" DLL'ization
80 *
81 * Revision 4.0  1995/07/26 13:48:06  ostell
82 * force revision to 4.0
83 *
84  * Revision 3.5  1995/07/22  21:59:13  ostell
85  * added support for ASN.1 spec 4.0
86  *
87  * Revision 3.4  1995/06/21  17:17:50  epstein
88  * *** empty log message ***
89  *
90  * Revision 3.3  95/05/15  21:22:00  ostell
91  * added Log line
92  *
93 *
94 *
95 *
96 * ==========================================================================
97 */
98 
99 #ifndef _NCBI_Seqalign_
100 #define _NCBI_Seqalign_
101 
102 #ifndef _ASNTOOL_
103 #include <asn.h>
104 #endif
105 #ifndef _NCBI_General_
106 #include <objgen.h>
107 #endif
108 #ifndef _NCBI_Seqloc_
109 #include <objloc.h>
110 #endif
111 
112 #undef NLM_EXTERN
113 #ifdef NLM_IMPORT
114 #define NLM_EXTERN NLM_IMPORT
115 #else
116 #define NLM_EXTERN extern
117 #endif
118 
119 #ifdef __cplusplus
120 extern "C" {
121 #endif
122 
123 /*****************************************************************************
124 *
125 *   loader
126 *
127 *****************************************************************************/
128 NLM_EXTERN Boolean LIBCALL SeqAlignAsnLoad PROTO((void));
129 
130 /*****************************************************************************
131 *
132 *   internal structures for NCBI-Seqalign objects
133 *
134 *****************************************************************************/
135 
136 /*****************************************************************************
137 *
138 *   Score
139 *     NOTE: read, write, and free always process GROUPS of scores
140 *
141 *****************************************************************************/
142 typedef struct score {
143     ObjectIdPtr id;
144     Uint1 choice;          /* 0=not set, 1=int, 2=real */
145     DataVal value;
146     struct score PNTR next;    /* for sets of scores */
147 } Score, PNTR ScorePtr;
148 
149 NLM_EXTERN ScorePtr LIBCALL ScoreNew PROTO((void));
150 NLM_EXTERN Boolean  LIBCALL ScoreSetAsnWrite PROTO((ScorePtr sp, AsnIoPtr aip, AsnTypePtr settype));
151 NLM_EXTERN ScorePtr LIBCALL ScoreSetAsnRead PROTO((AsnIoPtr aip, AsnTypePtr settype));
152 NLM_EXTERN ScorePtr LIBCALL ScoreSetFree PROTO((ScorePtr anp));
153 
154 /****************************************************************************
155 *
156 *  SeqAlignIndex
157 *
158 *    This structure is the public face of a data structure which is
159 *    extended in AlignMgr for alignment indexing, alignment features
160 *    and other utilities.
161 *
162 *    It is left as a limited structure "stub" here
163 *
164 ****************************************************************************/
165 /** the VoidPtr below should really be a SeqAlignIndexPtr **/
166 typedef Boolean (LIBCALLBACK * SeqAlignIndexFreeFunc)(VoidPtr);
167 
168 typedef struct seqalignindex {
169 	Uint1 indextype;
170 	SeqAlignIndexFreeFunc freefunc;
171 } SeqAlignIndex, PNTR SeqAlignIndexPtr;
172 
173 NLM_EXTERN SeqAlignIndexPtr LIBCALL SeqAlignIndexFree (SeqAlignIndexPtr saip);
174 
175 /*****************************************************************************
176 *
177 *   SeqAlign
178 *   type =  type of alignment
179         not-set (0) ,
180         global (1) ,
181         diags (2) ,
182         partial (3) ,           -- mapping pieces together
183 		disc (4) ,
184         other (255) } ,
185     segtype = type of segs structure
186         not-set 0
187         dendiag 1
188         denseq 2
189         std 3
190 		packed 4
191 		disc 5      SeqAlignSet is used
192 		spliced 6
193 *
194 *
195 *****************************************************************************/
196 /** SeqAlign.type values ***/
197 #define SAT_GLOBAL 1    /* ordered segments, over full length of seqs */
198 #define SAT_DIAGS 2     /* unordered, possibly overlapping segments */
199 #define SAT_PARTIAL 3   /* ordered segments, over part of sequence */
200 #define SAT_MASTERSLAVE 4   /* set of SeqAligns, all of which have one common */
201                             /* sequence. Not in ASN.1 yet */
202 
203 /** SeqAlign.segtype values ***/
204 #define SAS_DENDIAG 1
205 #define SAS_DENSEG 2
206 #define SAS_STD 3
207 #define SAS_PACKED 4
208 #define SAS_DISC 5
209 #define SAS_SPLICED 6
210 #define SAS_SPARSE 7
211 
212 
213 typedef struct seqalign {
214     Uint1 type,
215         segtype;
216     Int2 dim;
217     ScorePtr score;
218     Pointer segs;
219     struct seqalign PNTR next;
220 	SeqLocPtr bounds;      /* sequence of SeqLocPtr */
221 	ValNodePtr   id;
222 	struct struct_User_object PNTR   ext;
223     SeqIdPtr master;   /* for SAT_MASTERSLAVE */
224     SeqAlignIndexPtr saip;  /* for added Alignment Indexing structures */
225 	GatherIndex idx;      /* internal gather/objmgr tracking fields */
226 	Uint2 alignID;        /* unique number assigned to alignment */
227 } SeqAlign, PNTR SeqAlignPtr;
228 
229 NLM_EXTERN SeqAlignPtr LIBCALL SeqAlignNew PROTO((void));
230 NLM_EXTERN Boolean     LIBCALL SeqAlignAsnWrite PROTO((SeqAlignPtr anp, AsnIoPtr aip, AsnTypePtr atp));
231 NLM_EXTERN SeqAlignPtr LIBCALL SeqAlignAsnRead PROTO((AsnIoPtr aip, AsnTypePtr atp));
232 NLM_EXTERN SeqAlignPtr LIBCALL SeqAlignFree PROTO((SeqAlignPtr anp));
233 NLM_EXTERN Int2 LIBCALL SeqAlignLabel PROTO((SeqAlignPtr sap, CharPtr buffer, Int2 buflen, Uint1 content));
234 
235 /*****************************************************************************
236 *
237 *   SeqAlignSet
238 *
239 *****************************************************************************/
240 NLM_EXTERN Boolean     LIBCALL SeqAlignSetAsnWrite PROTO((SeqAlignPtr anp, AsnIoPtr aip, AsnTypePtr set, AsnTypePtr element));
241 NLM_EXTERN SeqAlignPtr LIBCALL SeqAlignSetAsnRead PROTO((AsnIoPtr aip, AsnTypePtr set, AsnTypePtr element));
242 NLM_EXTERN SeqAlignPtr LIBCALL SeqAlignSetFree PROTO((SeqAlignPtr sap));
243 NLM_EXTERN SeqAlignPtr LIBCALL SeqAlignSetNew PROTO((void));
244 NLM_EXTERN SeqAlignPtr LIBCALL SpecialSeqAlignSetAsnRead PROTO((AsnIoPtr aip, AsnTypePtr set));
245 NLM_EXTERN Boolean LIBCALL SpecialSeqAlignSetAsnWrite PROTO((SeqAlignPtr sap, AsnIoPtr aip, AsnTypePtr set));
246 NLM_EXTERN Boolean LIBCALL GenericSeqAlignSetAsnWrite PROTO((SeqAlignPtr sap, AsnIoPtr aip));
247 
248 
249 /*****************************************************************************
250 *
251 *   DenseDiag
252 *
253 *
254 *****************************************************************************/
255 typedef struct dendiag {
256     Int2 dim;                   /* this is a convenience, not in asn1 */
257     SeqIdPtr id;
258     Int4Ptr starts;
259     Int4 len;
260     Uint1Ptr strands;
261     ScorePtr scores;
262     struct dendiag PNTR next;
263 } DenseDiag, PNTR DenseDiagPtr;
264 
265 NLM_EXTERN DenseDiagPtr LIBCALL DenseDiagNew PROTO((void));
266 NLM_EXTERN Boolean      LIBCALL DenseDiagAsnWrite PROTO((DenseDiagPtr ddp, AsnIoPtr aip, AsnTypePtr atp));
267 NLM_EXTERN DenseDiagPtr LIBCALL DenseDiagAsnRead PROTO((AsnIoPtr aip, AsnTypePtr atp));
268 NLM_EXTERN DenseDiagPtr LIBCALL DenseDiagFree PROTO((DenseDiagPtr ddp));
269 
270 /*****************************************************************************
271 *
272 *   DenseSeg
273 *
274 *
275 *****************************************************************************/
276 typedef struct denseg {
277     Int2 dim,
278         numseg;
279     SeqIdPtr ids;           /* dimension is dim */
280     Int4Ptr starts;			/* dimension is dim * numseg */
281     Int4Ptr lens;			/* dimension is numseg */
282     Uint1Ptr strands;		/* dimension is dim * numseg */
283     ScorePtr scores;		/* dimension is numseg */
284 } DenseSeg, PNTR DenseSegPtr;
285 
286 NLM_EXTERN DenseSegPtr LIBCALL DenseSegNew PROTO((void));
287 NLM_EXTERN Boolean     LIBCALL DenseSegAsnWrite PROTO((DenseSegPtr dsp, AsnIoPtr aip, AsnTypePtr atp));
288 NLM_EXTERN DenseSegPtr LIBCALL DenseSegAsnRead PROTO((AsnIoPtr aip, AsnTypePtr atp));
289 NLM_EXTERN DenseSegPtr LIBCALL DenseSegFree PROTO((DenseSegPtr dsp));
290 
291 /*****************************************************************************
292 *
293 *   PackSeg
294 *
295 *
296 *****************************************************************************/
297 typedef struct packseg {
298     Int2 dim,
299         numseg;
300     SeqIdPtr ids;			/* dimension is dim */
301     Int4Ptr starts;			/* dimension is dim */
302 	ByteStorePtr present;	/* dimension is dim * numseg booleans */
303     Int4Ptr lens;			/* dimension is numseg */
304     Uint1Ptr strands;		/* dimension is dim */
305     ScorePtr scores;		/* dimension is numseg */
306 } PackSeg, PNTR PackSegPtr;
307 
308 NLM_EXTERN PackSegPtr LIBCALL PackSegNew PROTO((void));
309 NLM_EXTERN Boolean     LIBCALL PackSegAsnWrite PROTO((PackSegPtr psp, AsnIoPtr aip, AsnTypePtr atp));
310 NLM_EXTERN PackSegPtr LIBCALL PackSegAsnRead PROTO((AsnIoPtr aip, AsnTypePtr atp));
311 NLM_EXTERN PackSegPtr LIBCALL PackSegFree PROTO((PackSegPtr psp));
312 
313 /*****************************************************************************
314 *
315 *   StdSeg
316 *
317 *
318 *****************************************************************************/
319 typedef struct stdseg {
320     Int2 dim;
321     SeqIdPtr ids;    /* SeqId s */
322     SeqLocPtr loc;    /* SeqLoc s */
323     ScorePtr scores;
324     struct stdseg PNTR next;
325 } StdSeg, PNTR StdSegPtr;
326 
327 NLM_EXTERN StdSegPtr LIBCALL StdSegNew PROTO((void));
328 NLM_EXTERN Boolean   LIBCALL StdSegAsnWrite PROTO((StdSegPtr ssp, AsnIoPtr aip, AsnTypePtr atp));
329 NLM_EXTERN StdSegPtr LIBCALL StdSegAsnRead PROTO((AsnIoPtr aip, AsnTypePtr atp));
330 NLM_EXTERN StdSegPtr LIBCALL StdSegFree PROTO((StdSegPtr ssp));
331 
332 /**************************************************
333 *
334 *    SplicedSeg
335 *
336 **************************************************/
337 typedef struct struct_Spliced_seg {
338    Uint4 OBbits__;
339    ValNodePtr   product_id;
340    ValNodePtr   genomic_id;
341 #define OB__Spliced_seg_product_strand 0
342 
343    Uint2   product_strand;
344 #define OB__Spliced_seg_genomic_strand 1
345 
346    Uint2   genomic_strand;
347    Uint2   product_type;
348    /* following #defines are for enumerated type, not used by object loaders */
349 #define Spliced_seg_product_type_transcript 0
350 #define Spliced_seg_product_type_protein 1
351 
352    struct struct_Spliced_exon PNTR   exons;
353 #define OB__Spliced_seg_poly_a 2
354 
355    Int4   poly_a;
356 #define OB__Spliced_seg_product_length 3
357 
358    Int4   product_length;
359    ValNodePtr   modifiers;
360 } SplicedSeg, PNTR SplicedSegPtr;
361 
362 
363 NLM_EXTERN SplicedSegPtr LIBCALL SplicedSegFree PROTO ((SplicedSegPtr ));
364 NLM_EXTERN SplicedSegPtr LIBCALL SplicedSegNew PROTO (( void ));
365 NLM_EXTERN SplicedSegPtr LIBCALL SplicedSegAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
366 NLM_EXTERN Boolean LIBCALL SplicedSegAsnWrite PROTO (( SplicedSegPtr , AsnIoPtr, AsnTypePtr));
367 
368 
369 
370 /**************************************************
371 *
372 *    SparseSeg
373 *
374 **************************************************/
375 typedef struct struct_Sparse_seg {
376    Uint4 OBbits__;
377    ValNodePtr   master_id;
378    struct struct_Sparse_align PNTR   rows;
379    ScorePtr    row_scores;
380    struct struct_Sparse_seg_ext PNTR   ext;
381 } SparseSeg, PNTR SparseSegPtr;
382 
383 
384 NLM_EXTERN SparseSegPtr LIBCALL SparseSegFree PROTO ((SparseSegPtr ));
385 NLM_EXTERN SparseSegPtr LIBCALL SparseSegNew PROTO (( void ));
386 NLM_EXTERN SparseSegPtr LIBCALL SparseSegAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
387 NLM_EXTERN Boolean LIBCALL SparseSegAsnWrite PROTO (( SparseSegPtr , AsnIoPtr, AsnTypePtr));
388 
389 
390 
391 /**************************************************
392 *
393 *    SplicedExon
394 *
395 **************************************************/
396 typedef struct struct_Spliced_exon {
397    struct struct_Spliced_exon PNTR next;
398    ValNodePtr   product_start;
399    ValNodePtr   product_end;
400    Int4   genomic_start;
401    Int4   genomic_end;
402    ValNodePtr   product_id;
403    ValNodePtr   genomic_id;
404    Uint2   product_strand;
405    Uint2   genomic_strand;
406    ValNodePtr   parts;
407    ScorePtr   scores;
408    struct struct_Splice_site PNTR   acceptor_before_exon;
409    struct struct_Splice_site PNTR   donor_after_exon;
410    Uint1   partial;
411    struct struct_User_object PNTR   ext;
412 } SplicedExon, PNTR SplicedExonPtr;
413 
414 
415 NLM_EXTERN SplicedExonPtr LIBCALL SplicedExonFree PROTO ((SplicedExonPtr ));
416 NLM_EXTERN SplicedExonPtr LIBCALL SplicedExonNew PROTO (( void ));
417 NLM_EXTERN SplicedExonPtr LIBCALL SplicedExonAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
418 NLM_EXTERN Boolean LIBCALL SplicedExonAsnWrite PROTO (( SplicedExonPtr , AsnIoPtr, AsnTypePtr));
419 
420 typedef ValNodePtr SplicedSegModifierPtr;
421 typedef ValNode SplicedSegModifier;
422 #define SplicedSegModifier_start_codon_found 1
423 #define SplicedSegModifier_stop_codon_found 2
424 
425 
426 NLM_EXTERN SplicedSegModifierPtr LIBCALL SplicedSegModifierFree PROTO ((SplicedSegModifierPtr ));
427 NLM_EXTERN SplicedSegModifierPtr LIBCALL SplicedSegModifierAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
428 NLM_EXTERN Boolean LIBCALL SplicedSegModifierAsnWrite PROTO (( SplicedSegModifierPtr , AsnIoPtr, AsnTypePtr));
429 
430 typedef ValNodePtr ProductPosPtr;
431 typedef ValNode ProductPos;
432 #define ProductPos_nucpos 1
433 #define ProductPos_protpos 2
434 
435 
436 NLM_EXTERN ProductPosPtr LIBCALL ProductPosFree PROTO ((ProductPosPtr ));
437 NLM_EXTERN ProductPosPtr LIBCALL ProductPosAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
438 NLM_EXTERN Boolean LIBCALL ProductPosAsnWrite PROTO (( ProductPosPtr , AsnIoPtr, AsnTypePtr));
439 
440 typedef ValNodePtr SplicedExonChunkPtr;
441 typedef ValNode SplicedExonChunk;
442 #define SplicedExonChunk_match 1
443 #define SplicedExonChunk_mismatch 2
444 #define SplicedExonChunk_diag 3
445 #define SplicedExonChunk_product_ins 4
446 #define SplicedExonChunk_genomic_ins 5
447 
448 
449 NLM_EXTERN SplicedExonChunkPtr LIBCALL SplicedExonChunkFree PROTO ((SplicedExonChunkPtr ));
450 NLM_EXTERN SplicedExonChunkPtr LIBCALL SplicedExonChunkAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
451 NLM_EXTERN Boolean LIBCALL SplicedExonChunkAsnWrite PROTO (( SplicedExonChunkPtr , AsnIoPtr, AsnTypePtr));
452 
453 
454 
455 /**************************************************
456 *
457 *    SpliceSite
458 *
459 **************************************************/
460 typedef struct struct_Splice_site {
461    CharPtr   bases;
462 } SpliceSite, PNTR SpliceSitePtr;
463 
464 
465 NLM_EXTERN SpliceSitePtr LIBCALL SpliceSiteFree PROTO ((SpliceSitePtr ));
466 NLM_EXTERN SpliceSitePtr LIBCALL SpliceSiteNew PROTO (( void ));
467 NLM_EXTERN SpliceSitePtr LIBCALL SpliceSiteAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
468 NLM_EXTERN Boolean LIBCALL SpliceSiteAsnWrite PROTO (( SpliceSitePtr , AsnIoPtr, AsnTypePtr));
469 
470 
471 
472 /**************************************************
473 *
474 *    ProtPos
475 *
476 **************************************************/
477 typedef struct struct_Prot_pos {
478    Int4   amin;
479    Int4   frame;
480 } ProtPos, PNTR ProtPosPtr;
481 
482 
483 NLM_EXTERN ProtPosPtr LIBCALL ProtPosFree PROTO ((ProtPosPtr ));
484 NLM_EXTERN ProtPosPtr LIBCALL ProtPosNew PROTO (( void ));
485 NLM_EXTERN ProtPosPtr LIBCALL ProtPosAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
486 NLM_EXTERN Boolean LIBCALL ProtPosAsnWrite PROTO (( ProtPosPtr , AsnIoPtr, AsnTypePtr));
487 
488 
489 /**************************************************
490 *
491 *    SparseAlign
492 *
493 **************************************************/
494 typedef struct struct_Sparse_align {
495    struct struct_Sparse_align PNTR next;
496    Uint4 OBbits__;
497    ValNodePtr   first_id;
498    ValNodePtr   second_id;
499    Int4   numseg;
500    ValNodePtr   first_starts;
501    ValNodePtr   second_starts;
502    ValNodePtr   lens;
503    ValNodePtr   second_strands;
504    ScorePtr   seg_scores;
505 } SparseAlign, PNTR SparseAlignPtr;
506 
507 
508 NLM_EXTERN SparseAlignPtr LIBCALL SparseAlignFree PROTO ((SparseAlignPtr ));
509 NLM_EXTERN SparseAlignPtr LIBCALL SparseAlignNew PROTO (( void ));
510 NLM_EXTERN SparseAlignPtr LIBCALL SparseAlignAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
511 NLM_EXTERN Boolean LIBCALL SparseAlignAsnWrite PROTO (( SparseAlignPtr , AsnIoPtr, AsnTypePtr));
512 
513 
514 
515 /**************************************************
516 *
517 *    SparseSegExt
518 *
519 **************************************************/
520 typedef struct struct_Sparse_seg_ext {
521    struct struct_Sparse_seg_ext PNTR next;
522    Uint4 OBbits__;
523    Int4   index;
524 } SparseSegExt, PNTR SparseSegExtPtr;
525 
526 
527 NLM_EXTERN SparseSegExtPtr LIBCALL SparseSegExtFree PROTO ((SparseSegExtPtr ));
528 NLM_EXTERN SparseSegExtPtr LIBCALL SparseSegExtNew PROTO (( void ));
529 NLM_EXTERN SparseSegExtPtr LIBCALL SparseSegExtAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
530 NLM_EXTERN Boolean LIBCALL SparseSegExtAsnWrite PROTO (( SparseSegExtPtr , AsnIoPtr, AsnTypePtr));
531 
532 #ifdef __cplusplus
533 }
534 #endif
535 
536 #undef NLM_EXTERN
537 #ifdef NLM_EXPORT
538 #define NLM_EXTERN NLM_EXPORT
539 #else
540 #define NLM_EXTERN
541 #endif
542 
543 #endif
544