1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #pragma prototyped
23
24 /*
25 * catopen intercept
26 * the ast catalogs are checked first
27 * the ast mc* and native cat* routines do all the work
28 * catalogs found by mcfind() are converted from utf to ucs
29 *
30 * nl_catd is cast to void*
31 * this is either an Mc_t* (Mc_t.set != 0)
32 * or a Cc_t* where Cc_t.cat is the native nl_catd
33 */
34
35 #include <ast.h>
36 #include <mc.h>
37 #include <nl_types.h>
38 #include <iconv.h>
39
40 #ifndef DEBUG_trace
41 #define DEBUG_trace 0
42 #endif
43
44 #if _lib_catopen
45
46 #undef nl_catd
47 #undef catopen
48 #undef catgets
49 #undef catclose
50
51 typedef struct
52 {
53 Mcset_t* set;
54 nl_catd cat;
55 iconv_t cvt;
56 Sfio_t* tmp;
57 } Cc_t;
58
59 #else
60
61 #define _ast_nl_catd nl_catd
62 #define _ast_catopen catopen
63 #define _ast_catgets catgets
64 #define _ast_catclose catclose
65
66 #endif
67
68 _ast_nl_catd
_ast_catopen(const char * name,int flag)69 _ast_catopen(const char* name, int flag)
70 {
71 Mc_t* mc;
72 char* s;
73 Sfio_t* ip;
74 char path[PATH_MAX];
75
76 /*
77 * first try the ast catalogs
78 */
79
80 #if DEBUG_trace
81 sfprintf(sfstderr, "AHA#%d:%s %s\n", __LINE__, __FILE__, name);
82 #endif
83 if ((s = mcfind(path, NiL, name, LC_MESSAGES, flag)) && (ip = sfopen(NiL, s, "r")))
84 {
85 #if DEBUG_trace
86 sfprintf(sfstderr, "AHA#%d:%s %s\n", __LINE__, __FILE__, s);
87 #endif
88 mc = mcopen(ip);
89 sfclose(ip);
90 if (mc)
91 return (_ast_nl_catd)mc;
92 }
93 #if _lib_catopen
94 if (strcmp(setlocale(LC_MESSAGES, NiL), "debug"))
95 {
96 Cc_t* cc;
97 nl_catd d;
98
99 /*
100 * now the native catalogs
101 */
102
103 if (s && (d = catopen(s, flag)) != (nl_catd)(-1) || !(s = 0) && (d = catopen(name, flag)) != (nl_catd)(-1))
104 {
105 if (!(cc = newof(0, Cc_t, 1, 0)))
106 {
107 catclose(d);
108 return (_ast_nl_catd)(-1);
109 }
110 cc->cat = d;
111 if ((s || *name == '/') && (ast.locale.set & (1<<AST_LC_MESSAGES)))
112 {
113 if ((cc->cvt = iconv_open("", "utf")) == (iconv_t)(-1) || !(cc->tmp = sfstropen()))
114 {
115 catclose(d);
116 return (_ast_nl_catd)(-1);
117 }
118 }
119 else
120 cc->cvt = (iconv_t)(-1);
121 #if DEBUG_trace
122 sfprintf(sfstderr, "AHA#%d:%s %s %s native %p\n", __LINE__, __FILE__, s, name, cc->cat);
123 #endif
124 return (_ast_nl_catd)cc;
125 }
126 }
127 #endif
128
129 /*
130 * loser
131 */
132
133 return (_ast_nl_catd)(-1);
134 }
135
136 char*
_ast_catgets(_ast_nl_catd cat,int set,int num,const char * msg)137 _ast_catgets(_ast_nl_catd cat, int set, int num, const char* msg)
138 {
139 if (cat == (_ast_nl_catd)(-1))
140 return (char*)msg;
141 #if _lib_catopen
142 if (!((Cc_t*)cat)->set)
143 {
144 char* s;
145 size_t n;
146
147 msg = (char*)catgets(((Cc_t*)cat)->cat, set, num, msg);
148 if (((Cc_t*)cat)->cvt != (iconv_t)(-1))
149 {
150 s = (char*)msg;
151 n = strlen(s);
152 iconv_write(((Cc_t*)cat)->cvt, ((Cc_t*)cat)->tmp, &s, &n, NiL);
153 if (s = sfstruse(((Cc_t*)cat)->tmp))
154 return s;
155 }
156 return (char*)msg;
157 }
158 #endif
159 return mcget((Mc_t*)cat, set, num, msg);
160 }
161
162 int
_ast_catclose(_ast_nl_catd cat)163 _ast_catclose(_ast_nl_catd cat)
164 {
165 if (cat == (_ast_nl_catd)(-1))
166 return -1;
167 #if _lib_catopen
168 if (!((Cc_t*)cat)->set)
169 {
170 if (((Cc_t*)cat)->cvt != (iconv_t)(-1))
171 iconv_close(((Cc_t*)cat)->cvt);
172 if (((Cc_t*)cat)->tmp)
173 sfclose(((Cc_t*)cat)->tmp);
174 return catclose(((Cc_t*)cat)->cat);
175 }
176 #endif
177 return mcclose((Mc_t*)cat);
178 }
179