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