Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1186 | savelij | 1 | /* intformat.c */ |
2 | /*****************************************************************************/ |
||
3 | /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */ |
||
4 | /* */ |
||
5 | /* AS */ |
||
6 | /* */ |
||
7 | /* enums regarding integer constant notations */ |
||
8 | /* */ |
||
9 | /*****************************************************************************/ |
||
10 | |||
11 | #include "strutil.h" |
||
12 | #include "datatypes.h" |
||
13 | #include "stdinc.h" |
||
14 | #include <stdlib.h> |
||
15 | #include <string.h> |
||
16 | |||
17 | #include "intformat.h" |
||
18 | |||
19 | static const Word BaseVals[4] = |
||
20 | { |
||
21 | 2, 8, 16, 256 |
||
22 | }; |
||
23 | |||
24 | LongWord NativeIntConstModeMask, OtherIntConstModeMask; |
||
25 | tIntFormatList *IntFormatList = NULL; |
||
26 | tIntConstMode IntConstMode; |
||
27 | Boolean IntConstModeIBMNoTerm, RelaxedMode; |
||
28 | int RadixBase; |
||
29 | |||
30 | static Boolean ChkIntFormatCHex(tIntCheckCtx *pCtx, char Ch) |
||
31 | { |
||
32 | if ((pCtx->ExprLen > 2) |
||
33 | && (*pCtx->pExpr == '0') |
||
34 | && (RadixBase <= Ch - 'A' + 10) |
||
35 | && (as_toupper(pCtx->pExpr[1]) == Ch)) |
||
36 | { |
||
37 | pCtx->pExpr += 2; |
||
38 | pCtx->ExprLen -= 2; |
||
39 | return True; |
||
40 | } |
||
41 | return False; |
||
42 | } |
||
43 | |||
44 | static Boolean ChkIntFormatCBin(tIntCheckCtx *pCtx, char Ch) |
||
45 | { |
||
46 | if ((pCtx->ExprLen > 2) |
||
47 | && (*pCtx->pExpr == '0') |
||
48 | && (RadixBase <= Ch - 'A' + 10) |
||
49 | && (as_toupper(pCtx->pExpr[1]) == Ch)) |
||
50 | { |
||
51 | const char *pRun; |
||
52 | |||
53 | for (pRun = pCtx->pExpr + 2; pRun < pCtx->pExpr + pCtx->ExprLen; pRun++) |
||
54 | if (DigitVal(*pRun, 2) < 0) |
||
55 | return False; |
||
56 | pCtx->pExpr += 2; |
||
57 | pCtx->ExprLen -= 2; |
||
58 | return True; |
||
59 | } |
||
60 | return False; |
||
61 | } |
||
62 | |||
63 | static Boolean ChkIntFormatMot(tIntCheckCtx *pCtx, char Ch) |
||
64 | { |
||
65 | if ((pCtx->ExprLen > 1) |
||
66 | && (*pCtx->pExpr == Ch)) |
||
67 | { |
||
68 | pCtx->pExpr++; |
||
69 | pCtx->ExprLen--; |
||
70 | return True; |
||
71 | } |
||
72 | return False; |
||
73 | } |
||
74 | |||
75 | static Boolean ChkIntFormatInt(tIntCheckCtx *pCtx, char Ch) |
||
76 | { |
||
77 | if ((pCtx->ExprLen < 2) || !as_isdigit(*pCtx->pExpr)) |
||
78 | return False; |
||
79 | if ((RadixBase <= Ch - 'A' + 10) |
||
80 | && (as_toupper(pCtx->pExpr[pCtx->ExprLen - 1]) == Ch)) |
||
81 | { |
||
82 | pCtx->ExprLen--; |
||
83 | return True; |
||
84 | } |
||
85 | return False; |
||
86 | } |
||
87 | |||
88 | static Boolean ChkIntFormatIBM(tIntCheckCtx *pCtx, char Ch) |
||
89 | { |
||
90 | if ((pCtx->ExprLen < 3) |
||
91 | || (as_toupper(*pCtx->pExpr) != Ch) |
||
92 | || (pCtx->pExpr[1] != '\'')) |
||
93 | return False; |
||
94 | if ((pCtx->ExprLen > 3) && (pCtx->pExpr[pCtx->ExprLen - 1] == '\'')) |
||
95 | { |
||
96 | pCtx->pExpr += 2; |
||
97 | pCtx->ExprLen -= 3; |
||
98 | return True; |
||
99 | } |
||
100 | else if (IntConstModeIBMNoTerm) |
||
101 | { |
||
102 | pCtx->pExpr += 2; |
||
103 | pCtx->ExprLen -= 2; |
||
104 | return True; |
||
105 | } |
||
106 | return False; |
||
107 | } |
||
108 | |||
109 | static Boolean ChkIntFormatCOct(tIntCheckCtx *pCtx, char Ch) |
||
110 | { |
||
111 | const char *pRun; |
||
112 | UNUSED(Ch); |
||
113 | |||
114 | if ((pCtx->ExprLen < 2) |
||
115 | || (*pCtx->pExpr != '0')) |
||
116 | return False; |
||
117 | for (pRun = pCtx->pExpr + 1; pRun < pCtx->pExpr + pCtx->ExprLen; pRun++) |
||
118 | if (DigitVal(*pRun, 8) < 0) |
||
119 | return False; |
||
120 | return True; |
||
121 | } |
||
122 | |||
123 | static Boolean ChkIntFormatNatHex(tIntCheckCtx *pCtx, char Ch) |
||
124 | { |
||
125 | const char *pRun; |
||
126 | UNUSED(Ch); |
||
127 | |||
128 | if ((pCtx->ExprLen < 2) |
||
129 | || (*pCtx->pExpr != '0')) |
||
130 | return False; |
||
131 | for (pRun = pCtx->pExpr + 1; pRun < pCtx->pExpr + pCtx->ExprLen; pRun++) |
||
132 | if (!as_isxdigit(*pRun)) |
||
133 | return False; |
||
134 | return True; |
||
135 | } |
||
136 | |||
137 | static Boolean ChkIntFormatDef(tIntCheckCtx *pCtx, char Ch) |
||
138 | { |
||
139 | UNUSED(pCtx); |
||
140 | UNUSED(Ch); |
||
141 | return True; |
||
142 | } |
||
143 | |||
144 | static const tIntFormatList IntFormatList_All[] = |
||
145 | { |
||
146 | { ChkIntFormatCHex , eIntFormatCHex, 16, 'X', "0xhex" }, |
||
147 | { ChkIntFormatCBin , eIntFormatCBin, 2, 'B', "0bbin" }, |
||
148 | { ChkIntFormatMot , eIntFormatMotHex, 16, '$', "$hex" }, |
||
149 | { ChkIntFormatMot , eIntFormatMotBin, 2, '%', "%bin" }, |
||
150 | { ChkIntFormatMot , eIntFormatMotOct, 8, '@', "@oct" }, |
||
151 | { ChkIntFormatInt , eIntFormatIntHex, 16, 'H', "hexh" }, |
||
152 | { ChkIntFormatInt , eIntFormatIntBin, 2, 'B', "binb" }, |
||
153 | { ChkIntFormatInt , eIntFormatIntOOct, 8, 'O', "octo" }, |
||
154 | { ChkIntFormatInt , eIntFormatIntQOct, 8, 'Q', "octq" }, |
||
155 | { ChkIntFormatIBM , eIntFormatIBMHHex, 16, 'H', "h'hex'" }, |
||
156 | { ChkIntFormatIBM , eIntFormatIBMXHex, 16, 'X', "x'hex'" }, |
||
157 | { ChkIntFormatIBM , eIntFormatIBMBin, 2, 'B', "b'bin'" }, |
||
158 | { ChkIntFormatIBM , eIntFormatIBMOct, 8, 'O', "o'oct'" }, |
||
159 | { ChkIntFormatIBM , eIntFormatIBMAsc, 256, 'A', "a'asc'" }, |
||
160 | { ChkIntFormatCOct , eIntFormatCOct, 8, '0', "0oct" }, |
||
161 | { ChkIntFormatNatHex, eIntFormatNatHex, 16, '0', "0hex" }, |
||
162 | { ChkIntFormatDef , eIntFormatDefRadix,-1, '\0', "dec" }, /* -1 -> RadixBase */ |
||
163 | { NULL , (tIntFormatId)0, 0, '\0', "" } |
||
164 | }; |
||
165 | |||
166 | /*!------------------------------------------------------------------------ |
||
167 | * \fn GetIntConstIntelSuffix(unsigned Radix) |
||
168 | * \brief return Intel-style suffix letter fitting to number system |
||
169 | * \param Radix req'd number system |
||
170 | * \return * to suffix string (may be empty) |
||
171 | * ------------------------------------------------------------------------ */ |
||
172 | |||
173 | const char *GetIntConstIntelSuffix(unsigned Radix) |
||
174 | { |
||
175 | static const char BaseLetters[3] = |
||
176 | { |
||
177 | 'B', 'O', 'H' |
||
178 | }; |
||
179 | unsigned BaseIdx; |
||
180 | |||
181 | for (BaseIdx = 0; BaseIdx < as_array_size(BaseLetters); BaseIdx++) |
||
182 | if (Radix == BaseVals[BaseIdx]) |
||
183 | { |
||
184 | static char Result[2] = { '\0', '\0' }; |
||
185 | |||
186 | Result[0] = BaseLetters[BaseIdx] + (HexStartCharacter - 'A'); |
||
187 | return Result; |
||
188 | } |
||
189 | return ""; |
||
190 | } |
||
191 | |||
192 | /*!------------------------------------------------------------------------ |
||
193 | * \fn GetIntConstMotoPrefix(unsigned Radix) |
||
194 | * \brief return Motorola-style prefix letter fitting to number system |
||
195 | * \param Radix req'd number system |
||
196 | * \return * to prefix string (may be empty) |
||
197 | * ------------------------------------------------------------------------ */ |
||
198 | |||
199 | const char *GetIntConstMotoPrefix(unsigned Radix) |
||
200 | { |
||
201 | static const char BaseIds[3] = |
||
202 | { |
||
203 | '%', '@', '$' |
||
204 | }; |
||
205 | unsigned BaseIdx; |
||
206 | |||
207 | for (BaseIdx = 0; BaseIdx < as_array_size(BaseIds); BaseIdx++) |
||
208 | if (Radix == BaseVals[BaseIdx]) |
||
209 | { |
||
210 | static char Result[2] = { '\0', '\0' }; |
||
211 | |||
212 | Result[0] = BaseIds[BaseIdx]; |
||
213 | return Result; |
||
214 | } |
||
215 | return ""; |
||
216 | } |
||
217 | |||
218 | /*!------------------------------------------------------------------------ |
||
219 | * \fn GetIntConstCPrefix(unsigned Radix) |
||
220 | * \brief return C-style prefix letter fitting to number system |
||
221 | * \param Radix req'd number system |
||
222 | * \return * to prefix string (may be empty) |
||
223 | * ------------------------------------------------------------------------ */ |
||
224 | |||
225 | const char *GetIntConstCPrefix(unsigned Radix) |
||
226 | { |
||
227 | static const char BaseIds[3][3] = |
||
228 | { |
||
229 | "0b", "0", "0x" |
||
230 | }; |
||
231 | unsigned BaseIdx; |
||
232 | |||
233 | for (BaseIdx = 0; BaseIdx < as_array_size(BaseIds); BaseIdx++) |
||
234 | if (Radix == BaseVals[BaseIdx]) |
||
235 | return BaseIds[BaseIdx];; |
||
236 | return ""; |
||
237 | } |
||
238 | |||
239 | /*!------------------------------------------------------------------------ |
||
240 | * \fn GetIntConstIBMPrefix(unsigned Radix) |
||
241 | * \brief return IBM-style prefix letter fitting to number system |
||
242 | * \param Radix req'd number system |
||
243 | * \return * to prefix string (may be empty) |
||
244 | * ------------------------------------------------------------------------ */ |
||
245 | |||
246 | const char *GetIntConstIBMPrefix(unsigned Radix) |
||
247 | { |
||
248 | static const char BaseIds[4] = |
||
249 | { |
||
250 | 'B', 'O', 'X', 'A' |
||
251 | }; |
||
252 | unsigned BaseIdx; |
||
253 | |||
254 | for (BaseIdx = 0; BaseIdx < as_array_size(BaseIds); BaseIdx++) |
||
255 | if (Radix == BaseVals[BaseIdx]) |
||
256 | { |
||
257 | static char Result[3] = { '\0', '\'', '\0' }; |
||
258 | |||
259 | Result[0] = BaseIds[BaseIdx] + (HexStartCharacter - 'A'); |
||
260 | return Result; |
||
261 | } |
||
262 | return ""; |
||
263 | } |
||
264 | |||
265 | /*!------------------------------------------------------------------------ |
||
266 | * \fn GetIntConstIBMSuffix(unsigned Radix) |
||
267 | * \brief return IBM-style suffix fitting to number system |
||
268 | * \param Radix req'd number system |
||
269 | * \return * to prefix string (may be empty) |
||
270 | * ------------------------------------------------------------------------ */ |
||
271 | |||
272 | const char *GetIntConstIBMSuffix(unsigned Radix) |
||
273 | { |
||
274 | unsigned BaseIdx; |
||
275 | |||
276 | for (BaseIdx = 0; BaseIdx < as_array_size(BaseVals); BaseIdx++) |
||
277 | if (Radix == BaseVals[BaseIdx]) |
||
278 | return "\'"; |
||
279 | return ""; |
||
280 | } |
||
281 | |||
282 | /*!------------------------------------------------------------------------ |
||
283 | * \fn SetIntConstModeByMask(LongWord Mask) |
||
284 | * \brief set new (non-relaxed) integer constant mode by bit mask |
||
285 | * \param Mask modes to set |
||
286 | * ------------------------------------------------------------------------ */ |
||
287 | |||
288 | void SetIntConstModeByMask(LongWord Mask) |
||
289 | { |
||
290 | const tIntFormatList *pSrc; |
||
291 | tIntFormatList *pDest; |
||
292 | |||
293 | if (!IntFormatList) |
||
294 | IntFormatList = (tIntFormatList*)malloc(sizeof(IntFormatList_All)); |
||
295 | for (pDest = IntFormatList, pSrc = IntFormatList_All; pSrc->Check; pSrc++) |
||
296 | { |
||
297 | if (!((Mask >> pSrc->Id) & 1)) |
||
298 | continue; |
||
299 | *pDest++ = *pSrc; |
||
300 | } |
||
301 | memset(pDest, 0, sizeof(*pDest)); |
||
302 | } |
||
303 | |||
304 | /*!------------------------------------------------------------------------ |
||
305 | * \fn ModifyIntConstModeByMask(LongWord ANDMask, LongWord ORMask) |
||
306 | * \brief add or remove integer notations to/from native list |
||
307 | * \param ANDMask notations to remove |
||
308 | * \param ORMask notations to add |
||
309 | * \return True if mask was set up successfully |
||
310 | * ------------------------------------------------------------------------ */ |
||
311 | |||
312 | #define BadMask ((1ul << eIntFormatCOct) | (1ul << eIntFormatNatHex)) |
||
313 | |||
314 | Boolean ModifyIntConstModeByMask(LongWord ANDMask, LongWord ORMask) |
||
315 | { |
||
316 | LongWord NewMask = (NativeIntConstModeMask & ~ANDMask) | ORMask; |
||
317 | |||
318 | if ((NewMask & BadMask) == BadMask) |
||
319 | return False; |
||
320 | else |
||
321 | { |
||
322 | NativeIntConstModeMask = NewMask; |
||
323 | SetIntConstModeByMask(NativeIntConstModeMask | (RelaxedMode ? OtherIntConstModeMask : 0)); |
||
324 | return True; |
||
325 | } |
||
326 | } |
||
327 | |||
328 | /*!------------------------------------------------------------------------ |
||
329 | * \fn SetIntConstMode(tIntConstMode Mode) |
||
330 | * \brief set new (non-relaxed) integer constant mode |
||
331 | * \param Mode mode to set |
||
332 | * ------------------------------------------------------------------------ */ |
||
333 | |||
334 | void SetIntConstMode(tIntConstMode Mode) |
||
335 | { |
||
336 | IntConstMode = Mode; |
||
337 | switch (Mode) |
||
338 | { |
||
339 | case eIntConstModeC: |
||
340 | NativeIntConstModeMask = eIntFormatMaskC; |
||
341 | OtherIntConstModeMask = eIntFormatMaskIntel | eIntFormatMaskMoto | eIntFormatMaskIBM; |
||
342 | break; |
||
343 | case eIntConstModeIntel: |
||
344 | NativeIntConstModeMask = eIntFormatMaskIntel; |
||
345 | OtherIntConstModeMask = eIntFormatMaskC | eIntFormatMaskMoto | eIntFormatMaskIBM; |
||
346 | break; |
||
347 | case eIntConstModeMoto: |
||
348 | NativeIntConstModeMask = eIntFormatMaskMoto; |
||
349 | OtherIntConstModeMask = eIntFormatMaskC | eIntFormatMaskIntel | eIntFormatMaskIBM; |
||
350 | break; |
||
351 | case eIntConstModeIBM: |
||
352 | NativeIntConstModeMask = eIntFormatMaskIBM; |
||
353 | OtherIntConstModeMask = eIntFormatMaskC | eIntFormatMaskIntel | eIntFormatMaskMoto; |
||
354 | break; |
||
355 | default: |
||
356 | NativeIntConstModeMask = 0; |
||
357 | } |
||
358 | NativeIntConstModeMask |= (1ul << eIntFormatDefRadix); |
||
359 | SetIntConstModeByMask(NativeIntConstModeMask | (RelaxedMode ? OtherIntConstModeMask : 0)); |
||
360 | } |
||
361 | |||
362 | /*!------------------------------------------------------------------------ |
||
363 | * \fn SetIntConstRelaxedMode(Boolean NewRelaxedMode) |
||
364 | * \brief update relaxed mode - parser list |
||
365 | * \param NewRelaxedMode mode to set |
||
366 | * ------------------------------------------------------------------------ */ |
||
367 | |||
368 | void SetIntConstRelaxedMode(Boolean NewRelaxedMode) |
||
369 | { |
||
370 | SetIntConstModeByMask(NativeIntConstModeMask | (NewRelaxedMode ? OtherIntConstModeMask : 0)); |
||
371 | } |
||
372 | |||
373 | /*!------------------------------------------------------------------------ |
||
374 | * \fn GetIntFormatId(const char *pIdent) |
||
375 | * \brief transform identifier to id |
||
376 | * \param pIdent textual identifier |
||
377 | * \return resulting Id or None if not found |
||
378 | * ------------------------------------------------------------------------ */ |
||
379 | |||
380 | tIntFormatId GetIntFormatId(const char *pIdent) |
||
381 | { |
||
382 | const tIntFormatList *pList; |
||
383 | for (pList = IntFormatList_All; pList->Check; pList++) |
||
384 | if (!as_strcasecmp(pIdent, pList->Ident)) |
||
385 | return (tIntFormatId)pList->Id; |
||
386 | return eIntFormatNone; |
||
387 | } |
||
388 | |||
389 | /*!------------------------------------------------------------------------ |
||
390 | * \fn intformat_init(void) |
||
391 | * \brief module initialization |
||
392 | * ------------------------------------------------------------------------ */ |
||
393 | |||
394 | void intformat_init(void) |
||
395 | { |
||
396 | /* Allow all int const modes for handling possible -D options: */ |
||
397 | |||
398 | RelaxedMode = True; |
||
399 | SetIntConstMode(eIntConstModeC); |
||
400 | } |