Commit d7dec968 d7dec96841e872ffa6924d6c5f93a1be473bf8ff by Sergey Poznyakoff

Fix MH sequence parser.

* mh/mh_msgset.c (parse_range): Fix resolving non-existing UIDs.
* mh/tests/mhseq.at: Add more test cases.
1 parent ae06384d
...@@ -98,7 +98,6 @@ mh_msgset_single_message (mu_msgset_t msgset) ...@@ -98,7 +98,6 @@ mh_msgset_single_message (mu_msgset_t msgset)
98 } 98 }
99 return r->msg_beg == r->msg_end; 99 return r->msg_beg == r->msg_end;
100 } 100 }
101
102 101
103 struct msgset_parser 102 struct msgset_parser
104 { 103 {
...@@ -466,22 +465,42 @@ parse_range (struct msgset_parser *parser) ...@@ -466,22 +465,42 @@ parse_range (struct msgset_parser *parser)
466 return 0; 465 return 0;
467 if (!validuid) 466 if (!validuid)
468 { 467 {
469 size_t total, lastuid; 468 if (parser->sign)
470 msgset_last (parser->msgset->mbox, &total);
471 mu_mailbox_translate (parser->msgset->mbox,
472 MU_MAILBOX_MSGNO_TO_UID,
473 total, &lastuid);
474 if (start > lastuid)
475 { 469 {
476 if (!parser->sign) 470 while (1)
477 emptyrange_abort (parser->argv[-1]); 471 {
478 start = total; 472 if (--start == 0)
473 emptyrange_abort (parser->argv[-1]);
474 if (mu_mailbox_translate (parser->msgset->mbox,
475 MU_MAILBOX_UID_TO_MSGNO,
476 start, &start) == 0)
477 break;
478 }
479 } 479 }
480 else 480 else
481 { 481 {
482 if (parser->sign) 482 size_t total, lastuid;
483
484 msgset_last (parser->msgset->mbox, &total);
485 mu_mailbox_translate (parser->msgset->mbox,
486 MU_MAILBOX_MSGNO_TO_UID,
487 total, &lastuid);
488 if (start > lastuid)
483 emptyrange_abort (parser->argv[-1]); 489 emptyrange_abort (parser->argv[-1]);
484 start = 1; 490 else
491 while (1)
492 {
493 if (start == lastuid)
494 {
495 start = total;
496 break;
497 }
498 ++start;
499 if (mu_mailbox_translate (parser->msgset->mbox,
500 MU_MAILBOX_UID_TO_MSGNO,
501 start, &start) == 0)
502 break;
503 }
485 } 504 }
486 } 505 }
487 add_messages (parser, start, parser->number, parser->sign); 506 add_messages (parser, start, parser->number, parser->sign);
...@@ -489,47 +508,92 @@ parse_range (struct msgset_parser *parser) ...@@ -489,47 +508,92 @@ parse_range (struct msgset_parser *parser)
489 } 508 }
490 else if (*parser->curp == '-') 509 else if (*parser->curp == '-')
491 { 510 {
492 size_t lastuid = 0;
493 int validuid = parser->validuid; 511 int validuid = parser->validuid;
494 int rc; 512 int rc;
495 513
496 parser->curp++; 514 parser->curp++;
497 if (parse_term (parser, 0) == PARSE_EOF) 515 if (parse_term (parser, 0) == PARSE_EOF)
498 return 0; 516 return 0;
499 if (!parser->validuid) 517
518 /* If any of UIDs does not exist, try to find the nearest
519 existing one: */
520 if (!validuid || !parser->validuid)
500 { 521 {
501 size_t total; 522 size_t lastuid, num, maxnum;
502 523
503 msgset_last (parser->msgset->mbox, &total); 524 /* Order the limits */
525 if (!parser->validuid)
526 maxnum = parser->number;
527 else
528 mu_mailbox_translate (parser->msgset->mbox,
529 MU_MAILBOX_MSGNO_TO_UID,
530 parser->number, &maxnum);
531 if (!validuid)
532 num = start;
533 else
534 mu_mailbox_translate (parser->msgset->mbox,
535 MU_MAILBOX_MSGNO_TO_UID,
536 start, &num);
537
538 if (num > maxnum)
539 {
540 int v;
541 size_t n;
542
543 n = parser->number;
544 v = parser->validuid;
545 parser->number = start;
546 parser->validuid = validuid;
547 start = n;
548 validuid = v;
549 }
550
551 /* Adjust upper bound */
552 msgset_last (parser->msgset->mbox, &num);
504 mu_mailbox_translate (parser->msgset->mbox, MU_MAILBOX_MSGNO_TO_UID, 553 mu_mailbox_translate (parser->msgset->mbox, MU_MAILBOX_MSGNO_TO_UID,
505 total, &lastuid); 554 num, &lastuid);
506 555
507 if (parser->number > lastuid) 556 if (!parser->validuid && parser->number > lastuid)
508 parser->number = total;
509 else if (!validuid)
510 emptyrange_abort (parser->argv[-1]);
511 }
512 if (!validuid)
513 {
514 if (!lastuid)
515 { 557 {
516 size_t total; 558 parser->number = num;
517 msgset_last (parser->msgset->mbox, &total); 559 parser->validuid = 1;
518 mu_mailbox_translate (parser->msgset->mbox,
519 MU_MAILBOX_MSGNO_TO_UID,
520 total, &lastuid);
521 } 560 }
522 if (start > lastuid && !parser->validuid) 561
523 emptyrange_abort (parser->argv[-1]); 562 /* Shift the bounds towards each other until they resolve to
524 start = 1; 563 existing UIDs or clash */
525 } 564 do
526 rc = mu_msgset_add_range (parser->msgset, start, parser->number, 565 {
527 MU_MSGSET_NUM); 566 if (!validuid)
528 if (rc) 567 {
529 { 568 ++start;
530 mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_add_range", NULL, rc); 569 if (start > lastuid)
531 exit (1); 570 emptyrange_abort (parser->argv[-1]);
571 rc = mu_mailbox_translate (parser->msgset->mbox,
572 MU_MAILBOX_UID_TO_MSGNO,
573 start, &start);
574 if (rc == 0)
575 validuid = 1;
576 }
577 if (!parser->validuid)
578 {
579 if (parser->number == 1)
580 emptyrange_abort (parser->argv[-1]);
581 --parser->number;
582 rc = mu_mailbox_translate (parser->msgset->mbox,
583 MU_MAILBOX_UID_TO_MSGNO,
584 parser->number, &num);
585 if (rc == 0)
586 {
587 lastuid = parser->number;
588 parser->number = num;
589 parser->validuid = 1;
590 }
591 }
592 }
593 while (!validuid || !parser->validuid);
532 } 594 }
595 mu_msgset_add_range (parser->msgset, start, parser->number,
596 MU_MSGSET_NUM);
533 } 597 }
534 else if (!parser->validuid) 598 else if (!parser->validuid)
535 { 599 {
......
...@@ -406,5 +406,119 @@ mhseq last:2 ...@@ -406,5 +406,119 @@ mhseq last:2
406 5 406 5
407 ]) 407 ])
408 408
409 MH_CHECK([mhseq: sparse increasing message range (left fixup in the middle)],
410 [mhseq34],[
411 MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox])
412 mv Mail/inbox/5 Mail/inbox/20
413 mv Mail/inbox/4 Mail/inbox/15
414 mv Mail/inbox/3 Mail/inbox/8
415 MUT_MBCHMOD(Mail/inbox, 700)
416 mhseq 5-15
417 ],
418 [0],
419 [8
420 15
421 ])
422
423 MH_CHECK([mhseq: sparse increasing message range (right fixup in the middle)],
424 [mhseq35],[
425 MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox])
426 mv Mail/inbox/5 Mail/inbox/20
427 mv Mail/inbox/4 Mail/inbox/15
428 mv Mail/inbox/3 Mail/inbox/8
429 MUT_MBCHMOD(Mail/inbox, 700)
430 mhseq 8-17
431 ],
432 [0],
433 [8
434 15
435 ])
436
437 MH_CHECK([mhseq: sparse increasing message range (both fixups in the middle)],
438 [mhseq36],[
439 MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox])
440 mv Mail/inbox/5 Mail/inbox/20
441 mv Mail/inbox/4 Mail/inbox/15
442 mv Mail/inbox/3 Mail/inbox/8
443 MUT_MBCHMOD(Mail/inbox, 700)
444 mhseq 5-17
445 ],
446 [0],
447 [8
448 15
449 ])
450
451 MH_CHECK([mhseq: sparse decreasing message range (left fixup in the middle)],
452 [mhseq37],[
453 MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox])
454 mv Mail/inbox/5 Mail/inbox/20
455 mv Mail/inbox/4 Mail/inbox/15
456 mv Mail/inbox/3 Mail/inbox/8
457 MUT_MBCHMOD(Mail/inbox, 700)
458 mhseq 15-5
459 ],
460 [0],
461 [8
462 15
463 ])
464
465 MH_CHECK([mhseq: sparse decreasing message range (right fixup in the middle)],
466 [mhseq38],[
467 MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox])
468 mv Mail/inbox/5 Mail/inbox/20
469 mv Mail/inbox/4 Mail/inbox/15
470 mv Mail/inbox/3 Mail/inbox/8
471 MUT_MBCHMOD(Mail/inbox, 700)
472 mhseq 17-8
473 ],
474 [0],
475 [8
476 15
477 ])
478
479 MH_CHECK([mhseq: sparse decreasing message range (both fixups in the middle)],
480 [mhseq39],[
481 MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox])
482 mv Mail/inbox/5 Mail/inbox/20
483 mv Mail/inbox/4 Mail/inbox/15
484 mv Mail/inbox/3 Mail/inbox/8
485 MUT_MBCHMOD(Mail/inbox, 700)
486 mhseq 17-5
487 ],
488 [0],
489 [8
490 15
491 ])
492
493 MH_CHECK([mhseq: sparse counted range (positive, fixup)],
494 [mhseq40],[
495 MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox])
496 mv Mail/inbox/5 Mail/inbox/20
497 mv Mail/inbox/4 Mail/inbox/15
498 mv Mail/inbox/3 Mail/inbox/8
499 MUT_MBCHMOD(Mail/inbox, 700)
500 mhseq 3:2
501 ],
502 [0],
503 [8
504 15
505 ])
506
507 MH_CHECK([mhseq: sparse counted range (negative, fixup)],
508 [mhseq41],[
509 MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox])
510 mv Mail/inbox/5 Mail/inbox/20
511 mv Mail/inbox/4 Mail/inbox/15
512 mv Mail/inbox/3 Mail/inbox/8
513 MUT_MBCHMOD(Mail/inbox, 700)
514 mhseq 17:-3
515 ],
516 [0],
517 [2
518 8
519 15
520 ])
521
522
409 m4_popdef([MH_KEYWORDS]) 523 m4_popdef([MH_KEYWORDS])
410 # End of mhseq.at 524 # End of mhseq.at
...\ No newline at end of file ...\ No newline at end of file
......