1#!/bin/sh 2# 3# Copyright (C) 2014 Masatake YAMATO 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 2 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18set -e 19 20# Avoid trouble with weird bytes on non-C locales 21export LC_ALL=C 22 23READTAGS=${1:-./readtags} 24UNITS=${2:-./Units} 25shift 2 26 27MINITRIP= 28while [ $# -gt 0 ]; do 29 case $1 in 30 --minitrip) 31 MINITRIP=minitrip 32 ;; 33 *) 34 echo "Unexpected argument: $1" 1>&2 35 exit 1 36 ;; 37 esac 38 shift 39done 40 41s=0 42 43if ! [ -f "${READTAGS}" ]; then 44 echo "No such file: ${READTAGS}" 1>&2 45 exit 1 46fi 47 48if ! [ -x "${READTAGS}" ]; then 49 echo "Not an executable: ${READTAGS}" 1>&2 50 exit 1 51fi 52 53if ! [ -x "${UNITS}" ]; then 54 echo "Not such directory: ${UNITS}" 1>&2 55 exit 1 56fi 57 58 59# Expand CTags escape sequences (and keep the original, too) 60# See docs/format.rst 61expandEscapeSequences() 62{ 63 sed -e ' 64# early out if there is no escape sequence (common case) 65/\\/!b 66 67# loop until we handled all occurrences of \. 68# as it is not possible to do all replacements at once and we need not to 69# ever use the result of an replacement to perform another one, use two 70# reserved placeholders. 71:again 72 s/\\/__BACKSLASH__/ 73 s/__BACKSLASH__\\/__LITBACKSLASH__/; t again 74 s/__BACKSLASH__t/ /; t again 75 s/__BACKSLASH__r/'"$(printf '\r')"'/; t again 76 s/__BACKSLASH__n/\ 77/; t again 78 s/__BACKSLASH__a//; t again 79 s/__BACKSLASH__b/'"$(printf '\b')"'/; t again 80 s/__BACKSLASH__v//; t again 81 s/__BACKSLASH__f//; t again 82 s/__BACKSLASH__x01//; t again 83 s/__BACKSLASH__x02//; t again 84 s/__BACKSLASH__x03//; t again 85 s/__BACKSLASH__x04//; t again 86 s/__BACKSLASH__x05//; t again 87 s/__BACKSLASH__x06//; t again 88 s/__BACKSLASH__x07//; t again 89 s/__BACKSLASH__x08//; t again 90 s/__BACKSLASH__x09/ /; t again 91 s/__BACKSLASH__x0[aA]/\ 92/; t again 93 s/__BACKSLASH__x0[bB]//; t again 94 s/__BACKSLASH__x0[cC]//; t again 95 s/__BACKSLASH__x0[dD]/'"$(printf '\r')"'/; t again 96 s/__BACKSLASH__x0[eE]//; t again 97 s/__BACKSLASH__x0[fF]//; t again 98 s/__BACKSLASH__x10//; t again 99 s/__BACKSLASH__x11//; t again 100 s/__BACKSLASH__x12//; t again 101 s/__BACKSLASH__x13//; t again 102 s/__BACKSLASH__x14//; t again 103 s/__BACKSLASH__x15//; t again 104 s/__BACKSLASH__x16//; t again 105 s/__BACKSLASH__x17//; t again 106 s/__BACKSLASH__x18//; t again 107 s/__BACKSLASH__x19//; t again 108 s/__BACKSLASH__x1[aA]//; t again 109 s/__BACKSLASH__x1[bB]//; t again 110 s/__BACKSLASH__x1[cC]//; t again 111 s/__BACKSLASH__x1[dD]//; t again 112 s/__BACKSLASH__x1[eE]//; t again 113 s/__BACKSLASH__x1[fF]//; t again 114 s/__BACKSLASH__x21/!/; t again 115 s/__BACKSLASH__x20/ /; t again 116 s/__BACKSLASH__x7[fF]//; t again 117 /\\/b again 118 119# replace lonely "\"es 120s/__BACKSLASH__/\\/g 121# replace literal "\"es ("\\" from the input) 122s/__LITBACKSLASH__/\\/g 123' 124} 125 126# disable path expansion, because we don't need it and it's applied on the 127# result of the commands used to loop on, and we don't want that. 128set -f 129# remove space from IFS as it's valid in tag names 130OLD_IFS="$IFS" 131IFS=' 132' 133 134ntagfiles=0 135ntrips=0 136tagfiles=$(find "$UNITS" -name expected.tags) 137for tags in $tagfiles; do 138 ntagfiles=$(expr $ntagfiles + 1) 139 dir=$(dirname "$tags") 140 if [ -n "$MINITRIP" -a ! -e "$dir/$MINITRIP" ]; then 141 continue 142 fi 143 ntrips=$(expr $ntrips + 1) 144 145 tagnames=$(sed -e 's/^\([^ ]*\) .*/\1/' "$tags") 146 for name in $tagnames; do 147 # Yes, there is a reason for this craziness. We need to properly 148 # handle embedded newlines (expanded from "\n"), including trailing 149 # ones the shell would strip automatically. To work around this, we 150 # add a dummy character at the end to inhibit stripping, and then 151 # remove it, plus the extra newline, using variable substitutions. 152 # Note: we use "printf '%s\n'" instead of "echo" because Dash's "echo" 153 # unconditionally expands some sequences, like "\t" and alike. 154 t="$(printf '%s\n' "$name" | expandEscapeSequences; printf _)" 155 t="${t% 156_}" 157 if [ 1 -gt $("${READTAGS}" -t "$tags" - "$t" | wc -l) ]; then 158 printf 'FAILED: "%s" -t "%s" - "%s"\n' "${READTAGS}" "$tags" "$t" 159 printf ' The raw tag name was "%s"\n' "$name" 160 s=1 161 fi 162 done 163done 164 165IFS="$OLD_IFS" 166 167note= 168if [ -n "$MINITRIP" ]; then 169 note="[$MINITRIP]" 170fi 171printf "%s/%s%s...%d\n" "$ntrips" "$ntagfiles" "$note" "$s" 172 173exit $s 174