Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / nsgmls / Syntax.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: Syntax.C /main/2 1996/08/12 13:22:19 mgreess $ */
24 // Copyright (c) 1994 James Clark
25 // See the file COPYING for copying permission.
26
27 #ifdef __GNUG__
28 #pragma implementation
29 #endif
30 #include "splib.h"
31 #include "Syntax.h"
32 #include "Sd.h"
33 #include "CharsetInfo.h"
34 #include "ISetIter.h"
35 #include "macros.h"
36 #include "MarkupScan.h"
37 #include "constant.h"
38
39 #ifdef SP_NAMESPACE
40 namespace SP_NAMESPACE {
41 #endif
42
43 const int Syntax::referenceQuantity_[] = {
44   40,
45   960,
46   960,
47   16,
48   16,
49   16,
50   32,
51   96,
52   16,
53   240,
54   8,
55   2,
56   240,
57   960,
58   24
59 };
60
61 Syntax::Syntax(const Sd &sd)
62 : generalSubst_(0),
63   entitySubst_(0),
64   categoryTable_(otherCategory),
65   shuncharControls_(0),
66   multicode_(0),
67   markupScanTable_(MarkupScan::normal)
68 {
69   static const char lcletter[] = "abcdefghijklmnopqrstuvwxyz";
70   static const char ucletter[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
71   int i;
72   for (i = 0; i < 26; i++) {
73     Char lc = sd.execToDoc(lcletter[i]);
74     Char uc = sd.execToDoc(ucletter[i]); 
75     set_[nameStart] += lc;
76     set_[nameStart] += uc;
77     set_[minimumData] += lc;
78     set_[minimumData] += uc;
79     set_[significant] += lc;
80     set_[significant] += uc;
81     categoryTable_.setChar(lc, nameStartCategory);
82     categoryTable_.setChar(uc, nameStartCategory);
83     subst(lc, uc);
84   }
85   static const char digits[] = "0123456789";
86   for (i = 0; i < 10; i++) {
87     Char c = sd.execToDoc(digits[i]);
88     set_[digit] += c;
89     set_[minimumData] += c;
90     set_[significant] += c;
91     categoryTable_.setChar(c, digitCategory);
92   }
93   static const char special[] = "'()+,-./:=?";
94   for (i = 0; special[i] != '\0'; i++) {
95     Char c = sd.execToDoc(special[i]);
96     set_[minimumData] += c;
97     set_[significant] += c;
98   }
99   for (i = 0; i < nQuantity; i++)
100     quantity_[i] = referenceQuantity_[i];
101   for (i = 0; i < 3; i++)
102     standardFunctionValid_[i] = 0;
103 }
104
105
106 Syntax::Syntax(const Syntax & syn)
107         : generalSubst_(syn.generalSubst_),
108           entitySubst_(syn.entitySubst_),
109           shunchar_(syn.shunchar_),
110           shuncharControls_(syn.shuncharControls_),
111           namecaseGeneral_(syn.namecaseGeneral_),
112           namecaseEntity_(syn.namecaseEntity_),
113           delimShortrefComplex_(syn.delimShortrefComplex_),
114           delimShortrefSimple_(syn.delimShortrefSimple_),
115           nameTable_(syn.nameTable_),
116           functionTable_(syn.functionTable_),
117           upperSubst_(syn.upperSubst_),
118           identitySubst_(syn.identitySubst_),
119           categoryTable_(syn.categoryTable_),
120           multicode_(syn.multicode_),
121           markupScanTable_(syn.markupScanTable_)
122 {
123   int i;
124
125   for (i = 0; i < nSet; i++)
126     set_[i] = syn.set_[i];
127
128   for (i = 0; i < 3; i++) {
129     standardFunction_[i] = syn.standardFunction_[i];
130     standardFunctionValid_[i] = syn.standardFunctionValid_[i];
131   }
132
133   for (i = 0; i < nDelimGeneral; i++)
134     delimGeneral_[i] = syn.delimGeneral_[i];
135
136   for (i = 0; i < nNames; i++)
137     names_[i] = syn.names_[i];
138
139   for (i = 0; i < nQuantity; i++)
140     quantity_[i] = syn.quantity_[i];
141 }
142
143 void Syntax::addNameCharacters(const ISet<Char> &set)
144 {
145   ISetIter<Char> iter(set);
146   Char min, max;
147   while (iter.next(min, max)) {
148     set_[nmchar].addRange(min, max);
149     set_[significant].addRange(min, max);
150     categoryTable_.setRange(min, max, otherNameCategory);
151   }
152 }
153
154 void Syntax::addNameStartCharacters(const ISet<Char> &set)
155 {
156   ISetIter<Char> iter(set);
157   Char min, max;
158   while (iter.next(min, max)) {
159     set_[nameStart].addRange(min, max);
160     set_[significant].addRange(min, max);
161     categoryTable_.setRange(min, max, nameStartCategory);
162   }
163 }
164
165 void Syntax::addSubst(Char lc, Char uc)
166 {
167   subst(lc, uc);
168 }
169
170 void Syntax::setStandardFunction(StandardFunction f, Char c)
171 {
172   standardFunction_[f] = c;
173   standardFunctionValid_[f] = 1;
174   set_[minimumData] += c;
175   set_[s] += c;
176   categoryTable_.setChar(c, sCategory);
177   set_[functionChar] += c;
178   set_[significant] += c;
179   switch (f) {
180   case fSPACE:
181     set_[blank] += c;
182     break;
183   case fRE:
184   case fRS:
185     break;
186   }
187 }
188
189 void Syntax::enterStandardFunctionNames()
190 {
191   static ReservedName name[3] = {
192     rRE, rRS, rSPACE
193   };
194   for (int i = 0; i < 3; i++)
195     if (standardFunctionValid_[i])
196       functionTable_.insert(reservedName(name[i]), standardFunction_[i]);
197 }
198
199 void Syntax::setDelimGeneral(int i, const StringC &str)
200 {
201   delimGeneral_[i] = str;
202   for (size_t j = 0; j < str.size(); j++)
203     set_[significant] += str[j];
204 }
205
206 void Syntax::addDelimShortref(const StringC &str, const CharsetInfo &charset)
207 {
208   if (str.size() == 1 && str[0] != charset.execToDesc('B') && !isB(str[0]))
209     delimShortrefSimple_.add(str[0]);
210   else
211     delimShortrefComplex_.push_back(str);
212   for (size_t i = 0; i < str.size(); i++)
213     set_[significant] += str[i];
214 }
215
216 void Syntax::addDelimShortrefs(const ISet<Char> &shortrefChars,
217                                const CharsetInfo &charset)
218 {
219   ISetIter<Char> blankIter(set_[blank]);
220   Char min, max;
221   StringC specialChars;
222   while (blankIter.next(min, max)) {
223     do {
224       specialChars += min;
225     } while (min++ != max);
226   }
227   specialChars += charset.execToDesc('B');
228   const ISet<Char> *simpleCharsPtr = &shortrefChars;
229   ISet<Char> simpleChars;
230   for (size_t i = 0; i < specialChars.size(); i++)
231     if (shortrefChars.contains(specialChars[i])) {
232       if (simpleCharsPtr != &simpleChars) {
233         simpleChars = shortrefChars;
234         simpleCharsPtr = &simpleChars;
235       }
236       simpleChars.remove(specialChars[i]);
237     }
238   ISetIter<Char> iter(*simpleCharsPtr);
239   while (iter.next(min, max)) {
240     delimShortrefSimple_.addRange(min, max);
241     set_[significant].addRange(min, max);
242   }
243 }
244
245 void Syntax::addFunctionChar(const StringC &str, FunctionClass fun, Char c)
246 {
247   switch (fun) {
248   case cFUNCHAR:
249     break;
250   case cSEPCHAR:
251     set_[s] += c;
252     categoryTable_.setChar(c, sCategory);
253     set_[blank] += c;
254     set_[sepchar] += c;
255     break;
256   case cMSOCHAR:
257     multicode_ = 1;
258     markupScanTable_.setChar(c, MarkupScan::out);
259     break;
260   case cMSICHAR:
261     // don't need to do anything special if we just have MSICHARs
262     markupScanTable_.setChar(c, MarkupScan::in);
263     break;
264   case cMSSCHAR:
265     multicode_ = 1;
266     markupScanTable_.setChar(c, MarkupScan::suppress);
267     break;
268   }
269   set_[functionChar] += c;
270   set_[significant] += c;
271   functionTable_.insert(str, c);
272 }
273
274 void Syntax::setName(int i, const StringC &str)
275 {
276   names_[i] = str;
277   nameTable_.insert(str, i);
278 }
279
280 void Syntax::setNamecaseGeneral(Boolean b)
281 {
282   namecaseGeneral_ = b;
283   generalSubst_ = b ? &upperSubst_ : &identitySubst_;
284 }
285
286 void Syntax::setNamecaseEntity(Boolean b)
287 {
288   namecaseEntity_ = b;
289   entitySubst_ = b ? &upperSubst_ : &identitySubst_;
290 }
291
292 void Syntax::subst(Char from, Char to)
293 {
294   upperSubst_.addSubst(from, to);
295 }
296
297 void Syntax::addShunchar(Char c)
298 {
299   shunchar_.add(c);
300 }
301
302 Boolean Syntax::lookupReservedName(const StringC &str,
303                                    ReservedName *result) const
304 {
305   const int *tem = nameTable_.lookup(str);
306   if (tem) {
307     *result = ReservedName(*tem);
308     return 1;
309   }
310   else
311     return 0;
312 }
313
314 Boolean Syntax::lookupFunctionChar(const StringC &name, Char *result) const
315 {
316   const Char *p = functionTable_.lookup(name);
317   if (p) {
318     *result = *p;
319     return 1;
320   }
321   else
322     return 0;
323 }
324
325 #ifdef __GNUG__
326 typedef HashTableIter<StringC,Char> Dummy_HashTableIter_StringC_Char;
327 #endif
328
329 Boolean Syntax::charFunctionName(Char c, const StringC *&name) const
330 {
331   HashTableIter<StringC,Char> iter(functionTable_);
332   const Char *cp;
333   while (iter.next(name, cp))
334     if (*cp == c)
335       return 1;
336   return 0;
337 }
338
339 Boolean Syntax::isValidShortref(const StringC &str) const
340 {
341   if (str.size() == 1 && delimShortrefSimple_.contains(str[0]))
342     return 1;
343   for (size_t i = 0; i < delimShortrefComplex_.size(); i++)
344     if (str == delimShortrefComplex_[i])
345       return 1;
346   return 0;
347 }
348
349 void Syntax::implySgmlChar(const CharsetInfo &docCharset)
350 {
351   docCharset.getDescSet(set_[sgmlChar]);
352   ISet<WideChar> invalid;
353   checkSgmlChar(docCharset, 0, invalid);
354   ISetIter<WideChar> iter(invalid);
355   WideChar min, max;
356   while (iter.next(min, max)) {
357     do {
358       if (min <= charMax)
359         set_[sgmlChar].remove(Char(min));
360     } while (min++ != max);
361   }
362 }
363
364 void Syntax::checkSgmlChar(const CharsetInfo &docCharset,
365                            const ::SP_NAMESPACE_SCOPE Syntax *otherSyntax,
366                            ISet<WideChar> &invalid) const
367 {
368   ISetIter<Char> iter(shunchar_);
369   Char min, max;
370   while (iter.next(min, max)) {
371     if (min <= max) {
372       do {
373         if (!set_[significant].contains(min)
374             && (!otherSyntax || !otherSyntax->set_[significant].contains(min))
375             && set_[sgmlChar].contains(min))
376           invalid += min;
377       } while (min++ != max);
378     }
379   }
380   if (shuncharControls_) {
381     UnivChar i;
382     for (i = 0; i < 32; i++)
383       checkUnivControlChar(i, docCharset, otherSyntax, invalid);
384     for (i = 127; i < 160; i++)
385       checkUnivControlChar(i, docCharset, otherSyntax, invalid);
386   }
387 }
388
389 void Syntax::checkUnivControlChar(UnivChar univChar,
390                                   const CharsetInfo &docCharset,
391                                   const ::SP_NAMESPACE_SCOPE Syntax *otherSyntax,
392                                   ISet<WideChar> &invalid) const
393 {
394   WideChar c;
395   ISet<WideChar> set;
396   switch (docCharset.univToDesc(univChar, c, set)) {
397   case 0:
398     break;
399   case 1:
400     set += c;
401     // fall through
402   default:
403     {
404       ISetIter<WideChar> iter(set);
405       WideChar min, max;
406       while (iter.next(min, max)) {
407         do {
408           if (min > charMax)
409             break;
410           Char ch = Char(min);
411           if (!set_[significant].contains(ch)
412               && (!otherSyntax
413                   || !otherSyntax->set_[significant].contains(ch))
414               && set_[sgmlChar].contains(ch))
415             invalid += ch;
416         } while (min++ != max);
417       }
418     }
419   }
420 }
421
422 StringC Syntax::rniReservedName(ReservedName i) const
423 {
424   StringC result = delimGeneral(dRNI);
425   result += reservedName(i);
426   return result;
427 }
428
429 const SubstTable<Char> &Syntax::upperSubstTable() const
430 {
431   return upperSubst_;
432 }
433
434 const StringC &Syntax::peroDelim() const
435 {
436   return delimGeneral(dPERO);
437 }
438
439
440 #ifdef SP_NAMESPACE
441 }
442 #endif