1 //
2 //  Copyright (C) 2013  Nick Gasson
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 //
17 
18 #include "rt.h"
19 #include "util.h"
20 #include "tree.h"
21 
22 #include <string.h>
23 
24 typedef struct {
25    char  *text;
26    size_t len;
27 } glob_t;
28 
29 static int     n_incl = 0;
30 static int     incl_sz = 0;
31 static int     n_excl = 0;
32 static int     excl_sz = 0;
33 static glob_t *incl;
34 static glob_t *excl;
35 
wave_include_glob(const char * glob)36 void wave_include_glob(const char *glob)
37 {
38    if (n_incl == incl_sz) {
39       incl_sz = MAX(incl_sz * 2, 256);
40       incl = xrealloc(incl, incl_sz * sizeof(glob_t));
41    }
42 
43    incl[n_incl].text = strdup(glob);
44    incl[n_incl].len  = strlen(glob);
45 
46    n_incl++;
47 }
48 
wave_exclude_glob(const char * glob)49 void wave_exclude_glob(const char *glob)
50 {
51    if (n_excl == excl_sz) {
52       excl_sz = MAX(excl_sz * 2, 256);
53       excl = xrealloc(excl, excl_sz * sizeof(glob_t));
54    }
55 
56    excl[n_excl].text = strdup(glob);
57    excl[n_excl].len  = strlen(glob);
58 
59    n_excl++;
60 }
61 
wave_process_file(const char * fname,bool include)62 static void wave_process_file(const char *fname, bool include)
63 {
64    FILE *f = fopen(fname, "r");
65    if (f == NULL)
66       return;
67 
68    notef("%s signals from %s", include ? "including" : "excluding", fname);
69 
70    int lineno = 0;
71    char line[1024];
72    while (!feof(f) && (lineno++, fgets(line, sizeof(line), f) != NULL)) {
73       // Erase comments
74       bool comment = false;
75       for (char *p = line; *p != '\0'; p++) {
76          if (*p == '#')
77             comment = true;
78          if (comment || (*p == '\r') || (*p == '\n'))
79             *p = '\0';
80       }
81 
82       char glob[1024];
83       if (sscanf(line, " %1023s ", glob) == 1) {
84          if (include)
85             wave_include_glob(glob);
86          else
87             wave_exclude_glob(glob);
88       }
89    }
90 
91    fclose(f);
92 }
93 
wave_include_file(const char * base)94 void wave_include_file(const char *base)
95 {
96    char buf[256];
97 
98    checked_sprintf(buf, sizeof(buf), "%s.include", base);
99    wave_process_file(buf, true);
100 
101    checked_sprintf(buf, sizeof(buf), "%s.exclude", base);
102    wave_process_file(buf, false);
103 }
104 
wave_should_dump(tree_t decl)105 bool wave_should_dump(tree_t decl)
106 {
107    ident_t name = tree_ident(decl);
108 
109    for (int i = 0; i < n_excl; i++) {
110       if (ident_glob(name, excl[i].text, excl[i].len))
111          return false;
112    }
113 
114    for (int i = 0; i < n_incl; i++) {
115       if (ident_glob(name, incl[i].text, incl[i].len))
116          return true;
117    }
118 
119    return (n_incl == 0);
120 }
121