/* * Manual page at process.def */ INT16 CGEN_PUBLIC CProcess::Wait() { const SMic* pMic = NULL; // Method invocation context of Wait() CFunction* iCaller = NULL; // Function instance calling Wait() // Validate and initialize // ------------------------------------ if (!((m_nState & PRC_RUNNING)|PRC_COMPLETE)) // Not running return IERROR(this,PRC_CANTWAIT,"not started",0,0); // Forget it if (!(pMic = CDlpObject_MicGet(_this))) return -1; // Get method invocation context iCaller = (CFunction*)CDlpObject_OfKind("function",pMic->iCaller); // Get calling CFunction if (!iCaller) return -1; // Must be a function! // Wait for job to be completed // ------------------------------------ #ifdef USE_FORK if(!m_hThread && m_hPid){ // If there is a child process by fork >> waitpid(m_hPid,NULL,0); // Wait for child process m_nState &= ~PRC_RUNNING; // Clear running flag m_nState |= PRC_COMPLETE; // Set completed flag }else // << #endif dlp_join_thread(m_hThread); // Wait for the watcher thread to end ReceiveData(); // Receive transfer data // Aftermath // ------------------------------------ if (m_iDto) // This job was a function call Unmarshal(m_iDto,iCaller); // Unmarshal transfer data to caller else // This job was a program call MIC_PUT_N(m_nRetVal); // Push process return value return O_K; // Ok }
/** * Initializes the instance from the interpreter command line. * <h3>Note</h3> * <p>You must setup the method invocation context <code>m_lpMic</code> (see * <a href="dlpinst.html"><code class="link">CDlpInstance</code></a>) before * calling this method. Otherwise it will do noting.</p> * * @param _this This instance * @param nRec First record to read * @param nComp First component to read * @param nCount Number of items to read * @return O_K if successfull, an error code otherwise */ INT16 CGEN_PUBLIC CData_InitializeEx(CData* _this, INT32 nRec, INT32 nComp, INT32 nCount) { INT32 nXXR = 0; INT32 nXC = 0; INT32 nR = 0; INT32 nC = 0; INT32 nCtr = 0; BOOL bRead = 0; const char* lpsToken = NULL; if (_this && !CDlpObject_MicGet(BASEINST(_this))) return IERROR(_this,ERR_GENERIC,"No method invocation context",0,0); if (!_this || CData_IsEmpty(_this)) { /* _this == NULL is ok, just remove the tokens between { and } */ do { lpsToken = MIC_NEXTTOKEN_FORCE; if (!lpsToken) return IERROR(_this,DATA_HERESCAN,"}",0,0); } while (dlp_strcmp(lpsToken,"}")!=0); return O_K; } /* Actual setup */ nXXR = CData_GetMaxRecs(_this); nXC = CData_GetNComps(_this); nR = nRec; nC = nComp; bRead = TRUE; for (;;) { lpsToken = MIC_NEXTTOKEN_FORCE; if (!lpsToken) return IERROR(_this,DATA_HERESCAN,"}",0,0); if (dlp_strcmp(lpsToken,"}")==0) break; if (!bRead) continue; if (nR==nXXR || (nCount>=0 && nCtr>=nCount)) { /* Ignore further initializers */ bRead = FALSE; continue; } /* Initialize cell value; skip cell on wildcard '*' initializer */ if (dlp_strcmp(lpsToken,"*")!=0) IF_NOK(dlp_sscanx(lpsToken,CData_GetCompType(_this,nC),CData_XAddr(_this,nR,nC))) IERROR(_this,DATA_BADINITIALIZER,lpsToken,(int)nR,(int)nC); nCtr++; nC++; if (nC==nXC) { nC=nComp; nR++; } } if (nCount>=0&&nCtr<nCount) return IERROR(_this,DATA_INITIALIZERS,"few" ,0,0); if (!bRead ) return IERROR(_this,DATA_INITIALIZERS,"many",0,0); return O_K; }
/* * Manual page at process.def */ INT32 CGEN_PUBLIC CProcess::Start() { const SMic* pMic = NULL; // Method invocation context of Start() CFunction* iCaller = NULL; // Function calling Start() CFunction* iFnc = NULL; // Process function StkItm* pStkItm = NULL; // Stack item INT32 nArgs = 0; // Number of process function arguments // Validate and initialize // ------------------------------------ if (m_nState!=0) // Not virginal return IERROR(this,PRC_CANTSTART,"multiple starts not allowed",0,0); // Forget it! if (!(pMic = CDlpObject_MicGet(_this))) return -1; // Get method invocation context iCaller = (CFunction*)CDlpObject_OfKind("function",pMic->iCaller); // Get calling CFunction if (!iCaller) return -1; // Must be a function! // Initialize process // ------------------------------------ sprintf(m_psTmpFile,"%s%ld",dlp_tempnam(NULL,"~dLabPro#process#"),(long)dlp_time());// Initialize temp. file name prefix // Marshal arguments // ------------------------------------ if (!(pStkItm=iCaller->StackGet(0))) return IERROR(this,PRC_TOOFEWARGS,0,0,0);// Get stack top if (pStkItm->nType==T_INSTANCE) // Stack top is an instance iFnc = (CFunction*)CDlpObject_OfKind("function",pStkItm->val.i); // Get function to be called if (iFnc) // This process is a function call { // >> IFIELD_RESET(CDlpObject,"dto"); // Create data transfer object nArgs = CData_GetNRecs(iFnc->m_idArg); // Get number of function arguments Marshal(m_iDto,iCaller,nArgs); // Marshal arguments for transfer } // << else // This process is a program call dlp_strcpy(m_psCmdLine,iCaller->PopString(0)); // Get program command line #ifdef USE_FORK if (iFnc) // This process is a function call { // >> m_hPid=fork(); // Fork the process if(m_hPid>0){ // Parent process >> m_nState |= PRC_DATASENT; // Remember data have been sent m_nState |= PRC_RUNNING; // Set running flag m_hThread = 0; // Clear thread handle return O_K; // Everything is fine } // << if(m_hPid==0) return DoJobFork(iCaller,iFnc); // The child process runs the function return IERROR(this,PRC_CANTSTART,"fork() failed",0,0); // On error (fid<0) we return } // << #endif // Start job in watcher thread // ------------------------------------ m_hPid = 0; // Reset process id SendData(); // Send transfer data m_hThread = dlp_create_thread(DoJob,this); // Do the job and watch it return O_K; // Yo! }
/** * Get data initializer '{ ... }' from command line and store into token list * lpsInit. * <h3>Note</h3> * <p>You must setup the method invocation context <code>m_lpMic</code> (see * <a href="dlpinst.html"><code class="link">CDlpInstance</code></a>) before * calling this method. Otherwise it will do noting.</p> * * @param lpsInit Pointer to character buffer to store initializer in. The * tokens will be separated by nulls '\0', opening and closing * curly braces will not be included! The token list will be * terminated with a double null "\0\0". * @param nLen Maximal number of characters to place on lpsInit (including * the terminal double null) * @param bForce If TRUE the method does not seek for the opening curly brace * but starts reading initializers until it encounters a closing * curly brace '}'. A leading opening curly brace will, however, * be tolerated. If FALSE the method <i>expects</i> an opening * curly brace and does not read any initializers if no leading * opening brace is found. * @return The number of initializers read */ INT32 CGEN_PROTECTED CData_ReadInitializer ( CData* _this, char* lpsInit, INT32 nLen, BOOL bForce ) { const char* lpsToken; /* Current token */ INT32 nCnt; /* Token counter */ INT32 nPos; /* Position in output buffer */ BOOL bStor; /* Store next token */ /* Initialize */ /* --------------------------------- */ if (!CDlpObject_MicGet(BASEINST(_this))) return 0; /* Need invocation context */ if (!lpsInit) return 0; /* Need output buffer */ dlp_memset(lpsInit,0,nLen); /* Clear output buffer */ /* Do initializers follow? */ /* --------------------------------- */ lpsToken = MIC_NEXTTOKEN_FORCE; /* Ruthlessly get next token */ if (!lpsToken || dlp_strcmp(lpsToken,"{")!=0) /* No or not the "{" token */ { /* >> */ if (bForce) IERROR(_this,DATA_NOTFOUND,"Constant initializer ","'{'",0); /* If there should be some-> error */ if (lpsToken) MIC_REFUSETOKEN; /* Wrong token -> push it back */ return 0; /* Now get out'a here */ } /* << */ /* Get 'em tokens */ /* --------------------------------- */ for (nCnt=0,nPos=0,bStor=TRUE; ; nCnt++) /* Infinitely ... */ { /* >> */ lpsToken = MIC_NEXTTOKEN_FORCE; /* Ruthlessly get next token */ if (!lpsToken) return IERROR(_this,DATA_HERESCAN,"}",0,0); /* No more tokens -> forget it */ if (dlp_strcmp(lpsToken,"}")==0) break; /* End token -> get out'a here */ if (nLen<nPos+(INT32)dlp_strlen(lpsToken)+2) bStor = FALSE; /* Cannot store more tokens :( */ if (!bStor) continue; /* Ignore ALL following tokens */ dlp_strcpy(&lpsInit[nPos],lpsToken); /* Store token */ nPos+=(INT32)dlp_strlen(&lpsInit[nPos])+1; /* Set next token pointer */ } /* << */ return nCnt; /* Return number of tokens read */ }
/* * Manual page at process.def */ INT16 CGEN_PUBLIC CProcess::MarshalRetval() { CDlpObject* iDto = NULL; // Data transfer object const SMic* pMic = NULL; // Current method invocation context CFunction* iCaller = NULL; // Calling function StkItm* pStkItm = NULL; // Stack item to marshal // Validate and initialize // ------------------------------------ if (!(pMic = CDlpObject_MicGet(_this))) return -1; // Get method invocation context iCaller = (CFunction*)CDlpObject_OfKind("function",pMic->iCaller); // Get calling CFunction if (!iCaller) return -1; // Must be a function! // Pack second stack element into the CDlpObject on the stack top // ------------------------------------ iDto = iCaller->PopInstance(0); // Get instance on stack top if (!iDto) return NOT_EXEC; // No instance on stack top --> puuh! if (iCaller->StackGetLength()==0) return O_K; // Nothing more on the stack --> ok pStkItm = iCaller->StackGet(0); // Get stack top Pack(iDto,NULL,pStkItm,PRC_S_RETV); // Pack it as "~iRetv" iCaller->Pop(0); // Remove stack top return O_K; // Ok }
/** * Polymorphic set operations. * * @param lpsOpname * <p>Operator name</p> * <table> * <tr><th><code>lpsOpname</code></th><th>Boolean</th><th>Numeric</th><th>String</th><th>Instance</th></tr> * <tr><td><code>= </code></td><td>x</td><td>x</td><td>x</td><td>x</td></tr> * <tr><td><code>+= </code></td><td>x</td><td>x</td><td>x</td><td>-</td></tr> * <tr><td><code>-= </code></td><td>-</td><td>x</td><td>-</td><td>-</td></tr> * <tr><td><code>*= </code></td><td>x</td><td>x</td><td>-</td><td>-</td></tr> * <tr><td><code>/= </code></td><td>-</td><td>x</td><td>-</td><td>-</td></tr> * <tr><td><code>++=</code></td><td>-</td><td>x</td><td>-</td><td>-</td></tr> * <tr><td><code>--=</code></td><td>-</td><td>x</td><td>-</td><td>-</td></tr> * </table> * <p>For type conversion rules see * <code><a href="function.html"><code�class="link">CFunction</code></a><code>::StackLogic</code>, * <code><a href="function.html"><code�class="link">CFunction</code></a><code>::StackNumber</code>, * <code><a href="function.html"><code�class="link">CFunction</code></a><code>::StackString</code> and * <code><a href="function.html"><code�class="link">CFunction</code></a><code>::StackInstance</code>. * </p> * @return <code>O_K</code> if successfull, a (negative) error code otherwise */ INT16 CGEN_PROTECTED CVar_SetOp(CVar *_this,const char* lpsOpname) { StkItm si; if (dlp_strcmp(lpsOpname,"++=")!=0 && dlp_strcmp(lpsOpname,"--=")!=0) { if (!CDlpObject_MicGet(BASEINST(_this))->GetX) return IERROR(_this,VAR_NOTSUPPORTED,"Polymorphic signatures"," by caller",0); if (!MIC_GET_X(1,&si)) return NOT_EXEC; } if (dlp_strcmp(lpsOpname,"=")==0) switch (si.nType) { case T_BOOL : return CVar_Bset(_this,si.val.b); case T_COMPLEX : return CVar_Vset(_this,si.val.n); case T_STRING : return CVar_Sset(_this,si.val.s); case T_INSTANCE: return CVar_Iset(_this,si.val.i); default: DLPASSERT(FMSG("Unknown variable type")); return NOT_EXEC; } else if (dlp_strcmp(lpsOpname,"+=")==0) { if (_this->m_nType==T_COMPLEX) return CVar_Vset(_this,CMPLX_PLUS(_this->m_nNVal,si.val.n)); if (_this->m_nType==T_STRING) { char* lpsSi = NULL; MIC_PUT_X(&si); lpsSi = MIC_GET_S(1,0); _this->m_lpsSVal = (char*)dlp_realloc(_this->m_lpsSVal, dlp_strlen(_this->m_lpsSVal)+dlp_strlen(lpsSi)+1,sizeof(char)); if (!_this->m_lpsSVal) return IERROR(_this,ERR_NOMEM,0,0,0); dlp_strcat(_this->m_lpsSVal,lpsSi); return O_K; } if (_this->m_nType==T_BOOL) { MIC_PUT_X(&si); _this->m_bBVal|=MIC_GET_B(1,0); return O_K; } return IERROR(_this,VAR_NOTSUPPORTED,"Operator +="," for this variable type",0); } else if (dlp_strcmp(lpsOpname,"*=")==0) { if (_this->m_nType==T_COMPLEX) return CVar_Vset(_this,CMPLX_MULT(_this->m_nNVal,si.val.n)); if (_this->m_nType==T_BOOL) { MIC_PUT_X(&si); _this->m_bBVal&=MIC_GET_B(1,0); return O_K; } return IERROR(_this,VAR_NOTSUPPORTED,"Operator *="," for this variable type",0); } else if (dlp_strcmp(lpsOpname,"-=")==0) { if (_this->m_nType==T_COMPLEX) return CVar_Vset(_this,CMPLX_MINUS(_this->m_nNVal,si.val.n)); return IERROR(_this,VAR_NOTSUPPORTED,"Operator -="," for this variable type",0); } else if (dlp_strcmp(lpsOpname,"/=")==0) { if (_this->m_nType==T_COMPLEX) return CVar_Vset(_this,CMPLX_MULT(_this->m_nNVal,CMPLX_INVT(si.val.n))); return IERROR(_this,VAR_NOTSUPPORTED,"Operator /="," for this variable type",0); } else if (dlp_strcmp(lpsOpname,"++=")==0) { if (_this->m_nType==T_COMPLEX) return CVar_Vset(_this,CMPLX_INC(_this->m_nNVal)); return IERROR(_this,VAR_NOTSUPPORTED,"Operator ++="," for this variable type",0); } else if (dlp_strcmp(lpsOpname,"--=")==0) { if (_this->m_nType==T_COMPLEX) return CVar_Vset(_this,CMPLX_DEC(_this->m_nNVal)); return IERROR(_this,VAR_NOTSUPPORTED,"Operator --="," for this variable type",0); } return NOT_EXEC; }