32fe8ff27c5df59c24b945e665192cc6c6c17f0f
3 * Copyright (C) 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: ms2ps.cpp,v 1.4 2004/08/21 19:59:52 arty Exp $
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS seh conversion tool
22 * FILE: tools/ms2ps/ms2ps.cpp
23 * PURPOSE: Conversion tool from msvc to pseh style seh
24 * PROGRAMMER: Art Yerkes
44 typedef std::list
<std::string
> sl_t
;
45 typedef sl_t::iterator sl_it
;
47 string TRY_TOKEN
= "__try";
48 string EXCEPT_TOKEN
= "__except";
49 string FINALLY_TOKEN
= "__finally";
50 char *c_operators
[] = {
58 int isident( int c
) {
59 return (c
!= '{') && (c
!= '}') && (c
!= '(') && (c
!= ')') &&
60 (c
!= '\'') && (c
!= '\"') && !isspace(c
);
63 bool areinclass( string str
, int (*isclass
)(int) ) {
66 for( i
= 0; i
< (int)str
.size(); i
++ )
67 if( !isclass( str
[i
] ) ) return false;
72 bool areident( string s
) { return areinclass( s
, isident
); }
74 bool isop( string tok
) {
76 for( i
= 0; c_operators
[i
] && tok
!= c_operators
[i
]; i
++ );
77 if( c_operators
[i
] ) return true; else return false;
80 enum fstate
{ EMPTY
, INT
, FRAC
, EXP
};
82 string
generic_match( string tok
, string la
,
83 bool (*mf
)( string
) ) {
84 if( tok
.size() < 1 ) return "";
85 if( mf(tok
) && !mf(la
) ) return tok
; else return "";
88 string
match_operator( string tok
, string la
) {
89 return generic_match( tok
, la
, isop
);
92 string
match_ident( string tok
, string la
) {
93 return generic_match( tok
, la
, areident
);
96 string
match_quoted_const( string tok
, string la
, char q
) {
97 if( ((tok
.size() && tok
[0] == q
) ||
98 ((tok
.size() > 2) && tok
[0] == 'L' && tok
[1] == q
)) &&
99 (tok
.rfind(q
) == (tok
.size() - 1)) ) {
100 if( (tok
.rfind("\\") != (tok
.size() - 2)) ||
101 (tok
.size() > 3 && tok
.rfind("\\\\") == (tok
.size() - 3)) )
108 sl_t
snarf_tokens( string line
) {
111 string curtok
, la
, op
, ident
, qconst
;
115 for( i
= 0; i
< (int)line
.size() - 1; i
++ ) {
116 /*cout << "Char [" << line[i] << "] and [" << line[i+1] << "]"
119 if( (!curtok
.size() ||
120 (curtok
[0] != '\'' && curtok
[0] != '\"')) &&
121 (curtok
.size() <= 2 ||
123 (curtok
[1] != '\'' && curtok
[1] != '\"')) &&
125 if( curtok
.size() ) out
.push_back( curtok
);
130 curtok
.push_back( line
[i
] );
132 la
= curtok
+ line
[i
+1];
134 op
= match_operator( curtok
, la
);
137 out
.push_back( op
MAYBE(+ "O") );
142 if( la
!= "L\"" && la
!= "L\'" ) {
143 ident
= match_ident( curtok
, la
);
146 out
.push_back( ident
MAYBE(+ "I") );
152 qconst
= match_quoted_const( curtok
, la
, '\'' );
155 out
.push_back( qconst
MAYBE(+ "q") );
160 qconst
= match_quoted_const( curtok
, la
, '\"' );
163 out
.push_back( qconst
MAYBE(+ "Q") );
172 istream
&getline_no_comments( istream
&is
, string
&line
) {
175 int seen_slash
= false;
177 while( (ch
= is
.get()) != -1 ) {
182 } while( ch
!= -1 && ch
!= '\n' && ch
!= '\r' );
184 } else if( ch
== '*' ) {
185 ch
= is
.get(); /* Skip one char */
190 } while( ch
!= '/' );
193 buf
+= '/'; buf
+= (char)ch
;
197 if( ch
== '/' ) seen_slash
= true;
198 else if( ch
== '\r' || ch
== '\n' ) break;
199 else buf
+= (char)ch
;
208 bool expand_input( sl_t
&tok
) {
213 out
= getline_no_comments( cin
, line
);
214 while( line
.size() && isspace( line
[0] ) )
215 line
= line
.substr( 1 );
216 if( line
[0] == '#' ) {
217 tok
.push_back( line
);
218 while( line
[line
.size()-1] == '\\' ) {
219 getline_no_comments( cin
, line
);
220 tok
.push_back( line
);
221 tok
.push_back( "\n" );
223 tok
.push_back( "\n" );
225 new_tokens
= snarf_tokens( line
);
226 tok
.splice( tok
.end(), new_tokens
);
227 tok
.push_back( "\n" );
234 complete_block( sl_it i
,
236 string start_ch
, string end_ch
) {
239 for( i
++; i
!= end
&& bc
; i
++ ) {
240 if( *i
== start_ch
) bc
++;
241 if( *i
== end_ch
) bc
--;
247 string
makename( string intro
) {
251 sprintf( buf
, "%s%d", intro
.c_str(), i
++ );
256 void append_block( sl_t
&t
, sl_it b
, sl_it e
) {
263 void error( sl_t
&container
, sl_it it
, string l
) {
265 for( sl_it i
= container
.begin(); i
!= it
; i
++ )
266 if( (*i
)[0] == '#' ) {
267 sscanf( i
->substr(1).c_str(), "%d", &line
);
268 cerr
<< "*standard-input*:" << line
<< ": " << l
;
272 /* Goal: match and transform one __try { a } __except [ (foo) ] { b }
273 * [ __finally { c } ]
277 * _SEH_FINALLY(name1) { c }
278 * _SEH_FILTER(name2) { return (foo | EXCEPTION_EXECUTE_HANDLER); }
279 * _SEH_TRY_FILTER_FINALLY(name1,name2) {
286 void handle_try( sl_t
&container
, sl_it try_kw
, sl_it end
) {
288 sl_t pseh_clause
, temp_tok
;
289 string finally_name
, filter_name
;
290 sl_it try_block
, try_block_end
, except_kw
, paren
, end_paren
,
291 except_block
, except_block_end
, todelete
,
292 finally_kw
, finally_block
, finally_block_end
, clause_end
;
296 try_block_end
= complete_block( try_block
, end
, "{", "}" );
298 if( try_block_end
== end
)
299 error( container
, try_block
, "unclosed try block");
301 except_kw
= try_block_end
;
303 if( *except_kw
== FINALLY_TOKEN
) {
304 finally_kw
= except_kw
;
309 except_block_end
= end
;
310 } else if( *except_kw
== EXCEPT_TOKEN
) {
313 if( *paren
== "(" ) {
314 end_paren
= complete_block( paren
, end
, "(", ")" );
315 except_block
= end_paren
;
317 except_block
= paren
;
321 except_block_end
= complete_block( except_block
, end
, "{", "}" );
322 finally_kw
= except_block_end
;
324 except_kw
= paren
= end_paren
= except_block
= except_block_end
=
325 finally_kw
= finally_block
= finally_block_end
= end
;
328 if( finally_kw
!= end
&& *finally_kw
!= FINALLY_TOKEN
) {
331 finally_block_end
= end
;
333 finally_block
= finally_kw
;
335 finally_block_end
= complete_block( finally_block
, end
, "{", "}" );
338 if( finally_block_end
!= end
) clause_end
= finally_block_end
;
339 else if( except_block_end
!= end
) clause_end
= except_block_end
;
340 else clause_end
= try_block_end
;
342 /* Skip one so that we can do != on clause_end */
344 /* Now for the output phase -- we've collected the whole seh clause
345 * and it lies between try_kw and clause_end */
347 finally_name
= makename("_Finally");
348 filter_name
= makename("_Filter");
350 pseh_clause
.push_back( "_SEH_FINALLY" );
351 pseh_clause
.push_back( "(" );
352 pseh_clause
.push_back( finally_name
);
353 pseh_clause
.push_back( ")" );
354 if( finally_kw
!= end
)
355 append_block( pseh_clause
, finally_block
, finally_block_end
);
357 pseh_clause
.push_back( "{" );
358 pseh_clause
.push_back( "}" );
361 pseh_clause
.push_back( "_SEH_FILTER" );
362 pseh_clause
.push_back( "(" );
363 pseh_clause
.push_back( filter_name
);
364 pseh_clause
.push_back( ")" );
365 pseh_clause
.push_back( "{" );
366 pseh_clause
.push_back( "return" );
368 append_block( pseh_clause
, paren
, end_paren
);
370 pseh_clause
.push_back( "EXCEPTION_EXECUTE_HANDLER" );
371 pseh_clause
.push_back( ";" );
372 pseh_clause
.push_back( "}" );
374 pseh_clause
.push_back( "_SEH_TRY_FILTER_FINALLY" );
375 pseh_clause
.push_back( "(" );
376 pseh_clause
.push_back( filter_name
);
377 pseh_clause
.push_back( "," );
378 pseh_clause
.push_back( finally_name
);
379 pseh_clause
.push_back( ")" );
380 append_block( pseh_clause
, try_block
, try_block_end
);
381 pseh_clause
.push_back( "_SEH_HANDLE" );
382 pseh_clause
.push_back( "{" );
383 if( except_block
!= end
)
384 append_block( pseh_clause
, except_block
, except_block_end
);
385 pseh_clause
.push_back( "}" );
386 pseh_clause
.push_back( "_SEH_END" );
387 pseh_clause
.push_back( ";" );
389 container
.splice( try_kw
, pseh_clause
);
390 while( try_kw
!= clause_end
) {
393 container
.erase( todelete
);
397 void print_tokens( sl_it begin
, sl_it end
) {
398 for( sl_it i
= begin
; i
!= end
; i
++ )
399 if( *i
== "\n" ) cout
<< *i
;
400 else cout
<< /*"[" <<*/ *i
<< /*"]" <<*/ " ";
403 int main( int argc
, char **argv
) {
408 for( i
= 1; i
< argc
; i
++ ) {
409 if( string(argv
[i
]) == "-try" && i
< argc
- 1 ) {
412 } else if( string(argv
[i
]) == "-except" && i
< argc
- 1 ) {
414 EXCEPT_TOKEN
= argv
[i
];
415 } else if( string(argv
[i
]) == "-finally" && i
< argc
- 1 ) {
417 FINALLY_TOKEN
= argv
[i
];
421 /* XXX Uses much memory for large files */
422 while( expand_input(tok
) );
424 while( (try_found
= find( tok
.begin(), tok
.end(), TRY_TOKEN
)) !=
426 handle_try( tok
, try_found
, tok
.end() );
429 print_tokens( tok
.begin(), tok
.end() );