fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 410 lines 7.3 kB view raw
1/***************************************************************************** 2 * libini * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/libini/read.c * 7 * Created: 2001-08-24 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2001-2020 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 <stdio.h> 26#include <string.h> 27 28#include <libini/libini.h> 29#include <libini/scanner.h> 30 31 32extern int ini_eval (scanner_t *scn, ini_sct_t *sct, ini_val_t *val); 33 34static int parse_section (scanner_t *scn, ini_sct_t *sct, char *buf); 35 36 37static 38void parse_error (scanner_t *scn, const char *text, int src) 39{ 40 char c; 41 unsigned i; 42 const char *name; 43 44 if (scn->file != NULL) { 45 name = scn->file->name; 46 } 47 else { 48 name = NULL; 49 } 50 51 if (name == NULL) { 52 name = "<none>"; 53 } 54 55 fprintf (stderr, "%s:%lu: %s", 56 name, scn->line + 1, text 57 ); 58 59 if (src) { 60 fputs (": ", stderr); 61 62 for (i = 0; i < 64; i++) { 63 c = scn_get_chr (scn, i); 64 65 if (c == 0) { 66 fputs ("<eof>", stderr); 67 break; 68 } 69 70 if ((c == 0x0d) || (c == 0x0a)) { 71 fputs ("<nl>", stderr); 72 break; 73 } 74 75 fputc (c, stderr); 76 } 77 } 78 79 fputs ("\n", stderr); 80} 81 82static 83int skip_block (scanner_t *scn) 84{ 85 int c; 86 unsigned cnt; 87 88 cnt = 1; 89 90 while ((c = scn_get_chr (scn, 0)) != 0) { 91 scn_rmv_chr (scn, 1); 92 93 if (c == '{') { 94 cnt += 1; 95 } 96 else if (c == '}') { 97 cnt -= 1; 98 99 if (cnt == 0) { 100 return (0); 101 } 102 } 103 } 104 105 return (1); 106} 107 108static 109int parse_block (scanner_t *scn, ini_sct_t *sct, char *buf, int skip) 110{ 111 if (scn_match (scn, "{") == 0) { 112 return (1); 113 } 114 115 if (skip) { 116 return (skip_block (scn)); 117 } 118 119 if (parse_section (scn, sct, buf)) { 120 return (1); 121 } 122 123 if (scn_match (scn, "}") == 0) { 124 return (1); 125 } 126 127 return (0); 128} 129 130static 131int parse_assign_undef (scanner_t *scn, ini_sct_t *sct, ini_val_t *tmp, const char *name) 132{ 133 ini_val_t *val; 134 135 if (ini_eval (scn, sct, tmp)) { 136 return (1); 137 } 138 139 if (tmp->type == INI_VAL_NONE) { 140 return (1); 141 } 142 143 val = ini_get_val (sct, name, 0); 144 145 if (val != NULL) { 146 return (0); 147 } 148 149 val = ini_get_val (sct, name, 1); 150 151 if (val == NULL) { 152 return (1); 153 } 154 155 ini_val_copy (val, tmp); 156 157 return (0); 158} 159 160static 161int parse_if (scanner_t *scn, ini_sct_t *sct, char *buf) 162{ 163 int done, skip; 164 ini_val_t val; 165 166 ini_val_init (&val, NULL); 167 168 if (ini_eval (scn, sct, &val)) { 169 ini_val_free (&val); 170 return (1); 171 } 172 173 if ((val.type == INI_VAL_INT) && (val.val.u32 != 0)) { 174 skip = 0; 175 done = 1; 176 } 177 else if ((val.type == INI_VAL_STR) && (val.val.str[0] != 0)) { 178 skip = 0; 179 done = 1; 180 } 181 else { 182 skip = 1; 183 done = 0; 184 } 185 186 ini_val_free (&val); 187 188 if (parse_block (scn, sct, buf, skip)) { 189 return (1); 190 } 191 192 while (scn_match_ident (scn, "else")) { 193 if (scn_match_ident (scn, "if")) { 194 ini_val_init (&val, NULL); 195 196 if (ini_eval (scn, sct, &val)) { 197 ini_val_free (&val); 198 return (1); 199 } 200 201 skip = 1; 202 203 if (done == 0) { 204 if ((val.type == INI_VAL_INT) && (val.val.u32 != 0)) { 205 skip = 0; 206 done = 1; 207 } 208 else if ((val.type == INI_VAL_STR) && (val.val.str[0] != 0)) { 209 skip = 0; 210 done = 1; 211 } 212 } 213 214 ini_val_free (&val); 215 216 if (parse_block (scn, sct, buf, skip)) { 217 return (1); 218 } 219 } 220 else { 221 if (parse_block (scn, sct, buf, done)) { 222 return (1); 223 } 224 225 break; 226 } 227 } 228 229 return (0); 230} 231 232static 233int parse_include (scanner_t *scn, ini_sct_t *sct, char *buf, int rel) 234{ 235 int noerr; 236 237 noerr = (scn_match (scn, "?") != 0); 238 239 if (scn_match_string (scn, buf, 256) == 0) { 240 return (1); 241 } 242 243 if (scn_add_file (scn, buf, NULL, 1, rel)) { 244 if (noerr == 0) { 245 parse_error (scn, "can't open include file:", 0); 246 parse_error (scn, buf, 0); 247 return (1); 248 } 249 } 250 251 return (0); 252} 253 254static 255int parse_section (scanner_t *scn, ini_sct_t *sct, char *buf) 256{ 257 int r; 258 ini_sct_t *sub; 259 ini_val_t *val; 260 261 while (1) { 262 if (scn_match_name (scn, buf, 256) == 0) { 263 return (0); 264 } 265 266 if (strcmp (buf, "section") == 0) { 267 if (scn_match_name (scn, buf, 256) == 0) { 268 return (1); 269 } 270 } 271 272 if (scn_match (scn, "{")) { 273 sub = ini_get_sct (sct, buf, 1); 274 275 if (sub == NULL) { 276 return (1); 277 } 278 279 if (parse_section (scn, sub, buf)) { 280 return (1); 281 } 282 283 if (scn_match (scn, "}") == 0) { 284 return (1); 285 } 286 } 287 else if (scn_match (scn, "?=")) { 288 ini_val_t tmp; 289 290 ini_val_init (&tmp, NULL); 291 292 r = parse_assign_undef (scn, sct, &tmp, buf); 293 294 ini_val_free (&tmp); 295 296 if (r) { 297 return (1); 298 } 299 } 300 else if (scn_match (scn, "=")) { 301 val = ini_get_val (sct, buf, 1); 302 303 if (val == NULL) { 304 return (1); 305 } 306 307 if (ini_eval (scn, sct, val)) { 308 return (1); 309 } 310 311 if (val->type == INI_VAL_NONE) { 312 return (1); 313 } 314 } 315 else if (strcmp (buf, "if") == 0) { 316 if (parse_if (scn, sct, buf)) { 317 return (1); 318 } 319 } 320 else if (strcmp (buf, "include") == 0) { 321 if (parse_include (scn, sct, buf, 0)) { 322 return (1); 323 } 324 } 325 else if (strcmp (buf, "rinclude") == 0) { 326 if (parse_include (scn, sct, buf, 1)) { 327 return (1); 328 } 329 } 330 else { 331 return (1); 332 } 333 334 scn_match (scn, ";"); 335 } 336 337 return (1); 338} 339 340int ini_read_str (ini_sct_t *sct, const char *str) 341{ 342 scanner_t scn; 343 char buf[256]; 344 345 scn_init (&scn); 346 scn_set_str (&scn, str); 347 348 if (parse_section (&scn, sct, buf)) { 349 parse_error (&scn, "parse error before", 1); 350 scn_free (&scn); 351 return (1); 352 } 353 354 if (scn_get_chr (&scn, 0) != 0) { 355 parse_error (&scn, "parse error before", 1); 356 scn_free (&scn); 357 return (1); 358 } 359 360 scn_free (&scn); 361 362 return (0); 363} 364 365int ini_read_fp (ini_sct_t *sct, FILE *fp, const char *fname) 366{ 367 scanner_t scn; 368 char buf[256]; 369 370 scn_init (&scn); 371 372 if (scn_add_file (&scn, fname, fp, 0, 0)) { 373 ini_sct_del (sct); 374 return (1); 375 } 376 377 if (parse_section (&scn, sct, buf)) { 378 parse_error (&scn, "parse error before", 1); 379 scn_free (&scn); 380 return (1); 381 } 382 383 if (scn_get_chr (&scn, 0) != 0) { 384 parse_error (&scn, "parse error before", 1); 385 scn_free (&scn); 386 return (1); 387 } 388 389 scn_free (&scn); 390 391 return (0); 392} 393 394int ini_read (ini_sct_t *sct, const char *fname) 395{ 396 int r; 397 FILE *fp; 398 399 fp = fopen (fname, "rb"); 400 401 if (fp == NULL) { 402 return (1); 403 } 404 405 r = ini_read_fp (sct, fp, fname); 406 407 fclose (fp); 408 409 return (r); 410}