add debug
[kps.git] / conv.h
blobc00f7928c591849d341b4f001d9ee33bbfbdae9b
1 /* Kernel changelog analysis
2 * (C) 2008 Wang Chen
4 * This code is licenced under the GPL.
6 */
8 #ifndef INC_CONV
9 #define INC_CONV
11 #include <ctype.h>
13 #define MAXDATE 0xffffffff
15 /* Matching string with people's mail information. Instead of search string in
16 * whole mail information, we can strictly demand conv_cnt() to match the
17 * string with appointed field of mail information. There are 5 fields:
18 * 1.FIRSTNAME, 2.MIDNAME, 3.LASTNAME, 4.ACCOUNT, 5.DOMAIN
19 * We can still search the keyword in whole mail info by assigning field to 0
21 enum mail_field {
22 ALL, /* search a string in whole mail infor, match a substr */
23 FIRST, /* strictly, but not casesensitively match a string with first name */
24 MID, /* strictly, but not casesensitively match a string with mid name */
25 LAST, /* strictly, but not casesensitively match a string with last name */
26 ACCOUNT,/* strictly, but not casesensitively match a string with mail account */
27 DOMAIN, /* match a sub string with mail domain */
28 NAME /* strictly, but not casesensitively match a string with one word of name */
31 struct conv_country {
32 char *mail;
33 char *country;
34 /* which field of "FIRSTNAME MIDNAME LASTNAME <ACCOUNT@DOMAIN>" should
35 * match the compared keyword.
37 enum mail_field field;
40 struct conv_com {
41 char *from;
42 char *to;
45 struct conv_per {
46 char *from;
47 char *to;
48 char *to_com;
49 /* Some people move to another company but not change mail address.
50 * To known these people's commits attribution to which company, we
51 * need to known the people attribution to where in some time range.
53 unsigned int begin; /* attribution from when */
54 unsigned int end; /* attribution to when */
55 char *name; /* to fore the name */
58 #define CONV_CNT(_mail, _country) {\
59 .mail = _mail, \
60 .country = _country, \
61 .field = ALL, \
64 #define CONV_NAME_CNT(_mail, _country) {\
65 .mail = _mail, \
66 .country = _country, \
67 .field = NAME, \
70 #define CONV_FIRST_CNT(_mail, _country) {\
71 .mail = _mail, \
72 .country = _country, \
73 .field = FIRST, \
76 #define CONV_MID_CNT(_mail, _country) {\
77 .mail = _mail, \
78 .country = _country, \
79 .field = MID, \
82 #define CONV_LAST_CNT(_mail, _country) {\
83 .mail = _mail, \
84 .country = _country, \
85 .field = LAST, \
88 #define CONV_ACCOUNT_CNT(_mail, _country) {\
89 .mail = _mail, \
90 .country = _country, \
91 .field = ACCOUNT, \
94 #define CONV_DOMAIN_CNT(_mail, _country) {\
95 .mail = _mail, \
96 .country = _country, \
97 .field = DOMAIN, \
100 #define CONV_COM(_from, _to) {\
101 .from = _from, \
102 .to = _to, \
105 /* This define is used when declaring a people who didn't ever change
106 * attribution.
108 #define CONV_PER(_from, _to, _to_com) {\
109 .from = _from, \
110 .to = _to, \
111 .to_com = _to_com, \
112 .begin = 0, \
113 .end = 0, \
114 .name = NULL, \
117 /* This define is used when declaring a people who changed attribution
118 * sometime.
120 #define CONV_PER_TIME(_from, _to, _to_com, _begin, _end) {\
121 .from = _from, \
122 .to = _to, \
123 .to_com = _to_com, \
124 .begin = _begin, \
125 .end = _end, \
126 .name = NULL, \
129 /* This define is used when declaring a people who didn't ever change
130 * attribution and need a force name.
132 #define CONV_PER_NAME(_from, _to, _to_com, _name) {\
133 .from = _from, \
134 .to = _to, \
135 .to_com = _to_com, \
136 .begin = 0, \
137 .end = 0, \
138 .name = _name, \
141 /* This define is used when declaring a people who changed attribution
142 * sometime and need a force name.
144 #define CONV_PER_TIME_NAME(_from, _to, _to_com, _begin, _end, _name) {\
145 .from = _from, \
146 .to = _to, \
147 .to_com = _to_com, \
148 .begin = _begin, \
149 .end = _end, \
150 .name = _name, \
153 inline static int date_ok(unsigned int date, struct conv_per conv_per)
155 if (date <= conv_per.end && date >= conv_per.begin)
156 return 1;
157 else
158 return 0;
161 #include "nation.h"
162 #include "allconv.h"
164 static int convt_name(char **from, char *name)
166 char *tmp = NULL;
167 char *mail = NULL;
168 int len = 0;
169 int ret = 0;
171 ret = mail_from_per(&mail, *from);
172 if (ret < 0)
173 return 1;
174 len += strlen(mail);
175 len += strlen(name);
176 /* between name and mail, there is a whitespace */
177 len++;
179 if (init_str(&tmp, len+1))
180 return 1;
181 free(*from);
182 *from = tmp;
184 /* Copy name to new string */
185 memcpy(tmp, name, strlen(name));
186 /* Copy white space to new string */
187 tmp = strchr(*from, '\0');
188 memcpy(tmp, " ", 1);
189 /* Copy mail to new string */
190 tmp = strchr(*from, '\0');
191 memcpy(tmp, mail, strlen(mail));
193 free(mail);
194 return 0;
197 static int convt_per(char **from, char *mail)
199 char *tmp = *from;
200 int len = 0, len_name = 0;
202 /* Get len of author's name */
203 while ((tmp != NULL) && (*tmp != '\0') &&
204 (*tmp != '\n') && (*tmp != '<')) {
205 len_name++;
206 tmp++;
208 len = len_name + strlen(mail);
209 if (init_str(&tmp, len+1))
210 return 1;
211 /* Copy name to new string */
212 memcpy(tmp, *from, len_name);
213 free(*from);
214 *from = tmp;
215 /* Copy mail to new string */
216 tmp = strchr(*from, '\0');
217 memcpy(tmp, mail, strlen(mail));
218 return 0;
221 static int convt_com(char **from, char *to)
223 free(*from);
224 if (init_str(from, strlen(to)+1))
225 return 1;
226 memcpy(*from, to, strlen(to));
227 return 0;
230 /* Find out one's country name by his/her mail infor.
231 * @per: mail infor as formast(FIRSTNAME MIDNAME LASTNAME <ACCOUNT@DOMAIN>)
232 * @cnt: country name string
234 int conv_cnt(char *per, char **cnt)
236 int i;
237 const char *unknown = "Unknown";
238 char *str = NULL;
240 for (i = 0; conv_country[i].mail != NULL; i++) {
241 switch (conv_country[i].field) {
242 case ALL:
243 if (strcasestr(per, conv_country[i].mail))
244 goto cp_country;
245 break;
246 case FIRST:
247 if (firstname(&str, per))
248 if (strcasecmp(conv_country[i].mail, str) == 0)
249 goto cp_country;
250 break;
251 case MID:
252 if (midname(&str, per))
253 if (strcasecmp(conv_country[i].mail, str) == 0)
254 goto cp_country;
255 break;
256 case LAST:
257 if (lastname(&str, per))
258 if (strcasecmp(conv_country[i].mail, str) == 0)
259 goto cp_country;
260 break;
261 case ACCOUNT:
262 if (account(&str, per))
263 if (strcasecmp(conv_country[i].mail, str) == 0)
264 goto cp_country;
265 break;
266 case DOMAIN:
267 if (domain(&str, per))
268 if (strcasestr(str, conv_country[i].mail))
269 goto cp_country;
270 break;
271 case NAME:
272 if (firstname(&str, per))
273 if (strcasecmp(conv_country[i].mail, str) == 0)
274 goto cp_country;
275 if (str) {free(str); str = NULL;}
276 if (midname(&str, per))
277 if (strcasecmp(conv_country[i].mail, str) == 0)
278 goto cp_country;
279 if (str) {free(str); str = NULL;}
280 if (lastname(&str, per))
281 if (strcasecmp(conv_country[i].mail, str) == 0)
282 goto cp_country;
283 break;
284 default:
285 break;
287 if (str) {free(str); str = NULL;}
290 cp_country:
291 if (str) {free(str); str = NULL;}
292 if (conv_country[i].mail != NULL) {
293 if (init_str(cnt, strlen(conv_country[i].country)+1))
294 return 1;
295 memcpy(*cnt, conv_country[i].country,
296 strlen(conv_country[i].country));
297 } else {
298 if (init_str(cnt, strlen(unknown)+1))
299 return 1;
300 memcpy(*cnt, unknown, strlen(unknown));
303 return 0;
306 static void conv_mail2lower(char *per)
308 while (*per != '<' && *per != '\0') {
309 per++;
311 do {
312 per++;
313 *per = tolower(*per);
314 } while (*per != '>' && *per != '\0');
318 * conv_per_com: Convert mail addresses for one person and attribution an
319 * engineer to employer.
320 * @per: Engineer's name and mail address which needs convert. Convert result
321 * store in it too.
322 * @com: Engineer's employer which automaticlly matched but maybe not correct.
323 * Convert result store in it.
324 * @date:This commit's date which used to tell an engineer attribution to which
325 * employer in that date.
326 * Return: 0 - successful
327 * 1 - not successful
329 int conv_per_com(char **per, char **com, unsigned int date)
331 int i, ret;
332 char *mail;
334 conv_mail2lower(*per);
335 if (mail_from_per(&mail, *per) < 0) {
336 ret = 1;
337 goto out1;
340 /* Whether this company needs conversion.
341 * Should do this conversion before mail conversion.
343 for (i = 0; conv_com[i].from != NULL; i++)
344 if (strcasestr(*com, conv_com[i].from))
345 break;
346 if (conv_com[i].from != NULL) {
347 if (convt_com(com, conv_com[i].to)) {
348 ret = 1;
349 goto out;
351 } else {
352 if (convt_com(com, "Unknown")) {
353 ret = 1;
354 goto out;
358 /* Whether this mail or name needs conversion */
359 for (i = 0; conv_per[i].from != NULL; i++) {
360 if ( (*mail != '\0') &&
361 (strncasecmp(conv_per[i].from, mail, strlen(mail)) == 0)) {
362 /* mail convert */
363 if (conv_per[i].to != NULL)
364 if (convt_per(per, conv_per[i].to)) {
365 ret = 1;
366 goto out;
368 /* name convert */
369 if (conv_per[i].name != NULL)
370 if (convt_name(per, conv_per[i].name)) {
371 ret = 1;
372 goto out;
374 /* employer convert */
375 if (conv_per[i].to_com != NULL) {
376 if ((conv_per[i].begin + conv_per[i].end == 0) ||
377 date_ok(date, conv_per[i])) {
378 if (convt_com(com, conv_per[i].to_com)) {
379 ret = 1;
380 goto out;
382 break;
384 } else
385 break;
388 out:
389 if (mail)
390 free(mail);
391 out1:
392 return ret;
395 #endif