Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / export / symtab.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 /*
11 * symtab - symbol table routines
12 */
13 #include <afsconfig.h>
14 #include <afs/param.h>
15
16
17 #include "sys/types.h"
18 #include "sym.h"
19
20 /*
21 * using the toc_syment structure, that we fabricate:
22 * sym->n_offset is the string pointer
23 */
24 #ifdef __XCOFF64__
25 #define sym_str(sym) ((char *) (sym)->n_nptr)
26 #else
27 #define sym_off(sym) ((sym)->n_offset)
28 #define sym_str(sym) \
29 ((sym)->n_zeroes == 0 ? (char *) sym_off(sym) : (sym)->n_name)
30 #endif
31
32 sym_t *
33 sym_lookup(name, value)
34 char *name;
35 {
36 static sym_t *symsrch(), *search();
37 char buf[64];
38 sym_t *sym;
39
40 if (name) {
41 /*
42 * Heuristic:
43 * first, try just the name. if that fails, try with a
44 * prefix '.', and failing that, a prefix '_'.
45 */
46 if (sym = symsrch(name))
47 return sym;
48 memcpy(buf + 1, name, sizeof(buf) - 2);
49 buf[0] = '.';
50
51 if (sym = symsrch(buf))
52 return sym;
53
54 buf[0] = '_';
55
56 return symsrch(buf);
57 } else
58 return search(value);
59 }
60
61 static sym_t *
62 search(addr)
63 unsigned addr;
64 {
65 sym_t *sp;
66 sym_t *save;
67 unsigned value;
68
69 value = 0;
70 save = 0;
71
72 for (sp = toc_syms; sp < &toc_syms[toc_nsyms]; ++sp) {
73 if (sp->n_value <= addr && sp->n_value >= value) {
74 value = sp->n_value;
75 save = sp;
76 if (sp->n_value == addr)
77 break;
78 }
79 }
80 return save ? sym_flex(save) : 0;
81 }
82
83 static sym_t *
84 symsrch(s)
85 char *s;
86 {
87 sym_t *sp;
88 sym_t *found;
89 int len;
90 char *p;
91
92 /*
93 * determine length of symbol
94 */
95 for (len = 0, p = s; *p; ++p)
96 ++len;
97
98 found = 0;
99 for (sp = toc_syms; sp < &toc_syms[toc_nsyms]; ++sp) {
100 /*
101 * exact matches preferred
102 */
103 if (strcmp(sym_str(sp), s) == 0) {
104 found = sp;
105 break;
106 }
107 /*
108 * otherwise, prefices might interest us.
109 */
110 if (!found && (strncmp(sym_str(sp), s, len) == 0)) {
111 found = sp;
112 continue;
113 }
114 }
115
116 return found ? sym_flex(found) : 0;
117 }
118
119 /*
120 * sym_flex - convert a symbol so that there is no distinction between
121 * flex-string and non flex-string format.
122 *
123 * Input:
124 * sym - ^ to symbol table entry
125 *
126 * Returns:
127 * ^ to static location containing modified symbol.
128 */
129 sym_t *
130 sym_flex(sym)
131 sym_t *sym;
132 {
133 static sym_t symbol;
134 static char name[48];
135
136 strncpy(name, sym_str(sym), sizeof(name) - 1);
137
138 #ifndef __XCOFF64__
139 if (sym->n_zeroes != 0)
140 name[8] = 0; /* make sure that we truncate correctly */
141 symbol.n_zeroes = 0;
142 #endif
143
144 symbol = *sym;
145 symbol.n_nptr = name;
146
147 return &symbol;
148 }