Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpretor / faust-0.9.47mr3 / compiler / documentator / doc_lang.cpp
1 /************************************************************************
2 ************************************************************************
3 FAUST compiler
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
21
22
23 #include <iostream>
24 #include <fstream>
25 #include <set>
26 #include <string>
27 #include <time.h>
28 #include <cstdlib>
29 #include <errno.h>
30
31 #include "doc_lang.hh"
32 #include "doc_notice.hh"
33 #include "doc_autodoc.hh"
34 #include "doc_metadatas.hh"
35 #include "lateq.hh"
36 #include "enrobage.hh"
37 #include "compatibility.hh"
38
39
40
41 extern map<string, string> gDocNoticeStringMap;
42 extern set<string> gDocNoticeKeySet;
43
44 extern map<string, string> gDocAutodocStringMap;
45 extern set<string> gDocAutodocKeySet;
46
47 extern map<string, string> gDocMathStringMap;
48 extern set<string> gDocMathKeySet;
49
50 extern map<string, string> gDocMetadatasStringMap;
51 extern set<string> gDocMetadatasKeySet;
52
53 static const string gDocTextsDefaultFile = "mathdoctexts-default.txt";
54
55 static void importDocStrings(const string& filename);
56 static void getKey(string& s, string& key, size_t& pt1);
57 static void getText(string& s, size_t& pt1, string& text);
58 static void storePair(const string& key, const string& text);
59
60 static void printStringMapContent(map<string,string>& map, const string& name);
61
62 static istream* openArchFile (const string& filename);
63 static void getCurrentDir();
64 static int cholddir();
65
66 static string gCurrentDir; ///< Room to save current directory name.
67
68
69
70
71 /*****************************************************************************
72 Public functions
73 *****************************************************************************/
74
75
76 void loadTranslationFile(const string& lang)
77 {
78 initDocMath();
79 initDocNotice();
80 initDocAutodoc();
81 initDocMetadatas();
82
83 /** First ensure that the default file is loaded a least. */
84 importDocStrings(gDocTextsDefaultFile);
85
86 /** Then try and load the target file. */
87 if ( ! lang.empty() ) {
88 importDocStrings( "mathdoctexts-" + lang + ".txt" );
89 }
90 }
91
92
93
94 /*****************************************************************************
95 Static functions
96 *****************************************************************************/
97
98
99
100 /**
101 * @brief Feed the content of doc texts maps from a file.
102 *
103 * This mecchanism allows to load different files for translation.
104 *
105 * "mathdoctexts" files must have been formatted as follows :
106 * - a line beginning by ':' immediately declares a keyword,
107 * - a line beginning by '"' contains text until the last '"',
108 * - text can directly follow a keyword, if separated by one or
109 * many separator characters (space or tab).
110 * - a direct line break between two double quoted strings
111 * will insert a '\n' line break in the resulting notice string.
112 */
113 static void importDocStrings(const string& filename)
114 {
115 string s;
116 string key, text;
117 istream* file = openArchFile(filename);
118
119 while ( getline(*file, s) ) {
120 size_t pt1; // Text pointer.
121
122 /* The first character determines whether will follow a key or a text. */
123 switch (s[0]) {
124 case ':':
125 text = "";
126 getKey(s, key, pt1);
127 if (pt1==string::npos) continue;
128 break;
129 case '\"':
130 pt1 = 0;
131 break;
132 default:
133 continue;
134 }
135 getText(s, pt1, text);
136 storePair(key, text);
137 }
138 printStringMapContent(gDocNoticeStringMap, "gDocNoticeStringMap");
139 printStringMapContent(gDocAutodocStringMap, "gDocAutodocStringMap");
140 printStringMapContent(gDocMathStringMap, "gDocMathStringMap");
141 printStringMapContent(gDocMetadatasStringMap, "gDocMetadatasStringMap");
142 }
143
144
145 static void getKey(string& s, string& key, size_t& pt1)
146 {
147 /* Initialisation. */
148 key = "";
149 string separators = " \t";
150 size_t pk1 = 1;
151 size_t pk2 = s.find_first_of(separators);
152
153 /* Immediate '\n' after keyword case. */
154 if (pk2==string::npos) pk2 = s.size();
155
156 /* Capture and check the keyword. */
157 key = s.substr(pk1, pk2-1);
158
159 /* Prepare text capture. */
160 pt1 = s.find_first_of("\"", pk2);
161 }
162
163
164 static void getText(string& s, size_t& pt1, string& text)
165 {
166 /* Capture the text on the current line. */
167 size_t pt2;
168 pt2 = s.find_last_not_of("\"");
169 if (pt2!=string::npos) {
170 if (text.size() > 0) text += "\n"; // Handle line breaks.
171 text += s.substr(pt1+1, pt2-pt1);
172 }
173 }
174
175
176 static void storePair(const string& key, const string& text)
177 {
178 /* Store the current pair. */
179 if(!key.empty() && !text.empty()) {
180
181 if (gDocNoticeKeySet.find(key) != gDocNoticeKeySet.end()) {
182 gDocNoticeStringMap[key] = text;
183 }
184 else if (gDocAutodocKeySet.find(key) != gDocAutodocKeySet.end()) {
185 gDocAutodocStringMap[key] = text;
186 }
187 else if (gDocMathKeySet.find(key) != gDocMathKeySet.end()) {
188 gDocMathStringMap[key] = text;
189 }
190 else if (gDocMetadatasKeySet.find(key) != gDocMetadatasKeySet.end()) {
191 gDocMetadatasStringMap[key] = text;
192 }
193 else {
194 cerr << "Documentator : importDocStings : " << "warning : unknown key \"" << key << "\"" << endl;
195 }
196 //cerr << "gDocNoticeStringMap[\"" << key << "\"] = \"" << gDocNoticeStringMap[key] << "\"" << endl;
197 }
198 }
199
200
201 /**
202 * Simple trace function.
203 */
204 static void printStringMapContent(map<string,string>& m, const string& name) {
205 bool trace = false;
206 if(trace) {
207 cout << name << ".size() = " << m.size() << endl;
208 map<string,string>::iterator it;
209 int i = 1;
210 for(it = m.begin(); it!=m.end(); ++it)
211 cout << i++ << ".\t" << name << "[" << it->first << "] \t= '" << it->second << "'" << endl;
212 }
213 }
214
215
216
217
218 //------------------------ file managment -------------------------
219
220
221 /**
222 * Open architecture file.
223 */
224 static istream* openArchFile (const string& filename)
225 {
226 istream* file;
227 getCurrentDir(); // Save the current directory.
228 if ( (file = open_arch_stream(filename.c_str())) ) {
229 //cerr << "Documentator : openArchFile : Opening '" << filename << "'" << endl;
230 } else {
231 cerr << "ERROR : can't open architecture file " << filename << endl;
232 exit(1);
233 }
234 cholddir(); // Return to current directory.
235 return file;
236 }
237
238
239 /**
240 * Switch back to the previously stored current directory
241 */
242 static int cholddir ()
243 {
244 if (chdir(gCurrentDir.c_str()) == 0) {
245 return 0;
246 } else {
247 perror("cholddir");
248 exit(errno);
249 }
250 }
251
252
253 /**
254 * Get current directory and store it in gCurrentDir.
255 */
256 static void getCurrentDir ()
257 {
258 char buffer[FAUST_PATH_MAX];
259 gCurrentDir = getcwd (buffer, FAUST_PATH_MAX);
260 }
261
262