1 : /******* BEGIN LICENSE BLOCK *******
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
15 : * and László Németh (Hunspell). Portions created by the Initial Developers
16 : * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
17 : *
18 : * Contributor(s): László Németh (nemethl@gyorsposta.hu)
19 : * Caolan McNamara (caolanm@redhat.com)
20 : *
21 : * Alternatively, the contents of this file may be used under the terms of
22 : * either the GNU General Public License Version 2 or later (the "GPL"), or
23 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
24 : * in which case the provisions of the GPL or the LGPL are applicable instead
25 : * of those above. If you wish to allow use of your version of this file only
26 : * under the terms of either the GPL or the LGPL, and not to allow others to
27 : * use your version of this file under the terms of the MPL, indicate your
28 : * decision by deleting the provisions above and replace them with the notice
29 : * and other provisions required by the GPL or the LGPL. If you do not delete
30 : * the provisions above, a recipient may use your version of this file under
31 : * the terms of any one of the MPL, the GPL or the LGPL.
32 : *
33 : ******* END LICENSE BLOCK *******/
34 :
35 : #include <stdlib.h>
36 : #include <string.h>
37 : #include <ctype.h>
38 : #include <stdio.h>
39 :
40 : #include "dictmgr.hxx"
41 :
42 0 : DictMgr::DictMgr(const char * dictpath, const char * etype) : numdict(0)
43 : {
44 : // load list of etype entries
45 0 : pdentry = (dictentry *)malloc(MAXDICTIONARIES*sizeof(struct dictentry));
46 0 : if (pdentry) {
47 0 : if (parse_file(dictpath, etype)) {
48 0 : numdict = 0;
49 : // no dictionary.lst found is okay
50 : }
51 : }
52 0 : }
53 :
54 :
55 0 : DictMgr::~DictMgr()
56 : {
57 0 : dictentry * pdict = NULL;
58 0 : if (pdentry) {
59 0 : pdict = pdentry;
60 0 : for (int i=0;i<numdict;i++) {
61 0 : if (pdict->lang) {
62 0 : free(pdict->lang);
63 0 : pdict->lang = NULL;
64 : }
65 0 : if (pdict->region) {
66 0 : free(pdict->region);
67 0 : pdict->region=NULL;
68 : }
69 0 : if (pdict->filename) {
70 0 : free(pdict->filename);
71 0 : pdict->filename = NULL;
72 : }
73 0 : pdict++;
74 : }
75 0 : free(pdentry);
76 0 : pdentry = NULL;
77 0 : pdict = NULL;
78 : }
79 0 : numdict = 0;
80 0 : }
81 :
82 :
83 : // read in list of etype entries and build up structure to describe them
84 0 : int DictMgr::parse_file(const char * dictpath, const char * etype)
85 : {
86 :
87 : int i;
88 : char line[MAXDICTENTRYLEN+1];
89 0 : dictentry * pdict = pdentry;
90 :
91 : // open the dictionary list file
92 : FILE * dictlst;
93 0 : dictlst = fopen(dictpath,"r");
94 0 : if (!dictlst) {
95 0 : return 1;
96 : }
97 :
98 : // step one is to parse the dictionary list building up the
99 : // descriptive structures
100 :
101 : // read in each line ignoring any that dont start with etype
102 0 : while (fgets(line,MAXDICTENTRYLEN,dictlst)) {
103 0 : mychomp(line);
104 :
105 : /* parse in a dictionary entry */
106 0 : if (strncmp(line,etype,4) == 0) {
107 0 : if (numdict < MAXDICTIONARIES) {
108 0 : char * tp = line;
109 : char * piece;
110 0 : i = 0;
111 0 : while ((piece=mystrsep(&tp,' '))) {
112 0 : if (*piece != '\0') {
113 0 : switch(i) {
114 0 : case 0: break;
115 0 : case 1: pdict->lang = mystrdup(piece); break;
116 0 : case 2: if (strcmp (piece, "ANY") == 0)
117 0 : pdict->region = mystrdup("");
118 : else
119 0 : pdict->region = mystrdup(piece);
120 0 : break;
121 0 : case 3: pdict->filename = mystrdup(piece); break;
122 0 : default: break;
123 : }
124 0 : i++;
125 : }
126 0 : free(piece);
127 : }
128 0 : if (i == 4) {
129 0 : numdict++;
130 0 : pdict++;
131 : } else {
132 0 : switch (i) {
133 : case 3:
134 0 : free(pdict->region);
135 0 : pdict->region=NULL;
136 : case 2: //deliberate fallthrough
137 0 : free(pdict->lang);
138 0 : pdict->lang=NULL;
139 : default:
140 : break;
141 : }
142 0 : fprintf(stderr,"dictionary list corruption in line \"%s\"\n",line);
143 0 : fflush(stderr);
144 : }
145 : }
146 : }
147 : }
148 0 : fclose(dictlst);
149 0 : return 0;
150 : }
151 :
152 : // return text encoding of dictionary
153 0 : int DictMgr::get_list(dictentry ** ppentry)
154 : {
155 0 : *ppentry = pdentry;
156 0 : return numdict;
157 : }
158 :
159 :
160 :
161 : // strip strings into token based on single char delimiter
162 : // acts like strsep() but only uses a delim char and not
163 : // a delim string
164 :
165 0 : char * DictMgr::mystrsep(char ** stringp, const char delim)
166 : {
167 0 : char * rv = NULL;
168 0 : char * mp = *stringp;
169 0 : size_t n = strlen(mp);
170 0 : if (n > 0) {
171 0 : char * dp = (char *)memchr(mp,(int)((unsigned char)delim),n);
172 0 : if (dp) {
173 0 : *stringp = dp+1;
174 0 : size_t nc = dp - mp;
175 0 : rv = (char *) malloc(nc+1);
176 0 : if (rv) {
177 0 : memcpy(rv,mp,nc);
178 0 : *(rv+nc) = '\0';
179 : }
180 : } else {
181 0 : rv = (char *) malloc(n+1);
182 0 : if (rv) {
183 0 : memcpy(rv, mp, n);
184 0 : *(rv+n) = '\0';
185 0 : *stringp = mp + n;
186 : }
187 : }
188 : }
189 0 : return rv;
190 : }
191 :
192 :
193 : // replaces strdup with ansi version
194 0 : char * DictMgr::mystrdup(const char * s)
195 : {
196 0 : char * d = NULL;
197 0 : if (s) {
198 0 : int sl = strlen(s)+1;
199 0 : d = (char *) malloc(sl);
200 0 : if (d) memcpy(d,s,sl);
201 : }
202 0 : return d;
203 : }
204 :
205 :
206 : // remove cross-platform text line end characters
207 0 : void DictMgr:: mychomp(char * s)
208 : {
209 0 : int k = strlen(s);
210 0 : if ((k > 0) && ((*(s+k-1)=='\r') || (*(s+k-1)=='\n'))) *(s+k-1) = '\0';
211 0 : if ((k > 1) && (*(s+k-2) == '\r')) *(s+k-2) = '\0';
212 0 : }
213 :
|