From 5ebc9f2a5ad207b8621e1aacf7bb23d32a7ce772 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 9 Jul 2017 18:32:20 -0400 Subject: librexgettext: Make the tests pass --- src/lib/librexgettext | 84 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/src/lib/librexgettext b/src/lib/librexgettext index cc18999..27a701d 100755 --- a/src/lib/librexgettext +++ b/src/lib/librexgettext @@ -40,7 +40,7 @@ fi errusage() { if [[ $# -gt 0 ]]; then fmt="$(gettext "$1")"; shift - printf "${0##*/}: $fmt\n" "$@" + printf "${0##*/}: $fmt\n" "$@" >&2 fi usage >&2 } @@ -76,6 +76,7 @@ xgettext-sh() { } xgettext-flag() { + local file="$1" { # Stage 1: Generate # @@ -95,9 +96,10 @@ xgettext-flag() { declare -i i for (( i=1; empties < 3; i++ )); do local out - out="$(xgettext-sh --keyword="flag:$i,\"$i\"" "$@")" + out="$(xgettext-sh --keyword="flag:$i,\"$i\"" -- "$file")" if [[ -n $out ]]; then printf -- '%s\n' "$out" + empties=0 else empties+=1 fi @@ -130,36 +132,77 @@ xgettext-flag() { # # We do this by simply sorting them by the location # that they appear in the file. Then, when we see the - # argument number go back down to 1, we know that a - # new invocation has started! - IFS=$'\n' - local locations=($( + # argument number go back down, we know that a new + # invocation has started! + local locations=() + readarray -t locations < <( local i for i in "${!msgs[@]}"; do + local lines=() + readarray -t lines < <(printf '%s' "${msgs[$i]}") + declare -i arg row - local lines=(${msgs[$i]}) arg=${lines[0]#'#. '} row=${lines[1]##*:} - printf '%d.%d %d\n' "$row" "$arg" "$i" - done | sort -n - )) + + printf '%d %d %d\n' "$row" "$arg" "$i" + done | sort -k 1n -k 2n + ) # Stage 4: Output # # Now, we prune out the arguments that aren't # localizable. Also, remove the "#." comment lines. # As explained above (in stage 3), when we see $arg go - # to 1, that's the beginning of a new invocation. + # down, that's the beginning of a new invocation. local expectflag=true + local prev_arg=0 + local prev_row=0 # for better error messages only; no real logic local location for location in "${locations[@]}"; do - IFS=' .' + IFS=' ' local row arg i read -r row arg i <<<"$location" local msg="${msgs[$i]#*$'\n'}" - # Now we operate based on $row, $arg, and $msg - if [[ $arg == 1 ]]; then - expectflag=true + + # See if we need to fiddle with $expectflag + # (and do some sanity checking). + if [[ $arg != "$((prev_arg+1))" ]]; then + if ! $expectflag; then + local pos + if [[ $row != "$prev_row" ]]; then + printf -v pos "%s:%d-%d" "$file" "$prev_row" "$row" + else + printf -v pos "%s:%d" "$file" "$prev_row" + fi + >&2 printf "%s: $(gettext "flag error: Missing expected flag meaning at argument %d")\n" \ + "$pos" "$((prev_arg+1))" + exit 1 # $EXIT_FAILURE + elif [[ $arg == "$((prev_arg+2))" ]]; then + # skipped flag argument + expectflag=false + elif [[ "$arg" == 1 ]]; then + # started new invocation + expectflag=true + elif [[ $arg == 2 ]]; then + # started new invocation and skipped flag argument + expectflag=false + else + local pos + if [[ $row != "$prev_row" ]]; then + printf -v pos "%s:%d-%d" "$file" "$prev_row" "$row" + else + printf -v pos "%s:%d" "$file" "$prev_row" + fi + >&2 printf "%s: $(gettext "flag error: Jumped from argument %d to %d")\n" \ + "$pos" "$prev_arg" "$arg" + exit 1 # $EXIT_FAILURE + fi fi + prev_arg=$arg + prev_row=$row + + # Now we operate based on $row, $arg, $msg, + # and $expectflag. if $expectflag; then IFS=$'\n' local lines=(${msg}) @@ -177,6 +220,12 @@ xgettext-flag() { expectflag=true fi done + if ! $expectflag; then + >&2 printf "%s:%d: $(gettext "flag error: Missing expected flag meaning at argument %d")\n" \ + "$file" "$prev_row" \ + "$((prev_arg+1))" + exit 1 # $EXIT_FAILURE + fi } } @@ -186,6 +235,7 @@ whitespace-collapse() { } main() { + set -euE -o pipefail local simple=() local prose=() local files=() @@ -223,7 +273,9 @@ main() { { xgettext-sh "${simple[@]}" -- "${files[@]}" xgettext-sh "${prose[@]}" -- "${files[@]}" | whitespace-collapse - xgettext-flag -- "${files[@]}" + for file in "${files[@]}"; do + xgettext-flag "$file" + done } | sed '/^\#, sh-format/d' | msguniq -Fi --to-code=UTF-8 } -- cgit v1.2.2