char *FormatName( NAME name, VBUF *pvbuf ) /****************************************/ { VBUF prefix; bool ctordtor; VbufInit( pvbuf ); VbufInit( &prefix ); ctordtor = fmtSymName( NULL, name, &prefix, pvbuf, FF_NULL ); if( !ctordtor ) { VbufConcVbuf( pvbuf, &prefix ); } VbufFree( &prefix ); return( strrev( VbufString( pvbuf ) ) ); }
static void statsPrint( // PRINT STATISTICS INITFINI* defn ) // - definition { defn = defn; if( CompFlags.stats_printed ) { return; } if( CompFlags.quiet_mode ) { return; } if( ! CompFlags.srcfile_compiled ) { return; } if( WholeFName != NULL ) { VBUF buffer; VbufInit( &buffer ); VbufConcStr( &buffer, WholeFName ); VbufConcStr( &buffer, ": " ); intPrint( &buffer, "line", ", ", SrcLineCount ); if( IncLineCount != 0 ) { VbufConcStr( &buffer, "included " ); VbufConcDecimal( &buffer, IncLineCount ); VbufConcStr( &buffer, ", " ); } intPrint( &buffer, "warning", ", ", WngCount ); intPrint( &buffer, "error", "", ErrCount ); MsgDisplayLine( VbufString( &buffer ) ); CompFlags.stats_printed = 1; VbufFree( &buffer ); } }
static void collectStrings( VBUF *vinfo ) { VbufInit( vinfo ); while( CurToken == T_STRING ) { VbufConcStr( vinfo, Buffer ); NextToken(); } }
void FormatScope( SCOPE scope, VBUF *pvbuf, bool include_function ) /*****************************************************************/ // include_function - if true, include function scope resolution in formatting // - else terminate scope resolution at function { VbufInit( pvbuf ); fmtSymScope( scope, pvbuf, include_function ); strrev( VbufString( pvbuf ) ); }
static void fmtSymScope( SCOPE scope, VBUF *pvbuf, boolean include_function ) /***************************************************************************/ { TYPE class_type; NAME name; char *sname; SYMBOL sym; VBUF prefix; while( scope != NULL ) { switch( scope->id ) { case SCOPE_FILE: sname = ScopeNameSpaceFormatName( scope ); if( sname != NULL ) { VbufConcStrRev( pvbuf, scopeSep ); VbufConcStrRev( pvbuf, sname ); } break; case SCOPE_CLASS: class_type = ScopeClass( scope ); name = SimpleTypeName( class_type ); if( name != NULL ) { VbufConcStrRev( pvbuf, scopeSep ); if( class_type->flag & TF1_INSTANTIATION ) { fmtTemplateParms( pvbuf, class_type ); } VbufConcStrRev( pvbuf, NameStr( name ) ); } break; case SCOPE_FUNCTION: if( include_function ) { VbufInit( &prefix ); sym = ScopeFunction( scope ); formatScopedSym( sym, &prefix, FF_NULL ); if( VbufLen( &prefix ) > 0 ) { VbufConcStrRev( &prefix, functionDelim ); VbufPrepVbuf( pvbuf, &prefix ); } VbufFree( &prefix ); } return; // function scope resolved on function name case SCOPE_BLOCK: case SCOPE_TEMPLATE_DECL: case SCOPE_TEMPLATE_INST: case SCOPE_TEMPLATE_PARM: case SCOPE_TEMPLATE_SPEC_PARM: break; case SCOPE_MAX: default: VbufConcStrRev( pvbuf, scopeSep ); VbufConcStrRev( pvbuf, scopeError ); break; } scope = scope->enclosing; } }
static void doFormatSym( SYMBOL sym, VBUF *pvbuf, FMT_CONTROL control ) { VbufInit( pvbuf ); if( sym == NULL ) { VbufConcStr( pvbuf, nullSymbol ); } else { formatScopedSym( sym, pvbuf, control ); strrev( VbufString( pvbuf ) ); } }
static char *doFormatSym( SYMBOL sym, VBUF *pvbuf, FMT_CONTROL control ) { VbufInit( pvbuf ); if( sym == NULL ) { VbufConcStr( pvbuf, nullSymbol ); return( VbufString( pvbuf ) ); } else { return( strrev( formatScopedSym( sym, pvbuf, control ) ) ); } }
char *DbgSymNameFull( // GET FULL SYMBOL NAME SYMBOL sym, // - symbol VBUF *vbuf ) // - variable-sized buffer { if( sym != NULL ) { return( FormatSym( sym, vbuf ) ); } VbufInit( vbuf ); VbufConcStr( vbuf, "**NULL**" ); return( VbufString( vbuf ) ); }
void FormatTemplateParmScope( VBUF *parms, SCOPE parm_scope ) /***********************************************************/ { SYMBOL stop; SYMBOL curr; SYMBOL sym; const char *delim; TYPE type; auto VBUF sym_parm; auto VBUF type_parm_prefix; auto VBUF type_parm_suffix; VbufInit( parms ); if( parm_scope == NULL ) { makeUnknownTemplate( parms ); return; } delim = templateParmStart; curr = NULL; stop = ScopeOrderedStart( parm_scope ); for(;;) { curr = ScopeOrderedNext( stop, curr ); if( curr == NULL ) break; VbufConcStr( parms, delim ); type = curr->sym_type; if( SymIsConstantInt( curr ) ) { if( UnsignedIntType( type ) ) { VbufConcDecimal( parms, curr->u.uval ); } else { VbufConcInteger( parms, curr->u.sval ); } } else if( SymIsTypedef( curr ) ) { FormatType( type, &type_parm_prefix, &type_parm_suffix ); VbufTruncWhite( &type_parm_prefix ); VbufTruncWhite( &type_parm_suffix ); VbufConcVbuf( parms, &type_parm_prefix ); VbufConcVbuf( parms, &type_parm_suffix ); VbufFree( &type_parm_prefix ); VbufFree( &type_parm_suffix ); } else { sym = SymAddressOf( curr ); if( sym != NULL ) { FormatSym( sym, &sym_parm ); VbufConcVbuf( parms, &sym_parm ); VbufFree( &sym_parm ); } } delim = templateParmNext; } if( delim == templateParmStart ) { VbufConcStr( parms, templateParmStart ); } VbufConcStr( parms, templateParmStop ); }
bool CmdLnBatchRead( // READ NEXT LINE IN COMMAND BUFFER VBUF *buf ) // - virtual buffer { VbufInit( buf ); for(;;) { int c = nextChar(); if( CompFlags.batch_file_eof ) break; if( c == '\n' ) break; VbufConcChr( buf, c ); } DbgVerify( VbufLen( buf ) > 0, "CmdLnReadBatch -- nothing" ); ++ CompInfo.fc_file_line; return( VbufLen( buf ) ); }
void VbufPrepVbuf // PREPEND A VBUF TO VBUF ( VBUF *vbuf1 // - VBUF structure , VBUF *vbuf2 ) // - VBUF structure to be prepended { VBUF temp; if( vbuf2->used > 0 ) { VbufInit( &temp ); VbufReqd( &temp, vbuf1->used + vbuf2->used ); stxvcpy( temp.buf, vbuf2->buf, vbuf2->used ); stxvcpy( temp.buf + vbuf2->used, vbuf1->buf, vbuf1->used ); temp.used = vbuf1->used + vbuf2->used; VbufFree( vbuf1 ); *vbuf1 = temp; } }
static PC_SEGMENT *addDefSeg( // ADD A DEFAULT PC SEGMENT DEF_SEG *def_seg, // - default segment info. unsigned ads_control ) // - control mask { unsigned attrs; // - attributes for segment PC_SEGMENT *curr; // - segment pointer VBUF seg_name; // - virtual buffer for name unsigned sa_control; // - segmentAlloc control mask VbufInit( &seg_name ); ++def_seg->ctr; sa_control = SA_NULL; if( ads_control & ADS_MODULE_PREFIX ) { if(( ads_control & ADS_CODE_SEGMENT ) == 0 && DataSegName[0] != '\0' ) { VbufConcStr( &seg_name, DataSegName ); } else { VbufConcStr( &seg_name, ModuleName ); } sa_control |= SA_MODULE_PREFIX; } if( ads_control & ADS_STRING_SEGMENT ) { sa_control |= SA_DEFINE_ANYTIME; } VbufConcStr( &seg_name, def_seg->pcseg->name ); if( ads_control & ADS_ZM_SEGMENT ) { VbufConcDecimal( &seg_name, def_seg->ctr ); } if( def_seg == &code_def_seg ) { attrs = SGAT_CODE_GEN; } else { if( ads_control & ADS_CONST_SEGMENT ) { attrs = SGAT_DATA_PRIVATE_RO; } else { attrs = SGAT_DATA_PRIVATE_RW; } VbufConcDecimal( &seg_name, def_seg->ctr ); } curr = segmentAlloc( VbufString( &seg_name ), NULL, SEG_NULL, attrs, sa_control ); if( 0 == ( attrs & EXEC ) ) { _markUsed( curr, TRUE ); } if( ads_control & ADS_STRING_SEGMENT ) { curr->only_strings = TRUE; } VbufFree( &seg_name ); return( curr ); }
void MsgDisplayLineArgs // DISPLAY A BARE LINE, FROM ARGUMENTS ( char* seg // - the line segments , ... ) { va_list args; // - arg list char* str; // - current segment VBUF buffer; // - buffer VbufInit( &buffer ); va_start( args, seg ); for( str = seg; str != NULL; str = va_arg( args, char* ) ) { VbufConcStr( &buffer, str ); } ideDisplay( IDEMSGSEV_NOTE_MSG, 0, VbufString( &buffer ), NULL ); va_end( args ); VbufFree( &buffer ); }
void DumpObjectModelClass( // DUMP OBJECT MODEL: CLASS TYPE type ) // - structure type { DUMP_INFO di; // - dump information if( ! type->u.c.info->corrupted ) { CompFlags.log_note_msgs = TRUE; di.original = type; di.offset = 0; VbufInit( &di.buffer ); VstkOpen( &di.stack, sizeof( char* ), 16 ); dumpStruct( type, &di, "Object Model for:", DS_NULL ); VbufFree( &di.buffer ); VstkClose( &di.stack ); CompFlags.log_note_msgs = FALSE; } }
void CmdLnCtxInfo( // PRINT CONTEXT INFO void ) { CTX_CL* entry; // - current entry VBUF buf; // - buffer VbufInit( &buf ); for( entry = VstkTop( &cmdLnContexts ) ; entry != NULL ; entry = VstkNext( &cmdLnContexts, entry ) ) { VbufRewind( &buf ); switch( entry->base.ctx_type ) { case CTX_CLTYPE_ENV : VbufConcChr( &buf, '@' ); VbufConcStr( &buf, entry->env.var ); break; case CTX_CLTYPE_FC : VbufConcStr( &buf, "batch file of commands, line " ); VbufConcDecimal( &buf, CompInfo.fc_file_line ); break; case CTX_CLTYPE_PGM : VbufConcStr( &buf, "command line" ); break; case CTX_CLTYPE_FILE : VbufConcStr( &buf, SrcFileFullName( entry->file.source ) ); break; DbgDefault( "bad command-line context" ); } if( entry->base.sw_ptr != NULL ) { size_t size; char const * not_used; char const* old = CmdScanAddr(); CmdScanInit( entry->base.sw_ptr ); CmdScanChar(); size = CmdScanOption( ¬_used ) + 1; CmdScanInit( old ); VbufConcStr( &buf, ", switch: " ); for( old = entry->base.sw_ptr; size > 0; ++old, --size ) { VbufConcChr( &buf, *old ); } } InfMsgPtr( INF_SWITCH, VbufString( &buf ) ); } VbufFree( &buf ); }
void VbufPrepStr( // PREPEND STRING TO vbuf->buf VBUF *vbuf, // - VBUF structure char const *string ) // - string to be prepended { size_t prep_size; VBUF temp; prep_size = strlen( string ); if( prep_size > 0 ) { VbufInit( &temp ); VbufReqd( &temp, prep_size + vbuf->used ); stxvcpy( temp.buf, string, prep_size ); stxvcpy( temp.buf + prep_size, vbuf->buf, vbuf->used ); temp.used = prep_size + vbuf->used; VbufFree( vbuf ); *vbuf = temp; } }
void PrintFnovResolution( FNOV_RESULT result, arg_list *args, /***********************************************************/ FNOV_LIST *match, FNOV_LIST *reject, SYMBOL sym ) // pseudo pretty display of overloaded ranking information { int length; VBUF name; if( sym != NULL ) { FormatSym( sym, &name ); } else if( match != NULL ) { FormatSym( match->sym, &name ); } else if( reject != NULL ) { FormatSym( reject->sym, &name ); } else { VbufInit( &name ); } printf( " Result: %s\n", resultNames[result] ); if( VbufLen( &name ) > 0 ) { printf( "Symbol: '%s'", VbufString( &name ) ); VbufFree( &name ); length = RingCount( match ) + RingCount( reject ); if( length > 0 ) { printf( " occurs %d time%s", length, (length != 1 ? "s " : " " ) ); } } printf( "\n" ); if( sym == NULL && args != NULL ) { printf( "Ranked Arguments:\n" ); printArgs( args ); } if( match != NULL ) { printf( "Matching Functions:\n" ); PrintFnovList( match ); } if( reject != NULL ) { printf( "Rejected Functions:\n" ); PrintFnovList( reject ); } }
static void formatScopedSym( SYMBOL sym, VBUF *pvbuf, FMT_CONTROL control ) /*************************************************************************/ { VBUF prefix; boolean ctordtor; VbufInit( &prefix ); if( sym->name == NULL ) { ctordtor = fmtSymName( sym, NULL, &prefix, pvbuf, control ); } else { ctordtor = fmtSymName( sym, sym->name->name, &prefix, pvbuf, control ); } if( !SymIsAnonymous( sym ) ) { fmtSymScope( SymScope( sym ), pvbuf, TRUE ); } if( !ctordtor ) { VbufConcVbuf( pvbuf, &prefix ); } VbufFree( &prefix ); }
static void fmtSymOpName( SYMBOL sym, VBUF *pvbuf ) /*************************************************/ { VBUF prefix, suffix; TYPE type; VbufInit( pvbuf ); type = FunctionDeclarationType( sym->sym_type ); if( type != NULL ) { FormatFunctionType( type->of , &prefix , &suffix , 0 , FormatTypeDefault | FF_TYPEDEF_STOP ); VbufConcVbufRev( pvbuf, &suffix ); VbufTruncWhite( pvbuf ); VbufConcVbufRev( pvbuf, &prefix ); VbufFree( &prefix ); VbufFree( &suffix ); } }
static char *formatScopedSym( SYMBOL sym, VBUF *pvbuf, FMT_CONTROL control ) /**************************************************************************/ { VBUF prefix; bool ctordtor; VbufInit( &prefix ); if( sym->name == NULL ) { ctordtor = fmtSymName( sym, NULL, &prefix, pvbuf, control ); } else { ctordtor = fmtSymName( sym, sym->name->name, &prefix, pvbuf, control ); } if( !SymIsAnonymous( sym ) ) { fmtSymScope( SymScope( sym ), pvbuf, true ); } if( !ctordtor ) { VbufConcVbuf( pvbuf, &prefix ); } VbufFree( &prefix ); return( VbufString( pvbuf ) ); }
static void processCmdFile( // PROCESS A COMMAND FILE OPT_STORAGE *data ) // - option data { VBUF rec; // - record for file int c; // - next character VbufInit( &rec ); for(;;) { for(;;) { c = NextChar(); if( c == LCHR_EOF ) break; if( c == '\n' ) break; if( c == '\r' ) break; VbufConcChr( &rec, (char)c ); } procOptions( data, VbufString( &rec ) ); for( ; ( c == '\n' ) || ( c == '\r' ); c = NextChar() ); if( c == LCHR_EOF ) break; VbufRewind( &rec ); VbufConcChr( &rec, (char)c ); } VbufFree( &rec ); }
PTREE AsmStmt( void ) /*******************/ { boolean uses_auto; AUX_INFO *aux_info; unsigned skip_token; unsigned skip_alt_token; PTREE expr; TYPE fn_type; TYPE ret_type; SYMBOL sym; char *fn_name; auto VBUF code_buffer; ppstate_t save_ppstate; save_ppstate = PPState; PPState = PPS_EOL; PPStateAsm = TRUE; VbufInit( &code_buffer ); NextTokenSkipEOL(); AsmSysInit(); if( ( CurToken == T_LEFT_BRACE ) || ( CurToken == T_ALT_LEFT_BRACE ) ) { NextTokenSkipEOL(); for(;;) { getAsmLine( &code_buffer ); if( CurToken == T_RIGHT_BRACE ) break; if( CurToken == T_ALT_RIGHT_BRACE ) break; if( CurToken == T_EOF ) break; NextTokenSkipEOL(); } skip_token = T_RIGHT_BRACE; skip_alt_token = T_ALT_RIGHT_BRACE; } else { getAsmLine( &code_buffer ); skip_token = skip_alt_token = T_NULL; } PPStateAsm = FALSE; PPState = save_ppstate; if( ( CurToken == skip_token ) || ( CurToken == skip_alt_token ) ) { NextToken(); } if( AsmCodeAddress != 0 ) { fn_name = NameDummy(); aux_info = AsmSysCreateAux( fn_name ); uses_auto = AsmSysInsertFixups( &code_buffer ); if( uses_auto ) { AsmSysUsesAuto(); } AsmSysDone(); ret_type = GetBasicType( TYP_VOID ); fn_type = MakeModifiableFunction( ret_type, NULL ); fn_type->u.f.pragma = aux_info; fn_type = CheckDupType( fn_type ); sym = SymCreateFileScope( fn_type, SC_NULL, SF_NULL, fn_name ); LinkageSet( sym, "C" ); expr = genFnCall( fn_name ); } else { expr = NULL; } AsmSysFini(); VbufFree( &code_buffer ); return( expr ); }
void DumpObjectModelEnum( // DUMP OBJECT MODEL: ENUM TYPE type ) // - enum type { SYMBOL sym; // - current symbol TYPE base; // - base type VBUF buffer; // - printing buffer char buf[16]; // - buffer int numb; // - a numeric value const char *name; // - name to be printed bool sign; // - TRUE ==> signed enum unsigned mask; // - used to mask to true size unsigned val; // - value as unsigned CompFlags.log_note_msgs = TRUE; base = TypedefModifierRemoveOnly( type ); sym = base->u.t.sym; VbufInit( &buffer ); VbufConcStr( &buffer, "Object Model for: " ); if( NULL == sym->name->name || NameStr( sym->name->name )[0] == '.' ) { VbufConcStr( &buffer, "anonymous enum type" ); } else { VbufConcStr( &buffer, NameStr( sym->name->name ) ); } switch( TypedefModifierRemove( base->of ) -> id ) { case TYP_CHAR : case TYP_UCHAR : name = "unsigned char"; sign = FALSE; break; case TYP_SCHAR : name = "signed char"; sign = TRUE; break; case TYP_SSHORT : name = "signed short"; sign = TRUE; break; case TYP_USHORT : name = "unsigned short"; sign = FALSE; break; case TYP_SINT : name = "signed int"; sign = TRUE; break; case TYP_UINT : name = "unsigned int"; sign = FALSE; break; case TYP_SLONG : name = "signed long"; sign = TRUE; break; case TYP_ULONG : name = "unsigned long"; sign = FALSE; break; case TYP_SLONG64 : name = "__int64"; sign = TRUE; break; case TYP_ULONG64 : name = "unsigned __int64"; sign = FALSE; break; DbgDefault( "DumpObjectModelEnum -- bad underlying type" ); } VbufConcStr( &buffer, ", base type is " ); VbufConcStr( &buffer, name ); vbufWrite( &buffer ); mask = CgMemorySize( base ); if( mask == sizeof( unsigned ) ) { mask = -1; } else { mask = ( 1 << ( mask * 8 ) ) - 1; } for( ; ; ) { sym = sym->thread; if( ! SymIsEnumeration( sym ) ) break; VbufRewind( &buffer ); VbufConcStr( &buffer, " " ); VbufConcStr( &buffer, NameStr( sym->name->name ) ); VbufConcStr( &buffer, " = " ); numb = sym->u.sval; if( sign && numb < 0 ) { VbufConcChr( &buffer, '-' ); VbufConcDecimal( &buffer, -numb ); } else { VbufConcDecimal( &buffer, numb ); } val = mask & numb; if( val > 10 ) { itoa( val, buf, 16 ); VbufConcStr( &buffer, " /0x" ); VbufConcStr( &buffer, buf ); } vbufWrite( &buffer ); } VbufFree( &buffer ); CompFlags.log_note_msgs = FALSE; }
void MsgDisplay // DISPLAY A MESSAGE ( IDEMsgSeverity severity // - message severity , MSG_NUM msgnum // - message number , va_list args ) // - substitution arguments { VBUF buffer; // - formatting buffer SYMBOL sym; // - sym requiring location TOKEN_LOCN prt_locn; // - print location TOKEN_LOCN *msg_locn; // - message location CTX context; // - current context void *inf; // - information about context char *inf_prefix; // - prefix for information boolean context_changed; // - TRUE ==> new context from last time context_changed = CtxCurrent( &context, &inf, &inf_prefix ); setMsgLocation( context ); prt_locn = err_locn; ++reserveDepth; VbufInit( &buffer ); sym = msgBuild( msgnum, args, &buffer ); switch( severity ) { case IDEMSGSEV_ERROR : case IDEMSGSEV_WARNING : if( CompFlags.ew_switch_used ) { switch( context ) { case CTX_INIT : case CTX_FINI : case CTX_CMDLN_VALID : case CTX_CG_OPT : case CTX_ENDFILE : if( context_changed ) { fmt_inf_hdr( inf_prefix ); } break; case CTX_CMDLN_ENV : case CTX_CMDLN_PGM : if( context_changed ) { fmt_inf_hdr_switch( inf_prefix, inf ); } break; case CTX_CG_FUNC : case CTX_FUNC_GEN : if( context_changed ) { fmt_inf_hdr_sym( inf_prefix, inf ); } break; case CTX_FORCED_INCS : case CTX_SOURCE : build_file_nesting(); break; DbgDefault( "Unexpected message context" ); } } msg_locn = &prt_locn; break; case IDEMSGSEV_NOTE : case IDEMSGSEV_NOTE_MSG : msg_locn = ¬es_locn; break; default : msg_locn = NULL; break; } ideDisplay( severity , msgnum , VbufString( &buffer ) , msg_locn ); if( context_changed && ! CompFlags.ew_switch_used && ( severity == IDEMSGSEV_ERROR || severity == IDEMSGSEV_WARNING ) && ( context == CTX_SOURCE || context == CTX_FORCED_INCS ) ) { build_file_nesting(); } VbufFree( &buffer ); --reserveDepth; if( NULL != sym ) { notes_locn = sym->locn->tl; MsgDisplayArgs( IDEMSGSEV_NOTE , SymIsFunctionTemplateModel( sym ) ? INF_TEMPLATE_FN_DECL : INF_SYMBOL_DECLARATION , sym , &sym->locn->tl ); } }
void VbufFree( // FREE BUFFER VBUF *vbuf ) // - VBUF structure { FREE_BUFFER( vbuf ); VbufInit( vbuf ); }
static bool fmtSymName( SYMBOL sym, NAME name, VBUF *pvprefix, VBUF *pvbuf, FMT_CONTROL control ) /***********************************************************************************************/ // returns true if sym is CTOR/DTOR so that the caller drop the return type { VBUF prefix, suffix, op_name; CGOP oper; bool ctordtor = false; if( CppLookupOperatorName( name, &oper ) ) { switch( oper ) { case CO_CONVERT: if( sym == NULL ) { VbufConcStrRev( pvbuf, operatorSuffix ); VbufConcStrRev( pvbuf, operatorUnknown ); } else { fmtSymOpName( sym, &op_name ); fmtSymFunction( sym, &prefix, &suffix, (FormatTypeDefault & ~FF_USE_VOID) | FF_DROP_RETURN ); VbufConcVbufRev( pvbuf, &suffix ); VbufConcVbuf( pvbuf, &op_name ); VbufConcStrRev( pvbuf, operatorPrefix ); VbufConcVbufRev( pvbuf, &prefix ); VbufFree( &op_name ); VbufFree( &prefix ); VbufFree( &suffix ); } break; case CO_CTOR: if( sym == NULL ) { VbufConcStrRev( pvbuf, constructorName ); } else { name = SimpleTypeName( ScopeClass( SymScope( sym ) ) ); ctordtor = true; fmtSymFunction( sym, &prefix, &suffix, FormatTypeDefault ); VbufConcVbufRev( pvbuf, &suffix ); if( name != NULL ) { VbufConcStrRev( pvbuf, NameStr( name ) ); } VbufConcVbufRev( pvprefix, &prefix ); VbufFree( &prefix ); VbufFree( &suffix ); } break; case CO_DTOR: if( sym == NULL ) { VbufConcStrRev( pvbuf, destructorName ); } else { name = SimpleTypeName( ScopeClass( SymScope( sym ) ) ); ctordtor = true; fmtSymFunction( sym, &prefix, &suffix, FormatTypeDefault ); VbufConcVbufRev( pvbuf, &suffix ); if( name != NULL ) { VbufConcStrRev( pvbuf, NameStr( name ) ); } VbufConcStrRev( pvbuf, dtorPrefix ); VbufConcVbufRev( pvprefix, &prefix ); VbufFree( &prefix ); VbufFree( &suffix ); } break; default: if( sym == NULL ) { VbufConcStrRev( pvbuf, fmtSymCgop( oper ) ); VbufConcStrRev( pvbuf, operatorPrefix ); } else { fmtSymFunction( sym, &prefix, &suffix, FormatTypeDefault | control ); VbufConcVbufRev( pvbuf, &suffix ); VbufConcStrRev( pvbuf, fmtSymCgop( oper ) ); VbufConcStrRev( pvbuf, operatorPrefix ); VbufConcVbufRev( pvprefix, &prefix ); VbufFree( &prefix ); VbufFree( &suffix ); } break; } } else if( sym != NULL ) { if( SymIsFunction( sym ) ) { fmtSymFunction( sym, &prefix, &suffix, FormatTypeDefault | control ); } else if( !SymIsTypedef( sym ) ) { FormatType( sym->sym_type, &prefix, &suffix ); } else { VbufInit( &prefix ); VbufInit( &suffix ); } VbufConcVbufRev( pvbuf, &suffix ); if( name == NULL ) { VbufConcStrRev( pvbuf, nullSymname ); } else { VbufConcStrRev( pvbuf, NameStr( name ) ); } VbufConcVbufRev( pvprefix, &prefix ); VbufFree( &prefix ); VbufFree( &suffix ); } else if( name != NULL ) { VbufConcStrRev( pvbuf, NameStr( name ) ); } else { VbufConcStrRev( pvbuf, nullSymname ); } return( ctordtor ); }
static int insertFixups( VBUF *src_code ) { struct asmfixup *fix; struct asmfixup *head; struct asmfixup *chk; struct asmfixup *next; struct asmfixup **owner; unsigned char *src; unsigned char *src_start; unsigned char *src_end; unsigned char cg_fix; bool perform_fixups; byte_seq *seq; SYMBOL sym; NAME name; unsigned char *dst; byte_seq_len len; unsigned skip; int mutate_to_segment; bool uses_auto; #if _CPU == 8086 int fixup_padding; #endif VBUF out_code; uses_auto = FALSE; perform_fixups = FALSE; head = FixupHead; if( head == NULL ) { out_code = *src_code; } else { VbufInit( &out_code ); FixupHead = NULL; /* sort the fixup list in increasing fixup_loc's */ for( fix = head; fix != NULL; fix = next ) { owner = &FixupHead; for( ;; ) { chk = *owner; if( chk == NULL ) break; if( chk->fixup_loc > fix->fixup_loc ) break; owner = &chk->next; } next = fix->next; fix->next = *owner; *owner = fix; } len = 0; cg_fix = 0; sym = NULL; src_start = VbufBuffer( src_code ); src_end = src_start + VbufLen( src_code ); fix = FixupHead; owner = &FixupHead; /* insert fixup escape sequences */ for( src = src_start; src < src_end; ) { /* reserve at least ASM_BLOCK bytes in the buffer */ VbufReqd( &out_code, _RoundUp( len + ASM_BLOCK, ASM_BLOCK ) ); dst = VbufBuffer( &out_code ); if( fix != NULL && fix->fixup_loc == (src - src_start) ) { name = NULL; if( fix->name != NULL ) { name = NameCreateNoLen( fix->name ); sym = ScopeASMUseSymbol( name, &uses_auto ); if( sym == NULL ) { return( 0 ); } } /* insert fixup information */ skip = 0; dst[len++] = FLOATING_FIXUP_BYTE; mutate_to_segment = 0; #if _CPU == 8086 fixup_padding = 0; #endif switch( fix->fixup_type ) { case FIX_FPPATCH: dst[len++] = fix->offset; break; case FIX_SEG: if( name == NULL ) { // special case for floating point fixup if( ( src[0] == 0x90 ) && ( src[1] == 0x9B ) ) { // inline assembler FWAIT instruction 0x90, 0x9b dst[len++] = FIX_FPP_WAIT; } else if( src[0] == 0x9b && (src[1] & 0xd8) == 0xd8 ) { // FWAIT as first byte and FPU instruction opcode as second byte dst[len++] = FIX_FPP_NORMAL; } else if( src[0] == 0x9b && (src[2] & 0xd8) == 0xd8 ) { // FWAIT as first byte and FPU instruction opcode as third byte // second byte should be segment override prefix switch( src[1] ) { case PREFIX_ES: dst[len++] = FIX_FPP_ES; break; case PREFIX_CS: dst[len++] = FIX_FPP_CS; break; case PREFIX_SS: dst[len++] = FIX_FPP_SS; break; case PREFIX_DS: dst[len++] = FIX_FPP_DS; break; case PREFIX_GS: dst[len++] = FIX_FPP_GS; break; case PREFIX_FS: dst[len++] = FIX_FPP_FS; break; default: --len; break; // skip FP patch } } else { // skip FP patch --len; } } else { skip = 2; cg_fix = FIX_SYM_SEGMENT; } break; case FIX_RELOFF16: skip = 2; cg_fix = FIX_SYM_RELOFF; break; case FIX_RELOFF32: skip = 4; cg_fix = FIX_SYM_RELOFF; #if _CPU == 8086 fixup_padding = 1; #endif break; case FIX_PTR16: mutate_to_segment = 1; /* fall through */ case FIX_OFF16: skip = 2; cg_fix = FIX_SYM_OFFSET; break; case FIX_PTR32: mutate_to_segment = 1; /* fall through */ case FIX_OFF32: skip = 4; cg_fix = FIX_SYM_OFFSET; #if _CPU == 8086 fixup_padding = 1; #endif break; default: CErr2p( ERR_ASSEMBLER_ERROR, "cannot reach label" ); break; } if( skip != 0 ) { dst[len++] = cg_fix; *((BYTE_SEQ_SYM *)&dst[len]) = sym; len += sizeof( BYTE_SEQ_SYM ); *((BYTE_SEQ_OFF *)&dst[len]) = fix->offset; len += sizeof( BYTE_SEQ_OFF ); src += skip; } #if _CPU == 8086 if( fixup_padding ) { // add offset fixup padding to 32-bit // cg create only 16-bit offset fixup dst[len++] = 0; dst[len++] = 0; // } #endif if( mutate_to_segment ) { /* Since the CG escape sequences don't allow for FAR pointer fixups, we have to split them into two. This is done by doing the offset fixup first, then mutating the fixup structure to look like a segment fixup one near pointer size later. */ fix->fixup_type = FIX_SEG; fix->fixup_loc += skip; fix->offset = 0; } else { head = fix; fix = fix->next; if( head->external ) { *owner = fix; CMemFree( head->name ); CMemFree( head ); } else { owner = &head->next; } } } else { if( *src == FLOATING_FIXUP_BYTE ) { dst[len++] = FLOATING_FIXUP_BYTE; } dst[len++] = *src++; } VbufSetLen( &out_code, len ); } perform_fixups = TRUE; } len = VbufLen( &out_code ); seq = CMemAlloc( offsetof( byte_seq, data ) + len ); seq->relocs = perform_fixups; seq->length = len; memcpy( seq->data, VbufBuffer( &out_code ), len ); CurrInfo->code = seq; if( VbufBuffer( &out_code ) != VbufBuffer( src_code ) ) VbufFree( &out_code ); return( uses_auto ); }
static int GetByteSeq( void ) { int len; char *name; unsigned offset; unsigned fixword; int uses_auto; VBUF code_buffer; #if _CPU == 8086 bool use_fpu_emu = FALSE; #endif VbufInit( &code_buffer ); AsmSysInit(); PPCTL_ENABLE_MACROS(); NextToken(); len = 0; offset = 0; name = NULL; for( ;; ) { /* reserve at least ASM_BLOCK bytes in the buffer */ VbufReqd( &code_buffer, _RoundUp( len + ASM_BLOCK, ASM_BLOCK ) ); if( CurToken == T_STRING ) { AsmCodeAddress = len; AsmCodeBuffer = VbufBuffer( &code_buffer ); #if _CPU == 8086 AsmLine( Buffer, use_fpu_emu ); use_fpu_emu = FALSE; #else AsmLine( Buffer, FALSE ); #endif len = AsmCodeAddress; NextToken(); if( CurToken == T_COMMA ) { NextToken(); } } else if( CurToken == T_CONSTANT ) { #if _CPU == 8086 if( use_fpu_emu ) { AddAFix( len, NULL, FIX_SEG, 0 ); use_fpu_emu = FALSE; } #endif VbufBuffer( &code_buffer )[ len++ ] = U32Fetch( Constant64 ); NextToken(); } else { #if _CPU == 8086 use_fpu_emu = FALSE; #endif fixword = FixupKeyword(); if( fixword == FIXWORD_NONE ) break; if( fixword == FIXWORD_FLOAT ) { #if _CPU == 8086 if( GET_FPU_EMU( CpuSwitches ) ) { use_fpu_emu = TRUE; } #endif } else { /* seg or offset */ if( !IS_ID_OR_KEYWORD( CurToken ) ) { CErr1( ERR_EXPECTING_ID ); } else { name = strsave( Buffer ); offset = 0; NextToken(); if( CurToken == T_PLUS ) { NextToken(); if( CurToken == T_CONSTANT ) { offset = U32Fetch( Constant64 ); NextToken(); } } else if( CurToken == T_MINUS ) { NextToken(); if( CurToken == T_CONSTANT ) { offset = - U32Fetch( Constant64 ); NextToken(); } } } switch( fixword ) { case FIXWORD_RELOFF: #if _CPU == 8086 AddAFix( len, name, FIX_RELOFF16, offset ); len += 2; #else AddAFix( len, name, FIX_RELOFF32, offset ); len += 4; #endif break; case FIXWORD_OFFSET: #if _CPU == 8086 AddAFix( len, name, FIX_OFF16, offset ); len += 2; #else AddAFix( len, name, FIX_OFF32, offset ); len += 4; #endif break; case FIXWORD_SEGMENT: AddAFix( len, name, FIX_SEG, 0 ); len += 2; break; } } } VbufSetLen( &code_buffer, len ); } PPCTL_DISABLE_MACROS(); uses_auto = AsmSysInsertFixups( &code_buffer ); AsmSysFini(); VbufFree( &code_buffer ); return( uses_auto ); }
PTREE AsmStmt( void ) /*******************/ { bool uses_auto; AUX_INFO *auxinfo; TOKEN skip_token; TOKEN skip_alt_token; PTREE expr; TYPE fn_type; TYPE ret_type; SYMBOL sym; NAME fn_name; auto VBUF code_buffer; ppctl_t old_ppctl; old_ppctl = PPControl; PPCTL_ENABLE_EOL(); PPCTL_ENABLE_ASM(); VbufInit( &code_buffer ); NextTokenSkipEOL(); AsmSysInit(); if( ( CurToken == T_LEFT_BRACE ) || ( CurToken == T_ALT_LEFT_BRACE ) ) { NextTokenSkipEOL(); for(;;) { getAsmLine( &code_buffer ); if( CurToken == T_RIGHT_BRACE ) break; if( CurToken == T_ALT_RIGHT_BRACE ) break; if( CurToken == T_EOF ) break; NextTokenSkipEOL(); } skip_token = T_RIGHT_BRACE; skip_alt_token = T_ALT_RIGHT_BRACE; } else { getAsmLine( &code_buffer ); skip_token = skip_alt_token = T_NULL; } PPControl = old_ppctl; if( ( CurToken == skip_token ) || ( CurToken == skip_alt_token ) ) { NextToken(); } if( AsmCodeAddress != 0 ) { fn_name = NameDummy(); auxinfo = AsmSysCreateAux( NameStr( fn_name ) ); uses_auto = AsmSysInsertFixups( &code_buffer ); if( uses_auto ) { AsmSysUsesAuto(); } AsmSysDone(); ret_type = GetBasicType( TYP_VOID ); fn_type = MakeModifiableFunction( ret_type, NULL ); fn_type->u.f.pragma = auxinfo; fn_type = CheckDupType( fn_type ); sym = SymCreateFileScope( fn_type, SC_NULL, SF_NULL, fn_name ); LinkageSet( sym, "C" ); expr = genFnCall( fn_name ); } else { expr = NULL; } AsmSysFini(); VbufFree( &code_buffer ); return( expr ); }