📄 wdbgopherlib.c
字号:
gc->tapeIx += nbytes; return OK; }/******************************************************************************** gopherWriteString -**/static STATUS gopherWriteString ( wdbGopherCtx_t * gc, char * string ) { int maxlen; /* how much we can carry */ if (string == 0) { if (gc->tapeLen - gc->tapeIx < 2) { gc->status = WDB_ERR_GOPHER_TRUNCATED; return ERROR; } gc->pTape [gc->tapeIx++] = GOPHER_STRING; gc->pTape [gc->tapeIx++] = EOS; return OK; } /* we can write no more than the size of the remaining buffer minus 1 (we have to save a byte for the null terminator). */ maxlen = gc->tapeLen - gc->tapeIx; { int status; char * pEnd; int nRead; int numToRead = min (maxlen, MaxTgtStrLen); char * pReadBuf = new char [maxlen]; /* Get a chunk of memory which is of size numToRead */ status = Backend_T::tgtRead_s ((TGT_ADDR_T) string, pReadBuf, numToRead); if (status != OK) { gc->status = WDB_ERR_MEM_ACCES; return ERROR; } /* Null terminate the chunk */ pReadBuf [numToRead - 1] = EOS; /* Find the real end of the string */ pEnd = strchr (pReadBuf, EOS); if (pEnd == NULL) { memcpy (gc->pTape + gc->tapeIx, pReadBuf, numToRead - 1); gc->tapeIx += numToRead - 1; gc->status = WDB_ERR_GOPHER_TRUNCATED; return ERROR; } nRead = (UINT32) pEnd - (UINT32) pReadBuf; nRead++; /* account for EOS character ('\0') */ memcpy (gc->pTape + gc->tapeIx, pReadBuf, nRead); gc->tapeIx += nRead; delete [] pReadBuf; return OK; } }/******************************************************************************** gopherWriteP - write the pointer to the tape** NOMANUAL*/STATUS gopherWriteP ( wdbGopherCtx_t * gc /* gopher context */ ) { int nbytes = 4; /* p is a UINT32 */ /* We must have at least nbytes+1 bytes left: one for type marker, nbytes for the scalar itself. */ if (gc->tapeLen - gc->tapeIx < nbytes+1) { gc->status = WDB_ERR_GOPHER_TRUNCATED; return ERROR; } /* Write the scalar type. */ gc->pTape [gc->tapeIx++] = GOPHER_UINT32; /* Write the scalar itself. */ memcpy ((gc->pTape + gc->tapeIx), (char *) &gc->p, nbytes); gc->tapeIx += nbytes; return OK; }#else/******************************************************************************** wdbGopherLibInit -*/void wdbGopherLibInit (void) { pAddTape [0] = tape; wdbSvcAdd (WDB_EVALUATE_GOPHER, wdbEvaluateGopher, xdr_WDB_STRING_T, xdr_WDB_MEM_XFER); }/******************************************************************************** wdbEvaluateGopher -*/static UINT32 wdbEvaluateGopher ( WDB_STRING_T * pProgram, WDB_MEM_XFER * pValueTape ) { wdbGopherCtx_t gc; int ix; gc.status = OK; pAddTape [0] = tape; if (*pProgram != NULL) { /* starting a new evaluation */ tapeIndex = 0; gc.program = *pProgram; gc.p = 0; gc.tapeLen = tapeLen; gc.execute = 1; if (wdbIsNowTasking() && (pWdbRtIf->taskLock != NULL)) { /* we check that no info is stored */ for (ix = 0; (ix < ADD_TAPE_NB); ix++) { if ((pAddTape[ix]) && ix && (pWdbRtIf->free != NULL)) { (*pWdbRtIf->free) (pAddTape[ix]); pAddTape [ix] = NULL; } pAddTapeIx[ix] = 0; } gc.pTape = pAddTape[0]; gc.tapeIx = 0; if (wdbGopherLock) { (*pWdbRtIf->taskLock)(); gopher (&gc); (*pWdbRtIf->taskUnlock)(); } else gopher (&gc); pAddTapeIx[tapeIndex] = gc.tapeIx; } else { /* * system mode : malloc is forbidden we can only store result * in pAddTape[0] */ gc.pTape = pAddTape[0]; gc.tapeIx = 0; gopher (&gc); pAddTapeIx [0] = gc.tapeIx; } /* prepare transfer by resetting tapeIndex */ tapeIndex = 0; } if (gc.status == OK) gc.status = wdbTransferGopher (pValueTape); else { /* delete additional tapes if some were allocated */ for (ix = 0; (ix < ADD_TAPE_NB) && (pWdbRtIf->free != NULL); ix++) if ((pAddTape[ix]) && ix) { (*pWdbRtIf->free) (pAddTape[ix]); pAddTape[ix] = NULL; } } return (gc.status); }/******************************************************************************** wdbTransferGopher - answer to a gopher request using stored results** This routine also frees tapes when they become out of date (ie when we are* transfering the next one).**/static STATUS wdbTransferGopher ( WDB_MEM_XFER * pValueTape ) { int offset = 0; int tIndex = 0; int ix; /* * from the index of the request we computed the start address of the * result string */#ifdef DEBUG printErr ("tapeIndex = %d\n", tapeIndex);#endif for (ix = 0; (ix < tapeIndex); ix++) { offset += min (wdbCommMtu - WDB_GOPHER_MTU_OFFSET, tapeLen); if (offset >= pAddTapeIx[tIndex]) { offset = 0; tIndex++; } } tapeIndex ++; /* free the last used tape if necessary */ if ((tIndex > 1) && (pAddTape[tIndex - 1]) && (pWdbRtIf->free != NULL)) { (*pWdbRtIf->free) (pAddTape[tIndex - 1]); pAddTape[tIndex - 1] = NULL; } /* check if every thing is transfered or if we should send another tape */ if ((tIndex == ADD_TAPE_NB) || (pAddTapeIx[tIndex] == 0)) { pValueTape->numBytes = 0; return OK; } pValueTape->source = (char *)((int)pAddTape[tIndex] + offset); pValueTape->numBytes = min (pAddTapeIx[tIndex] - offset, wdbCommMtu - WDB_GOPHER_MTU_OFFSET);#ifdef DEBUG printErr ("pAddTapeIx[%d]= %d, offset = %d, numbytes = %d\n", tIndex, pAddTapeIx[tIndex], offset, pValueTape->numBytes);#endif /* * what about status to return * the only case to return OK is no tapes were allocated and the current * tape is transfered */ if (tIndex == 0) { if ((pValueTape->numBytes + offset >= pAddTapeIx[tIndex]) && (pAddTape[tIndex + 1] == NULL)) /* tape 0 is finished and there is no other one */ return OK; } return (OK | WDB_TO_BE_CONTINUED); }/******************************************************************************* gopherNewTapeAllocate - when possible allocate a buffer to store a longer* gopher string**/static STATUS gopherNewTapeAllocate ( wdbGopherCtx_t * gc ) { pAddTapeIx[tapeIndex] = gc->tapeIx; if (wdbIsNowTasking ()) { /* try to allocate a new tape if possible */ if ((pWdbRtIf->malloc == NULL) || (++tapeIndex >= ADD_TAPE_NB) || ((pAddTape[tapeIndex] = (*pWdbRtIf->malloc) (gc->tapeLen)) == NULL)) { gc->status = WDB_ERR_GOPHER_TRUNCATED; return ERROR; } gc->pTape = pAddTape[tapeIndex]; gc->tapeIx = 0; } else { /* system mode: we can't allocate more than the static buffer */ gc->status = WDB_ERR_GOPHER_TRUNCATED; return ERROR; } return OK; }/****************************************************************************** * gopherWriteScalar - write a scalar value on a gopher tape**/static STATUS gopherWriteScalar ( wdbGopherCtx_t * gc, /* gopher context */ UINT8 * src, /* source address */ int type /* GOPHER_UINT32, etc. */ ) { int nbytes = 4; /* UINT32 is most common */ int r1; /* memProbe result */ int r2; /* memProbe result */ INT8 dummy [4]; /* dummy memProbe buf */ if (type == GOPHER_UINT16) nbytes = 2; /* fix nbytes if size != 4 */ if (type == GOPHER_UINT8) nbytes = 1; if (type == GOPHER_FLOAT64) nbytes = 8; if (type == GOPHER_FLOAT80) nbytes = 10; /* We must have at least nbytes+1 bytes left: one for type marker, nbytes for the scalar itself. */ if (gc->tapeLen - gc->tapeIx < nbytes+1) { if (gopherNewTapeAllocate (gc) == ERROR) return ERROR; } /* Write the scalar type. */ gc->pTape [gc->tapeIx++] = type; /* Write the scalar itself--probe the two endpoints. */ if (nbytes <= 4) { r1 = r2 = (*pWdbRtIf->memProbe) ((char *) src, VX_READ, nbytes, dummy); } else { r1 = (*pWdbRtIf->memProbe) ((char *) src, VX_READ, 1, dummy); r2 = (*pWdbRtIf->memProbe) ((char *) src + nbytes - 1, VX_READ, 1, dummy); } if (r1 == OK && r2 == OK) { bcopy ((char *) src, gc->pTape + gc->tapeIx, nbytes); gc->tapeIx += nbytes; return OK; } else { gc->status = WDB_ERR_GOPHER_FAULT; return ERROR; } }/******************************************************************************* gopherWriteString - write a string to a gopher tape**/static STATUS gopherWriteString ( wdbGopherCtx_t * gc, char * string ) { int r1; /* memProbe result */ int r2; /* memProbe result */ int r3 = 0; /* memProbe result */ char dummy; /* memProbe read value */ int maxlen; /* how much we can carry */ char * p = string; int ix; if (string == 0) { if (gc->tapeLen - gc->tapeIx < 1) { if (gopherNewTapeAllocate (gc) == ERROR) return ERROR; } gc->pTape [gc->tapeIx++] = GOPHER_STRING; if (gc->tapeLen - gc->tapeIx < 1) { if (gopherNewTapeAllocate (gc) == ERROR) return ERROR; } gc->pTape [gc->tapeIx++] = EOS; return OK; } /* if possible, write the gopher type on the tape */ if (gc->tapeLen - gc->tapeIx < 1) { if (gopherNewTapeAllocate (gc) == ERROR) return ERROR; } gc->pTape [gc->tapeIx++] = GOPHER_STRING; /* write the string itself */ while (1) { /* We can write no more than the size of the remaining buffer */ maxlen = gc->tapeLen - gc->tapeIx; /* probe the two endpoints. Note there's a weakness here; it may be that a short string lies near the boundary of a memory accessibility region and we're about to probe past the end of it, which may give a false result. But we can't call strlen on the string without some hope that it is bounded by real memory. */ r1 = (*pWdbRtIf->memProbe) (p, VX_READ, 1, &dummy); r2 = (*pWdbRtIf->memProbe) (p + maxlen, VX_READ, 1, &dummy); if (r1 == OK && r2 != OK) { /* If the start endpoint probe was okay, but not the end one then * we assume we have tried to read outside the memory boundary. * Given that the boundary is probably at the very least 2K byte * aligned (more likely 64k or more), we modify the top * address to account for this and repeat the probe just for good * measure. */ maxlen = ((((long) (p + maxlen)) & ~0x7ff) - 1) - (long) p; r3 = (*pWdbRtIf->memProbe) (p + maxlen, VX_READ, 1, &dummy); } if (r1 != OK || r3 != OK) break; /* exit loop: there is an error */ for (ix = 0; *p && ix < maxlen; p++, ix++) { /* * Do not need to test if there is place for each character. * We can't write more than <maxlen> character (i.e. fill the * current tape ). */ gc->pTape [gc->tapeIx++] = *p; }#if DEBUG printf ("maxlen=%d, r1=%d, r2=%d, r3=%d, ix=%d, *p=%#x\n", maxlen, r1, r2, r3, ix, *p);#endif if (*p == EOS) { /* EOS found : write null terminator and return OK */ if (gc->tapeLen - gc->tapeIx < 1) { if (gopherNewTapeAllocate (gc) == ERROR) return ERROR; } gc->pTape [gc->tapeIx++] = *p; return OK; } else if (r2 != OK) { /* we reached maxlen (hardware limitation) : return ERROR */ gc->status = WDB_ERR_GOPHER_TRUNCATED; return (ERROR); } else { /* * we finished the probed zone so re-probe before continuing * we allocate a new tape (if needed) to update maxlen computation */ if (gc->tapeLen - gc->tapeIx < 1) { if (gopherNewTapeAllocate (gc) == ERROR) return (ERROR); } } } /* one of the endpoints was bogus. Can't write the string. */ gc->status = WDB_ERR_GOPHER_FAULT; return ERROR; }#endif /* #ifdef HOST */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -