comparison tools/gfxconv.c @ 1889:ac9784afae27

Improve option argument parsing.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 25 Jun 2018 17:10:24 +0300
parents b97f273a9d54
children ee95059b4c18
comparison
equal deleted inserted replaced
1888:b97f273a9d54 1889:ac9784afae27
126 { 17, 'F', "formats", "List supported input/output formats", OPT_NONE }, 126 { 17, 'F', "formats", "List supported input/output formats", OPT_NONE },
127 { 8, 'q', "sequential", "Output sequential files (image output only)", OPT_NONE }, 127 { 8, 'q', "sequential", "Output sequential files (image output only)", OPT_NONE },
128 { 6, 'c', "colormap", "Color mappings (see below for information)", OPT_ARGREQ }, 128 { 6, 'c', "colormap", "Color mappings (see below for information)", OPT_ARGREQ },
129 { 7, 'n', "numitems", "How many 'items' to output (default: all)", OPT_ARGREQ }, 129 { 7, 'n', "numitems", "How many 'items' to output (default: all)", OPT_ARGREQ },
130 { 11, 'w', "width", "Item width (number of items per row, min 1)", OPT_ARGREQ }, 130 { 11, 'w', "width", "Item width (number of items per row, min 1)", OPT_ARGREQ },
131 { 9, 'S', "scale", "Scale output image by <n> or <x>:<y> integer factor(s). " 131 { 9, 'S', "scale", "Scale output image by <n>, <x>:<y>, <x>:<y>*<n> integer factor(s). "
132 "-S <n> scales both height and width by <n>.", OPT_ARGREQ }, 132 "-S <n> scales both height and width by <n>. -S <x>:<y>*<n> scales "
133 "width by X*n and height Y*n.", OPT_ARGREQ },
133 { 12, 'P', "paletted", "Use indexed/paletted output IF possible.", OPT_NONE }, 134 { 12, 'P', "paletted", "Use indexed/paletted output IF possible.", OPT_NONE },
134 { 13, 'N', "nplanes", "# of bitplanes (some output formats)", OPT_ARGREQ }, 135 { 13, 'N', "nplanes", "# of bitplanes (some output formats)", OPT_ARGREQ },
135 { 18, 'B', "bpp", "Bits per pixel (some output formats)", OPT_ARGREQ }, 136 { 18, 'B', "bpp", "Bits per pixel (some output formats)", OPT_ARGREQ },
136 { 14, 'I', "interleave", "Interleaved/planar output (some output formats)", OPT_NONE }, 137 { 14, 'I', "interleave", "Interleaved/planar output (some output formats)", OPT_NONE },
137 { 16, 'R', "remap", "Remap output image colors (-R <(#RRGGBB|index):index>[,<..>][+remove] | -R @map.txt[+remove])", OPT_ARGREQ }, 138 { 16, 'R', "remap", "Remap output image colors (-R <(#RRGGBB|index):index>[,<..>][+remove] | -R @map.txt[+remove])", OPT_ARGREQ },
557 558
558 return TRUE; 559 return TRUE;
559 } 560 }
560 561
561 562
562 BOOL dmParseIntValWithSep(char **arg, int *value, char *end, const char sep) 563 BOOL dmParseIntValWithSep(char **arg, unsigned int *value, char *last, const char sep)
563 { 564 {
564 unsigned int val; 565 char *ptr = *arg, *end, *start;
565 char *ptr = *arg, *ptr2;
566 BOOL ret;
567 566
568 // Skip any whitespace at start 567 // Skip any whitespace at start
569 while (*ptr != 0 && isspace(*ptr)) 568 while (*ptr != 0 && isspace(*ptr))
570 ptr++; 569 ptr++;
571 570
572 // Find end of non-whitespace 571 start = ptr;
573 while (*ptr != 0 && (isxdigit(*ptr) || *ptr == 'x' || *ptr == '$') && *ptr != sep) 572
573 // Find next not-xdigit/separator
574 while (*ptr != 0 &&
575 (isxdigit(*ptr) || *ptr == 'x' || *ptr == '$') &&
576 *ptr != sep)
574 ptr++; 577 ptr++;
575 578
576 ptr2 = ptr; 579 end = ptr;
577 580
578 // Skip whitespace again 581 // Skip whitespace again
579 while (*ptr != 0 && isspace(*ptr)) 582 while (*ptr != 0 && isspace(*ptr))
580 ptr++; 583 ptr++;
581 584
582 *end = *ptr; 585 // Return last character in "last"
583 *ptr2 = 0; 586 *last = *ptr;
584 if (*end != 0) 587
588 // Set end to NUL
589 *end = 0;
590
591 // And if last character is not NUL, move ptr
592 if (*last != 0)
585 ptr++; 593 ptr++;
586 594
587 ret = dmGetIntVal(*arg, &val);
588 *arg = ptr; 595 *arg = ptr;
589 *value = val; 596
590 return ret; 597 return dmGetIntVal(start, value);
591 } 598 }
592 599
593 600
594 BOOL argHandleOpt(const int optN, char *optArg, char *currArg) 601 BOOL argHandleOpt(const int optN, char *optArg, char *currArg)
595 { 602 {
596 int tmpInt; 603 unsigned int tmpUInt;
597 char *tmpStr; 604 char *tmpStr;
598 605
599 switch (optN) 606 switch (optN)
600 { 607 {
601 case 0: 608 case 0:
675 dmPrint(1, "\n"); 682 dmPrint(1, "\n");
676 } 683 }
677 break; 684 break;
678 685
679 case 7: 686 case 7:
680 if (sscanf(optArg, "%d", &optItemCount) != 1) 687 if (!dmGetIntVal(optArg, &tmpUInt) ||
681 { 688 tmpUInt < 1)
682 dmErrorMsg("Invalid count value argument '%s'.\n", optArg); 689 {
690 dmErrorMsg("Invalid count value argument '%s' [1 .. MAXINT]\n",
691 optArg);
683 return FALSE; 692 return FALSE;
684 } 693 }
694 optItemCount = tmpUInt;
685 break; 695 break;
686 696
687 case 8: 697 case 8:
688 optSequential = TRUE; 698 optSequential = TRUE;
689 break; 699 break;
690 700
691 case 9: 701 case 9:
692 { 702 {
693 BOOL error = FALSE; 703 BOOL error = FALSE;
704 unsigned int tmpUInt2;
694 char *tmpStr = dm_strdup(optArg), 705 char *tmpStr = dm_strdup(optArg),
695 *tmpOpt = tmpStr, sep; 706 *tmpOpt = tmpStr, sep;
696 707
697 if (dmParseIntValWithSep(&tmpOpt, &tmpInt, &sep, ':')) 708 if (dmParseIntValWithSep(&tmpOpt, &tmpUInt, &sep, ':'))
698 { 709 {
699 if (sep == ':' && 710 if (sep == ':' &&
700 dmParseIntValWithSep(&tmpOpt, &optSpec.scaleY, &sep, '*')) 711 dmParseIntValWithSep(&tmpOpt, &tmpUInt2, &sep, '*'))
701 { 712 {
702 optSpec.scaleX = tmpInt; 713 optSpec.scaleX = tmpUInt;
714 optSpec.scaleY = tmpUInt2;
715
703 if (sep == '*' && 716 if (sep == '*' &&
704 dmParseIntValWithSep(&tmpOpt, &tmpInt, &sep, 0)) 717 dmParseIntValWithSep(&tmpOpt, &tmpUInt, &sep, 0))
705 { 718 {
706 optSpec.scaleX *= tmpInt; 719 optSpec.scaleX *= tmpUInt;
707 optSpec.scaleY *= tmpInt; 720 optSpec.scaleY *= tmpUInt;
708 } 721 }
709
710 error = (sep != 0); 722 error = (sep != 0);
711 } 723 }
712 else 724 else
713 error = TRUE; 725 error = TRUE;
714 } 726 }
725 return FALSE; 737 return FALSE;
726 } 738 }
727 739
728 if (optSpec.scaleX < 1 || optSpec.scaleX > 50) 740 if (optSpec.scaleX < 1 || optSpec.scaleX > 50)
729 { 741 {
730 dmErrorMsg("Invalid X scale value '%d'.\n", optSpec.scaleX); 742 dmErrorMsg("Invalid X scale value %d.\n", optSpec.scaleX);
731 return FALSE; 743 return FALSE;
732 } 744 }
733 if (optSpec.scaleY < 1 || optSpec.scaleY > 50) 745 if (optSpec.scaleY < 1 || optSpec.scaleY > 50)
734 { 746 {
735 dmErrorMsg("Invalid Y scale value '%d'.\n", optSpec.scaleY); 747 dmErrorMsg("Invalid Y scale value %d.\n", optSpec.scaleY);
736 return FALSE; 748 return FALSE;
737 } 749 }
738 } 750 }
739 break; 751 break;
740 752
741 case 11: 753 case 11:
742 if (sscanf(optArg, "%d", &optPlanedWidth) != 1) 754 if (!dmGetIntVal(optArg, &tmpUInt) ||
743 { 755 tmpUInt < 1 || tmpUInt > 512)
744 dmErrorMsg("Invalid planed width value argument '%s'.\n", 756 {
757 dmErrorMsg("Invalid planed width value '%s' [1 .. 512]\n",
745 optArg); 758 optArg);
746 return FALSE; 759 return FALSE;
747 } 760 }
748 if (optPlanedWidth < 1 || optPlanedWidth > 512) 761 optPlanedWidth = tmpUInt;
749 {
750 dmErrorMsg("Invalid planed width value '%d' [1..512].\n",
751 optPlanedWidth);
752 return FALSE;
753 }
754 break; 762 break;
755 763
756 case 12: 764 case 12:
757 optSpec.paletted = TRUE; 765 optSpec.paletted = TRUE;
758 break; 766 break;
759 767
760 case 13: 768 case 13:
761 if (sscanf(optArg, "%d", &tmpInt) != 1 || 769 if (!dmGetIntVal(optArg, &tmpUInt) ||
762 tmpInt < 1 || tmpInt > 8) 770 tmpUInt < 1 || tmpUInt > 8)
763 { 771 {
764 dmErrorMsg("Invalid number of bitplanes value '%s' [1..8].\n", 772 dmErrorMsg("Invalid number of bitplanes value '%s' [1 .. 8]\n",
765 optArg); 773 optArg);
766 return FALSE; 774 return FALSE;
767 } 775 }
768 optSpec.nplanes = tmpInt; 776 optSpec.nplanes = tmpUInt;
769 break; 777 break;
770 778
771 case 18: 779 case 18:
772 if (sscanf(optArg, "%d", &tmpInt) != 1 || 780 if (!dmGetIntVal(optArg, &tmpUInt) ||
773 tmpInt < 1 || tmpInt > 32) 781 tmpUInt < 1 || tmpUInt > 32)
774 { 782 {
775 dmErrorMsg("Invalid number of bits per pixel value '%s' [1..32].\n", 783 dmErrorMsg("Invalid number of bits per pixel value '%s' [1 .. 32]\n",
776 optArg); 784 optArg);
777 return FALSE; 785 return FALSE;
778 } 786 }
779 optSpec.nplanes = tmpInt; 787 optSpec.nplanes = tmpUInt;
780 break; 788 break;
781 789
782 case 14: 790 case 14:
783 optSpec.planar = TRUE; 791 optSpec.planar = TRUE;
784 break; 792 break;