1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2012 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #pragma prototyped
23
24 /*
25 * Glenn Fowler
26 * AT&T Research
27 *
28 * generate a license comment -- see proto(1)
29 *
30 * NOTE: coded for minimal library dependence
31 * not so for the legal department
32 */
33
34 #ifndef _PPLIB_H
35 #include <ast.h>
36 #include <time.h>
37 #endif
38
39 #ifndef O_cloexec
40 #ifdef O_CLOEXEC
41 #define O_cloexec 0
42 #else
43 #define O_cloexec 0
44 #endif
45 #endif
46
47 #undef copy
48 #undef BSD /* guess who defines this */
49 #undef END
50 #undef INLINE
51 #undef TEST
52 #undef VERBOSE
53
54 #define NONE 0
55 #define INLINE 1
56 #define TEST 2
57 #define VERBOSE 3
58 #define USAGE 4
59 #define OPEN 5
60 #define CPL 6
61 #define EPL 7
62 #define BSD 8
63 #define ZLIB 9
64 #define MIT 10
65 #define GPL 11
66 #define SPECIAL 12
67 #define NONEXCLUSIVE 13
68 #define NONCOMMERCIAL 14
69 #define PROPRIETARY 15
70
71 #define AUTHOR 0
72 #define CLASS 1
73 #define COMPANY 2
74 #define COMPONENT 3
75 #define CONTRIBUTOR 4
76 #define CORPORATION 5
77 #define DOMAIN 6
78 #define ID 7
79 #define INCORPORATION 8
80 #define LICENSE 9
81 #define LOCATION 10
82 #define NAME 11
83 #define NOTICE 12
84 #define ORGANIZATION 13
85 #define PACKAGE 14
86 #define PARENT 15
87 #define QUERY 16
88 #define SINCE 17
89 #define SOURCE 18
90 #define START 19
91 #define STYLE 20
92 #define URL 21
93 #define URLMD5 22
94 #define VERSION 23
95
96 #define IDS 64
97
98 #define COMDATA 70
99 #define COMLINE (COMDATA+4)
100 #define COMLONG (COMDATA-32)
101 #define COMMENT(x,b,s,u) comment(x,b,s,sizeof(s)-1,u)
102
103 #define PUT(b,c) (((b)->nxt<(b)->end)?(*(b)->nxt++=(c)):((c),(-1)))
104 #define BUF(b) ((b)->buf)
105 #define USE(b) ((b)->siz=(b)->nxt-(b)->buf,(b)->nxt=(b)->buf,(b)->siz)
106 #define SIZ(b) ((b)->nxt-(b)->buf)
107 #define END(b) (*((b)->nxt>=(b)->end?((b)->nxt=(b)->end-1):(b)->nxt)=0,(b)->nxt-(b)->buf)
108
109 #ifndef NiL
110 #define NiL ((char*)0)
111 #endif
112
113 typedef struct Buffer_s
114 {
115 char* buf;
116 char* nxt;
117 char* end;
118 int siz;
119 } Buffer_t;
120
121 typedef struct Item_s
122 {
123 char* data;
124 int size;
125 int quote;
126 } Item_t;
127
128 typedef struct Id_s
129 {
130 Item_t name;
131 Item_t value;
132 } Id_t;
133
134 /*
135 * NOTE: key[] element order must match the corresponding macro
136 */
137
138 #define KEY(s) {s,sizeof(s)-1,0}
139
140 static const Item_t key[] =
141 {
142 KEY("author"),
143 KEY("class"),
144 KEY("company"),
145 KEY("component"),
146 KEY("contributor"),
147 KEY("corporation"),
148 KEY("domain"),
149 KEY("id"),
150 KEY("incorporation"),
151 KEY("license"),
152 KEY("location"),
153 KEY("name"),
154 KEY("notice"),
155 KEY("organization"),
156 KEY("package"),
157 KEY("parent"),
158 KEY("query"),
159 KEY("since"),
160 KEY("source"),
161 KEY("start"),
162 KEY("type"),
163 KEY("url"),
164 KEY("urlmd5"),
165 KEY("version"),
166 {0}
167 };
168
169 #define ITEMS (sizeof(key)/sizeof(key[0])-1)
170
171 #define LIC(s,c) {s,sizeof(s)-1,c}
172
173 static const Item_t lic[] =
174 {
175 LIC("none", NONE),
176 LIC("inline", SPECIAL),
177 LIC("test", TEST),
178 LIC("verbose", VERBOSE),
179 LIC("usage", USAGE),
180 LIC("open", OPEN),
181 LIC("cpl", OPEN),
182 LIC("epl", OPEN),
183 LIC("bsd", OPEN),
184 LIC("zlib", OPEN),
185 LIC("mit", OPEN),
186 LIC("gpl", GPL),
187 LIC("special", SPECIAL),
188 LIC("nonexclusive", SPECIAL),
189 LIC("noncommercial", SPECIAL),
190 LIC("proprietary", PROPRIETARY),
191 {0}
192 };
193
194 typedef struct Notice_s
195 {
196 int test;
197 int type;
198 int verbose;
199 int ids;
200 Item_t item[ITEMS];
201 Id_t id[IDS];
202 char cc[3];
203 } Notice_t;
204
205 /*
206 * return index given <name,size>
207 */
208
209 static int
lookup(register const Item_t * item,const char * name,int size)210 lookup(register const Item_t* item, const char* name, int size)
211 {
212 register int c;
213 register int i;
214
215 c = name[0];
216 for (i = 0; item[i].data; i++)
217 if (c == item[i].data[0] && size == item[i].size && !strncmp(name, item[i].data, size))
218 return i;
219 return -1;
220 }
221
222 /*
223 * copy s of size n to b
224 * n<0 means 0 terminated string
225 */
226
227 static void
copy(register Buffer_t * b,register char * s,int n)228 copy(register Buffer_t* b, register char* s, int n)
229 {
230 if (n < 0)
231 n = strlen(s);
232 while (n--)
233 PUT(b, *s++);
234 }
235
236 /*
237 * center and copy comment line s to p
238 * if s==0 then
239 * n>0 first frame line
240 * n=0 blank line
241 * n<0 last frame line
242 * if u>0 then s converted to upper case
243 * if u<0 then s is left justified
244 */
245
246 static void
comment(Notice_t * notice,register Buffer_t * b,register char * s,register int n,int u)247 comment(Notice_t* notice, register Buffer_t* b, register char* s, register int n, int u)
248 {
249 register int i;
250 register int m;
251 register int x;
252 int cc;
253
254 cc = notice->cc[1];
255 if (!s)
256 {
257 if (n)
258 {
259 PUT(b, notice->cc[n > 0 ? 0 : 1]);
260 for (i = 0; i < COMDATA; i++)
261 PUT(b, cc);
262 PUT(b, notice->cc[n > 0 ? 1 : 2]);
263 }
264 else
265 s = "";
266 }
267 if (s)
268 {
269 if (n > COMDATA)
270 n = COMDATA;
271 PUT(b, cc);
272 m = (u < 0) ? 1 : (COMDATA - n) / 2;
273 if ((x = COMDATA - m - n) < 0)
274 n--;
275 while (m-- > 0)
276 PUT(b, ' ');
277 while (n-- > 0)
278 {
279 i = *s++;
280 if (u > 0 && i >= 'a' && i <= 'z')
281 i = i - 'a' + 'A';
282 PUT(b, i);
283 }
284 while (x-- > 0)
285 PUT(b, ' ');
286 PUT(b, cc);
287 }
288 PUT(b, '\n');
289 }
290
291 /*
292 * expand simple ${...}
293 */
294
295 static void
expand(Notice_t * notice,register Buffer_t * b,const Item_t * item)296 expand(Notice_t* notice, register Buffer_t* b, const Item_t* item)
297 {
298 register char* t;
299 register char* e;
300 register int q;
301 register char* x;
302 register char* z;
303 register int c;
304 int m;
305 int i;
306 int k;
307
308 if (t = item->data)
309 {
310 q = item->quote;
311 e = t + item->size;
312 i = 0;
313 while (t < e)
314 {
315 if (*t == '$' && t < (e + 2) && *(t + 1) == '{')
316 {
317 k = m = 0;
318 x = t += 2;
319 while (t < e && (c = *t++) != '}')
320 if (c == '.')
321 x = t;
322 else if (c == '-')
323 {
324 k = 1;
325 break;
326 }
327 else if (c == '/')
328 {
329 m = 1;
330 break;
331 }
332 if ((c = lookup(key, x, t - x - 1)) >= 0 && (x = notice->item[c].data))
333 {
334 z = x + notice->item[c].size;
335 while (x < z)
336 {
337 c = *x++;
338 if (!m || c >= '0' && c <= '9')
339 PUT(b, c);
340 }
341 }
342 else if (k)
343 {
344 k = 0;
345 i++;
346 }
347 if (k || m)
348 {
349 k = 1;
350 while (t < e)
351 if ((c = *t++) == '{')
352 k++;
353 else if (c == '}' && !--k)
354 break;
355 }
356 }
357 else if (q > 0 && *t == '\\' && (*(t + 1) == q || *(t + 1) == '\\'))
358 t++;
359 else if (*t == '}' && i)
360 {
361 t++;
362 i--;
363 }
364 else
365 PUT(b, *t++);
366 }
367 }
368 }
369
370 /*
371 * generate a copright notice
372 */
373
374 static void
copyright(Notice_t * notice,register Buffer_t * b)375 copyright(Notice_t* notice, register Buffer_t* b)
376 {
377 register char* x;
378 register char* t;
379 time_t clock;
380
381 copy(b, "Copyright (c) ", -1);
382 if (notice->test)
383 {
384 clock = (time_t)1000212300;
385 t = ctime(&clock) + 20;
386 }
387 else if (!(t = notice->item[SOURCE].data))
388 {
389 time(&clock);
390 t = ctime(&clock) + 20;
391 }
392 if ((x = notice->item[START].data) && strncmp(t, x, 4) < 0)
393 t = x;
394 if ((x = notice->item[SINCE].data) && strncmp(x, t, 4) < 0)
395 {
396 expand(notice, b, ¬ice->item[SINCE]);
397 PUT(b, '-');
398 }
399 copy(b, t, 4);
400 if (notice->item[PARENT].data)
401 {
402 PUT(b, ' ');
403 expand(notice, b, ¬ice->item[PARENT]);
404 }
405 if (notice->item[CORPORATION].data)
406 {
407 PUT(b, ' ');
408 expand(notice, b, ¬ice->item[CORPORATION]);
409 if (notice->item[INCORPORATION].data)
410 {
411 PUT(b, ' ');
412 expand(notice, b, ¬ice->item[INCORPORATION]);
413 }
414 }
415 else if (notice->item[COMPANY].data)
416 {
417 PUT(b, ' ');
418 expand(notice, b, ¬ice->item[COMPANY]);
419 }
420 }
421
422 typedef struct Stack_s
423 {
424 char* info;
425 char* file;
426 int line;
427 int size;
428 } Stack_t;
429
430 static int
push(Stack_t * sp,char * file,char * parent,char * info,int size,Buffer_t * buf)431 push(Stack_t* sp, char* file, char* parent, char* info, int size, Buffer_t* buf)
432 {
433 char* s;
434 char* t;
435 int i;
436 int n;
437 char path[1024];
438
439 if (size <= 8)
440 {
441 copy(buf, file, -1);
442 copy(buf, ": no space", -1);
443 PUT(buf, 0);
444 return -1;
445 }
446 if (*file != '/' && parent && (s = strrchr(parent, '/')))
447 {
448 n = s - parent + 1;
449 if ((strlen(file) + n + 1) <= sizeof(path))
450 {
451 memcpy(path, parent, n);
452 strcpy(path + n, file);
453 file = path;
454 }
455 }
456 if ((i = open(file, O_RDONLY|O_cloexec)) < 0)
457 {
458 /* this hack viewpath lookup works for default package setups */
459 if (file == path)
460 for (s = path; *s; s++)
461 if (s[0] == '/' && s[1] == 'a' && s[2] == 'r' && s[3] == 'c' && s[4] == 'h' && s[5] == '/')
462 {
463 t = s;
464 for (s += 6; *s && *s != '/'; s++);
465 while (*t++ = *s++);
466 i = open(file, O_RDONLY|O_cloexec);
467 }
468 if (i < 0)
469 {
470 copy(buf, file, -1);
471 copy(buf, ": cannot open", -1);
472 PUT(buf, 0);
473 return -1;
474 }
475 }
476 n = read(i, info, size - 1);
477 close(i);
478 if (n < 0)
479 {
480 copy(buf, file, -1);
481 copy(buf, ": cannot read", -1);
482 PUT(buf, 0);
483 return -1;
484 }
485 info[n++] = 0;
486 sp->file = file;
487 sp->info = info;
488 sp->line = 0;
489 sp->size = n;
490 return 0;
491 }
492
493 /*
494 * read the license file and generate a comment in p, length size
495 * license length in p returned, -1 on error
496 * -1 return places 0 terminated error string in p
497 */
498
499 int
astlicense(char * p,int size,char * file,char * options,int cc1,int cc2,int cc3)500 astlicense(char* p, int size, char* file, char* options, int cc1, int cc2, int cc3)
501 {
502 register char* s;
503 register char* v;
504 register char* x;
505 register int c;
506 int i;
507 int h;
508 int k;
509 int n;
510 int q;
511 int contributor;
512 int first;
513 int level;
514 int quote;
515 char* data;
516 char tmpbuf[COMLINE];
517 char info[8 * 1024];
518 Stack_t input[4];
519 Notice_t notice;
520 Item_t item;
521 Buffer_t buf;
522 Buffer_t tmp;
523
524 buf.end = (buf.buf = buf.nxt = p) + size;
525 tmp.end = (tmp.buf = tmp.nxt = tmpbuf) + sizeof(tmpbuf);
526 level = 0;
527 data = info;
528 level = -1;
529 if (options)
530 {
531 level++;
532 input[level].file = "<options>";
533 input[level].info = options;
534 input[level].line = 0;
535 }
536 if (file && *file)
537 {
538 if (push(&input[++level], file, 0, data, &info[sizeof(info)] - data, &buf))
539 return -1;
540 data += input[level].size;
541 }
542 if (level < 0)
543 return 0;
544 s = input[level].info;
545 notice.test = 0;
546 notice.type = NONE;
547 notice.verbose = 0;
548 notice.ids = 0;
549 notice.cc[0] = cc1;
550 notice.cc[1] = cc2;
551 notice.cc[2] = cc3;
552 for (i = 0; i < ITEMS; i++)
553 notice.item[i].data = 0;
554 notice.item[STYLE] = notice.item[CLASS] = lic[notice.type];
555 notice.item[STYLE].quote = notice.item[CLASS].quote = 0;
556 contributor = i = k = 0;
557 for (;;)
558 {
559 first = 1;
560 while (c = *s)
561 {
562 while (c == ' ' || c == '\t' || c == '\n' && ++input[level].line || c == '\r' || c == ',' || c == ';' || c == ')')
563 c = *++s;
564 if (!c)
565 break;
566 if (c == '#')
567 {
568 while (*++s && *s != '\n');
569 if (*s)
570 s++;
571 input[level].line++;
572 continue;
573 }
574 if (c == '.')
575 {
576 while ((c = *++s) && (c == ' ' || c == '\t'));
577 file = s;
578 while (c && c != ' ' && c != '\t' && c != '\r' && c != '\n')
579 c = *++s;
580 *s = 0;
581 while (c && c != '\n')
582 c = *++s;
583 if (*file)
584 {
585 input[level].info = s + (c != 0);
586 if (++level >= (sizeof(input) / sizeof(input[0])) || push(&input[level], file, input[level-1].file, data, &info[sizeof(info)] - data, &buf))
587 return -1;
588 data += input[level].size;
589 s = input[level].info;
590 }
591 continue;
592 }
593 if (c == '\n')
594 {
595 s++;
596 input[level].line++;
597 continue;
598 }
599 if (c == '[')
600 c = *++s;
601 x = s;
602 n = 0;
603 while (c && c != '+' && c != '=' && c != ']' && c != ')' && c != ',' && c != ' ' && c != '\t' && c != '\n' && c != '\r')
604 c = *++s;
605 n = s - x;
606 h = lookup(key, x, n);
607 if (c == '+' || c == ']')
608 c = *++s;
609 quote = 0;
610 if (c == '=' || first)
611 {
612 if (c == '=')
613 {
614 q = ((c = *++s) == '"' || c == '\'') ? *s++ : 0;
615 if (c == '(')
616 {
617 s++;
618 if (h == LICENSE)
619 contributor = 0;
620 else if (h == CONTRIBUTOR)
621 contributor = 1;
622 else
623 {
624 q = 1;
625 i = 0;
626 for (;;)
627 {
628 switch (*s++)
629 {
630 case 0:
631 s--;
632 break;
633 case '(':
634 if (!i)
635 q++;
636 continue;
637 case ')':
638 if (!i && !--q)
639 break;
640 continue;
641 case '"':
642 case '\'':
643 if (!i)
644 i = *(s - 1);
645 else if (i == *(s - 1))
646 i = 0;
647 continue;
648 case '\\':
649 if (*s == i && i == '"')
650 i++;
651 continue;
652 case '\n':
653 input[level].line++;
654 continue;
655 default:
656 continue;
657 }
658 break;
659 }
660 }
661 continue;
662 }
663 v = s;
664 while ((c = *s) && (q == '"' && (c == '\\' && (*(s + 1) == '"' || *(s + 1) == '\\') && s++ && (quote = q)) || q && c != q || !q && c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != ',' && c != ';'))
665 {
666 if (c == '\n')
667 input[level].line++;
668 s++;
669 }
670 }
671 else
672 {
673 h = STYLE;
674 v = x;
675 }
676 if (c == '\n')
677 input[level].line++;
678 if (contributor)
679 {
680 for (i = 0; i < notice.ids; i++)
681 if (n == notice.id[i].name.size && !strncmp(x, notice.id[i].name.data, n))
682 break;
683 if (i < IDS)
684 {
685 notice.id[i].name.data = x;
686 notice.id[i].name.size = n;
687 notice.id[i].name.quote = 0;
688 notice.id[i].value.data = v;
689 notice.id[i].value.size = s - v;
690 notice.id[i].value.quote = quote;
691 if (notice.ids <= i)
692 notice.ids = i + 1;
693 }
694 }
695 else if (h == QUERY)
696 {
697 if ((s - v) == 3 && v[0] == 'a' && v[1] == 'l' && v[2] == 'l')
698 {
699 for (i = 0; i < ITEMS; i++)
700 if (notice.item[i].size)
701 {
702 expand(¬ice, &buf, &key[i]);
703 PUT(&buf, '=');
704 for (h = 0;; h++)
705 if (h >= notice.item[i].size)
706 {
707 h = 0;
708 break;
709 }
710 else if (notice.item[i].data[h] == ' ' || notice.item[i].data[h] == '\t')
711 break;
712 if (h)
713 PUT(&buf, '\'');
714 expand(¬ice, &buf, ¬ice.item[i]);
715 if (h)
716 PUT(&buf, '\'');
717 PUT(&buf, '\n');
718 }
719 }
720 else
721 {
722 if ((h = lookup(key, v, s - v)) < 0)
723 {
724 item.data = v;
725 item.size = s - v;
726 item.quote = 0;
727 expand(¬ice, &buf, &item);
728 }
729 else
730 expand(¬ice, &buf, ¬ice.item[h]);
731 PUT(&buf, '\n');
732 }
733 return END(&buf);
734 }
735 else
736 {
737 if (h == STYLE)
738 switch (c = lookup(lic, v, s - v))
739 {
740 case NONE:
741 return 0;
742 case TEST:
743 notice.test = 1;
744 h = -1;
745 break;
746 case VERBOSE:
747 notice.verbose = 1;
748 h = -1;
749 break;
750 case USAGE:
751 notice.type = c;
752 h = -1;
753 break;
754 case -1:
755 c = SPECIAL;
756 /*FALLTHROUGH*/
757 default:
758 notice.type = c;
759 notice.item[CLASS].data = lic[lic[c].quote].data;
760 notice.item[CLASS].size = lic[lic[c].quote].size;
761 if (notice.item[STYLE].data != lic[NONE].data)
762 h = -1;
763 break;
764 }
765 if (h >= 0)
766 {
767 notice.item[h].data = (notice.item[h].size = s - v) ? v : (char*)0;
768 notice.item[h].quote = quote;
769 k = 1;
770 }
771 }
772 }
773 else
774 {
775 if (input[level].file)
776 {
777 copy(&buf, "\"", -1);
778 copy(&buf, input[level].file, -1);
779 copy(&buf, "\", line ", -1);
780 x = &tmpbuf[sizeof(tmpbuf)];
781 *--x = 0;
782 n = ++input[level].line;
783 do *--x = ("0123456789")[n % 10]; while (n /= 10);
784 copy(&buf, x, -1);
785 copy(&buf, ": ", -1);
786 }
787 copy(&buf, "option error: assignment expected", -1);
788 PUT(&buf, 0);
789 return -1;
790 }
791 if (*s)
792 s++;
793 first = 0;
794 }
795 if (!level--)
796 break;
797 s = input[level].info;
798 }
799 if (!k)
800 return 0;
801 if (notice.type == INLINE && (!notice.verbose || !notice.item[NOTICE].data))
802 return 0;
803 if (notice.type != USAGE)
804 {
805 if (!notice.type)
806 notice.type = SPECIAL;
807 comment(¬ice, &buf, NiL, 1, 0);
808 comment(¬ice, &buf, NiL, 0, 0);
809 if (notice.item[PACKAGE].data)
810 {
811 copy(&tmp, "This software is part of the ", -1);
812 expand(¬ice, &tmp, ¬ice.item[PACKAGE]);
813 copy(&tmp, " package", -1);
814 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
815 }
816 if (notice.type >= OPEN)
817 {
818 copyright(¬ice, &tmp);
819 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
820 if (notice.type >= SPECIAL)
821 COMMENT(¬ice, &buf, "All Rights Reserved", 0);
822 }
823 if (notice.type == CPL || notice.type == EPL)
824 {
825 copy(&tmp, notice.item[PACKAGE].data ? "and" : "This software", -1);
826 copy(&tmp, " is licensed under the", -1);
827 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
828 if (notice.type == EPL)
829 copy(&tmp, "Eclipse Public License", -1);
830 else
831 copy(&tmp, "Common Public License", -1);
832 if (notice.item[VERSION].data)
833 {
834 copy(&tmp, ", Version ", -1);
835 expand(¬ice, &tmp, ¬ice.item[VERSION]);
836 }
837 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
838 if (notice.item[CORPORATION].data || notice.item[COMPANY].data)
839 {
840 copy(&tmp, "by ", -1);
841 if (notice.item[PARENT].data)
842 {
843 expand(¬ice, &tmp, ¬ice.item[PARENT]);
844 copy(&tmp, " ", -1);
845 }
846 if (notice.item[CORPORATION].data)
847 {
848 expand(¬ice, &tmp, ¬ice.item[CORPORATION]);
849 if (notice.item[INCORPORATION].data)
850 {
851 copy(&tmp, " ", -1);
852 expand(¬ice, &tmp, ¬ice.item[INCORPORATION]);
853 }
854 }
855 else if (notice.item[COMPANY].data)
856 expand(¬ice, &tmp, ¬ice.item[COMPANY]);
857 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
858 }
859 comment(¬ice, &buf, NiL, 0, 0);
860 COMMENT(¬ice, &buf, "A copy of the License is available at", 0);
861 if (notice.item[URL].data)
862 {
863 expand(¬ice, &tmp, ¬ice.item[URL]);
864 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
865 if (notice.item[URLMD5].data)
866 {
867 copy(&tmp, "(with md5 checksum ", -1);
868 expand(¬ice, &tmp, ¬ice.item[URLMD5]);
869 copy(&tmp, ")", -1);
870 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
871 }
872 }
873 else if (notice.type == EPL)
874 COMMENT(¬ice, &buf, "http://www.eclipse.org/org/documents/epl-v10.html", 0);
875 else
876 COMMENT(¬ice, &buf, "http://www.opensource.org/licenses/cpl", 0);
877 comment(¬ice, &buf, NiL, 0, 0);
878 }
879 else if (notice.type == OPEN)
880 {
881 copy(&tmp, notice.item[PACKAGE].data ? "and it" : "This software", -1);
882 copy(&tmp, " may only be used by you under license from", -1);
883 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
884 if (notice.item[i = CORPORATION].data)
885 {
886 if (notice.item[PARENT].data)
887 {
888 expand(¬ice, &tmp, ¬ice.item[i = PARENT]);
889 copy(&tmp, " ", -1);
890 }
891 expand(¬ice, &tmp, ¬ice.item[CORPORATION]);
892 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
893 }
894 else if (notice.item[i = COMPANY].data)
895 {
896 if (notice.item[PARENT].data)
897 {
898 expand(¬ice, &tmp, ¬ice.item[i = PARENT]);
899 copy(&tmp, " ", -1);
900 }
901 expand(¬ice, &tmp, ¬ice.item[COMPANY]);
902 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
903 }
904 else
905 i = -1;
906 if (notice.item[URL].data)
907 {
908 COMMENT(¬ice, &buf, "A copy of the Source Code Agreement is available", 0);
909 copy(&tmp, "at the ", -1);
910 if (i >= 0)
911 expand(¬ice, &tmp, ¬ice.item[i]);
912 copy(&tmp, " Internet web site URL", -1);
913 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
914 comment(¬ice, &buf, NiL, 0, 0);
915 expand(¬ice, &tmp, ¬ice.item[URL]);
916 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
917 if (notice.item[URLMD5].data)
918 {
919 copy(&tmp, "(with an md5 checksum of ", -1);
920 expand(¬ice, &tmp, ¬ice.item[URLMD5]);
921 copy(&tmp, ")", -1);
922 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
923 }
924 comment(¬ice, &buf, NiL, 0, 0);
925 }
926 COMMENT(¬ice, &buf, "If you have copied or used this software without agreeing", 0);
927 COMMENT(¬ice, &buf, "to the terms of the license you are infringing on", 0);
928 COMMENT(¬ice, &buf, "the license and copyright and are violating", 0);
929 if (i >= 0)
930 expand(¬ice, &tmp, ¬ice.item[i]);
931 copy(&tmp, "'s", -1);
932 if (n >= COMLONG)
933 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
934 else
935 PUT(&tmp, ' ');
936 copy(&tmp, "intellectual property rights.", -1);
937 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
938 comment(¬ice, &buf, NiL, 0, 0);
939 }
940 else if (notice.type == GPL)
941 {
942 comment(¬ice, &buf, NiL, 0, 0);
943 COMMENT(¬ice, &buf, "This is free software; you can redistribute it and/or", 0);
944 COMMENT(¬ice, &buf, "modify it under the terms of the GNU General Public License", 0);
945 COMMENT(¬ice, &buf, "as published by the Free Software Foundation;", 0);
946 COMMENT(¬ice, &buf, "either version 2, or (at your option) any later version.", 0);
947 comment(¬ice, &buf, NiL, 0, 0);
948 COMMENT(¬ice, &buf, "This software is distributed in the hope that it", 0);
949 COMMENT(¬ice, &buf, "will be useful, but WITHOUT ANY WARRANTY;", 0);
950 COMMENT(¬ice, &buf, "without even the implied warranty of MERCHANTABILITY", 0);
951 COMMENT(¬ice, &buf, "or FITNESS FOR A PARTICULAR PURPOSE.", 0);
952 COMMENT(¬ice, &buf, "See the GNU General Public License for more details.", 0);
953 comment(¬ice, &buf, NiL, 0, 0);
954 COMMENT(¬ice, &buf, "You should have received a copy of the", 0);
955 COMMENT(¬ice, &buf, "GNU General Public License", 0);
956 COMMENT(¬ice, &buf, "along with this software (see the file COPYING.)", 0);
957 COMMENT(¬ice, &buf, "If not, a copy is available at", 0);
958 COMMENT(¬ice, &buf, "http://www.gnu.org/copyleft/gpl.html", 0);
959 comment(¬ice, &buf, NiL, 0, 0);
960 }
961 else if (notice.type == BSD)
962 {
963 comment(¬ice, &buf, NiL, 0, 0);
964 COMMENT(¬ice, &buf, "Redistribution and use in source and binary forms, with or", -1);
965 COMMENT(¬ice, &buf, "without modification, are permitted provided that the following", -1);
966 COMMENT(¬ice, &buf, "conditions are met:", -1);
967 comment(¬ice, &buf, NiL, 0, 0);
968 COMMENT(¬ice, &buf, " 1. Redistributions of source code must retain the above", -1);
969 COMMENT(¬ice, &buf, " copyright notice, this list of conditions and the", -1);
970 COMMENT(¬ice, &buf, " following disclaimer.", -1);
971 comment(¬ice, &buf, NiL, 0, 0);
972 COMMENT(¬ice, &buf, " 2. Redistributions in binary form must reproduce the above", -1);
973 COMMENT(¬ice, &buf, " copyright notice, this list of conditions and the", -1);
974 COMMENT(¬ice, &buf, " following disclaimer in the documentation and/or other", -1);
975 COMMENT(¬ice, &buf, " materials provided with the distribution.", -1);
976 comment(¬ice, &buf, NiL, 0, 0);
977 copy(&tmp, " 3. Neither the name of ", -1);
978 if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data || notice.item[i = COMPANY].data)
979 expand(¬ice, &tmp, ¬ice.item[i]);
980 else
981 copy(&tmp, "the copyright holder", -1);
982 copy(&tmp, " nor the", -1);
983 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), -1);
984 COMMENT(¬ice, &buf, " names of its contributors may be used to endorse or", -1);
985 COMMENT(¬ice, &buf, " promote products derived from this software without", -1);
986 COMMENT(¬ice, &buf, " specific prior written permission.", -1);
987 comment(¬ice, &buf, NiL, 0, 0);
988 COMMENT(¬ice, &buf, "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND", -1);
989 COMMENT(¬ice, &buf, "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,", -1);
990 COMMENT(¬ice, &buf, "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF", -1);
991 COMMENT(¬ice, &buf, "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE", -1);
992 COMMENT(¬ice, &buf, "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS", -1);
993 COMMENT(¬ice, &buf, "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,", -1);
994 COMMENT(¬ice, &buf, "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED", -1);
995 COMMENT(¬ice, &buf, "TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,", -1);
996 COMMENT(¬ice, &buf, "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON", -1);
997 COMMENT(¬ice, &buf, "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,", -1);
998 COMMENT(¬ice, &buf, "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY", -1);
999 COMMENT(¬ice, &buf, "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE", -1);
1000 COMMENT(¬ice, &buf, "POSSIBILITY OF SUCH DAMAGE.", -1);
1001 comment(¬ice, &buf, NiL, 0, 0);
1002 }
1003 else if (notice.type == ZLIB)
1004 {
1005 comment(¬ice, &buf, NiL, 0, 0);
1006 COMMENT(¬ice, &buf, "This software is provided 'as-is', without any express or implied", -1);
1007 COMMENT(¬ice, &buf, "warranty. In no event will the authors be held liable for any", -1);
1008 COMMENT(¬ice, &buf, "damages arising from the use of this software.", -1);
1009 comment(¬ice, &buf, NiL, 0, 0);
1010 COMMENT(¬ice, &buf, "Permission is granted to anyone to use this software for any", -1);
1011 COMMENT(¬ice, &buf, "purpose, including commercial applications, and to alter it and", -1);
1012 COMMENT(¬ice, &buf, "redistribute it freely, subject to the following restrictions:", -1);
1013 comment(¬ice, &buf, NiL, 0, 0);
1014 COMMENT(¬ice, &buf, " 1. The origin of this software must not be misrepresented;", -1);
1015 COMMENT(¬ice, &buf, " you must not claim that you wrote the original software. If", -1);
1016 COMMENT(¬ice, &buf, " you use this software in a product, an acknowledgment in the", -1);
1017 COMMENT(¬ice, &buf, " product documentation would be appreciated but is not", -1);
1018 COMMENT(¬ice, &buf, " required.", -1);
1019 comment(¬ice, &buf, NiL, 0, 0);
1020 COMMENT(¬ice, &buf, " 2. Altered source versions must be plainly marked as such,", -1);
1021 COMMENT(¬ice, &buf, " and must not be misrepresented as being the original", -1);
1022 COMMENT(¬ice, &buf, " software.", -1);
1023 comment(¬ice, &buf, NiL, 0, 0);
1024 COMMENT(¬ice, &buf, " 3. This notice may not be removed or altered from any source", -1);
1025 COMMENT(¬ice, &buf, " distribution.", -1);
1026 comment(¬ice, &buf, NiL, 0, 0);
1027 }
1028 else if (notice.type == MIT)
1029 {
1030 comment(¬ice, &buf, NiL, 0, 0);
1031 COMMENT(¬ice, &buf, "Permission is hereby granted, free of charge, to any person", 0);
1032 COMMENT(¬ice, &buf, "obtaining a copy of this software and associated", 0);
1033 COMMENT(¬ice, &buf, "documentation files (the \"Software\"), to deal in the", 0);
1034 COMMENT(¬ice, &buf, "Software without restriction, including without limitation", 0);
1035 COMMENT(¬ice, &buf, "the rights to use, copy, modify, merge, publish, distribute,", 0);
1036 COMMENT(¬ice, &buf, "sublicense, and/or sell copies of the Software, and to", 0);
1037 COMMENT(¬ice, &buf, "permit persons to whom the Software is furnished to do so,", 0);
1038 COMMENT(¬ice, &buf, "subject to the following conditions:", 0);
1039 comment(¬ice, &buf, NiL, 0, 0);
1040 COMMENT(¬ice, &buf, "The above copyright notice and this permission notice shall", 0);
1041 COMMENT(¬ice, &buf, "be included in all copies or substantial portions of the", 0);
1042 COMMENT(¬ice, &buf, "Software.", 0);
1043 comment(¬ice, &buf, NiL, 0, 0);
1044 COMMENT(¬ice, &buf, "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY", 0);
1045 COMMENT(¬ice, &buf, "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE", 0);
1046 COMMENT(¬ice, &buf, "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR", 0);
1047 COMMENT(¬ice, &buf, "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS", 0);
1048 COMMENT(¬ice, &buf, "OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR", 0);
1049 COMMENT(¬ice, &buf, "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR", 0);
1050 COMMENT(¬ice, &buf, "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE", 0);
1051 COMMENT(¬ice, &buf, "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", 0);
1052 comment(¬ice, &buf, NiL, 0, 0);
1053 }
1054 else
1055 {
1056 if (notice.type == PROPRIETARY)
1057 {
1058 if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data || notice.item[i = COMPANY].data)
1059 {
1060 expand(¬ice, &tmp, ¬ice.item[i]);
1061 copy(&tmp, " - ", -1);
1062 }
1063 else
1064 i = -1;
1065 copy(&tmp, "Proprietary", -1);
1066 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1);
1067 comment(¬ice, &buf, NiL, 0, 0);
1068 if (notice.item[URL].data)
1069 {
1070 copy(&tmp, "This is proprietary source code", -1);
1071 if (i >= 0)
1072 copy(&tmp, " licensed by", -1);
1073 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1);
1074 if (notice.item[PARENT].data)
1075 {
1076 expand(¬ice, &tmp, ¬ice.item[PARENT]);
1077 copy(&tmp, " ", -1);
1078 }
1079 if (notice.item[CORPORATION].data)
1080 {
1081 expand(¬ice, &tmp, ¬ice.item[CORPORATION]);
1082 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1);
1083 }
1084 else if (notice.item[COMPANY].data)
1085 {
1086 expand(¬ice, &tmp, ¬ice.item[COMPANY]);
1087 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1);
1088 }
1089 }
1090 else
1091 {
1092 copy(&tmp, "This is unpublished proprietary source code", -1);
1093 if (i >= 0)
1094 copy(&tmp, " of", -1);
1095 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1);
1096 if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data)
1097 expand(¬ice, &tmp, ¬ice.item[i]);
1098 if (notice.item[COMPANY].data)
1099 {
1100 if (SIZ(&tmp))
1101 PUT(&tmp, ' ');
1102 expand(¬ice, &tmp, ¬ice.item[COMPANY]);
1103 }
1104 if (SIZ(&tmp))
1105 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 1);
1106 COMMENT(¬ice, &buf, "and is not to be disclosed or used except in", 1);
1107 COMMENT(¬ice, &buf, "accordance with applicable agreements", 1);
1108 }
1109 comment(¬ice, &buf, NiL, 0, 0);
1110 }
1111 else if (notice.type == NONEXCLUSIVE)
1112 {
1113 COMMENT(¬ice, &buf, "For nonexclusive individual use", 1);
1114 comment(¬ice, &buf, NiL, 0, 0);
1115 }
1116 else if (notice.type == NONCOMMERCIAL)
1117 {
1118 COMMENT(¬ice, &buf, "For noncommercial use", 1);
1119 comment(¬ice, &buf, NiL, 0, 0);
1120 }
1121 if (notice.type >= PROPRIETARY && !notice.item[URL].data)
1122 {
1123 COMMENT(¬ice, &buf, "Unpublished & Not for Publication", 0);
1124 comment(¬ice, &buf, NiL, 0, 0);
1125 }
1126 if (notice.item[URL].data)
1127 {
1128 copy(&tmp, "This software is licensed", -1);
1129 if (notice.item[CORPORATION].data || notice.item[COMPANY].data)
1130 {
1131 copy(&tmp, " by", -1);
1132 if ((notice.item[PARENT].size + (notice.item[CORPORATION].data ? (notice.item[CORPORATION].size + notice.item[INCORPORATION].size) : notice.item[COMPANY].size)) >= (COMLONG - 6))
1133 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
1134 else
1135 PUT(&tmp, ' ');
1136 if (notice.item[PARENT].data)
1137 {
1138 expand(¬ice, &tmp, ¬ice.item[PARENT]);
1139 copy(&tmp, " ", -1);
1140 }
1141 if (notice.item[CORPORATION].data)
1142 {
1143 expand(¬ice, &tmp, ¬ice.item[CORPORATION]);
1144 if (notice.item[INCORPORATION].data)
1145 {
1146 copy(&tmp, " ", -1);
1147 expand(¬ice, &tmp, ¬ice.item[INCORPORATION]);
1148 }
1149 }
1150 else if (notice.item[COMPANY].data)
1151 expand(¬ice, &tmp, ¬ice.item[COMPANY]);
1152 }
1153 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
1154 COMMENT(¬ice, &buf, "under the terms and conditions of the license in", 0);
1155 expand(¬ice, &tmp, ¬ice.item[URL]);
1156 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
1157 if (notice.item[URLMD5].data)
1158 {
1159 copy(&tmp, "(with an md5 checksum of ", -1);
1160 expand(¬ice, &tmp, ¬ice.item[URLMD5]);
1161 copy(&tmp, ")", -1);
1162 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
1163 }
1164 comment(¬ice, &buf, NiL, 0, 0);
1165 }
1166 else if (notice.type == PROPRIETARY)
1167 {
1168 COMMENT(¬ice, &buf, "The copyright notice above does not evidence any", 0);
1169 COMMENT(¬ice, &buf, "actual or intended publication of such source code", 0);
1170 comment(¬ice, &buf, NiL, 0, 0);
1171 }
1172 }
1173 if (v = notice.item[NOTICE].data)
1174 {
1175 x = v + notice.item[NOTICE].size;
1176 if (*v == '\n')
1177 v++;
1178 item.quote = notice.item[NOTICE].quote;
1179 do
1180 {
1181 for (item.data = v; v < x && *v != '\n'; v++);
1182 if ((item.size = v - item.data) && *item.data == '\t')
1183 {
1184 item.data++;
1185 item.size--;
1186 h = 0;
1187 }
1188 else
1189 h = -1;
1190 expand(¬ice, &tmp, &item);
1191 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), h);
1192 } while (v++ < x);
1193 if (item.size)
1194 comment(¬ice, &buf, NiL, 0, 0);
1195 }
1196 if (notice.item[ORGANIZATION].data)
1197 {
1198 expand(¬ice, &tmp, ¬ice.item[ORGANIZATION]);
1199 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
1200 if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data)
1201 expand(¬ice, &tmp, ¬ice.item[i]);
1202 if (notice.item[COMPANY].data)
1203 {
1204 if (SIZ(&tmp))
1205 PUT(&tmp, ' ');
1206 expand(¬ice, &tmp, ¬ice.item[COMPANY]);
1207 }
1208 if (SIZ(&tmp))
1209 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
1210 if (notice.item[LOCATION].data)
1211 {
1212 expand(¬ice, &tmp, ¬ice.item[LOCATION]);
1213 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
1214 }
1215 comment(¬ice, &buf, NiL, 0, 0);
1216 }
1217 }
1218 if (v = notice.item[AUTHOR].data)
1219 {
1220 x = v + notice.item[AUTHOR].size;
1221 q = (x - v) == 1 && (*v == '*' || *v == '-');
1222 k = q && notice.type != USAGE ? -1 : 0;
1223 for (;;)
1224 {
1225 if (!q)
1226 {
1227 while (v < x && (*v == ' ' || *v == '\t' || *v == '\r' || *v == '\n' || *v == ',' || *v == '+'))
1228 v++;
1229 if (v >= x)
1230 break;
1231 item.data = v;
1232 while (v < x && *v != ',' && *v != '+' && *v++ != '>');
1233 item.size = v - item.data;
1234 item.quote = notice.item[AUTHOR].quote;
1235 }
1236 h = 0;
1237 for (i = 0; i < notice.ids; i++)
1238 if (q || item.size == notice.id[i].name.size && !strncmp(item.data, notice.id[i].name.data, item.size))
1239 {
1240 h = 1;
1241 if (notice.type == USAGE)
1242 {
1243 copy(&buf, "[-author?", -1);
1244 expand(¬ice, &buf, ¬ice.id[i].value);
1245 PUT(&buf, ']');
1246 }
1247 else
1248 {
1249 if (k < 0)
1250 {
1251 COMMENT(¬ice, &buf, "CONTRIBUTORS", 0);
1252 comment(¬ice, &buf, NiL, 0, 0);
1253 }
1254 k = 1;
1255 expand(¬ice, &tmp, ¬ice.id[i].value);
1256 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
1257 }
1258 if (!q)
1259 break;
1260 }
1261 if (q)
1262 break;
1263 if (!h)
1264 {
1265 if (notice.type == USAGE)
1266 {
1267 copy(&buf, "[-author?", -1);
1268 expand(¬ice, &buf, &item);
1269 PUT(&buf, ']');
1270 }
1271 else
1272 {
1273 if (k < 0)
1274 {
1275 COMMENT(¬ice, &buf, "CONTRIBUTORS", 0);
1276 comment(¬ice, &buf, NiL, 0, 0);
1277 }
1278 k = 1;
1279 expand(¬ice, &tmp, &item);
1280 comment(¬ice, &buf, BUF(&tmp), USE(&tmp), 0);
1281 }
1282 }
1283 }
1284 if (k > 0)
1285 comment(¬ice, &buf, NiL, 0, 0);
1286 }
1287 if (notice.type == USAGE)
1288 {
1289 copy(&buf, "[-copyright?", -1);
1290 copyright(¬ice, &buf);
1291 PUT(&buf, ']');
1292 if (notice.item[URL].data)
1293 {
1294 copy(&buf, "[-license?", -1);
1295 expand(¬ice, &buf, ¬ice.item[URL]);
1296 PUT(&buf, ']');
1297 }
1298 PUT(&buf, '\n');
1299 }
1300 else
1301 comment(¬ice, &buf, NiL, -1, 0);
1302 return END(&buf);
1303 }
1304