#!/usr/bin/env bash # A script for counting the number of lines of code in this repository into # buckets based on a series of regexps. set -e set -o pipefail if [[ $(uname -s) == "Darwin" ]]; then FIND=gfind else FIND=find fi if ! [ -d code ]; then echo "Error: this script expects to be run from the root of HACL*, e.g. ./tools/$0" exit 1 fi declare -A buckets function mywc () { wc -l $1 | sed 's/^ *\([0-9]*\).*/\1/' } function matches () { if echo $1 | grep -q $2; then # Uncomment the line below to debug and to check that things are bucketized # properly. # echo $1 is a match for $2 local v=${buckets[$2]} local l=$(mywc $1) buckets[$2]=$(($v + $l)) else false fi } total=0 # Regexps are matched in order. To improve on this script, just insert a fresh # regexps in the right position, then insert a label at the exact same position. # It is a good idea to compare the output of the script before and after. declare -a regexps regexps=( ".vaf$" "^./obj" "^./specs/Spec." "^./vale/specs/crypto/Vale.AES" "^./specs/" "^./vale/specs/interop" "^./vale/specs/\(defs\|hardware\|math\)" "^./vale/specs/crypto" "^./vale/code" "^./code/experimental" "^./code" "^./lib" "^./secure_api/merkle_tree" "^./providers/test" "^./providers/evercrypt") declare -a labels labels=( \ "Vale source files (.vaf)" "Generated F* files (from .vaf files)" "Reference (HACL) spec files" "Vale GCM spec (a reference spec used for AEAD)" "Auxiliary spec files (lemmas, derived specs, tests)" "Vale interop" "Vale hardware specs" "Other Vale crypto specs (proven equivalent to reference spec)" "Vale code" "Experimental Low* code" "Low* algorithms" "Low* support libraries" "Merkle Tree" "EverCrypt tests" "EverCrypt") # Everything is zero by default. for r in ${regexps[@]}; do buckets[$r]=0 done # Note: explicitly avoiding AES_s.fst since the spec already exists in specs/ for file in $($FIND . -\( -iname '*.fst' -or -iname '*.fsti' -or -iname '*.vaf' -\) \ -and -not -iname '*.types.vaf' -and -not -ipath './code/old/*' \ -and -not -ipath './specs/old/*' -and -not -ipath './doc/*' \ -and -not -iname 'Vale.AES.AES_s.fst'); do total=$(($total + $(mywc $file))) found=false for r in ${regexps[@]}; do if matches $file $r; then found=true break fi done if ! $found; then echo $file was not bucketized but still counts towards the total fi done for r in ${!regexps[@]}; do echo -e "${labels[$r]}: ${buckets[${regexps[r]}]}" done echo "Total: $total"