Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / programs / dthelp / parser / pass1 / util / context.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 libraries 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: context.c /main/3 1995/11/08 10:29:06 rswiston $ */
24 /*
25               Copyright 1986 Tandem Computers Incorporated.
26 This product and information is proprietary of Tandem Computers Incorporated.
27                Copyright (c) 1986, 1987, 1988, 1989 Hewlett-Packard Co.
28 */
29
30 /*
31 Context.c contains the main procedure for program CONTEXT.
32
33 CONTEXT builds scanning and parsing tables for a simple
34 state-transition recognizer.  Input consists of two files, delimiter
35 declarations in file "delim.dat" and state tables with corresponding
36 actions in file "context.dat". If a parameter is present on the
37 command line, a sparse matrix technique is used to encode some of the
38 output arrays.
39
40 Data lines in "delim.dat" contain the name of the delimiter followed
41 by the text of the delimiter (one or more non-white space
42 characters).  The delimiter name must begin in the first column.  
43 Lines with white-space in the first column are considered comments.
44
45 Data in "context.dat" consists of free-form multi-line declarations.
46 Each declaration is terminated by a semi-colon. It begins with the
47 name of a token followed by any number of pairs of contexts (parser
48 states).  The context pairs are separated by a colon and may
49 optionally be followed by some C code enclosed in braces.  In each
50 pair, the first context is one in which the delimiter is recognized,
51 the second is the state that will result from an occurrence of the
52 delimiter in the first context. If code is specified, it is to be
53 executed by the parser when the delimiter occurs in the first context
54 of the pair. If successive pairs of contexts are separated by a
55 comma, code which follows is common to all the pairs.
56
57 The tokens specified in "context.dat" can either be delimiters defined in
58 "delim.dat" or other tokens (e.g., number, name, end_of_file) that will
59 be recognized by the user-defined scanner.
60
61 For example, suppose "delim.dat" contains the line
62
63                grpo (
64
65 and "context.dat" includes
66
67                grpo element:namegroup
68                     content:model {openmod() ;}
69                     excon:openex
70                     pcon:type ;
71
72                name namegroup:namesep {eltname() ;}
73                     model:connector,
74                     model2:connector
75                       {storemod(nstring) ;}
76
77 These declarations specify that the "grpo" delimiter is "(" and is
78 recognized in contexts "element", "content", "excon", and "pcon". 
79 Procedure openmod() is called when "grpo" occurs in "content" and,
80 beyond the state change, no code is executed in other contexts when
81 "grpo" occurs.  The "name" token is valid in contexts "namegroup",
82 "model", and "model2"; in the first, the context is set to "namesep"
83 and procedure eltname() is called, in the last two, the context is
84 set to "connector" and storemod(nstring) is called.
85
86 The program has several output files: case.c, delim.h, context.h, and
87 error.  Case.c contains nested switch statements to execute the code
88 specified with the context transitions.  Delim.h contains C
89 declarations related to delimiters; context.h has declarations
90 related to contexts.  Programs that include delim.h should define
91 M_DELIMDEF for definition form of the declarations and not define it
92 for the declaration form.  Programs that include context.h should
93 define M_CONDEF analogously.
94
95 The program numbers the delimiter names and the contexts as
96 encountered and outputs corresponding #define instructions with all
97 letters in the names forced to uppercase to delim.h and context.h.
98 In addition, an array named for each delimiter (with all letters
99 forced to lowercase) is initialized to the delimiter text.  The first
100 declaration in the above example, for instance, would result in the
101 following lines written to delim.h:
102
103                #define GRPO 1
104                M_DELIMEXTERN char grpo[] M_DELIMINIT("(") ;
105
106 These lines would be written to context.h:
107
108                #define ELEMENT 1
109                #define NAMEGROUP 2
110                #define CONTENT 3
111                #define MODEL 4
112                #define EXCON 5
113                #define OPENEX 6
114                #define PCON 7
115                #define TYPE 8
116                #define NAMESEP 9
117                #define CONNECTOR 10
118                #define MODEL2 11
119
120 Delim.h also contains an array, m_dlmptr, which contains pointers to the
121 names of all the defined delimiters.  In addition, delim.h contains the
122 declaration of a tree representation of the delimiters allowed in each
123 context. Internally, the program represents the delimiter strings with a
124 tree.  The children of the root of this tree represent the set of characters
125 with which delimiters can start. Children of other nodes represent
126 characters that can follow the character of their parent.  Leaf nodes
127 are associated with the null character, indicating the end of a
128 delimiter.  A path from the root to a leaf thus represents a valid
129 delimiter.
130
131 The form in which the tree is represented within this program is not
132 quite the same as the output data structure.  In the latter, each
133 element consists of a flag called 'more' indicating whether it is the last
134 child of its parent; a character, called 'symbol'; and an integer,
135 called 'index'. All sons of a node are stored in adjacent elements
136 ordered in increaing value of their 'symbol' fields. 'Symbol'
137 contains the character associated with the node (0 if the node is a
138 leaf node), with the sign bit turned on if the node is the last child
139 of its parent.  'Index' contains the array index of the first son of
140 the node, if the node is not a leaf.  If the node is a leaf, 'index'
141 is the number of the represented delimiter (i.e., 1 for "grpo" in the
142 above example).
143
144 As the tree is constructed, it is not feasible to store brothers in adjacent
145 elements, so the internal data structure is different.  It contains a 'next'
146 field which points to the first brother of a given node. Because the 'next'
147 field can be used to detect the last child of a parent, it is not necessary
148 to use the sign bit of 'symbol' to indicate this special case.
149
150 Two other arrays are written to context.h.  Contree[i] points to the root
151 of the delimiter tree for the ith context within the array tree whose
152 declaration is in delim.h; nextcon[i][j] indicates the state
153 resulting from an occurrence of delimiter j+1 in state i+1.  Finally,
154 a #define of MAXD to the length of the longest delimiter is written to
155 delim.h.
156 */
157
158 #include <stdlib.h>
159 #include <stdio.h>
160 #include <stdlib.h>
161 #include "basic.h"
162 #include "trie.h"
163
164 #include "common.h"
165 #include "chartype.h"
166 #define CONTDEF 1
167 #include "cont.h"
168
169 /* Main procedure */
170 int main(int argc, char **argv)
171 {
172 int n ;
173
174 m_openchk(&delim, "delim.h", "w") ;
175 m_openchk(&context, "context.h", "w") ;
176 m_openchk(&fcase, "case.c", "w") ;
177 m_openchk(&cdat, "context.dat", "r") ;
178 m_openchk(&ddat, "delim.dat", "r") ;
179 m_openchk(&m_errfile, "error", "w") ;
180 fputs("    switch(m_token) {\n", fcase) ; /* keep the "}" balanced */
181
182 fputs("#if defined(M_DELIMDEF)\n", delim) ;
183 fputs("#define M_DELIMEXTERN\n", delim) ;
184 fputs("#define M_DELIMINIT(a) = a\n", delim) ;
185 fputs("#else\n", delim) ;
186 fputs("#define M_DELIMEXTERN extern\n", delim) ;
187 fputs("#define M_DELIMINIT(a)\n", delim) ;
188 fputs("#endif\n\n", delim) ;
189
190 fputs("#if defined(M_CONDEF)\n", context) ;
191 fputs("#define M_CONEXTERN\n", context) ;
192 fputs("#else\n", context) ;
193 fputs("#define M_CONEXTERN extern\n", context) ;
194 fputs("#endif\n\n", context) ;
195
196 contree = (M_TRIE **) calloc(NUMCON, sizeof(M_TRIE *)) ;
197 xtransit = (int *) calloc(NUMCON * NUMDELIM, sizeof(int)) ;
198 contexts = (M_WCHAR **) calloc(NUMCON, sizeof(char *)) ;
199 dlmptr = (char**) calloc(NUMDELIM, sizeof(char*)) ;
200
201 loaddelim() ;
202 while (getdname())
203     {
204     casestarted = FALSE ;
205     while ((n = getContext()) >= 0)
206         {
207         if (withdelim) enterdelim(n) ;
208         getcolon() ;
209         if (transit(n, curdelim))
210             {
211             if (! withdelim) 
212                 {
213                 char *mb_dname, *mb_contexts;
214
215                 mb_dname = MakeMByteString(dname);
216                 mb_contexts = MakeMByteString(contexts[n]);
217                 warning2(
218                     "Duplicate assignment to token \"%s\" in context \"%s\"",
219                          mb_dname,
220                          mb_contexts) ;
221                 m_free(mb_dname,"multi-byte string");
222                 m_free(mb_contexts,"multi-byte string");
223                 }
224             }
225         transit(n, curdelim) = getContext() + 1 ;
226         getcode(n) ;
227         }
228     if (casestarted)
229         {
230         fprintf(fcase, "          default:\n            break ;\n") ;
231         /* keep the "{" balanced */
232         fprintf(fcase, "          }\n        break ;\n") ;
233         }
234     }
235 /* keep the "{" balanced */
236 fprintf(fcase, "      default:\n        break ;\n      }\n") ;
237 fprintf(context, "#define MAXD %d\n", maxd) ;
238 dumptree((LOGICAL) (argc > 1)) ;
239 fprintf(stderr, "NUMCON set to %d\n", NUMCON) ;
240 fprintf(stderr, "NUMDELIM set to %d\n", NUMDELIM) ;
241 exit(errexit) ;
242 }