1 /* $OpenBSD: tbl.c,v 1.22 2017/06/08 18:11:15 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4 * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 #include <sys/types.h> 19 20 #include <assert.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <time.h> 25 26 #include "mandoc.h" 27 #include "mandoc_aux.h" 28 #include "libmandoc.h" 29 #include "libroff.h" 30 31 32 enum rofferr 33 tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos) 34 { 35 const char *cp; 36 int active; 37 38 /* 39 * In the options section, proceed to the layout section 40 * after a semicolon, or right away if there is no semicolon. 41 * Ignore semicolons in arguments. 42 */ 43 44 if (tbl->part == TBL_PART_OPTS) { 45 tbl->part = TBL_PART_LAYOUT; 46 active = 1; 47 for (cp = p + pos; *cp != '\0'; cp++) { 48 switch (*cp) { 49 case '(': 50 active = 0; 51 continue; 52 case ')': 53 active = 1; 54 continue; 55 case ';': 56 if (active) 57 break; 58 continue; 59 default: 60 continue; 61 } 62 break; 63 } 64 if (*cp == ';') { 65 tbl_option(tbl, ln, p, &pos); 66 if (p[pos] == '\0') 67 return ROFF_IGN; 68 } 69 } 70 71 /* Process the other section types. */ 72 73 switch (tbl->part) { 74 case TBL_PART_LAYOUT: 75 tbl_layout(tbl, ln, p, pos); 76 return ROFF_IGN; 77 case TBL_PART_CDATA: 78 return tbl_cdata(tbl, ln, p, pos) ? ROFF_TBL : ROFF_IGN; 79 default: 80 break; 81 } 82 83 tbl_data(tbl, ln, p, pos); 84 return ROFF_TBL; 85 } 86 87 struct tbl_node * 88 tbl_alloc(int pos, int line, struct mparse *parse) 89 { 90 struct tbl_node *tbl; 91 92 tbl = mandoc_calloc(1, sizeof(*tbl)); 93 tbl->line = line; 94 tbl->pos = pos; 95 tbl->parse = parse; 96 tbl->part = TBL_PART_OPTS; 97 tbl->opts.tab = '\t'; 98 tbl->opts.decimal = '.'; 99 return tbl; 100 } 101 102 void 103 tbl_free(struct tbl_node *tbl) 104 { 105 struct tbl_row *rp; 106 struct tbl_cell *cp; 107 struct tbl_span *sp; 108 struct tbl_dat *dp; 109 110 while ((rp = tbl->first_row) != NULL) { 111 tbl->first_row = rp->next; 112 while (rp->first != NULL) { 113 cp = rp->first; 114 rp->first = cp->next; 115 free(cp->wstr); 116 free(cp); 117 } 118 free(rp); 119 } 120 121 while ((sp = tbl->first_span) != NULL) { 122 tbl->first_span = sp->next; 123 while (sp->first != NULL) { 124 dp = sp->first; 125 sp->first = dp->next; 126 free(dp->string); 127 free(dp); 128 } 129 free(sp); 130 } 131 132 free(tbl); 133 } 134 135 void 136 tbl_restart(int line, int pos, struct tbl_node *tbl) 137 { 138 if (tbl->part == TBL_PART_CDATA) 139 mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->parse, 140 line, pos, "T&"); 141 142 tbl->part = TBL_PART_LAYOUT; 143 tbl->line = line; 144 tbl->pos = pos; 145 } 146 147 const struct tbl_span * 148 tbl_span(struct tbl_node *tbl) 149 { 150 struct tbl_span *span; 151 152 assert(tbl); 153 span = tbl->current_span ? tbl->current_span->next 154 : tbl->first_span; 155 if (span) 156 tbl->current_span = span; 157 return span; 158 } 159 160 int 161 tbl_end(struct tbl_node **tblp) 162 { 163 struct tbl_node *tbl; 164 struct tbl_span *sp; 165 166 tbl = *tblp; 167 *tblp = NULL; 168 169 if (tbl->part == TBL_PART_CDATA) 170 mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->parse, 171 tbl->line, tbl->pos, "TE"); 172 173 sp = tbl->first_span; 174 while (sp != NULL && sp->first == NULL) 175 sp = sp->next; 176 if (sp == NULL) { 177 mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->parse, 178 tbl->line, tbl->pos, NULL); 179 return 0; 180 } 181 return 1; 182 } 183