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