OSDN Git Service

upgrade to 3.6.2
[jnethack/source.git] / sys / unix / depend.awk
1 # depend.awk -- awk script used to construct makefile dependencies
2 # for nethack's source files (`make depend' support for Makefile.src).
3 # $NHDT-Date: 1546220373 2018/12/31 01:39:33 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.8 $
4 #
5 # usage:
6 #   cd src ; nawk -f depend.awk ../include/*.h list-of-.c/.cpp-files
7 #
8 # This awk program scans each file in sequence, looking for lines beginning
9 # with `#include "' and recording the name inside the quotes.  For .h files,
10 # that's all it does.  For each .c file, it writes out a make rule for the
11 # corresponding .o file; dependencies in nested header files are propagated
12 # to the .o target.
13 #
14 # config.h and hack.h get special handling because of their heavy use;
15 #       timestamps for them allow make to avoid rechecking dates on
16 #       subsidiary headers for every source file;
17 # extern.h gets special handling to avoid excessive recompilation
18 #       during development;
19 # patchlev.h gets special handling because it only exists on systems
20 #       which consider filename patchlevel.h to be too long;
21 # interp.c gets special handling because it usually doesn't exist; it's
22 #       assumed to be the last #include in the file where it occurs.
23 # win32api.h gets special handling because it only exists for some ports;
24 #       it's assumed to be the last #include in the file where it occurs
25 # zlib.h ditto
26 #
27 BEGIN           { FS = "\""                     #for `#include "X"', $2 is X
28                   special[++sp_cnt] = "../include/config.h"
29                   special[++sp_cnt] = "../include/hack.h"
30                   alt_deps["../include/extern.h"] = ""
31                   alt_deps["../include/patchlev.h"] = ""
32                   alt_deps["interp.c"] = " #interp.c"   #comment it out
33                   alt_deps["../include/win32api.h"] = " #../include/win32api.h"
34                   alt_deps["../include/zlib.h"] = " #zlib.h"    #comment it out
35                 }
36 FNR == 1        { output_dep()                  #finish previous file
37                   file = FILENAME               #setup for current file
38                 }
39 /^\#[ \t]*include[ \t]+\"/  {                   #find `#include "X"'
40                   incl = $2
41                   #[3.4.0: gnomehack headers currently aren't in include]
42                   #[3.6.2: Qt4 headers aren't in include either]
43                   #[3.6.2: curses headers likewise]
44                   if (incl ~ /\.h$/) {
45                     if (incl ~ "curses\.h")
46                       incl = ""  # skip "curses.h"; it should be <curses.h>
47                     else if (incl ~ /^curs/)    # curses special case
48                       incl = "../win/curses/" incl
49                     else if (incl ~ /^qt4/)     # Qt v4 special case
50                       incl = "../win/Qt4/" incl
51                     else if (incl ~ /^gn/)      # gnomehack special case
52                       incl = "../win/gnome/" incl
53                     else
54                       incl = "../include/" incl
55                   }
56                   deps[file] = deps[file] " " incl
57                 }
58 END             { output_dep() }                #finish the last file
59
60
61 #
62 # `file' has been fully scanned, so process it now; for .h files,
63 # don't do anything (we've just been collecting their dependencies);
64 # for .c files, output the `make' rule for corresponding .o file
65 #
66 function output_dep(                            targ)
67 {
68   if (file ~ /\.cp*$/) {
69     #prior to very first .c|.cpp file, handle some special header file cases
70     if (!c_count++)
71       output_specials()
72     #construct object filename from source filename
73     targ = file;  sub("^.+/", "", targ);  sub("\\.cp*$", ".o", targ)
74     #format and write the collected dependencies
75     format_dep(targ, file)
76   }
77 }
78
79 #
80 # handle some targets (config.h, hack.h) via special timestamping rules
81 #
82 function output_specials(                       i, sp, alt_sp)
83 {
84   for (i = 1; i <= sp_cnt; i++) {
85     sp = special[i]
86     #change "../include/foo.h" first to "foo.h", then ultimately to "$(FOO_H)"
87     alt_sp = sp;  sub("^.+/", "", alt_sp)
88     print "#", alt_sp, "timestamp"      #output a `make' comment
89  #- sub("\\.", "_", alt_sp);  alt_sp = "$(" toupper(alt_sp) ")"
90  #+ Some nawks don't have toupper(), so hardwire these instead.
91     sub("config.h", "$(CONFIG_H)", alt_sp);  sub("hack.h", "$(HACK_H)", alt_sp)
92     format_dep(alt_sp, sp)              #output the target
93     print "\ttouch " alt_sp             #output a build command
94     alt_deps[sp] = alt_sp               #alternate dependency for depend()
95   }
96   print "#"
97 }
98
99 #
100 # write a target and its dependency list in pretty-printed format;
101 # if target's primary source file has a path prefix, also write build command
102 #
103 function format_dep(target, source,             n, i, list)
104 {
105   split("", done)                       #``for (x in done) delete done[x]''
106   printf("%s:", target);  col = length(target) + 1
107   #- printf("\t");  col += 8 - (col % 8);
108   #- if (col == 8) { printf("\t"); col += 8 }
109   source = depend("", source, 0)
110   n = split(source, list, " +")
111   for (i = 2; i <= n; i++) {    #(leading whitespace yields empty 1st element)
112     if (col + length(list[i]) >= (i < n ? 78 : 80)) {
113       printf(" \\\n\t\t");  col = 16    #make a backslash+newline split
114     } else {
115       printf(" ");  col++;
116     }
117     printf("%s", list[i]);  col += length(list[i])
118   }
119   printf("\n")                          #terminate
120   #write build command if first source entry has non-include path prefix
121   source = list[2]
122   if (source ~ /\// && substr(source, 1, 11) != "../include/") {
123     if (source ~ /\.cpp$/ )
124       print "\t$(CXX) $(CXXFLAGS) -c -o $@ " source
125     else if (source ~ /\/X11\//)        # "../win/X11/foo.c"
126       print "\t$(CC) $(CFLAGS) $(X11CFLAGS) -c -o $@ " source
127     else if (source ~ /\/gnome\//)      # "../win/gnome/foo.c"
128       print "\t$(CC) $(CFLAGS) $(GNOMEINC) -c -o $@ " source
129     else
130       print "\t$(CC) $(CFLAGS) -c -o $@ " source
131   }
132 }
133
134 #
135 # recursively add the dependencies for file `name' to string `inout'
136 # (unless `skip', in which case we're only marking files as already done)
137 #
138 function depend(inout, name, skip,              n, i, list)
139 {
140   if (!done[name]++) {
141     if (name in alt_deps) {     #some names have non-conventional dependencies
142       if (!skip) inout = inout " " alt_deps[name]
143       skip = 1
144     } else {                    #ordinary name
145       if (!skip) inout = inout " " name
146     }
147     if (name in deps) {
148  #-   n = split(deps[name], list, " +")
149  #-   for (i = 2; i <= n; i++)  #(leading whitespace yields empty 1st element)
150  #-     inout = depend(inout, list[i], skip)
151  #+  At least one implementation of nawk handles the local array `list' wrong,
152  #+  so the clumsier substitute code below is used as a workaround.
153       list = deps[name];  sub("^ +", "", list)
154       while (list) {
155         match((list " "), " +");  i = RSTART;  n = RLENGTH
156         inout = depend(inout, substr(list, 1, i-1), skip)
157         list = substr(list, i+n)
158       }
159     }
160   }
161   return inout
162 }
163
164 #depend.awk#