Branch data Line data Source code
1 : : /* do not edit automatically generated by mc from M2StackSpell. */
2 : : /* M2StackSpell.mod maintain a stack of scopes used in spell checks.
3 : :
4 : : Copyright (C) 2025 Free Software Foundation, Inc.
5 : : Contributed by Gaius Mulley <gaiusmod2@gmail.com>.
6 : :
7 : : This file is part of GNU Modula-2.
8 : :
9 : : GNU Modula-2 is free software; you can redistribute it and/or modify
10 : : it under the terms of the GNU General Public License as published by
11 : : the Free Software Foundation; either version 3, or (at your option)
12 : : any later version.
13 : :
14 : : GNU Modula-2 is distributed in the hope that it will be useful, but
15 : : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : : General Public License for more details.
18 : :
19 : : You should have received a copy of the GNU General Public License
20 : : along with GNU Modula-2; see the file COPYING3. If not see
21 : : <http://www.gnu.org/licenses/>. */
22 : :
23 : : #include "config.h"
24 : : #include "system.h"
25 : : #include "gcc-consolidation.h"
26 : :
27 : : #include <stdbool.h>
28 : : # if !defined (PROC_D)
29 : : # define PROC_D
30 : : typedef void (*PROC_t) (void);
31 : : typedef struct { PROC_t proc; } PROC;
32 : : # endif
33 : :
34 : : #if defined(__cplusplus)
35 : : # undef NULL
36 : : # define NULL 0
37 : : #endif
38 : : #define _M2StackSpell_C
39 : :
40 : : #include "GM2StackSpell.h"
41 : : # include "GSymbolTable.h"
42 : : # include "GSymbolKey.h"
43 : : # include "GDynamicStrings.h"
44 : : # include "GFormatStrings.h"
45 : : # include "GNameKey.h"
46 : : # include "GM2MetaError.h"
47 : : # include "GM2StackWord.h"
48 : : # include "GCDataTypes.h"
49 : : # include "Gm2spellcheck.h"
50 : :
51 : : static M2StackWord_StackOfWord DefaultStack;
52 : : static unsigned int PushCount;
53 : : static m2spellcheck_Candidates PushCandidate;
54 : :
55 : : /*
56 : : GetSpellHint - return a string describing a spelling hint.
57 : : */
58 : :
59 : : extern "C" DynamicStrings_String M2StackSpell_GetSpellHint (unsigned int unknown);
60 : :
61 : : /*
62 : : Push - push a scope onto the spelling stack.
63 : : sym might be a ModSym, DefImpSym or a varsym
64 : : of a record type denoting a with statement.
65 : : */
66 : :
67 : : extern "C" void M2StackSpell_Push (unsigned int sym);
68 : :
69 : : /*
70 : : Pop - remove the top scope from the spelling stack.
71 : : */
72 : :
73 : : extern "C" void M2StackSpell_Pop (void);
74 : :
75 : : /*
76 : : GetRecordField - return the record field containing fieldName.
77 : : An error is generated if the fieldName is not
78 : : found in record.
79 : : */
80 : :
81 : : extern "C" unsigned int M2StackSpell_GetRecordField (unsigned int tokno, unsigned int record, NameKey_Name fieldName);
82 : :
83 : : /*
84 : : PushName -
85 : : */
86 : :
87 : : static void PushName (unsigned int sym);
88 : :
89 : : /*
90 : : ForeachRecordFieldDo -
91 : : */
92 : :
93 : : static void ForeachRecordFieldDo (unsigned int record, SymbolKey_PerformOperation op);
94 : :
95 : : /*
96 : : PushCandidates -
97 : : */
98 : :
99 : : static unsigned int PushCandidates (m2spellcheck_Candidates cand, unsigned int sym);
100 : :
101 : : /*
102 : : CheckForHintStr - lookup a spell hint matching misspelt. If one exists
103 : : then append it to HintStr. Return HintStr.
104 : : */
105 : :
106 : : static DynamicStrings_String CheckForHintStr (unsigned int sym, DynamicStrings_String HintStr, DynamicStrings_String misspelt);
107 : :
108 : : /*
109 : : AddPunctuation - adds punct to the end of str providing that str is non NIL.
110 : : */
111 : :
112 : : static DynamicStrings_String AddPunctuation (DynamicStrings_String str, const char *punct_, unsigned int _punct_high);
113 : :
114 : : /*
115 : : Init -
116 : : */
117 : :
118 : : static void Init (void);
119 : :
120 : :
121 : : /*
122 : : PushName -
123 : : */
124 : :
125 : 2208 : static void PushName (unsigned int sym)
126 : : {
127 : 2208 : DynamicStrings_String str;
128 : :
129 : 2208 : str = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (sym)));
130 : 2208 : m2spellcheck_Push (PushCandidate, const_cast <const char * > (static_cast <char * > (DynamicStrings_string (str))));
131 : : /* str := KillString (str) */
132 : 2208 : PushCount += 1;
133 : 2208 : }
134 : :
135 : :
136 : : /*
137 : : ForeachRecordFieldDo -
138 : : */
139 : :
140 : 12 : static void ForeachRecordFieldDo (unsigned int record, SymbolKey_PerformOperation op)
141 : : {
142 : 12 : unsigned int i;
143 : 12 : unsigned int field;
144 : :
145 : 12 : i = 1;
146 : 36 : do {
147 : 36 : field = SymbolTable_GetNth (record, i);
148 : 36 : if (field != SymbolTable_NulSym)
149 : : {
150 : 24 : (*op.proc) (field);
151 : : }
152 : 36 : i += 1;
153 : 36 : } while (! (field == SymbolTable_NulSym));
154 : 12 : }
155 : :
156 : :
157 : : /*
158 : : PushCandidates -
159 : : */
160 : :
161 : 156 : static unsigned int PushCandidates (m2spellcheck_Candidates cand, unsigned int sym)
162 : : {
163 : 156 : PushCount = 0;
164 : 156 : PushCandidate = cand;
165 : 156 : if ((SymbolTable_IsModule (sym)) || (SymbolTable_IsDefImp (sym)))
166 : : {
167 : 144 : SymbolTable_ForeachProcedureDo (sym, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) PushName});
168 : 144 : SymbolTable_ForeachLocalSymDo (sym, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) PushName});
169 : : }
170 : 12 : else if (SymbolTable_IsEnumeration (sym))
171 : : {
172 : : /* avoid dangling else. */
173 : 0 : SymbolTable_ForeachFieldEnumerationDo (sym, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) PushName});
174 : : }
175 : 12 : else if (SymbolTable_IsRecord (sym))
176 : : {
177 : : /* avoid dangling else. */
178 : 12 : ForeachRecordFieldDo (sym, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) PushName});
179 : : }
180 : 156 : return PushCount;
181 : : /* static analysis guarentees a RETURN statement will be used before here. */
182 : : __builtin_unreachable ();
183 : : }
184 : :
185 : :
186 : : /*
187 : : CheckForHintStr - lookup a spell hint matching misspelt. If one exists
188 : : then append it to HintStr. Return HintStr.
189 : : */
190 : :
191 : 150 : static DynamicStrings_String CheckForHintStr (unsigned int sym, DynamicStrings_String HintStr, DynamicStrings_String misspelt)
192 : : {
193 : 150 : m2spellcheck_Candidates cand;
194 : 150 : const char * content;
195 : 150 : DynamicStrings_String str;
196 : :
197 : 150 : if (((((SymbolTable_IsModule (sym)) || (SymbolTable_IsDefImp (sym))) || (SymbolTable_IsProcedure (sym))) || (SymbolTable_IsRecord (sym))) || (SymbolTable_IsEnumeration (sym)))
198 : : {
199 : 150 : cand = m2spellcheck_InitCandidates ();
200 : 150 : if ((PushCandidates (cand, sym)) > 1)
201 : : {
202 : 150 : content = m2spellcheck_FindClosestCharStar (cand, const_cast <const char * > (static_cast <char * > (DynamicStrings_string (misspelt))));
203 : : }
204 : : else
205 : : {
206 : : content = static_cast<const char *> (NULL);
207 : : }
208 : 150 : m2spellcheck_KillCandidates (&cand);
209 : 150 : if (content != NULL)
210 : : {
211 : 36 : str = DynamicStrings_InitStringCharStar (static_cast <void *> (const_cast <char * > (content)));
212 : 36 : if (HintStr == NULL)
213 : : {
214 : 36 : return FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) ", did you mean %s", 17)), (const unsigned char *) &str, (sizeof (str)-1));
215 : : }
216 : : else
217 : : {
218 : 0 : return FormatStrings_Sprintf2 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "%s or %s", 8)), (const unsigned char *) &HintStr, (sizeof (HintStr)-1), (const unsigned char *) &str, (sizeof (str)-1));
219 : : }
220 : : }
221 : : }
222 : 114 : return HintStr;
223 : : /* static analysis guarentees a RETURN statement will be used before here. */
224 : : __builtin_unreachable ();
225 : : }
226 : :
227 : :
228 : : /*
229 : : AddPunctuation - adds punct to the end of str providing that str is non NIL.
230 : : */
231 : :
232 : 186 : static DynamicStrings_String AddPunctuation (DynamicStrings_String str, const char *punct_, unsigned int _punct_high)
233 : : {
234 : 186 : char punct[_punct_high+1];
235 : :
236 : : /* make a local copy of each unbounded array. */
237 : 186 : memcpy (punct, punct_, _punct_high+1);
238 : :
239 : 186 : if (str == NULL)
240 : : {
241 : : return static_cast<DynamicStrings_String> (NULL);
242 : : }
243 : : else
244 : : {
245 : 36 : return DynamicStrings_ConCat (str, DynamicStrings_Mark (DynamicStrings_InitString ((const char *) punct, _punct_high)));
246 : : }
247 : : /* static analysis guarentees a RETURN statement will be used before here. */
248 : : __builtin_unreachable ();
249 : 186 : }
250 : :
251 : :
252 : : /*
253 : : Init -
254 : : */
255 : :
256 : 15506 : static void Init (void)
257 : : {
258 : 0 : DefaultStack = M2StackWord_InitStackWord ();
259 : 0 : }
260 : :
261 : :
262 : : /*
263 : : GetSpellHint - return a string describing a spelling hint.
264 : : */
265 : :
266 : 186 : extern "C" DynamicStrings_String M2StackSpell_GetSpellHint (unsigned int unknown)
267 : : {
268 : 186 : unsigned int i;
269 : 186 : unsigned int n;
270 : 186 : unsigned int sym;
271 : 186 : DynamicStrings_String misspell;
272 : 186 : DynamicStrings_String HintStr;
273 : :
274 : 186 : misspell = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (unknown)));
275 : 186 : HintStr = static_cast<DynamicStrings_String> (NULL);
276 : 186 : n = M2StackWord_NoOfItemsInStackWord (DefaultStack);
277 : 186 : i = 1;
278 : 378 : while ((i <= n) && (HintStr == NULL))
279 : : {
280 : 150 : sym = static_cast<unsigned int> (M2StackWord_PeepWord (DefaultStack, i));
281 : 150 : HintStr = CheckForHintStr (sym, HintStr, misspell);
282 : 150 : if ((SymbolTable_IsModule (sym)) || (SymbolTable_IsDefImp (sym)))
283 : : {
284 : : /* Cannot see beyond a module scope. */
285 : 144 : return AddPunctuation (HintStr, (const char *) "?", 1);
286 : : }
287 : 6 : i += 1;
288 : : }
289 : 42 : return AddPunctuation (HintStr, (const char *) "?", 1);
290 : : /* static analysis guarentees a RETURN statement will be used before here. */
291 : : __builtin_unreachable ();
292 : : }
293 : :
294 : :
295 : : /*
296 : : Push - push a scope onto the spelling stack.
297 : : sym might be a ModSym, DefImpSym or a varsym
298 : : of a record type denoting a with statement.
299 : : */
300 : :
301 : 5423691 : extern "C" void M2StackSpell_Push (unsigned int sym)
302 : : {
303 : 5423691 : M2StackWord_PushWord (DefaultStack, sym);
304 : 5423691 : }
305 : :
306 : :
307 : : /*
308 : : Pop - remove the top scope from the spelling stack.
309 : : */
310 : :
311 : 5423438 : extern "C" void M2StackSpell_Pop (void)
312 : : {
313 : 5423438 : if ((M2StackWord_PopWord (DefaultStack)) == 0)
314 : : {} /* empty. */
315 : 5423438 : }
316 : :
317 : :
318 : : /*
319 : : GetRecordField - return the record field containing fieldName.
320 : : An error is generated if the fieldName is not
321 : : found in record.
322 : : */
323 : :
324 : 26824 : extern "C" unsigned int M2StackSpell_GetRecordField (unsigned int tokno, unsigned int record, NameKey_Name fieldName)
325 : : {
326 : 26824 : DynamicStrings_String str;
327 : 26824 : unsigned int sym;
328 : 26824 : NameKey_Name recordName;
329 : 26824 : const char * content;
330 : 26824 : m2spellcheck_Candidates cand;
331 : 26824 : DynamicStrings_String fieldStr;
332 : 26824 : DynamicStrings_String recordStr;
333 : 26824 : DynamicStrings_String contentStr;
334 : :
335 : 26824 : sym = SymbolTable_GetLocalSym (record, fieldName);
336 : 26824 : if (sym == SymbolTable_NulSym)
337 : : {
338 : 6 : recordName = SymbolTable_GetSymName (record);
339 : 6 : content = static_cast<const char *> (NULL);
340 : 6 : cand = m2spellcheck_InitCandidates ();
341 : 6 : if ((PushCandidates (cand, record)) > 0)
342 : : {
343 : 6 : content = m2spellcheck_FindClosestCharStar (cand, const_cast <const char * > (static_cast <char * > (NameKey_KeyToCharStar (fieldName))));
344 : : }
345 : 6 : fieldStr = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (fieldName)));
346 : 6 : recordStr = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (recordName)));
347 : 6 : if (content == NULL)
348 : : {
349 : 0 : str = FormatStrings_Sprintf2 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "field %s does not exist within record %s", 40)), (const unsigned char *) &fieldStr, (sizeof (fieldStr)-1), (const unsigned char *) &recordStr, (sizeof (recordStr)-1));
350 : : }
351 : : else
352 : : {
353 : 6 : contentStr = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (static_cast <void *> (const_cast <char * > (content))));
354 : 6 : str = FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "field %s does not exist within record %s, did you mean %s?", 58)), (const unsigned char *) &fieldStr, (sizeof (fieldStr)-1), (const unsigned char *) &recordStr, (sizeof (recordStr)-1), (const unsigned char *) &contentStr, (sizeof (contentStr)-1));
355 : : }
356 : 6 : M2MetaError_MetaErrorStringT0 (tokno, str);
357 : 6 : m2spellcheck_KillCandidates (&cand);
358 : : }
359 : 26824 : return sym;
360 : : /* static analysis guarentees a RETURN statement will be used before here. */
361 : : __builtin_unreachable ();
362 : : }
363 : :
364 : 15506 : extern "C" void _M2_M2StackSpell_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
365 : : {
366 : 15506 : Init ();
367 : 15506 : }
368 : :
369 : 0 : extern "C" void _M2_M2StackSpell_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
370 : : {
371 : 0 : }
|