Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1126 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
}