#!/usr/bin/perl -W # # konw-nasm.pl - Skrypt konwertujacy pliki naglowkowe jezyka C na pliki naglowkowe dla NASMa # konw-nasm.pl - A script which converts C header files to NASM-compatible header files # # Copyright (C) 2006-2009 Bogdan 'bogdro' Drozdowski, http://rudy.mif.pg.gda.pl/~bogdro/inne/ # (bogdandr AT op.pl, bogdro AT rudy.mif.pg.gda.pl) # # Licencja / Licence: # Powszechna Licencja Publiczna GNU v3+ / GNU General Public Licence v3+ # # Ostatnia modyfikacja / Last modified : 2009-07-28 # # Sposob uzycia / Syntax: # ./konw-nasm.pl xxx.h [yyy.inc] # # Jesli nazwa pliku wyjsciowego nie zostanie podana, jest brana taka sama jak pliku # wejsciowego (tylko rozszerzenie sie zmieni na .inc). Jesli za nazwe # pliku wejsciowego podano "-", czytane jest standardowe wejscie. # Jesli nazwa pliku wyjsciowego to "-" (lub nie ma jej, gdy wejscie to stdin), # wynik bedzie na standardowym wyjsciu. # # If there's no output filename, then it is assumed to be the same as the # input filename (only the extension will be changed to .inc). If the # input filename is "-", standard input will be read. If the # output filename is "-" (or missing, when input is stdin), # the result will be written to the standard output. # # Niniejszy program jest wolnym oprogramowaniem; mozesz go # rozprowadzac dalej i/lub modyfikowac na warunkach Powszechnej # Licencji Publicznej GNU, wydanej przez Fundacje Wolnego # Oprogramowania - wedlug wersji 3-ciej tej Licencji lub ktorejs # z pozniejszych wersji. # # Niniejszy program rozpowszechniany jest z nadzieja, iz bedzie on # uzyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyslnej # gwarancji PRZYDATNOSCI HANDLOWEJ albo PRZYDATNOSCI DO OKRESLONYCH # ZASTOSOWAN. W celu uzyskania blizszych informacji - Powszechna # Licencja Publiczna GNU. # # Z pewnoscia wraz z niniejszym programem otrzymales tez egzemplarz # Powszechnej Licencji Publicznej GNU (GNU General Public License); # jesli nie - napisz do Free Software Foudation: # Free Software Foundation # 51 Franklin Street, Fifth Floor # Boston, MA 02110-1301 # USA # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 3 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foudation: # Free Software Foundation # 51 Franklin Street, Fifth Floor # Boston, MA 02110-1301 # USA use strict; use warnings; use Getopt::Long; my ($wyj); my ($help, $lic, $help_msg, $lic_msg); $help_msg = "$0:\n Skrypt konwertujacy pliki naglowkowe jezyka C na pliki naglowkowe dla NASMa\n". " / A script which converts C header files to NASM-compatible header files.\nAutor/Author: Bogdan Drozdowski, ". "http://rudy.mif.pg.gda.pl/~bogdro/inne/\n". "Skladnia/Syntax: $0 [--help] [--license] xxx.h [yyy.inc]\n\n Jesli nazwa pliku wyjsciowego nie zostanie podana, jest brana taka sama jak pliku wejsciowego (tylko rozszerzenie sie zmieni na .inc). Jesli za nazwe pliku wejsciowego podano \"-\", czytane jest standardowe wejscie. Jesli nazwa pliku wyjsciowego to \"-\" (lub nie ma jej, gdy wejscie to stdin), wynik bedzie na standardowym wyjsciu. If there's no output filename, then it is assumed to be the same as the input filename (only the extension will be changed to .inc). If the input filename is \"-\", standard input will be read. If the output filename is \"-\" (or missing, when input is stdin), the result will be written to the standard output.\n"; $lic_msg = "$0:\n Skrypt konwertujacy pliki naglowkowe jezyka C na pliki naglowkowe dla NASMa\n". " / A script which converts C header files to NASM-compatible header files.\nAutor/Author: Bogdan Drozdowski, ". "http://rudy.mif.pg.gda.pl/~bogdro/inne/\n\n". " Niniejszy program jest wolnym oprogramowaniem; mozesz go rozprowadzac dalej i/lub modyfikowac na warunkach Powszechnej Licencji Publicznej GNU, wydanej przez Fundacje Wolnego Oprogramowania - wedlug wersji 2-giej tej Licencji lub ktorejs z pozniejszych wersji. Niniejszy program rozpowszechniany jest z nadzieja, iz bedzie on uzyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyslnej gwarancji PRZYDATNOSCI HANDLOWEJ albo PRZYDATNOSCI DO OKRESLONYCH ZASTOSOWAN. W celu uzyskania blizszych informacji - Powszechna Licencja Publiczna GNU. Z pewnoscia wraz z niniejszym programem otrzymales tez egzemplarz Powszechnej Licencji Publicznej GNU (GNU General Public License); jesli nie - napisz do Free Software Foudation: Free Software Foundation 51 Franklin Street, Fifth Floor Boston, MA 02110-1301 USA This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foudation: Free Software Foundation 51 Franklin Street, Fifth Floor Boston, MA 02110-1301 USA\n"; if ( @ARGV == 0 ) { print $help_msg; exit 1; } Getopt::Long::Configure("ignore_case", "ignore_case_always"); if ( ! GetOptions( 'h|help|?' => \$help, 'license|licence|L' => \$lic ) ) { print $help_msg; exit 1; } if ( $lic ) { print $lic_msg; exit 1; } if ( @ARGV == 0 || $help ) { print $help_msg; exit 1; } if ( @ARGV > 1 && $ARGV[0] ne "-" && $ARGV[0] eq $ARGV[1] ) { print "$0: Plik wejsciowy i wyjsciowy NIE moga byc takie same.\n"; print "$0: Input file and output file must NOT be the same.\n"; exit 4; } ########################################################## # Otwieranie plikow (opening the files) my ($we, $wy); if ( !open ( $we, $ARGV[0] ) ) { # $! jest trescia bledu. ($! is the error message) print "$0: $ARGV[0]: $!\n"; exit 2; } if ( @ARGV > 1 ) { $wyj = $ARGV[1]; } else { # bierzemy tylko nazwe pliku (take only the filename) ($wyj = $ARGV[0]) =~ s/.*\/([^\/]+)/$1/; # Zmieniamy rozszerzenie z .h na .inc (change the extension from .h to .inc) $wyj =~ s/\.h$/\.inc/io; # Zmieniamy spacje na podkreslenia (change spaces to underlines) $wyj =~ s/\s+/_/go; if ( $wyj eq $ARGV[0] && $wyj ne "-" ) { $wyj .= ".inc"; } } if ( !open ( $wy, "> $wyj" ) ) { print "$0: $wyj: $!\n"; close $we; exit 3; } ########################################################## # Przetwarzanie (processing): CZYTAJ: while ( <$we> ) { # puste linie przepisujemy (empty lines go without change) if ( /^\s*$/o ) { print $wy "\n"; next; } # sklejanie wierszy (joining lines) while ( /[\\,]$/o ) { s/\\\n//o; $_ .= <$we>; } # sprawdzamy, czy komentarz jest jedyny na linii (check if a comment is the only thing on this line) if ( /^\s*\/\*.*\*\/\s*$/o ) { &komen(1); next; } # przetwarzanie dyrektyw kompilacji warunkowej (processing of conditional compiling directives) &kom_war(1); # Include'y (includes) if ( /\s*#\s*include/io ) { s/\s*#\s*include\s*[<\"]([\w\/\.]+)[>\"](.*)$/\%include "$1" $2 \n/i; # nazwa pliku ^^^^^^ (filename) print $wy "$_"; next; } # Extern'y (externs) if ( /^\s*extern/io ) { &komen(0); # extern "C" { if ( /\s*extern\s*\"C\"\s*{/io ) { s/\s*extern\s*\"C\"\s*{//io; print $wy "$_"; next; } # laczymy linie (joining lines) while ( ! /;/o ) { s/\n//o; $_ .= <$we>; } # extern'y funkcji (external functions) # najpier usuwamy (first remove): extern MACRO_NAME ( fcn name, args, ... ) s/\s*\w*\s*extern[\w\*\s]+\s+[A-Z0-9_\*]+\s*\(.*//io; # typ ^^^^^^ (type) # uwaga na rozne makra przed argumentami (look out for various macroes in front of the arguments) # poczatkowe \w* jest dla __attribute__ itp. (the leading \w* is for __attribute__ etc.) s/\s*\w*\s*extern[\w\*\s]+[A-Z0-9_\*]*\s+[\(\*\s]*([a-z0-9_]+)\s*\)*\s*[A-Z0-9_\*]*\s*\(.*/extern\t$1\n/i; # typ ^^^^^^ nazwa funkcji ^^^^^^^ makra ^^^^^^^ arg ^^ (type, name, macroes, arg) # extern'y zmiennych (external variables) s/\s*extern[\w\*\s]+\s+\**(\w+)\s*;/extern\t$1/i; # typ ^^^^^^ nazwa ^^^ (type, name) print $wy "$_"; next; } # typedef if ( /typedef/io ) { if ( /\(/o ) { while ( ! /\)/o or /,\s*$/o ) { s/\n//o; $_ .= <$we>; } } if ( /\(/o ) { s/^.*$/\n/o; } elsif ( !/{/ && /;/ ) { s/\s*typedef([\w\*\s]+)\s+\**(\w+)\s*;/$2\tequ\t$1/i; print $wy "$_"; next CZYTAJ; } # stary typ ^^^^^^ nowy^^^ (old type, new) # "typedef struct ...." ----> "struct ....." elsif ( /(struct|union|enum)/io ) { s/\s*typedef\s+//io; } # to nie ma NEXT (no NEXT here). } # Struktury (structures): # Pomijamy wyrazenia typu: (skip over expressions of the type): # struct xxx; # struct xxx function(arg1, ...); if ( /^\s*struct/io && ! /^\s*struct[^\{]+;.*$/io && !/\(/ ) { # pomijamy (skip over) "struct foo;" if ( /^\s*struct\s*\w+\s*;/io ) { next; } # nazwa struktury (the name of the structure) s/\s*struct\s+(\w+)/struc\t$1 /i; my $nazwa; if ( $1 and $1 ne "" and $1 !~ /\{/o ) { $nazwa = $1; } else { $nazwa = ""; } # jesli byl '{' w pierwszej linii, dajemy go do drugiej # (if there was a '{' in the first line, we put it in the second) s/\s*\{/\n\{\n/; # struktura moze sie konczyc w tej samej linijce lub zawierac wiele deklaracji na linie # po prostu stawiamy znak nowej linii za kazdym srednikiem i idziemy dalej # (a structure can end in the same line or contain many declaration per line # we simply put a newline after each semicolon and go on) s/;/;\n/go; # zmiana komentarzy (changing the comments) &komen(1); do { # sklejanie wierszy (joining lines) while ( /[\\,]$/o ) { s/\\\n//o; $_ .= <$we>; } # wiele zmiennych tego samego typu - dajemy kazda do osobnej linii wraz z typem # (many variables of the same type - we put each on a separate line together with its type) if ( /\/\*/o ) { while ( /,\s*$/o ) { s/\n//o; $_ .= <$we>; } while ( /,.*\/\*/o && !/\(/o ) { if ( /\[.*\/\*/o ) { s/([\w ]*)\s+(\w+)\s*(\[\w+\]),\s*(.*)/$1 $2$3;\n$1 $4/; } else { s/([\w ]*)\s+([\w\*]+)\s*,\s*(.*)/$1 $2;\n$1 $3/; } # typ^^^ nazwa ^^^^ ^ ^^ (type, name) } } else { while ( /,\s*$/o ) { s/\n//o; $_ .= <$we>; } while ( /,.*/o && !/\(/o ) { if ( /\[.*/o ) { s/([\w ]*)\s+(\w+)\s*(\[\w+\]),\s*(.*)/$1 $2$3;\n$1 $4/; } else { s/([\w ]*)\s+([\w\*]+)\s*,\s*(.*)/$1 $2;\n$1 $3/; } # typ^^^ nazwa ^^^^ ^ ^^ (type, name) } } # zmiana komentarzy (changing the comments) &komen(0); if ( /^\s*union\s+(\w+)/io ) { my $roz = &zrob_unie(0); print $wy "\t.$1\trb $roz\n" if $roz; goto STR_END; } if ( /^\s*union/io ) { my $roz = &zrob_unie(1); #print $wy "\t\trb $roz\n" if $roz; goto STR_END; } # najpierw pozbywamy sie ":cyfra" w polach struktur # (first we remove the ":digit" from the structure fields) s/(.*):\s*\d+\s*/$1/g; # pomijamy (skip over) 'volatile' s/_*volatile_*//gio; # wskazniki do funkcji (pointers to functions) s/.+\(\s*\*\s*(\w+)\s*\)\s*\(.*\)\s*;/\t\.$1:\t\tresd 1/g; # typ wskaznikowy (pointer type) s/.+\*\s*(\w+)\s*;/\t\.$1:\t\tresd 1/g; # tablice (arrays) s/.*struct\s+(\w+)\s+(\w+)\s*\[(\w+)\]\s*;/\t\.$2:\t\t$1/gi; s/.*(signed|unsigned)?\s+long\s+long(\s+int)?\s+(\w+)\s*\[(\w+)\]\s*;/\t\.$3:\t\tresq $4/gi; s/.*long\s+double\s+(\w+)\s*\[(\w+)\]\s*;/\t\.$1:\t\trest $2/gi; s/.*(char|unsigned\s+char|signed\s+char)\s+(\w+)\s*\[(\w+)\]\s*;/\t\.$2:\t\tresb $3/gi; s/.*float\s+(\w+)\s*\[(\w+)\]\s*;/\t\.$1:\t\tresd $2/gi; s/.*double\s+(\w+)\s*\[(\w+)\]\s*;/\t\.$1:\t\tresq $2/gi; s/.*(short|signed\s+short|unsigned\s+short){1}(\s+int)?\s+(\w+)\s*\[(\w+)\]\s*;/\t\.$3:\t\tresw $4/gi; s/.*(long|signed|signed\s+long|unsigned|unsigned\s+long|int){1}(\s+int)?\s+(\w+)\s*\[(\w+)\]\s*;/\t\.$3:\t\tresd $4/gi; # typy zmiennych (variables' types) # wszystkie "\w+" oznaczaja nazwe zmiennej (all "\w+" stand for the variable name) s/.*struct\s+(\w+)\s+(\w+)\s*;/\t\.$2:\t\t$1/gi; s/.*(signed|unsigned)?\s+long\s+long(\s+int)?\s+(\w+)\s*;/\t\.$3:\t\tresq 1/gi; s/.*long\s+double\s+(\w+)\s*;/\t\.$1:\t\trest 1/gi; s/.*(char|unsigned\s+char|signed\s+char)\s+(\w+)\s*;/\t\.$2:\t\tresb 1/gi; s/.*float\s+(\w+)\s*;/\t\.$1:\t\tresd 1/gi; s/.*double\s+(\w+)\s*;/\t\.$1:\t\tresq 1/gi; s/.*(short|signed\s+short|unsigned\s+short){1}(\s+int)?\s+(\w+)\s*;/\t\.$3:\t\tresw 1/gi; s/.*(long|signed|signed\s+long|unsigned|unsigned\s+long|int){1}(\s+int)?\s+(\w+)\s*;/\t\.$3:\t\tresd 1/gi; # szukamy konca struktury (look for the end of the structure) if ( /\s*\}.*/o ) { # dolaczamy definicje rozmiaru struktury (add a structure size definition) #if ( $nazwa ne "" && $nazwa !~/\{/ ) # { s/\s*\}.*/\n\t${nazwa}_size\t=\t\$ - .\n\}\n/; } #else { s/\s*\}.*/\nendstruc\n/o; #} print $wy "$_"; next CZYTAJ; } # przetwarzanie dyrektyw kompilacji warunkowej (processing of conditional compiling directives) &kom_war(0); print $wy "$_"; STR_END: } while ( <$we> ); next CZYTAJ; } # enum if ( /^\s*enum/io ) { # usuwamy slowo enum i jego nazwe (remove the 'enum' and its name) s/.*enum\s+\w+\s*\{?//io; my $wartosc = 0; # sprawdzamy 1-linijkowe (check if one-line enum) if ( /}/o ) { # zmiana komentarzy (changing the comments) &komen(1); # nie ma dyrektyw kompilacji warunkowej (there are no conditional compiling directives) #&kom_war(0); while ( /,.*;/o ) { s/([\w\s]*)\s+(\w+)\s*=\s*(\w+)\s*,/$1\n$2\tequ\t$3/ and $wartosc = $3+1; # ^^^^ ^^^ ^^^ cokolwiek, nazwa, wartosc (anything, name, value) s/([\w\s]*)\s+(\w+)\s*,/$1\n$2\tequ\t$wartosc/ and $wartosc++; } # ostatnia linia nie ma przecinka (the last line has no comma) s/([\w\s]*)\s+(\w+)\s*=\s*(\w+)\s*\}\s*;/$1\n$2\tequ\t$3\n/; s/([\w\s]*)\s+(\w+)\s*\}\s*;/$1\n$2\tequ\t$wartosc/; print $wy "$_"; next CZYTAJ; } while ( <$we> ) { # zmiana komentarzy (changing the comments) &komen(1); # przetwarzanie dyrektyw kompilacji warunkowej (processing of conditional compiling directives) if ( /^\s*#/o ) { &kom_war(1); next; } # pomiajmy pierwszy znak '{' (skip over the first '{' character) if ( /^\s*\{\s*$/o ) { next; } # jesli stala ma przypisana wartosc, nie ruszamy jej # (if the constant has a value, we don't touch it) if ( ! /=/o ) { s/\s*(\w+)\s*,?/$1\tequ\t$wartosc/; $wartosc++; } else { # przypisujemy kolejna wartosc # (assign a subsequent value) s/\s*(\w+)\s*=\s*(\w+)\s*,?/$1\tequ\t$2/; $wartosc = $2 + 1; } # szukamy konca enum (look for the end of the enum) if ( /\s*\}.*/o ) { next CZYTAJ; } print $wy "$_"; }; } if ( /union/io ) { &zrob_unie(1); next; } # zmiana komentarzy (change the comments) &komen(1); } # koniec petli CZYTAJ (end of CZYTAJ loop) ########################################################## # Zmiana komentarzy (changing the comments): sub komen { # parametr = 0 => nie ma drukowania (when the parameter is 0, there will be no printing) my $drukuj = shift; # Komentarze jednolinijkowe (one-line comments): if ( /(.+)\/\*(.*)\*\/(.+)$/o ) { s/(.+)\/\*(.*)\*\/(.+)$/$1 $3 ; $2/g; return $_; } if ( /\/\*(.*)\*\/(.+)$/o ) { s/\/\*(.*)\*\/(.+)$/$2 ; $1/g; return $_; } if ( /(.+)\/\*(.*)\*\/$/o ) { s/(.+)\/\*(.*)\*\/$/$1 ; $2/g; return $_; } # Jesli komentarz jest jedyna rzecza w wierszu, to od razu go wypisujemy i idziemy dalej # (if the comment is the only thing on this line, we print it to the file and go further) if ( /^\/\*(.*)\*\/$/o ) { s/\/\*(.*)\*\/$/; $1/g; print $wy "$_" if $drukuj; return $_; } # Komentarze wielolinijkowe (multi-line comments) if ( /(.*)\/\*(.*)$/o ) { # wyrzucamy /* z zachowaniem tego, co bylo przed tym # (we remove the /*, saving whatever was in front of it) s/(.*)\/\*(.*)$/$1; $2/; print $wy "$_" if $drukuj; while ( <$we> ) { # po prostu stawiamy srednik przed kazda linia # (we simply add a semicolon in front of every line) s/^(.*)$/; $1/; # jak trafimy na */, to go kasujemy i przerywamy ta petle # (when we find */, we remove it and stop this loop) if ( /\*\//o ) { s/\*\///o; print $wy "$_" if $drukuj; $_ =""; return;# $_; } print $wy "$_" if $drukuj; } } } ########################################################## # Kompilacja warunkowa (conditional compiling) sub kom_war { # parametr = 0 => nie ma drukowania (when the parameter is 0, there will be no printing) my $drukuj = shift; # zmiana komentarzy (changing the comments) &komen($drukuj); # sklejanie wierszy (joining lines) while ( /\\$/o ) { s/\\\n//o; $_ .= <$we>; } # pomijamy makra (skip over macros) if ( /^\s*\#\s*define\s+\w+\s*\(/io ) { s/\s*\#\s*define\s+\w+\s*\(.*/\n/io; return; } # Definicje stalych #define (definitions of #define constants) if ( /^\s*#\s*define\s+/io ) { # bez wartosci - ustawiamy na 1; zasieg: assembler (without a value - set to 1; scope: assembler) s/\s*#\s*define\s+(\w+)\s*$/\%define\t$1\t1\n/i; # z wartoscia; zasieg: assembler (with a value; scope: assembler) # dopuszczamy "(-cyfry)" / "(-digits)" is allowed s/\s*#\s*define\s+(\w+)\s*(\(?-?\d+\)?)/\%define\t$1\t$2\n/i; # z wartoscia nienumeryczna; zasieg: preprocesor (with a non-number value; scope: preprocessor) s/\s*#\s*define\s+(\w+)\s*([\w\"\(\)\-\+]*)/\%define\t$1\t$2/i; if ( $drukuj ) { print $wy "$_"; } } # Kompilacja warunkowa (conditional compiling) if ( /^\s*#\s*ifdef/io ) { s/\s*#\s*ifdef(.*)$/\%ifdef\t$1/i; if ( $drukuj ) { print $wy "$_"; } } if ( /^\s*#\s*ifndef/io ) { s/\s*#\s*ifndef(.*)$/\%ifndef\t$1/i; if ( $drukuj ) { print $wy "$_"; } } if ( /^\s*#\s*endif/io ) { s/\s*#\s*endif.*$/\%endif/io; if ( $drukuj ) { print $wy "$_"; } } if ( /^\s*#\s*else\s+if/io ) { s/\s*#\s*else\s+if(.*)$/\%elif\t$1/i; if ( $drukuj ) { print $wy "$_"; } } if ( /^\s*#\s*else/io ) { s/\s*#\s*else(.*)$/\%else\t$1/i; if ( $drukuj ) { print $wy "$_"; } } if ( /^\s*#\s*if/io ) { s/\s*#\s*if(.*)$/\%if\t$1/i; # s/!\s*defined\s+(\w+)/~(defined $1)/g; # s/!\s*defined\s+(\w+)/($1 || $1 = 0)/g; # if ( /~defined/ ) { s/$/\n\@\@:\n/; }; if ( $drukuj ) { print $wy "$_"; } } if ( /^\s*#\s*error/io || /^\s*#\s*warning/io ) { s/\s*#\s*(error|warning)(.*)$/\%error\t$2/i; if ( $drukuj ) { print $wy "$_"; } } } ########################################################## # Unie (unions) sub zrob_unie { # parametr = 0 => nie ma drukowania (when the parameter is 0, there will be no printing) my $drukuj = shift; # pomijamy (skip over) "union foo;" if ( /\s*union\s*\w+\s*;/io ) { return 0; } # nazwa unii (the name of the union) s/\s*union\s+(\w+)/struc\t$1 /i; my $nazwa; if ( $1 and $1 ne "" and $1 !~ /\{/o ) { $nazwa = $1; } else { $nazwa = ""; } my $rozmiar = 0; # jesli byl '{' w pierwszej linii, dajemy go do drugiej # (if there was a '{' in the first line, we put it in the second) if ( ! /union/io ) { s/\s*\{/\n\{\n/o; } else { s/\s*union\s*{//io; s/\s*union//io; }; # unia moze sie konczyc w tej samej linijce lub zawierac wiele deklaracji na linie # po prostu stawiamy znak nowej linii za kazdym srednikiem i idziemy dalej # (an union can end in the same line or contain many declaration per line # we simply put a newline after each semicolon and go on) s/;/;\n/go; do { if ( $nazwa eq "" ) { s/\{//go; } # zmiana komentarzy (changing the comments) &komen; # typ wskaznikowy (pointer type) if ( /.+\*\s*(\w+)\s*;/o ) { s/.+\*\s*(\w+)\s*;/\t\.$1:/g; $rozmiar = max($rozmiar, 4); } # typy zmiennych (variables' types) # wszystkie "\w+" oznaczaja nazwe zmiennej (all "\w+" stand for the variable name) #s/.*struct\s+(\w+)\s+(\w+)\s*;/\t\.$2\t\t$1/g; if ( /.*(signed|unsigned)?\s+long\s+long(\s+int)?\s+(\w+)\s*;/io ) { s/.*(signed|unsigned)?\s+long\s+long(\s+int)?\s+(\w+)\s*;/\t\.$3:/gi; $rozmiar = max($rozmiar, 8); } if ( /.*long\s+double\s+(\w+)\s*;/io ) { s/.*long\s+double\s+(\w+)\s*;/\t\.$1:/gi; $rozmiar = max($rozmiar, 10); } if ( /.*(char|unsigned\s+char|signed\s+char)\s+(\w+)\s*;/io ) { s/.*(char|unsigned\s+char|signed\s+char)\s+(\w+)\s*;/\t\.$2:/gi; $rozmiar = max($rozmiar, 1); } if ( /.*float\s+(\w+)\s*;/io ) { s/.*float\s+(\w+)\s*;/\t\.$1:/gi; $rozmiar = max($rozmiar, 4); } if ( /.*double\s+(\w+)\s*;/io ) { s/.*double\s+(\w+)\s*;/\t\.$1:/gi; $rozmiar = max($rozmiar, 8); } if ( /.*(short|signed\s+short|unsigned\s+short){1}(\s+int)?\s+(\w+)\s*;/io ) { s/.*(short|signed\s+short|unsigned\s+short){1}(\s+int)?\s+(\w+)\s*;/\t\.$3:/gi; $rozmiar = max($rozmiar, 2); } if ( /.*(long|signed|signed\s+long|unsigned|unsigned\s+long|int){1}(\s+int)?\s+(\w+)\s*;/io ) { s/.*(long|signed|signed\s+long|unsigned|unsigned\s+long|int){1}(\s+int)?\s+(\w+)\s*;/\t\.$3:/gi; $rozmiar = max($rozmiar, 4); } # tablice (arrays) if ( /.*(signed|unsigned)?\s+long\s+long(\s+int)?\s+(\w+)\s*\[(\d+)\]\s*;/io ) { s/.*(signed|unsigned)?\s+long\s+long(\s+int)?\s+(\w+)\s*\[(\d+)\]\s*;/\t\.$3:/gi; $rozmiar = max($rozmiar, 8*$4); } if ( /.*long\s+double\s+(\w+)\s*\[(\d+)\]\s*;/io ) { s/.*long\s+double\s+(\w+)\s*\[(\d+)\]\s*;/\t\.$1:/gi; $rozmiar = max($rozmiar, 10*$2); } if ( /.*(char|unsigned\s+char|signed\s+char)\s+(\w+)\s*\[(\d+)\]\s*;/io ) { s/.*(char|unsigned\s+char|signed\s+char)\s+(\w+)\s*\[(\d+)\]\s*;/\t\.$2:/gi; $rozmiar = max($rozmiar, 1*$3); } if ( /.*float\s+(\w+)\s*\[(\d+)\]\s*;/io ) { s/.*float\s+(\w+)\s*\[(\d+)\]\s*;/\t\.$1:/gi; $rozmiar = max($rozmiar, 4*$2); } if ( /.*double\s+(\w+)\s*\[(\d+)\]\s*;/io ) { s/.*double\s+(\w+)\s*\[(\d+)\]\s*;/\t\.$1:/gi; $rozmiar = max($rozmiar, 8*$2); } if ( /.*(short|signed\s+short|unsigned\s+short){1}(\s+int)?\s+(\w+)\s*\[(\d+)\]\s*;/i ) { s/.*(short|signed\s+short|unsigned\s+short){1}(\s+int)?\s+(\w+)\s*\[(\d+)\]\s*;/\t\.$3:/gi; $rozmiar = max($rozmiar, 2*$4); } if ( /.*(long|signed|signed\s+long|unsigned|unsigned\s+long|int){1}(\s+int)?\s+(\w+)\s*\[(\d+)\]\s*;/io ) { s/.*(long|signed|signed\s+long|unsigned|unsigned\s+long|int){1}(\s+int)?\s+(\w+)\s*\[(\d+)\]\s*;/\t\.$3:/gi; $rozmiar = max($rozmiar, 4*$4); } # szukamy konca unii (look for the end of the union) if ( /\s*\}.*/o ) { s/\s*\}\s*(\w+)\s*;/\t.$1:\n}\n/; s/\s*\}.*/\t\trb\t$rozmiar/; if ( $nazwa ne "" ) { $_ .= "\n}\n"; } # dolaczamy definicje rozmiar unii (add an union size definition) if ( $nazwa ne "" ) { $_ .= "\n\t${nazwa}_size\t=\t$rozmiar\n"; } if ( $drukuj ) { print $wy "$_"; } return $rozmiar; } # przetwarzanie dyrektyw kompilacji warunkowej (processing of conditional compiling directives) &kom_war(0); if ( $drukuj ) { print $wy "$_"; } } while ( <$we> ); } sub max { my $a=shift, $b=shift; return $a if $a > $b; return $b; } ########################################################## # Koniec (the end): close $wy; close $we;