- Added code for detection of missing types.
- Added missing types. - Added a function for each type test to improve compiling with -O2.
This commit is contained in:
parent
b9ae9eca13
commit
aac9ff400c
|
@ -47,7 +47,11 @@ EMR
|
|||
EMRABORTPATH
|
||||
EMRANGLEARC
|
||||
EMRARC
|
||||
EMRARCTO
|
||||
EMRBEGINPATH
|
||||
EMRBITBLT
|
||||
EMRCHORD
|
||||
EMRCLOSEFIGURE
|
||||
EMRCREATEBRUSHINDIRECT
|
||||
!EMRCREATECOLORSPACE
|
||||
!EMRCREATECOLORSPACEW
|
||||
|
@ -58,6 +62,7 @@ EMRCREATEPEN
|
|||
EMRDELETECOLORSPACE
|
||||
EMRDELETEOBJECT
|
||||
EMRELLIPSE
|
||||
EMRENDPATH
|
||||
EMREOF
|
||||
EMREXCLUDECLIPRECT
|
||||
EMREXTCREATEFONTINDIRECTW
|
||||
|
@ -65,45 +70,80 @@ EMREXTCREATEPEN
|
|||
EMREXTFLOODFILL
|
||||
EMREXTSELECTCLIPRGN
|
||||
EMREXTTEXTOUTA
|
||||
EMREXTTEXTOUTW
|
||||
EMRFILLPATH
|
||||
EMRFILLRGN
|
||||
EMRFLATTENPATH
|
||||
EMRFORMAT
|
||||
EMRFRAMERGN
|
||||
EMRGDICOMMENT
|
||||
EMRGLSBOUNDEDRECORD
|
||||
EMRGLSRECORD
|
||||
EMRINVERTRGN
|
||||
EMRINTERSECTCLIPRECT
|
||||
EMRLINETO
|
||||
EMRMASKBLT
|
||||
EMRMODIFYWORLDTRANSFORM
|
||||
EMRMOVETOEX
|
||||
EMROFFSETCLIPRGN
|
||||
EMRPAINTRGN
|
||||
EMRPIE
|
||||
EMRPIXELFORMAT
|
||||
EMRPLGBLT
|
||||
EMRPOLYBEZIER
|
||||
EMRPOLYBEZIERTO
|
||||
EMRPOLYDRAW
|
||||
EMRPOLYGON
|
||||
EMRPOLYLINE
|
||||
EMRPOLYLINETO
|
||||
EMRPOLYPOLYGON
|
||||
EMRPOLYPOLYLINE
|
||||
EMRPOLYTEXTOUTA
|
||||
EMRPOLYTEXTOUTW
|
||||
EMRREALIZEPALETTE
|
||||
EMRRECTANGLE
|
||||
EMRRESIZEPALETTE
|
||||
EMRRESTOREDC
|
||||
EMRROUNDRECT
|
||||
EMRSAVEDC
|
||||
EMRSCALEVIEWPORTEXTEX
|
||||
EMRSCALEWINDOWEXTEX
|
||||
EMRSELECTCLIPPATH
|
||||
EMRSELECTCOLORSPACE
|
||||
EMRSELECTOBJECT
|
||||
EMRSELECTPALETTE
|
||||
EMRSETARCDIRECTION
|
||||
EMRSETBKCOLOR
|
||||
EMRSETBKMODE
|
||||
EMRSETBRUSHORGEX
|
||||
EMRSETCOLORADJUSTMENT
|
||||
!EMRSETCOLORSPACE
|
||||
EMRSETDIBITSTODEVICE
|
||||
EMRSETICMMODE
|
||||
!EMRSETLAYOUT
|
||||
EMRSETMAPMODE
|
||||
EMRSETMAPPERFLAGS
|
||||
EMRSETMETARGN
|
||||
EMRSETMITERLIMIT
|
||||
!EMRSETPALETTEENTRIES
|
||||
EMRSETPIXELV
|
||||
EMRSETPOLYFILLMODE
|
||||
EMRSETROP2
|
||||
EMRSETSTRETCHBLTMODE
|
||||
EMRSETTEXTALIGN
|
||||
EMRSETTEXTCOLOR
|
||||
!EMRSETTEXTJUSTIFICATION
|
||||
EMRSETVIEWPORTEXTEX
|
||||
EMRSETVIEWPORTORGEX
|
||||
EMRSETWINDOWEXTEX
|
||||
EMRSETWINDOWORGEX
|
||||
EMRSETWORLDTRANSFORM
|
||||
EMRSTRETCHBLT
|
||||
EMRSTRETCHDIBITS
|
||||
EMRSTROKEANDFILLPATH
|
||||
EMRSTROKEPATH
|
||||
EMRTEXT
|
||||
EMRWIDENPATH
|
||||
ENHMETAHEADER: !szlMicrometers
|
||||
ENHMETARECORD
|
||||
ENHMFENUMPROC
|
||||
|
@ -178,7 +218,7 @@ LPGRADIENT_RECT
|
|||
LPGRADIENT_TRIANGLE
|
||||
LPHANDLETABLE
|
||||
LPKERNINGPAIR
|
||||
LPLOCALESIGNATUREE
|
||||
LPLOCALESIGNATURE
|
||||
LPLOGBRUSH
|
||||
LPLOGCOLORSPACEA
|
||||
LPLOGCOLORSPACEW
|
||||
|
@ -325,6 +365,7 @@ PEMRSETBRUSHORGEX
|
|||
PEMRSETCOLORADJUSTMENT
|
||||
!PEMRSETCOLORSPACE
|
||||
PEMRSETDIBITSTODEVICE
|
||||
PEMRSETICMMODE
|
||||
!PEMRSETLAYOUT
|
||||
PEMRSETMAPMODE
|
||||
PEMRSETMAPPERFLAGS
|
||||
|
@ -359,7 +400,7 @@ PGRADIENT_RECT
|
|||
PGRADIENT_TRIANGLE
|
||||
PHANDLETABLE
|
||||
PIXELFORMATDESCRIPTOR
|
||||
PLOCALESIGNATUR
|
||||
PLOCALESIGNATURE
|
||||
PLOGBRUSH
|
||||
PLOGFONTA
|
||||
PLOGFONTW
|
||||
|
@ -428,17 +469,18 @@ CRITICAL_SECTION
|
|||
CRITICAL_SECTION_DEBUG
|
||||
DCB
|
||||
DEBUG_EVENT
|
||||
ENUMRESLANGPROCA
|
||||
ENUMRESLANGPROCW
|
||||
ENUMRESNAMEPROCA
|
||||
ENUMRESNAMEPROCW
|
||||
ENUMRESTYPEPROCA
|
||||
ENUMRESTYPEPROCW
|
||||
!ENUMRESLANGPROCA
|
||||
!ENUMRESLANGPROCW
|
||||
!ENUMRESNAMEPROCA
|
||||
!ENUMRESNAMEPROCW
|
||||
!ENUMRESTYPEPROCA
|
||||
!ENUMRESTYPEPROCW
|
||||
EXCEPTION_DEBUG_INFO
|
||||
EXIT_PROCESS_DEBUG_INFO
|
||||
EXIT_THREAD_DEBUG_INFO
|
||||
!FILETIME
|
||||
HW_PROFILE_INFOA
|
||||
HW_PROFILE_INFOW
|
||||
LDT_ENTRY
|
||||
LOAD_DLL_DEBUG_INFO
|
||||
LPBY_HANDLE_FILE_INFORMATION
|
||||
|
@ -520,7 +562,7 @@ SYSTEMTIME
|
|||
SYSTEM_POWER_STATUS
|
||||
TIME_ZONE_INFORMATION
|
||||
UNLOAD_DLL_DEBUG_INFO
|
||||
WAITORTIMERCALLBACK
|
||||
!WAITORTIMERCALLBACK
|
||||
WIN32_FILE_ATTRIBUTE_DATA
|
||||
WIN32_FIND_DATAA
|
||||
WIN32_FIND_DATAW
|
||||
|
@ -560,9 +602,11 @@ CCHAR
|
|||
CHAR
|
||||
COLORREF
|
||||
!CONTEXT
|
||||
!CONTEXT86
|
||||
!DATE
|
||||
!DOUBLE
|
||||
DWORD
|
||||
DWORD32
|
||||
!DWORD64
|
||||
!DWORDLONG
|
||||
DWORD_PTR
|
||||
|
@ -576,6 +620,7 @@ FLOATING_SAVE_AREA
|
|||
FPO_DATA
|
||||
GENERIC_MAPPING
|
||||
GLOBALHANDLE
|
||||
HALF_PTR
|
||||
HANDLE
|
||||
HCURSOR
|
||||
HFILE
|
||||
|
@ -617,7 +662,10 @@ IMAGE_THUNK_DATA
|
|||
IMAGE_TLS_DIRECTORY
|
||||
IMAGE_VXD_HEADER
|
||||
INT
|
||||
!INT16
|
||||
INT32
|
||||
!INT64
|
||||
!INT8
|
||||
INT_PTR
|
||||
LANGID
|
||||
!LARGE_INTEGER
|
||||
|
@ -625,6 +673,7 @@ LCID
|
|||
LIST_ENTRY
|
||||
LOCALHANDLE
|
||||
LONG
|
||||
LONG32
|
||||
!LONG64
|
||||
!LONGLONG
|
||||
LONG_PTR
|
||||
|
@ -664,7 +713,7 @@ PCSTR
|
|||
PCWCH
|
||||
PCWSTR
|
||||
!PEXCEPTION_FRAME
|
||||
PEXCEPTION_HANDLER
|
||||
!PEXCEPTION_HANDLER
|
||||
PEXCEPTION_POINTERS
|
||||
PEXCEPTION_RECORD
|
||||
PFLOATING_SAVE_AREA
|
||||
|
@ -713,6 +762,9 @@ PMESSAGE_RESOURCE_BLOCK
|
|||
PMESSAGE_RESOURCE_DATA
|
||||
PMESSAGE_RESOURCE_ENTRY
|
||||
PNT_TIB
|
||||
POINT
|
||||
POINTL
|
||||
POINTS
|
||||
PPOINT
|
||||
PPOINTS
|
||||
PPRIVILEGE_SET
|
||||
|
@ -741,8 +793,11 @@ PULARGE_INTEGER
|
|||
PVOID
|
||||
PWCH
|
||||
PWSTR
|
||||
RECT
|
||||
RECTL
|
||||
RTL_CRITICAL_SECTION
|
||||
RTL_CRITICAL_SECTION_DEBUG
|
||||
RTL_RESOURCE_DEBUG
|
||||
SECURITY_CONTEXT_TRACKING_MODE
|
||||
SECURITY_DESCRIPTOR
|
||||
SECURITY_DESCRIPTOR_CONTROL
|
||||
|
@ -754,9 +809,11 @@ SID
|
|||
SID_AND_ATTRIBUTES
|
||||
SID_IDENTIFIER_AUTHORITY
|
||||
SINGLE_LIST_ENTRY
|
||||
SIZE
|
||||
SIZEL
|
||||
SIZE_T
|
||||
SSIZE_T
|
||||
!STACK_FRAME_HEADER
|
||||
SYSTEM_ALARM_ACE
|
||||
SYSTEM_AUDIT_ACE
|
||||
TCHAR
|
||||
|
@ -769,11 +826,16 @@ TOKEN_SOURCE
|
|||
!TOKEN_STATISTICS
|
||||
TOKEN_USER
|
||||
UCHAR
|
||||
UHALF_PTR
|
||||
UINT
|
||||
!UINT16
|
||||
UINT32
|
||||
!UINT64
|
||||
!UINT8
|
||||
UINT_PTR
|
||||
!ULARGE_INTEGER
|
||||
ULONG
|
||||
ULONG32
|
||||
!ULONG64
|
||||
!ULONGLONG
|
||||
ULONG_PTR
|
||||
|
@ -784,6 +846,7 @@ WORD
|
|||
WPARAM
|
||||
__int16
|
||||
__int32
|
||||
!__int64
|
||||
__int8
|
||||
|
||||
%%%dlls/user/tests
|
||||
|
@ -816,6 +879,7 @@ CBTACTIVATESTRUCT
|
|||
CBT_CREATEWNDA
|
||||
CBT_CREATEWNDW
|
||||
CLIENTCREATESTRUCT
|
||||
COMBOBOXINFO
|
||||
COMPAREITEMSTRUCT
|
||||
COPYDATASTRUCT
|
||||
CREATESTRUCTA
|
||||
|
@ -829,19 +893,15 @@ DESKTOPENUMPROCA
|
|||
DESKTOPENUMPROCW
|
||||
DLGITEMTEMPLATE
|
||||
DLGPROC
|
||||
DLGPROC
|
||||
DLGTEMPLATE
|
||||
!DRAWITEMSTRUCT
|
||||
DRAWSTATEPROC
|
||||
DRAWSTATEPROC
|
||||
DRAWTEXTPARAMS
|
||||
EDITWORDBREAKPROCA
|
||||
EDITWORDBREAKPROCA
|
||||
EDITWORDBREAKPROCW
|
||||
EDITWORDBREAKPROCW
|
||||
EVENTMSG
|
||||
FILTERKEYS
|
||||
GRAYSTRINGPROC
|
||||
GUITHREADINFO
|
||||
GRAYSTRINGPROC
|
||||
HARDWAREHOOKSTRUCT
|
||||
HARDWAREINPUT
|
||||
|
@ -853,7 +913,6 @@ HELPWININFOW
|
|||
HIGHCONTRASTA
|
||||
HIGHCONTRASTW
|
||||
HOOKPROC
|
||||
HOOKPROC
|
||||
ICONINFO
|
||||
ICONMETRICSA
|
||||
ICONMETRICSW
|
||||
|
@ -974,8 +1033,6 @@ MSLLHOOKSTRUCT
|
|||
MULTIKEYHELPA
|
||||
MULTIKEYHELPW
|
||||
NAMEENUMPROCA
|
||||
NAMEENUMPROCA
|
||||
NAMEENUMPROCW
|
||||
NAMEENUMPROCW
|
||||
NCCALCSIZE_PARAMS
|
||||
NMHDR
|
||||
|
@ -1024,12 +1081,8 @@ PNONCLIENTMETRICSA
|
|||
PNONCLIENTMETRICSW
|
||||
PPAINTSTRUCT
|
||||
PROPENUMPROCA
|
||||
PROPENUMPROCA
|
||||
PROPENUMPROCEXA
|
||||
PROPENUMPROCEXA
|
||||
PROPENUMPROCEXW
|
||||
PROPENUMPROCEXW
|
||||
PROPENUMPROCW
|
||||
PROPENUMPROCW
|
||||
PWINDOWINFO
|
||||
PWINDOWPLACEMENT
|
||||
|
@ -1040,7 +1093,6 @@ PWNDCLASSEXW
|
|||
PWNDCLASSW
|
||||
SCROLLINFO
|
||||
SENDASYNCPROC
|
||||
SENDASYNCPROC
|
||||
SERIALKEYSA
|
||||
SERIALKEYSW
|
||||
SOUNDSENTRYA
|
||||
|
@ -1048,7 +1100,6 @@ SOUNDSENTRYW
|
|||
STICKYKEYS
|
||||
STYLESTRUCT
|
||||
TIMERPROC
|
||||
TIMERPROC
|
||||
TOGGLEKEYS
|
||||
TPMPARAMS
|
||||
TRACKMOUSEEVENT
|
||||
|
@ -1056,7 +1107,6 @@ WINDOWINFO: !dwWindowStatus
|
|||
!WINDOWPLACEMENT
|
||||
WINDOWPOS
|
||||
WINEVENTPROC
|
||||
WINEVENTPROC
|
||||
WINSTAENUMPROCA
|
||||
WINSTAENUMPROCW
|
||||
WNDCLASSA
|
||||
|
@ -1064,5 +1114,4 @@ WNDCLASSEXA
|
|||
WNDCLASSEXW
|
||||
WNDCLASSW
|
||||
WNDENUMPROC
|
||||
WNDENUMPROC
|
||||
WNDPROC
|
||||
|
|
|
@ -225,11 +225,7 @@ sub _find_align_kind_size {
|
|||
$align = 4;
|
||||
$kind = "unsigned";
|
||||
$size = 4;
|
||||
} elsif (/^LP(?:CSTR|CWSTR|DWORD|STR|VOID|THREAD_START_ROUTINE|WSTR)$/) {
|
||||
$align = 4;
|
||||
$kind = "pointer";
|
||||
$size = 4;
|
||||
} elsif (/^(?:(?:MSGBOX)CALLBACK[AW]?|(?:FAR|WND)PROC[AW]?)$/) {
|
||||
} elsif (/^LP(?:CSTR|CWSTR|DWORD|VOID|WSTR)$/) {
|
||||
$align = 4;
|
||||
$kind = "pointer";
|
||||
$size = 4;
|
||||
|
@ -247,7 +243,10 @@ sub _find_align_kind_size {
|
|||
$output->write("$type_name: can't parse type\n");
|
||||
$size_parse_reported{$_} = 1;
|
||||
}
|
||||
|
||||
} elsif (/^\w+\s*\((?:\s*CALLBACK|\s*NTAPI|\s*WINAPI)?\s*\*\s*\)\s*\(.*?\)$/) {
|
||||
$align = 4;
|
||||
$kind = "pointer";
|
||||
$size = 4;
|
||||
}
|
||||
|
||||
my $align2;
|
||||
|
@ -627,17 +626,24 @@ sub output_test_pack_type {
|
|||
if (defined($type2)) {
|
||||
return $type2;
|
||||
} else {
|
||||
$output->write("$type_name2: type not found (ignored)\n");
|
||||
if ($type_name2 !~ /^(?:PVOID|VOID|void)$/) {
|
||||
$output->write("$type_name2: warning: type not found 1\n");
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
} else {
|
||||
} elsif ($type_name2 =~ /^\w+$/) {
|
||||
my $type2 = $$type_name2type{$type_name2};
|
||||
if (defined($type2)) {
|
||||
return &$dereference_type($type2);
|
||||
} else {
|
||||
$output->write("$type_name2: type not found (ignored)\n");
|
||||
$output->write("$type_name2: warning: type not found\n");
|
||||
return undef;
|
||||
}
|
||||
} elsif ($type_name2 =~ /^\w+\s*\((?:\s*CALLBACK|\s*NTAPI|\s*WINAPI)?\s*\*\s*\)\s*\(.*?\)$/) {
|
||||
return undef;
|
||||
} else {
|
||||
$output->write("$type_name2: warning: type can't be parsed\n");
|
||||
return undef;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -653,7 +659,7 @@ sub output_test_pack_type {
|
|||
if (!$optional && !scalar(keys(%$optional_fields2)) && defined($type_align2) && defined($type_size2)) {
|
||||
print OUT " TEST_TYPE_POINTER($type_name, $type_size2, $type_align2);\n";
|
||||
} else {
|
||||
$output->write("$type_name: type size not found (ignored)\n");
|
||||
# $output->write("$type_name: warning: type size not found\n");
|
||||
}
|
||||
}
|
||||
} elsif ($type_kind eq "signed") {
|
||||
|
@ -715,12 +721,13 @@ sub output_test_pack {
|
|||
my $test_dir = shift;
|
||||
my $test = shift;
|
||||
|
||||
my $type_names_used = shift;
|
||||
|
||||
$output->prefix("$test_dir: $test: ");
|
||||
|
||||
my @headers = $tests->get_section($test_dir, $test, "header");
|
||||
my @type_names = $tests->get_section($test_dir, $test, "type");
|
||||
|
||||
my %type_name_not_used;
|
||||
my %type_name2optional;
|
||||
my %type_name2optional_fields;
|
||||
|
||||
|
@ -742,7 +749,6 @@ sub output_test_pack {
|
|||
}
|
||||
|
||||
$type_name2optional_fields{$type_name} = $optional_fields;
|
||||
$type_name_not_used{$type_name} = 1;
|
||||
}
|
||||
|
||||
foreach my $header (@headers) {
|
||||
|
@ -751,31 +757,25 @@ sub output_test_pack {
|
|||
foreach my $_type_name (@type_names) {
|
||||
my $type_name = $_type_name;
|
||||
|
||||
next if $type_name =~ /^!/;
|
||||
my $skip = ($type_name =~ s/^!//);
|
||||
$type_name =~ s/:.*?$//;
|
||||
|
||||
my $type = $$type_name2type{$type_name};
|
||||
if (!defined($type)) {
|
||||
next;
|
||||
}
|
||||
$type_name_not_used{$type_name} = 0;
|
||||
$$type_names_used{$type_name} = $skip ? -1 : 1;
|
||||
next if $skip;
|
||||
|
||||
output_test_pack_type(\*OUT, $type_name2type, \%type_name2optional, \%type_name2optional_fields, $type_name, $type);
|
||||
output_test_pack_fields(\*OUT, $type_name2type, \%type_name2optional, \%type_name2optional_fields, $type_name, $type, 0);
|
||||
print OUT "static void test_${test}_$type_name(void)\n";
|
||||
print OUT "{\n";
|
||||
output_test_pack_type(\*OUT, $type_name2type, \%type_name2optional, \%type_name2optional_fields,
|
||||
$type_name, $type);
|
||||
output_test_pack_fields(\*OUT, $type_name2type, \%type_name2optional, \%type_name2optional_fields,
|
||||
$type_name, $type, 0);
|
||||
print OUT "}\n";
|
||||
print OUT "\n";
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $_type_name (@type_names) {
|
||||
my $type_name = $_type_name;
|
||||
|
||||
next if $type_name =~ /^!/;
|
||||
$type_name =~ s/:.*?$//;
|
||||
|
||||
if ($type_name_not_used{$type_name}) {
|
||||
# $output->write("$type_name: type not found (ignored)\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -788,18 +788,27 @@ sub output_file {
|
|||
my $test_dir = shift;
|
||||
my @tests = @{(shift)};
|
||||
|
||||
my $type_names_used = shift;
|
||||
|
||||
output_header(\*OUT, $test_dir, \@tests);
|
||||
|
||||
foreach my $test (@tests) {
|
||||
print OUT "void test_$test(void)\n";
|
||||
print OUT "{\n";
|
||||
my %type_names_used2;
|
||||
|
||||
if ($test eq "pack") {
|
||||
output_test_pack(\*OUT, $test_dir, $test);
|
||||
output_test_pack(\*OUT, $test_dir, $test, \%type_names_used2);
|
||||
} else {
|
||||
die "no such test ($test)\n";
|
||||
}
|
||||
|
||||
print OUT "static void test_$test(void)\n";
|
||||
print OUT "{\n";
|
||||
foreach my $type_name (sort(keys(%type_names_used2))) {
|
||||
$$type_names_used{$type_name} = $type_names_used2{$type_name};
|
||||
if ($type_names_used2{$type_name} > 0) {
|
||||
print OUT " test_${test}_$type_name();\n";
|
||||
}
|
||||
}
|
||||
print OUT "}\n";
|
||||
print OUT "\n";
|
||||
}
|
||||
|
@ -812,8 +821,38 @@ sub output_file {
|
|||
########################################################################
|
||||
# main
|
||||
|
||||
my %type_names_used = ();
|
||||
|
||||
my @test_dirs = $tests->get_test_dirs();
|
||||
foreach my $test_dir (@test_dirs) {
|
||||
my $file = "$wine_dir/$test_dir/generated.c";
|
||||
replace_file($file, \&output_file, $test_dir, \@tests);
|
||||
replace_file($file, \&output_file, $test_dir, \@tests, \%type_names_used);
|
||||
}
|
||||
|
||||
foreach my $header (sort(keys(%file2types))) {
|
||||
$output->prefix("$header: ");
|
||||
$header =~ s%^include/%%;
|
||||
my $type_name2type = $file2types{"include/$header"};
|
||||
foreach my $_type_name (sort(keys(%$type_name2type))) {
|
||||
my $type_name = $_type_name;
|
||||
|
||||
if (!exists($type_names_used{$type_name})) {
|
||||
$output->write("$type_name: type not used\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$output->prefix("$winapi_dir/tests.dat: ");
|
||||
foreach my $type_name (sort(keys(%type_names_used))) {
|
||||
my $found = 0;
|
||||
foreach my $header (sort(keys(%file2types))) {
|
||||
my $type_name2type = $file2types{"include/$header"};
|
||||
if (exists($type_name2type{$type_name})) {
|
||||
$found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
$output->write("$type_name: type not used\n");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue