1*45a5aec3SBaptiste Daroussin /* $Id: dbm.c,v 1.7 2019/07/01 22:56:24 schwarze Exp $ */ 261d06d6bSBaptiste Daroussin /* 361d06d6bSBaptiste Daroussin * Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org> 461d06d6bSBaptiste Daroussin * 561d06d6bSBaptiste Daroussin * Permission to use, copy, modify, and distribute this software for any 661d06d6bSBaptiste Daroussin * purpose with or without fee is hereby granted, provided that the above 761d06d6bSBaptiste Daroussin * copyright notice and this permission notice appear in all copies. 861d06d6bSBaptiste Daroussin * 961d06d6bSBaptiste Daroussin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1061d06d6bSBaptiste Daroussin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1161d06d6bSBaptiste Daroussin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1261d06d6bSBaptiste Daroussin * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1361d06d6bSBaptiste Daroussin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1461d06d6bSBaptiste Daroussin * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1561d06d6bSBaptiste Daroussin * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1661d06d6bSBaptiste Daroussin * 1761d06d6bSBaptiste Daroussin * Map-based version of the mandoc database, for read-only access. 1861d06d6bSBaptiste Daroussin * The interface is defined in "dbm.h". 1961d06d6bSBaptiste Daroussin */ 2061d06d6bSBaptiste Daroussin #include "config.h" 2161d06d6bSBaptiste Daroussin 2261d06d6bSBaptiste Daroussin #include <assert.h> 2361d06d6bSBaptiste Daroussin #if HAVE_ENDIAN 2461d06d6bSBaptiste Daroussin #include <endian.h> 2561d06d6bSBaptiste Daroussin #elif HAVE_SYS_ENDIAN 2661d06d6bSBaptiste Daroussin #include <sys/endian.h> 2761d06d6bSBaptiste Daroussin #elif HAVE_NTOHL 2861d06d6bSBaptiste Daroussin #include <arpa/inet.h> 2961d06d6bSBaptiste Daroussin #endif 3061d06d6bSBaptiste Daroussin #if HAVE_ERR 3161d06d6bSBaptiste Daroussin #include <err.h> 3261d06d6bSBaptiste Daroussin #endif 3361d06d6bSBaptiste Daroussin #include <errno.h> 3461d06d6bSBaptiste Daroussin #include <regex.h> 3561d06d6bSBaptiste Daroussin #include <stdint.h> 3661d06d6bSBaptiste Daroussin #include <stdio.h> 3761d06d6bSBaptiste Daroussin #include <stdlib.h> 3861d06d6bSBaptiste Daroussin #include <string.h> 3961d06d6bSBaptiste Daroussin 4061d06d6bSBaptiste Daroussin #include "mansearch.h" 4161d06d6bSBaptiste Daroussin #include "dbm_map.h" 4261d06d6bSBaptiste Daroussin #include "dbm.h" 4361d06d6bSBaptiste Daroussin 4461d06d6bSBaptiste Daroussin struct macro { 4561d06d6bSBaptiste Daroussin int32_t value; 4661d06d6bSBaptiste Daroussin int32_t pages; 4761d06d6bSBaptiste Daroussin }; 4861d06d6bSBaptiste Daroussin 4961d06d6bSBaptiste Daroussin struct page { 5061d06d6bSBaptiste Daroussin int32_t name; 5161d06d6bSBaptiste Daroussin int32_t sect; 5261d06d6bSBaptiste Daroussin int32_t arch; 5361d06d6bSBaptiste Daroussin int32_t desc; 5461d06d6bSBaptiste Daroussin int32_t file; 5561d06d6bSBaptiste Daroussin }; 5661d06d6bSBaptiste Daroussin 5761d06d6bSBaptiste Daroussin enum iter { 5861d06d6bSBaptiste Daroussin ITER_NONE = 0, 5961d06d6bSBaptiste Daroussin ITER_NAME, 6061d06d6bSBaptiste Daroussin ITER_SECT, 6161d06d6bSBaptiste Daroussin ITER_ARCH, 6261d06d6bSBaptiste Daroussin ITER_DESC, 6361d06d6bSBaptiste Daroussin ITER_MACRO 6461d06d6bSBaptiste Daroussin }; 6561d06d6bSBaptiste Daroussin 6661d06d6bSBaptiste Daroussin static struct macro *macros[MACRO_MAX]; 6761d06d6bSBaptiste Daroussin static int32_t nvals[MACRO_MAX]; 6861d06d6bSBaptiste Daroussin static struct page *pages; 6961d06d6bSBaptiste Daroussin static int32_t npages; 7061d06d6bSBaptiste Daroussin static enum iter iteration; 7161d06d6bSBaptiste Daroussin 7261d06d6bSBaptiste Daroussin static struct dbm_res page_bytitle(enum iter, const struct dbm_match *); 7361d06d6bSBaptiste Daroussin static struct dbm_res page_byarch(const struct dbm_match *); 7461d06d6bSBaptiste Daroussin static struct dbm_res page_bymacro(int32_t, const struct dbm_match *); 7561d06d6bSBaptiste Daroussin static char *macro_bypage(int32_t, int32_t); 7661d06d6bSBaptiste Daroussin 7761d06d6bSBaptiste Daroussin 7861d06d6bSBaptiste Daroussin /*** top level functions **********************************************/ 7961d06d6bSBaptiste Daroussin 8061d06d6bSBaptiste Daroussin /* 8161d06d6bSBaptiste Daroussin * Open a disk-based mandoc database for read-only access. 8261d06d6bSBaptiste Daroussin * Map the pages and macros[] arrays. 8361d06d6bSBaptiste Daroussin * Return 0 on success. Return -1 and set errno on failure. 8461d06d6bSBaptiste Daroussin */ 8561d06d6bSBaptiste Daroussin int 8661d06d6bSBaptiste Daroussin dbm_open(const char *fname) 8761d06d6bSBaptiste Daroussin { 8861d06d6bSBaptiste Daroussin const int32_t *mp, *ep; 8961d06d6bSBaptiste Daroussin int32_t im; 9061d06d6bSBaptiste Daroussin 9161d06d6bSBaptiste Daroussin if (dbm_map(fname) == -1) 9261d06d6bSBaptiste Daroussin return -1; 9361d06d6bSBaptiste Daroussin 9461d06d6bSBaptiste Daroussin if ((npages = be32toh(*dbm_getint(4))) < 0) { 9561d06d6bSBaptiste Daroussin warnx("dbm_open(%s): Invalid number of pages: %d", 9661d06d6bSBaptiste Daroussin fname, npages); 9761d06d6bSBaptiste Daroussin goto fail; 9861d06d6bSBaptiste Daroussin } 9961d06d6bSBaptiste Daroussin pages = (struct page *)dbm_getint(5); 10061d06d6bSBaptiste Daroussin 10161d06d6bSBaptiste Daroussin if ((mp = dbm_get(*dbm_getint(2))) == NULL) { 10261d06d6bSBaptiste Daroussin warnx("dbm_open(%s): Invalid offset of macros array", fname); 10361d06d6bSBaptiste Daroussin goto fail; 10461d06d6bSBaptiste Daroussin } 10561d06d6bSBaptiste Daroussin if (be32toh(*mp) != MACRO_MAX) { 10661d06d6bSBaptiste Daroussin warnx("dbm_open(%s): Invalid number of macros: %d", 10761d06d6bSBaptiste Daroussin fname, be32toh(*mp)); 10861d06d6bSBaptiste Daroussin goto fail; 10961d06d6bSBaptiste Daroussin } 11061d06d6bSBaptiste Daroussin for (im = 0; im < MACRO_MAX; im++) { 11161d06d6bSBaptiste Daroussin if ((ep = dbm_get(*++mp)) == NULL) { 11261d06d6bSBaptiste Daroussin warnx("dbm_open(%s): Invalid offset of macro %d", 11361d06d6bSBaptiste Daroussin fname, im); 11461d06d6bSBaptiste Daroussin goto fail; 11561d06d6bSBaptiste Daroussin } 11661d06d6bSBaptiste Daroussin nvals[im] = be32toh(*ep); 11761d06d6bSBaptiste Daroussin macros[im] = (struct macro *)++ep; 11861d06d6bSBaptiste Daroussin } 11961d06d6bSBaptiste Daroussin return 0; 12061d06d6bSBaptiste Daroussin 12161d06d6bSBaptiste Daroussin fail: 12261d06d6bSBaptiste Daroussin dbm_unmap(); 12361d06d6bSBaptiste Daroussin errno = EFTYPE; 12461d06d6bSBaptiste Daroussin return -1; 12561d06d6bSBaptiste Daroussin } 12661d06d6bSBaptiste Daroussin 12761d06d6bSBaptiste Daroussin void 12861d06d6bSBaptiste Daroussin dbm_close(void) 12961d06d6bSBaptiste Daroussin { 13061d06d6bSBaptiste Daroussin dbm_unmap(); 13161d06d6bSBaptiste Daroussin } 13261d06d6bSBaptiste Daroussin 13361d06d6bSBaptiste Daroussin 13461d06d6bSBaptiste Daroussin /*** functions for handling pages *************************************/ 13561d06d6bSBaptiste Daroussin 13661d06d6bSBaptiste Daroussin int32_t 13761d06d6bSBaptiste Daroussin dbm_page_count(void) 13861d06d6bSBaptiste Daroussin { 13961d06d6bSBaptiste Daroussin return npages; 14061d06d6bSBaptiste Daroussin } 14161d06d6bSBaptiste Daroussin 14261d06d6bSBaptiste Daroussin /* 14361d06d6bSBaptiste Daroussin * Give the caller pointers to the data for one manual page. 14461d06d6bSBaptiste Daroussin */ 14561d06d6bSBaptiste Daroussin struct dbm_page * 14661d06d6bSBaptiste Daroussin dbm_page_get(int32_t ip) 14761d06d6bSBaptiste Daroussin { 14861d06d6bSBaptiste Daroussin static struct dbm_page res; 14961d06d6bSBaptiste Daroussin 15061d06d6bSBaptiste Daroussin assert(ip >= 0); 15161d06d6bSBaptiste Daroussin assert(ip < npages); 15261d06d6bSBaptiste Daroussin res.name = dbm_get(pages[ip].name); 15361d06d6bSBaptiste Daroussin if (res.name == NULL) 1547295610fSBaptiste Daroussin res.name = "(NULL)\0"; 15561d06d6bSBaptiste Daroussin res.sect = dbm_get(pages[ip].sect); 15661d06d6bSBaptiste Daroussin if (res.sect == NULL) 1577295610fSBaptiste Daroussin res.sect = "(NULL)\0"; 15861d06d6bSBaptiste Daroussin res.arch = pages[ip].arch ? dbm_get(pages[ip].arch) : NULL; 15961d06d6bSBaptiste Daroussin res.desc = dbm_get(pages[ip].desc); 16061d06d6bSBaptiste Daroussin if (res.desc == NULL) 16161d06d6bSBaptiste Daroussin res.desc = "(NULL)"; 16261d06d6bSBaptiste Daroussin res.file = dbm_get(pages[ip].file); 16361d06d6bSBaptiste Daroussin if (res.file == NULL) 1647295610fSBaptiste Daroussin res.file = " (NULL)\0"; 16561d06d6bSBaptiste Daroussin res.addr = dbm_addr(pages + ip); 16661d06d6bSBaptiste Daroussin return &res; 16761d06d6bSBaptiste Daroussin } 16861d06d6bSBaptiste Daroussin 16961d06d6bSBaptiste Daroussin /* 17061d06d6bSBaptiste Daroussin * Functions to start filtered iterations over manual pages. 17161d06d6bSBaptiste Daroussin */ 17261d06d6bSBaptiste Daroussin void 17361d06d6bSBaptiste Daroussin dbm_page_byname(const struct dbm_match *match) 17461d06d6bSBaptiste Daroussin { 17561d06d6bSBaptiste Daroussin assert(match != NULL); 17661d06d6bSBaptiste Daroussin page_bytitle(ITER_NAME, match); 17761d06d6bSBaptiste Daroussin } 17861d06d6bSBaptiste Daroussin 17961d06d6bSBaptiste Daroussin void 18061d06d6bSBaptiste Daroussin dbm_page_bysect(const struct dbm_match *match) 18161d06d6bSBaptiste Daroussin { 18261d06d6bSBaptiste Daroussin assert(match != NULL); 18361d06d6bSBaptiste Daroussin page_bytitle(ITER_SECT, match); 18461d06d6bSBaptiste Daroussin } 18561d06d6bSBaptiste Daroussin 18661d06d6bSBaptiste Daroussin void 18761d06d6bSBaptiste Daroussin dbm_page_byarch(const struct dbm_match *match) 18861d06d6bSBaptiste Daroussin { 18961d06d6bSBaptiste Daroussin assert(match != NULL); 19061d06d6bSBaptiste Daroussin page_byarch(match); 19161d06d6bSBaptiste Daroussin } 19261d06d6bSBaptiste Daroussin 19361d06d6bSBaptiste Daroussin void 19461d06d6bSBaptiste Daroussin dbm_page_bydesc(const struct dbm_match *match) 19561d06d6bSBaptiste Daroussin { 19661d06d6bSBaptiste Daroussin assert(match != NULL); 19761d06d6bSBaptiste Daroussin page_bytitle(ITER_DESC, match); 19861d06d6bSBaptiste Daroussin } 19961d06d6bSBaptiste Daroussin 20061d06d6bSBaptiste Daroussin void 20161d06d6bSBaptiste Daroussin dbm_page_bymacro(int32_t im, const struct dbm_match *match) 20261d06d6bSBaptiste Daroussin { 20361d06d6bSBaptiste Daroussin assert(im >= 0); 20461d06d6bSBaptiste Daroussin assert(im < MACRO_MAX); 20561d06d6bSBaptiste Daroussin assert(match != NULL); 20661d06d6bSBaptiste Daroussin page_bymacro(im, match); 20761d06d6bSBaptiste Daroussin } 20861d06d6bSBaptiste Daroussin 20961d06d6bSBaptiste Daroussin /* 21061d06d6bSBaptiste Daroussin * Return the number of the next manual page in the current iteration. 21161d06d6bSBaptiste Daroussin */ 21261d06d6bSBaptiste Daroussin struct dbm_res 21361d06d6bSBaptiste Daroussin dbm_page_next(void) 21461d06d6bSBaptiste Daroussin { 21561d06d6bSBaptiste Daroussin struct dbm_res res = {-1, 0}; 21661d06d6bSBaptiste Daroussin 21761d06d6bSBaptiste Daroussin switch(iteration) { 21861d06d6bSBaptiste Daroussin case ITER_NONE: 21961d06d6bSBaptiste Daroussin return res; 22061d06d6bSBaptiste Daroussin case ITER_ARCH: 22161d06d6bSBaptiste Daroussin return page_byarch(NULL); 22261d06d6bSBaptiste Daroussin case ITER_MACRO: 22361d06d6bSBaptiste Daroussin return page_bymacro(0, NULL); 22461d06d6bSBaptiste Daroussin default: 22561d06d6bSBaptiste Daroussin return page_bytitle(iteration, NULL); 22661d06d6bSBaptiste Daroussin } 22761d06d6bSBaptiste Daroussin } 22861d06d6bSBaptiste Daroussin 22961d06d6bSBaptiste Daroussin /* 23061d06d6bSBaptiste Daroussin * Functions implementing the iteration over manual pages. 23161d06d6bSBaptiste Daroussin */ 23261d06d6bSBaptiste Daroussin static struct dbm_res 23361d06d6bSBaptiste Daroussin page_bytitle(enum iter arg_iter, const struct dbm_match *arg_match) 23461d06d6bSBaptiste Daroussin { 23561d06d6bSBaptiste Daroussin static const struct dbm_match *match; 23661d06d6bSBaptiste Daroussin static const char *cp; 23761d06d6bSBaptiste Daroussin static int32_t ip; 23861d06d6bSBaptiste Daroussin struct dbm_res res = {-1, 0}; 23961d06d6bSBaptiste Daroussin 24061d06d6bSBaptiste Daroussin assert(arg_iter == ITER_NAME || arg_iter == ITER_DESC || 24161d06d6bSBaptiste Daroussin arg_iter == ITER_SECT); 24261d06d6bSBaptiste Daroussin 24361d06d6bSBaptiste Daroussin /* Initialize for a new iteration. */ 24461d06d6bSBaptiste Daroussin 24561d06d6bSBaptiste Daroussin if (arg_match != NULL) { 24661d06d6bSBaptiste Daroussin iteration = arg_iter; 24761d06d6bSBaptiste Daroussin match = arg_match; 24861d06d6bSBaptiste Daroussin switch (iteration) { 24961d06d6bSBaptiste Daroussin case ITER_NAME: 25061d06d6bSBaptiste Daroussin cp = dbm_get(pages[0].name); 25161d06d6bSBaptiste Daroussin break; 25261d06d6bSBaptiste Daroussin case ITER_SECT: 25361d06d6bSBaptiste Daroussin cp = dbm_get(pages[0].sect); 25461d06d6bSBaptiste Daroussin break; 25561d06d6bSBaptiste Daroussin case ITER_DESC: 25661d06d6bSBaptiste Daroussin cp = dbm_get(pages[0].desc); 25761d06d6bSBaptiste Daroussin break; 25861d06d6bSBaptiste Daroussin default: 25961d06d6bSBaptiste Daroussin abort(); 26061d06d6bSBaptiste Daroussin } 26161d06d6bSBaptiste Daroussin if (cp == NULL) { 26261d06d6bSBaptiste Daroussin iteration = ITER_NONE; 26361d06d6bSBaptiste Daroussin match = NULL; 26461d06d6bSBaptiste Daroussin cp = NULL; 26561d06d6bSBaptiste Daroussin ip = npages; 26661d06d6bSBaptiste Daroussin } else 26761d06d6bSBaptiste Daroussin ip = 0; 26861d06d6bSBaptiste Daroussin return res; 26961d06d6bSBaptiste Daroussin } 27061d06d6bSBaptiste Daroussin 27161d06d6bSBaptiste Daroussin /* Search for a name. */ 27261d06d6bSBaptiste Daroussin 27361d06d6bSBaptiste Daroussin while (ip < npages) { 27461d06d6bSBaptiste Daroussin if (iteration == ITER_NAME) 27561d06d6bSBaptiste Daroussin cp++; 27661d06d6bSBaptiste Daroussin if (dbm_match(match, cp)) 27761d06d6bSBaptiste Daroussin break; 27861d06d6bSBaptiste Daroussin cp = strchr(cp, '\0') + 1; 27961d06d6bSBaptiste Daroussin if (iteration == ITER_DESC) 28061d06d6bSBaptiste Daroussin ip++; 28161d06d6bSBaptiste Daroussin else if (*cp == '\0') { 28261d06d6bSBaptiste Daroussin cp++; 28361d06d6bSBaptiste Daroussin ip++; 28461d06d6bSBaptiste Daroussin } 28561d06d6bSBaptiste Daroussin } 28661d06d6bSBaptiste Daroussin 28761d06d6bSBaptiste Daroussin /* Reached the end without a match. */ 28861d06d6bSBaptiste Daroussin 28961d06d6bSBaptiste Daroussin if (ip == npages) { 29061d06d6bSBaptiste Daroussin iteration = ITER_NONE; 29161d06d6bSBaptiste Daroussin match = NULL; 29261d06d6bSBaptiste Daroussin cp = NULL; 29361d06d6bSBaptiste Daroussin return res; 29461d06d6bSBaptiste Daroussin } 29561d06d6bSBaptiste Daroussin 29661d06d6bSBaptiste Daroussin /* Found a match; save the quality for later retrieval. */ 29761d06d6bSBaptiste Daroussin 29861d06d6bSBaptiste Daroussin res.page = ip; 29961d06d6bSBaptiste Daroussin res.bits = iteration == ITER_NAME ? cp[-1] : 0; 30061d06d6bSBaptiste Daroussin 30161d06d6bSBaptiste Daroussin /* Skip the remaining names of this page. */ 30261d06d6bSBaptiste Daroussin 30361d06d6bSBaptiste Daroussin if (++ip < npages) { 30461d06d6bSBaptiste Daroussin do { 30561d06d6bSBaptiste Daroussin cp++; 30661d06d6bSBaptiste Daroussin } while (cp[-1] != '\0' || 30761d06d6bSBaptiste Daroussin (iteration != ITER_DESC && cp[-2] != '\0')); 30861d06d6bSBaptiste Daroussin } 30961d06d6bSBaptiste Daroussin return res; 31061d06d6bSBaptiste Daroussin } 31161d06d6bSBaptiste Daroussin 31261d06d6bSBaptiste Daroussin static struct dbm_res 31361d06d6bSBaptiste Daroussin page_byarch(const struct dbm_match *arg_match) 31461d06d6bSBaptiste Daroussin { 31561d06d6bSBaptiste Daroussin static const struct dbm_match *match; 31661d06d6bSBaptiste Daroussin struct dbm_res res = {-1, 0}; 31761d06d6bSBaptiste Daroussin static int32_t ip; 31861d06d6bSBaptiste Daroussin const char *cp; 31961d06d6bSBaptiste Daroussin 32061d06d6bSBaptiste Daroussin /* Initialize for a new iteration. */ 32161d06d6bSBaptiste Daroussin 32261d06d6bSBaptiste Daroussin if (arg_match != NULL) { 32361d06d6bSBaptiste Daroussin iteration = ITER_ARCH; 32461d06d6bSBaptiste Daroussin match = arg_match; 32561d06d6bSBaptiste Daroussin ip = 0; 32661d06d6bSBaptiste Daroussin return res; 32761d06d6bSBaptiste Daroussin } 32861d06d6bSBaptiste Daroussin 32961d06d6bSBaptiste Daroussin /* Search for an architecture. */ 33061d06d6bSBaptiste Daroussin 33161d06d6bSBaptiste Daroussin for ( ; ip < npages; ip++) 33261d06d6bSBaptiste Daroussin if (pages[ip].arch) 33361d06d6bSBaptiste Daroussin for (cp = dbm_get(pages[ip].arch); 33461d06d6bSBaptiste Daroussin *cp != '\0'; 33561d06d6bSBaptiste Daroussin cp = strchr(cp, '\0') + 1) 33661d06d6bSBaptiste Daroussin if (dbm_match(match, cp)) { 33761d06d6bSBaptiste Daroussin res.page = ip++; 33861d06d6bSBaptiste Daroussin return res; 33961d06d6bSBaptiste Daroussin } 34061d06d6bSBaptiste Daroussin 34161d06d6bSBaptiste Daroussin /* Reached the end without a match. */ 34261d06d6bSBaptiste Daroussin 34361d06d6bSBaptiste Daroussin iteration = ITER_NONE; 34461d06d6bSBaptiste Daroussin match = NULL; 34561d06d6bSBaptiste Daroussin return res; 34661d06d6bSBaptiste Daroussin } 34761d06d6bSBaptiste Daroussin 34861d06d6bSBaptiste Daroussin static struct dbm_res 34961d06d6bSBaptiste Daroussin page_bymacro(int32_t arg_im, const struct dbm_match *arg_match) 35061d06d6bSBaptiste Daroussin { 35161d06d6bSBaptiste Daroussin static const struct dbm_match *match; 35261d06d6bSBaptiste Daroussin static const int32_t *pp; 35361d06d6bSBaptiste Daroussin static const char *cp; 35461d06d6bSBaptiste Daroussin static int32_t im, iv; 35561d06d6bSBaptiste Daroussin struct dbm_res res = {-1, 0}; 35661d06d6bSBaptiste Daroussin 35761d06d6bSBaptiste Daroussin assert(im >= 0); 35861d06d6bSBaptiste Daroussin assert(im < MACRO_MAX); 35961d06d6bSBaptiste Daroussin 36061d06d6bSBaptiste Daroussin /* Initialize for a new iteration. */ 36161d06d6bSBaptiste Daroussin 36261d06d6bSBaptiste Daroussin if (arg_match != NULL) { 36361d06d6bSBaptiste Daroussin iteration = ITER_MACRO; 36461d06d6bSBaptiste Daroussin match = arg_match; 36561d06d6bSBaptiste Daroussin im = arg_im; 36661d06d6bSBaptiste Daroussin cp = nvals[im] ? dbm_get(macros[im]->value) : NULL; 36761d06d6bSBaptiste Daroussin pp = NULL; 36861d06d6bSBaptiste Daroussin iv = -1; 36961d06d6bSBaptiste Daroussin return res; 37061d06d6bSBaptiste Daroussin } 37161d06d6bSBaptiste Daroussin if (iteration != ITER_MACRO) 37261d06d6bSBaptiste Daroussin return res; 37361d06d6bSBaptiste Daroussin 37461d06d6bSBaptiste Daroussin /* Find the next matching macro value. */ 37561d06d6bSBaptiste Daroussin 37661d06d6bSBaptiste Daroussin while (pp == NULL || *pp == 0) { 37761d06d6bSBaptiste Daroussin if (++iv == nvals[im]) { 37861d06d6bSBaptiste Daroussin iteration = ITER_NONE; 37961d06d6bSBaptiste Daroussin return res; 38061d06d6bSBaptiste Daroussin } 38161d06d6bSBaptiste Daroussin if (iv) 38261d06d6bSBaptiste Daroussin cp = strchr(cp, '\0') + 1; 38361d06d6bSBaptiste Daroussin if (dbm_match(match, cp)) 38461d06d6bSBaptiste Daroussin pp = dbm_get(macros[im][iv].pages); 38561d06d6bSBaptiste Daroussin } 38661d06d6bSBaptiste Daroussin 38761d06d6bSBaptiste Daroussin /* Found a matching page. */ 38861d06d6bSBaptiste Daroussin 38961d06d6bSBaptiste Daroussin res.page = (struct page *)dbm_get(*pp++) - pages; 39061d06d6bSBaptiste Daroussin return res; 39161d06d6bSBaptiste Daroussin } 39261d06d6bSBaptiste Daroussin 39361d06d6bSBaptiste Daroussin 39461d06d6bSBaptiste Daroussin /*** functions for handling macros ************************************/ 39561d06d6bSBaptiste Daroussin 39661d06d6bSBaptiste Daroussin int32_t 39761d06d6bSBaptiste Daroussin dbm_macro_count(int32_t im) 39861d06d6bSBaptiste Daroussin { 39961d06d6bSBaptiste Daroussin assert(im >= 0); 40061d06d6bSBaptiste Daroussin assert(im < MACRO_MAX); 40161d06d6bSBaptiste Daroussin return nvals[im]; 40261d06d6bSBaptiste Daroussin } 40361d06d6bSBaptiste Daroussin 40461d06d6bSBaptiste Daroussin struct dbm_macro * 40561d06d6bSBaptiste Daroussin dbm_macro_get(int32_t im, int32_t iv) 40661d06d6bSBaptiste Daroussin { 40761d06d6bSBaptiste Daroussin static struct dbm_macro macro; 40861d06d6bSBaptiste Daroussin 40961d06d6bSBaptiste Daroussin assert(im >= 0); 41061d06d6bSBaptiste Daroussin assert(im < MACRO_MAX); 41161d06d6bSBaptiste Daroussin assert(iv >= 0); 41261d06d6bSBaptiste Daroussin assert(iv < nvals[im]); 41361d06d6bSBaptiste Daroussin macro.value = dbm_get(macros[im][iv].value); 41461d06d6bSBaptiste Daroussin macro.pp = dbm_get(macros[im][iv].pages); 41561d06d6bSBaptiste Daroussin return ¯o; 41661d06d6bSBaptiste Daroussin } 41761d06d6bSBaptiste Daroussin 41861d06d6bSBaptiste Daroussin /* 41961d06d6bSBaptiste Daroussin * Filtered iteration over macro entries. 42061d06d6bSBaptiste Daroussin */ 42161d06d6bSBaptiste Daroussin void 42261d06d6bSBaptiste Daroussin dbm_macro_bypage(int32_t im, int32_t ip) 42361d06d6bSBaptiste Daroussin { 42461d06d6bSBaptiste Daroussin assert(im >= 0); 42561d06d6bSBaptiste Daroussin assert(im < MACRO_MAX); 42661d06d6bSBaptiste Daroussin assert(ip != 0); 42761d06d6bSBaptiste Daroussin macro_bypage(im, ip); 42861d06d6bSBaptiste Daroussin } 42961d06d6bSBaptiste Daroussin 43061d06d6bSBaptiste Daroussin char * 43161d06d6bSBaptiste Daroussin dbm_macro_next(void) 43261d06d6bSBaptiste Daroussin { 43361d06d6bSBaptiste Daroussin return macro_bypage(MACRO_MAX, 0); 43461d06d6bSBaptiste Daroussin } 43561d06d6bSBaptiste Daroussin 43661d06d6bSBaptiste Daroussin static char * 43761d06d6bSBaptiste Daroussin macro_bypage(int32_t arg_im, int32_t arg_ip) 43861d06d6bSBaptiste Daroussin { 43961d06d6bSBaptiste Daroussin static const int32_t *pp; 44061d06d6bSBaptiste Daroussin static int32_t im, ip, iv; 44161d06d6bSBaptiste Daroussin 44261d06d6bSBaptiste Daroussin /* Initialize for a new iteration. */ 44361d06d6bSBaptiste Daroussin 44461d06d6bSBaptiste Daroussin if (arg_im < MACRO_MAX && arg_ip != 0) { 44561d06d6bSBaptiste Daroussin im = arg_im; 44661d06d6bSBaptiste Daroussin ip = arg_ip; 44761d06d6bSBaptiste Daroussin pp = dbm_get(macros[im]->pages); 44861d06d6bSBaptiste Daroussin iv = 0; 44961d06d6bSBaptiste Daroussin return NULL; 45061d06d6bSBaptiste Daroussin } 45161d06d6bSBaptiste Daroussin if (im >= MACRO_MAX) 45261d06d6bSBaptiste Daroussin return NULL; 45361d06d6bSBaptiste Daroussin 45461d06d6bSBaptiste Daroussin /* Search for the next value. */ 45561d06d6bSBaptiste Daroussin 45661d06d6bSBaptiste Daroussin while (iv < nvals[im]) { 45761d06d6bSBaptiste Daroussin if (*pp == ip) 45861d06d6bSBaptiste Daroussin break; 45961d06d6bSBaptiste Daroussin if (*pp == 0) 46061d06d6bSBaptiste Daroussin iv++; 46161d06d6bSBaptiste Daroussin pp++; 46261d06d6bSBaptiste Daroussin } 46361d06d6bSBaptiste Daroussin 46461d06d6bSBaptiste Daroussin /* Reached the end without a match. */ 46561d06d6bSBaptiste Daroussin 46661d06d6bSBaptiste Daroussin if (iv == nvals[im]) { 46761d06d6bSBaptiste Daroussin im = MACRO_MAX; 46861d06d6bSBaptiste Daroussin ip = 0; 46961d06d6bSBaptiste Daroussin pp = NULL; 47061d06d6bSBaptiste Daroussin return NULL; 47161d06d6bSBaptiste Daroussin } 47261d06d6bSBaptiste Daroussin 47361d06d6bSBaptiste Daroussin /* Found a match; skip the remaining pages of this entry. */ 47461d06d6bSBaptiste Daroussin 47561d06d6bSBaptiste Daroussin if (++iv < nvals[im]) 47661d06d6bSBaptiste Daroussin while (*pp++ != 0) 47761d06d6bSBaptiste Daroussin continue; 47861d06d6bSBaptiste Daroussin 47961d06d6bSBaptiste Daroussin return dbm_get(macros[im][iv - 1].value); 48061d06d6bSBaptiste Daroussin } 481