eqn.c (6d38604fc532a3fc060788e3ce40464b46047eaf) | eqn.c (c1c95add8c80843ba15d784f95c361d795b1f593) |
---|---|
1/* $Id: eqn.c,v 1.84 2020/01/08 12:16:24 schwarze Exp $ */ | 1/* $Id: eqn.c,v 1.86 2023/04/28 19:11:03 schwarze Exp $ */ |
2/* | 2/* |
3 * Copyright (c) 2014, 2015, 2017, 2018, 2020, 2022 4 * Ingo Schwarze <schwarze@openbsd.org> |
|
3 * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> | 5 * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> |
4 * Copyright (c) 2014,2015,2017,2018,2020 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 --- 337 unchanged lines hidden (view full) --- 350 return &ep->defs[i]; 351 352 return NULL; 353} 354 355/* 356 * Parse a token from the input text. The modes are: 357 * MODE_QUOTED: Use *ep->start as the delimiter; the token ends | 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR --- 337 unchanged lines hidden (view full) --- 351 return &ep->defs[i]; 352 353 return NULL; 354} 355 356/* 357 * Parse a token from the input text. The modes are: 358 * MODE_QUOTED: Use *ep->start as the delimiter; the token ends |
358 * before its next occurence. Do not interpret the token in any | 359 * before its next occurrence. Do not interpret the token in any |
359 * way and return EQN_TOK_QUOTED. All other modes behave like 360 * MODE_QUOTED when *ep->start is '"'. 361 * MODE_NOSUB: If *ep->start is a curly brace, the token ends after it; 362 * otherwise, it ends before the next whitespace or brace. 363 * Do not interpret the token and return EQN_TOK__MAX. 364 * MODE_SUB: Like MODE_NOSUB, but try to interpret the token as an 365 * alias created with define. If it is an alias, replace it with 366 * its string value and reparse. 367 * MODE_TOK: Like MODE_SUB, but also check the token against the list 368 * of tokens, and if there is a match, return that token. Otherwise, 369 * if the token matches a symbol, return EQN_TOK_SYM; if it matches 370 * a function name, EQN_TOK_FUNC, or else EQN_TOK__MAX. Except for 371 * a token match, *ep->start is set to an allocated string that the 372 * caller is expected to free. 373 * All modes skip whitespace following the end of the token. 374 */ 375static enum eqn_tok 376eqn_next(struct eqn_node *ep, enum parse_mode mode) 377{ | 360 * way and return EQN_TOK_QUOTED. All other modes behave like 361 * MODE_QUOTED when *ep->start is '"'. 362 * MODE_NOSUB: If *ep->start is a curly brace, the token ends after it; 363 * otherwise, it ends before the next whitespace or brace. 364 * Do not interpret the token and return EQN_TOK__MAX. 365 * MODE_SUB: Like MODE_NOSUB, but try to interpret the token as an 366 * alias created with define. If it is an alias, replace it with 367 * its string value and reparse. 368 * MODE_TOK: Like MODE_SUB, but also check the token against the list 369 * of tokens, and if there is a match, return that token. Otherwise, 370 * if the token matches a symbol, return EQN_TOK_SYM; if it matches 371 * a function name, EQN_TOK_FUNC, or else EQN_TOK__MAX. Except for 372 * a token match, *ep->start is set to an allocated string that the 373 * caller is expected to free. 374 * All modes skip whitespace following the end of the token. 375 */ 376static enum eqn_tok 377eqn_next(struct eqn_node *ep, enum parse_mode mode) 378{ |
378 static int last_len, lim; 379 | |
380 struct eqn_def *def; 381 size_t start; | 379 struct eqn_def *def; 380 size_t start; |
382 int diff, i, quoted; | 381 int diff, i, newlen, quoted; |
383 enum eqn_tok tok; 384 385 /* 386 * Reset the recursion counter after advancing | 382 enum eqn_tok tok; 383 384 /* 385 * Reset the recursion counter after advancing |
387 * beyond the end of the previous substitution. | 386 * beyond the end of the rightmost substitution. |
388 */ | 387 */ |
389 if (ep->end - ep->data >= last_len) 390 lim = 0; | 388 if (ep->end - ep->data >= ep->sublen) 389 ep->subcnt = 0; |
391 392 ep->start = ep->end; 393 quoted = mode == MODE_QUOTED; 394 for (;;) { 395 switch (*ep->start) { 396 case '\0': 397 ep->toksz = 0; 398 return EQN_TOK_EOF; --- 30 unchanged lines hidden (view full) --- 429 while (*ep->end != '\0' && strchr(" \t^~", *ep->end) != NULL) 430 ep->end++; 431 if (quoted) /* Cannot return, may have to strndup. */ 432 break; 433 if (mode == MODE_NOSUB) 434 return EQN_TOK__MAX; 435 if ((def = eqn_def_find(ep)) == NULL) 436 break; | 390 391 ep->start = ep->end; 392 quoted = mode == MODE_QUOTED; 393 for (;;) { 394 switch (*ep->start) { 395 case '\0': 396 ep->toksz = 0; 397 return EQN_TOK_EOF; --- 30 unchanged lines hidden (view full) --- 428 while (*ep->end != '\0' && strchr(" \t^~", *ep->end) != NULL) 429 ep->end++; 430 if (quoted) /* Cannot return, may have to strndup. */ 431 break; 432 if (mode == MODE_NOSUB) 433 return EQN_TOK__MAX; 434 if ((def = eqn_def_find(ep)) == NULL) 435 break; |
437 if (++lim > EQN_NEST_MAX) { | 436 if (++ep->subcnt > EQN_NEST_MAX) { |
438 mandoc_msg(MANDOCERR_ROFFLOOP, 439 ep->node->line, ep->node->pos, NULL); | 437 mandoc_msg(MANDOCERR_ROFFLOOP, 438 ep->node->line, ep->node->pos, NULL); |
440 return EQN_TOK_EOF; | 439 break; |
441 } 442 443 /* Replace a defined name with its string value. */ 444 if ((diff = def->valsz - ep->toksz) > 0) { 445 start = ep->start - ep->data; 446 ep->sz += diff; 447 ep->data = mandoc_realloc(ep->data, ep->sz + 1); 448 ep->start = ep->data + start; | 440 } 441 442 /* Replace a defined name with its string value. */ 443 if ((diff = def->valsz - ep->toksz) > 0) { 444 start = ep->start - ep->data; 445 ep->sz += diff; 446 ep->data = mandoc_realloc(ep->data, ep->sz + 1); 447 ep->start = ep->data + start; |
448 ep->sublen += diff; |
|
449 } 450 if (diff) 451 memmove(ep->start + def->valsz, ep->start + ep->toksz, 452 strlen(ep->start + ep->toksz) + 1); 453 memcpy(ep->start, def->val, def->valsz); | 449 } 450 if (diff) 451 memmove(ep->start + def->valsz, ep->start + ep->toksz, 452 strlen(ep->start + ep->toksz) + 1); 453 memcpy(ep->start, def->val, def->valsz); |
454 last_len = ep->start - ep->data + def->valsz; | 454 newlen = ep->start - ep->data + def->valsz; 455 if (ep->sublen < newlen) 456 ep->sublen = newlen; |
455 } 456 if (mode != MODE_TOK) 457 return quoted ? EQN_TOK_QUOTED : EQN_TOK__MAX; 458 if (quoted) { 459 ep->start = mandoc_strndup(ep->start, ep->toksz); 460 return EQN_TOK_QUOTED; 461 } 462 for (tok = 0; tok < EQN_TOK__MAX; tok++) --- 210 unchanged lines hidden (view full) --- 673 * Empty equation. 674 * Do not add it to the high-level syntax tree. 675 */ 676 677 if (ep->data == NULL) 678 return; 679 680 ep->start = ep->end = ep->data; | 457 } 458 if (mode != MODE_TOK) 459 return quoted ? EQN_TOK_QUOTED : EQN_TOK__MAX; 460 if (quoted) { 461 ep->start = mandoc_strndup(ep->start, ep->toksz); 462 return EQN_TOK_QUOTED; 463 } 464 for (tok = 0; tok < EQN_TOK__MAX; tok++) --- 210 unchanged lines hidden (view full) --- 675 * Empty equation. 676 * Do not add it to the high-level syntax tree. 677 */ 678 679 if (ep->data == NULL) 680 return; 681 682 ep->start = ep->end = ep->data; |
683 ep->sublen = 0; 684 ep->subcnt = 0; |
|
681 682next_tok: 683 tok = eqn_next(ep, MODE_TOK); 684 switch (tok) { 685 case EQN_TOK_UNDEF: 686 eqn_undef(ep); 687 break; 688 case EQN_TOK_NDEFINE: --- 444 unchanged lines hidden --- | 685 686next_tok: 687 tok = eqn_next(ep, MODE_TOK); 688 switch (tok) { 689 case EQN_TOK_UNDEF: 690 eqn_undef(ep); 691 break; 692 case EQN_TOK_NDEFINE: --- 444 unchanged lines hidden --- |