@@ -32,6 +32,7 @@ use std::path::PathBuf;
3232
3333pub mod elf;
3434pub mod macho;
35+ pub mod pe;
3536
3637use crate :: error:: Warning ;
3738use crate :: platform;
@@ -117,6 +118,7 @@ impl Args {
117118 match PlatformKind :: host ( ) {
118119 PlatformKind :: Elf => Ok ( Args :: Elf ( elf:: ElfArgs :: new ( ) ?) ) ,
119120 PlatformKind :: MachO => Ok ( Args :: MachO ( macho:: MachOArgs :: new ( ) ?) ) ,
121+ PlatformKind :: Pe => Ok ( Args :: Pe ( pe:: PeArgs :: new ( ) ?) ) ,
120122 }
121123 }
122124
@@ -137,6 +139,7 @@ impl Args {
137139 match self {
138140 Args :: Elf ( args) => args. parse ( input) ,
139141 Args :: MachO ( args) => args. parse ( input) ,
142+ Args :: Pe ( args) => args. parse ( input) ,
140143 }
141144 }
142145
@@ -156,28 +159,33 @@ impl Args {
156159
157160 pub ( crate ) fn common ( & self ) -> & CommonArgs {
158161 match self {
159- Args :: Elf ( elf_args) => & elf_args. common ,
160- Args :: MachO ( macho_args) => & macho_args. common ,
162+ Args :: Elf ( args) => & args. common ,
163+ Args :: MachO ( args) => & args. common ,
164+ Args :: Pe ( args) => & args. common ,
161165 }
162166 }
163167
164168 pub ( crate ) fn common_mut ( & mut self ) -> & mut CommonArgs {
165169 match self {
166- Args :: Elf ( elf_args) => & mut elf_args. common ,
167- Args :: MachO ( macho_args) => & mut macho_args. common ,
170+ Args :: Elf ( args) => & mut args. common ,
171+ Args :: MachO ( args) => & mut args. common ,
172+ Args :: Pe ( args) => & mut args. common ,
168173 }
169174 }
170175}
171176
172177enum PlatformKind {
173178 Elf ,
174179 MachO ,
180+ Pe ,
175181}
176182
177183impl PlatformKind {
178184 fn host ( ) -> Self {
179185 if cfg ! ( target_os = "macos" ) {
180186 PlatformKind :: MachO
187+ } else if cfg ! ( target_os = "windows" ) {
188+ PlatformKind :: Pe
181189 } else {
182190 PlatformKind :: Elf
183191 }
@@ -426,13 +434,15 @@ pub struct ThreadPool {
426434pub enum Args {
427435 Elf ( elf:: ElfArgs ) ,
428436 MachO ( macho:: MachOArgs ) ,
437+ Pe ( pe:: PeArgs ) ,
429438}
430439
431440impl std:: fmt:: Debug for Args {
432441 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
433442 match self {
434443 Args :: Elf ( args) => args. fmt ( f) ,
435444 Args :: MachO ( args) => args. fmt ( f) ,
445+ Args :: Pe ( args) => args. fmt ( f) ,
436446 }
437447 }
438448}
@@ -550,10 +560,46 @@ pub(crate) enum UnresolvedSymbols {
550560 IgnoreAll ,
551561}
552562
563+ #[ derive( Clone , Copy ) ]
564+ enum OptionStyle {
565+ /// `--flag=value`, `-flag`, case-sensitive
566+ Unix ,
567+ /// `/FLAG:value`, case-insensitive
568+ Windows ,
569+ }
570+
571+ impl OptionStyle {
572+ fn strip_option ( self , arg : & str ) -> Option < & str > {
573+ match self {
574+ Self :: Unix => arg. strip_prefix ( "--" ) . or ( arg. strip_prefix ( '-' ) ) ,
575+ Self :: Windows => arg. strip_prefix ( '/' ) . or ( arg. strip_prefix ( '-' ) ) ,
576+ }
577+ }
578+
579+ fn has_option_prefix ( self , arg : & str ) -> bool {
580+ match self {
581+ Self :: Unix => arg. starts_with ( '-' ) ,
582+ Self :: Windows => arg. starts_with ( '/' ) || arg. starts_with ( '-' ) ,
583+ }
584+ }
585+
586+ fn find_separator ( self , stripped : & str ) -> Option < usize > {
587+ match self {
588+ Self :: Unix => stripped. find ( '=' ) ,
589+ Self :: Windows => stripped. find ( ':' ) ,
590+ }
591+ }
592+
593+ fn is_case_insensitive ( self ) -> bool {
594+ matches ! ( self , Self :: Windows )
595+ }
596+ }
597+
553598struct ArgumentParser < T > {
554599 options : HashMap < & ' static str , OptionHandler < T > > , // Long option lookup
555600 short_options : HashMap < & ' static str , OptionHandler < T > > , // Short option lookup
556601 prefix_options : HashMap < & ' static str , PrefixOptionHandler < T > > , // For options like -L, -l, etc.
602+ style : OptionStyle ,
557603}
558604
559605impl < T : platform:: Args > Default for ArgumentParser < T > {
@@ -569,6 +615,17 @@ impl<T: platform::Args> ArgumentParser<T> {
569615 options : HashMap :: new ( ) ,
570616 short_options : HashMap :: new ( ) ,
571617 prefix_options : HashMap :: new ( ) ,
618+ style : OptionStyle :: Unix ,
619+ }
620+ }
621+
622+ #[ must_use]
623+ fn new_windows ( ) -> Self {
624+ Self {
625+ options : HashMap :: new ( ) ,
626+ short_options : HashMap :: new ( ) ,
627+ prefix_options : HashMap :: new ( ) ,
628+ style : OptionStyle :: Windows ,
572629 }
573630 }
574631
@@ -608,6 +665,22 @@ impl<T: platform::Args> ArgumentParser<T> {
608665 }
609666 }
610667
668+ fn get_option_handler ( & self , option_name : & str ) -> Option < & OptionHandler < T > > {
669+ if self . style . is_case_insensitive ( ) {
670+ if let Some ( handler) = self . options . get ( option_name) {
671+ return Some ( handler) ;
672+ }
673+ for ( key, handler) in & self . options {
674+ if key. eq_ignore_ascii_case ( option_name) {
675+ return Some ( handler) ;
676+ }
677+ }
678+ None
679+ } else {
680+ self . options . get ( option_name)
681+ }
682+ }
683+
611684 fn handle_argument < S : AsRef < str > , I : Iterator < Item = S > > (
612685 & self ,
613686 args : & mut T ,
@@ -628,13 +701,12 @@ impl<T: platform::Args> ArgumentParser<T> {
628701 return Ok ( ( ) ) ;
629702 }
630703
631- if let Some ( stripped) = strip_option ( arg) {
632- // Check for option with '=' syntax
633- if let Some ( eq_pos) = stripped. find ( '=' ) {
704+ if let Some ( stripped) = self . style . strip_option ( arg) {
705+ if let Some ( eq_pos) = self . style . find_separator ( stripped) {
634706 let option_name = & stripped[ ..eq_pos] ;
635707 let value = & stripped[ eq_pos + 1 ..] ;
636708
637- if let Some ( handler) = self . options . get ( option_name) {
709+ if let Some ( handler) = self . get_option_handler ( option_name) {
638710 match & handler. handler {
639711 OptionHandlerFn :: WithParam ( f) => f ( args, modifier_stack, value) ?,
640712 OptionHandlerFn :: OptionalParam ( f) => f ( args, modifier_stack, Some ( value) ) ?,
@@ -644,14 +716,14 @@ impl<T: platform::Args> ArgumentParser<T> {
644716 }
645717 } else {
646718 if stripped == "build-id"
647- && let Some ( handler) = self . options . get ( stripped)
719+ && let Some ( handler) = self . get_option_handler ( stripped)
648720 && let OptionHandlerFn :: WithParam ( f) = & handler. handler
649721 {
650722 f ( args, modifier_stack, "fast" ) ?;
651723 return Ok ( ( ) ) ;
652724 }
653725
654- if let Some ( handler) = self . options . get ( stripped) {
726+ if let Some ( handler) = self . get_option_handler ( stripped) {
655727 match & handler. handler {
656728 OptionHandlerFn :: NoParam ( f) => f ( args, modifier_stack) ?,
657729 OptionHandlerFn :: WithParam ( f) => {
@@ -709,7 +781,6 @@ impl<T: platform::Args> ArgumentParser<T> {
709781 SubOptionHandler :: WithValue ( f) => f ( args, modifier_stack, param_value) ?,
710782 }
711783 } else {
712- // Fall back to the main handler
713784 ( handler. handler ) ( args, modifier_stack, & value) ?;
714785 }
715786 } else {
@@ -730,8 +801,8 @@ impl<T: platform::Args> ArgumentParser<T> {
730801 }
731802 }
732803
733- if arg . starts_with ( '-' ) {
734- if let Some ( stripped) = strip_option ( arg)
804+ if self . style . has_option_prefix ( arg ) {
805+ if let Some ( stripped) = self . style . strip_option ( arg)
735806 && IGNORED_FLAGS . contains ( & stripped)
736807 {
737808 args. warn_unsupported ( arg) ?;
@@ -1092,10 +1163,6 @@ impl<'a, T> OptionDeclaration<'a, T, WithOptionalParam> {
10921163 }
10931164}
10941165
1095- fn strip_option ( arg : & str ) -> Option < & str > {
1096- arg. strip_prefix ( "--" ) . or ( arg. strip_prefix ( '-' ) )
1097- }
1098-
10991166pub ( crate ) fn read_args_from_file ( path : & Path ) -> Result < Vec < String > > {
11001167 let contents = std:: fs:: read_to_string ( path)
11011168 . with_context ( || format ! ( "Failed to read arguments from file `{}`" , path. display( ) ) ) ?;
0 commit comments