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