]> git.sur5r.net Git - cc65/blob - src/ca65/symentry.c
Write imports out as debug symbols.
[cc65] / src / ca65 / symentry.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                symentry.c                                 */
4 /*                                                                           */
5 /*              Symbol table entry for the ca65 macroassembler               */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2011, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37
38 /* common */
39 #include "addrsize.h"
40 #include "symdefs.h"
41 #include "xmalloc.h"
42
43 /* ca65 */
44 #include "error.h"
45 #include "expr.h"
46 #include "global.h"
47 #include "scanner.h"
48 #include "segment.h"
49 #include "spool.h"
50 #include "studyexpr.h"          /* ### */
51 #include "symentry.h"
52 #include "symtab.h"
53
54
55
56 /*****************************************************************************/
57 /*                                   Data                                    */
58 /*****************************************************************************/
59
60
61
62 /* List of all symbol table entries */
63 SymEntry* SymList = 0;
64
65 /* Pointer to last defined symbol */
66 SymEntry* SymLast = 0;
67
68
69
70 /*****************************************************************************/
71 /*                                   Code                                    */
72 /*****************************************************************************/
73
74
75
76 SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags)
77 /* Allocate a symbol table entry, initialize and return it */
78 {
79     unsigned I;
80
81     /* Allocate memory */
82     SymEntry* S = xmalloc (sizeof (SymEntry));
83
84     /* Initialize the entry */
85     S->Left       = 0;
86     S->Right      = 0;
87     S->Locals     = 0;
88     S->Sym.Tab    = 0;
89     S->LineInfos  = EmptyCollection;
90     GetFullLineInfo (&S->LineInfos, 1);
91     for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) {
92         S->GuessedUse[I] = 0;
93     }
94     S->Flags      = Flags;
95     S->DebugSymId = ~0U;
96     S->ImportId   = ~0U;
97     S->ExportId   = ~0U;
98     S->Expr       = 0;
99     S->ExprRefs   = AUTO_COLLECTION_INITIALIZER;
100     S->ExportSize = ADDR_SIZE_DEFAULT;
101     S->AddrSize   = ADDR_SIZE_DEFAULT;
102     memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
103     S->Name       = GetStrBufId (Name);
104
105     /* Insert it into the list of all entries */
106     S->List = SymList;
107     SymList = S;
108
109     /* Return the initialized entry */
110     return S;
111 }
112
113
114
115 int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E)
116 /* Search in the given tree for a name. If we find the symbol, the function
117  * will return 0 and put the entry pointer into E. If we did not find the
118  * symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
119  * E will be set to the last entry, and the result of the function is <0 if
120  * the entry should be inserted on the left side, and >0 if it should get
121  * inserted on the right side.
122  */
123 {
124     /* Is there a tree? */
125     if (T == 0) {
126         *E = 0;
127         return 1;
128     }
129
130     /* We have a table, search it */
131     while (1) {
132
133         /* Get the symbol name */
134         const StrBuf* SymName = GetStrBuf (T->Name);
135
136         /* Choose next entry */
137         int Cmp = SB_Compare (Name, SymName);
138         if (Cmp < 0 && T->Left) {
139             T = T->Left;
140         } else if (Cmp > 0&& T->Right) {
141             T = T->Right;
142         } else {
143             /* Found or end of search, return the result */
144             *E = T;
145             return Cmp;
146         }
147     }
148 }
149
150
151
152 void SymRef (SymEntry* S)
153 /* Mark the given symbol as referenced */
154 {
155     /* Mark the symbol as referenced */
156     S->Flags |= SF_REFERENCED;
157 }
158
159
160
161 void SymTransferExprRefs (SymEntry* From, SymEntry* To)
162 /* Transfer all expression references from one symbol to another. */
163 {
164     unsigned I;
165
166     for (I = 0; I < CollCount (&From->ExprRefs); ++I) {
167
168         /* Get the expression node */
169         ExprNode* E = CollAtUnchecked (&From->ExprRefs, I);
170
171         /* Safety */
172         CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == From);
173
174         /* Replace the symbol reference */
175         E->V.Sym = To;
176
177         /* Add the expression reference */
178         SymAddExprRef (To, E);
179     }
180
181     /* Remove all symbol references from the old symbol */
182     CollDeleteAll (&From->ExprRefs);
183 }
184
185
186
187 static void SymReplaceExprRefs (SymEntry* S)
188 /* Replace the references to this symbol by a copy of the symbol expression */
189 {
190     unsigned I;
191     long     Val;
192
193     /* Check if the expression is const and get its value */
194     int IsConst = IsConstExpr (S->Expr, &Val);
195     CHECK (IsConst);
196
197     /* Loop over all references */
198     for (I = 0; I < CollCount (&S->ExprRefs); ++I) {
199
200         /* Get the expression node */
201         ExprNode* E = CollAtUnchecked (&S->ExprRefs, I);
202
203         /* Safety */
204         CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == S);
205
206         /* We cannot touch the root node, since there are pointers to it.
207          * Replace it by a literal node.
208          */
209         E->Op = EXPR_LITERAL;
210         E->V.IVal = Val;
211     }
212
213     /* Remove all symbol references from the symbol */
214     CollDeleteAll (&S->ExprRefs);
215 }
216
217
218
219 void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags)
220 /* Define a new symbol */
221 {
222     if (S->Flags & SF_IMPORT) {
223         /* Defined symbol is marked as imported external symbol */
224         Error ("Symbol `%m%p' is already an import", GetSymName (S));
225         return;
226     }
227     if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
228         /* Variable symbols cannot be exports or globals */
229         Error ("Var symbol `%m%p' cannot be an export or global symbol", GetSymName (S));
230         return;
231     }
232     if (S->Flags & SF_DEFINED) {
233         /* Multiple definition. In case of a variable, this is legal. */
234         if ((S->Flags & SF_VAR) == 0) {
235             Error ("Symbol `%m%p' is already defined", GetSymName (S));
236             S->Flags |= SF_MULTDEF;
237             return;
238         } else {
239             /* Redefinition must also be a variable symbol */
240             if ((Flags & SF_VAR) == 0) {
241                 Error ("Symbol `%m%p' is already different kind", GetSymName (S));
242                 return;
243             }
244             /* Delete the current symbol expression, since it will get
245              * replaced
246              */
247             FreeExpr (S->Expr);
248             S->Expr = 0;
249         }
250     }
251
252     /* Map a default address size to a real value */
253     if (AddrSize == ADDR_SIZE_DEFAULT) {
254         /* ### Must go! Delay address size calculation until end of assembly! */
255         ExprDesc ED;
256         ED_Init (&ED);
257         StudyExpr (Expr, &ED);
258         AddrSize = ED.AddrSize;
259         ED_Done (&ED);
260     }
261
262     /* Set the symbol value */
263     S->Expr = Expr;
264
265     /* In case of a variable symbol, walk over all expressions containing
266      * this symbol and replace the (sub-)expression by the literal value of
267      * the tree. Be sure to replace the expression node in place, since there
268      * may be pointers to it.
269      */
270     if (Flags & SF_VAR) {
271         SymReplaceExprRefs (S);
272     }
273
274     /* If the symbol is marked as global, export it. Address size is checked
275      * below.
276      */
277     if (S->Flags & SF_GLOBAL) {
278         S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
279     }
280
281     /* Mark the symbol as defined and use the given address size */
282     S->Flags |= (SF_DEFINED | Flags);
283     S->AddrSize = AddrSize;
284
285     /* If the symbol is exported, check the address sizes */
286     if (S->Flags & SF_EXPORT) {
287         if (S->ExportSize == ADDR_SIZE_DEFAULT) {
288             /* Use the real size of the symbol */
289             S->ExportSize = S->AddrSize;
290         } else if (S->AddrSize > S->ExportSize) {
291             /* We're exporting a symbol smaller than it actually is */
292             LIWarning (&S->LineInfos, 1, "Symbol `%m%p' is %s but exported %s",
293                        GetSymName (S), AddrSizeToStr (S->AddrSize),
294                        AddrSizeToStr (S->ExportSize));
295         }
296     }
297
298     /* If this is not a local symbol, remember it as the last global one */
299     if ((S->Flags & SF_LOCAL) == 0) {
300         SymLast = S;
301     }
302 }
303
304
305
306 void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
307 /* Mark the given symbol as an imported symbol */
308 {
309     if (S->Flags & SF_DEFINED) {
310         Error ("Symbol `%m%p' is already defined", GetSymName (S));
311         S->Flags |= SF_MULTDEF;
312         return;
313     }
314     if (S->Flags & SF_EXPORT) {
315         /* The symbol is already marked as exported symbol */
316         Error ("Cannot import exported symbol `%m%p'", GetSymName (S));
317         return;
318     }
319
320     /* If no address size is given, use the address size of the enclosing
321      * segment.
322      */
323     if (AddrSize == ADDR_SIZE_DEFAULT) {
324         AddrSize = GetCurrentSegAddrSize ();
325     }
326
327     /* If the symbol is marked as import or global, check the address size,
328      * then do silently remove the global flag.
329      */
330     if (S->Flags & SF_IMPORT) {
331         if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
332             Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
333         }
334         if (AddrSize != S->AddrSize) {
335             Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
336         }
337     }
338     if (S->Flags & SF_GLOBAL) {
339         S->Flags &= ~SF_GLOBAL;
340         if (AddrSize != S->AddrSize) {
341             Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
342         }
343     }
344
345     /* Set the symbol data */
346     S->Flags |= (SF_IMPORT | Flags);
347     S->AddrSize = AddrSize;
348 }
349
350
351
352 void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
353 /* Mark the given symbol as an exported symbol */
354 {
355     /* Check if it's ok to export the symbol */
356     if (S->Flags & SF_IMPORT) {
357         /* The symbol is already marked as imported external symbol */
358         Error ("Symbol `%m%p' is already an import", GetSymName (S));
359         return;
360     }
361     if (S->Flags & SF_VAR) {
362         /* Variable symbols cannot be exported */
363         Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
364         return;
365     }
366
367     /* If the symbol was marked as global before, remove the global flag and
368      * proceed, but check the address size.
369      */
370     if (S->Flags & SF_GLOBAL) {
371         if (AddrSize != S->ExportSize) {
372             Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
373         }
374         S->Flags &= ~SF_GLOBAL;
375     }
376
377     /* If the symbol was already marked as an export, but wasn't defined
378      * before, the address sizes in both definitions must match.
379      */
380     if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) {
381         if (S->ExportSize != AddrSize) {
382             Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
383         }
384     }
385     S->ExportSize = AddrSize;
386
387     /* If the symbol is already defined, check symbol size against the
388      * exported size.
389      */
390     if (S->Flags & SF_DEFINED) {
391         if (S->ExportSize == ADDR_SIZE_DEFAULT) {
392             /* No export size given, use the real size of the symbol */
393             S->ExportSize = S->AddrSize;
394         } else if (S->AddrSize > S->ExportSize) {
395             /* We're exporting a symbol smaller than it actually is */
396             Warning (1, "Symbol `%m%p' is %s but exported %s",
397                      GetSymName (S), AddrSizeToStr (S->AddrSize),
398                      AddrSizeToStr (S->ExportSize));
399         }
400     }
401
402     /* Set the symbol data */
403     S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);
404 }
405
406
407
408 void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
409 /* Mark the given symbol as a global symbol, that is, as a symbol that is
410  * either imported or exported.
411  */
412 {
413     if (S->Flags & SF_VAR) {
414         /* Variable symbols cannot be exported or imported */
415         Error ("Var symbol `%m%p' cannot be made global", GetSymName (S));
416         return;
417     }
418
419     /* If the symbol is already marked as import, the address size must match.
420      * Apart from that, ignore the global declaration.
421      */
422     if (S->Flags & SF_IMPORT) {
423         if (AddrSize == ADDR_SIZE_DEFAULT) {
424             /* Use the size of the current segment */
425             AddrSize = GetCurrentSegAddrSize ();
426         }
427         if (AddrSize != S->AddrSize) {
428             Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
429         }
430         return;
431     }
432
433     /* If the symbol is already an export: If it is not defined, the address
434      * sizes must match.
435      */
436     if (S->Flags & SF_EXPORT) {
437         if ((S->Flags & SF_DEFINED) == 0) {
438             /* Symbol is undefined */
439             if (AddrSize != S->ExportSize) {
440                 Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
441             }
442         } else if (AddrSize != ADDR_SIZE_DEFAULT) {
443             /* Symbol is defined and address size given */
444             if (AddrSize != S->ExportSize) {
445                 Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
446             }
447         }
448         return;
449     }
450
451     /* If the symbol is already marked as global, the address size must match.
452      * Use the ExportSize here, since it contains the actual address size
453      * passed to this function.
454      */
455     if (S->Flags & SF_GLOBAL) {
456         if (AddrSize != S->ExportSize) {
457             Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
458         }
459         return;
460     }
461
462     /* If we come here, the symbol was neither declared as export, import or
463      * global before. Check if it is already defined, in which case it will
464      * become an export. If it is not defined, mark it as global and remember
465      * the given address sizes.
466      */
467     if (S->Flags & SF_DEFINED) {
468         /* The symbol is defined, export it */
469         S->ExportSize = AddrSize;
470         if (S->ExportSize == ADDR_SIZE_DEFAULT) {
471             /* No export size given, use the real size of the symbol */
472             S->ExportSize = S->AddrSize;
473         } else if (S->AddrSize > S->ExportSize) {
474             /* We're exporting a symbol smaller than it actually is */
475             Warning (1, "Symbol `%m%p' is %s but exported %s",
476                      GetSymName (S), AddrSizeToStr (S->AddrSize),
477                      AddrSizeToStr (S->ExportSize));
478         }
479         S->Flags |= (SF_EXPORT | Flags);
480     } else {
481         /* Since we don't know if the symbol will get exported or imported,
482          * remember two different address sizes: One for an import in AddrSize,
483          * and the other one for an export in ExportSize.
484          */
485         S->AddrSize = AddrSize;
486         if (S->AddrSize == ADDR_SIZE_DEFAULT) {
487             /* Use the size of the current segment */
488             S->AddrSize = GetCurrentSegAddrSize ();
489         }
490         S->ExportSize = AddrSize;
491         S->Flags |= (SF_GLOBAL | Flags);
492     }
493 }
494
495
496
497 void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio)
498 /* Mark the given symbol as a module constructor/destructor. This will also
499  * mark the symbol as an export. Initializers may never be zero page symbols.
500  */
501 {
502     /* Check the parameters */
503 #if (CD_TYPE_MIN != 0)
504     CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
505 #else
506     CHECK (Type <= CD_TYPE_MAX);
507 #endif
508     CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);
509
510     /* Check for errors */
511     if (S->Flags & SF_IMPORT) {
512         /* The symbol is already marked as imported external symbol */
513         Error ("Symbol `%m%p' is already an import", GetSymName (S));
514         return;
515     }
516     if (S->Flags & SF_VAR) {
517         /* Variable symbols cannot be exported or imported */
518         Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
519         return;
520     }
521
522     /* If the symbol was already marked as an export or global, check if
523      * this was done specifiying the same address size. In case of a global
524      * declaration, silently remove the global flag.
525      */
526     if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
527         if (S->ExportSize != AddrSize) {
528             Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
529         }
530         S->Flags &= ~SF_GLOBAL;
531     }
532     S->ExportSize = AddrSize;
533
534     /* If the symbol is already defined, check symbol size against the
535      * exported size.
536      */
537     if (S->Flags & SF_DEFINED) {
538         if (S->ExportSize == ADDR_SIZE_DEFAULT) {
539             /* Use the real size of the symbol */
540             S->ExportSize = S->AddrSize;
541         } else if (S->AddrSize != S->ExportSize) {
542             Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
543         }
544     }
545
546     /* If the symbol was already declared as a condes, check if the new
547      * priority value is the same as the old one.
548      */
549     if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
550         if (S->ConDesPrio[Type] != Prio) {
551             Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
552         }
553     }
554     S->ConDesPrio[Type] = Prio;
555
556     /* Set the symbol data */
557     S->Flags |= (SF_EXPORT | SF_REFERENCED);
558 }
559
560
561
562 void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize)
563 /* Mark the address size of the given symbol as guessed. The address size
564  * passed as argument is the one NOT used, because the actual address size
565  * wasn't known. Example: Zero page addressing was not used because symbol
566  * is undefined, and absolute addressing was available.
567  */
568 {
569     /* We must have a valid address size passed */
570     PRECONDITION (AddrSize != ADDR_SIZE_DEFAULT);
571
572     /* We do not support all address sizes currently */
573     if (AddrSize > sizeof (Sym->GuessedUse) / sizeof (Sym->GuessedUse[0])) {
574         return;
575     }
576
577     /* We can only remember one such occurance */
578     if (Sym->GuessedUse[AddrSize-1]) {
579         return;
580     }
581
582     /* Ok, remember the file position */
583     Sym->GuessedUse[AddrSize-1] = xdup (&CurTok.Pos, sizeof (CurTok.Pos));
584 }
585
586
587
588 void SymExportFromGlobal (SymEntry* S)
589 /* Called at the end of assembly. Converts a global symbol that is defined
590  * into an export.
591  */
592 {
593     /* Remove the global flag and make the symbol an export */
594     S->Flags &= ~SF_GLOBAL;
595     S->Flags |= SF_EXPORT;
596 }
597
598
599
600 void SymImportFromGlobal (SymEntry* S)
601 /* Called at the end of assembly. Converts a global symbol that is undefined
602  * into an import.
603  */
604 {
605     /* Remove the global flag and make it an import */
606     S->Flags &= ~SF_GLOBAL;
607     S->Flags |= SF_IMPORT;
608 }
609
610
611
612 int SymIsConst (const SymEntry* S, long* Val)
613 /* Return true if the given symbol has a constant value. If Val is not NULL
614  * and the symbol has a constant value, store it's value there.
615  */
616 {
617     /* Check for constness */
618     return (SymHasExpr (S) && IsConstExpr (S->Expr, Val));
619 }
620
621
622
623 SymTable* GetSymParentScope (SymEntry* S)
624 /* Get the parent scope of the symbol (not the one it is defined in). Return
625  * NULL if the symbol is a cheap local, or defined on global level.
626  */
627 {
628     if ((S->Flags & SF_LOCAL) != 0) {
629         /* This is a cheap local symbol */
630         return 0;
631     } else if (S->Sym.Tab == 0) {
632         /* Symbol not in a table. This may happen if there have been errors
633          * before. Return NULL in this case to avoid further errors.
634          */
635         return 0;
636     } else {
637         /* This is a global symbol */
638         return S->Sym.Tab->Parent;
639     }
640 }
641
642
643
644 struct ExprNode* GetSymExpr (SymEntry* S)
645 /* Get the expression for a non-const symbol */
646 {
647     PRECONDITION (S != 0 && SymHasExpr (S));
648     return S->Expr;
649 }
650
651
652
653 const struct ExprNode* SymResolve (const SymEntry* S)
654 /* Helper function for DumpExpr. Resolves a symbol into an expression or return
655  * NULL. Do not call in other contexts!
656  */
657 {
658     return SymHasExpr (S)? S->Expr : 0;
659 }
660
661
662
663 long GetSymVal (SymEntry* S)
664 /* Return the value of a symbol assuming it's constant. FAIL will be called
665  * in case the symbol is undefined or not constant.
666  */
667 {
668     long Val;
669     CHECK (S != 0 && SymHasExpr (S) && IsConstExpr (GetSymExpr (S), &Val));
670     return Val;
671 }
672
673
674
675 unsigned GetSymImportId (const SymEntry* S)
676 /* Return the import id for the given symbol */
677 {
678     PRECONDITION (S != 0 && (S->Flags & SF_IMPORT) && S->ImportId != ~0U);
679     return S->ImportId;
680 }
681
682
683
684 unsigned GetSymExportId (const SymEntry* S)
685 /* Return the export id for the given symbol */
686 {
687     PRECONDITION (S != 0 && (S->Flags & SF_EXPORT) && S->ExportId != ~0U);
688     return S->ExportId;
689 }
690
691
692
693 unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal)
694 /* Return a set of flags used when writing symbol information into a file.
695  * If the SYM_CONST bit is set, ConstVal will contain the constant value
696  * of the symbol. The result does not include the condes count.
697  * See common/symdefs.h for more information.
698  */
699 {
700     /* Setup info flags */
701     unsigned Flags = 0;
702     Flags |= SymIsConst (S, ConstVal)? SYM_CONST : SYM_EXPR;
703     Flags |= (S->Flags & SF_LABEL)? SYM_LABEL : SYM_EQUATE;
704     Flags |= (S->Flags & SF_LOCAL)? SYM_CHEAP_LOCAL : SYM_STD;
705     if (S->Flags & SF_EXPORT) {
706         Flags |= SYM_EXPORT;
707     }
708     if (S->Flags & SF_IMPORT) {
709         Flags |= SYM_IMPORT;
710     }
711
712     /* Return the result */
713     return Flags;
714 }
715
716
717