1#!/bin/bash
2# SPDX-License-Identifier: BSD-3-Clause
3# Copyright(c) 2018 Intel Corporation. All rights reserved.
4
5# Simple script for printing preprocessor output in human-readable fashion
6# Mostly useful for debugging macro metaprogramming
7# For more detailed useage, use --h option.
8enstyle(){
9	awk \
10		-v style="${1}" \
11		-v regex="${2}" \
12'{\
13	gsub(\
14		regex,\
15		"\033["style"m&\033[0m"\
16	);\
17	print;\
18}'
19}
20styleUserRegexp()
21{
22	if [[ "${USER_REGEXP}" != "" ]] ; then
23		enstyle "7;33" "${USER_REGEXP}"
24	else
25		tee # pipe that does nothing, just pass input to output
26	fi
27}
28styleAll(){
29	if [[ "${COLORISE}" == "1" ]] ; then
30		enstyle   "33" '[{}()\\[\\],;]'\
31		| enstyle "1;31" '->|\\.|&'\
32		| enstyle "1;35" '\\s(if|while|do|for|return|exit|panic)'\
33		| enstyle "1;36" '(u?int(32|64)_t|void|struct|const|char|volatile|static|unsigned|long)\\s*\\**'\
34		| enstyle   "32" '0x[A-Za-z0-9]+'\
35		| styleUserRegexp
36	else
37		tee # pipe that does nothing, just pass input to output
38	fi
39}
40
41pretty_macro(){
42	params="${1}"
43	infile="${2}"
44
45	gcc_params="${params} -E -dD ${infile}"
46	if [[ "${SHOW_ERR}" == "0" ]] ; then
47		gcc_params+=" 2>/dev/null"
48	fi
49	cmd="gcc ${gcc_params}"
50	if [[ "${VERBOSE}"  == "1" ]] ; then
51		echo "params are: [${params}]"
52		echo "infile  is: [${infile}]"
53		echo "cmd     is: [${cmd}]"
54	fi
55
56	bash -c "$cmd" \
57		| sed\
58			-e 's/;\ /;\n\t/g'\
59			-e 's/{\ /\n{\n\t/g'\
60			-e 's/}[\ ]*/\n}\n/g'\
61		| styleAll
62}
63
64VERBOSE=0
65SHOW_ERR=0
66COLORISE=0
67gcc_params=""
68USER_REGEXP=""
69while getopts ":f:I:u:hevc" opt; do
70	case ${opt} in
71		h) #usage
72			echo \
73"usage: $0 [-hevc] (-f IN_FILE) [-I INCLUDE_DIR] [-u USER_REGEXP]
74
75Expands c macroes in files given with -f flag and prints them prettily.
76
77mandatory arguments:
78    -f IN_FILE      input file to gcc
79optional  arguments:
80    -h              show this help message and exit
81    -e              don't redirect gcc errors to /dev/null
82    -v              show verbose output
83    -c              color the output
84    -u USER_REGEXP  highlights user defined regular expression
85    -I INCLUDE_DIR  pass INCLUDE_DIR to gcc with -I option
86"
87			exit 0
88		;;
89		u)
90			USER_REGEXP="${OPTARG}"
91		;;
92		e)
93			SHOW_ERR=1
94		;;
95		v)
96			VERBOSE=1
97		;;
98		c)
99			COLORISE=1
100		;;
101		I)
102			gcc_params+=" -I ${OPTARG}"
103		;;
104		f)
105			infiles+=("${OPTARG}")
106		;;
107		\?)
108			echo "Invalid option: -${OPTARG}" >&2
109			exit 1
110		;;
111		:)
112			echo "Option -${OPTARG} requires an argument." >&2
113			exit 1
114		;;
115	esac
116done
117if [[ "${VERBOSE}" == "1" ]] ; then
118	echo "gcc_params are: [${gcc_params}]"
119	echo "infiles    are: [${infiles[@]}]"
120	echo "user regexp is: [${USER_REGEXP}]"
121fi
122for file in ${infiles[@]} ; do
123	pretty_macro "${gcc_params}" "${file}"
124done
125exit 0
126
127