Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 1
/* decpseudo.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS                                                                        */
6
/*                                                                           */
7
/* Commonly Used VAX/PDP-11 Pseudo Instructions                              */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
/*****************************************************************************
12
 * Includes
13
 *****************************************************************************/
14
 
15
#include "stdinc.h"
16
#include <string.h>
17
 
18
#include "strutil.h"
19
#include "asmdef.h"
20
#include "asmpars.h"
21
#include "asmerr.h"
22
#include "errmsg.h"
23
 
24
#include "decpseudo.h"
25
 
26
/*****************************************************************************
27
 * Global Types
28
 *****************************************************************************/
29
 
30
/*!------------------------------------------------------------------------
31
 * \fn     decode_dec_packed(Word index)
32
 * \brief  encode number or decimal string in packed decimal format
33
 * ------------------------------------------------------------------------ */
34
 
35
static void append_digit(Byte digit, Boolean *p_half)
36
{
37
  if (*p_half)
38
  {
39
    BAsmCode[CodeLen] |= (digit & 15);
40
    CodeLen++;
41
    switch (ListGrans[ActPC])
42
    {
43
      case 1:
44
        break;
45
      case 2:
46
        if (!(CodeLen & 1))
47
          WAsmCode[(CodeLen / 2) - 1] = ((Word)BAsmCode[CodeLen - 1]) << 8 | BAsmCode[CodeLen - 2];
48
        break;
49
    }
50
  }
51
  else
52
  {
53
    SetMaxCodeLen(CodeLen + 1);
54
    BAsmCode[CodeLen] = (digit & 15) << 4;
55
  }
56
  *p_half = !*p_half;
57
}
58
 
59
void decode_dec_packed(Word index)
60
{
61
  TempResult value;
62
  const char *p_str = NULL;
63
  char tmp_dec_str[33];
64
 
65
  UNUSED(index);
66
 
67
  if (!ChkArgCnt(1, 2))
68
    return;
69
 
70
  as_tempres_ini(&value);
71
  EvalStrExpression(&ArgStr[1], &value);
72
  switch (value.Typ)
73
  {
74
    case TempNone:
75
      break;
76
    case TempInt:
77
      as_snprintf(tmp_dec_str, sizeof(tmp_dec_str), "%lld", value.Contents.Int);
78
      p_str = tmp_dec_str;
79
      goto writeout;
80
    case TempString:
81
      p_str = value.Contents.str.p_str;
82
      goto writeout;
83
    case TempFloat:
84
      WrStrErrorPos(ErrNum_StringOrIntButFloat, &ArgStr[1]);
85
      break;
86
    default:
87
      WrStrErrorPos(ErrNum_ExpectIntOrString, &ArgStr[1]);
88
      break;
89
    writeout:
90
    {
91
      size_t num_digits = 0, l;
92
      Boolean half, negative;
93
 
94
      switch (*p_str)
95
      {
96
        case '-':
97
          negative = True;
98
          p_str++;
99
          break;
100
        case '+':
101
          negative = False;
102
          p_str++;
103
          break;
104
        default:
105
          negative = False;
106
      }
107
 
108
      l = strlen(p_str);
109
      half = False;
110
      /* leading zero padding digit is not counted into num_digits: */
111
      if (!(l & 1))
112
        append_digit(0, &half);
113
      for (; *p_str; p_str++)
114
      {
115
        if (!isdigit(*p_str))
116
        {
117
          WrStrErrorPos(ErrNum_InvalidDecDigit, &ArgStr[1]);
118
          CodeLen = 0; half = False;
119
          break;
120
        }
121
        append_digit(*p_str - '0', &half);
122
        if (++num_digits > 31)
123
        {
124
          WrStrErrorPos(ErrNum_DecStringTooLong, &ArgStr[1]);
125
          CodeLen = 0; half = False;
126
          break;
127
        }
128
      }
129
      if (CodeLen || half)
130
      {
131
        append_digit(negative ? 13 : 12, &half);
132
        if (2 == ArgCnt)
133
          EnterIntSymbol(&ArgStr[2], num_digits, SegNone, False);
134
      }
135
    }
136
  }
137
 
138
  as_tempres_free(&value);
139
}