fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 375 lines 5.9 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/lib/text.c * 7 * Created: 2021-11-30 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2021-2023 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include <config.h> 24 25#include <stdlib.h> 26#include <string.h> 27 28#include "text.h" 29 30 31void txt_init (pce_text_t *ctx, FILE *fp) 32{ 33 memset (ctx, 0, sizeof (pce_text_t)); 34 35 ctx->fp = fp; 36} 37 38void txt_free (pce_text_t *ctx) 39{ 40} 41 42int txt_putc (pce_text_t *ctx, int c) 43{ 44 return (fputc (c, ctx->fp)); 45} 46 47int txt_error (pce_text_t *ctx, const char *str) 48{ 49 int c; 50 51 if (str == NULL) { 52 str = "unknown"; 53 } 54 55 c = txt_getc (ctx, 0); 56 57 fprintf (stderr, "pce-text:%u: error (%s), next = %02X\n", 58 ctx->line + 1, str, c 59 ); 60 61 return (1); 62} 63 64int txt_getc (pce_text_t *ctx, unsigned idx) 65{ 66 int c; 67 unsigned i; 68 69 if (idx >= sizeof (ctx->buf)) { 70 return (EOF); 71 } 72 73 for (i = ctx->cnt; i <= idx; i++) { 74 if ((c = fgetc (ctx->fp)) == EOF) { 75 return (EOF); 76 } 77 78 ctx->buf[ctx->cnt++] = c; 79 } 80 81 return (ctx->buf[idx]); 82} 83 84void txt_skip (pce_text_t *ctx, unsigned cnt) 85{ 86 unsigned i; 87 88 if (cnt >= ctx->cnt) { 89 cnt -= ctx->cnt; 90 ctx->cnt = 0; 91 92 while (cnt-- > 0) { 93 if (fgetc (ctx->fp) == EOF) { 94 return; 95 } 96 } 97 } 98 else { 99 for (i = cnt; i < ctx->cnt; i++) { 100 ctx->buf[i - cnt] = ctx->buf[i]; 101 } 102 103 ctx->cnt -= cnt; 104 } 105} 106 107int txt_match_space (pce_text_t *ctx) 108{ 109 int c, cr, ok, line; 110 111 line = 0; 112 ok = 0; 113 cr = 0; 114 115 while (1) { 116 if ((c = txt_getc (ctx, 0)) == EOF) { 117 return (ok); 118 } 119 120 if (c == 0x0d) { 121 line = 0; 122 ctx->line += 1; 123 } 124 else if (c == 0x0a) { 125 line = 0; 126 127 if (cr == 0) { 128 ctx->line += 1; 129 } 130 } 131 else if (line) { 132 ; 133 } 134 else if ((c == '\t') || (c == ' ')) { 135 ; 136 } 137 else if ((c == '#') || (c == ';')) { 138 line = 1; 139 } 140 else { 141 return (ok); 142 } 143 144 cr = (c == 0x0d); 145 ok = 1; 146 147 txt_skip (ctx, 1); 148 } 149} 150 151int txt_match_eol (pce_text_t *ctx) 152{ 153 int c, line; 154 155 line = 0; 156 157 while (1) { 158 if ((c = txt_getc (ctx, 0)) == EOF) { 159 return (1); 160 } 161 162 if (c == 0x0d) { 163 ctx->line += 1; 164 txt_skip (ctx, (txt_getc (ctx, 1) == 0x0a) ? 2 : 1); 165 166 return (1); 167 } 168 else if (c == 0x0a) { 169 ctx->line += 1; 170 txt_skip (ctx, 1); 171 172 return (1); 173 } 174 else if (line) { 175 ; 176 } 177 else if ((c == '\t') || (c == ' ')) { 178 ; 179 } 180 else if ((c == '#') || (c == ';')) { 181 line = 1; 182 } 183 else { 184 return (0); 185 } 186 187 txt_skip (ctx, 1); 188 } 189} 190 191int txt_match (pce_text_t *ctx, const char *str, int skip) 192{ 193 int c; 194 unsigned i, n; 195 196 txt_match_space (ctx); 197 198 n = 0; 199 200 while (str[n] != 0) { 201 if (n >= ctx->cnt) { 202 if ((c = fgetc (ctx->fp)) == EOF) { 203 return (0); 204 } 205 206 ctx->buf[ctx->cnt++] = c; 207 } 208 209 if (ctx->buf[n] != str[n]) { 210 return (0); 211 } 212 213 n += 1; 214 } 215 216 if (skip) { 217 for (i = n; i < ctx->cnt; i++) { 218 ctx->buf[i - n] = ctx->buf[i]; 219 } 220 221 ctx->cnt -= n; 222 } 223 224 return (1); 225} 226 227int txt_match_string (pce_text_t *ctx, char *str, unsigned max) 228{ 229 int c, esc, quote; 230 unsigned idx; 231 232 txt_match_space (ctx); 233 234 if ((c = txt_getc (ctx, 0)) != '"') { 235 return (0); 236 } 237 238 quote = '"'; 239 240 txt_skip (ctx, 1); 241 242 idx = 0; 243 esc = 0; 244 245 while (idx < max) { 246 if ((c = txt_getc (ctx, 0)) == EOF) { 247 return (0); 248 } 249 250 txt_skip (ctx, 1); 251 252 if (esc) { 253 idx -= 1; 254 255 if (c == 'n') { 256 c = 0x0a; 257 } 258 else if (c == 'r') { 259 c = 0x0d; 260 } 261 else if (c == 't') { 262 c = 0x09; 263 } 264 else if (c == '\\') { 265 c = '\\'; 266 } 267 else if (c == '"') { 268 c = '"'; 269 } 270 else { 271 idx += 1; 272 } 273 274 esc = 0; 275 } 276 else if (c == '\\') { 277 esc = 1; 278 } 279 else if (c == quote) { 280 break; 281 } 282 283 str[idx++] = c; 284 } 285 286 if (idx >= max) { 287 return (0); 288 } 289 290 str[idx] = 0; 291 292 return (1); 293} 294 295int txt_match_hex_digit (pce_text_t *ctx, unsigned *val) 296{ 297 int c; 298 299 c = txt_getc (ctx, 0); 300 301 if ((c >= '0') && (c <= '9')) { 302 *val = c - '0'; 303 } 304 else if ((c >= 'A') && (c <= 'F')) { 305 *val = c - 'A' + 10; 306 } 307 else if ((c >= 'a') && (c <= 'f')) { 308 *val = c - 'a' + 10; 309 } 310 else { 311 return (0); 312 } 313 314 txt_skip (ctx, 1); 315 316 return (1); 317} 318 319int txt_match_uint (pce_text_t *ctx, unsigned base, unsigned long *val) 320{ 321 unsigned i, dig; 322 int c, s, ok; 323 324 txt_match_space (ctx); 325 326 i = 0; 327 s = 0; 328 ok = 0; 329 330 c = txt_getc (ctx, i); 331 332 if ((c == '-') || (c == '+')) { 333 s = (c == '-'); 334 335 c = txt_getc (ctx, ++i); 336 } 337 338 *val = 0; 339 340 while (1) { 341 if ((c >= '0') && (c <= '9')) { 342 dig = c - '0'; 343 } 344 else if ((c >= 'a') && (c <= 'z')) { 345 dig = c - 'a' + 10; 346 } 347 else if ((c >= 'A') && (c <= 'Z')) { 348 dig = c - 'A' + 10; 349 } 350 else { 351 break; 352 } 353 354 if (dig >= base) { 355 return (0); 356 } 357 358 *val = base * *val + dig; 359 ok = 1; 360 361 c = txt_getc (ctx, ++i); 362 } 363 364 if (ok == 0) { 365 return (0); 366 } 367 368 if (s) { 369 *val = ~*val + 1; 370 } 371 372 txt_skip (ctx, i); 373 374 return (1); 375}