ccanlint: offer to insert license comments where they're missing.
[ccan] / tools / ccanlint / licenses.c
1 #include "licenses.h"
2 #include "ccanlint.h"
3 #include <ccan/str/str.h>
4 #include <ccan/tal/tal.h>
5 #include <ccan/tal/str/str.h>
6
7 const struct license_info licenses[] = {
8         { "LGPLv2+", "LGPL",
9           "GNU LGPL version 2 (or later)",
10           { "gnu lesser general public license",
11             "version 2",
12             "or at your option any later version"
13           }
14         },
15         { "LGPLv2", "LGPL",
16           "GNU LGPL version 2",
17           { "gnu lesser general public license",
18             "version 2",
19             NULL
20           }
21         },
22         { "LGPLv3", "LGPL",
23           "GNU LGPL version 3",
24           { "gnu lesser general public license",
25             "version 3",
26             NULL
27           }
28         },
29         { "LGPL", "LGPL",
30           "GNU LGPL",
31           { "gnu lesser general public license",
32             NULL,
33             NULL
34           }
35         },
36         { "GPLv2+", "GPL",
37           "GNU GPL version 2 (or later)",
38           { "gnu general public license",
39             "version 2",
40             "or at your option any later version"
41           }
42         },
43         { "GPLv2", "GPL",
44           "GNU GPL version 2",
45           { "gnu general public license",
46             "version 2",
47             NULL
48           }
49         },
50         { "GPLv3", "GPL",
51           "GNU GPL version 3 (or later)",
52           { "gnu general public license",
53             "version 3",
54             NULL
55           }
56         },
57         { "GPL", "GPL",
58           "GNU GPL",
59           { "gnu general public license",
60             NULL,
61             NULL
62           }
63         },
64         { "BSD-3CLAUSE", "BSD",
65           "3-clause BSD license",
66           { "redistributions of source code must retain",
67             "redistributions in binary form must reproduce",
68             "endorse or promote"
69           }
70         },
71         { "BSD-MIT", "MIT",
72           "MIT (BSD) license",
73           { "without restriction",
74             "above copyright notice",
75             "without warranty"
76           }
77         },
78         { "CC0", "CC0",
79           "CC0 license (public domain)",
80           { "Waiver.",
81             "unconditionally waives",
82             NULL
83           }
84         },
85         { "Public domain", "Public domain",
86           NULL,
87           { NULL, NULL, NULL  }
88         },
89         { "Unknown license", "Unknown license",
90           NULL,
91           { NULL, NULL, NULL  }
92         },
93 };
94
95 /* License compatibilty chart (simplified: we don't test that licenses between
96  * files are compatible). */
97 #define O true
98 #define X false
99 bool license_compatible[LICENSE_UNKNOWN+1][LICENSE_UNKNOWN] = {
100 /*     LGPL2+   LGPL3   GPL2+   GPL3     BSD     CC0
101             LGPL2    LGPL   GPL2     GPL     MIT     PD   */
102 /* _info says: LGPL2+ */
103         { O,  X,  X,  O,  X,  X,  X,  X,  O,  O,  O,  O },
104 /* _info says: LGPL2 only */
105         { O,  O,  X,  O,  X,  X,  X,  X,  O,  O,  O,  O },
106 /* _info says: LGPL3 (or any later version) */
107         { O,  X,  O,  O,  X,  X,  X,  X,  O,  O,  O,  O },
108 /* _info says: LGPL (no version specified) */
109         { O,  O,  O,  O,  X,  X,  X,  X,  O,  O,  O,  O },
110 /* _info says: GPL2+ */
111         { O,  O,  O,  O,  O,  X,  X,  O,  O,  O,  O,  O },
112 /* _info says: GPL2 only */
113         { O,  O,  O,  O,  O,  O,  X,  O,  O,  O,  O,  O },
114 /* _info says: GPL3 (or any later version) */
115         { O,  O,  O,  O,  O,  X,  O,  O,  O,  O,  O,  O },
116 /* _info says: GPL (unknown version) */
117         { O,  O,  O,  O,  O,  O,  O,  O,  O,  O,  O,  O },
118 /* _info says: BSD (3-clause) */
119         { X,  X,  X,  X,  X,  X,  X,  X,  O,  O,  O,  O },
120 /* _info says: MIT */
121         { X,  X,  X,  X,  X,  X,  X,  X,  X,  O,  O,  O },
122 /* _info says: CC0 */
123         { X,  X,  X,  X,  X,  X,  X,  X,  X,  X,  O,  O },
124 /* _info says: Public domain */
125         { X,  X,  X,  X,  X,  X,  X,  X,  X,  X,  O,  O },
126 /* _info says something we don't understand */
127         { X,  X,  X,  X,  X,  X,  X,  X,  X,  X,  O,  O }
128 };
129 #undef X
130 #undef O
131
132 /* See GPLv2 and v2 (basically same wording) for interpreting versions:
133  * the "any later version" means the recepient can choose. */
134 enum license which_license(struct doc_section *d)
135 {
136         if (!d)
137                 return LICENSE_UNKNOWN;
138
139         /* This means "user chooses what version", including GPLv1! */
140         if (streq(d->lines[0], "GPL"))
141                 return LICENSE_GPL;
142         /* This means "v2 only". */
143         if (streq(d->lines[0], "GPLv2"))
144                 return LICENSE_GPLv2;
145         /* This means "v2 or above" at user's choice. */
146         if (streq(d->lines[0], "GPL (v2 or any later version)"))
147                 return LICENSE_GPLv2_PLUS;
148         /* This means "v3 or above" at user's choice. */
149         if (streq(d->lines[0], "GPL (v3 or any later version)"))
150                 return LICENSE_GPLv3;
151
152         /* This means "user chooses what version" */
153         if (streq(d->lines[0], "LGPL"))
154                 return LICENSE_LGPL;
155         /* This means "v2.1 only". */
156         if (streq(d->lines[0], "LGPLv2.1"))
157                 return LICENSE_LGPLv2;
158         /* This means "v2.1 or above" at user's choice. */
159         if (streq(d->lines[0], "LGPL (v2.1 or any later version)"))
160                 return LICENSE_LGPLv2_PLUS;
161         /* This means "v3 or above" at user's choice. */
162         if (streq(d->lines[0], "LGPL (v3 or any later version)"))
163                 return LICENSE_LGPLv3;
164
165         if (streq(d->lines[0], "BSD-MIT") || streq(d->lines[0], "MIT"))
166                 return LICENSE_MIT;
167         if (streq(d->lines[0], "BSD (3 clause)"))
168                 return LICENSE_BSD;
169         if (streq(d->lines[0], "CC0"))
170                 return LICENSE_CC0;
171         if (tal_strreg(NULL, d->lines[0], "CC0 \\([Pp]ublic [Dd]omain\\)",
172                        NULL))
173                 return LICENSE_CC0;
174         if (tal_strreg(NULL, d->lines[0], "[Pp]ublic [Dd]omain"))
175                 return LICENSE_PUBLIC_DOMAIN;
176
177         return LICENSE_UNKNOWN;
178 }
179
180 const char *get_ccan_simplified(struct ccan_file *f)
181 {
182         if (!f->simplified) {
183                 unsigned int i, j;
184
185                 /* Simplify for easy matching: only alnum and single spaces. */
186                 f->simplified = tal_strdup(f, get_ccan_file_contents(f));
187                 for (i = 0, j = 0; f->simplified[i]; i++) {
188                         if (cisupper(f->simplified[i]))
189                                 f->simplified[j++] = tolower(f->simplified[i]);
190                         else if (cislower(f->simplified[i]))
191                                 f->simplified[j++] = f->simplified[i];
192                         else if (cisdigit(f->simplified[i]))
193                                 f->simplified[j++] = f->simplified[i];
194                         else if (cisspace(f->simplified[i])) {
195                                 if (j != 0 && f->simplified[j-1] != ' ')
196                                         f->simplified[j++] = ' ';
197                         }
198                 }
199                 f->simplified[j] = '\0';
200         }
201         return f->simplified;
202 }
203
204 bool find_boilerplate(struct ccan_file *f, enum license license)
205 {
206         unsigned int i;
207
208         for (i = 0; i < NUM_CLAUSES; i++) {
209                 if (!licenses[license].clause[i])
210                         break;
211
212                 if (!strstr(get_ccan_simplified(f),
213                             licenses[license].clause[i])) {
214                         return false;
215                 }
216         }
217         return true;
218 }
219
220 struct doc_section *find_license_tag(const struct manifest *m)
221 {
222         struct doc_section *d;
223
224         list_for_each(get_ccan_file_docs(m->info_file), d, list) {
225                 if (!streq(d->function, m->modname))
226                         continue;
227                 if (streq(d->type, "license"))
228                         return d;
229         }
230         return NULL;
231 }
232
233 const char *get_license_oneliner(const tal_t *ctx, enum license license)
234 {
235         return tal_fmt(ctx, "/* %s - see LICENSE file for details */",
236                        licenses[license].describe);
237 }