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.3 2004/08/21 19:49:22 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" );
224 new_tokens
= snarf_tokens( line
);
225 tok
.splice( tok
.end(), new_tokens
);
226 tok
.push_back( "\n" );
233 complete_block( sl_it i
,
235 string start_ch
, string end_ch
) {
238 for( i
++; i
!= end
&& bc
; i
++ ) {
239 if( *i
== start_ch
) bc
++;
240 if( *i
== end_ch
) bc
--;
246 string
makename( string intro
) {
250 sprintf( buf
, "%s%d", intro
.c_str(), i
++ );
255 void append_block( sl_t
&t
, sl_it b
, sl_it e
) {
262 void error( sl_t
&container
, sl_it it
, string l
) {
264 for( sl_it i
= container
.begin(); i
!= it
; i
++ )
265 if( (*i
)[0] == '#' ) {
266 sscanf( i
->substr(1).c_str(), "%d", &line
);
267 cerr
<< "*standard-input*:" << line
<< ": " << l
;
271 /* Goal: match and transform one __try { a } __except [ (foo) ] { b }
272 * [ __finally { c } ]
276 * _SEH_FINALLY(name1) { c }
277 * _SEH_FILTER(name2) { return (foo | EXCEPTION_EXECUTE_HANDLER); }
278 * _SEH_TRY_FILTER_FINALLY(name1,name2) {
285 void handle_try( sl_t
&container
, sl_it try_kw
, sl_it end
) {
287 sl_t pseh_clause
, temp_tok
;
288 string finally_name
, filter_name
;
289 sl_it try_block
, try_block_end
, except_kw
, paren
, end_paren
,
290 except_block
, except_block_end
, todelete
,
291 finally_kw
, finally_block
, finally_block_end
, clause_end
;
295 try_block_end
= complete_block( try_block
, end
, "{", "}" );
297 if( try_block_end
== end
)
298 error( container
, try_block
, "unclosed try block");
300 except_kw
= try_block_end
;
302 if( *except_kw
== FINALLY_TOKEN
) {
303 finally_kw
= except_kw
;
308 except_block_end
= end
;
309 } else if( *except_kw
== EXCEPT_TOKEN
) {
312 if( *paren
== "(" ) {
313 end_paren
= complete_block( paren
, end
, "(", ")" );
314 except_block
= end_paren
;
316 except_block
= paren
;
320 except_block_end
= complete_block( except_block
, end
, "{", "}" );
321 finally_kw
= except_block_end
;
323 except_kw
= paren
= end_paren
= except_block
= except_block_end
=
324 finally_kw
= finally_block
= finally_block_end
= end
;
327 if( finally_kw
!= end
&& *finally_kw
!= FINALLY_TOKEN
) {
330 finally_block_end
= end
;
332 finally_block
= finally_kw
;
334 finally_block_end
= complete_block( finally_block
, end
, "{", "}" );
337 if( finally_block_end
!= end
) clause_end
= finally_block_end
;
338 else if( except_block_end
!= end
) clause_end
= except_block_end
;
339 else clause_end
= try_block_end
;
341 /* Skip one so that we can do != on clause_end */
343 /* Now for the output phase -- we've collected the whole seh clause
344 * and it lies between try_kw and clause_end */
346 finally_name
= makename("_Finally");
347 filter_name
= makename("_Filter");
349 pseh_clause
.push_back( "_SEH_FINALLY" );
350 pseh_clause
.push_back( "(" );
351 pseh_clause
.push_back( finally_name
);
352 pseh_clause
.push_back( ")" );
353 if( finally_kw
!= end
)
354 append_block( pseh_clause
, finally_block
, finally_block_end
);
356 pseh_clause
.push_back( "{" );
357 pseh_clause
.push_back( "}" );
360 pseh_clause
.push_back( "_SEH_FILTER" );
361 pseh_clause
.push_back( "(" );
362 pseh_clause
.push_back( filter_name
);
363 pseh_clause
.push_back( ")" );
364 pseh_clause
.push_back( "{" );
365 pseh_clause
.push_back( "return" );
367 append_block( pseh_clause
, paren
, end_paren
);
369 pseh_clause
.push_back( "EXCEPTION_EXECUTE_HANDLER" );
370 pseh_clause
.push_back( ";" );
371 pseh_clause
.push_back( "}" );
373 pseh_clause
.push_back( "_SEH_TRY_FILTER_FINALLY" );
374 pseh_clause
.push_back( "(" );
375 pseh_clause
.push_back( filter_name
);
376 pseh_clause
.push_back( "," );
377 pseh_clause
.push_back( finally_name
);
378 pseh_clause
.push_back( ")" );
379 append_block( pseh_clause
, try_block
, try_block_end
);
380 pseh_clause
.push_back( "_SEH_HANDLE" );
381 pseh_clause
.push_back( "{" );
382 if( except_block
!= end
)
383 append_block( pseh_clause
, except_block
, except_block_end
);
384 pseh_clause
.push_back( "}" );
385 pseh_clause
.push_back( "_SEH_END" );
386 pseh_clause
.push_back( ";" );
388 container
.splice( try_kw
, pseh_clause
);
389 while( try_kw
!= clause_end
) {
392 container
.erase( todelete
);
396 void print_tokens( sl_it begin
, sl_it end
) {
397 for( sl_it i
= begin
; i
!= end
; i
++ )
398 cout
<< /*"[" <<*/ *i
<< /*"]" <<*/ " ";
401 int main( int argc
, char **argv
) {
406 for( i
= 1; i
< argc
; i
++ ) {
407 if( string(argv
[i
]) == "-try" && i
< argc
- 1 ) {
410 } else if( string(argv
[i
]) == "-except" && i
< argc
- 1 ) {
412 EXCEPT_TOKEN
= argv
[i
];
413 } else if( string(argv
[i
]) == "-finally" && i
< argc
- 1 ) {
415 FINALLY_TOKEN
= argv
[i
];
419 /* XXX Uses much memory for large files */
420 while( expand_input(tok
) );
422 while( (try_found
= find( tok
.begin(), tok
.end(), TRY_TOKEN
)) !=
424 handle_try( tok
, try_found
, tok
.end() );
427 print_tokens( tok
.begin(), tok
.end() );