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, &notice->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, &notice->item[PARENT]);
404 	}
405 	if (notice->item[CORPORATION].data)
406 	{
407 		PUT(b, ' ');
408 		expand(notice, b, &notice->item[CORPORATION]);
409 		if (notice->item[INCORPORATION].data)
410 		{
411 			PUT(b, ' ');
412 			expand(notice, b, &notice->item[INCORPORATION]);
413 		}
414 	}
415 	else if (notice->item[COMPANY].data)
416 	{
417 		PUT(b, ' ');
418 		expand(notice, b, &notice->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(&notice, &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(&notice, &buf, &notice.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(&notice, &buf, &item);
728 						}
729 						else
730 							expand(&notice, &buf, &notice.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(&notice, &buf, NiL, 1, 0);
808 		comment(&notice, &buf, NiL, 0, 0);
809 		if (notice.item[PACKAGE].data)
810 		{
811 			copy(&tmp, "This software is part of the ", -1);
812 			expand(&notice, &tmp, &notice.item[PACKAGE]);
813 			copy(&tmp, " package", -1);
814 			comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
815 		}
816 		if (notice.type >= OPEN)
817 		{
818 			copyright(&notice, &tmp);
819 			comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
820 			if (notice.type >= SPECIAL)
821 				COMMENT(&notice, &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(&notice, &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(&notice, &tmp, &notice.item[VERSION]);
836 			}
837 			comment(&notice, &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(&notice, &tmp, &notice.item[PARENT]);
844 					copy(&tmp, " ", -1);
845 				}
846 				if (notice.item[CORPORATION].data)
847 				{
848 					expand(&notice, &tmp, &notice.item[CORPORATION]);
849 					if (notice.item[INCORPORATION].data)
850 					{
851 						copy(&tmp, " ", -1);
852 						expand(&notice, &tmp, &notice.item[INCORPORATION]);
853 					}
854 				}
855 				else if (notice.item[COMPANY].data)
856 					expand(&notice, &tmp, &notice.item[COMPANY]);
857 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
858 			}
859 			comment(&notice, &buf, NiL, 0, 0);
860 			COMMENT(&notice, &buf, "A copy of the License is available at", 0);
861 			if (notice.item[URL].data)
862 			{
863 				expand(&notice, &tmp, &notice.item[URL]);
864 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
865 				if (notice.item[URLMD5].data)
866 				{
867 					copy(&tmp, "(with md5 checksum ", -1);
868 					expand(&notice, &tmp, &notice.item[URLMD5]);
869 					copy(&tmp, ")", -1);
870 					comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
871 				}
872 			}
873 			else if (notice.type == EPL)
874 				COMMENT(&notice, &buf, "http://www.eclipse.org/org/documents/epl-v10.html", 0);
875 			else
876 				COMMENT(&notice, &buf, "http://www.opensource.org/licenses/cpl", 0);
877 			comment(&notice, &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(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
884 			if (notice.item[i = CORPORATION].data)
885 			{
886 				if (notice.item[PARENT].data)
887 				{
888 					expand(&notice, &tmp, &notice.item[i = PARENT]);
889 					copy(&tmp, " ", -1);
890 				}
891 				expand(&notice, &tmp, &notice.item[CORPORATION]);
892 				comment(&notice, &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(&notice, &tmp, &notice.item[i = PARENT]);
899 					copy(&tmp, " ", -1);
900 				}
901 				expand(&notice, &tmp, &notice.item[COMPANY]);
902 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
903 			}
904 			else
905 				i = -1;
906 			if (notice.item[URL].data)
907 			{
908 				COMMENT(&notice, &buf, "A copy of the Source Code Agreement is available", 0);
909 				copy(&tmp, "at the ", -1);
910 				if (i >= 0)
911 					expand(&notice, &tmp, &notice.item[i]);
912 				copy(&tmp, " Internet web site URL", -1);
913 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
914 				comment(&notice, &buf, NiL, 0, 0);
915 				expand(&notice, &tmp, &notice.item[URL]);
916 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
917 				if (notice.item[URLMD5].data)
918 				{
919 					copy(&tmp, "(with an md5 checksum of ", -1);
920 					expand(&notice, &tmp, &notice.item[URLMD5]);
921 					copy(&tmp, ")", -1);
922 					comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
923 				}
924 				comment(&notice, &buf, NiL, 0, 0);
925 			}
926 			COMMENT(&notice, &buf, "If you have copied or used this software without agreeing", 0);
927 			COMMENT(&notice, &buf, "to the terms of the license you are infringing on", 0);
928 			COMMENT(&notice, &buf, "the license and copyright and are violating", 0);
929 			if (i >= 0)
930 				expand(&notice, &tmp, &notice.item[i]);
931 			copy(&tmp, "'s", -1);
932 			if (n >= COMLONG)
933 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
934 			else
935 				PUT(&tmp, ' ');
936 			copy(&tmp, "intellectual property rights.", -1);
937 			comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
938 			comment(&notice, &buf, NiL, 0, 0);
939 		}
940 		else if (notice.type == GPL)
941 		{
942 			comment(&notice, &buf, NiL, 0, 0);
943 			COMMENT(&notice, &buf, "This is free software; you can redistribute it and/or", 0);
944 			COMMENT(&notice, &buf, "modify it under the terms of the GNU General Public License", 0);
945 			COMMENT(&notice, &buf, "as published by the Free Software Foundation;", 0);
946 			COMMENT(&notice, &buf, "either version 2, or (at your option) any later version.", 0);
947 			comment(&notice, &buf, NiL, 0, 0);
948 			COMMENT(&notice, &buf, "This software is distributed in the hope that it", 0);
949 			COMMENT(&notice, &buf, "will be useful, but WITHOUT ANY WARRANTY;", 0);
950 			COMMENT(&notice, &buf, "without even the implied warranty of MERCHANTABILITY", 0);
951 			COMMENT(&notice, &buf, "or FITNESS FOR A PARTICULAR PURPOSE.", 0);
952 			COMMENT(&notice, &buf, "See the GNU General Public License for more details.", 0);
953 			comment(&notice, &buf, NiL, 0, 0);
954 			COMMENT(&notice, &buf, "You should have received a copy of the", 0);
955 			COMMENT(&notice, &buf, "GNU General Public License", 0);
956 			COMMENT(&notice, &buf, "along with this software (see the file COPYING.)", 0);
957 			COMMENT(&notice, &buf, "If not, a copy is available at", 0);
958 			COMMENT(&notice, &buf, "http://www.gnu.org/copyleft/gpl.html", 0);
959 			comment(&notice, &buf, NiL, 0, 0);
960 		}
961 		else if (notice.type == BSD)
962 		{
963 			comment(&notice, &buf, NiL, 0, 0);
964 			COMMENT(&notice, &buf, "Redistribution and use in source and binary forms, with or", -1);
965 			COMMENT(&notice, &buf, "without modification, are permitted provided that the following", -1);
966 			COMMENT(&notice, &buf, "conditions are met:", -1);
967 			comment(&notice, &buf, NiL, 0, 0);
968 			COMMENT(&notice, &buf, "   1. Redistributions of source code must retain the above", -1);
969 			COMMENT(&notice, &buf, "      copyright notice, this list of conditions and the", -1);
970 			COMMENT(&notice, &buf, "      following disclaimer.", -1);
971 			comment(&notice, &buf, NiL, 0, 0);
972 			COMMENT(&notice, &buf, "   2. Redistributions in binary form must reproduce the above", -1);
973 			COMMENT(&notice, &buf, "      copyright notice, this list of conditions and the", -1);
974 			COMMENT(&notice, &buf, "      following disclaimer in the documentation and/or other", -1);
975 			COMMENT(&notice, &buf, "      materials provided with the distribution.", -1);
976 			comment(&notice, &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(&notice, &tmp, &notice.item[i]);
980 			else
981 				copy(&tmp, "the copyright holder", -1);
982 			copy(&tmp, " nor the", -1);
983 			comment(&notice, &buf, BUF(&tmp), USE(&tmp), -1);
984 			COMMENT(&notice, &buf, "      names of its contributors may be used to endorse or", -1);
985 			COMMENT(&notice, &buf, "      promote products derived from this software without", -1);
986 			COMMENT(&notice, &buf, "      specific prior written permission.", -1);
987 			comment(&notice, &buf, NiL, 0, 0);
988 			COMMENT(&notice, &buf, "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND", -1);
989 			COMMENT(&notice, &buf, "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,", -1);
990 			COMMENT(&notice, &buf, "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF", -1);
991 			COMMENT(&notice, &buf, "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE", -1);
992 			COMMENT(&notice, &buf, "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS", -1);
993 			COMMENT(&notice, &buf, "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,", -1);
994 			COMMENT(&notice, &buf, "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED", -1);
995 			COMMENT(&notice, &buf, "TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,", -1);
996 			COMMENT(&notice, &buf, "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON", -1);
997 			COMMENT(&notice, &buf, "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,", -1);
998 			COMMENT(&notice, &buf, "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY", -1);
999 			COMMENT(&notice, &buf, "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE", -1);
1000 			COMMENT(&notice, &buf, "POSSIBILITY OF SUCH DAMAGE.", -1);
1001 			comment(&notice, &buf, NiL, 0, 0);
1002 		}
1003 		else if (notice.type == ZLIB)
1004 		{
1005 			comment(&notice, &buf, NiL, 0, 0);
1006 			COMMENT(&notice, &buf, "This software is provided 'as-is', without any express or implied", -1);
1007 			COMMENT(&notice, &buf, "warranty. In no event will the authors be held liable for any", -1);
1008 			COMMENT(&notice, &buf, "damages arising from the use of this software.", -1);
1009 			comment(&notice, &buf, NiL, 0, 0);
1010 			COMMENT(&notice, &buf, "Permission is granted to anyone to use this software for any", -1);
1011 			COMMENT(&notice, &buf, "purpose, including commercial applications, and to alter it and", -1);
1012 			COMMENT(&notice, &buf, "redistribute it freely, subject to the following restrictions:", -1);
1013 			comment(&notice, &buf, NiL, 0, 0);
1014 			COMMENT(&notice, &buf, " 1. The origin of this software must not be misrepresented;", -1);
1015 			COMMENT(&notice, &buf, "    you must not claim that you wrote the original software. If", -1);
1016 			COMMENT(&notice, &buf, "    you use this software in a product, an acknowledgment in the", -1);
1017 			COMMENT(&notice, &buf, "    product documentation would be appreciated but is not", -1);
1018 			COMMENT(&notice, &buf, "    required.", -1);
1019 			comment(&notice, &buf, NiL, 0, 0);
1020 			COMMENT(&notice, &buf, " 2. Altered source versions must be plainly marked as such,", -1);
1021 			COMMENT(&notice, &buf, "    and must not be misrepresented as being the original", -1);
1022 			COMMENT(&notice, &buf, "    software.", -1);
1023 			comment(&notice, &buf, NiL, 0, 0);
1024 			COMMENT(&notice, &buf, " 3. This notice may not be removed or altered from any source", -1);
1025 			COMMENT(&notice, &buf, "    distribution.", -1);
1026 			comment(&notice, &buf, NiL, 0, 0);
1027 		}
1028 		else if (notice.type == MIT)
1029 		{
1030 			comment(&notice, &buf, NiL, 0, 0);
1031 			COMMENT(&notice, &buf, "Permission is hereby granted, free of charge, to any person", 0);
1032 			COMMENT(&notice, &buf, "obtaining a copy of this software and associated", 0);
1033 			COMMENT(&notice, &buf, "documentation files (the \"Software\"), to deal in the", 0);
1034 			COMMENT(&notice, &buf, "Software without restriction, including without limitation", 0);
1035 			COMMENT(&notice, &buf, "the rights to use, copy, modify, merge, publish, distribute,", 0);
1036 			COMMENT(&notice, &buf, "sublicense, and/or sell copies of the Software, and to", 0);
1037 			COMMENT(&notice, &buf, "permit persons to whom the Software is furnished to do so,", 0);
1038 			COMMENT(&notice, &buf, "subject to the following conditions:", 0);
1039 			comment(&notice, &buf, NiL, 0, 0);
1040 			COMMENT(&notice, &buf, "The above copyright notice and this permission notice shall", 0);
1041 			COMMENT(&notice, &buf, "be included in all copies or substantial portions of the", 0);
1042 			COMMENT(&notice, &buf, "Software.", 0);
1043 			comment(&notice, &buf, NiL, 0, 0);
1044 			COMMENT(&notice, &buf, "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY", 0);
1045 			COMMENT(&notice, &buf, "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE", 0);
1046 			COMMENT(&notice, &buf, "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR", 0);
1047 			COMMENT(&notice, &buf, "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS", 0);
1048 			COMMENT(&notice, &buf, "OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR", 0);
1049 			COMMENT(&notice, &buf, "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR", 0);
1050 			COMMENT(&notice, &buf, "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE", 0);
1051 			COMMENT(&notice, &buf, "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", 0);
1052 			comment(&notice, &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(&notice, &tmp, &notice.item[i]);
1061 					copy(&tmp, " - ", -1);
1062 				}
1063 				else
1064 					i = -1;
1065 				copy(&tmp, "Proprietary", -1);
1066 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
1067 				comment(&notice, &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(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
1074 					if (notice.item[PARENT].data)
1075 					{
1076 						expand(&notice, &tmp, &notice.item[PARENT]);
1077 						copy(&tmp, " ", -1);
1078 					}
1079 					if (notice.item[CORPORATION].data)
1080 					{
1081 						expand(&notice, &tmp, &notice.item[CORPORATION]);
1082 						comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
1083 					}
1084 					else if (notice.item[COMPANY].data)
1085 					{
1086 						expand(&notice, &tmp, &notice.item[COMPANY]);
1087 						comment(&notice, &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(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
1096 					if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data)
1097 						expand(&notice, &tmp, &notice.item[i]);
1098 					if (notice.item[COMPANY].data)
1099 					{
1100 						if (SIZ(&tmp))
1101 							PUT(&tmp, ' ');
1102 						expand(&notice, &tmp, &notice.item[COMPANY]);
1103 					}
1104 					if (SIZ(&tmp))
1105 						comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
1106 					COMMENT(&notice, &buf, "and is not to be disclosed or used except in", 1);
1107 					COMMENT(&notice, &buf, "accordance with applicable agreements", 1);
1108 				}
1109 				comment(&notice, &buf, NiL, 0, 0);
1110 			}
1111 			else if (notice.type == NONEXCLUSIVE)
1112 			{
1113 				COMMENT(&notice, &buf, "For nonexclusive individual use", 1);
1114 				comment(&notice, &buf, NiL, 0, 0);
1115 			}
1116 			else if (notice.type == NONCOMMERCIAL)
1117 			{
1118 				COMMENT(&notice, &buf, "For noncommercial use", 1);
1119 				comment(&notice, &buf, NiL, 0, 0);
1120 			}
1121 			if (notice.type >= PROPRIETARY && !notice.item[URL].data)
1122 			{
1123 				COMMENT(&notice, &buf, "Unpublished & Not for Publication", 0);
1124 				comment(&notice, &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(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
1134 					else
1135 						PUT(&tmp, ' ');
1136 					if (notice.item[PARENT].data)
1137 					{
1138 						expand(&notice, &tmp, &notice.item[PARENT]);
1139 						copy(&tmp, " ", -1);
1140 					}
1141 					if (notice.item[CORPORATION].data)
1142 					{
1143 						expand(&notice, &tmp, &notice.item[CORPORATION]);
1144 						if (notice.item[INCORPORATION].data)
1145 						{
1146 							copy(&tmp, " ", -1);
1147 							expand(&notice, &tmp, &notice.item[INCORPORATION]);
1148 						}
1149 					}
1150 					else if (notice.item[COMPANY].data)
1151 						expand(&notice, &tmp, &notice.item[COMPANY]);
1152 				}
1153 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
1154 				COMMENT(&notice, &buf, "under the terms and conditions of the license in", 0);
1155 				expand(&notice, &tmp, &notice.item[URL]);
1156 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
1157 				if (notice.item[URLMD5].data)
1158 				{
1159 					copy(&tmp, "(with an md5 checksum of ", -1);
1160 					expand(&notice, &tmp, &notice.item[URLMD5]);
1161 					copy(&tmp, ")", -1);
1162 					comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
1163 				}
1164 				comment(&notice, &buf, NiL, 0, 0);
1165 			}
1166 			else if (notice.type == PROPRIETARY)
1167 			{
1168 				COMMENT(&notice, &buf, "The copyright notice above does not evidence any", 0);
1169 				COMMENT(&notice, &buf, "actual or intended publication of such source code", 0);
1170 				comment(&notice, &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(&notice, &tmp, &item);
1191 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), h);
1192 			} while (v++ < x);
1193 			if (item.size)
1194 				comment(&notice, &buf, NiL, 0, 0);
1195 		}
1196 		if (notice.item[ORGANIZATION].data)
1197 		{
1198 			expand(&notice, &tmp, &notice.item[ORGANIZATION]);
1199 			comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
1200 			if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data)
1201 				expand(&notice, &tmp, &notice.item[i]);
1202 			if (notice.item[COMPANY].data)
1203 			{
1204 				if (SIZ(&tmp))
1205 					PUT(&tmp, ' ');
1206 				expand(&notice, &tmp, &notice.item[COMPANY]);
1207 			}
1208 			if (SIZ(&tmp))
1209 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
1210 			if (notice.item[LOCATION].data)
1211 			{
1212 				expand(&notice, &tmp, &notice.item[LOCATION]);
1213 				comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
1214 			}
1215 			comment(&notice, &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(&notice, &buf, &notice.id[i].value);
1245 						PUT(&buf, ']');
1246 					}
1247 					else
1248 					{
1249 						if (k < 0)
1250 						{
1251 							COMMENT(&notice, &buf, "CONTRIBUTORS", 0);
1252 							comment(&notice, &buf, NiL, 0, 0);
1253 						}
1254 						k = 1;
1255 						expand(&notice, &tmp, &notice.id[i].value);
1256 						comment(&notice, &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(&notice, &buf, &item);
1269 					PUT(&buf, ']');
1270 				}
1271 				else
1272 				{
1273 					if (k < 0)
1274 					{
1275 						COMMENT(&notice, &buf, "CONTRIBUTORS", 0);
1276 						comment(&notice, &buf, NiL, 0, 0);
1277 					}
1278 					k = 1;
1279 					expand(&notice, &tmp, &item);
1280 					comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
1281 				}
1282 			}
1283 		}
1284 		if (k > 0)
1285 			comment(&notice, &buf, NiL, 0, 0);
1286 	}
1287 	if (notice.type == USAGE)
1288 	{
1289 		copy(&buf, "[-copyright?", -1);
1290 		copyright(&notice, &buf);
1291 		PUT(&buf, ']');
1292 		if (notice.item[URL].data)
1293 		{
1294 			copy(&buf, "[-license?", -1);
1295 			expand(&notice, &buf, &notice.item[URL]);
1296 			PUT(&buf, ']');
1297 		}
1298 		PUT(&buf, '\n');
1299 	}
1300 	else
1301 		comment(&notice, &buf, NiL, -1, 0);
1302 	return END(&buf);
1303 }
1304