1*60395358Sschwarze /* $OpenBSD: tbl.c,v 1.28 2025/01/05 18:03:51 schwarze Exp $ */ 2393cb51eSschwarze /* 32791bd1cSschwarze * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4bdf8ed0fSschwarze * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org> 5393cb51eSschwarze * 6393cb51eSschwarze * Permission to use, copy, modify, and distribute this software for any 7393cb51eSschwarze * purpose with or without fee is hereby granted, provided that the above 8393cb51eSschwarze * copyright notice and this permission notice appear in all copies. 9393cb51eSschwarze * 10393cb51eSschwarze * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11393cb51eSschwarze * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12393cb51eSschwarze * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13393cb51eSschwarze * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14393cb51eSschwarze * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15393cb51eSschwarze * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16393cb51eSschwarze * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17393cb51eSschwarze */ 1830997c59Sschwarze #include <sys/types.h> 1930997c59Sschwarze 20393cb51eSschwarze #include <assert.h> 21393cb51eSschwarze #include <stdio.h> 22393cb51eSschwarze #include <stdlib.h> 23393cb51eSschwarze #include <string.h> 242791bd1cSschwarze #include <time.h> 25393cb51eSschwarze 264f4f7972Sschwarze #include "mandoc_aux.h" 27fae2491eSschwarze #include "mandoc.h" 28fae2491eSschwarze #include "tbl.h" 292791bd1cSschwarze #include "libmandoc.h" 30fb382a01Sschwarze #include "tbl_parse.h" 31fb382a01Sschwarze #include "tbl_int.h" 32393cb51eSschwarze 3349aff9f8Sschwarze 34d93f8561Sschwarze void 3539aede77Sschwarze tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos) 36393cb51eSschwarze { 372791bd1cSschwarze const char *cp; 38bdf8ed0fSschwarze int active; 39393cb51eSschwarze 402791bd1cSschwarze /* 41bdf8ed0fSschwarze * In the options section, proceed to the layout section 42bdf8ed0fSschwarze * after a semicolon, or right away if there is no semicolon. 43bdf8ed0fSschwarze * Ignore semicolons in arguments. 442791bd1cSschwarze */ 45393cb51eSschwarze 46bdf8ed0fSschwarze if (tbl->part == TBL_PART_OPTS) { 47393cb51eSschwarze tbl->part = TBL_PART_LAYOUT; 48bdf8ed0fSschwarze active = 1; 4939aede77Sschwarze for (cp = p + pos; *cp != '\0'; cp++) { 50bdf8ed0fSschwarze switch (*cp) { 51bdf8ed0fSschwarze case '(': 52bdf8ed0fSschwarze active = 0; 53bdf8ed0fSschwarze continue; 54bdf8ed0fSschwarze case ')': 55bdf8ed0fSschwarze active = 1; 56bdf8ed0fSschwarze continue; 57bdf8ed0fSschwarze case ';': 58bdf8ed0fSschwarze if (active) 59bdf8ed0fSschwarze break; 60bdf8ed0fSschwarze continue; 61bdf8ed0fSschwarze default: 62bdf8ed0fSschwarze continue; 63bdf8ed0fSschwarze } 64bdf8ed0fSschwarze break; 65bdf8ed0fSschwarze } 66bdf8ed0fSschwarze if (*cp == ';') { 6739aede77Sschwarze tbl_option(tbl, ln, p, &pos); 6839aede77Sschwarze if (p[pos] == '\0') 69d93f8561Sschwarze return; 70bdf8ed0fSschwarze } 71bdf8ed0fSschwarze } 72393cb51eSschwarze 73bdf8ed0fSschwarze /* Process the other section types. */ 742791bd1cSschwarze 75393cb51eSschwarze switch (tbl->part) { 7649aff9f8Sschwarze case TBL_PART_LAYOUT: 7739aede77Sschwarze tbl_layout(tbl, ln, p, pos); 78d93f8561Sschwarze break; 7949aff9f8Sschwarze case TBL_PART_CDATA: 80d93f8561Sschwarze tbl_cdata(tbl, ln, p, pos); 81d93f8561Sschwarze break; 82393cb51eSschwarze default: 83d93f8561Sschwarze tbl_data(tbl, ln, p, pos); 84393cb51eSschwarze break; 85393cb51eSschwarze } 86393cb51eSschwarze } 87393cb51eSschwarze 882791bd1cSschwarze struct tbl_node * 8991305757Sschwarze tbl_alloc(int pos, int line, struct tbl_node *last_tbl) 90393cb51eSschwarze { 91e263f8eaSschwarze struct tbl_node *tbl; 92393cb51eSschwarze 9321da0636Sschwarze tbl = mandoc_calloc(1, sizeof(*tbl)); 94fb382a01Sschwarze if (last_tbl != NULL) 95fb382a01Sschwarze last_tbl->next = tbl; 96e263f8eaSschwarze tbl->line = line; 97e263f8eaSschwarze tbl->pos = pos; 98e263f8eaSschwarze tbl->part = TBL_PART_OPTS; 99e263f8eaSschwarze tbl->opts.tab = '\t'; 100e263f8eaSschwarze tbl->opts.decimal = '.'; 101526e306bSschwarze return tbl; 102393cb51eSschwarze } 103393cb51eSschwarze 1042791bd1cSschwarze void 105e263f8eaSschwarze tbl_free(struct tbl_node *tbl) 106393cb51eSschwarze { 107fb382a01Sschwarze struct tbl_node *old_tbl; 1082791bd1cSschwarze struct tbl_row *rp; 109393cb51eSschwarze struct tbl_cell *cp; 1102791bd1cSschwarze struct tbl_span *sp; 1112791bd1cSschwarze struct tbl_dat *dp; 112393cb51eSschwarze 113fb382a01Sschwarze while (tbl != NULL) { 11421da0636Sschwarze while ((rp = tbl->first_row) != NULL) { 115e263f8eaSschwarze tbl->first_row = rp->next; 11621da0636Sschwarze while (rp->first != NULL) { 1172791bd1cSschwarze cp = rp->first; 1182791bd1cSschwarze rp->first = cp->next; 1192791bd1cSschwarze free(cp); 1202791bd1cSschwarze } 1212791bd1cSschwarze free(rp); 122393cb51eSschwarze } 12321da0636Sschwarze while ((sp = tbl->first_span) != NULL) { 124e263f8eaSschwarze tbl->first_span = sp->next; 12521da0636Sschwarze while (sp->first != NULL) { 1262791bd1cSschwarze dp = sp->first; 1272791bd1cSschwarze sp->first = dp->next; 1282791bd1cSschwarze free(dp->string); 1292791bd1cSschwarze free(dp); 1302791bd1cSschwarze } 1312791bd1cSschwarze free(sp); 132393cb51eSschwarze } 133fb382a01Sschwarze old_tbl = tbl; 134fb382a01Sschwarze tbl = tbl->next; 135fb382a01Sschwarze free(old_tbl); 136fb382a01Sschwarze } 137393cb51eSschwarze } 138393cb51eSschwarze 1392791bd1cSschwarze void 1402791bd1cSschwarze tbl_restart(int line, int pos, struct tbl_node *tbl) 1412791bd1cSschwarze { 14292ff8da6Sschwarze if (tbl->part == TBL_PART_CDATA) 143a5a5f808Sschwarze mandoc_msg(MANDOCERR_TBLDATA_BLK, line, pos, "T&"); 144393cb51eSschwarze 1452791bd1cSschwarze tbl->part = TBL_PART_LAYOUT; 1462791bd1cSschwarze tbl->line = line; 1472791bd1cSschwarze tbl->pos = pos; 1482791bd1cSschwarze } 1492791bd1cSschwarze 150fb382a01Sschwarze struct tbl_span * 1517374e4feSschwarze tbl_span(struct tbl_node *tbl) 152393cb51eSschwarze { 1537374e4feSschwarze struct tbl_span *span; 154393cb51eSschwarze 1557374e4feSschwarze span = tbl->current_span ? tbl->current_span->next 1567374e4feSschwarze : tbl->first_span; 157fb382a01Sschwarze if (span != NULL) 1587374e4feSschwarze tbl->current_span = span; 159526e306bSschwarze return span; 160393cb51eSschwarze } 161393cb51eSschwarze 16292ff8da6Sschwarze int 163fb382a01Sschwarze tbl_end(struct tbl_node *tbl, int still_open) 164393cb51eSschwarze { 165fd9b947eSschwarze struct tbl_span *sp; 166f8618d99Sschwarze 167fb382a01Sschwarze if (still_open) 168a5a5f808Sschwarze mandoc_msg(MANDOCERR_BLK_NOEND, tbl->line, tbl->pos, "TS"); 169fb382a01Sschwarze else if (tbl->part == TBL_PART_CDATA) 170a5a5f808Sschwarze mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->line, tbl->pos, "TE"); 17192ff8da6Sschwarze 172fd9b947eSschwarze sp = tbl->first_span; 173fd9b947eSschwarze while (sp != NULL && sp->first == NULL) 174fd9b947eSschwarze sp = sp->next; 17592ff8da6Sschwarze if (sp == NULL) { 176a5a5f808Sschwarze mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->line, tbl->pos, NULL); 177526e306bSschwarze return 0; 17892ff8da6Sschwarze } 179526e306bSschwarze return 1; 180393cb51eSschwarze } 181