| /* | |
| Copyright (c) 2009-2016 mingw-w64 project | |
| Contributing authors: Kai Tietz, Jonathan Yong | |
| Permission is hereby granted, free of charge, to any person obtaining a | |
| copy of this software and associated documentation files (the "Software"), | |
| to deal in the Software without restriction, including without limitation | |
| the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| and/or sell copies of the Software, and to permit persons to whom the | |
| Software is furnished to do so, subject to the following conditions: | |
| The above copyright notice and this permission notice shall be included in | |
| all copies or substantial portions of the Software. | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| DEALINGS IN THE SOFTWARE. | |
| */ | |
| #ifdef HAVE_CONFIG_H | |
| #include "config.h" | |
| #endif | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #ifdef HAVE_MALLOC_H | |
| #include <malloc.h> | |
| #endif | |
| #include <string.h> | |
| #include <inttypes.h> | |
| #include <stdint.h> | |
| #include "m_token.h" | |
| #include "m_ms.h" | |
| static uMToken *m_combine (sMSCtx *c, uMToken *l, uMToken *r); | |
| static uMToken *m_type (sMSCtx *c, const char *typname); | |
| static uMToken *m_cv (sMSCtx *c, const char *cv); | |
| static uMToken *m_coloncolon (sMSCtx *c, uMToken *l, uMToken *r); | |
| static uMToken *m_element (sMSCtx *c, uMToken *el); | |
| static uMToken *m_array (sMSCtx *c, uMToken *dim); | |
| static uMToken *m_scope (sMSCtx *c, uMToken *n); | |
| static uMToken *m_oper (sMSCtx *c, uMToken *n); | |
| static uMToken *m_name (sMSCtx *c, const char *str); | |
| static uMToken *m_colon (sMSCtx *c, const char *str); | |
| static uMToken *m_opname (sMSCtx *c, const char *str); | |
| static uMToken *m_rtti (sMSCtx *c, const char *str); | |
| static uMToken *m_frame (sMSCtx *c, uMToken *u); | |
| static uMToken *m_rframe (sMSCtx *c, uMToken *u); | |
| static uMToken *m_ltgt (sMSCtx *c, uMToken *u); | |
| static uMToken *m_throw (sMSCtx *c, uMToken *u); | |
| static uMToken *m_lexical_frame (sMSCtx *c, uMToken *u); | |
| static uMToken *get_decorated_name (sMSCtx *c); | |
| static uMToken *get_string_literal_type (sMSCtx *c); | |
| static uMToken *get_symbol_name (sMSCtx *c); | |
| static uMToken *get_zbuf_name (sMSCtx *c, int updateCache); | |
| static uMToken *get_dimension_signed (sMSCtx *c); | |
| static uMToken *get_dimension (sMSCtx *c,int fSigned, int fNegate); | |
| static uMToken *extract_name (sMSCtx *c, char term); | |
| static uMToken *get_scope (sMSCtx *c); | |
| static uMToken *get_template_name (sMSCtx *c, int fReadTerminator); | |
| static uMToken *get_operator_name (sMSCtx *c, int fIsTemplate, int *pfReadTemplateArguments); | |
| static uMToken *get_template_argument_list (sMSCtx *c); | |
| static uMToken *get_lexical_frame(sMSCtx *c); | |
| static uMToken *get_string_encoding (sMSCtx *c, int wantBody); | |
| static uMToken *get_template_constant (sMSCtx *c); | |
| static uMToken *get_data_type (sMSCtx *c); | |
| static uMToken *get_indirect_data_type(sMSCtx *c, uMToken *superType, char prType, uMToken *cvType, int thisFlag); | |
| static uMToken *get_primary_data_type (sMSCtx *c, uMToken *superType); | |
| static uMToken *get_based_type (sMSCtx *c); | |
| static uMToken *get_scoped_name (sMSCtx *c); | |
| static uMToken *get_basic_data_type (sMSCtx *c, uMToken *superName); | |
| static uMToken *get_pointer_reference_type (sMSCtx *c, uMToken *cvType, uMToken *superType, char ptrChar); | |
| static uMToken *get_indirect_function_type (sMSCtx *c, uMToken *superType); | |
| static uMToken *get_pointer_reference_data_type (sMSCtx *c, uMToken *superType,int isPtr); | |
| static uMToken *get_ECSU_data_type (sMSCtx *c); | |
| static uMToken *get_enum_size_type (sMSCtx *c); | |
| static uMToken *get_this_type (sMSCtx *c); | |
| static uMToken *get_calling_convention (sMSCtx *c); | |
| static uMToken *get_throw_types (sMSCtx *c); | |
| static uMToken *get_argument_types (sMSCtx *c); | |
| static uMToken *get_return_type (sMSCtx *c); | |
| static uMToken *get_array_type (sMSCtx *c, uMToken *superType); | |
| static uMToken *get_argument_list (sMSCtx *c); | |
| static uMToken *compose_decl (sMSCtx *c, uMToken *symbol); | |
| static uMToken *get_vftable_type (sMSCtx *c, uMToken *superType); | |
| static int get_number_of_dimensions (sMSCtx *c); | |
| static int get_encoded_type (sMSCtx *); | |
| static uMToken *get_vdisp_map_type (sMSCtx *c, uMToken *superType); | |
| static uMToken *get_ext_data_type (sMSCtx *c, uMToken *superType); | |
| uMToken * | |
| libmangle_decode_ms_name (libmangle_gc_context_t *gc, const char *name) | |
| { | |
| sMSCtx ctx; | |
| sCached ZNameList, ArgList, TempArgList; | |
| uMToken *ret = NULL; | |
| if (!name || *name == 0) | |
| return NULL; | |
| memset (&ctx, 0, sizeof (ctx)); | |
| ctx.gc = gc; | |
| memset (&ZNameList, 0, sizeof (ZNameList)); | |
| memset (&ArgList, 0, sizeof (ArgList)); | |
| memset (&TempArgList, 0, sizeof (TempArgList)); | |
| ctx.name = name; | |
| ctx.end = name + strlen (name); | |
| ctx.pos = ctx.name; | |
| ctx.pZNameList = &ZNameList; | |
| ctx.pArgList = &ArgList; | |
| ctx.pTemplateArgList = &TempArgList; | |
| #if 0 | |
| fprintf(stderr,"decode_ms_name: %s\n", name); | |
| #endif | |
| if (name[0] == '?') | |
| { | |
| if (name[1] == '@') | |
| { | |
| SKIP_CHAR(&ctx,2); | |
| ret = get_decorated_name (&ctx); | |
| /* CV: ??? */ | |
| } | |
| else if (name[1] == '$') | |
| { | |
| if (!(ret = get_template_name (&ctx, 0))) | |
| ret = get_decorated_name (&ctx); | |
| } | |
| else | |
| ret = get_decorated_name (&ctx); | |
| } | |
| else | |
| ret = get_decorated_name (&ctx); | |
| if (!ret) | |
| { | |
| ret = gen_name (ctx.gc, eMST_unmangled, name); | |
| } | |
| return ret; | |
| } | |
| char * | |
| libmangle_encode_ms_name (libmangle_gc_context_t *gc, uMToken *tok) | |
| { | |
| return NULL; | |
| } | |
| static uMToken * | |
| get_decorated_name (sMSCtx *c) | |
| { | |
| uMToken *n = NULL; | |
| uMToken *d = NULL; | |
| int isudc; | |
| if (GET_CHAR (c) != '?') | |
| { | |
| if (GET_CHAR (c) == 0) | |
| c->err = 1; | |
| fprintf (stderr,"*** get_decorated_name %s empty\n", c->name); | |
| return NULL; | |
| } | |
| INC_CHAR (c); | |
| n = get_symbol_name (c); | |
| isudc = (n && (MTOKEN_FLAGS (n) & MTOKEN_FLAGS_UDC)) ? 1 : 0; | |
| if (c->err) | |
| return n; | |
| if (GET_CHAR (c) != 0 && GET_CHAR (c) != '@') | |
| { | |
| d = get_scope (c); | |
| if (d) | |
| { | |
| if (c->fExplicitTemplateParams == 0) | |
| n = m_coloncolon (c, d, n); | |
| else | |
| { | |
| c->fExplicitTemplateParams = 0; | |
| n = m_combine (c, n, d); | |
| if (GET_CHAR (c) != '@') | |
| { | |
| d = get_scope (c); | |
| n = m_coloncolon (c, d, n); | |
| } | |
| } | |
| } | |
| } | |
| if (!n) | |
| return n; | |
| if (isudc) | |
| MTOKEN_FLAGS (n) |= MTOKEN_FLAGS_UDC; | |
| if (MTOKEN_FLAGS (n) & MTOKEN_FLAGS_NOTE) | |
| return n; | |
| if (GET_CHAR (c) != 0) | |
| { | |
| if (GET_CHAR (c) != '@') | |
| return NULL; | |
| INC_CHAR (c); | |
| } | |
| return compose_decl (c, n); | |
| } | |
| static uMToken * | |
| get_symbol_name (sMSCtx *c) | |
| { | |
| if (GET_CHAR (c) != '?') | |
| return get_zbuf_name (c, 1); | |
| if (c->pos[1] == '$') | |
| return get_template_name (c, 1); | |
| INC_CHAR (c); | |
| return get_operator_name (c, 0, NULL); | |
| } | |
| static uMToken * | |
| get_zbuf_name (sMSCtx *c, int updateCache) | |
| { | |
| const char *ntmp; | |
| uMToken *dim, *ret = NULL, *n = NULL; | |
| if (GET_CHAR(c) >= '0' && GET_CHAR (c) <= '9') | |
| { | |
| ret = c->pZNameList->arr[GET_CHAR (c) - '0']; | |
| INC_CHAR (c); | |
| return ret; | |
| } | |
| if (GET_CHAR (c) == '?') | |
| { | |
| n = get_template_name (c, 0); | |
| if (GET_CHAR (c) == '@') | |
| INC_CHAR (c); | |
| if (updateCache && c->pZNameList->count < 10) | |
| { | |
| c->pZNameList->arr[c->pZNameList->count] = n; | |
| c->pZNameList->count += 1; | |
| } | |
| return n; | |
| } | |
| ntmp="template-parameter-"; | |
| if (!strncmp(c->pos,"template-parameter-",19)) | |
| SKIP_CHAR (c,19); | |
| else | |
| { | |
| ntmp="generic-type-"; | |
| if (!strncmp(c->pos, "generic-type-", 13)) | |
| SKIP_CHAR (c,13); | |
| else | |
| { | |
| n = extract_name (c, '@'); | |
| if (updateCache && c->pZNameList->count < 10) | |
| { | |
| c->pZNameList->arr[c->pZNameList->count] = n; | |
| c->pZNameList->count += 1; | |
| } | |
| return n; | |
| } | |
| } | |
| dim=get_dimension_signed (c); | |
| n=chain_tok (gen_name (c->gc, eMST_templargname, ntmp), dim); | |
| if (updateCache && c->pZNameList->count < 10) | |
| { | |
| c->pZNameList->arr[c->pZNameList->count] = n; | |
| c->pZNameList->count += 1; | |
| } | |
| return n; | |
| } | |
| static uMToken * | |
| get_dimension_signed (sMSCtx *c) | |
| { | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err=1; | |
| return NULL; | |
| } | |
| if (GET_CHAR (c) != '?') | |
| return get_dimension (c, 0, 0); | |
| INC_CHAR (c); | |
| return get_dimension (c, 0, 1/* be negative*/); | |
| } | |
| static uMToken * | |
| get_dimension (sMSCtx *c, int fSigned, int fNegate) | |
| { | |
| const char *non_tt_param=NULL; | |
| uint64_t v_r = 0ULL, v1; | |
| if (GET_CHAR (c) == 'Q') | |
| { | |
| INC_CHAR (c); | |
| non_tt_param="'non-type-template-parameter"; | |
| } | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| if (GET_CHAR (c) >= '0' && GET_CHAR (c) <= '9') | |
| { | |
| uint64_t v = (uint64_t) ((GET_CHAR (c)-'0') + 1); | |
| INC_CHAR (c); | |
| return gen_dim (c->gc, eMST_dim,v, non_tt_param, fSigned, fNegate); | |
| } | |
| while (GET_CHAR (c) != '@') | |
| { | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| if (GET_CHAR (c) < 'A' || GET_CHAR (c) > 'P') | |
| { | |
| c->err = 1; | |
| return NULL; | |
| } | |
| v1=(uint64_t) (GET_CHAR (c) - 'A'); | |
| v_r = v_r*10ULL + v1; | |
| INC_CHAR (c); | |
| } | |
| if (GET_CHAR (c) !='@') | |
| { | |
| c->err = 1; | |
| return NULL; | |
| } | |
| INC_CHAR (c); | |
| return gen_dim (c->gc, eMST_dim,v_r, non_tt_param, fSigned, fNegate); | |
| } | |
| static uMToken * | |
| extract_name (sMSCtx *c, char term) | |
| { | |
| uMToken *ret; | |
| char *txt; | |
| size_t len; | |
| const char *sv = c->pos; | |
| while (GET_CHAR (c) != 0 && GET_CHAR (c) != term) | |
| { | |
| INC_CHAR (c); | |
| } | |
| if (GET_CHAR (c) != '@') | |
| { | |
| c->err = 1; | |
| return NULL; | |
| } | |
| len = (size_t) (c->pos - sv); | |
| txt = (char *) malloc (len + 1); | |
| memcpy (txt, sv, len); | |
| txt[len] = 0; | |
| INC_CHAR (c); | |
| ret = m_name (c, txt); | |
| free (txt); | |
| return ret; | |
| } | |
| static uMToken * | |
| get_scope (sMSCtx *c) | |
| { | |
| uMToken *n = NULL; | |
| while (1) | |
| { | |
| if (GET_CHAR (c) == 0 || GET_CHAR (c) == '@') | |
| break; | |
| if (c->fExplicitTemplateParams != 0 && !c->fGetTemplateArgumentList) | |
| return n; | |
| if (GET_CHAR (c) == '?') | |
| { | |
| INC_CHAR (c); | |
| if (GET_CHAR (c) == '$') | |
| { | |
| DEC_CHAR (c); | |
| n = m_coloncolon (c, get_zbuf_name (c, 1), n); | |
| } | |
| else if (GET_CHAR (c) == '%' || GET_CHAR (c) == 'A') | |
| { | |
| while (GET_CHAR (c) != '@') | |
| INC_CHAR (c); | |
| INC_CHAR (c); | |
| n = m_coloncolon (c, m_name (c, "anonymous_namespace"), n); | |
| } | |
| else if (GET_CHAR (c) == '?') | |
| { | |
| if (c->pos[1] == '_' && c->pos[2] == '?') | |
| { | |
| INC_CHAR (c); | |
| n = m_coloncolon (c, get_operator_name (c, 0,NULL), n); | |
| if (GET_CHAR (c) == '@') | |
| INC_CHAR (c); | |
| } | |
| else | |
| { | |
| n = m_coloncolon (c, gen_unary (c->gc, eMST_slashed, get_decorated_name (c)), n); | |
| } | |
| } | |
| else if (GET_CHAR (c) == 'I') | |
| { | |
| INC_CHAR (c); | |
| n = m_coloncolon (c, m_array (c, get_zbuf_name (c, 1)), n); | |
| } | |
| else | |
| n = m_coloncolon (c, get_lexical_frame (c), n); | |
| } | |
| else | |
| n = m_coloncolon (c, get_zbuf_name (c, 1), n); | |
| } | |
| if (n) | |
| n = m_scope (c, n); | |
| if (GET_CHAR (c)) | |
| { | |
| if (GET_CHAR (c) == '@') | |
| return n; | |
| } | |
| else | |
| { | |
| c->err = 2; | |
| return n; | |
| } | |
| return n; | |
| } | |
| static uMToken * | |
| get_template_name (sMSCtx *c, int fReadTerminator) | |
| { | |
| sCached rep1; | |
| sCached rep2; | |
| sCached rep3; | |
| sCached *svZName,*svArgList,*svTempArgList; | |
| uMToken *n = NULL; | |
| int fFlag = 0; | |
| if (GET_CHAR (c) !='?' || c->pos[1] != '$') | |
| return NULL; | |
| memset (&rep1, 0, sizeof (rep1)); | |
| memset (&rep2, 0, sizeof (rep2)); | |
| memset (&rep3, 0, sizeof (rep3)); | |
| svTempArgList = c->pTemplateArgList; | |
| svArgList = c->pArgList; | |
| svZName = c->pZNameList; | |
| SKIP_CHAR(c,2); | |
| c->pArgList=&rep1; | |
| c->pZNameList=&rep2; | |
| c->pTemplateArgList=&rep3; | |
| if (GET_CHAR (c) == '?') | |
| { | |
| INC_CHAR (c); | |
| n = get_operator_name (c, 1, &fFlag); | |
| } | |
| else | |
| n = get_zbuf_name (c, 1); | |
| if (!n) | |
| c->fExplicitTemplateParams = 1; | |
| if (!fFlag) | |
| { | |
| n = get_template_argument_list (c); | |
| n = m_ltgt (c, n); | |
| if (fReadTerminator) | |
| INC_CHAR (c); | |
| } | |
| c->pArgList = svArgList; | |
| c->pZNameList = svZName; | |
| c->pTemplateArgList = svTempArgList; | |
| return n; | |
| } | |
| static uMToken * | |
| get_operator_name (sMSCtx *c, int fIsTemplate, int *pfReadTemplateArguments) | |
| { | |
| const char *svName; | |
| char ch = GET_CHAR (c); | |
| uMToken *n = NULL,*h = NULL; | |
| if (!ch) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| INC_CHAR (c); | |
| switch(ch) | |
| { | |
| case '0': case '1': | |
| if (fIsTemplate) | |
| { | |
| h = m_ltgt (c, get_template_argument_list (c)); | |
| if (pfReadTemplateArguments) | |
| *pfReadTemplateArguments = 1; | |
| ch = GET_CHAR (c); | |
| if (ch == 0) | |
| return m_oper (c, h); | |
| INC_CHAR (c); | |
| } | |
| svName = c->pos; | |
| n = get_zbuf_name (c, 0); | |
| c->pos = svName; | |
| if (n && ch == '1') | |
| n=gen_unary (c->gc, eMST_destructor, n); | |
| n = chain_tok (n, h); | |
| return m_oper (c, n); | |
| case '2': | |
| return m_oper (c, m_opname (c, "operator new")); | |
| case '3': | |
| return m_oper (c, m_opname (c, "operator delete")); | |
| case '4': | |
| return m_oper (c, m_opname (c, "operator =")); | |
| case '5': | |
| return m_oper (c, m_opname (c, "operator >>")); | |
| case '6': | |
| return m_oper (c, m_opname (c, "operator <<")); | |
| case '7': | |
| return m_oper (c, m_opname (c, "operator !")); | |
| case '8': | |
| return m_oper (c, m_opname (c, "operator ==")); | |
| case '9': | |
| return m_oper (c, m_opname (c, "operator !=")); | |
| case 'A': | |
| return m_oper (c, m_opname (c, "operator []")); | |
| case 'B': | |
| n = m_opname (c, "operator"); | |
| MTOKEN_FLAGS(n) |= MTOKEN_FLAGS_UDC; | |
| n = m_oper (c, n); | |
| MTOKEN_FLAGS(n) |= MTOKEN_FLAGS_UDC; | |
| return n; | |
| case 'C': | |
| return m_oper (c, m_opname (c, "operator ->")); | |
| case 'D': | |
| return m_oper (c, m_opname (c, "operator *")); | |
| case 'E': | |
| return m_oper (c, m_opname (c, "operator ++")); | |
| case 'F': | |
| return m_oper (c, m_opname (c, "operator --")); | |
| case 'G': | |
| return m_oper (c, m_opname (c, "operator -")); | |
| case 'H': | |
| return m_oper (c, m_opname (c, "operator +")); | |
| case 'I': | |
| return m_oper (c, m_opname (c, "operator &")); | |
| case 'J': | |
| return m_oper (c, m_opname (c, "operator ->*")); | |
| case 'K': | |
| return m_oper (c, m_opname (c, "operator /")); | |
| case 'L': | |
| return m_oper (c, m_opname (c, "operator %")); | |
| case 'M': | |
| return m_oper (c, m_opname (c, "operator <")); | |
| case 'N': | |
| return m_oper (c, m_opname (c, "operator <=")); | |
| case 'O': | |
| return m_oper (c, m_opname (c, "operator >")); | |
| case 'P': | |
| return m_oper (c, m_opname (c, "operator >=")); | |
| case 'Q': | |
| return m_oper (c, m_opname (c, "operator ,")); | |
| case 'R': | |
| return m_oper (c, m_opname (c, "operator ()")); | |
| case 'S': | |
| return m_oper (c, m_opname (c, "operator ~")); | |
| case 'T': | |
| return m_oper (c, m_opname (c, "operator ^")); | |
| case 'U': | |
| return m_oper (c, m_opname (c, "operator |")); | |
| case 'V': | |
| return m_oper (c, m_opname (c, "operator &&")); | |
| case 'W': | |
| return m_oper (c, m_opname (c, "operator ||")); | |
| case 'X': | |
| return m_oper (c, m_opname (c, "operator *=")); | |
| case 'Y': | |
| return m_oper (c, m_opname (c, "operator +=")); | |
| case 'Z': | |
| return m_oper (c, m_opname (c, "operator -=")); | |
| case '_': | |
| break; | |
| default: | |
| fprintf (stderr, " *** get_operator_name unknown '%c'\n", ch); | |
| return NULL; | |
| } | |
| ch = GET_CHAR (c); | |
| if (! ch) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| INC_CHAR (c); | |
| switch(ch) | |
| { | |
| case '_': | |
| ch = GET_CHAR (c); | |
| INC_CHAR (c); | |
| switch (ch) | |
| { | |
| case 'A': | |
| return m_oper (c, m_opname (c, "__man_vec_ctor")); | |
| case 'B': | |
| return m_oper (c, m_opname (c, "__man_vec_dtor")); | |
| case 'C': | |
| return m_oper (c, m_opname (c, "__ehvec_copy_ctor")); | |
| case 'D': | |
| return m_oper (c, m_opname (c, "__ehvec_copy_ctor_vb")); | |
| } | |
| fprintf (stderr, " *** get_operator_name unknown '__%c'\n", ch); | |
| return NULL; | |
| case '0': | |
| return m_oper (c, m_opname (c, "operator /=")); | |
| case '1': | |
| return m_oper (c, m_opname (c, "operator %=")); | |
| case '2': | |
| return m_oper (c, m_opname (c, "operator >>=")); | |
| case '3': | |
| return m_oper (c, m_opname (c, "operator <<=")); | |
| case '4': | |
| return m_oper (c, m_opname (c, "operator &=")); | |
| case '5': | |
| return m_oper (c, m_opname (c, "operator |=")); | |
| case '6': | |
| return m_oper (c, m_opname (c, "operator ^=")); | |
| case '7': | |
| return m_oper (c, gen_name (c->gc, eMST_vftable, "$vftable")); | |
| case '8': | |
| return m_oper (c, gen_name (c->gc, eMST_vbtable, "$vbtable")); | |
| case '9': | |
| return m_oper (c, gen_name (c->gc, eMST_vcall, "vcall")); | |
| case 'A': | |
| return m_oper (c, m_opname (c,"typeof")); | |
| case 'B': | |
| return m_oper (c, m_opname (c,"local_static_guard")); | |
| case 'C': | |
| n = get_string_encoding (c, 1); | |
| MTOKEN_FLAGS(n) |= MTOKEN_FLAGS_NOTE; | |
| return n; | |
| case 'D': | |
| return m_oper (c, m_opname (c,"vbase_destructor")); | |
| case 'E': | |
| return m_oper (c, m_opname (c,"__vecDelDtor")); | |
| case 'F': | |
| return m_oper (c, m_opname (c,"__dflt_ctor_closure")); | |
| case 'G': | |
| return m_oper (c, m_opname (c, "__delDtor")); | |
| case 'H': | |
| return m_oper (c, m_opname (c, "__vec_ctor")); | |
| case 'I': | |
| return m_oper (c, m_opname (c, "__vec_dtor")); | |
| case 'J': | |
| return m_oper (c, m_opname (c, "__vec_ctor_vb")); | |
| case 'K': | |
| return m_oper (c, m_opname (c, "$vdispmap")); | |
| case 'L': | |
| return m_oper (c, m_opname (c, "__ehvec_ctor")); | |
| case 'M': | |
| return m_oper (c, m_opname (c, "__ehvec_dtor")); | |
| case 'N': | |
| return m_oper (c, m_name (c, "__ehvec_ctor_vb")); | |
| case 'O': | |
| return m_oper (c, m_opname (c, "__copy_ctor_closure")); | |
| case 'P': | |
| return gen_unary (c->gc, eMST_udt_returning, get_operator_name (c, 0, NULL)); | |
| case 'Q': | |
| return m_oper (c, m_opname (c, "operator 'EH'")); | |
| case 'R': | |
| ch = GET_CHAR (c); | |
| INC_CHAR (c); | |
| switch (ch) | |
| { | |
| case '0': | |
| h = m_rtti (c, "$type_descriptor"); | |
| return m_oper (c, m_combine (c, get_data_type (c) , h)); | |
| case '1': | |
| h = m_rtti (c, "base_class_descriptor"); | |
| n = m_element (c, get_dimension_signed (c)); | |
| n = chain_tok (n, m_element (c, get_dimension_signed (c))); | |
| n = chain_tok (n, m_element (c, get_dimension_signed (c))); | |
| n = chain_tok (n, m_element (c, get_dimension (c, 0, 0))); | |
| n = m_frame (c, n); | |
| return m_oper (c, gen_binary (c->gc, eMST_assign, h, n)); | |
| case '2': | |
| return m_oper (c, m_rtti (c, "base_class_array")); | |
| case '3': | |
| return m_oper (c, m_rtti (c, "class_hierarchy_descriptor")); | |
| case '4': | |
| return m_oper (c, m_rtti (c, "complete_object_locator")); | |
| } | |
| DEC_CHAR (c); | |
| fprintf (stderr, " *** Unkown RTTI %c\n", ch); | |
| c->err = 2; | |
| return NULL; | |
| case 'S': | |
| return m_oper (c, m_opname (c, "$locvftable")); | |
| case 'T': | |
| return m_oper (c, m_opname (c, "__local_vftable_ctor_closure")); | |
| case 'U': | |
| n = m_opname (c, "operator new[]"); | |
| return m_oper (c, n); | |
| case 'V': | |
| n = m_opname (c, "operator delete[]"); | |
| return m_oper (c, n); | |
| case 'W': /* omni callsig ??? */ | |
| default: | |
| fprintf (stderr, " *** get_operator_name unknown '_%c'\n", ch); | |
| return NULL; | |
| case 'X': | |
| return m_oper (c, m_opname (c, "__placement_delete_closure")); | |
| case 'Y': | |
| return m_oper (c, m_opname (c, "__placement_arrayDelete_closure")); | |
| case '?': | |
| break; | |
| } | |
| ch = GET_CHAR (c); | |
| if (!ch) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| INC_CHAR (c); | |
| switch(ch) | |
| { | |
| case '0': | |
| m_combine (c, m_name (c, "using namespace"), get_string_encoding (c, 0)); | |
| MTOKEN_FLAGS (n) |= MTOKEN_FLAGS_NOTE; | |
| return n; | |
| } | |
| fprintf (stderr, " *** get_operator_name unknown '__?%c'\n", ch); | |
| return NULL; | |
| } | |
| static uMToken * | |
| get_template_argument_list (sMSCtx *c) | |
| { | |
| uMToken *n = NULL; | |
| uMToken *h = NULL; | |
| int idx; | |
| int beFirst=1; | |
| c->fGetTemplateArgumentList = 1; | |
| do | |
| { | |
| if (GET_CHAR (c) == 0 || GET_CHAR (c) == '@') | |
| break; | |
| idx = (int) (GET_CHAR (c) - '0'); | |
| if (GET_CHAR (c) >= '0' && GET_CHAR (c) <= '9') | |
| { | |
| h = c->pTemplateArgList->arr[idx]; | |
| INC_CHAR (c); | |
| } | |
| else | |
| { | |
| const char *svPos = c->pos; | |
| if (GET_CHAR (c) =='X') | |
| { | |
| INC_CHAR (c); | |
| h = m_type (c, "void"); | |
| } | |
| else if (GET_CHAR (c) == '$' && c->pos[1] != '$') | |
| { | |
| INC_CHAR (c); | |
| h = get_template_constant (c); | |
| } | |
| else if (GET_CHAR (c) == '?') | |
| { | |
| uMToken *sdim = get_dimension_signed (c); | |
| h = gen_binary (c->gc, eMST_templateparam, m_name (c, "template-parameter"), sdim); | |
| } | |
| else | |
| h = get_primary_data_type (c, NULL); | |
| if ((int)(c->pos-svPos)>1 && | |
| c->pTemplateArgList->count < 10) | |
| { | |
| c->pTemplateArgList->arr[c->pTemplateArgList->count] = h; | |
| c->pTemplateArgList->count += 1; | |
| } | |
| } | |
| h = m_element (c, h); | |
| if (beFirst) | |
| { | |
| n = h; | |
| beFirst = 0; | |
| } | |
| else | |
| { | |
| n = chain_tok (n, h); | |
| } | |
| } | |
| while (c->err == 0); | |
| c->fGetTemplateArgumentList = 0; | |
| if (n) | |
| n = gen_unary (c->gc, eMST_template_argument_list, n); | |
| return n; | |
| } | |
| static uMToken * | |
| get_lexical_frame (sMSCtx *c) | |
| { | |
| return m_lexical_frame (c, get_dimension (c, 0, 0)); | |
| } | |
| static uMToken * | |
| get_string_encoding (sMSCtx *c, int wantBody) | |
| { | |
| uMToken *length = NULL; | |
| uMToken *crc = NULL, *h = NULL; | |
| uMToken *typ = NULL; | |
| const char *svName; | |
| size_t len; | |
| char *hp; | |
| if (GET_CHAR (c) != '@') return NULL; | |
| INC_CHAR (c); | |
| typ = get_string_literal_type (c); | |
| length = get_dimension (c, 0, 0); | |
| crc = get_dimension (c, 0, 0); | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| svName = c->pos; | |
| while (GET_CHAR (c) != 0) | |
| { | |
| if (GET_CHAR (c) == '@') | |
| break; | |
| INC_CHAR (c); | |
| } | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| len = (size_t) (c->pos - svName); | |
| hp = (char *) malloc (len + 1); | |
| memcpy (hp, svName, len); | |
| hp[len] = 0; | |
| INC_CHAR (c); | |
| h = m_name (c, hp); | |
| free (hp); | |
| if (wantBody) | |
| h = m_combine (c, typ, m_combine (c, h, m_array (c, length))); | |
| return h; | |
| } | |
| static uMToken * | |
| get_template_constant (sMSCtx *c) | |
| { | |
| char ch; | |
| uMToken *n = NULL; | |
| uMToken *exp; | |
| ch = GET_CHAR(c); | |
| if (!ch) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| INC_CHAR (c); | |
| if (ch =='E') | |
| return get_decorated_name (c); | |
| if (ch > 'E' && ch <= 'J') | |
| { | |
| if (ch >= 'H' && ch <= 'J') | |
| { | |
| exp = m_element (c, get_decorated_name (c)); | |
| if (!n) n = exp; | |
| else chain_tok (n, exp); | |
| } | |
| switch(ch) | |
| { | |
| case 'G': case 'J': | |
| exp = m_element (c, get_dimension_signed (c)); | |
| if (!n) n = exp; | |
| else chain_tok (n, exp); | |
| case 'F': case 'I': | |
| exp = m_element (c, get_dimension_signed (c)); | |
| if (!n) n = exp; | |
| else chain_tok (n, exp); | |
| case 'H': | |
| exp = m_element (c, get_dimension_signed (c)); | |
| if (!n) n = exp; | |
| else chain_tok (n, exp); | |
| break; | |
| } | |
| return m_frame (c, n); | |
| } | |
| if (ch == 'Q' || ch == 'D') | |
| { | |
| n = get_dimension_signed (c); | |
| if (ch == 'D') | |
| return gen_binary (c->gc, eMST_templateparam, m_name (c, "template-parameter"), n); | |
| return gen_binary (c->gc, eMST_nonetypetemplateparam, m_name (c, "none-type-template-parameter"), n); | |
| } | |
| if (ch == '0') | |
| return get_dimension_signed (c); | |
| if (ch == '1') | |
| { | |
| if (GET_CHAR (c) != '@') | |
| return m_combine (c, m_cv (c, "&"), get_decorated_name (c)); | |
| INC_CHAR (c); | |
| return m_name (c, "NULL"); | |
| } | |
| if (ch != '2') | |
| { | |
| fprintf (stderr, " *** get_template_constant unknown '%c'\n", ch); | |
| return NULL; | |
| } | |
| n = get_dimension_signed (c); | |
| exp = get_dimension_signed (c); | |
| return gen_binary (c->gc, eMST_exp, n, exp); | |
| } | |
| static uMToken * | |
| get_data_type (sMSCtx *c) | |
| { | |
| uMToken *n = NULL; | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return n; | |
| } | |
| if (GET_CHAR (c) == '?') | |
| { | |
| INC_CHAR (c); | |
| n = get_indirect_data_type (c, n, (char)0, NULL, 0); | |
| return get_primary_data_type (c, n); | |
| } | |
| if (GET_CHAR (c) != 'X') | |
| return get_primary_data_type (c, n); | |
| INC_CHAR (c); | |
| return m_combine (c, m_type (c, "void"), n); | |
| } | |
| static uMToken * | |
| get_indirect_data_type (sMSCtx *c, uMToken *superType, char prType, uMToken *cvType, int thisFlag) | |
| { | |
| uMToken *n = NULL, *n1 = NULL, *n2 = NULL; | |
| int state; | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| if (thisFlag != 0) | |
| return NULL; | |
| if (!superType) | |
| { | |
| if (!cvType) | |
| return NULL; | |
| return cvType; | |
| } | |
| if (MTOKEN_FLAGS (superType) & MTOKEN_FLAGS_PTRREF) | |
| return superType; | |
| if (!cvType) | |
| return superType; | |
| return m_combine (c, cvType, superType); | |
| } | |
| if (GET_CHAR (c) == '$') | |
| { | |
| INC_CHAR (c); | |
| if (GET_CHAR (c) == 'A') | |
| { | |
| n = m_cv (c, "__gc"); | |
| INC_CHAR (c); | |
| } | |
| else if (GET_CHAR (c) == 'B') | |
| { | |
| n = m_cv (c, "__pin"); | |
| INC_CHAR (c); | |
| } | |
| else | |
| { | |
| state = (int)(GET_CHAR (c) - '3')*16; | |
| INC_CHAR (c); | |
| state += (int)GET_CHAR (c); | |
| INC_CHAR (c); | |
| n = gen_value (c->gc, eMST_gcarray, (uint64_t) state, 0, 4); | |
| if (superType) | |
| { | |
| if (!(MTOKEN_FLAGS (superType) & MTOKEN_FLAGS_ARRAY)) | |
| superType = m_rframe (c, superType); | |
| n=m_combine (c, superType, n); | |
| } | |
| INC_CHAR (c); | |
| return n; | |
| } | |
| } | |
| state = (GET_CHAR (c) - (GET_CHAR (c) < 'A' ? 0x16 : 0x41)); | |
| while (1) | |
| { | |
| if (state == 4) | |
| n1 = m_combine (c, n1, m_cv (c, "__ptr64")); | |
| else if (state == 5) | |
| n2 = m_combine (c, n2, m_cv (c, "__unaligned")); | |
| else if (state != 8) | |
| { | |
| uMToken *ret = NULL; | |
| INC_CHAR (c); | |
| if (state > 31) | |
| return NULL; | |
| if (prType == '*') | |
| ret = m_cv (c, "*"); | |
| else if (prType == '&') | |
| ret = m_cv (c, "&"); | |
| ret = m_combine (c, n ,ret); | |
| ret = m_combine (c, ret, n1); | |
| ret = m_combine (c, n2, ret); | |
| if ((state & 0x10) != 0) | |
| { | |
| if (thisFlag != 0) | |
| return NULL; | |
| if (prType) | |
| { | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return ret; | |
| } | |
| else | |
| { | |
| if (ret) | |
| ret = gen_binary (c->gc, eMST_coloncolon , get_scope (c), ret); | |
| else | |
| ret = get_scope (c); | |
| } | |
| if (GET_CHAR (c) == 0) c->err = 2; | |
| else | |
| { | |
| char ch = GET_CHAR (c); | |
| INC_CHAR (c); | |
| if (ch != '@') | |
| return NULL; | |
| } | |
| } | |
| else if (GET_CHAR (c) == 0) | |
| c->err = 2; | |
| else | |
| { | |
| ret = get_scope (c); | |
| if (GET_CHAR (c) != 0) | |
| { | |
| char ch = GET_CHAR (c); | |
| INC_CHAR (c); | |
| if (ch != '@') | |
| return NULL; | |
| } | |
| else | |
| c->err = 2; | |
| } | |
| } | |
| if ((state&0xc)==0xc) | |
| { | |
| if (thisFlag != 0) | |
| return NULL; | |
| ret = m_combine (c, get_based_type (c), ret); | |
| } | |
| if ((state & 2) != 0) | |
| ret = m_combine (c, m_cv (c, "volatile"), ret); | |
| if ((state & 1) != 0) | |
| ret = m_combine (c, m_cv (c, "const"), ret); | |
| if (thisFlag != 0) | |
| { | |
| if (!ret) | |
| ret = m_name (c, ""); | |
| MTOKEN_FLAGS(ret) |= MTOKEN_FLAGS_PTRREF; | |
| return ret; | |
| } | |
| if (!superType) | |
| { | |
| if (cvType) | |
| ret = m_combine (c, ret, cvType); | |
| if (!ret) | |
| ret = m_name (c, ""); | |
| MTOKEN_FLAGS(ret) |= MTOKEN_FLAGS_PTRREF; | |
| return ret; | |
| } | |
| if (MTOKEN_FLAGS(superType) & MTOKEN_FLAGS_PTRREF) | |
| { | |
| if (cvType) | |
| { | |
| ret = m_combine (c, ret, cvType); | |
| ret = m_combine (c, ret, superType); | |
| MTOKEN_FLAGS(ret) |= MTOKEN_FLAGS_PTRREF; | |
| return ret; | |
| } | |
| } | |
| if (!(MTOKEN_FLAGS(superType)&MTOKEN_FLAGS_ARRAY)) | |
| ret = m_combine (c, ret, superType); | |
| else | |
| ret = superType; | |
| MTOKEN_FLAGS(ret) |= MTOKEN_FLAGS_PTRREF; | |
| return ret; | |
| } | |
| else | |
| { | |
| if (!n1) | |
| n1 = m_cv (c, "__restrict"); | |
| else | |
| n1 = m_combine (c, n1, m_cv (c, "__restrict")); | |
| } | |
| INC_CHAR (c); | |
| state=GET_CHAR (c)-(GET_CHAR (c) < 'A' ? 0x16 : 0x41); | |
| } | |
| } | |
| static uMToken * | |
| get_primary_data_type (sMSCtx *c, uMToken *superType) | |
| { | |
| uMToken *superName = NULL; | |
| uMToken *cvType = NULL; | |
| switch(GET_CHAR (c)) | |
| { | |
| case 0: | |
| c->err = 2; | |
| return superType; | |
| case 'B': | |
| cvType = m_cv (c, "volatile"); | |
| /* fall through */ | |
| case 'A': | |
| superName = superType; | |
| if (!superName) | |
| superName = m_name (c, ""); | |
| MTOKEN_FLAGS (superName) |= MTOKEN_FLAGS_PTRREF; | |
| INC_CHAR (c); | |
| return get_pointer_reference_type (c, cvType, superName, '&'); | |
| case '$': | |
| if (c->pos[1] == '$') | |
| { | |
| SKIP_CHAR (c, 2); | |
| break; | |
| } | |
| if (c->pos[1] == 0) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| fprintf (stderr, " *** get_primary_data_type '$%c' unknown\n", c->pos[1]); | |
| return NULL; | |
| default: | |
| return get_basic_data_type (c, superType); | |
| } | |
| switch(GET_CHAR (c)) | |
| { | |
| case 0: | |
| c->err = 2; | |
| return superType; | |
| case 'A': | |
| INC_CHAR (c); | |
| return get_indirect_function_type (c, superType); | |
| case 'B': | |
| INC_CHAR (c); | |
| return get_pointer_reference_data_type (c, superType, 1); | |
| case 'C': | |
| INC_CHAR (c); | |
| return get_basic_data_type (c, get_indirect_data_type (c, superType, (char)0, superName, 0)); | |
| } | |
| fprintf (stderr, " *** get_primary_data_type '$$%c' unknown\n", GET_CHAR (c)); | |
| return NULL; | |
| } | |
| static uMToken * | |
| get_based_type (sMSCtx *c) | |
| { | |
| uMToken *n = m_cv (c, "__based"); | |
| uMToken *p = NULL; | |
| char ch; | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return gen_binary (c->gc, eMST_based, n, NULL); | |
| } | |
| ch = GET_CHAR (c); | |
| INC_CHAR (c); | |
| switch(ch) | |
| { | |
| case '0': | |
| p = m_type (c, "void"); | |
| break; | |
| case '2': | |
| p = get_scoped_name (c); | |
| break; | |
| case '5': | |
| fprintf (stderr, " *** get_based_type unknown '%c'\n", ch); | |
| return NULL; | |
| default: | |
| fprintf (stderr, " *** get_based_type unknown '%c' (ignored)\n", ch); | |
| break; | |
| } | |
| return gen_binary (c->gc, eMST_based, n, p); | |
| } | |
| static uMToken * | |
| get_scoped_name (sMSCtx *c) | |
| { | |
| uMToken *n = NULL; | |
| n = get_zbuf_name (c, 1); | |
| if (n && GET_CHAR (c) != 0) | |
| { | |
| if (GET_CHAR (c) =='@') | |
| { | |
| INC_CHAR (c); | |
| return n; | |
| } | |
| n = m_coloncolon (c, get_scope (c), n); | |
| } | |
| if (GET_CHAR (c) == '@') | |
| { | |
| INC_CHAR (c); | |
| return n; | |
| } | |
| if (GET_CHAR (c) != 0) | |
| return n; | |
| c->err = 2; | |
| return n; | |
| } | |
| static uMToken * | |
| get_basic_data_type (sMSCtx *c, uMToken *superName) | |
| { | |
| uMToken *bTyp = NULL; | |
| uMToken *cvName = NULL; | |
| uMToken *arType = NULL; | |
| uMToken *tmp = NULL; | |
| char svChar,svChar1; | |
| int flags; | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return superName; | |
| } | |
| svChar1 = GET_CHAR (c); | |
| INC_CHAR (c); | |
| flags=~0; | |
| switch (svChar1) | |
| { | |
| case 'M': | |
| bTyp = m_type (c, "float"); | |
| break; | |
| case 'C': | |
| bTyp = m_type (c, "signed char"); | |
| break; | |
| case 'D': | |
| bTyp = m_type (c, "char"); | |
| break; | |
| case 'E': | |
| bTyp = m_type (c, "unsigned char"); | |
| break; | |
| case 'F': | |
| bTyp = m_type (c, "short"); | |
| break; | |
| case 'G': | |
| bTyp = m_type (c, "unsigned short"); | |
| break; | |
| case 'H': | |
| bTyp = m_type (c, "int"); | |
| break; | |
| case 'I': | |
| bTyp = m_type (c, "unsigned int"); | |
| break; | |
| case 'J': | |
| bTyp = m_type (c, "long"); | |
| break; | |
| case 'K': | |
| bTyp = m_type (c, "unsigned long"); | |
| break; | |
| case 'N': | |
| bTyp = m_type (c, "double"); | |
| break; | |
| case 'O': | |
| bTyp = m_type (c, "long double"); | |
| break; | |
| case 'P': | |
| return get_pointer_reference_type (c, bTyp, superName, '*'); | |
| case 'Q': | |
| if (!superName) | |
| bTyp = m_cv (c, "const"); | |
| return get_pointer_reference_type (c, bTyp, superName, '*'); | |
| case 'R': | |
| if (!superName) | |
| bTyp = m_cv (c, "volatile"); | |
| return get_pointer_reference_type (c, bTyp, superName, '*'); | |
| case 'S': | |
| if (!superName) | |
| { | |
| bTyp = m_cv (c, "const"); | |
| bTyp = m_combine (c, bTyp, m_cv (c, "volatile")); | |
| } | |
| return get_pointer_reference_type (c, bTyp, superName, '*'); | |
| case '_': | |
| svChar = GET_CHAR (c); | |
| INC_CHAR (c); | |
| switch(svChar) | |
| { | |
| case 'N': | |
| bTyp = m_type (c, "bool"); | |
| break; | |
| case 'O': | |
| if (!superName) | |
| superName = m_name (c, ""); | |
| cvName=superName; | |
| MTOKEN_FLAGS (cvName) |= MTOKEN_FLAGS_ARRAY; | |
| arType = get_pointer_reference_type (c, bTyp, cvName, 0); | |
| if (!(MTOKEN_FLAGS (arType)&MTOKEN_FLAGS_ARRAY)) | |
| arType = m_combine (c, arType, m_array (c, NULL)); | |
| return arType; | |
| case 'W': | |
| bTyp = m_type (c, "wchar_t"); | |
| break; | |
| case 'X': | |
| case 'Y': | |
| DEC_CHAR (c); | |
| if (!(bTyp = get_ECSU_data_type (c))) | |
| return NULL; | |
| break; | |
| case 'D': | |
| bTyp = m_type (c, "__int8"); | |
| break; | |
| case 'E': | |
| bTyp = m_type (c, "unsigned __int8"); | |
| break; | |
| case 'F': | |
| bTyp = m_type (c, "__int16"); | |
| break; | |
| case 'G': | |
| bTyp = m_type (c, "unsigned __int16"); | |
| break; | |
| case 'H': | |
| bTyp = m_type (c, "__int32"); | |
| break; | |
| case 'I': | |
| bTyp = m_type (c, "unsigned __int32"); | |
| break; | |
| case 'J': | |
| bTyp = m_type (c, "__int64"); | |
| break; | |
| case 'K': | |
| bTyp = m_type (c, "unsigned __int64"); | |
| break; | |
| case 'L': | |
| bTyp = m_type (c, "__int128"); | |
| break; | |
| case 'M': | |
| bTyp = m_type (c, "unsigned"); | |
| break; | |
| case '$': | |
| bTyp = get_basic_data_type (c, superName); | |
| return m_combine (c, m_cv (c, "__w64"), bTyp); | |
| default: | |
| fprintf (stderr, " *** get_basic_data_type unknown '_%c' (ignored).\n", svChar); | |
| bTyp = m_type (c, "UNKNOWN"); | |
| break; | |
| } | |
| break; | |
| default: | |
| DEC_CHAR (c); | |
| bTyp = get_ECSU_data_type (c); | |
| if (!bTyp) | |
| return bTyp; | |
| break; | |
| } | |
| if (superName) | |
| bTyp = m_combine (c, bTyp, superName); | |
| return bTyp; | |
| } | |
| static uMToken * | |
| get_pointer_reference_type (sMSCtx *c, uMToken *cvType, uMToken *superType, char ptrChar) | |
| { | |
| uMToken *n = NULL; | |
| if (ptrChar == '&') | |
| n = m_cv (c, "&"); | |
| else if (ptrChar == '*') | |
| n = m_cv (c, "*"); | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| if (cvType) | |
| { | |
| if (!n) | |
| n = cvType; | |
| else | |
| n = m_combine (c, n, cvType); | |
| } | |
| if (superType) | |
| n = m_combine (c, n, superType); | |
| return n; | |
| } | |
| if (GET_CHAR (c) < '6' || GET_CHAR (c) > '9') | |
| { | |
| if (GET_CHAR (c) != '_') | |
| return get_pointer_reference_data_type (c, | |
| get_indirect_data_type (c, superType, ptrChar, cvType, 0),(ptrChar=='*' ? 1 : 0)); | |
| } | |
| if (cvType) | |
| { | |
| if (!superType || !(MTOKEN_FLAGS (superType)&MTOKEN_FLAGS_PTRREF)) | |
| { | |
| if (!n) | |
| n = cvType; | |
| else | |
| n = m_combine (c, n, cvType); | |
| } | |
| } | |
| if (superType) | |
| { | |
| if (!n) | |
| n = superType; | |
| else | |
| n = m_combine (c, n, superType); | |
| } | |
| return get_indirect_function_type (c, n); | |
| } | |
| static uMToken * | |
| get_indirect_function_type (sMSCtx *c, uMToken *superType) | |
| { | |
| uMToken *retType = NULL; | |
| uMToken *n1 = NULL, *n2 = NULL; | |
| int flag; | |
| int cidx; | |
| char ch = GET_CHAR (c); | |
| if (ch == 0) | |
| { | |
| c->err = 2; | |
| return superType; | |
| } | |
| if (ch != '_' && (ch < '6' || ch > '9')) | |
| return NULL; | |
| cidx = (int) (ch - '6'); | |
| INC_CHAR (c); | |
| if (ch == '_') | |
| { | |
| ch = GET_CHAR (c); | |
| if (ch == 0) | |
| { | |
| c->err = 2; | |
| return superType; | |
| } | |
| if (ch < 'A' || ch > 'D') | |
| return NULL; | |
| cidx=(int)(ch - 'A') + 4; | |
| INC_CHAR (c); | |
| } | |
| n2 = superType; | |
| flag = cidx & 2; | |
| if (flag) | |
| { | |
| ch = GET_CHAR (c); | |
| if (ch == 0) | |
| { | |
| c->err = 2; | |
| return n2; | |
| } | |
| n2 = m_coloncolon (c, get_scope (c), n2); | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return n2; | |
| } | |
| if (GET_CHAR (c) != '@') | |
| return NULL; | |
| INC_CHAR (c); | |
| n1 = get_this_type (c); | |
| } | |
| if (cidx & 4) | |
| n2 = m_combine (c, get_based_type (c), n2); | |
| n2 = m_combine (c, get_calling_convention (c), n2); | |
| if (superType) | |
| n2 = m_rframe (c, n2); | |
| retType = get_return_type (c); | |
| n2 = m_combine (c, n2, m_rframe (c, get_argument_types (c))); | |
| if (flag) | |
| n2 = m_combine (c, n2, n1); | |
| n2 = m_combine (c, n2, get_throw_types (c)); | |
| return m_combine (c, retType, n2); | |
| } | |
| static uMToken * | |
| get_pointer_reference_data_type (sMSCtx *c, uMToken *superType,int isPtr) | |
| { | |
| uMToken *n = NULL; | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return superType; | |
| } | |
| if (isPtr && GET_CHAR (c) == 'X') | |
| { | |
| INC_CHAR (c); | |
| n = m_type (c, "void"); | |
| if (superType) | |
| n = m_combine (c, n, superType); | |
| return n; | |
| } | |
| if (GET_CHAR (c) == 'Y') | |
| { | |
| INC_CHAR (c); | |
| return get_array_type (c, superType); | |
| } | |
| if (GET_CHAR (c) != '_') | |
| return get_basic_data_type (c, superType); | |
| if (c->pos[1] != 'Z') | |
| return get_basic_data_type (c, superType); | |
| SKIP_CHAR (c, 2); | |
| n = m_cv (c, "__box"); | |
| return m_combine (c, n, get_basic_data_type (c, superType)); | |
| } | |
| static uMToken * | |
| get_ECSU_data_type (sMSCtx *c) | |
| { | |
| char ch = GET_CHAR (c); | |
| uMToken *n = NULL; | |
| if (!ch) | |
| { | |
| c->err = 2; | |
| return m_type (c, "no-ecsu"); | |
| } | |
| INC_CHAR (c); | |
| switch (ch) | |
| { | |
| default: | |
| fprintf (stderr, " *** get_ECSU_data_type unknown %c\n", ch); | |
| n = m_type (c, "unknown ecsu"); | |
| break; | |
| case 'T': | |
| n = m_type (c, "union"); | |
| break; | |
| case 'U': | |
| n = m_type (c, "struct"); | |
| break; | |
| case 'V': | |
| n = m_type (c, "class"); | |
| break; | |
| case 'W': | |
| n = m_type (c, "enum"); | |
| get_enum_size_type (c); | |
| break; | |
| case 'X': | |
| n = m_type (c, "coclass"); | |
| break; | |
| case 'Y': | |
| n = m_type (c, "cointerface"); | |
| break; | |
| } | |
| return gen_binary (c->gc, eMST_ecsu, n, get_scoped_name (c)); | |
| } | |
| static uMToken * | |
| get_string_literal_type (sMSCtx *c) | |
| { | |
| uMToken *n = NULL; | |
| char ch = GET_CHAR (c); | |
| if (ch == 0) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| if (ch == '_') | |
| { | |
| INC_CHAR (c); | |
| n = m_cv (c, "const"); | |
| } | |
| ch = GET_CHAR (c); | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| INC_CHAR (c); | |
| switch (ch) | |
| { | |
| case '0': | |
| return m_combine (c, n, m_type (c, "char")); | |
| case '1': | |
| return m_combine (c, n, m_type (c, "wchar_t")); | |
| } | |
| fprintf (stderr, " *** get_string_literal_type unknown '_%c'\n", ch); | |
| return NULL; | |
| } | |
| static uMToken * | |
| get_enum_size_type (sMSCtx *c) | |
| { | |
| uMToken *n = NULL; | |
| switch (GET_CHAR (c)) | |
| { | |
| case 0: | |
| c->err = 2; | |
| return NULL; | |
| case '0': | |
| n = m_type (c, "char"); | |
| break; | |
| case '1': | |
| n = m_type (c, "unsigned char"); | |
| break; | |
| case '2': | |
| n = m_type (c, "short"); | |
| break; | |
| case '3': | |
| n = m_type (c, "unsigned short"); | |
| break; | |
| case '4': | |
| n = m_type (c, "int"); | |
| break; | |
| case '5': | |
| n = m_type (c, "unsigned int"); | |
| break; | |
| case '6': | |
| n = m_type (c, "long"); | |
| break; | |
| case '7': | |
| n = m_type (c, "unsigned long"); | |
| break; | |
| default: | |
| fprintf (stderr, " *** get_enum_size_type unknown ,%c'\n", GET_CHAR (c)); | |
| return NULL; | |
| } | |
| INC_CHAR (c); | |
| return n; | |
| } | |
| static uMToken * | |
| get_this_type (sMSCtx *c) | |
| { | |
| return get_indirect_data_type (c, NULL, (char)0, NULL, 1); | |
| } | |
| static uMToken * | |
| get_calling_convention (sMSCtx *c) | |
| { | |
| char ch = GET_CHAR (c); | |
| if (ch == 0) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| INC_CHAR (c); | |
| switch(ch) | |
| { | |
| case 'A': case 'B': | |
| return m_cv (c, "__cdecl"); | |
| case 'C': case 'D': | |
| return m_cv (c, "__pascal"); | |
| case 'E': case 'F': | |
| return m_cv (c, "__thiscall"); | |
| case 'G': case 'H': | |
| return m_cv (c, "__stdcall"); | |
| case 'I': case 'J': | |
| return m_cv (c, "__fastcall"); | |
| case 'K': case 'L': | |
| return m_cv (c, ""); | |
| case 'M': | |
| return m_cv (c, "__clrcall"); | |
| } | |
| fprintf (stderr, " *** get_calling_convention ,%c' unknown.\n", ch); | |
| return NULL; | |
| } | |
| static uMToken * | |
| get_throw_types (sMSCtx *c) | |
| { | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return m_throw (c, m_rframe (c, NULL)); | |
| } | |
| if (GET_CHAR (c) == 'Z') | |
| { | |
| INC_CHAR (c); | |
| return m_name (c, ""); | |
| } | |
| return m_throw (c, m_rframe (c, get_argument_types (c))); | |
| } | |
| static uMToken * | |
| get_argument_types (sMSCtx *c) | |
| { | |
| char ch = GET_CHAR (c); | |
| uMToken *n = NULL; | |
| if (ch == 'X') | |
| { | |
| INC_CHAR (c); | |
| return m_element (c, m_type (c, "void")); | |
| } | |
| if (ch == 'Z') | |
| { | |
| INC_CHAR (c); | |
| return m_element (c, m_type (c, "...")); | |
| } | |
| n = get_argument_list (c); | |
| if (!n || c->err) | |
| return n; | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return n; | |
| } | |
| if (GET_CHAR (c) == '@') | |
| { | |
| INC_CHAR (c); | |
| return n; | |
| } | |
| if (GET_CHAR (c) == 'Z') | |
| { | |
| INC_CHAR (c); | |
| return chain_tok (n, m_element (c, m_type (c, "..."))); | |
| } | |
| fprintf (stderr, " *** get_argument_types unknown ,%c'\n", GET_CHAR (c)); | |
| return NULL; | |
| } | |
| static uMToken * | |
| get_return_type (sMSCtx *c) | |
| { | |
| if (GET_CHAR (c) == '@') | |
| { | |
| INC_CHAR (c); | |
| return m_name (c, ""); | |
| } | |
| return get_data_type (c); | |
| } | |
| static int | |
| get_number_of_dimensions (sMSCtx *c) | |
| { | |
| int ret = 0; | |
| if (GET_CHAR (c)) | |
| return 0; | |
| if (GET_CHAR (c) >= '0' && GET_CHAR (c) <= '9') | |
| { | |
| ret = (int) (GET_CHAR (c) - '0') + 1; | |
| INC_CHAR (c); | |
| return ret; | |
| } | |
| while (GET_CHAR (c) != '@') | |
| { | |
| if (GET_CHAR (c) == 0) | |
| return 0; | |
| if (GET_CHAR (c) < 'A' || GET_CHAR (c) > 'P') | |
| return -1; | |
| ret <<= 4; | |
| ret += (int) (GET_CHAR (c) - 'A'); | |
| INC_CHAR (c); | |
| } | |
| if (GET_CHAR (c) == '@') | |
| { | |
| INC_CHAR (c); | |
| return ret; | |
| } | |
| return -1; | |
| } | |
| static uMToken * | |
| get_array_type (sMSCtx *c, uMToken *superType) | |
| { | |
| uMToken *n = NULL, *h = NULL; | |
| int dims; | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| if (superType) | |
| return m_combine (c, m_rframe (c, superType), m_array (c, NULL)); | |
| return m_array (c, NULL); | |
| } | |
| dims = get_number_of_dimensions (c); | |
| if ( dims < 0) | |
| dims=0; | |
| if (!dims) | |
| { | |
| c->err = 2; | |
| return get_basic_data_type (c, m_array (c, NULL)); | |
| } | |
| if (superType && (MTOKEN_FLAGS(superType)&MTOKEN_FLAGS_ARRAY)) | |
| h = m_array (c, NULL); | |
| do { | |
| n = m_array (c, get_dimension (c, 0, 0)); | |
| if (!h) | |
| h = n; | |
| else | |
| h = m_combine (c, h, n); | |
| } while (--dims != 0); | |
| if (superType) | |
| { | |
| if (!(MTOKEN_FLAGS(superType)&MTOKEN_FLAGS_ARRAY)) | |
| superType = m_rframe (c, superType); | |
| h = m_combine (c, superType, h); | |
| } | |
| n = get_primary_data_type (c, h); | |
| MTOKEN_FLAGS (n) |= MTOKEN_FLAGS_ARRAY; | |
| return n; | |
| } | |
| static uMToken * | |
| get_argument_list (sMSCtx *c) | |
| { | |
| uMToken *n = NULL, *h = NULL; | |
| int idx; | |
| if (c->err) | |
| return NULL; | |
| do { | |
| h = NULL; | |
| if (GET_CHAR (c) == '@' || GET_CHAR (c) == 'Z') | |
| return n; | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return n; | |
| } | |
| idx= (int) (GET_CHAR (c) - '0'); | |
| if (idx < 0 || idx > 9) | |
| { | |
| const char *svName = c->pos; | |
| h = get_primary_data_type (c, NULL); | |
| if ((size_t) (c->pos - svName)>1 && c->pArgList->count < 10) | |
| { | |
| c->pArgList->arr[c->pArgList->count]=h; | |
| c->pArgList->count += 1; | |
| } | |
| } | |
| else | |
| { | |
| INC_CHAR (c); | |
| h = c->pArgList->arr[idx]; | |
| } | |
| h = m_element (c, h); | |
| n = chain_tok (n, h); | |
| } while (c->err != 2); | |
| return n; | |
| } | |
| static uMToken * | |
| get_vdisp_map_type (sMSCtx *c, uMToken *superType) | |
| { | |
| uMToken *n = superType; | |
| uMToken *h = get_scope (c); | |
| h = m_combine (c, m_name (c, "for"), h); | |
| h = m_frame (c, h); | |
| n = m_combine (c, n, h); | |
| if (GET_CHAR (c) =='@') | |
| INC_CHAR (c); | |
| return n; | |
| } | |
| static uMToken * | |
| get_ext_data_type (sMSCtx *c, uMToken *superType) | |
| { | |
| uMToken *dt = NULL,*n = NULL; | |
| dt = get_data_type (c); | |
| n = get_indirect_data_type (c, NULL, (char)0, NULL, 0); | |
| if (superType) | |
| n = m_combine (c, n, superType); | |
| return m_combine (c, dt, n); | |
| } | |
| static uMToken *getVCallThunkType(sMSCtx *c) | |
| { | |
| if (GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return NULL; | |
| } | |
| if (GET_CHAR (c) != 'A') | |
| { | |
| fprintf (stderr, " *** getVCallThunkType unknown '%c'\n", GET_CHAR (c)); | |
| return NULL; | |
| } | |
| INC_CHAR (c); | |
| return m_cv (c, "{flat}"); | |
| } | |
| static uMToken * | |
| get_vftable_type (sMSCtx *c, uMToken *superType) | |
| { | |
| uMToken *n = superType; | |
| if (c->err || GET_CHAR (c) == 0) | |
| { | |
| c->err = 2; | |
| return n; | |
| } | |
| n = m_combine (c, get_indirect_data_type (c, NULL, (char)0, NULL, 0), n); | |
| if (c->err == 2 || !n) | |
| return n; | |
| if (GET_CHAR (c) != '@') | |
| { | |
| n = m_combine (c, n, m_name (c, "{for ")); | |
| while (c->err == 0) | |
| { | |
| if (GET_CHAR (c) ==0 || GET_CHAR (c) =='@') | |
| break; | |
| n = m_combine (c, n, m_lexical_frame (c, get_scope (c))); | |
| if (GET_CHAR (c) == '@') | |
| INC_CHAR (c); | |
| if (c->err == 0 && GET_CHAR (c) != '@') | |
| n = m_combine (c, n, m_name (c, "s ")); | |
| } | |
| if (c->err == 0) | |
| { | |
| if (GET_CHAR (c) == 0) | |
| c->err = 2; | |
| n = m_combine (c, n, m_name (c, "}")); | |
| } | |
| if (GET_CHAR (c) != '@') | |
| return n; | |
| } | |
| INC_CHAR (c); | |
| return n; | |
| } | |
| static uMToken * | |
| compose_decl (sMSCtx *c, uMToken *symbol) | |
| { | |
| uMToken *n = NULL; | |
| int et = get_encoded_type (c); | |
| int nIsUDC = (symbol && (MTOKEN_FLAGS (symbol) & MTOKEN_FLAGS_UDC)) ? 1 : 0; | |
| if (et==0xffff) | |
| return NULL; | |
| if (et==0xfffe) | |
| { | |
| c->err = 2; | |
| return symbol; | |
| } | |
| if (et==0xfffd) | |
| return symbol; | |
| if ((et&0x8000)==0) | |
| { | |
| n = symbol; | |
| if ((et&0x7c00)==0x6800) | |
| return get_vftable_type (c, n); | |
| if ((et&0x7c00)==0x7000) | |
| return get_vftable_type (c, n); | |
| if ((et&0x7c00)==0x6000) | |
| { | |
| uMToken *ll = m_element (c, get_dimension (c, 0, 0)); | |
| ll = m_frame (c, ll); | |
| return m_combine (c, n, ll); | |
| } | |
| if ((et&0x7c00)==0x7c00) | |
| return get_vdisp_map_type (c, n); | |
| if ((et&0x7c00)==0x7800) | |
| return n; | |
| n = get_ext_data_type (c, n); | |
| if ((et&0x6000)!=0) | |
| { | |
| if ((et&0x1000)) | |
| n = m_combine (c, m_colon (c, "[thunk]"), n); | |
| return n; | |
| } | |
| n = m_combine (c, m_cv (c, "static"), n); | |
| if ((et&0x700) == 0x400 || (et&0x700) == 0x500) | |
| n = m_combine (c, m_cv (c, "virtual"), n); | |
| switch ((et&0x1800)) | |
| { | |
| case 0x800: | |
| n = m_combine (c, m_colon (c, "private"), n); | |
| break; | |
| case 0x1000: | |
| n = m_combine (c, m_colon (c, "protected"), n); | |
| break; | |
| case 0x0: | |
| n = m_combine (c, m_colon (c, "public"), n); | |
| break; | |
| } | |
| if ((et&0x400)) | |
| n = m_combine (c, m_colon (c, "[thunk]"), n); | |
| return n; | |
| } | |
| if ((et&0x1f00)==0x1000 || (et&0x1f00)==0x1400) | |
| { | |
| n = symbol; | |
| if ((et&0x6000)!=0 || (et&0x7f00)==0x1400) | |
| n = m_combine (c, n, m_name (c, "local_static_destructor_helper")); | |
| n = get_ext_data_type (c, n); | |
| symbol = NULL; | |
| } | |
| else if ((et&0x1f00)==0x1500 || (et&0x1f00)==0x1600) | |
| { | |
| n = symbol; | |
| symbol = NULL; | |
| if ((et&0x1f00)==0x1500) | |
| n = m_combine (c, n, m_name (c, "template_static_data_member_constructor_helper")); | |
| else if ((et&0x1f00)==0x1600) | |
| n = m_combine (c, n, m_name (c, "template_static_data_member_destructor_helper")); | |
| } | |
| else | |
| { | |
| if ((et&0x4000)!=0) | |
| n = get_based_type (c); | |
| if ((et&0x1800)==0x1800) | |
| { | |
| uMToken *hh = NULL; | |
| hh = m_element (c, get_dimension (c, 0, 0)); | |
| hh = chain_tok (hh, m_element (c, getVCallThunkType (c))); | |
| n = m_combine (c, symbol, | |
| m_frame (c, hh)); | |
| n = m_combine (c, get_calling_convention (c), n); | |
| } | |
| else | |
| { | |
| uMToken *h = NULL; | |
| uMToken *n1 = NULL; | |
| uMToken *n2 = NULL; | |
| uMToken *n3 = NULL; | |
| if ((et&0x1000)!=0 || (et&0x1c00)==0xc00) | |
| { | |
| if ((et&0x1f00)==0xd00) | |
| n1 = get_dimension (c, 1, 0); | |
| n2 = get_dimension (c, 1, 0); | |
| } | |
| if (((et&0x1800)==0x800) && (et&0x700)!=0x200) | |
| n3 = get_this_type (c); | |
| n = m_combine (c, get_calling_convention (c), n); | |
| if (symbol) | |
| n = m_combine (c, n, symbol); | |
| if (nIsUDC) | |
| n = m_combine (c, n, get_return_type (c)); | |
| h = get_return_type (c); | |
| if (((et&0x1800)!=0x800 ? (et&0x1000)!=0 : (et&0x400)!=0)) | |
| { | |
| if (((et&0x1800)==0x800) && (et&0x700)==0x500) | |
| { | |
| n2 = chain_tok ( | |
| m_element (c, n1), | |
| m_element (c, n2)); | |
| n2 = m_frame (c, n2); | |
| n = m_combine (c, n, m_combine (c, m_name (c, "vtordisp"), n2)); | |
| } | |
| else | |
| { | |
| n2 = m_frame (c, m_element (c, n2)); | |
| n = m_combine (c, n, m_combine (c, m_name (c, "adjustor"), n2)); | |
| } | |
| } | |
| n = m_combine (c, n, m_rframe (c, get_argument_types (c))); | |
| if (((et&0x1800)==0x800) && (et&0x700)!=0x200) | |
| n = m_combine (c, n, n3); | |
| n = m_combine (c, n, get_throw_types (c)); | |
| if (h) | |
| n = m_combine (c, h, n); | |
| } | |
| } | |
| if ((et&0x1800)!=0x800) { | |
| if ((et&0x1000)) | |
| n = m_combine (c, m_colon (c, "[thunk]"), n); | |
| return n; | |
| } | |
| switch ((et&0x700)) | |
| { | |
| case 0x200: | |
| n = m_combine (c, m_cv (c, "static"), n); | |
| break; | |
| case 0x100: | |
| case 0x400: | |
| case 0x500: | |
| n = m_combine (c, m_cv (c, "virtual"), n); | |
| break; | |
| } | |
| switch ((et&0xc0)) | |
| { | |
| case 0x40: | |
| n = m_combine (c, m_colon (c, "private"), n); | |
| break; | |
| case 0x80: | |
| n = m_combine (c, m_colon (c, "protected"), n); | |
| break; | |
| case 0x0: | |
| n = m_combine (c, m_colon (c, "public"), n); | |
| break; | |
| } | |
| if ((et&0x400)) | |
| n = m_combine (c, m_colon (c, "[thunk]"), n); | |
| return n; | |
| } | |
| static int | |
| get_encoded_type (sMSCtx *c) | |
| { | |
| int ret; | |
| for(;;) | |
| { | |
| ret = 0; | |
| if (GET_CHAR (c) == '_') | |
| { | |
| INC_CHAR (c); | |
| ret = 0x4000; | |
| } | |
| if (GET_CHAR (c) >= 'A' && GET_CHAR (c) <= 'Z') | |
| { | |
| int chc = (int) (GET_CHAR (c) - 'A'); | |
| INC_CHAR (c); | |
| if ((chc & 1) == 0) | |
| ret |= 0x8000; | |
| else | |
| ret |= 0xa000; | |
| if (chc >= 0x18) | |
| return ret; | |
| ret |= 0x800; | |
| switch((chc&0x18)) | |
| { | |
| case 0: | |
| ret |= 0x40; | |
| break; | |
| case 8: | |
| ret |= 0x80; | |
| break; | |
| case 0x10: | |
| break; | |
| } | |
| switch((chc&6)) | |
| { | |
| case 0: | |
| return ret; | |
| case 2: | |
| return ret|0x200; | |
| case 4: | |
| return ret|0x100; | |
| case 6: | |
| return ret|0x400; | |
| } | |
| return 0xffff; | |
| } | |
| if (GET_CHAR (c) != '$') | |
| { | |
| INC_CHAR (c); | |
| switch(c->pos[-1]) | |
| { | |
| case '0': | |
| return 0x800; | |
| case '1': | |
| return 0x1000; | |
| case '2': | |
| return 0; | |
| case '3': | |
| return 0x4000; | |
| case '4': | |
| return 0x2000; | |
| case '5': | |
| return 0x6000; | |
| case '6': | |
| return 0x6800; | |
| case '7': | |
| return 0x7000; | |
| case '8': | |
| return 0x7800; | |
| case '9': | |
| return 0xfffd; | |
| case 0: | |
| DEC_CHAR (c); | |
| return 0xfffe; | |
| } | |
| DEC_CHAR (c); | |
| return 0xffff; | |
| } | |
| INC_CHAR (c); | |
| switch(GET_CHAR (c)) | |
| { | |
| case 'A': | |
| INC_CHAR (c); | |
| return ret|0x9000; | |
| case 'B': | |
| INC_CHAR (c); | |
| return ret|0x9800; | |
| case 'C': | |
| INC_CHAR (c); | |
| return ret|0x7c00; | |
| case 'D': | |
| INC_CHAR (c); | |
| return ret|0x9100; | |
| case 'E': | |
| INC_CHAR (c); | |
| return ret|0x9200; | |
| case 0: | |
| INC_CHAR (c); | |
| return 0xfffe; | |
| case '0': | |
| INC_CHAR (c); | |
| return ret|0x8d40; | |
| case '1': | |
| INC_CHAR (c); | |
| return ret|0xad40; | |
| case '2': | |
| INC_CHAR (c); | |
| return ret|0x8d80; | |
| case '3': | |
| INC_CHAR (c); | |
| return ret|0xad80; | |
| case '4': | |
| INC_CHAR (c); | |
| return ret|0x8d00; | |
| case '5': | |
| INC_CHAR (c); | |
| return ret|0xad00; | |
| case '$': | |
| if (c->pos[1] == 'P') | |
| INC_CHAR (c); | |
| break; | |
| default: | |
| return 0xffff; | |
| } | |
| INC_CHAR (c); | |
| switch(GET_CHAR (c)) | |
| { | |
| case 'F': case 'G': case 'H': case 'I': case 'L': case 'M': | |
| INC_CHAR (c); | |
| break; | |
| case 'J': case 'K': case 'N': case 'O': | |
| INC_CHAR (c); | |
| if (GET_CHAR (c) < '0' || GET_CHAR (c) > '9') | |
| { | |
| INC_CHAR (c); | |
| return 0xffff; | |
| } | |
| { | |
| int skip = (GET_CHAR (c) - '0') + 1; | |
| SKIP_CHAR (c, skip); | |
| } | |
| break; | |
| default: | |
| INC_CHAR (c); | |
| return ret; | |
| } | |
| } | |
| } | |
| static uMToken * | |
| m_combine (sMSCtx *c, uMToken *l, uMToken *r) | |
| { | |
| if (!l && !r) | |
| return NULL; | |
| if (!l) | |
| return r; | |
| if (!r) | |
| return l; | |
| return gen_binary (c->gc, eMST_combine, l, r); | |
| } | |
| static uMToken * | |
| m_type (sMSCtx *c, const char *typname) | |
| { | |
| return gen_name (c->gc, eMST_type, typname); | |
| } | |
| static uMToken * | |
| m_cv (sMSCtx *c, const char *cv) | |
| { | |
| return gen_name (c->gc, eMST_cv, cv); | |
| } | |
| static uMToken * | |
| m_coloncolon (sMSCtx *c, uMToken *l, uMToken *r) | |
| { | |
| if (!l) | |
| return r; | |
| if (!r) | |
| return l; | |
| return gen_binary (c->gc, eMST_coloncolon, l, r); | |
| } | |
| static uMToken * | |
| m_element (sMSCtx *c, uMToken *el) | |
| { | |
| return gen_unary (c->gc, eMST_element, el); | |
| } | |
| static uMToken * | |
| m_array (sMSCtx *c, uMToken *dim) | |
| { | |
| return gen_unary (c->gc, eMST_array, dim); | |
| } | |
| static uMToken * | |
| m_scope (sMSCtx *c, uMToken *n) | |
| { | |
| return gen_unary (c->gc, eMST_scope, n); | |
| } | |
| static uMToken * | |
| m_oper (sMSCtx *c, uMToken *n) | |
| { | |
| return gen_unary (c->gc, eMST_oper, n); | |
| } | |
| static uMToken * | |
| m_name (sMSCtx *c, const char *str) | |
| { | |
| return gen_name (c->gc, eMST_name, str); | |
| } | |
| static uMToken * | |
| m_colon (sMSCtx *c, const char *str) | |
| { | |
| return gen_name (c->gc, eMST_colon, str); | |
| } | |
| static uMToken * | |
| m_opname (sMSCtx *c, const char *str) | |
| { | |
| return gen_name (c->gc, eMST_opname, str); | |
| } | |
| static uMToken * | |
| m_rtti (sMSCtx *c, const char *str) | |
| { | |
| return gen_name (c->gc, eMST_rtti, str); | |
| } | |
| static uMToken * | |
| m_frame (sMSCtx *c, uMToken *u) | |
| { | |
| return gen_unary (c->gc, eMST_frame, u); | |
| } | |
| static uMToken * | |
| m_rframe (sMSCtx *c, uMToken *u) | |
| { | |
| return gen_unary (c->gc, eMST_rframe, u); | |
| } | |
| static uMToken * | |
| m_ltgt (sMSCtx *c, uMToken *u) | |
| { | |
| return gen_unary (c->gc, eMST_ltgt, u); | |
| } | |
| static uMToken * | |
| m_throw (sMSCtx *c, uMToken *u) | |
| { | |
| return gen_unary (c->gc, eMST_throw, u); | |
| } | |
| static uMToken * | |
| m_lexical_frame (sMSCtx *c, uMToken *u) | |
| { | |
| return gen_unary (c->gc, eMST_lexical_frame, u); | |
| } |