1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | /**************************************************************************/ |
5 | /* asmParse is basically a wrapper around a YACC grammer COM+ assembly */ |
6 | |
7 | #ifndef asmparse_h |
8 | #define asmparse_h |
9 | |
10 | #include <stdio.h> // for FILE |
11 | |
12 | #include "assembler.h" // for ErrorReporter Labels |
13 | //class Assembler; |
14 | //class BinStr; |
15 | |
16 | |
17 | /**************************************************************************/ |
18 | /* an abstraction of a stream of input characters */ |
19 | class ReadStream { |
20 | public: |
21 | |
22 | virtual unsigned getAll(__out char** ppch) = 0; |
23 | |
24 | // read at most 'buffLen' bytes into 'buff', Return the |
25 | // number of characters read. On EOF return 0 |
26 | virtual unsigned read(__out_ecount(buffLen) char* buff, unsigned buffLen) = 0; |
27 | |
28 | // Return the name of the stream, (for error reporting). |
29 | //virtual const char* name() = 0; |
30 | // Return the Unicode name of the stream |
31 | virtual const WCHAR* namew() = 0; |
32 | //return ptr to buffer containing specified source line |
33 | virtual char* getLine(int lineNum) = 0; |
34 | }; |
35 | |
36 | /**************************************************************************/ |
37 | class BinStrStream : public ReadStream { |
38 | public: |
39 | BinStrStream(BinStr* pbs) |
40 | { |
41 | m_pStart = (char*)(pbs->ptr()); |
42 | m_pCurr = m_pStart; |
43 | m_pEnd = m_pStart + pbs->length(); |
44 | m_pBS = pbs; |
45 | }; |
46 | ~BinStrStream() |
47 | { |
48 | //if(m_pBS) |
49 | // delete m_pBS; |
50 | }; |
51 | unsigned getAll(__out char **ppbuff) |
52 | { |
53 | *ppbuff = m_pStart; |
54 | return m_pBS->length(); |
55 | }; |
56 | unsigned read(__out_ecount(buffLen) char* buff, unsigned buffLen) |
57 | { |
58 | _ASSERTE(m_pStart != NULL); |
59 | unsigned Remainder = (unsigned)(m_pEnd - m_pCurr); |
60 | unsigned Len = buffLen; |
61 | if(Len > Remainder) Len = Remainder; |
62 | memcpy(buff,m_pCurr,Len); |
63 | m_pCurr += Len; |
64 | if(Len < buffLen) |
65 | { |
66 | memset(buff+Len,0,buffLen-Len); |
67 | } |
68 | return Len; |
69 | } |
70 | |
71 | const WCHAR* namew() |
72 | { |
73 | return W("local_define" ); |
74 | } |
75 | |
76 | BOOL IsValid() |
77 | { |
78 | return(m_pStart != NULL); |
79 | } |
80 | |
81 | char* getLine(int lineNum) |
82 | { |
83 | return NULL; // this function is not used |
84 | } |
85 | |
86 | private: |
87 | char* m_pStart; |
88 | char* m_pEnd; |
89 | char* m_pCurr; |
90 | BinStr* m_pBS; |
91 | |
92 | |
93 | }; |
94 | /**************************************************************************/ |
95 | class MappedFileStream : public ReadStream { |
96 | public: |
97 | MappedFileStream(__in __nullterminated WCHAR* wFileName) |
98 | { |
99 | fileNameW = wFileName; |
100 | m_hFile = INVALID_HANDLE_VALUE; |
101 | m_hMapFile = NULL; |
102 | m_pStart = open(wFileName); |
103 | m_pCurr = m_pStart; |
104 | m_pEnd = m_pStart + m_FileSize; |
105 | //memset(fileNameANSI,0,MAX_FILENAME_LENGTH*4); |
106 | //WszWideCharToMultiByte(CP_ACP,0,wFileName,-1,fileNameANSI,MAX_FILENAME_LENGTH*4,NULL,NULL); |
107 | } |
108 | ~MappedFileStream() |
109 | { |
110 | if (m_hFile != INVALID_HANDLE_VALUE) |
111 | { |
112 | if (m_pStart) |
113 | UnmapViewOfFile((void*)m_pStart); |
114 | if (m_hMapFile) |
115 | CloseHandle(m_hMapFile); |
116 | CloseHandle(m_hFile); |
117 | |
118 | m_pStart = NULL; |
119 | m_hMapFile = NULL; |
120 | m_hFile = INVALID_HANDLE_VALUE; |
121 | m_FileSize = 0; |
122 | delete [] fileNameW; |
123 | fileNameW = NULL; |
124 | } |
125 | } |
126 | unsigned getAll(__out char** pbuff) |
127 | { |
128 | *pbuff = m_pStart; |
129 | return m_FileSize; |
130 | } |
131 | unsigned read(__out_ecount(buffLen) char* buff, unsigned buffLen) |
132 | { |
133 | _ASSERTE(m_pStart != NULL); |
134 | unsigned Remainder = (unsigned)(m_pEnd - m_pCurr); |
135 | unsigned Len = buffLen; |
136 | if(Len > Remainder) Len = Remainder; |
137 | memcpy(buff,m_pCurr,Len); |
138 | m_pCurr += Len; |
139 | if(Len < buffLen) |
140 | { |
141 | memset(buff+Len,0,buffLen-Len); |
142 | } |
143 | return Len; |
144 | } |
145 | |
146 | //const char* name() |
147 | //{ |
148 | // return(&fileNameANSI[0]); |
149 | //} |
150 | |
151 | const WCHAR* namew() |
152 | { |
153 | return fileNameW; |
154 | } |
155 | |
156 | void set_namew(const WCHAR* namew) |
157 | { |
158 | fileNameW = namew; |
159 | } |
160 | |
161 | BOOL IsValid() |
162 | { |
163 | return(m_pStart != NULL); |
164 | } |
165 | |
166 | char* getLine(int lineNum) |
167 | { |
168 | return NULL; // this function is not used |
169 | } |
170 | |
171 | private: |
172 | char* map_file() |
173 | { |
174 | DWORD dwFileSizeLow; |
175 | |
176 | dwFileSizeLow = GetFileSize( m_hFile, NULL); |
177 | if (dwFileSizeLow == INVALID_FILE_SIZE) |
178 | return NULL; |
179 | m_FileSize = dwFileSizeLow; |
180 | |
181 | // No difference between A and W in this case: last param (LPCTSTR) is NULL |
182 | m_hMapFile = WszCreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL); |
183 | if (m_hMapFile == NULL) |
184 | return NULL; |
185 | |
186 | return (char*)(HMODULE) MapViewOfFile(m_hMapFile, FILE_MAP_READ, 0, 0, 0); |
187 | } |
188 | char* open(const WCHAR* moduleName) |
189 | { |
190 | _ASSERTE(moduleName); |
191 | if (!moduleName) |
192 | return NULL; |
193 | |
194 | m_hFile = WszCreateFile(moduleName, GENERIC_READ, FILE_SHARE_READ, |
195 | 0, OPEN_EXISTING, 0, 0); |
196 | return (m_hFile == INVALID_HANDLE_VALUE) ? NULL : map_file(); |
197 | } |
198 | |
199 | const WCHAR* fileNameW; // FileName (for error reporting) |
200 | //char fileNameANSI[MAX_FILENAME_LENGTH*4]; |
201 | HANDLE m_hFile; // File we are reading from |
202 | DWORD m_FileSize; |
203 | HANDLE m_hMapFile; |
204 | char* m_pStart; |
205 | char* m_pEnd; |
206 | char* m_pCurr; |
207 | |
208 | }; |
209 | |
210 | typedef LIFO<ARG_NAME_LIST> ARG_NAME_LIST_STACK; |
211 | |
212 | // functional pointers used in parsing |
213 | /*--------------------------------------------------------------------------*/ |
214 | typedef char*(*PFN_NEXTCHAR)(char*); |
215 | |
216 | char* nextcharA(__in __nullterminated char* pos); |
217 | char* nextcharU(__in __nullterminated char* pos); |
218 | char* nextcharW(__in __nullterminated char* pos); |
219 | |
220 | /*--------------------------------------------------------------------------*/ |
221 | typedef unsigned(*PFN_SYM)(char*); |
222 | |
223 | unsigned SymAU(__in __nullterminated char* curPos); |
224 | unsigned SymW(__in __nullterminated char* curPos); |
225 | /*--------------------------------------------------------------------------*/ |
226 | typedef char*(*PFN_NEWSTRFROMTOKEN)(char*,size_t); |
227 | |
228 | char* NewStrFromTokenAU(__in_ecount(tokLen) char* curTok, size_t tokLen); |
229 | char* NewStrFromTokenW(__in_ecount(tokLen) char* curTok, size_t tokLen); |
230 | /*--------------------------------------------------------------------------*/ |
231 | typedef char*(*PFN_NEWSTATICSTRFROMTOKEN)(char*,size_t,char*,size_t); |
232 | |
233 | char* NewStaticStrFromTokenAU(__in_ecount(tokLen) char* curTok, size_t tokLen, __out_ecount(bufSize) char* staticBuf, size_t bufSize); |
234 | char* NewStaticStrFromTokenW(__in_ecount(tokLen) char* curTok, size_t tokLen, __out_ecount(bufSize) char* staticBuf, size_t bufSize); |
235 | /*--------------------------------------------------------------------------*/ |
236 | typedef unsigned(*PFN_GETDOUBLE)(char*,unsigned,double**); |
237 | |
238 | unsigned GetDoubleAU(__in __nullterminated char* begNum, unsigned L, double** ppRes); |
239 | unsigned GetDoubleW(__in __nullterminated char* begNum, unsigned L, double** ppRes); |
240 | /*--------------------------------------------------------------------------*/ |
241 | struct PARSING_ENVIRONMENT |
242 | { |
243 | char* curTok; // The token we are in the process of processing (for error reporting) |
244 | char* curPos; // current place in input buffer |
245 | char* endPos; // points just past the end of valid data in the buffer |
246 | |
247 | ReadStream* in; // how we fill up our buffer |
248 | |
249 | PFN_NEXTCHAR pfn_nextchar; |
250 | PFN_SYM pfn_Sym; |
251 | PFN_NEWSTRFROMTOKEN pfn_NewStrFromToken; |
252 | PFN_NEWSTATICSTRFROMTOKEN pfn_NewStaticStrFromToken; |
253 | PFN_GETDOUBLE pfn_GetDouble; |
254 | |
255 | bool bExternSource; |
256 | bool bExternSourceAutoincrement; |
257 | unsigned nExtLine; |
258 | unsigned nExtCol; |
259 | unsigned nExtLineEnd; |
260 | unsigned nExtColEnd; |
261 | unsigned curLine; // Line number (for error reporting) |
262 | |
263 | unsigned uCodePage; |
264 | |
265 | char szFileName[MAX_FILENAME_LENGTH*3+1]; |
266 | |
267 | }; |
268 | typedef LIFO<PARSING_ENVIRONMENT> PARSING_ENVIRONMENT_STACK; |
269 | |
270 | /**************************************************************************/ |
271 | /* AsmParse does all the parsing. It also builds up simple data structures, |
272 | (like signatures), but does not do the any 'heavy lifting' like define |
273 | methods or classes. Instead it calls to the Assembler object to do that */ |
274 | |
275 | class AsmParse : public ErrorReporter |
276 | { |
277 | public: |
278 | AsmParse(ReadStream* stream, Assembler *aAssem); |
279 | ~AsmParse(); |
280 | void CreateEnvironment(ReadStream* stream); |
281 | void ParseFile(ReadStream* stream); |
282 | // The parser knows how to put line numbers on things and report the error |
283 | virtual void error(const char* fmt, ...); |
284 | virtual void warn(const char* fmt, ...); |
285 | virtual void msg(const char* fmt, ...); |
286 | char *getLine(int lineNum) { return penv->in->getLine(lineNum); }; |
287 | unsigned getAll(__out char** pbuff) { return penv->in->getAll(pbuff); }; |
288 | bool Success() {return success; }; |
289 | void SetIncludePath(__in WCHAR* wz) { wzIncludePath = wz; }; |
290 | |
291 | ARG_NAME_LIST_STACK m_ANSFirst; |
292 | ARG_NAME_LIST_STACK m_ANSLast; |
293 | PARSING_ENVIRONMENT *penv; |
294 | PARSING_ENVIRONMENT_STACK PEStack; |
295 | |
296 | private: |
297 | BinStr* MakeSig(unsigned callConv, BinStr* retType, BinStr* args, int ntyargs = 0); |
298 | BinStr* MakeTypeClass(CorElementType kind, mdToken tk); |
299 | BinStr* MakeTypeArray(CorElementType kind, BinStr* elemType, BinStr* bounds); |
300 | |
301 | char* fillBuff(__in_opt __nullterminated char* curPos); // refill the input buffer |
302 | DWORD IsItUnicode(CONST LPVOID pBuff, int cb, LPINT lpi); |
303 | HANDLE hstdout; |
304 | HANDLE hstderr; |
305 | |
306 | private: |
307 | friend void yyerror(__in __nullterminated const char* str); |
308 | friend int parse_literal(unsigned curSym, __inout __nullterminated char* &curPos, BOOL translate_escapes); |
309 | friend int yyparse(); |
310 | friend int yylex(); |
311 | friend Instr* SetupInstr(unsigned short opcode); |
312 | friend int findKeyword(const char* name, size_t nameLen, unsigned short* opcode); |
313 | friend TypeDefDescr* findTypedef(__in_ecount(nameLen) char* name, size_t nameLen); |
314 | friend char* skipBlanks(__in __nullterminated char*,unsigned*); |
315 | friend char* nextBlank(__in __nullterminated char*); |
316 | friend int ProcessEOF(); |
317 | friend unsigned __int8* skipType(unsigned __int8* ptr, BOOL fFixupType); |
318 | friend void FixupConstraints(); |
319 | |
320 | Assembler* assem; // This does most of the semantic processing |
321 | bool success; // overall success of the compilation |
322 | WCHAR* wzIncludePath; |
323 | }; |
324 | |
325 | #endif |
326 | |
327 | |