1700 lines · 42.8 KB · Perl
RawDownload
# This is the PerSAX Handlers Package package DOMTSHandler; use Switch; use XML::XPath;use XML::XPath::XMLParser; our $description = 0;our $string_index = 0;our $ret_index = 0;our $condition_index = 0;our $test_index = 0;our $iterator_index = 0;our $temp_index = 0;# Sometimes, we need temp nodesour $tnode_index = 0;our $dom_feature = "\"XML\"";our %bootstrap_api = (	dom_implementation_create_document_type => "",	dom_implementation_create_document	=> "",);our %native_interface = (	DOMString => \&generate_domstring_interface,	DOMTimeStamp => "",	DOMUserData => "",	DOMObject =>"",);our %special_type = (	# Some of the type are not defined now!	boolean => "bool ",	int => "int32_t ",	"unsigned long" => "dom_ulong ",	DOMString => "dom_string *",	List => "list *",	Collection => "list *",	DOMImplementation => "dom_implementation *",	NamedNodeMap => "dom_namednodemap *",	NodeList => "dom_nodelist *",        HTMLCollection => "dom_html_collection *",        HTMLFormElement => "dom_html_form_element *",	CharacterData => "dom_characterdata *",	CDATASection => "dom_cdata_section *",        HTMLAnchorElement => "dom_html_anchor_element *",	HTMLElement => "dom_html_element *",	HTMLTableCaptionElement => "dom_html_table_caption_element *",	HTMLTableSectionElement => "dom_html_table_section_element *",	HTMLTableElement => "dom_html_table_element *",	HTMLTableRowElement => "dom_html_table_row_element *",	HTMLOptionsCollection => "dom_html_options_collection *",);our %special_prefix = (	DOMString => "dom_string",	DOMImplementation => "dom_implementation",	NamedNodeMap => "dom_namednodemap",	NodeList => "dom_nodelist",        HTMLCollection => "dom_html_collection",        HTMLFormElement => "dom_html_form_element",	CharacterData => "dom_characterdata",	CDATASection => "dom_cdata_section *",        HTMLHRElement => "dom_html_hr_element",        HTMLBRElement => "dom_html_br_element",        HTMLLIElement => "dom_html_li_element",        HTMLTableCaptionElement => "dom_html_table_caption_element",	HTMLTableSectionElement => "dom_html_table_section_element",	HTMLIsIndexElement => "dom_html_isindex_element",        HTMLIFrameElement => "dom_html_iframe_element",        HTMLOListElement => "dom_html_olist_element",        HTMLDListElement => "dom_html_dlist_element",	caption => "dom_html_table_caption_element *",	section => "dom_html_table_section_element *",	createCaption => "dom_html_element *",	createTHead => "dom_html_element *",	createTFoot => "dom_html_element *",	deleteCaption => "dom_html_element *",	deleteTHead => "dom_html_element *",	deleteTFoot => "dom_html_element *",	insertRow => "dom_html_element *",	deleteRow => "dom_html_element *",	form => "dom_html_form_element *",); our %unref_prefix = (	DOMString => "dom_string",	NamedNodeMap => "dom_namednodemap",	NodeList => "dom_nodelist",	HTMLCollection => "dom_html_collection",	HTMLOptionsCollection => "dom_html_options_collection",	HTMLDocument => "dom_html_document",); our %special_method = (); our %special_attribute = (	namespaceURI => "namespace",	URL => "url",); our %no_unref = (	"boolean" => 1,	"int" => 1,	"unsigned int" => 1,	"unsigned long" => 1,	"List" => 1,	"Collection" => 1,); our %override_suffix = (	boolean => "bool",	int => "int",	"unsigned long" => "unsigned_long",	DOMString => "domstring",	DOMImplementation => "domimplementation",	NamedNodeMap => "domnamednodemap",	NodeList => "domnodelist",        HTMLCollection => "domhtmlcollection",	Collection => "list",	List => "list",); our %exceptions = (		DOM_NO_ERR			=>  0,	DOM_INDEX_SIZE_ERR		=>  1,	DOM_DOMSTRING_SIZE_ERR		=>  2,	DOM_HIERARCHY_REQUEST_ERR	=>  3,	DOM_WRONG_DOCUMENT_ERR		=>  4,	DOM_INVALID_CHARACTER_ERR	=>  5,	DOM_NO_DATA_ALLOWED_ERR		=>  6,	DOM_NO_MODIFICATION_ALLOWED_ERR	=>  7,	DOM_NOT_FOUND_ERR		=>  8,	DOM_NOT_SUPPORTED_ERR		=>  9,	DOM_INUSE_ATTRIBUTE_ERR		=> 10,	DOM_INVALID_STATE_ERR		=> 11,	DOM_SYNTAX_ERR			=> 12,	DOM_INVALID_MODIFICATION_ERR	=> 13,	DOM_NAMESPACE_ERR		=> 14,	DOM_INVALID_ACCESS_ERR		=> 15,	DOM_VALIDATION_ERR		=> 16,	DOM_TYPE_MISMATCH_ERR		=> 17, 	DOM_UNSPECIFIED_EVENT_TYPE_ERR  => (1<<30)+0,	DOM_DISPATCH_REQUEST_ERR        => (1<<30)+1, 	DOM_NO_MEM_ERR			=> (1<<31)+0, ); our @condition = qw(same equals notEquals less lessOrEquals greater greaterOrEquals isNull notNull and or xor not instanceOf isTrue isFalse hasSize contentType hasFeature implementationAttribute); our @exception = qw(INDEX_SIZE_ERR DOMSTRING_SIZE_ERR HIERARCHY_REQUEST_ERR WRONG_DOCUMENT_ERR INVALID_CHARACTER_ERR NO_DATA_ALLOWED_ERR NO_MODIFICATION_ALLOWED_ERR NOT_FOUND_ERR NOT_SUPPORTED_ERR INUSE_ATTRIBUTE_ERR NAMESPACE_ERR UNSPECIFIED_EVENT_TYPE_ERR DISPATCH_REQUEST_ERR); our @assertion = qw(assertTrue assertFalse assertNull assertNotNull assertEquals assertNotEquals assertSame assertInstanceOf assertSize assertEventCount assertURIEquals); our @assertexception = qw(assertDOMException assertEventException assertImplementationException); our @control = qw(if while for-each else); our @framework_statement = qw(assign increment decrement append plus subtract mult divide load implementation comment hasFeature implementationAttribute EventMonitor.setUserObj EventMonitor.getAtEvents EventMonitor.getCaptureEvents EventMonitor.getBubbleEvents EventMonitor.getAllEvents wait); sub new {	my $type = shift;	my $dtd = shift;        my $chdir = shift;	my $dd = XML::XPath->new(filename => $dtd);	my $self = {			# The DTD file of the xml files			dd => $dd,			# To indicate whether we are in comments			comment => 0,			# To indicate that whether we are in <comment> element			inline_comment => 0,			# The stack of elements encountered utill now			context => [],			# The map for <var> name => type			var => {},			# See the comment on generate_condition2 for this member			condition_stack => [],			# The list for UNREF			unref => [],			string_unref => [],                        block_unrefs => ["!!!"],			# The indent of current statement			indent => "",			# The variables for List/Collection			# We now, declare an array for a list and then add them into a list			# The map for all the List/Collection in one test			# "List Name" => "Member type"			list_map => {},			# The name of the current List/Collection			list_name => "",			# The number of items of the current List/Collection			list_last_name => [],			# The number of items of the current List/Collection			list_num => 0,			# Whether List/Collection has members			list_hasmem => 0,			# The type of the current List/Collection			member_list_declared => 0,			# The type of the current List/Collection			list_type => "",			# Whether we are in exception assertion			exception => 0,                        # Where to chdir                        chdir => $chdir			}; 	return bless $self, $type;} sub start_element {	my ($self, $element) = @_; 	my $en = $element->{Name}; 	my $dd = $self->{dd};	my $ct = $self->{context};	push(@$ct, $en); 	switch ($en) {		case "test" {			;		}		case "metadata" {			# start comments here			print "/*\n";			$self->{comment} = 1;		} 		# Print the var definition		case "var" {			$self->generate_var($element->{Attributes});		} 		case "member" {			if ($self->{context}->[-2] eq "var") {				if ($self->{"list_hasmem"} eq 1) {					print ", ";				}				$self->{"list_hasmem"} = 1;				$self->{"list_num"} ++;			}		}  		# The framework statements		case [@framework_statement] {			# Because the implementationAttribute & hasFeature belongs to both 			# framework-statement and condition, we should distinct the two 			# situation here. Let the generate_condtion to do the work.			if ($en eq "hasFeature" || $en eq "implementationAttribute") {				next;			} 			$self->generate_framework_statement($en, $element->{Attributes});		} 		case [@control] {			$self->generate_control_statement($en, $element->{Attributes});		} 		# Test condition		case [@condition] {			$self->generate_condition($en, $element->{Attributes});		} 		# The assertsions		case [@assertion] {			$self->generate_assertion($en, $element->{Attributes});		}				case [@assertexception] {			# Indeed, nothing to do here!		} 		# Deal with exception		case [@exception] {			# Just see end_element			$self->{'exception'} = 1;		} 		# Then catch other case		else {			# we don't care the comment nodes			if ($self->{comment} eq 0) {				$self->generate_interface($en, $element->{Attributes});			}		}	}} sub end_element {	my ($self, $element) = @_; 	my @ct = @{$self->{context}};	my $name = pop(@{$self->{context}}); 	switch ($name) {		case "metadata" {			print "*/\n";			$self->{comment} = 0;			$self->generate_main();		}		case "test" {			$self->cleanup();		} 		case "var" {			$self->generate_list();		} 		# End of condition		case [@condition] {			$self->complete_condition($name);		} 		# The assertion		case [@assertion] {			$self->complete_assertion($name);		} 		case [@control] {			$self->complete_control_statement($name);		} 		case [@exception] {			$name = "DOM_".$name;			print "assert(exp == $exceptions{$name});\n";			$self->{'exception'} = 0;		} 	}} sub characters {	my ($self, $data) = @_;	our $description; 	my $ct = $self->{context}; 	if ($self->{"inline_comment"} eq 1) {		print "$data->{Data}";		return ;	} 	# We print the comments here	if ($self->{comment} eq 1) {		# So, we are in comments state		my $top = $ct->[$#{$ct}];		if ($top eq "metadata") {			return;		} 		if ($top eq "description") {			if ($description eq 0) {				print "description: \n";				$description = 1;			}			print "$data->{Data}";		} else {			print "$top: $data->{Data}\n";		}		return;	} 	if ($self->{context}->[-1] eq "member") {		# We should mark that the List/Collection has members		$self->{"list_hasmem"} = 1; 		# Here, we should detect the characters type		# whether it is a integer or string (now, we only take care		# of the two types, because I did not find any other type).		if ($self->{"list_type"} eq "") {			if ($data->{Data} =~ /^\"/) {				$self->{"list_type"} = "char *";				print "const char *".$self->{"list_name"}."Array[] = \{ $data->{Data}";			} else { 				if ($data->{Data} =~ /^[0-9]+/) {					$self->{"list_type"} = "int *";					print "int ".$self->{"list_name"}."Array[] = \{ $data->{Data}";				} else {					die "Some data in the <member> we can't process: \"$data->{Data}\"";				}			}		} else {			# So, we must have known the type, just output the member			print "$data->{Data}";		}	}} sub generate_main {	my $self = shift;	# Firstly, push a new "b" to the string_unref list	push(@{$self->{"string_unref"}}, "b"); 	print << "__EOF__" #include <stdio.h>#include <string.h>#include <stdbool.h>#include <unistd.h> #include <dom/dom.h>#include <dom/functypes.h> #include <domts.h> dom_implementation *doc_impl; int main(int argc, char **argv){	dom_exception exp; 	(void)argc;	(void)argv; 	if (chdir("$self->{chdir}") < 0) {		perror("chdir (\\"$self->{chdir})\\"");		return 1;	}	int list_temp[100], count = -1;__EOF__} # Note that, we have not just declare variables here# we should also define EventListener here!# I think this should be done after the EventListener design# is completesub generate_var {	my ($self, $ats) = @_; 	my $type = "";	my $dstring = ""; 	# For the case like <var name="v" type="DOMString" value="some some"	if ($ats->{"type"} eq "DOMString" and exists $ats->{"value"}) {		$dstring = $self->generate_domstring($ats->{"value"});		$ats->{"value"} = $dstring;	} 	$type = type_to_ctype($ats->{"type"});	if ($type eq "") {		print "Not implement this type now\n";		return;	} 	print "\t$type$ats->{'name'}";	if (exists $ats->{"value"}) {		print " = $ats->{'value'};\n";	} else {		if ($type =~ m/\*/) {			print " = NULL;\n";		} else {			print ";\n";		}	} 	my $var = $self->{"var"};	$var->{$ats->{"name"}} = $ats->{"type"}; 	# If the type is List/Collection, we should take care of it	if ($ats->{"type"} =~ /^(List|Collection)$/) {		$self->{"list_name"} = $ats->{"name"};	}} sub generate_list {	my $self = shift; 	# We should deal with the end of <var> when the <var> is declaring a List/Collection	if ($self->{"list_hasmem"} eq 1) {		# Yes, we are in List/Collection declaration		# Firstly, enclose the Array declaration		print "};\n";		# Now, we should create the list * for the List/Collection		# Note, we should deal with "int" or "string" type with different params.		if ($self->{"list_type"} eq "char *") {			print $self->{"list_name"}." = list_new(STRING);\n";		}		if ($self->{"list_type"} eq "int *") {			print $self->{"list_name"}." = list_new(INT);\n";			while(defined ($x = pop @{$self->{"list_last_name"}})) {				print $x." = list_new(INT);\n";			}		}		while(defined($x = pop(@{$self->{"list_last_name"}}))) {			print $x." = list_new(DOM_STRING);\n";		}		$self->{"member_list_declared"} = 1;		if ($self->{"list_type"} eq "") {			die "A List/Collection has children member but no type is impossible!";		}		if ($self->{"list_type"} eq "int *") {						for (my $i = 0; $i < $self->{"list_num"}; $i++) {				# Use *(char **) to convert char *[] to char *				print "list_add(".$self->{"list_name"}.", (int *)(".$self->{"list_name"}."Array) + $i);\n";			}

Lines 1–500 of 1700.