File indexing completed on 2024-12-08 05:05:48

0001 #!/bin/awk
0002 #
0003 # Copyright (c) 2014, Michal Policht. This file is dually licensed under terms of 
0004 # either WTFPL or BEER-WARE LICENSE. You may obtain the copy of WTFPL or BEER-WARE
0005 # LICENSE in nearest drug store.
0006 #
0007 # THIS SOFTWARE IS ADDICTED TO DRUGS AND ALCOHOL AND IS A SUSPECT OF DRIVING UNDER THE 
0008 # INFLUENCE OF ALCOHOL. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
0009 # CONTRIBUTORS "AS IS NOT" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
0010 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS AND APPLICATION AND 
0011 # ACCOMODATION FOR A PARTICULAR PURPOSE AND MANY OTHERS NOT MENTIONED, NOR EVEN
0012 # INVENTED WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 
0013 # OR CONTRIBUTORS BE LIABLE FOR ANY TEMPORAL, PERMANENT, UNFORTUNATE, UNLUCKY,
0014 # LUCKY, DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ACCIDENTAL, MENTAL, 
0015 # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
0016 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION; 
0017 # OR BEING KILLED BY A LIGHTNING; OR FLOOD; OR FIRE; OR ANTEATER (INCLUDING BUT NOT 
0018 # LIMITED TO, GIANT ANTEATER, ANTEATER WHO LIES ON A SOFA; ANTEATER WHO LISTENS HEAVY 
0019 # METAL MUSIC; ANTEATER WHO ATE HUMAN BEFORE) OR ANOTHER BEING.) HOWEVER CAUSED AND ON 
0020 # ANY, ANY THEORY OF LIABILITY, CONSPIRACY THEORY, ANY THEORY OF RELATIVITY, WHETHER IN 
0021 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 
0022 # WAY OUT OF THE USE OF THIS SOFTWARE, ARISING IN ANY WAY OUT OF THE SUN, EVEN IF PROMISSED 
0023 # WISHED OR ASSURED SUCH DAMAGE. THIS SOFTWARE CAN REALLY DO TERRIBLE THINGS.
0024 #
0025 # Script updates C/C++ include guards with macros based on header path (including directory structure).
0026 # It seeks for "#ifndef, #define" pair and substitutes first encountered pair with generated values.
0027 # Script does not distinguish include guards from other macros, so each HEADER FILE MUST CONTAIN 
0028 # INCLUDE GUARD AS ITS FIRST "#ifndef, #define" MACRO PAIR. Script only updates include guards; 
0029 # if file does not contain something that looks like include guard to the script it will not add one. 
0030 # Script will also eat everything after last "#endif", presumably include guard comment. It's a stupid 
0031 # beast, so always backup your data before use.
0032 #
0033 # usage: awk [-v prefix="PREFIX"] -f awkgward.awk header
0034 # example: awk -v prefix="PROJECT_" -f awkgward.awk file.hpp
0035 #
0036 # parameters: 
0037 # header - header file.
0038 #
0039 # required tools: awk.
0040 
0041 function create_guard_macro(prefix, filename)
0042 {
0043     escaped_underscores = toupper(filename);
0044     # Just in case, escape single underscores.
0045     gsub(/_/, "_u_", escaped_underscores);
0046     # \/ = slash (/), \. = dot (.), \\ = backslash (\) - replace them with underscore.
0047     gsub(/[\/\.\\]/, "_", escaped_underscores);
0048     return prefix escaped_underscores;
0049 }
0050 
0051 function create_guard(prefix, filename)
0052 {
0053     guard_macro = create_guard_macro(prefix, filename);
0054     guard = "#ifndef " guard_macro ORS "#define " guard_macro;
0055     return guard;
0056 }
0057 
0058 function print_or_buf(line)
0059 {
0060     if (global_buf_mode)
0061         global_buf = global_buf line ORS;
0062     else
0063         print line;
0064 }
0065 
0066 BEGIN {
0067     S_START = 0;
0068     S_FIRST_IFNDEF = 1;
0069     S_END = 2;
0070 
0071     if (!prefix)
0072         prefix = "";
0073 
0074     global_buf = "";
0075     global_buf_mode = 0;
0076     endif_line = "";
0077 
0078     ifndef_buf = "";
0079     # simple automata:
0080     # S_START            /^#ifndef\s.*/  -> S_FIRST_IFNDEF     /^#define\s.*/ -> S_END     // -> S_START
0081     # S_FIRST_IFNDEF     /^#define\s.*/ -> S_END
0082     # S_END              // -> S_END
0083     state = S_START;
0084 }
0085  
0086 /^#ifndef[\t ].*/ {
0087     if (state == S_START) {
0088         ifndef_buf = $0;
0089         state = S_FIRST_IFNDEF;
0090         next;
0091     }
0092 }
0093 
0094 /^#define[\t ].*/ {
0095     if (state == S_FIRST_IFNDEF) {
0096         #eat old guard and replace it with new one
0097         print_or_buf(create_guard(prefix, FILENAME));
0098         state = S_END;
0099         next;
0100     }
0101     if (state == S_START)
0102         state = S_END;
0103 }
0104 
0105 /^#endif[\t ].*/ {
0106     #flush old buffer and whatever was in endif line
0107     if (global_buf_mode) {
0108         print endif_line;
0109         printf global_buf;
0110         global_buf = "";
0111     }
0112     endif_line = $0;
0113     global_buf_mode = 1;
0114     next;
0115 }
0116 
0117 
0118 {
0119     if (state == S_END || state == S_START)
0120         print_or_buf($0);
0121     if (state == S_FIRST_IFNDEF) {
0122         print_or_buf(ifndef_buf);
0123         print_or_buf($0);
0124         state = S_END;
0125     }
0126 }
0127 
0128 END {
0129     if (global_buf_mode) {
0130         #it's last endif so do not print full endif_line
0131         print "#endif";
0132         printf global_buf; #flush whatever was after last endif
0133     }
0134 }
0135