OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | |
3 * Use of this source code is governed by a BSD-style license that can be | |
4 * found in the LICENSE file. | |
5 */ | |
6 | |
7 /* | |
8 * Hexidecimal text to bytes conversion tools. | |
9 */ | |
10 #ifndef NACL_TRUSTED_BUT_NOT_TCB | |
11 #error("This file is not meant for use in the TCB.") | |
12 #endif | |
13 | |
14 #include "native_client/src/trusted/validator/x86/testing/enuminsts/text2hex.h" | |
15 | |
16 #include <stdio.h> | |
17 | |
18 #include "native_client/src/include/portability_io.h" | |
19 | |
20 #define kBufferSize 1024 | |
21 | |
22 /* Returns the integer corresponding to a hex value in ASCII. This would | |
23 * be faster as an array lookup, however since it's only used for command | |
24 * line input it doesn't matter. | |
25 */ | |
26 static unsigned int A2INibble(const char nibble) { | |
27 switch (nibble) { | |
28 case '0': return 0; | |
29 case '1': return 1; | |
30 case '2': return 2; | |
31 case '3': return 3; | |
32 case '4': return 4; | |
33 case '5': return 5; | |
34 case '6': return 6; | |
35 case '7': return 7; | |
36 case '8': return 8; | |
37 case '9': return 9; | |
38 case 'a': | |
39 case 'A': return 0xA; | |
40 case 'b': | |
41 case 'B': return 0xB; | |
42 case 'c': | |
43 case 'C': return 0xC; | |
44 case 'd': | |
45 case 'D': return 0xD; | |
46 case 'e': | |
47 case 'E': return 0xE; | |
48 case 'f': | |
49 case 'F': return 0xF; | |
50 default: break; | |
51 } | |
52 fprintf(stderr, "bad hex value %c", nibble); | |
53 exit(1); | |
54 } | |
55 | |
56 /* Convert a two-character string representing an byte value in hex | |
57 * into the corresponding byte value. | |
58 */ | |
59 static unsigned int A2IByte(const char nibble1, const char nibble2) { | |
60 return A2INibble(nibble2) + A2INibble(nibble1) * 0x10; | |
61 } | |
62 | |
63 /* Generates a buffer containing the context message to print. | |
64 * Arguments are: | |
65 * context - String describing the context (i.e. filename or | |
66 * command line argument description). | |
67 * line - The line number associated with the context (if negative, | |
68 * it assumes that the line number shouldn't be reported). | |
69 */ | |
70 static const char* TextContext(const char* context, | |
71 const int line) { | |
72 if (line < 0) { | |
73 return context; | |
74 } else { | |
75 static char buffer[kBufferSize]; | |
76 SNPRINTF(buffer, kBufferSize, "%s line %d", context, line); | |
77 return buffer; | |
78 } | |
79 } | |
80 | |
81 /* Installs byte into the byte buffer. Returns the new value for num_bytes. | |
82 * Arguments are: | |
83 * ibytes - The found sequence of opcode bytes. | |
84 * num_bytes - The number of bytes currently in ibytes. | |
85 * mini_buf - The buffer containing the two hexidecimal characters to convert. | |
86 * context - String describing the context (i.e. filename or | |
87 * command line argument description). | |
88 * line - The line number associated with the context (if negative, | |
89 * it assumes that the line number shouldn't be reported). | |
90 */ | |
91 static int InstallTextByte(InstByteArray ibytes, | |
92 int num_bytes, | |
93 const char mini_buf[2], | |
94 const char* itext, | |
95 const char* context, | |
96 const int line) { | |
97 if (num_bytes == NACL_ENUM_MAX_INSTRUCTION_BYTES) { | |
98 char buffer[kBufferSize]; | |
99 SNPRINTF(buffer, kBufferSize, | |
100 "%s: opcode sequence too long in '%s'", | |
101 TextContext(context, line), itext); | |
102 ReportFatalError(buffer); | |
103 } | |
104 ibytes[num_bytes] = A2IByte(mini_buf[0], mini_buf[1]); | |
105 return num_bytes + 1; | |
106 } | |
107 | |
108 /* Reads a line of text defining the sequence of bytes that defines | |
109 * an instruction, and converts that to the corresponding sequence of | |
110 * opcode bytes. Returns the number of bytes found. Arguments are: | |
111 * ibytes - The found sequence of opcode bytes. | |
112 * itext - The sequence of bytes to convert. | |
113 * context - String describing the context (i.e. filename or | |
114 * command line argument description). | |
115 * line - The line number associated with the context (if negative, | |
116 * it assumes that the line number shouldn't be reported). | |
117 */ | |
118 int Text2Bytes(InstByteArray ibytes, | |
119 const char* itext, | |
120 const char* context, | |
121 const int line) { | |
122 char mini_buf[2]; | |
123 size_t mini_buf_index; | |
124 char *next; | |
125 char ch; | |
126 int num_bytes = 0; | |
127 Bool continue_translation = TRUE; | |
128 | |
129 /* Now process text of itext. */ | |
130 next = (char*) &itext[0]; | |
131 mini_buf_index = 0; | |
132 while (continue_translation && (ch = *(next++))) { | |
133 switch (ch) { | |
134 case '#': | |
135 /* Comment, skip reading any more characters. */ | |
136 continue_translation = FALSE; | |
137 break; | |
138 case '0': | |
139 case '1': | |
140 case '2': | |
141 case '3': | |
142 case '4': | |
143 case '5': | |
144 case '6': | |
145 case '7': | |
146 case '8': | |
147 case '9': | |
148 case 'a': | |
149 case 'b': | |
150 case 'c': | |
151 case 'd': | |
152 case 'e': | |
153 case 'f': | |
154 case 'A': | |
155 case 'B': | |
156 case 'C': | |
157 case 'D': | |
158 case 'E': | |
159 case 'F': | |
160 /* Hexidecimal character. Add to mini buffer, and install | |
161 * if two bytes. | |
162 */ | |
163 mini_buf[mini_buf_index++] = ch; | |
164 if (2 == mini_buf_index) { | |
165 num_bytes = InstallTextByte(ibytes, num_bytes, mini_buf, itext, | |
166 context, line); | |
167 mini_buf_index = 0; | |
168 } | |
169 break; | |
170 case ' ': | |
171 case '\t': | |
172 case '\n': | |
173 /* Space - assume it is a separator between bytes. */ | |
174 switch(mini_buf_index) { | |
175 case 0: | |
176 break; | |
177 case 2: | |
178 num_bytes = InstallTextByte(ibytes, num_bytes, mini_buf, itext, | |
179 context, line); | |
180 mini_buf_index = 0; | |
181 break; | |
182 default: | |
183 continue_translation = FALSE; | |
184 } | |
185 break; | |
186 default: { | |
187 char buffer[kBufferSize]; | |
188 SNPRINTF(buffer, kBufferSize, | |
189 "%s: contains bad text:\n '%s'\n", | |
190 TextContext(context, line), itext); | |
191 ReportFatalError(buffer); | |
192 break; | |
193 } | |
194 } | |
195 } | |
196 | |
197 /* If only a single byte was used to define hex value, convert it. */ | |
198 if (mini_buf_index > 0) { | |
199 char buffer[kBufferSize]; | |
200 SNPRINTF(buffer, kBufferSize, | |
201 "%s: Opcode sequence must be an even number of chars '%s'", | |
202 TextContext(context, line), itext); | |
203 ReportFatalError(buffer); | |
204 } | |
205 | |
206 return num_bytes; | |
207 } | |
OLD | NEW |