#!/bin/sh -
#

# FLASK

set -e

awk=$1
shift

# output files
av_permissions="av_permissions.h"
av_inherit="av_inherit.h"
common_perm_to_string="common_perm_to_string.h"
av_perm_to_string="av_perm_to_string.h"

cat $* | $awk "
BEGIN	{
		outfile = \"$av_permissions\"
		inheritfile = \"$av_inherit\"
		cpermfile = \"$common_perm_to_string\"
		avpermfile = \"$av_perm_to_string\"
		"'
		nextstate = "COMMON_OR_AV";
		printf("/* This file is automatically generated.  Do not edit. */\n") > outfile;
		printf("/* This file is automatically generated.  Do not edit. */\n") > inheritfile;
		printf("/* This file is automatically generated.  Do not edit. */\n") > cpermfile;
		printf("/* This file is automatically generated.  Do not edit. */\n") > avpermfile;
;
	}
/^[ \t]*#/	{ 
			next;
		}
$1 == "common"	{ 
			if (nextstate != "COMMON_OR_AV")
			{
				printf("Parse error:  Unexpected COMMON definition on line %d\n", NR);
				next;	
			}

			if ($2 in common_defined)
			{
				printf("Duplicate COMMON definition for %s on line %d.\n", $2, NR);
				next;
			}	
			common_defined[$2] = 1;

			tclass = $2;
			common_name = $2; 
			permission = 1;

			printf("TB_(common_%s_perm_to_string)\n", $2) > cpermfile;

			nextstate = "COMMON-OPENBRACKET";
			next;
		}
$1 == "class"	{
			if (nextstate != "COMMON_OR_AV" &&
			    nextstate != "CLASS_OR_CLASS-OPENBRACKET")
			{
				printf("Parse error:  Unexpected class definition on line %d\n", NR);
				next;	
			}

			tclass = $2;

			if (tclass in av_defined)
			{
				printf("Duplicate access vector definition for %s on line %d\n", tclass, NR);
				next;
			} 
			av_defined[tclass] = 1;

			inherits = "";
			permission = 1;

			nextstate = "INHERITS_OR_CLASS-OPENBRACKET";
			next;
		}
$1 == "inherits" {			
			if (nextstate != "INHERITS_OR_CLASS-OPENBRACKET")
			{
				printf("Parse error:  Unexpected INHERITS definition on line %d\n", NR);
				next;	
			}

			if (!($2 in common_defined))
			{
				printf("COMMON %s is not defined (line %d).\n", $2, NR);
				next;
			}

			inherits = $2;
			permission = common_base[$2];

			for (combined in common_perms)
			{
				split(combined,separate, SUBSEP);
				if (separate[1] == inherits)
				{
					inherited_perms[common_perms[combined]] = separate[2];
				}
			}

                        j = 1;
                        for (i in inherited_perms) {
                            ind[j] = i + 0;
                            j++;
                        }
                        n = asort(ind);
			for (i = 1; i <= n; i++) {
				perm = inherited_perms[ind[i]];
				printf("#define %s__%s", toupper(tclass), toupper(perm)) > outfile; 
				spaces = 40 - (length(perm) + length(tclass));
				if (spaces < 1)
				      spaces = 1;
				for (j = 0; j < spaces; j++) 
					printf(" ") > outfile; 
				printf("0x%08xUL\n", ind[i]) > outfile; 
			}
			printf("\n") > outfile;
                        for (i in ind) delete ind[i];
                        for (i in inherited_perms) delete inherited_perms[i];

			printf("   S_(SECCLASS_%s, %s, 0x%08xUL)\n", toupper(tclass), inherits, permission) > inheritfile; 

			nextstate = "CLASS_OR_CLASS-OPENBRACKET";
			next;
		}
$1 == "{"	{ 
			if (nextstate != "INHERITS_OR_CLASS-OPENBRACKET" &&
			    nextstate != "CLASS_OR_CLASS-OPENBRACKET" &&
			    nextstate != "COMMON-OPENBRACKET")
			{
				printf("Parse error:  Unexpected { on line %d\n", NR);
				next;
			}

			if (nextstate == "INHERITS_OR_CLASS-OPENBRACKET")
				nextstate = "CLASS-CLOSEBRACKET";

			if (nextstate == "CLASS_OR_CLASS-OPENBRACKET")
				nextstate = "CLASS-CLOSEBRACKET";

			if (nextstate == "COMMON-OPENBRACKET")
				nextstate = "COMMON-CLOSEBRACKET";
		}
/[a-z][a-z_]*/	{
			if (nextstate != "COMMON-CLOSEBRACKET" &&
			    nextstate != "CLASS-CLOSEBRACKET")
			{
				printf("Parse error:  Unexpected symbol %s on line %d\n", $1, NR);		
				next;
			}

			if (nextstate == "COMMON-CLOSEBRACKET")
			{
				if ((common_name,$1) in common_perms)
				{
					printf("Duplicate permission %s for common %s on line %d.\n", $1, common_name, NR);
					next;
				}

				common_perms[common_name,$1] = permission;

				printf("#define COMMON_%s__%s", toupper(common_name), toupper($1)) > outfile; 

				printf("    S_(\"%s\")\n", $1) > cpermfile;
			}
			else
			{
				if ((tclass,$1) in av_perms)
				{
					printf("Duplicate permission %s for %s on line %d.\n", $1, tclass, NR);
					next;
				}

				av_perms[tclass,$1] = permission;
		
				if (inherits != "")
				{
					if ((inherits,$1) in common_perms)
					{
						printf("Permission %s in %s on line %d conflicts with common permission.\n", $1, tclass, inherits, NR);
						next;
					}
				}

				printf("#define %s__%s", toupper(tclass), toupper($1)) > outfile; 

				printf("   S_(SECCLASS_%s, %s__%s, \"%s\")\n", toupper(tclass), toupper(tclass), toupper($1), $1) > avpermfile; 
			}

			spaces = 40 - (length($1) + length(tclass));
			if (spaces < 1)
			      spaces = 1;

			for (i = 0; i < spaces; i++) 
				printf(" ") > outfile; 
			printf("0x%08xUL\n", permission) > outfile; 
			permission = permission * 2;
		}
$1 == "}"	{
			if (nextstate != "CLASS-CLOSEBRACKET" && 
			    nextstate != "COMMON-CLOSEBRACKET")
			{
				printf("Parse error:  Unexpected } on line %d\n", NR);
				next;
			}

			if (nextstate == "COMMON-CLOSEBRACKET")
			{
				common_base[common_name] = permission;
				printf("TE_(common_%s_perm_to_string)\n\n", common_name) > cpermfile; 
			}

			printf("\n") > outfile;

			nextstate = "COMMON_OR_AV";
		}
END	{
		if (nextstate != "COMMON_OR_AV" && nextstate != "CLASS_OR_CLASS-OPENBRACKET")
			printf("Parse error:  Unexpected end of file\n");

	}'

# FLASK
