/* * db_eget -- * Front-end to db_get, special case handling for empty files. * * PUBLIC: int db_eget __P((SCR *, db_recno_t, CHAR_T **, size_t *, int *)); */ int db_eget(SCR *sp, db_recno_t lno, CHAR_T **pp, size_t *lenp, int *isemptyp) /* Line number. */ /* Pointer store. */ /* Length store. */ { db_recno_t l1; if (isemptyp != NULL) *isemptyp = 0; /* If the line exists, simply return it. */ if (!db_get(sp, lno, 0, pp, lenp)) return (0); /* * If the user asked for line 0 or line 1, i.e. the only possible * line in an empty file, find the last line of the file; db_last * fails loudly. */ if ((lno == 0 || lno == 1) && db_last(sp, &l1)) return (1); /* If the file isn't empty, fail loudly. */ if ((lno != 0 && lno != 1) || l1 != 0) { db_err(sp, lno); return (1); } if (isemptyp != NULL) *isemptyp = 1; return (1); }
/* * db_get -- * Look in the text buffers for a line, followed by the cache, followed * by the database. * * PUBLIC: int db_get __P((SCR *, db_recno_t, u_int32_t, CHAR_T **, size_t *)); */ int db_get(SCR *sp, db_recno_t lno, u_int32_t flags, CHAR_T **pp, size_t *lenp) /* Line number. */ /* Pointer store. */ /* Length store. */ { DBT data, key; EXF *ep; TEXT *tp; db_recno_t l1, l2; const CHAR_T *wp; size_t wlen; size_t nlen; /* * The underlying recno stuff handles zero by returning NULL, but * have to have an OOB condition for the look-aside into the input * buffer anyway. */ if (lno == 0) goto err1; /* Check for no underlying file. */ if ((ep = sp->ep) == NULL) { ex_emsg(sp, NULL, EXM_NOFILEYET); goto err3; } if (LF_ISSET(DBG_NOCACHE)) goto nocache; /* * Look-aside into the TEXT buffers and see if the line we want * is there. */ if (F_ISSET(sp, SC_TINPUT)) { l1 = ((TEXT *)sp->tiq.cqh_first)->lno; l2 = ((TEXT *)sp->tiq.cqh_last)->lno; if (l1 <= lno && l2 >= lno) { #if defined(DEBUG) && 0 vtrace(sp, "retrieve TEXT buffer line %lu\n", (u_long)lno); #endif for (tp = sp->tiq.cqh_first; tp->lno != lno; tp = tp->q.cqe_next); if (lenp != NULL) *lenp = tp->len; if (pp != NULL) *pp = tp->lb; return (0); } /* * Adjust the line number for the number of lines used * by the text input buffers. */ if (lno > l2) lno -= l2 - l1; } /* Look-aside into the cache, and see if the line we want is there. */ if (lno == sp->c_lno) { #if defined(DEBUG) && 0 vtrace(sp, "retrieve cached line %lu\n", (u_long)lno); #endif if (lenp != NULL) *lenp = sp->c_len; if (pp != NULL) *pp = sp->c_lp; return (0); } sp->c_lno = OOBLNO; nocache: nlen = 1024; retry: /* data.size contains length in bytes */ BINC_GOTO(sp, CHAR_T, sp->c_lp, sp->c_blen, nlen); /* Get the line from the underlying database. */ memset(&key, 0, sizeof(key)); key.data = &lno; key.size = sizeof(lno); memset(&data, 0, sizeof(data)); data.data = sp->c_lp; data.ulen = sp->c_blen; data.flags = DB_DBT_USERMEM; switch (ep->db->get(ep->db, NULL, &key, &data, 0)) { case DB_BUFFER_SMALL: nlen = data.size; goto retry; default: goto err2; case DB_NOTFOUND: err1: if (LF_ISSET(DBG_FATAL)) err2: db_err(sp, lno); alloc_err: err3: if (lenp != NULL) *lenp = 0; if (pp != NULL) *pp = NULL; return (1); case 0: ; } if (FILE2INT(sp, data.data, data.size, wp, wlen)) { if (!F_ISSET(sp, SC_CONV_ERROR)) { F_SET(sp, SC_CONV_ERROR); msgq(sp, M_ERR, "324|Conversion error on line %d", lno); } goto err3; } /* Reset the cache. */ if (wp != data.data) { BINC_GOTOW(sp, sp->c_lp, sp->c_blen, wlen); MEMCPYW(sp->c_lp, wp, wlen); } sp->c_lno = lno; sp->c_len = wlen; #if defined(DEBUG) && 0 vtrace(sp, "retrieve DB line %lu\n", (u_long)lno); #endif if (lenp != NULL) *lenp = wlen; if (pp != NULL) *pp = sp->c_lp; return (0); }
/* * db_get -- * Look in the text buffers for a line, followed by the cache, followed * by the database. * * PUBLIC: int db_get(SCR *, recno_t, u_int32_t, CHAR_T **, size_t *); */ int db_get( SCR *sp, recno_t lno, /* Line number. */ u_int32_t flags, CHAR_T **pp, /* Pointer store. */ size_t *lenp) /* Length store. */ { DBT data, key; EXF *ep; TEXT *tp; recno_t l1, l2; CHAR_T *wp; size_t wlen; /* * The underlying recno stuff handles zero by returning NULL, but * have to have an OOB condition for the look-aside into the input * buffer anyway. */ if (lno == 0) goto err1; /* Check for no underlying file. */ if ((ep = sp->ep) == NULL) { ex_emsg(sp, NULL, EXM_NOFILEYET); goto err3; } if (LF_ISSET(DBG_NOCACHE)) goto nocache; /* * Look-aside into the TEXT buffers and see if the line we want * is there. */ if (F_ISSET(sp, SC_TINPUT)) { l1 = ((TEXT *)TAILQ_FIRST(sp->tiq))->lno; l2 = ((TEXT *)TAILQ_LAST(sp->tiq, _texth))->lno; if (l1 <= lno && l2 >= lno) { #if defined(DEBUG) && 0 TRACE(sp, "retrieve TEXT buffer line %lu\n", (u_long)lno); #endif for (tp = TAILQ_FIRST(sp->tiq); tp->lno != lno; tp = TAILQ_NEXT(tp, q)); if (lenp != NULL) *lenp = tp->len; if (pp != NULL) *pp = tp->lb; return (0); } /* * Adjust the line number for the number of lines used * by the text input buffers. */ if (lno > l2) lno -= l2 - l1; } /* Look-aside into the cache, and see if the line we want is there. */ if (lno == ep->c_lno) { #if defined(DEBUG) && 0 TRACE(sp, "retrieve cached line %lu\n", (u_long)lno); #endif if (lenp != NULL) *lenp = ep->c_len; if (pp != NULL) *pp = ep->c_lp; return (0); } ep->c_lno = OOBLNO; nocache: /* Get the line from the underlying database. */ key.data = &lno; key.size = sizeof(lno); switch (ep->db->get(ep->db, &key, &data, 0)) { case -1: goto err2; case 1: err1: if (LF_ISSET(DBG_FATAL)) err2: db_err(sp, lno); alloc_err: err3: if (lenp != NULL) *lenp = 0; if (pp != NULL) *pp = NULL; return (1); } if (FILE2INT(sp, data.data, data.size, wp, wlen)) { if (!F_ISSET(sp, SC_CONV_ERROR)) { F_SET(sp, SC_CONV_ERROR); msgq(sp, M_ERR, "324|Conversion error on line %d", lno); } goto err3; } /* Reset the cache. */ if (wp != data.data) { BINC_GOTOW(sp, ep->c_lp, ep->c_blen, wlen); MEMCPY(ep->c_lp, wp, wlen); } else ep->c_lp = data.data; ep->c_lno = lno; ep->c_len = wlen; #if defined(DEBUG) && 0 TRACE(sp, "retrieve DB line %lu\n", (u_long)lno); #endif if (lenp != NULL) *lenp = wlen; if (pp != NULL) *pp = ep->c_lp; return (0); }