function SharedInfo = C_Funcall(FunInfo,FileInfo,SharedInfo,FlagCall) // function SharedInfo = C_Funcall(FunInfo,FileInfo,SharedInfo,FlagCall) // ----------------------------------------------------------------- // Get function for a generic SCI2C table. // // Input data: // //NUT: add description here // // Output data: // //NUT: add description here // // Status: // 27-Oct-2007 -- Raffaele Nutricato: Author. // // Copyright 2007 Raffaele Nutricato. // Contact: raffaele.nutricato@tiscali.it // ----------------------------------------------------------------- // ------------------------------ // --- Check input arguments. --- // ------------------------------ SCI2CNInArgCheck(argn(2),4,4); // ----------------------- // --- Initialization. --- // ----------------------- nxtscifunname = SharedInfo.NextSCIFunName; nxtscifunnumber = SharedInfo.NextSCIFunNumber; ReportFileName = FileInfo.Funct(nxtscifunnumber).ReportFileName; CPass1FileName = FileInfo.Funct(nxtscifunnumber).CPass1FileName; CPass1FreeFileName = FileInfo.Funct(nxtscifunnumber).CPass1FreeFileName; HeaderFileName = FileInfo.Funct(nxtscifunnumber).Pass1HeaderFileName; CDeclarationFileName = FileInfo.Funct(nxtscifunnumber).CDeclarationFileName; CInitVarsFileName = FileInfo.Funct(nxtscifunnumber).CInitVarsFileName; IndentLevel = SharedInfo.NIndent; CCall = ''; Target = SharedInfo.Target; // --- Extract Function Info. --- FunctionName = FunInfo.SCIFunctionName; CFunName = FunInfo.CFunctionName; InArg = FunInfo.InArg; NInArg = FunInfo.NInArg; OutArg = FunInfo.OutArg; NOutArg = FunInfo.NOutArg; PosFirstOutScalar = FunInfo.PosFirstOutScalar; // #RNU_RES_B PrintStringInfo(' ',ReportFileName,'file','y'); PrintStringInfo('***Generating C code***',ReportFileName,'file','y'); // #RNU_RES_E // --------------------------- // --- End Initialization. --- // --------------------------- // -------------------------------------------------- // --- Manage anticipated exit from the function. --- // -------------------------------------------------- if (SharedInfo.SkipNextFun > 0) SharedInfo.SkipNextFun = SharedInfo.SkipNextFun - 1; return; end // #RNU_RES_B // Exit if the function is a precision specifier and the corresponding flag is 1. // #RNU_RES_E if ((sum(mtlb_strcmp(FunctionName,SharedInfo.Annotations.DataPrec)) > 0) & ... (SharedInfo.SkipNextPrec == 1)) // #RNU_RES_B PrintStringInfo(' Skipping code generating because already generated in the previous function.',ReportFileName,'file','y'); // #RNU_RES_E SharedInfo.SkipNextPrec = SharedInfo.SkipNextPrec - 1; return; end // #RNU_RES_B // Exit if the function is OpEqual and the corresponding skip flag is enabled. // #RNU_RES_E if ((mtlb_strcmp(FunctionName,'OpEqual')) & ... (SharedInfo.SkipNextEqual == 1)) // #RNU_RES_B PrintStringInfo(' Skipping code generating because already generated in the previous function.',ReportFileName,'file','y'); // #RNU_RES_E SharedInfo.SkipNextEqual = SharedInfo.SkipNextEqual - 1; return; end // #BJ // size should be managed as other functions // otherwise size(4) will lead to a C variable __4Size reference // wich will never exists // #RNU_RES_B // Exit if the function is size. // #RNU_RES_E // if ((mtlb_strcmp(FunctionName,'size'))) // // #RNU_RES_B // PrintStringInfo(' Anticipated exit for the size function.',ReportFileName,'file','y'); // // #RNU_RES_E // CCall =''; // if (NInArg == 1) // if (NOutArg == 1) // CCall = CCall+OutArg(1).Name+'[0] = __'+InArg(1).Name+'Size[0];'; // // #RNU_RES_B // PrintStringInfo(' '+CCall,ReportFileName,'file','y'); // // #RNU_RES_E // PrintStringInfo(C_IndentBlanks(IndentLevel)+CCall,CPass1FileName,'file','y'); // CCall =''; // CCall = CCall+OutArg(1).Name+'[1] = __'+InArg(1).Name+'Size[1];'; // // #RNU_RES_B // PrintStringInfo(' '+CCall,ReportFileName,'file','y'); // // #RNU_RES_E // PrintStringInfo(C_IndentBlanks(IndentLevel)+CCall,CPass1FileName,'file','y'); // elseif (NOutArg == 2) // CCall = CCall+OutArg(1).Name+' = __'+InArg(1).Name+'Size[0];'; // // #RNU_RES_B // PrintStringInfo(' '+CCall,ReportFileName,'file','y'); // // #RNU_RES_E // PrintStringInfo(C_IndentBlanks(IndentLevel)+CCall,CPass1FileName,'file','y'); // CCall =''; // CCall = CCall+OutArg(2).Name+' = __'+InArg(1).Name+'Size[1];'; // // #RNU_RES_B // PrintStringInfo(' '+CCall,ReportFileName,'file','y'); // // #RNU_RES_E // PrintStringInfo(C_IndentBlanks(IndentLevel)+CCall,CPass1FileName,'file','y'); // else // SCI2Cerror('Don''t know how to manage size function with number of output args different from 1 and 2.'); // end // elseif (NInArg == 2) // if (NOutArg == 1) // if (InArg(2).Value == 1) // CCall = CCall+OutArg(1).Name+' = __'+InArg(1).Name+'Size[0];'; // // #RNU_RES_B // PrintStringInfo(' '+CCall,ReportFileName,'file','y'); // // #RNU_RES_E // PrintStringInfo(C_IndentBlanks(IndentLevel)+CCall,CPass1FileName,'file','y'); // elseif (InArg(2).Value == 2) // CCall = CCall+OutArg(1).Name+' = __'+InArg(1).Name+'Size[1];'; // // #RNU_RES_B // PrintStringInfo(' '+CCall,ReportFileName,'file','y'); // // #RNU_RES_E // PrintStringInfo(C_IndentBlanks(IndentLevel)+CCall,CPass1FileName,'file','y'); // else // SCI2Cerror('Not known the value of the second input arg for the size function.'); // end // else // SCI2Cerror('Don''t know how to manage size function with number of output args different from 1.'); // end // else // SCI2Cerror('Don''t know how to manage size function with number of input args different from 1 and 2.'); // end // return; // end // ------------------------------------------------------ // --- End Manage anticipated exit from the function. --- // ------------------------------------------------------ // #RNU_RES_B // ------------------------------------------------------------ // --- Allocate memory and size array for output arguments. --- // ------------------------------------------------------------ // #RNU_RES_E if (FlagCall == 1) // #RNU_RES_B //RNU qui va tolto tutto una volta sicuri che la memallocout puo' essere fatta dentro la st_insoutarg // C_MemAllocOutTempVars(OutArg,NOutArg,CPass1FileName,CPass1FreeFileName,IndentLevel,ReportFileName); // #RNU_RES_E end // ---------------------------- // --- Generate the C call. --- // ---------------------------- CCall =''; if(mtlb_strcmp(part(CFunName,1:9),'PI_thread') == %T) //Functions that are to be ru in separate thread in case of RPi target, //need to have specific name which is PI_THREAD(functionname) CCall = CCall + 'PI_THREAD('+CFunName+')' else if (FunInfo.CFunctionName == SharedInfo.CMainFunName) if (FlagCall == 1) error(9999, 'main function called in a source code!'); else CCall =CCall+'int '; end elseif ((mtlb_strcmp(part(CFunName,1:5),'odefn') == %T)) //Return type of function containing ODEs must be int. CCall = CCall + 'int '; else if (PosFirstOutScalar >= 1) if (FlagCall == 1) CCall = CCall+OutArg(PosFirstOutScalar).Name+' = '; else CCall = CCall+C_Type(OutArg(PosFirstOutScalar).Type)+' '; end else if (FlagCall == 0) CCall = CCall+'void '; end end end // FIXME : Wrap library function call with prefixed name //if CFunName == "main" CCall = CCall + CFunName + "("; //else // CCall = CCall+"SCI2C("+CFunName+")("; //end // #RNU_RES_B PrintStringInfo(' C call after output scalar args check: '+CCall,ReportFileName,'file','y'); // #RNU_RES_E clear counterin if(mtlb_strcmp(part(CFunName,1:5),'odefn') == %F) for counterin = 1:NInArg if (InArg(counterin).Type == 'g' & InArg(counterin).Scope == 'String') TmpInArgName = '""'+InArg(counterin).Name+'""'; elseif (InArg(counterin).Type == 'z' & (InArg(counterin).Scope == 'Number')) TmpInArgName = 'DoubleComplex('+SCI2Cstring(real(InArg(counterin).Value))+','+SCI2Cstring(imag(InArg(counterin).Value))+')'; elseif (InArg(counterin).Type == 'c' & (InArg(counterin).Scope == 'Number')) TmpInArgName = 'FloatComplex('+SCI2Cstring(real(InArg(counterin).Value))+','+SCI2Cstring(imag(InArg(counterin).Value))+')'; else TmpInArgName = InArg(counterin).Name; end TmpInArgType = C_Type(InArg(counterin).Type); //if (FunctionName == 'OpEqual') // TmpInArgSizeVar = '__'+OutArg(counterin).Name+'Size'; // else TmpInArgSizeVar = '__'+InArg(counterin).Name+'Size'; //end if (InArg(counterin).Dimension == 0) if (FlagCall == 0) CCall = CCall+TmpInArgType+' '; end CCall = CCall+TmpInArgName+','; else if (FlagCall == 0) CCall = CCall+TmpInArgType+'* '+TmpInArgName+', int* __'+TmpInArgName+'Size,'; else CCall = CCall+TmpInArgName+', '+TmpInArgSizeVar+','; end end end else //If current function contains 'odefn' at the beginning, then it contains //differnetial equations and its function call need to be differnt than //other function call. GSL library being used for solving ODEs, requires //function containing odes in specific format which is differnt than generated //above. for counterin = 1:NInArg //if((NInArg == 4 & counterin <> 3) | (NInArg == 5 & counterin <> 4)) //Skip third argument if (InArg(counterin).Type == 'g' & InArg(counterin).Scope == 'String') TmpInArgName = '""'+InArg(counterin).Name+'""'; elseif (InArg(counterin).Type == 'z' & (InArg(counterin).Scope == 'Number')) TmpInArgName = 'DoubleComplex('+SCI2Cstring(real(InArg(counterin).Value))+','+SCI2Cstring(imag(InArg(counterin).Value))+')'; elseif (InArg(counterin).Type == 'c' & (InArg(counterin).Scope == 'Number')) TmpInArgName = 'FloatComplex('+SCI2Cstring(real(InArg(counterin).Value))+','+SCI2Cstring(imag(InArg(counterin).Value))+')'; else TmpInArgName = InArg(counterin).Name; end TmpInArgType = C_Type(InArg(counterin).Type); //if (FunctionName == 'OpEqual') // TmpInArgSizeVar = '__'+OutArg(counterin).Name+'Size'; // else TmpInArgSizeVar = '__'+InArg(counterin).Name+'Size'; //end if (InArg(counterin).Dimension == 0) if (FlagCall == 0) CCall = CCall+TmpInArgType+' '; end CCall = CCall+TmpInArgName+','; else if (FlagCall == 0) CCall = CCall+TmpInArgType+'* '+TmpInArgName+', ';//int* __'+TmpInArgName+'Size,'; else CCall = CCall+TmpInArgName+', ';//+TmpInArgSizeVar+','; end end //end end end // #RNU_RES_B PrintStringInfo(' C call after input args analysis: '+CCall,ReportFileName,'file','y'); // #RNU_RES_E for counterout = 1:NOutArg TmpOutArgName = OutArg(counterout).Name; TmpOutArgType = C_Type(OutArg(counterout).Type); if (counterout == PosFirstOutScalar) if (FlagCall == 0) // #RNU_RES_B // --- Write in the declaration file the returned output scalar (if any). --- // #RNU_RES_E outscalardeclaration = TmpOutArgType+' '+TmpOutArgName+';'; // #RNU_RES_B PrintStringInfo(outscalardeclaration,ReportFileName,'file','y'); // #RNU_RES_E PrintStringInfo(C_IndentBlanks(1)+outscalardeclaration,CDeclarationFileName,'file','y'); PrintStringInfo(' ',CDeclarationFileName,'file','y'); end else if (OutArg(counterout).Dimension == 0) if (FlagCall == 0) // --- Write in the declaration file the returned output scalar (if any). --- outscalardeclaration = TmpOutArgType+' '+TmpOutArgName+';'; PrintStringInfo(outscalardeclaration,ReportFileName,'file','y'); PrintStringInfo(C_IndentBlanks(1)+outscalardeclaration,CDeclarationFileName,'file','y'); PrintStringInfo(' ',CDeclarationFileName,'file','y'); CCall = CCall+TmpOutArgType+'* __ptr'+TmpOutArgName+', '; else CCall = CCall+'&'+TmpOutArgName+', ';//NUT: verifica se ci vuole l'& end else if (FlagCall == 0) CCall = CCall+TmpOutArgType+'* '+TmpOutArgName+','; if (OutArg(counterout).FindLike == 1) CCall = CCall+'int* __'+TmpOutArgName+'Size'+','; end // #RNU_RES_B //NUT prova a sostituire le variabili strutture con variabili dichiarate all'inizio del codice. // --- Declare the size of the output arguments. --- // #RNU_RES_E outscalardeclaration = 'int __'+TmpOutArgName+'Size[2];'; PrintStringInfo(outscalardeclaration,ReportFileName,'file','y'); PrintStringInfo(C_IndentBlanks(1)+outscalardeclaration,CDeclarationFileName,'file','y'); outscalardeclaration = '__'+TmpOutArgName+'Size[0] = '+(OutArg(counterout).Size(1))+';'; PrintStringInfo(outscalardeclaration,ReportFileName,'file','y'); PrintStringInfo(C_IndentBlanks(1)+outscalardeclaration,CInitVarsFileName,'file','y'); outscalardeclaration = '__'+TmpOutArgName+'Size[1] = '+(OutArg(counterout).Size(2))+';'; PrintStringInfo(outscalardeclaration,ReportFileName,'file','y'); PrintStringInfo(C_IndentBlanks(1)+outscalardeclaration,CInitVarsFileName,'file','y'); PrintStringInfo(' ',CInitVarsFileName,'file','y'); else CCall = CCall+OutArg(counterout).Name+','; if (OutArg(counterout).FindLike == 1) CCall = CCall+'(int* ) __'+TmpOutArgName+'Size'+','; end end end end end PrintStringInfo(' C call after output args analysis: '+CCall,ReportFileName,'file','y'); // Remove the last " " and "," if (part(CCall,length(CCall):length(CCall)) == ' ') CCall = part(CCall,1:length(CCall)-1); end if (part(CCall,length(CCall):length(CCall)) == ',') CCall = part(CCall,1:length(CCall)-1); end //__ysize is added to input arguments at last to comply with form required by GSL if(mtlb_strcmp(part(CFunName,1:5),'odefn') == %T) CCall = CCall + ', int* '+TmpInArgSizeVar; end CCall = CCall+')'; if (FlagCall == 1) CCall = CCall+';'; end end //NUT: la parte di generazione della C call va inserita in una funzione a parte. //NUT: tale funzione deve avere anche uno switch che consenta di generare differenti versioni //NUT: delle chiamate C in accordo con la libreria disponibile, fermo restando che //NUT: e' sempre possibile fornire la lista delle macro. if mtlb_strcmp(FunctionName,'return') // Here I introduce the pointer assignment for output scalar arguments. for cntout = 1:SharedInfo.CurrentFunInfo.NOutArg if (cntout ~= SharedInfo.CurrentFunInfo.PosFirstOutScalar & ... SharedInfo.CurrentFunInfo.OutArg(cntout).Dimension == 0) CCall = ''; CCall = CCall+'*__ptr'+SharedInfo.CurrentFunInfo.OutArg(cntout).Name+' = '+... SharedInfo.CurrentFunInfo.OutArg(cntout).Name+';'; PrintStringInfo(' '+CCall,ReportFileName,'file','y'); PrintStringInfo(C_IndentBlanks(IndentLevel)+CCall,CPass1FileName,'file','y'); end end // --- Then I free the memory dinamically allocated. --- // ---------------------------- // --- Handle Free section. --- // ---------------------------- PrintStringInfo(C_IndentBlanks(1)+'/*',CPass1FreeFileName,'file','y'); PrintStringInfo(C_IndentBlanks(1)+'** ------------------------- ',CPass1FreeFileName,'file','y'); PrintStringInfo(C_IndentBlanks(1)+'** --- End Free Section. --- ',CPass1FreeFileName,'file','y'); PrintStringInfo(C_IndentBlanks(1)+'** ------------------------- ',CPass1FreeFileName,'file','y'); PrintStringInfo(C_IndentBlanks(1)+'*/',CPass1FreeFileName,'file','y'); PrintStringInfo(' ',CPass1FreeFileName,'file','y'); SCI2Ccopyfile(CPass1FreeFileName,... CPass1FileName,'append'); // -------------------------------- // --- End Handle Free section. --- // -------------------------------- // --- Then I introduce the return to the first scalar output arguments. --- CCall = ''; // #RNU_RES_B //NUT: non capisco questo skip a questo punto. //NUT: perche' la return finale la sto gestendo nella AST_HandleEndProgram. PrintStringInfo(' return function of the AST is skipped.',ReportFileName,'file','y'); //RN provo a non skippare e a mettere la return. // #RNU_RES_E if (SharedInfo.CurrentFunInfo.CFunctionName == SharedInfo.CMainFunName) CCall = CCall+'return(0);'; elseif (mtlb_strcmp(part(SharedInfo.CurrentFunInfo.CFunctionName,1:5),'odefn') == %T) //For GSL library, function containing ODEs must return GSL_SUCCESS CCall = CCall + 'return GSL_SUCCESS;' else if (SharedInfo.CurrentFunInfo.PosFirstOutScalar > 0) CCall = CCall+'return('+SharedInfo.CurrentFunInfo.OutArg(SharedInfo.CurrentFunInfo.PosFirstOutScalar).Name+');' end end // #RNU_RES_B PrintStringInfo(' '+CCall,ReportFileName,'file','y'); // #RNU_RES_E PrintStringInfo(C_IndentBlanks(IndentLevel)+CCall,CPass1FileName,'file','y'); else // #RNU_RES_B PrintStringInfo(' '+CCall,ReportFileName,'file','y'); // #RNU_RES_E PrintStringInfo(C_IndentBlanks(IndentLevel)+CCall,CPass1FileName,'file','y'); if (FlagCall == 0) // Add prototype to the header file C_InitHeader(CCall+';',HeaderFileName,SharedInfo.Sci2CLibMainHeaderFName,Target,SharedInfo.OpenCVUsed); // Add { at the beginning of the function. PrintStringInfo(' {',ReportFileName,'file','y'); PrintStringInfo(C_IndentBlanks(IndentLevel)+'{',CPass1FileName,'file','y'); end end // #RNU_RES_B // Add in the C code the new size of the output argument when SCI2Cresize function is called. // #RNU_RES_E if (FunctionName == 'SCI2Cresize') // #RNU_RES_B PrintStringInfo(' Found SCI2Cresize -> Changing the size of the output argument.',ReportFileName,'file','y'); // #RNU_RES_E OutArgName = OutArg(counterout).Name; tmpcode = '__'+OutArgName+'Size[0]='+OutArg(counterout).Size(1)+';'; PrintStringInfo(C_IndentBlanks(IndentLevel)+tmpcode,CPass1FileName,'file','y'); // #RNU_RES_B PrintStringInfo(' '+tmpcode,ReportFileName,'file','y'); // #RNU_RES_E tmpcode = '__'+OutArgName+'Size[1]='+OutArg(counterout).Size(2)+';'; PrintStringInfo(C_IndentBlanks(IndentLevel)+tmpcode,CPass1FileName,'file','y'); // #RNU_RES_B PrintStringInfo(' '+tmpcode,ReportFileName,'file','y'); // #RNU_RES_E end endfunction