Link with C++ linker
[oweals/cde.git] / cde / programs / nsgmls / ModeInfo.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: ModeInfo.C /main/1 1996/07/29 16:57:59 cde-hp $ */
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 <limits.h>
32 #include <stdlib.h>
33 #include "macros.h"
34 #include "types.h"
35 #include "Syntax.h"
36 #include "token.h"
37 #include "Sd.h"
38 #include "Mode.h"
39 #include "ModeInfo.h"
40
41 #ifdef SP_NAMESPACE
42 namespace SP_NAMESPACE {
43 #endif
44
45 const unsigned REQUIRE_SHORTTAG = 1;
46 const unsigned REQUIRE_CONCUR = 2;
47 const unsigned REQUIRE_LINK_OR_CONCUR = 4;
48 const unsigned REQUIRE_FLAGS = 7;
49
50 #define ULONG_BIT (CHAR_BIT * sizeof(unsigned long))
51
52 struct PackedTokenInfo {
53   Token token;                  // token to be returned
54   unsigned flags;
55   unsigned char contents[2];    // components of the delimiter or d-i-c
56   unsigned char modes[25];      // list of modes in which it is recognized,
57                                 // terminated by EOM
58   // a bit vector computed from modes (lo to hi)
59   unsigned long modeBits[(nModes + ULONG_BIT - 1)/ULONG_BIT];
60   void computeModeBits();
61   Boolean inMode(Mode mode) const;
62 };
63
64 const unsigned char SET = Syntax::nDelimGeneral;
65 const unsigned char FUNCTION = SET + Syntax::nSet;
66 const unsigned char NOTHING = UCHAR_MAX;
67
68 const unsigned char EOM = 255;  // end of modes
69
70 static PackedTokenInfo tokenTable[] = {
71   // Delimiters and delimiters in context
72   { tokenAnd, 0, { Syntax::dAND, NOTHING }, { grpMode, EOM }},
73   { tokenCom, 0, { Syntax::dCOM, NOTHING },
74     { mdMode, mdMinusMode, mdPeroMode, comMode, sdcomMode, EOM }},
75   { tokenCroDigit, 0, { Syntax::dCRO, SET + Syntax::digit },
76     { econMode, mconMode, rcconMode, econnetMode, mconnetMode, rcconnetMode,
77       rcconeMode, plitMode, plitaMode, pliteMode, sdplitMode, sdplitaMode,
78       alitMode, alitaMode, aliteMode,
79       talitMode, talitaMode, taliteMode, rcmsMode, EOM }},
80   { tokenCroNameStart, 0, { Syntax::dCRO, SET + Syntax::nameStart },
81     { econMode, mconMode, rcconMode, econnetMode, mconnetMode, rcconnetMode,
82       rcconeMode, plitMode, plitaMode, pliteMode, sdplitMode, sdplitaMode,
83       alitMode, alitaMode, aliteMode,
84       talitMode, talitaMode, taliteMode, rcmsMode, EOM }},
85   { tokenDsc, 0, { Syntax::dDSC, NOTHING },
86     { /* mdMode, */ asMode, dsMode, EOM }},
87   { tokenDso, 0, { Syntax::dDSO, NOTHING }, { mdMode, EOM }},
88   { tokenDtgc, 0, { Syntax::dDTGC, NOTHING }, { grpMode, EOM }},
89   { tokenDtgo, 0, { Syntax::dDTGO, NOTHING }, { grpMode, EOM }},
90   { tokenEroNameStart, 0, { Syntax::dERO, SET + Syntax::nameStart },
91     { econMode, mconMode, rcconMode, econnetMode, mconnetMode, rcconnetMode,
92       rcconeMode, alitMode, alitaMode, aliteMode, talitMode, talitaMode,
93       taliteMode, rcmsMode, EOM }},
94   { tokenEroGrpo, REQUIRE_LINK_OR_CONCUR, { Syntax::dERO, Syntax::dGRPO },
95     { econMode, mconMode, rcconMode, econnetMode, mconnetMode, rcconnetMode,
96       rcconeMode, alitMode, alitaMode, aliteMode, talitMode, talitaMode,
97       taliteMode, rcmsMode, EOM }},
98   { tokenEtago, 0, { Syntax::dETAGO, NOTHING }, { tagMode, EOM }},
99   { tokenEtagoNameStart, 0, { Syntax::dETAGO, SET + Syntax::nameStart },
100     { econMode, mconMode, cconMode, rcconMode,
101       econnetMode, mconnetMode, cconnetMode, rcconnetMode, EOM }},
102   { tokenEtagoTagc, REQUIRE_SHORTTAG, { Syntax::dETAGO, Syntax::dTAGC },
103     { econMode, mconMode, cconMode, rcconMode,
104       econnetMode, mconnetMode, cconnetMode, rcconnetMode, EOM }},
105   { tokenEtagoGrpo, REQUIRE_CONCUR, { Syntax::dETAGO, Syntax::dGRPO },
106     { econMode, mconMode, cconMode, rcconMode,
107       econnetMode, mconnetMode, cconnetMode, rcconnetMode, EOM }},
108   { tokenGrpc, 0, { Syntax::dGRPC, NOTHING }, { grpMode, EOM }},
109   { tokenGrpo, 0, { Syntax::dGRPO, NOTHING },
110     { mdMode, mdMinusMode, grpMode, EOM }},
111   { tokenLit, 0, { Syntax::dLIT, NOTHING },
112     { alitMode, talitMode, plitMode, sdplitMode, mlitMode, slitMode,
113       asMode, tagMode, mdMode, grpMode, EOM }},
114   { tokenLita, 0, { Syntax::dLITA, NOTHING },
115     { alitaMode, talitaMode, plitaMode, sdplitaMode, mlitaMode, slitaMode,
116       asMode, tagMode, mdMode, grpMode, EOM }},
117   { tokenMdc, 0, { Syntax::dMDC, NOTHING }, { mdMode, EOM }},
118   { tokenMdoNameStart, 0, { Syntax::dMDO, SET + Syntax::nameStart },
119     { econMode, mconMode, econnetMode, mconnetMode,
120       proMode, dsMode, dsiMode, EOM }},
121   { tokenMdoMdc, 0, { Syntax::dMDO, Syntax::dMDC },
122     { econMode, mconMode, econnetMode, mconnetMode,
123       proMode, dsMode, dsiMode, EOM }},
124   { tokenMdoCom, 0, { Syntax::dMDO, Syntax::dCOM },
125     { econMode, mconMode, econnetMode, mconnetMode,
126       proMode, dsMode, dsiMode, EOM }},
127   { tokenMdoDso, 0, { Syntax::dMDO, Syntax::dDSO },
128     { econMode, mconMode, econnetMode, mconnetMode,
129       dsMode, dsiMode, imsMode, EOM }},
130   { tokenMinus, 0, { Syntax::dMINUS, NOTHING }, { mdMinusMode, EOM }},
131   { tokenMinusGrpo, 0, { Syntax::dMINUS, Syntax::dGRPO }, { mdMode, EOM }},
132   { tokenMscMdc, 0, { Syntax::dMSC, Syntax::dMDC},
133     { imsMode, cmsMode, rcmsMode,
134       econMode, mconMode, econnetMode, mconnetMode, dsMode, dsiMode, EOM }},
135   { tokenNet, 0, { Syntax::dNET, NOTHING },
136     { econnetMode, mconnetMode, cconnetMode, rcconnetMode, tagMode, EOM }},
137   { tokenOpt, 0, { Syntax::dOPT, NOTHING }, { grpMode, grpsufMode, EOM }},
138   { tokenOr, 0, { Syntax::dOR, NOTHING }, { grpMode, EOM }},
139   { tokenPero, 0, { Syntax::dPERO, NOTHING }, { mdPeroMode, EOM }},
140   { tokenPeroNameStart, 0, { Syntax::dPERO, SET + Syntax::nameStart }, {
141     mdMode, mdMinusMode, mdPeroMode, dsMode, dsiMode, grpMode,
142     plitMode, plitaMode, pliteMode, sdplitMode, sdplitaMode, EOM }},
143   { tokenPeroGrpo, REQUIRE_LINK_OR_CONCUR, { Syntax::dPERO, Syntax::dGRPO },
144     { mdMode, mdMinusMode, mdPeroMode, dsMode, dsiMode, grpMode,
145       plitMode, plitaMode, pliteMode, sdplitMode, sdplitaMode, EOM }},
146   { tokenPic, 0, { Syntax::dPIC, NOTHING }, { piMode, EOM }},
147   { tokenPio, 0, { Syntax::dPIO, NOTHING },
148     { econMode, mconMode, econnetMode, mconnetMode, proMode,
149       dsMode, dsiMode, EOM }},
150   { tokenPlus, 0, { Syntax::dPLUS, NOTHING }, { grpMode, grpsufMode, EOM }},
151   { tokenPlusGrpo, 0, { Syntax::dPLUS, Syntax::dGRPO }, { mdMode, EOM }},
152   { tokenRefc, 0, { Syntax::dREFC, NOTHING }, { refMode, EOM }},
153   { tokenRep, 0, { Syntax::dREP, NOTHING }, { grpMode, grpsufMode, EOM }},
154   { tokenRni, 0, { Syntax::dRNI, NOTHING },
155     { grpMode, mdMode, mdPeroMode, EOM }},
156   { tokenSeq, 0, { Syntax::dSEQ, NOTHING }, { grpMode, EOM }},
157   { tokenStago, 0, { Syntax::dSTAGO, NOTHING }, { tagMode, EOM }},
158   { tokenStagoNameStart, 0, { Syntax::dSTAGO, SET + Syntax::nameStart },
159     { econMode, mconMode, econnetMode, mconnetMode, EOM }},
160   { tokenStagoTagc, REQUIRE_SHORTTAG, { Syntax::dSTAGO, Syntax::dTAGC },
161     { econMode, mconMode, econnetMode, mconnetMode, EOM }},
162   { tokenStagoGrpo, REQUIRE_CONCUR, { Syntax::dSTAGO, Syntax::dGRPO },
163     { econMode, mconMode, econnetMode, mconnetMode, EOM }},
164   { tokenTagc, 0, { Syntax::dTAGC, NOTHING }, { tagMode, EOM }},
165   { tokenVi, 0, { Syntax::dVI, NOTHING }, { tagMode, asMode, EOM }},
166   // Other tokens
167   { tokenRe, 0, { FUNCTION + Syntax::fRE, NOTHING },
168     { mconMode, cconMode, rcconMode,
169       mconnetMode, cconnetMode, rcconnetMode,
170       rcconeMode, cmsMode, rcmsMode, refMode,
171       mlitMode, mlitaMode, alitMode, alitaMode, aliteMode,
172       talitMode, talitaMode, taliteMode,
173       EOM }},
174   { tokenRs, 0, { FUNCTION + Syntax::fRS, NOTHING },
175     { mconMode, cconMode, rcconMode,
176       mconnetMode, cconnetMode, rcconnetMode,
177       rcconeMode, cmsMode, rcmsMode,
178       mlitMode, mlitaMode, alitMode, alitaMode, aliteMode,
179       talitMode, talitaMode, taliteMode,
180       EOM }},
181   { tokenSpace, 0, { FUNCTION + Syntax::fSPACE, NOTHING },
182     { mlitMode, mlitaMode, talitMode, talitaMode, taliteMode, EOM }},
183   { tokenSepchar, 0, { SET + Syntax::sepchar, NOTHING },
184     { alitMode, alitaMode, aliteMode,
185       talitMode, talitaMode, taliteMode, EOM }},
186   { tokenS, 0, { SET + Syntax::s, NOTHING },
187     { econMode, econnetMode, grpMode, mdMode, mdMinusMode, mdPeroMode,
188       proMode, dsMode, dsiMode, asMode, tagMode, EOM }},
189   { tokenNameStart, 0, { SET + Syntax::nameStart, NOTHING },
190     { grpMode, mdMode, mdMinusMode, mdPeroMode,
191       asMode, tagMode, EOM }},
192   { tokenDigit, 0, { SET + Syntax::digit, NOTHING },
193     { grpMode, mdMode, mdMinusMode, asMode, tagMode, EOM }},
194   { tokenLcUcNmchar, 0, { SET + Syntax::nmchar, NOTHING },
195     { grpMode, mdMode, asMode, tagMode, EOM }},
196   { tokenIgnoredChar, 0, { SET + Syntax::sgmlChar, NOTHING },
197     { imsMode, EOM }},
198   { tokenChar, 0, { SET + Syntax::sgmlChar, NOTHING },
199     // Note that character data is recognized in element content,
200     // and will cause #PCDATA to begin.
201     { alitMode, alitaMode, aliteMode,
202       talitMode, talitaMode, taliteMode,
203       comMode, piMode,
204       cmsMode, rcmsMode,
205       plitMode, plitaMode, pliteMode,
206       slitMode, slitaMode,
207       econMode, mconMode, cconMode, rcconMode,
208       econnetMode, mconnetMode, cconnetMode, rcconnetMode, rcconeMode, EOM }},
209   { tokenChar, 0, { SET + Syntax::minimumData, NOTHING },
210     { mlitMode, mlitaMode, EOM }},
211   { tokenChar, 0, { SET + Syntax::significant, NOTHING },
212     { sdplitMode, sdplitaMode, sdcomMode, EOM }},
213 };
214
215 inline Boolean PackedTokenInfo::inMode(Mode mode) const
216 {
217   return ((modeBits[unsigned(mode) / ULONG_BIT]
218            & ((unsigned long)1 << (unsigned(mode) % ULONG_BIT)))
219           != 0);
220 }
221
222 void PackedTokenInfo::computeModeBits()
223 {
224   for (unsigned char *p = modes; *p != EOM; p++)
225     modeBits[*p / ULONG_BIT] |= (unsigned long)1 << (*p % ULONG_BIT);
226 }
227
228 struct TokenTableIniter {
229   TokenTableIniter();
230 };
231
232 static TokenTableIniter tokenTableIniter;
233
234 TokenTableIniter::TokenTableIniter()
235 {
236   for (size_t i = 0; i < SIZEOF(tokenTable); i++)
237     tokenTable[i].computeModeBits();
238 }
239
240 ModeInfo::ModeInfo(Mode mode, const Sd &sd)
241 : mode_(mode), p_(tokenTable), count_(SIZEOF(tokenTable)),
242   missingRequirements_(REQUIRE_FLAGS)
243 {
244   if (sd.shorttag())
245     missingRequirements_ &= ~REQUIRE_SHORTTAG;
246   if (sd.concur())
247     missingRequirements_ &= ~(REQUIRE_CONCUR|REQUIRE_LINK_OR_CONCUR);
248   if (sd.link())
249     missingRequirements_ &= ~REQUIRE_LINK_OR_CONCUR;
250 }
251   
252 Boolean ModeInfo::nextToken(TokenInfo *t)
253 {
254   for (; count_ > 0; --count_, ++p_)
255     if (p_->inMode(mode_) && (p_->flags & missingRequirements_) == 0) {
256       t->token = p_->token;
257       t->priority = Priority::delim;
258       const unsigned char *contents = p_->contents;
259       --count_;
260       ++p_;
261       unsigned char c = contents[0];
262       if (c < SET)
263         t->delim1 = Syntax::DelimGeneral(c);
264       else if (c < SET + Syntax::nSet) {
265         t->set = Syntax::Set(c - SET);
266         t->type = TokenInfo::setType;
267         switch (t->set) {
268         case Syntax::sepchar:
269         case Syntax::s:
270         case Syntax::blank:
271           t->priority = Priority::function;
272           break;
273         default:
274           t->priority = Priority::data;
275           break;
276         }
277         return 1;
278       }
279       else {
280         t->function = Syntax::StandardFunction(c - FUNCTION);
281         t->priority = Priority::function;
282         t->type = TokenInfo::functionType;
283         return 1;
284       }
285       c = contents[1];
286       if (c == NOTHING) {
287         t->type = TokenInfo::delimType;
288         return 1;
289       }
290       if (c < SET) {
291         t->delim2 = Syntax::DelimGeneral(c);
292         t->type = TokenInfo::delimDelimType;
293         return 1;
294       }
295       if (c < SET + Syntax::nSet) {
296         t->set = Syntax::Set(c - SET);
297         t->type = TokenInfo::delimSetType;
298         return 1;
299       }
300       abort();
301     }
302   return 0;
303 }
304
305 #ifdef SP_NAMESPACE
306 }
307 #endif