#! /bin/bash # Last edited on 2012-12-08 21:40:44 by stolfilocal PROG_NAME=${0##*/} PROG_DESC="create a cross-reference of identifiers matching a given regexp" PROG_HELP=( "${PROG_NAME} '{REGEXP}' {FILENAME}.. " ) PROG_INFO=( "\nNAME" "\n ${PROG_NAME} - ${PROG_DESC}." "\n" "\nSYNOPSIS" "\n ${PROG_HELP[@]}" "\n" "\nDESCRIPTION" "\n Reads the C source files from the {FILENAME} list. Prints all" \ "\n occurrences of the given {REGEXP}, marking each as 'D' for" \ "\n definition, 'U' for use, sorted." "\nSEE ALSO" "\n " "\nAUTHOR" "\n Created 2006-04-29 by Jorge Stolfi, Unicamp" ) # Internal options # ---------------------------------------------------------------------- # COMMAND LINE PARSING # Parse command line switches: fasulla= while [[ ( $# -ge 1 ) && ( "/$1" =~ /-.* ) ]]; do if [[ ( $# -ge 1 ) && ( "/$1" == "/-fasulla" ) ]]; then fasulla=1; shift; shift; else echo "unknown option $1" 1>&2 ; echo -e "usage:\n ${PROG_HELP[@]}" 1>&2 ; exit 1 fi done # Get basic geometry parameters if [[ $# -ge 1 ]]; then regexp="$1"; shift; files=( "$@" ); shift $#; else echo 'wrong number of arguments "'"$1"'" ...' 1>&2 ; echo -e "usage:\n ${PROG_HELP[@]}" 1>&2 ; exit 1 fi if [[ $# -ne 0 ]]; then echo 'wrong number of arguments "'"$1"'" ...' 1>&2 ; echo -e "usage:\n ${PROG_HELP[@]}" 1>&2 ; exit 1 fi # END COMMAND LINE PARSING # ---------------------------------------------------------------------- # Prefix for temporary file names tmp="/tmp/$$" # Collects uses and definitions: egrep -n -e "${regexp}" "${files[@]}" \ | gawk \ -v re="${regexp}" \ ' BEGIN{ } // { lin=$0; if (match(lin, /^[^ ]*[.][ch][:][0-9]+[:]/)) { loc = substr(lin, 1, RLENGTH); txt = substr(lin, 1+RLENGTH); # See if it looks like a definition def = match(txt, /^([\#]define|[a-zA-Z])/); while (match(txt, re)) { occ = substr(txt, RSTART, RLENGTH); if (occ == "") { data_error("empty match"); } printf "%s%s:%s\n", loc, (def ? "D" : "U"), occ; txt = substr(txt, RSTART+RLENGTH); } } else { data_error("bad format"); } next; } function data_error(msg) { printf "%s:%d:%s\n", FILENAME, FNR, $0 > "/dev/stderr"; printf "%s:%d: ** %s\n", FILENAME, FNR, msg > "/dev/stderr"; exit 1; } ' \ > ${tmp}.occs # Sorted printout cat ${tmp}.occs \ | sort -t':' -b +3 -4 +2 -3 +0 -1 +1 -2 \ | gawk \ ' BEGIN { oitm = ""; } // { lin = $0; itm = lin; gsub(/^[^:]*[:][^:]*[:][UD][:]/, "", itm); if (itm != oitm) { printf "\n %s\n\n", itm; oitm = itm; } gsub(/[:]D[:]/, ": D ", lin); gsub(/[:]U[:]/, ": U ", lin); print lin; } ' /bin/rm -f ${tmp}.occs