blob: 6bef76fe6c2f3964c5ad3f359edadde7f99bd92c [file] [log] [blame]
Jimmy Brissonc7e28f52021-01-21 16:23:21 -06001#
2# Copyright (c) 2021 Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#!/usr/bin/env bash
7set -euo pipefail
8
9# Overview
10# ========
11#
12# This script generates source lines of code as a tab separated values (TSV)
13# file and a stacked bar chart. It uses `tokei` for gathering the data, and
14# `gnuplot` for generating the plot. The data is available on stderr and the
15# plot will be put in stdout.
16#
17# This script generates information about the directory that it's run in,
18# aggregated by subdirectory.
19# It is recommended that you run it from within the TF-A root directory for
20# best results.
21
22# Variables
23# =========
24
25# convert newlines to tabs
26n2t="tr \n \t"
27
28# We will build the final data file incrementally throughout the script. We need
29# A place to store this data, temporarily, so mktemp fills the role.
30data=$(mktemp XXXXXX-sloc.tsv)
31
32# Top level TF-A directories that we consider by themselves.
33toplevel=$(find -mindepth 1 -maxdepth 1 -type d -and ! -name ".*" | sed "s|./||g")
34
35# Second level TF-A directories that we consider separately.
36secondlevel=$(find drivers plat -mindepth 1 -maxdepth 1 -type d || true)
37
38# We want to be sure that we always put the data in the same order, with the
39# same keys in the resulting TSV file. To ensure this, we keep a json-encoded
40# array of the categories we would like to show in the graph.
41# This was generated by taking the output of `tokei --output json | jq keys`
42# and trimming out things that we don't really need like "Svg"
43categories='["AssemblyGAS", "C", "CHeader", "DeviceTree", "Makefile", "Python", "ReStructuredText"]'
44
45# Data File Generation
46# ====================
47#
48# Below we generate the data file used for the graph. The table is a
49# tab separated value(TSV) matrix with columns of code language (Bash, C, etc),
50# and rows of subdirectories of TF-A that contain the code.
51
52# Column headers
53# --------------
54(echo module; echo $categories | jq ".[]" ) | $n2t > $data
55# add a newline
56echo >> $data
57
58# Build Each Row
59# --------------
60for dir in $toplevel $secondlevel; do
61 # Gnuplot likes to treat underscores as a syntax for subscripts. This
62 # looks weird, as module names are not named with this syntax in mind.
63 # Further, it turns out that we go through 3 expansions, so we need 8 (2^3)
64 # backslashes.
65 echo $dir | sed -e "s/_/\\\\\\\\_/g" | $n2t >> $data
66 # This is the heart of the implementation, and probably the most
67 # complicated line in this script. First, we generate the subdirectory
68 # sloc with tokei, in json format. We then filter it with jq. The jq
Weronika Wiesiolek88b24012021-09-08 12:31:51 +010069 # filter iterates over the column names as saved in the categories
70 # variable. Each iteration through the loop, we print out the code
71 # value, when it exists, or null + 0. This takes advantage of the
72 # property of null:
Jimmy Brissonc7e28f52021-01-21 16:23:21 -060073 # > null can be added to any value, and returns the other value
74 # > unchanged.
75 tokei --output json $dir \
Weronika Wiesiolek88b24012021-09-08 12:31:51 +010076 | jq " .[$categories[]].code + 0" \
Jimmy Brissonc7e28f52021-01-21 16:23:21 -060077 | $n2t >> $data
78 echo >> $data
79done
80
81cat $data 1>&2
82gnuplot -c ${0%bash}plot $data
83
84rm $data