From c6a8fb89efd2a586d6ce44fae92d32571c624843 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 19 Jun 2007 13:24:33 +0000 Subject: * Makefile.am: Add windmc tool. * Makefile.in: Regenerate. * configure.in: Add windmc tool. * configure: Regenerate. * mclex.c: New. * mcparse.y: New. * windmc.c: New. * windmc.h: New. * doc/Makefile.am: Add windmc tool. * doc/Makefile.in: Regenerate. * doc/binutils.texi: Add windmc documentation. * NEWS: Mention new tool. --- binutils/ChangeLog | 17 +- binutils/Makefile.am | 42 +- binutils/Makefile.in | 101 ++-- binutils/NEWS | 10 +- binutils/configure | 19 +- binutils/configure.in | 16 + binutils/doc/Makefile.am | 8 + binutils/doc/Makefile.in | 13 +- binutils/doc/binutils.texi | 167 ++++++ binutils/mclex.c | 441 ++++++++++++++++ binutils/mcparse.y | 356 +++++++++++++ binutils/windmc.c | 1197 ++++++++++++++++++++++++++++++++++++++++++++ binutils/windmc.h | 99 ++++ 13 files changed, 2443 insertions(+), 43 deletions(-) create mode 100644 binutils/mclex.c create mode 100644 binutils/mcparse.y create mode 100644 binutils/windmc.c create mode 100644 binutils/windmc.h (limited to 'binutils') diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 18568bbea6..c210ccc956 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,18 @@ +2007-06-19 Kai Tietz + + * Makefile.am: Add windmc tool. + * Makefile.in: Regenerate. + * configure.in: Add windmc tool. + * configure: Regenerate. + * mclex.c: New. + * mcparse.y: New. + * windmc.c: New. + * windmc.h: New. + * doc/Makefile.am: Add windmc tool. + * doc/Makefile.in: Regenerate. + * doc/binutils.texi: Add windmc documentation. + * NEWS: Mention new tool. + 2007-06-18 Andi Kleen * objdump.c: Include sys/mman.h @@ -28,7 +43,7 @@ * winduni.h: (wind_default_codepage, wind_current_codepage): Export. * doc/binutils.texi: Document new option. - * NEWS: Mention new feature. + * NEWS: Mention new features of windres. 2007-06-18 Brian D. Watt diff --git a/binutils/Makefile.am b/binutils/Makefile.am index 3b36d1578a..24a34fd73e 100644 --- a/binutils/Makefile.am +++ b/binutils/Makefile.am @@ -48,18 +48,19 @@ ADDR2LINE_PROG=addr2line NLMCONV_PROG=nlmconv DLLTOOL_PROG=dlltool WINDRES_PROG=windres +WINDMC_PROG=windmc DLLWRAP_PROG=dllwrap SRCONV_PROG=srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT) -bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_INSTALL_MISC@ +bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ @BUILD_WINDMC@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_INSTALL_MISC@ ## We need a special rule to install the programs which are built with ## -new, and to rename cxxfilt to c++filt. RENAMED_PROGS = $(NM_PROG) $(STRIP_PROG) $(DEMANGLER_PROG) noinst_PROGRAMS = $(RENAMED_PROGS) @BUILD_MISC@ -EXTRA_PROGRAMS = $(NLMCONV_PROG) srconv sysdump coffdump $(DLLTOOL_PROG) $(WINDRES_PROG) $(DLLWRAP_PROG) +EXTRA_PROGRAMS = $(NLMCONV_PROG) srconv sysdump coffdump $(DLLTOOL_PROG) $(WINDRES_PROG) $(WINDMC_PROG) $(DLLWRAP_PROG) # Stuff that goes in tooldir/ if appropriate. TOOL_PROGS = nm-new strip-new ar ranlib dlltool objdump objcopy @@ -80,9 +81,10 @@ INCLUDES = -D_GNU_SOURCE \ HFILES = \ arsup.h binemul.h bucomm.h budbg.h \ coffgrok.h debug.h dlltool.h nlmconv.h \ - windres.h winduni.h windint.h + windres.h winduni.h windint.h \ + windmc.h -GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h rcparse.h +GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h rcparse.h mcparse.h CFILES = \ addr2line.c ar.c arsup.c bin2c.c binemul.c bucomm.c \ @@ -95,11 +97,12 @@ CFILES = \ rclex.c rdcoff.c rddbg.c readelf.c rename.c \ resbin.c rescoff.c resrc.c resres.c \ size.c srconv.c stabs.c strings.c sysdump.c version.c \ - windres.c winduni.c wrstabs.c + windres.c winduni.c wrstabs.c \ + windmc.c mclex.c GENERATED_CFILES = \ arparse.c arlex.c sysroff.c sysinfo.c syslex.c \ - defparse.c deflex.c nlmheader.c rcparse.c + defparse.c deflex.c nlmheader.c rcparse.c mcparse.c DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c @@ -198,6 +201,7 @@ sysdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) coffdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) dlltool_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) windres_DEPENDENCIES = $(LIBINTL_DEP) $(LIBICONV) $(LIBIBERTY) $(BFDLIB) +windmc_DEPENDENCIES = $(LIBINTL_DEP) $(LIBICONV) $(LIBIBERTY) $(BFDLIB) addr2line_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) readelf_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) dllwrap_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) @@ -290,6 +294,7 @@ arparse.h: arparse.c defparse.h: defparse.c nlmheader.h: nlmheader.c rcparse.h: rcparse.c +mcparse.h: mcparse.c sysinfo.h: sysinfo.c # Disable -Werror, if it has been enabled, since old versions of bison/ @@ -308,8 +313,12 @@ nlmheader.o: $(COMPILE) -c $< $(NO_WERROR) rcparse.o: $(COMPILE) -c $< $(NO_WERROR) +mcparse.o: + $(COMPILE) -c $< $(NO_WERROR) rclex.o: $(COMPILE) -c $< $(NO_WERROR) +mclex.o: + $(COMPILE) -c $< $(NO_WERROR) srconv_SOURCES = srconv.c coffgrok.c $(BULIBS) @@ -338,12 +347,17 @@ windres_SOURCES = windres.c resrc.c rescoff.c resbin.c rcparse.y rclex.c \ winduni.c resres.c $(BULIBS) windres_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL) +windmc_SOURCES = windmc.c mcparse.y mclex.c \ + winduni.c $(BULIBS) +windmc_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL) + dllwrap_SOURCES = dllwrap.c version.c dllwrap_LDADD = $(LIBIBERTY) $(LIBINTL) EXTRA_DIST = arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \ - syslex.c deflex.c defparse.h defparse.c rcparse.h rcparse.c + syslex.c deflex.c defparse.h defparse.c rcparse.h rcparse.c \ + mcparse.h mcparse.c diststuff: $(EXTRA_DIST) info all: info @@ -626,6 +640,11 @@ windres.o: windres.c sysdep.h $(INCDIR)/ansidecl.h \ $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \ $(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h $(INCDIR)/obstack.h \ bucomm.h windres.h winduni.h windint.h +windmc.o: windmc.c sysdep.h $(INCDIR)/ansidecl.h \ + ../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \ + $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \ + $(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h $(INCDIR)/obstack.h \ + bucomm.h windmc.h winduni.h windint.h winduni.o: winduni.c sysdep.h $(INCDIR)/ansidecl.h \ ../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \ $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h winduni.h $(INCDIR)/safe-ctype.h @@ -659,8 +678,17 @@ rcparse.o: rcparse.c sysdep.h $(INCDIR)/ansidecl.h \ $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \ $(INCDIR)/ansidecl.h windres.h winduni.h windint.h \ $(INCDIR)/safe-ctype.h +mcparse.o: mcparse.c sysdep.h $(INCDIR)/ansidecl.h \ + ../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \ + $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \ + $(INCDIR)/ansidecl.h windmc.h winduni.h \ + $(INCDIR)/safe-ctype.h rclex.o: rclex.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \ config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \ $(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \ $(INCDIR)/safe-ctype.h windres.h winduni.h windint.h rcparse.h +mclex.o: mclex.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \ + config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/safe-ctype.h windmc.h winduni.h mcparse.h # IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/binutils/Makefile.in b/binutils/Makefile.in index f43cfc07fe..6ce70d5ffc 100644 --- a/binutils/Makefile.in +++ b/binutils/Makefile.in @@ -37,23 +37,23 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -bin_PROGRAMS = $(am__EXEEXT_5) $(am__EXEEXT_6) $(am__EXEEXT_7) \ - $(am__EXEEXT_8) $(am__EXEEXT_9) $(am__EXEEXT_10) \ +bin_PROGRAMS = $(am__EXEEXT_6) $(am__EXEEXT_7) $(am__EXEEXT_8) \ + $(am__EXEEXT_9) $(am__EXEEXT_10) $(am__EXEEXT_11) \ @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ \ - $(am__EXEEXT_11) $(am__EXEEXT_12) @BUILD_DLLWRAP@ \ - @BUILD_INSTALL_MISC@ $(am__empty) -noinst_PROGRAMS = $(am__EXEEXT_16) @BUILD_MISC@ + @BUILD_WINDMC@ $(am__EXEEXT_12) $(am__EXEEXT_13) \ + @BUILD_DLLWRAP@ @BUILD_INSTALL_MISC@ $(am__empty) +noinst_PROGRAMS = $(am__EXEEXT_17) @BUILD_MISC@ EXTRA_PROGRAMS = $(am__EXEEXT_1) srconv$(EXEEXT) sysdump$(EXEEXT) \ coffdump$(EXEEXT) $(am__EXEEXT_2) $(am__EXEEXT_3) \ - $(am__EXEEXT_4) + $(am__EXEEXT_4) $(am__EXEEXT_5) DIST_COMMON = $(srcdir)/../config.guess $(srcdir)/../config.sub NEWS \ README ChangeLog $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ $(srcdir)/config.in $(srcdir)/../mkinstalldirs \ $(top_srcdir)/po/Make-in arparse.h arparse.c arlex.c \ defparse.h defparse.c deflex.c nlmheader.h nlmheader.c \ - arparse.h arparse.c arlex.c rcparse.h rcparse.c \ - $(srcdir)/../ylwrap $(srcdir)/../ltmain.sh \ + arparse.h arparse.c arlex.c mcparse.h mcparse.c rcparse.h \ + rcparse.c $(srcdir)/../ylwrap $(srcdir)/../ltmain.sh \ $(srcdir)/../config.guess $(srcdir)/../config.sub subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -81,21 +81,22 @@ CONFIG_CLEAN_FILES = po/Makefile.in am__EXEEXT_1 = nlmconv$(EXEEXT) am__EXEEXT_2 = dlltool$(EXEEXT) am__EXEEXT_3 = windres$(EXEEXT) -am__EXEEXT_4 = dllwrap$(EXEEXT) -am__EXEEXT_5 = size$(EXEEXT) -am__EXEEXT_6 = objdump$(EXEEXT) -am__EXEEXT_7 = ar$(EXEEXT) -am__EXEEXT_8 = strings$(EXEEXT) -am__EXEEXT_9 = ranlib$(EXEEXT) -am__EXEEXT_10 = objcopy$(EXEEXT) -am__EXEEXT_11 = addr2line$(EXEEXT) -am__EXEEXT_12 = readelf$(EXEEXT) +am__EXEEXT_4 = windmc$(EXEEXT) +am__EXEEXT_5 = dllwrap$(EXEEXT) +am__EXEEXT_6 = size$(EXEEXT) +am__EXEEXT_7 = objdump$(EXEEXT) +am__EXEEXT_8 = ar$(EXEEXT) +am__EXEEXT_9 = strings$(EXEEXT) +am__EXEEXT_10 = ranlib$(EXEEXT) +am__EXEEXT_11 = objcopy$(EXEEXT) +am__EXEEXT_12 = addr2line$(EXEEXT) +am__EXEEXT_13 = readelf$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) -am__EXEEXT_13 = nm-new$(EXEEXT) -am__EXEEXT_14 = strip-new$(EXEEXT) -am__EXEEXT_15 = cxxfilt$(EXEEXT) -am__EXEEXT_16 = $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) +am__EXEEXT_14 = nm-new$(EXEEXT) +am__EXEEXT_15 = strip-new$(EXEEXT) +am__EXEEXT_16 = cxxfilt$(EXEEXT) +am__EXEEXT_17 = $(am__EXEEXT_14) $(am__EXEEXT_15) $(am__EXEEXT_16) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am__objects_1 = bucomm.$(OBJEXT) version.$(OBJEXT) filemode.$(OBJEXT) am_addr2line_OBJECTS = addr2line.$(OBJEXT) $(am__objects_1) @@ -162,6 +163,9 @@ strip_new_LDADD = $(LDADD) am_sysdump_OBJECTS = sysdump.$(OBJEXT) $(am__objects_1) sysdump_OBJECTS = $(am_sysdump_OBJECTS) sysdump_LDADD = $(LDADD) +am_windmc_OBJECTS = windmc.$(OBJEXT) mcparse.$(OBJEXT) mclex.$(OBJEXT) \ + winduni.$(OBJEXT) $(am__objects_1) +windmc_OBJECTS = $(am_windmc_OBJECTS) am_windres_OBJECTS = windres.$(OBJEXT) resrc.$(OBJEXT) \ rescoff.$(OBJEXT) resbin.$(OBJEXT) rcparse.$(OBJEXT) \ rclex.$(OBJEXT) winduni.$(OBJEXT) resres.$(OBJEXT) \ @@ -189,7 +193,8 @@ SOURCES = $(addr2line_SOURCES) $(ar_SOURCES) $(coffdump_SOURCES) \ $(nlmconv_SOURCES) $(nm_new_SOURCES) $(objcopy_SOURCES) \ $(objdump_SOURCES) $(ranlib_SOURCES) $(readelf_SOURCES) \ $(size_SOURCES) $(srconv_SOURCES) $(strings_SOURCES) \ - $(strip_new_SOURCES) $(sysdump_SOURCES) $(windres_SOURCES) + $(strip_new_SOURCES) $(sysdump_SOURCES) $(windmc_SOURCES) \ + $(windres_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ @@ -217,6 +222,7 @@ BUILD_INSTALL_MISC = @BUILD_INSTALL_MISC@ BUILD_MISC = @BUILD_MISC@ BUILD_NLMCONV = @BUILD_NLMCONV@ BUILD_SRCONV = @BUILD_SRCONV@ +BUILD_WINDMC = @BUILD_WINDMC@ BUILD_WINDRES = @BUILD_WINDRES@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ @@ -375,6 +381,7 @@ ADDR2LINE_PROG = addr2line NLMCONV_PROG = nlmconv DLLTOOL_PROG = dlltool WINDRES_PROG = windres +WINDMC_PROG = windmc DLLWRAP_PROG = dllwrap SRCONV_PROG = srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT) RENAMED_PROGS = $(NM_PROG) $(STRIP_PROG) $(DEMANGLER_PROG) @@ -395,9 +402,10 @@ INCLUDES = -D_GNU_SOURCE \ HFILES = \ arsup.h binemul.h bucomm.h budbg.h \ coffgrok.h debug.h dlltool.h nlmconv.h \ - windres.h winduni.h windint.h + windres.h winduni.h windint.h \ + windmc.h -GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h rcparse.h +GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h rcparse.h mcparse.h CFILES = \ addr2line.c ar.c arsup.c bin2c.c binemul.c bucomm.c \ coffdump.c coffgrok.c cxxfilt.c \ @@ -409,11 +417,12 @@ CFILES = \ rclex.c rdcoff.c rddbg.c readelf.c rename.c \ resbin.c rescoff.c resrc.c resres.c \ size.c srconv.c stabs.c strings.c sysdump.c version.c \ - windres.c winduni.c wrstabs.c + windres.c winduni.c wrstabs.c \ + windmc.c mclex.c GENERATED_CFILES = \ arparse.c arlex.c sysroff.c sysinfo.c syslex.c \ - defparse.c deflex.c nlmheader.c rcparse.c + defparse.c deflex.c nlmheader.c rcparse.c mcparse.c DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c @@ -460,6 +469,7 @@ sysdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) coffdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) dlltool_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) windres_DEPENDENCIES = $(LIBINTL_DEP) $(LIBICONV) $(LIBIBERTY) $(BFDLIB) +windmc_DEPENDENCIES = $(LIBINTL_DEP) $(LIBICONV) $(LIBIBERTY) $(BFDLIB) addr2line_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) readelf_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) dllwrap_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) @@ -493,10 +503,15 @@ windres_SOURCES = windres.c resrc.c rescoff.c resbin.c rcparse.y rclex.c \ winduni.c resres.c $(BULIBS) windres_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL) +windmc_SOURCES = windmc.c mcparse.y mclex.c \ + winduni.c $(BULIBS) + +windmc_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(LIBINTL) dllwrap_SOURCES = dllwrap.c version.c dllwrap_LDADD = $(LIBIBERTY) $(LIBINTL) EXTRA_DIST = arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \ - syslex.c deflex.c defparse.h defparse.c rcparse.h rcparse.c + syslex.c deflex.c defparse.h defparse.c rcparse.h rcparse.c \ + mcparse.h mcparse.c DISTCLEANFILES = sysroff.c sysroff.h site.exp site.bak @@ -516,15 +531,15 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ - echo ' cd $(srcdir) && $(AUTOMAKE) --cygnus '; \ - cd $(srcdir) && $(AUTOMAKE) --cygnus \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ + cd $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --cygnus Makefile + $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -648,6 +663,9 @@ strip-new$(EXEEXT): $(strip_new_OBJECTS) $(strip_new_DEPENDENCIES) sysdump$(EXEEXT): $(sysdump_OBJECTS) $(sysdump_DEPENDENCIES) @rm -f sysdump$(EXEEXT) $(LINK) $(sysdump_LDFLAGS) $(sysdump_OBJECTS) $(sysdump_LDADD) $(LIBS) +windmc$(EXEEXT): $(windmc_OBJECTS) $(windmc_DEPENDENCIES) + @rm -f windmc$(EXEEXT) + $(LINK) $(windmc_LDFLAGS) $(windmc_OBJECTS) $(windmc_LDADD) $(LIBS) windres$(EXEEXT): $(windres_OBJECTS) $(windres_DEPENDENCIES) @rm -f windres$(EXEEXT) $(LINK) $(windres_LDFLAGS) $(windres_OBJECTS) $(windres_LDADD) $(LIBS) @@ -879,6 +897,8 @@ maintainer-clean-generic: -rm -f deflex.c -rm -f defparse.c -rm -f defparse.h + -rm -f mcparse.c + -rm -f mcparse.h -rm -f nlmheader.c -rm -f nlmheader.h -rm -f rcparse.c @@ -1060,6 +1080,7 @@ arparse.h: arparse.c defparse.h: defparse.c nlmheader.h: nlmheader.c rcparse.h: rcparse.c +mcparse.h: mcparse.c sysinfo.h: sysinfo.c # Disable -Werror, if it has been enabled, since old versions of bison/ @@ -1078,8 +1099,12 @@ nlmheader.o: $(COMPILE) -c $< $(NO_WERROR) rcparse.o: $(COMPILE) -c $< $(NO_WERROR) +mcparse.o: + $(COMPILE) -c $< $(NO_WERROR) rclex.o: $(COMPILE) -c $< $(NO_WERROR) +mclex.o: + $(COMPILE) -c $< $(NO_WERROR) dlltool.o: $(COMPILE) -c $(DLLTOOL_DEFS) $(srcdir)/dlltool.c @@ -1365,6 +1390,11 @@ windres.o: windres.c sysdep.h $(INCDIR)/ansidecl.h \ $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \ $(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h $(INCDIR)/obstack.h \ bucomm.h windres.h winduni.h windint.h +windmc.o: windmc.c sysdep.h $(INCDIR)/ansidecl.h \ + ../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \ + $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \ + $(INCDIR)/ansidecl.h $(INCDIR)/safe-ctype.h $(INCDIR)/obstack.h \ + bucomm.h windmc.h winduni.h windint.h winduni.o: winduni.c sysdep.h $(INCDIR)/ansidecl.h \ ../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \ $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h winduni.h $(INCDIR)/safe-ctype.h @@ -1398,10 +1428,19 @@ rcparse.o: rcparse.c sysdep.h $(INCDIR)/ansidecl.h \ $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \ $(INCDIR)/ansidecl.h windres.h winduni.h windint.h \ $(INCDIR)/safe-ctype.h +mcparse.o: mcparse.c sysdep.h $(INCDIR)/ansidecl.h \ + ../bfd/bfdver.h config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h \ + $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h $(INCDIR)/libiberty.h \ + $(INCDIR)/ansidecl.h windmc.h winduni.h \ + $(INCDIR)/safe-ctype.h rclex.o: rclex.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \ config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \ $(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \ $(INCDIR)/safe-ctype.h windres.h winduni.h windint.h rcparse.h +mclex.o: mclex.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \ + config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/symcat.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/safe-ctype.h windmc.h winduni.h mcparse.h # IF YOU PUT ANYTHING HERE IT WILL GO AWAY # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/binutils/NEWS b/binutils/NEWS index 3eceac03a0..ad6058f75b 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -1,6 +1,14 @@ -*- text -*- -* Add codepage support to the windres tool. +* A new tool "windmc" has been added for some targets. This is a message + compiler which attempts to be compatible with the MS version. + +* Add codepage support to the windres tool. It now supports many new + resource types (e.g. MANIFEST, TOOLBAR, etc). The output generation + for binary files is done now via bfd itself. The endianess problems + for different hosts are solved. Dumps of .res files can now be + re-compiled by windres without lossing resources or compilation errors. + Some problems on dialog resource translations are corrected. * Add --extract-symbol command line option to objcopy, which will strip everything out of an ordinary object file or executable except diff --git a/binutils/configure b/binutils/configure index 288004f18d..a10a8adcc0 100755 --- a/binutils/configure +++ b/binutils/configure @@ -458,7 +458,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE LIBTOOL SED EGREP FGREP GREP LD DUMPBIN ac_ct_DUMPBIN NM LN_S AR ac_ct_AR RANLIB ac_ct_RANLIB lt_ECHO CPP WARN_CFLAGS NO_WERROR YACC LEX LEXLIB LEX_OUTPUT_ROOT USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT GENINSRC_NEVER_TRUE GENINSRC_NEVER_FALSE HDEFINES CC_FOR_BUILD EXEEXT_FOR_BUILD DEMANGLER_NAME ALLOCA LIBICONV LTLIBICONV NLMCONV_DEFS BUILD_NLMCONV BUILD_SRCONV BUILD_DLLTOOL DLLTOOL_DEFS BUILD_WINDRES BUILD_DLLWRAP BUILD_MISC BUILD_INSTALL_MISC OBJDUMP_DEFS EMULATION EMULATION_VECTOR datarootdir docdir htmldir LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE LIBTOOL SED EGREP FGREP GREP LD DUMPBIN ac_ct_DUMPBIN NM LN_S AR ac_ct_AR RANLIB ac_ct_RANLIB lt_ECHO CPP WARN_CFLAGS NO_WERROR YACC LEX LEXLIB LEX_OUTPUT_ROOT USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT GENINSRC_NEVER_TRUE GENINSRC_NEVER_FALSE HDEFINES CC_FOR_BUILD EXEEXT_FOR_BUILD DEMANGLER_NAME ALLOCA LIBICONV LTLIBICONV NLMCONV_DEFS BUILD_NLMCONV BUILD_SRCONV BUILD_DLLTOOL DLLTOOL_DEFS BUILD_WINDRES BUILD_WINDMC BUILD_DLLWRAP BUILD_MISC BUILD_INSTALL_MISC OBJDUMP_DEFS EMULATION EMULATION_VECTOR datarootdir docdir htmldir LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -14417,6 +14417,7 @@ BUILD_DLLTOOL= DLLTOOL_DEFS= DLLTOOL_DEFAULT= BUILD_WINDRES= +BUILD_WINDMC= BUILD_DLLWRAP= BUILD_MISC= BUILD_INSTALL_MISC= @@ -14460,6 +14461,7 @@ do fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM_EPOC -DDLLTOOL_ARM" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; arm-wince-pe* | arm-*-wince) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -14468,6 +14470,7 @@ do fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM_WINCE -DDLLTOOL_ARM" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; arm-*-pe*) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -14476,6 +14479,7 @@ do fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; thumb-*-pe*) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -14484,6 +14488,7 @@ do fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; x86_64-*-mingw*) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -14492,6 +14497,7 @@ do fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MX86_64" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)' ;; i[3-7]86-*-pe* | i[3-7]86-*-cygwin* | i[3-7]86-*-mingw32** | i[3-7]86-*-netbsdpe*) @@ -14501,6 +14507,7 @@ do fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)' ;; i[3-7]86-*-interix) @@ -14522,6 +14529,7 @@ do fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_PPC" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; powerpc*-*-linux* | powerpc*-*-elf*) BUILD_INSTALL_MISC="${BUILD_INSTALL_MISC} embedspu" @@ -14533,6 +14541,7 @@ do fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_SH" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; spu-*-*) BUILD_MISC="${BUILD_MISC} "'bin2c$(EXEEXT_FOR_BUILD)' @@ -14544,6 +14553,7 @@ do fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MIPS" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; mcore-*-pe) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -14552,6 +14562,7 @@ do fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MCORE" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; mcore-*-elf) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -14573,6 +14584,11 @@ if test "${with_windres+set}" = set; then BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' fi +if test "${with_windmc+set}" = set; then + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' +fi + + @@ -15637,6 +15653,7 @@ s,@BUILD_SRCONV@,$BUILD_SRCONV,;t t s,@BUILD_DLLTOOL@,$BUILD_DLLTOOL,;t t s,@DLLTOOL_DEFS@,$DLLTOOL_DEFS,;t t s,@BUILD_WINDRES@,$BUILD_WINDRES,;t t +s,@BUILD_WINDMC@,$BUILD_WINDMC,;t t s,@BUILD_DLLWRAP@,$BUILD_DLLWRAP,;t t s,@BUILD_MISC@,$BUILD_MISC,;t t s,@BUILD_INSTALL_MISC@,$BUILD_INSTALL_MISC,;t t diff --git a/binutils/configure.in b/binutils/configure.in index fe1bb9fe83..19aaabc867 100644 --- a/binutils/configure.in +++ b/binutils/configure.in @@ -211,6 +211,7 @@ BUILD_DLLTOOL= DLLTOOL_DEFS= DLLTOOL_DEFAULT= BUILD_WINDRES= +BUILD_WINDMC= BUILD_DLLWRAP= BUILD_MISC= BUILD_INSTALL_MISC= @@ -256,6 +257,7 @@ changequote([,])dnl fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM_EPOC -DDLLTOOL_ARM" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; arm-wince-pe* | arm-*-wince) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -264,6 +266,7 @@ changequote([,])dnl fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM_WINCE -DDLLTOOL_ARM" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; arm-*-pe*) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -272,6 +275,7 @@ changequote([,])dnl fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; thumb-*-pe*) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -280,6 +284,7 @@ changequote([,])dnl fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; x86_64-*-mingw*) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -288,6 +293,7 @@ changequote([,])dnl fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MX86_64" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)' ;; changequote(,)dnl @@ -299,6 +305,7 @@ changequote([,])dnl fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)' ;; changequote(,)dnl @@ -324,6 +331,7 @@ changequote([,])dnl fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_PPC" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; powerpc*-*-linux* | powerpc*-*-elf*) BUILD_INSTALL_MISC="${BUILD_INSTALL_MISC} embedspu" @@ -335,6 +343,7 @@ changequote([,])dnl fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_SH" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; spu-*-*) BUILD_MISC="${BUILD_MISC} "'bin2c$(EXEEXT_FOR_BUILD)' @@ -346,6 +355,7 @@ changequote([,])dnl fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MIPS" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; mcore-*-pe) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -354,6 +364,7 @@ changequote([,])dnl fi DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MCORE" BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' ;; mcore-*-elf) BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' @@ -375,12 +386,17 @@ if test "${with_windres+set}" = set; then BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' fi +if test "${with_windmc+set}" = set; then + BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)' +fi + AC_SUBST(NLMCONV_DEFS) AC_SUBST(BUILD_NLMCONV) AC_SUBST(BUILD_SRCONV) AC_SUBST(BUILD_DLLTOOL) AC_SUBST(DLLTOOL_DEFS) AC_SUBST(BUILD_WINDRES) +AC_SUBST(BUILD_WINDMC) AC_SUBST(BUILD_DLLWRAP) AC_SUBST(BUILD_MISC) AC_SUBST(BUILD_INSTALL_MISC) diff --git a/binutils/doc/Makefile.am b/binutils/doc/Makefile.am index 5d8520cf52..ceeda41b00 100644 --- a/binutils/doc/Makefile.am +++ b/binutils/doc/Makefile.am @@ -28,6 +28,7 @@ man_MANS = \ strings.1 \ strip.1 \ windres.1 \ + windmc.1 \ $(DEMANGLER_NAME).1 info_TEXINFOS = binutils.texi @@ -130,6 +131,13 @@ windres.1: $(binutils_TEXI) $(binutils_TEXINFOS) mv -f $@.T$$$$ $@) || (rm -f $@.T$$$$ && exit 1) rm -f windres.pod +windmc.1: $(binutils_TEXI) $(binutils_TEXINFOS) + touch $@ + -$(TEXI2POD) $(MANCONF) -Dwindmc < $(binutils_TEXI) > windmc.pod + -($(POD2MAN) windmc.pod | sed -e '/^.if n .na/d' > $@.T$$$$ && \ + mv -f $@.T$$$$ $@) || (rm -f $@.T$$$$ && exit 1) + rm -f windmc.pod + cxxfilt.man: $(binutils_TEXI) $(binutils_TEXINFOS) touch $@ -$(TEXI2POD) $(MANCONF) -Dcxxfilt < $(binutils_TEXI) > $(DEMANGLER_NAME).pod diff --git a/binutils/doc/Makefile.in b/binutils/doc/Makefile.in index 12928a138f..2455745999 100644 --- a/binutils/doc/Makefile.in +++ b/binutils/doc/Makefile.in @@ -93,6 +93,7 @@ BUILD_INSTALL_MISC = @BUILD_INSTALL_MISC@ BUILD_MISC = @BUILD_MISC@ BUILD_NLMCONV = @BUILD_NLMCONV@ BUILD_SRCONV = @BUILD_SRCONV@ +BUILD_WINDMC = @BUILD_WINDMC@ BUILD_WINDRES = @BUILD_WINDRES@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ @@ -249,6 +250,7 @@ man_MANS = \ strings.1 \ strip.1 \ windres.1 \ + windmc.1 \ $(DEMANGLER_NAME).1 info_TEXINFOS = binutils.texi @@ -280,9 +282,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --cygnus doc/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --cygnus doc/Makefile + $(AUTOMAKE) --foreign doc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -679,6 +681,13 @@ windres.1: $(binutils_TEXI) $(binutils_TEXINFOS) mv -f $@.T$$$$ $@) || (rm -f $@.T$$$$ && exit 1) rm -f windres.pod +windmc.1: $(binutils_TEXI) $(binutils_TEXINFOS) + touch $@ + -$(TEXI2POD) $(MANCONF) -Dwindmc < $(binutils_TEXI) > windmc.pod + -($(POD2MAN) windmc.pod | sed -e '/^.if n .na/d' > $@.T$$$$ && \ + mv -f $@.T$$$$ $@) || (rm -f $@.T$$$$ && exit 1) + rm -f windmc.pod + cxxfilt.man: $(binutils_TEXI) $(binutils_TEXINFOS) touch $@ -$(TEXI2POD) $(MANCONF) -Dcxxfilt < $(binutils_TEXI) > $(DEMANGLER_NAME).pod diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 9591fe9e9c..da49e1f521 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -25,6 +25,7 @@ START-INFO-DIR-ENTRY * addr2line: (binutils)addr2line. Convert addresses to file and line * nlmconv: (binutils)nlmconv. Converts object code into an NLM * windres: (binutils)windres. Manipulate Windows resources +* windmc: (binutils)windmc. Generator for Windows message resources * dlltool: (binutils)dlltool. Create files needed to build and use DLLs END-INFO-DIR-ENTRY @end format @@ -145,6 +146,9 @@ Convert object code into a Netware Loadable Module @item windres Manipulate Windows resources +@item windmc +Genertor for Windows message resources + @item dlltool Create the files needed to build and use Dynamic Link Libraries @end table @@ -169,6 +173,7 @@ section entitled "GNU Free Documentation License". * addr2line:: Convert addresses to file and line * nlmconv:: Converts object code into an NLM * windres:: Manipulate Windows resources +* windmc:: Generator for Windows message resources * dlltool:: Create files needed to build and use DLLs * Common Options:: Command-line options for all utilities * Selecting The Target System:: How these utilities determine the target. @@ -2869,6 +2874,168 @@ the Info entries for @file{binutils}. @c man end @end ignore +@node windmc +@chapter windmc + +@command{windmc} may be used to generator Windows message resources. + +@quotation +@emph{Warning:} @command{windmc} is not always built as part of the binary +utilities, since it is only useful for Windows targets. +@end quotation + +@c man title windmc generates Windows message resources. + +@smallexample +@c man begin SYNOPSIS windres +windmc [options] input-file +@c man end +@end smallexample + +@c man begin DESCRIPTION windmc + +@command{windmc} reads message definitions from an input file (.mc) and +translate them into a set of output files. The output files may be of +four kinds: + +@table @code +@item h +A C header file containing the message definitions. + +@item rc +A resource file compilable by the @command{windres} tool. + +@item bin +One or more binary files containing the resource data for a specific +message language. + +@item dbg +A C include file that maps message id's to their symbolic name. +@end table + +The exact description of these different formats is available in +documentation from Microsoft. + +When @command{windmc} converts from the @code{mc} format to the @code{bin} +format, @code{rc}, @code{h}, and optional @code{dbg} it is acting like the +Windows Message Compiler. + +@c man end + +@c man begin OPTIONS windmc + +@table @env +@item -a +@itemx --ascii_in +Specifies that the input file specified is ANSI. This is the default +behaviour. + +@item -A +@itemx --ascii_out +Specifies that messages in the output @code{bin} files should be in ANSI +format. + +@item -b +@itemx --binprefix +Specifies that @code{bin} filenames should have to be prefixed by the +basename of the source file. + +@item -c +@itemx --customflag +Sets the customer bit in all message id's. + +@item -C @var{codepage} +@itemx --codepage_in @var{codepage} +Sets the default codepage to be used to convert input file to UTF16. The +default is ocdepage 1252. + +@item -d +@itemx --decimal_values +Outputs the constants in the header file in decimal. Default is using +hexadecimal output. + +@item -e @var{ext} +@itemx --extension @var{ext} +The extension for the header file. The default is .h extension. + +@item -F @var{target} +@itemx --target @var{target} +Specify the BFD format to use for a bin file as output. This +is a BFD target name; you can use the @option{--help} option to see a list +of supported targets. Normally @command{windmc} will use the default +format, which is the first one listed by the @option{--help} option. +@ifclear man +@ref{Target Selection}. +@end ifclear + +@item -h @var{path} +@itemx --headerdir @var{path} +The target directory of the generated header file. The default is the +current directory. + +@item -H +@itemx --help +Displays a list of command line options and then exits. + +@item -m @var{characters} +@itemx --maxlength @var{characters} +Instructs @command{windmc} to generate a warning if the length +of any message exceeds the number specified. + +@item -n +@itemx --nullterminate +Terminate message text in @code{bin} files by zero. By default they are +terminated by CR/LF. + +@item -o +@itemx --hresult_use +Not yet implemented. Instructs @code{windmc} to generate an OLE2 header +file, using HRESULT definitions. Status codes are used if the flag is not +specified. + +@item -O @var{codepage} +@itemx --codepage_out @var{codepage} +Sets the default codepage to be used to output text files. The default +is ocdepage 1252. + +@item -r @var{path} +@itemx --rcdir @var{path} +The target directory for the generated @code{rc} script and the generated +@code{bin} files that the resource compiler script includes. The default +is the current directory. + +@item -u +@itemx --unicode_in +Specifies that the input file is UTF16. + +@item -U +@itemx --unicode_out +Specifies that messages in the output @code{bin} file should be in UTF16 +format. This is the default behaviour. + +@item -v +@item --verbose +Enable verbose mode. This tells you what the preprocessor is if you +didn't specify one. + +@item -V +@item --version +Prints the version number for @command{windres}. + +@item -x @var{path} +@itemx --xdgb @var{path} +The path of the @code{dbg} C include file that maps message id's to the +symbolic name. No such file is generated without specifying the switch. +@end table + +@c man end + +@ignore +@c man begin SEEALSO windmc +the Info entries for @file{binutils}. +@c man end +@end ignore + @node windres @chapter windres diff --git a/binutils/mclex.c b/binutils/mclex.c new file mode 100644 index 0000000000..f6cedd9efd --- /dev/null +++ b/binutils/mclex.c @@ -0,0 +1,441 @@ +/* mclex.c -- lexer for Windows mc files parser. + Copyright 2007 + Free Software Foundation, Inc. + + Written by Kai Tietz, Onevision. + + This file is part of GNU Binutils. + + 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 + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* This is a lexer used by the Windows rc file parser. + It basically just recognized a bunch of keywords. */ + +#include "sysdep.h" +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "safe-ctype.h" +#include "windmc.h" +#include "mcparse.h" + +#include + +/* Exported globals. */ +bfd_boolean mclex_want_nl = FALSE; +bfd_boolean mclex_want_line = FALSE; +bfd_boolean mclex_want_filename = FALSE; + +/* Local globals. */ +static unichar *input_stream = NULL; +static unichar *input_stream_pos = NULL; +static int input_line = 1; +static const char *input_filename = NULL; + +void +mc_set_content (const unichar *src) +{ + if (!src) + return; + input_stream = input_stream_pos = unichar_dup (src); +} + +void +mc_set_inputfile (const char *name) +{ + if (! name || *name == 0) + input_filename = "-"; + else + { + const char *s1 = strrchr (name, '/'); + const char *s2 = strrchr (name, '\\'); + + if (! s1) + s1 = s2; + if (s1 && s2 && s1 < s2) + s1 = s2; + if (! s1) + s1 = name; + else + s1++; + s1 = xstrdup (s1); + input_filename = s1; + } +} + +static void +show_msg (const char *kind, const char *msg, va_list argp) +{ + fprintf (stderr, "In %s at line %d: %s: ", input_filename, input_line, kind); + vfprintf (stderr, msg, argp); + fprintf (stderr, ".\n"); +} + +void +mc_warn (const char *s, ...) +{ + va_list argp; + va_start (argp, s); + show_msg ("warning", s, argp); + va_end (argp); +} + +void +mc_fatal (const char *s, ...) +{ + va_list argp; + va_start (argp, s); + show_msg ("fatal", s, argp); + va_end (argp); + xexit (1); +} + + +int +yyerror (const char *s, ...) +{ + va_list argp; + va_start (argp, s); + show_msg ("parser", s, argp); + va_end (argp); + return 1; +} + +static unichar * +get_diff (unichar *end, unichar *start) +{ + unichar *ret; + unichar save = *end; + + *end = 0; + ret = unichar_dup (start); + *end = save; + return ret; +} + +static rc_uint_type +parse_digit (unichar ch) +{ + rc_uint_type base = 10, v = 0, c; + + if (ch == '0') + { + base = 8; + switch (input_stream_pos[0]) + { + case 'x': case 'X': base = 16; input_stream_pos++; break; + case 'o': case 'O': base = 8; input_stream_pos++; break; + case 'b': case 'B': base = 2; input_stream_pos++; break; + } + } + else + v = (rc_uint_type) (ch - '0'); + + while ((ch = input_stream_pos[0]) != 0) + { + if (ch >= 'A' && ch <= 'F') + c = (rc_uint_type) (ch - 'A') + 10; + else if (ch >= 'a' && ch <= 'f') + c = (rc_uint_type) (ch - 'a') + 10; + else if (ch >= '0' && ch <= '9') + c = (rc_uint_type) (ch - '0'); + else + break; + v *= base; + v += c; + ++input_stream_pos; + } + if (input_stream_pos[0] == 'U' || input_stream_pos[0] == 'u') + input_stream_pos++; + if (input_stream_pos[0] == 'L' || input_stream_pos[0] == 'l') + input_stream_pos++; + if (input_stream_pos[0] == 'L' || input_stream_pos[0] == 'l') + input_stream_pos++; + return v; +} + +static mc_keyword *keyword_top = NULL; + +const mc_keyword * +enum_facility (int e) +{ + mc_keyword *h = keyword_top; + + while (h != NULL) + { + while (h && strcmp (h->group_name, "facility") != 0) + h = h->next; + if (e == 0) + return h; + --e; + if (h) + h = h->next; + } + return h; +} + +const mc_keyword * +enum_severity (int e) +{ + mc_keyword *h = keyword_top; + + while (h != NULL) + { + while (h && strcmp (h->group_name, "severity") != 0) + h = h->next; + if (e == 0) + return h; + --e; + if (h) + h = h->next; + } + return h; +} + +static void +mc_add_keyword_ascii (const char *sz, int rid, const char *grp, rc_uint_type nv, const char *sv) +{ + unichar *usz, *usv = NULL; + rc_uint_type usz_len; + + unicode_from_codepage (&usz_len, &usz, sz, CP_ACP); + if (sv) + unicode_from_codepage (&usz_len, &usv, sv, CP_ACP); + mc_add_keyword (usz, rid, grp, nv, usv); +} + +void +mc_add_keyword (unichar *usz, int rid, const char *grp, rc_uint_type nv, unichar *sv) +{ + mc_keyword *p, *c, *n; + size_t len = unichar_len (usz); + + c = keyword_top; + p = NULL; + while (c != NULL) + { + if (c->len > len) + break; + if (c->len == len) + { + int e = memcmp (usz, c->usz, len * sizeof (unichar)); + + if (e < 0) + break; + if (! e) + { + if (! strcmp (grp, "keyword") || strcmp (c->group_name, grp) != 0) + fatal (_("Duplicate symbol entered into keyword list.")); + c->rid = rid; + c->nval = nv; + c->sval = (!sv ? NULL : unichar_dup (sv)); + if (! strcmp (grp, "language")) + { + const wind_language_t *lag = wind_find_language_by_id ((unsigned) nv); + + if (lag == NULL) + fatal ("Language ident 0x%lx is not resolvable.\n", (long) nv); + memcpy (&c->lang_info, lag, sizeof (*lag)); + } + return; + } + } + c = (p = c)->next; + } + n = xmalloc (sizeof (mc_keyword)); + n->next = c; + n->len = len; + n->group_name = grp; + n->usz = usz; + n->rid = rid; + n->nval = nv; + n->sval = (!sv ? NULL : unichar_dup (sv)); + if (! strcmp (grp, "language")) + { + const wind_language_t *lag = wind_find_language_by_id ((unsigned) nv); + if (lag == NULL) + fatal ("Language ident 0x%lx is not resolvable.\n", (long) nv); + memcpy (&n->lang_info, lag, sizeof (*lag)); + } + if (! p) + keyword_top = n; + else + p->next = n; +} + +static int +mc_token (const unichar *t, size_t len) +{ + static int was_init = 0; + mc_keyword *k; + + if (! was_init) + { + was_init = 1; + mc_add_keyword_ascii ("OutputBase", MCOUTPUTBASE, "keyword", 0, NULL); + mc_add_keyword_ascii ("MessageIdTypedef", MCMESSAGEIDTYPEDEF, "keyword", 0, NULL); + mc_add_keyword_ascii ("SeverityNames", MCSEVERITYNAMES, "keyword", 0, NULL); + mc_add_keyword_ascii ("FacilityNames", MCFACILITYNAMES, "keyword", 0, NULL); + mc_add_keyword_ascii ("LanguageNames", MCLANGUAGENAMES, "keyword", 0, NULL); + mc_add_keyword_ascii ("MessageId", MCMESSAGEID, "keyword", 0, NULL); + mc_add_keyword_ascii ("Severity", MCSEVERITY, "keyword", 0, NULL); + mc_add_keyword_ascii ("Facility", MCFACILITY, "keyword", 0, NULL); + mc_add_keyword_ascii ("SymbolicName", MCSYMBOLICNAME, "keyword", 0, NULL); + mc_add_keyword_ascii ("Language", MCLANGUAGE, "keyword", 0, NULL); + mc_add_keyword_ascii ("Success", MCTOKEN, "severity", 0, NULL); + mc_add_keyword_ascii ("Informational", MCTOKEN, "severity", 1, NULL); + mc_add_keyword_ascii ("Warning", MCTOKEN, "severity", 2, NULL); + mc_add_keyword_ascii ("Error", MCTOKEN, "severity", 3, NULL); + mc_add_keyword_ascii ("System", MCTOKEN, "facility", 0xff, NULL); + mc_add_keyword_ascii ("Application", MCTOKEN, "facility", 0xfff, NULL); + mc_add_keyword_ascii ("English", MCTOKEN, "language", 0x409, "MSG00001"); + } + k = keyword_top; + if (!len || !t || *t == 0) + return -1; + while (k != NULL) + { + if (k->len > len) + break; + if (k->len == len) + { + if (! memcmp (k->usz, t, len * sizeof (unichar))) + { + if (k->rid == MCTOKEN) + yylval.tok = k; + return k->rid; + } + } + k = k->next; + } + return -1; +} + +int +yylex (void) +{ + unichar *start_token; + unichar ch; + + if (! input_stream_pos) + { + fatal ("Input stream not setuped.\n"); + return -1; + } + if (mclex_want_line) + { + start_token = input_stream_pos; + if (input_stream_pos[0] == '.' + && (input_stream_pos[1] == '\n' + || (input_stream_pos[1] == '\r' && input_stream_pos[2] == '\n'))) + { + mclex_want_line = FALSE; + while (input_stream_pos[0] != 0 && input_stream_pos[0] != '\n') + ++input_stream_pos; + if (input_stream_pos[0] == '\n') + ++input_stream_pos; + return MCENDLINE; + } + while (input_stream_pos[0] != 0 && input_stream_pos[0] != '\n') + ++input_stream_pos; + if (input_stream_pos[0] == '\n') + ++input_stream_pos; + yylval.ustr = get_diff (input_stream_pos, start_token); + return MCLINE; + } + while ((ch = input_stream_pos[0]) <= 0x20) + { + if (ch == 0) + return -1; + ++input_stream_pos; + if (ch == '\n') + input_line += 1; + if (mclex_want_nl && ch == '\n') + { + mclex_want_nl = FALSE; + return NL; + } + } + start_token = input_stream_pos; + ++input_stream_pos; + if (mclex_want_filename) + { + mclex_want_filename = FALSE; + if (ch == '"') + { + start_token++; + while ((ch = input_stream_pos[0]) != 0) + { + if (ch == '"') + break; + ++input_stream_pos; + } + yylval.ustr = get_diff (input_stream_pos, start_token); + if (ch == '"') + ++input_stream_pos; + } + else + { + while ((ch = input_stream_pos[0]) != 0) + { + if (ch <= 0x20 || ch == ')') + break; + ++input_stream_pos; + } + yylval.ustr = get_diff (input_stream_pos, start_token); + } + return MCFILENAME; + } + switch (ch) + { + case ';': + ++start_token; + while (input_stream_pos[0] != '\n' && input_stream_pos[0] != 0) + ++input_stream_pos; + if (input_stream_pos[0] == '\n') + input_stream_pos++; + yylval.ustr = get_diff (input_stream_pos, start_token); + return MCCOMMENT; + case '=': + return '='; + case '(': + return '('; + case ')': + return ')'; + case '+': + return '+'; + case ':': + return ':'; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + yylval.ival = parse_digit (ch); + return MCNUMBER; + default: + if (ch >= 0x40) + { + int ret; + while (input_stream_pos[0] >= 0x40 || (input_stream_pos[0] >= '0' && input_stream_pos[0] <= '9')) + ++input_stream_pos; + ret = mc_token (start_token, (size_t) (input_stream_pos - start_token)); + if (ret != -1) + return ret; + yylval.ustr = get_diff (input_stream_pos, start_token); + return MCIDENT; + } + yyerror ("illegal character 0x%x.", ch); + } + return -1; +} diff --git a/binutils/mcparse.y b/binutils/mcparse.y new file mode 100644 index 0000000000..9aaba9b8d4 --- /dev/null +++ b/binutils/mcparse.y @@ -0,0 +1,356 @@ +%{ /* mcparse.y -- parser for Windows mc files + Copyright 2007 + Free Software Foundation, Inc. + + Parser for Windows mc files + Written by Kai Tietz, Onevision. + + This file is part of GNU Binutils. + + 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 + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* This is a parser for Windows rc files. It is based on the parser + by Gunther Ebert . */ + +#include "sysdep.h" +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "windmc.h" +#include "safe-ctype.h" + +static rc_uint_type mc_last_id = 0; +static rc_uint_type mc_sefa_val = 0; +static unichar *mc_last_symbol = NULL; +static const mc_keyword *mc_cur_severity = NULL; +static const mc_keyword *mc_cur_facility = NULL; +static mc_node *cur_node = NULL; + +%} + +%union +{ + rc_uint_type ival; + unichar *ustr; + const mc_keyword *tok; + mc_node *nod; +}; + +%start input + +%token NL +%token MCIDENT MCFILENAME MCLINE MCCOMMENT +%token MCTOKEN +%token MCENDLINE +%token MCLANGUAGENAMES MCFACILITYNAMES MCSEVERITYNAMES MCOUTPUTBASE MCMESSAGEIDTYPEDEF +%token MCLANGUAGE MCMESSAGEID MCSEVERITY MCFACILITY MCSYMBOLICNAME +%token MCNUMBER + +%type id vid sefasy_def +%type alias_name token lines comments +%type lang + +%% +input: entities + ; + +entities: + /* empty */ + | entities entity + ; +entity: global_section + | message + | comments + { + cur_node = mc_add_node (); + cur_node->user_text = $1; + } + | error { mc_fatal ("syntax error"); } +; + +global_section: + MCSEVERITYNAMES '=' '(' severitymaps ')' + | MCSEVERITYNAMES '=' '(' severitymaps error { mc_fatal ("missing ')' in SeverityNames"); } + | MCSEVERITYNAMES '=' error { mc_fatal ("missing '(' in SeverityNames"); } + | MCSEVERITYNAMES error { mc_fatal ("missing '=' for SeverityNames"); } + | MCLANGUAGENAMES '=' '(' langmaps ')' + | MCLANGUAGENAMES '=' '(' langmaps error { mc_fatal ("missing ')' in LanguageNames"); } + | MCLANGUAGENAMES '=' error { mc_fatal ("missing '(' in LanguageNames"); } + | MCLANGUAGENAMES error { mc_fatal ("missing '=' for LanguageNames"); } + | MCFACILITYNAMES '=' '(' facilitymaps ')' + | MCFACILITYNAMES '=' '(' facilitymaps error { mc_fatal ("missing ')' in FacilityNames"); } + | MCFACILITYNAMES '=' error { mc_fatal ("missing '(' in FacilityNames"); } + | MCFACILITYNAMES error { mc_fatal ("missing '=' for FacilityNames"); } + | MCOUTPUTBASE '=' MCNUMBER + { + if ($3 != 10 && $3 != 16) + mc_fatal ("OutputBase allows 10 or 16 as value"); + mcset_out_values_are_decimal = ($3 == 10 ? 1 : 0); + } + | MCMESSAGEIDTYPEDEF '=' MCIDENT + { + mcset_msg_id_typedef = $3; + } + | MCMESSAGEIDTYPEDEF '=' error + { + mc_fatal ("MessageIdTypedef expects an identifier"); + } + | MCMESSAGEIDTYPEDEF error + { + mc_fatal ("missing '=' for MessageIdTypedef"); + } +; + +severitymaps: + severitymap + | severitymaps severitymap + | error { mc_fatal ("severity ident missing"); } +; + +severitymap: + token '=' MCNUMBER alias_name + { + mc_add_keyword ($1, MCTOKEN, "severity", $3, $4); + } + | token '=' error { mc_fatal ("severity number missing"); } + | token error { mc_fatal ("severity missing '='"); } +; + +facilitymaps: + facilitymap + | facilitymaps facilitymap + | error { mc_fatal ("missing ident in FacilityNames"); } +; + +facilitymap: + token '=' MCNUMBER alias_name + { + mc_add_keyword ($1, MCTOKEN, "facility", $3, $4); + } + | token '=' error { mc_fatal ("facility number missing"); } + | token error { mc_fatal ("facility missing '='"); } +; + +langmaps: + langmap + | langmaps langmap + | error { mc_fatal ("missing ident in LanguageNames"); } +; + +langmap: + token '=' MCNUMBER lex_want_filename ':' MCFILENAME + { + mc_add_keyword ($1, MCTOKEN, "language", $3, $6); + } + | token '=' MCNUMBER lex_want_filename ':' error { mc_fatal ("missing filename in LanguageNames"); } + | token '=' MCNUMBER error { mc_fatal ("missing ':' in LanguageNames"); } + | token '=' error { mc_fatal ("missing language code in LanguageNames"); } + | token error { mc_fatal ("missing '=' for LanguageNames"); } +; + +alias_name: + /* empty */ + { + $$ = NULL; + } + | ':' MCIDENT + { + $$ = $2; + } + | ':' error { mc_fatal ("illegal token in identifier"); $$ = NULL; } +; + +message: + id sefasy_def + { + cur_node = mc_add_node (); + cur_node->symbol = mc_last_symbol; + cur_node->facility = mc_cur_facility; + cur_node->severity = mc_cur_severity; + cur_node->id = ($1 & 0xffffUL); + cur_node->vid = ($1 & 0xffffUL) | mc_sefa_val; + mc_last_id = $1; + } + lang_entities +; + +id: MCMESSAGEID '=' vid { $$ = $3; } + | MCMESSAGEID '=' error { mc_fatal ("missing number in MessageId"); $$ = 0; } + | MCMESSAGEID error { mc_fatal ("missing '=' for MessageId"); $$ = 0; } +; + +vid: /* empty */ + { + $$ = ++mc_last_id; + } + | MCNUMBER + { + $$ = $1; + } + | '+' MCNUMBER + { + $$ = mc_last_id + $2; + } + | '+' error { mc_fatal ("missing number after MessageId '+'"); } +; + +sefasy_def: + /* empty */ + { + $$ = 0; + mc_sefa_val = (mcset_custom_bit ? 1 : 0) << 29; + mc_last_symbol = NULL; + mc_cur_severity = NULL; + mc_cur_facility = NULL; + } + | sefasy_def severity + { + if ($1 & 1) + mc_warn (_("duplicate definition of Severity")); + $$ = $1 | 1; + } + | sefasy_def facility + { + if ($1 & 2) + mc_warn (_("duplicate definition of Facility")); + $$ = $1 | 2; + } + | sefasy_def symbol + { + if ($1 & 4) + mc_warn (_("duplicate definition of SymbolicName")); + $$ = $1 | 4; + } +; + +severity: MCSEVERITY '=' MCTOKEN + { + mc_sefa_val &= ~ (0x3UL << 30); + mc_sefa_val |= (($3->nval & 0x3UL) << 30); + mc_cur_severity = $3; + } +; + +facility: MCFACILITY '=' MCTOKEN + { + mc_sefa_val &= ~ (0xfffUL << 16); + mc_sefa_val |= (($3->nval & 0xfffUL) << 16); + mc_cur_facility = $3; + } +; + +symbol: MCSYMBOLICNAME '=' MCIDENT + { + mc_last_symbol = $3; + } +; + +lang_entities: + lang_entity + | lang_entities lang_entity +; + +lang_entity: + lang lex_want_line lines MCENDLINE + { + mc_node_lang *h; + h = mc_add_node_lang (cur_node, $1, cur_node->vid); + h->message = $3; + if (mcset_max_message_length != 0 && unichar_len (h->message) > mcset_max_message_length) + mc_warn ("message length to long"); + } +; + +lines: MCLINE + { + $$ = $1; + } + | lines MCLINE + { + unichar *h; + rc_uint_type l1,l2; + l1 = unichar_len ($1); + l2 = unichar_len ($2); + h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar)); + if (l1) memcpy (h, $1, l1 * sizeof (unichar)); + if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar)); + h[l1 + l2] = 0; + $$ = h; + } + | error { mc_fatal ("missing end of message text"); $$ = NULL; } + | lines error { mc_fatal ("missing end of message text"); $$ = $1; } +; + +comments: MCCOMMENT { $$ = $1; } + | comments MCCOMMENT + { + unichar *h; + rc_uint_type l1,l2; + l1 = unichar_len ($1); + l2 = unichar_len ($2); + h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar)); + if (l1) memcpy (h, $1, l1 * sizeof (unichar)); + if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar)); + h[l1 + l2] = 0; + $$ = h; + } +; + +lang: MCLANGUAGE lex_want_nl '=' MCTOKEN NL + { + $$ = $4; + } + | MCLANGUAGE lex_want_nl '=' MCIDENT NL + { + $$ = NULL; + mc_fatal (_("undeclared language identifier")); + } + | MCLANGUAGE lex_want_nl '=' token error + { + $$ = NULL; + mc_fatal ("missing newline after Language"); + } + | MCLANGUAGE lex_want_nl '=' error + { + $$ = NULL; + mc_fatal ("missing ident for Language"); + } + | MCLANGUAGE error + { + $$ = NULL; + mc_fatal ("missing '=' for Language"); + } +; + +token: MCIDENT { $$ = $1; } + | MCTOKEN { $$ = $1->usz; } +; + +lex_want_nl: + /* Empty */ { mclex_want_nl = 1; } +; + +lex_want_line: + /* Empty */ { mclex_want_line = 1; } +; + +lex_want_filename: + /* Empty */ { mclex_want_filename = 1; } +; + +%% + +/* Something else. */ diff --git a/binutils/windmc.c b/binutils/windmc.c new file mode 100644 index 0000000000..5465b351cd --- /dev/null +++ b/binutils/windmc.c @@ -0,0 +1,1197 @@ +/* windmc.c -- a program to compile Windows message files. + Copyright 2007 + Free Software Foundation, Inc. + Written by Kai Tietz, Onevision. + + This file is part of GNU Binutils. + + 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 + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* This program can read and comile Windows message format. + + It is based on information taken from the following sources: + + * Microsoft documentation. + + * The wmc program, written by Bertho A. Stultiens (BS). */ + +#include "sysdep.h" +#include +#include +#include "bfd.h" +#include "getopt.h" +#include "bucomm.h" +#include "libiberty.h" +#include "safe-ctype.h" +#include "obstack.h" + +#include "windmc.h" +#include "windint.h" + +/* Defines a message compiler element item with length and offset + information. */ +typedef struct mc_msg_item +{ + rc_uint_type res_len; + rc_uint_type res_off; + struct bin_messagetable_item *res; +} mc_msg_item; + +/* Defined in bfd/binary.c. Used to set architecture and machine of input + binary files. */ +extern enum bfd_architecture bfd_external_binary_architecture; +extern unsigned long bfd_external_machine; + +int target_is_bigendian = 0; +const char *def_target_arch; + +/* Globals and static variable definitions. */ + +/* bfd global helper struct variable. */ +static struct +{ + bfd *abfd; + asection *sec; +} mc_bfd; + +/* Memory list. */ +mc_node *mc_nodes = NULL; +static mc_node_lang **mc_nodes_lang = NULL; +static int mc_nodes_lang_count = 0; +static mc_keyword **mc_severity_codes = NULL; +static int mc_severity_codes_count = 0; +static mc_keyword **mc_facility_codes = NULL; +static int mc_facility_codes_count = 0; + +/* When we are building a resource tree, we allocate everything onto + an obstack, so that we can free it all at once if we want. */ +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +/* The resource building obstack. */ +static struct obstack res_obstack; + +/* Flag variables. */ +/* Set by -C. Set the default code page to be used for input text file. */ +static rc_uint_type mcset_codepage_in = 0; + +/* Set by -O. Set the default code page to be used for output text files. */ +static rc_uint_type mcset_codepage_out = 0; + +/* Set by -b. .BIN filename should have .mc filename_ included for uniqueness. */ +static int mcset_prefix_bin = 0; + +/* The base name of the .mc file. */ +static const char *mcset_mc_basename = "unknown"; + +/* Set by -e . Specify the extension for the header file. */ +static const char *mcset_header_ext = ".h"; + +/* Set by -h . Gives the path of where to create the C include file. */ +static const char *mcset_header_dir = "./"; + +/* Set by -r . Gives the path of where to create the RC include file + and the binary message resource files it includes. */ +static const char *mcset_rc_dir = "./"; + +/* Modified by -a & -u. By -u input file is unicode, by -a is ASCII (default). */ +static int mcset_text_in_is_unicode = 0; + +/* Modified by -A & -U. By -U bin file is unicode (default), by -A is ASCII. */ +static int mcset_bin_out_is_unicode = 1; + +/* Set by -c. Sets the Customer bit in all the message ID's. */ +int mcset_custom_bit = 0; + +/* Set by -o. Generate OLE2 header file. Use HRESULT definition instead of + status code definition. */ +static int mcset_use_hresult = 0; + +/* Set by -m . Generate a warning if the size of any message exceeds + maxmsglen characters. */ +rc_uint_type mcset_max_message_length = 0; + +/* Set by -d. Sets message values in header to decimal initially. */ +int mcset_out_values_are_decimal = 0; + +/* Set by -n. terminates all strings with null's in the message tables. */ +static int mcset_automatic_null_termination = 0; + +/* The type used for message id output in header. */ +unichar *mcset_msg_id_typedef = NULL; + +/* Set by -x path. Geberated debug C file for mapping ID's to text. */ +static const char *mcset_dbg_dir = NULL; + +/* getopt long name definitions. */ +static const struct option long_options[] = +{ + {"binprefix", no_argument, 0, 'b'}, + {"target", required_argument, 0, 'F'}, + {"extension", required_argument, 0, 'e'}, + {"headerdir", required_argument, 0, 'h'}, + {"rcdir", required_argument, 0, 'r'}, + {"verbose", no_argument, 0, 'v'}, + {"codepage_in", required_argument, 0, 'C'}, + {"codepage_out", required_argument, 0, 'O'}, + {"maxlength", required_argument, 0, 'm'}, + {"ascii_in", no_argument, 0, 'a'}, + {"ascii_out", no_argument, 0, 'A'}, + {"unicode_in", no_argument, 0, 'u'}, + {"unicode_out", no_argument, 0, 'U'}, + {"customflag", no_argument, 0, 'c'}, + {"decimal_values", no_argument, 0, 'd'}, + {"hresult_use", no_argument, 0, 'o'}, + {"nullterminate", no_argument, 0, 'n'}, + {"xdbg", required_argument, 0, 'x'}, + {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'H'}, + {0, no_argument, 0, 0} +}; + + +/* Initialize the resource building obstack. */ +static void +res_init (void) +{ + obstack_init (&res_obstack); +} + +/* Allocate space on the resource building obstack. */ +void * +res_alloc (rc_uint_type bytes) +{ + return (void *) obstack_alloc (&res_obstack, (size_t) bytes); +} + +static FILE * +mc_create_path_text_file (const char *path, const char *ext) +{ + FILE *ret; + size_t len = 1; + char *hsz; + + len += (path != NULL ? strlen (path) : 0); + len += strlen (mcset_mc_basename); + len += (ext != NULL ? strlen (ext) : 0); + hsz = xmalloc (len); + sprintf (hsz, "%s%s%s", (path != NULL ? path : ""), mcset_mc_basename, + (ext != NULL ? ext : "")); + if ((ret = fopen (hsz, "wb")) == NULL) + fatal (_("can't create %s file ,%s' for output.\n"), (ext ? ext : "text"), hsz); + free (hsz); + return ret; +} + +static void +usage (FILE *stream, int status) +{ + fprintf (stream, _("Usage: %s [option(s)] [input-file]\n"), + program_name); + fprintf (stream, _(" The options are:\n\ + -a --ascii_in Read input file as ASCII file\n\ + -A --ascii_out Write binary messages as ASCII\n\ + -b --binprefix .bin filename is prefixed by .mc filename_ for uniqueness.\n\ + -c --customflag Set custom flags for messages\n\ + -C --codepage_in= Set codepage when reading mc text file\n\ + -d --decimal_values Print values to text files decimal\n\ + -e --extension= Set header extension used on export header file\n\ + -F --target Specify output target for endianess.\n\ + -h --headerdir= Set the export directory for headers\n\ + -u --unicode_in Read input file as UTF16 file\n\ + -U --unicode_out Write binary messages as UFT16\n\ + -m --maxlength= Set the maximal allowed message length\n\ + -n --nullterminate Automatic add a zero termination to strings\n\ + -o --hresult_use Use HRESULT definition instead of status code definition\n\ + -O --codepage_out= Set codepage used for writing text file\n\ + -r --rcdir= Set the export directory for rc files\n\ + -x --xdbg= Where to create the .dbg C include file\n\ + that maps message ID's to their symbolic name.\n\ +")); + fprintf (stream, _("\ + -H --help Print this help message\n\ + -v --verbose Verbose - tells you what it's doing\n\ + -V --version Print version information\n")); + + list_supported_targets (program_name, stream); + + if (REPORT_BUGS_TO[0] && status == 0) + fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); + + exit (status); +} + +static void +set_endianess (bfd *abfd, const char *target) +{ + const bfd_target *target_vec; + + def_target_arch = NULL; + target_vec = bfd_find_target (target, abfd); + if (! target_vec) + fatal ("Can't detect target endianess and architecture."); + target_is_bigendian = ((target_vec->byteorder == BFD_ENDIAN_BIG) ? 1 : 0); + { + const char *tname = target_vec->name; + const char **arch = bfd_arch_list (); + + if (arch && tname) + { + if (strchr (tname, '-') != NULL) + tname = strchr (tname, '-') + 1; + while (*arch != NULL) + { + const char *in_a = strstr (*arch, tname); + char end_ch = (in_a ? in_a[strlen (tname)] : 0); + if (in_a && (in_a == *arch || in_a[-1] == ':') + && end_ch == 0) + { + def_target_arch = *arch; + break; + } + arch++; + } + } + if (! def_target_arch) + fatal ("Can't detect architecture."); + } +} + +static int +probe_codepage (rc_uint_type *cp, int *is_uni, const char *pswitch, int defmode) +{ + if (*is_uni == -1) + { + if (*cp != CP_UTF16) + *is_uni = defmode; + else + *is_uni = 1; + } + if (*is_uni) + { + if (*cp != 0 && *cp != CP_UTF16) + { + fprintf (stderr, _("%s: warning: "), program_name); + fprintf (stderr, _("A codepage was specified switch ,%s' and UTF16.\n"), pswitch); + fprintf (stderr, _("\tcodepage settings are ignored.\n")); + } + *cp = CP_UTF16; + return 1; + } + if (*cp == CP_UTF16) + { + *is_uni = 1; + return 1; + } + if (*cp == 0) + *cp = 1252; + if (! unicode_is_valid_codepage (*cp)) + fatal ("Code page 0x%x is unknown.", (unsigned int) *cp); + *is_uni = 0; + return 1; +} + +mc_node * +mc_add_node (void) +{ + mc_node *ret; + + ret = res_alloc (sizeof (mc_node)); + memset (ret, 0, sizeof (mc_node)); + if (! mc_nodes) + mc_nodes = ret; + else + { + mc_node *h = mc_nodes; + + while (h->next != NULL) + h = h->next; + h->next = ret; + } + return ret; +} + +mc_node_lang * +mc_add_node_lang (mc_node *root, const mc_keyword *lang, rc_uint_type vid) +{ + mc_node_lang *ret, *h, *p; + + if (! lang || ! root) + fatal (_("try to add a ill language.")); + ret = res_alloc (sizeof (mc_node_lang)); + memset (ret, 0, sizeof (mc_node_lang)); + ret->lang = lang; + ret->vid = vid; + if ((h = root->sub) == NULL) + root->sub = ret; + else + { + p = NULL; + while (h != NULL) + { + if (h->lang->nval > lang->nval) + break; + if (h->lang->nval == lang->nval) + { + if (h->vid > vid) + break; + if (h->vid == vid) + fatal ("double defined message id %ld.\n", (long) vid); + } + h = (p = h)->next; + } + ret->next = h; + if (! p) + root->sub = ret; + else + p->next = ret; + } + return ret; +} + +static char * +convert_unicode_to_ACP (const unichar *usz) +{ + char *s; + rc_uint_type l; + + if (! usz) + return NULL; + codepage_from_unicode (&l, usz, &s, mcset_codepage_out); + if (! s) + fatal ("unicode string not mappable to ASCII codepage 0x%lx.\n", (long) mcset_codepage_out); + return s; +} + +static void +write_dbg_define (FILE *fp, const unichar *sym_name, const unichar *typecast) +{ + char *sym; + + if (!sym_name || sym_name[0] == 0) + return; + sym = convert_unicode_to_ACP (sym_name); + fprintf (fp, " {("); + if (typecast) + unicode_print (fp, typecast, unichar_len (typecast)); + else + fprintf (fp, "DWORD"); + fprintf (fp, ") %s, \"%s\" },\n", sym, sym); +} + +static void +write_header_define (FILE *fp, const unichar *sym_name, rc_uint_type vid, const unichar *typecast, mc_node_lang *nl) +{ + char *sym; + char *tdef = NULL; + + if (!sym_name || sym_name[0] == 0) + { + if (nl != NULL) + { + if (mcset_out_values_are_decimal) + fprintf (fp, "//\n// MessageId: 0x%lu\n//\n", (unsigned long) vid); + else + fprintf (fp, "//\n// MessageId: 0x%lx\n//\n", (unsigned long) vid); + } + return; + } + sym = convert_unicode_to_ACP (sym_name); + if (typecast && typecast[0] != 0) + tdef = convert_unicode_to_ACP (typecast); + fprintf (fp, "//\n// MessageId: %s\n//\n", sym); + if (! mcset_out_values_are_decimal) + fprintf (fp, "#define %s %s%s%s 0x%lx\n\n", sym, + (tdef ? "(" : ""), (tdef ? tdef : ""), (tdef ? ")" : ""), + (unsigned long) vid); + else + fprintf (fp, "#define %s %s%s%s 0x%lu\n\n", sym, + (tdef ? "(" : ""), (tdef ? tdef : ""), (tdef ? ")" : ""), + (unsigned long) vid); +} + +static int +sort_mc_node_lang (const void *l, const void *r) +{ + const mc_node_lang *l1 = *((const mc_node_lang **)l); + const mc_node_lang *r1 = *((const mc_node_lang **)r); + + if (l == r) + return 0; + if (l1->lang != r1->lang) + { + if (l1->lang->nval < r1->lang->nval) + return -1; + return 1; + } + if (l1->vid == r1->vid) + return 0; + if (l1->vid < r1->vid) + return -1; + return 1; +} + +static int +sort_keyword_by_nval (const void *l, const void *r) +{ + const mc_keyword *l1 = *((const mc_keyword **)l); + const mc_keyword *r1 = *((const mc_keyword **)r); + rc_uint_type len1, len2; + int e; + + if (l == r) + return 0; + if (l1->nval != r1->nval) + { + if (l1->nval < r1->nval) + return -1; + return 1; + } + len1 = unichar_len (l1->usz); + len2 = unichar_len (r1->usz); + if (len1 <= len2) + e = memcmp (l1->usz, r1->usz, sizeof (unichar) * len1); + else + e = memcmp (l1->usz, r1->usz, sizeof (unichar) * len2); + if (e) + return e; + if (len1 < len2) + return -1; + else if (len1 > len2) + return 1; + return 0; +} + +static void +do_sorts (void) +{ + mc_node *h; + mc_node_lang *n; + const mc_keyword *k; + int i; + + /* Sort message by their language and id ascending. */ + mc_nodes_lang_count = 0; + + h = mc_nodes; + while (h != NULL) + { + n = h->sub; + while (n != NULL) + { + mc_nodes_lang_count +=1; + n = n->next; + } + h = h->next; + } + + if (mc_nodes_lang_count != 0) + { + h = mc_nodes; + i = 0; + mc_nodes_lang = xmalloc (sizeof (mc_node_lang *) * mc_nodes_lang_count); + + while (h != NULL) + { + n = h->sub; + while (n != NULL) + { + mc_nodes_lang[i++] = n; + n = n->next; + } + h = h->next; + } + qsort (mc_nodes_lang, (size_t) mc_nodes_lang_count, sizeof (mc_node_lang *), sort_mc_node_lang); + } + /* Sort facility code definitions by there id ascending. */ + i = 0; + while ((k = enum_facility (i)) != NULL) + ++i; + mc_facility_codes_count = i; + if (i != 0) + { + mc_facility_codes = xmalloc (sizeof (mc_keyword *) * i); + i = 0; + while ((k = enum_facility (i)) != NULL) + mc_facility_codes[i++] = (mc_keyword *) k; + qsort (mc_facility_codes, (size_t) mc_facility_codes_count, sizeof (mc_keyword *), sort_keyword_by_nval); + } + + /* Sort severity code definitions by there id ascending. */ + i = 0; + while ((k = enum_severity (i)) != NULL) + ++i; + mc_severity_codes_count = i; + if (i != 0) + { + mc_severity_codes = xmalloc (sizeof (mc_keyword *) * i); + i = 0; + while ((k = enum_severity (i)) != NULL) + mc_severity_codes[i++] = (mc_keyword *) k; + qsort (mc_severity_codes, (size_t) mc_severity_codes_count, sizeof (mc_keyword *), sort_keyword_by_nval); + } +} + +static int +mc_get_block_count (mc_node_lang **nl, int elems) +{ + rc_uint_type exid; + int i, ret; + + if (! nl) + return 0; + i = 0; + ret = 0; + while (i < elems) + { + ret++; + exid = nl[i++]->vid; + while (i < elems && nl[i]->vid == exid + 1) + exid = nl[i++]->vid; + } + return ret; +} + +static bfd * +windmc_open_as_binary (const char *filename) +{ + bfd *abfd; + + abfd = bfd_openw (filename, "binary"); + if (! abfd) + fatal ("can't open `%s' for output", filename); + + return abfd; +} + +static void +target_put_16 (void *p, rc_uint_type value) +{ + assert (!! p); + + if (target_is_bigendian) + bfd_putb16 (value, p); + else + bfd_putl16 (value, p); +} + +static void +target_put_32 (void *p, rc_uint_type value) +{ + assert (!! p); + + if (target_is_bigendian) + bfd_putb32 (value, p); + else + bfd_putl32 (value, p); +} + +static struct bin_messagetable_item * +mc_generate_bin_item (mc_node_lang *n, rc_uint_type *res_len) +{ + struct bin_messagetable_item *ret = NULL; + rc_uint_type len; + + *res_len = 0; + if (mcset_bin_out_is_unicode == 1) + { + unichar *ht = n->message; + rc_uint_type txt_len; + + txt_len = unichar_len (n->message); + if (mcset_automatic_null_termination && txt_len != 0) + { + while (txt_len > 0 && ht[txt_len - 1] > 0 && ht[txt_len - 1] < 0x20) + ht[--txt_len] = 0; + } + txt_len *= sizeof (unichar); + len = BIN_MESSAGETABLE_ITEM_SIZE + txt_len + sizeof (unichar); + ret = res_alloc ((len + 3) & ~3); + memset (ret, 0, (len + 3) & ~3); + target_put_16 (ret->length, (len + 3) & ~3); + target_put_16 (ret->flags, MESSAGE_RESOURCE_UNICODE); + txt_len = 0; + while (*ht != 0) + { + target_put_16 (ret->data + txt_len, *ht++); + txt_len += 2; + } + } + else + { + rc_uint_type txt_len, l; + char *cvt_txt; + + codepage_from_unicode( &l, n->message, &cvt_txt, n->lang->lang_info.wincp); + if (! cvt_txt) + fatal ("Failed to convert message to language codepage.\n"); + txt_len = strlen (cvt_txt); + if (mcset_automatic_null_termination && txt_len > 0) + { + while (txt_len > 0 && cvt_txt[txt_len - 1] > 0 && cvt_txt[txt_len - 1] < 0x20) + cvt_txt[--txt_len] = 0; + } + len = BIN_MESSAGETABLE_ITEM_SIZE + txt_len + 1; + ret = res_alloc ((len + 3) & ~3); + memset (ret, 0, (len + 3) & ~3); + target_put_16 (ret->length, (len + 3) & ~3); + target_put_16 (ret->flags, 0); + strcpy ((char *) ret->data, cvt_txt); + } + *res_len = (len + 3) & ~3; + return ret; +} + +static void +mc_write_blocks (struct bin_messagetable *mtbl, mc_node_lang **nl, mc_msg_item *ml, int elems) +{ + int i, idx = 0; + rc_uint_type exid; + + if (! nl) + return; + i = 0; + while (i < elems) + { + target_put_32 (mtbl->items[idx].lowid, nl[i]->vid); + target_put_32 (mtbl->items[idx].highid, nl[i]->vid); + target_put_32 (mtbl->items[idx].offset, ml[i].res_off); + exid = nl[i++]->vid; + while (i < elems && nl[i]->vid == exid + 1) + { + target_put_32 (mtbl->items[idx].highid, nl[i]->vid); + exid = nl[i++]->vid; + } + ++idx; + } +} + +static void +set_windmc_bfd_content (const void *data, rc_uint_type off, rc_uint_type length) +{ + if (! bfd_set_section_contents (mc_bfd.abfd, mc_bfd.sec, data, off, length)) + bfd_fatal ("bfd_set_section_contents"); +} + +static void +windmc_write_bin (const char *filename, mc_node_lang **nl, int elems) +{ + unsigned long sec_length = 1; + int block_count, i; + mc_msg_item *mi; + struct bin_messagetable *mtbl; + rc_uint_type dta_off, dta_start; + + if (elems <= 0) + return; + mc_bfd.abfd = windmc_open_as_binary (filename); + mc_bfd.sec = bfd_make_section (mc_bfd.abfd, ".data"); + if (mc_bfd.sec == NULL) + bfd_fatal ("bfd_make_section"); + if (! bfd_set_section_flags (mc_bfd.abfd, mc_bfd.sec, + (SEC_HAS_CONTENTS | SEC_ALLOC + | SEC_LOAD | SEC_DATA))) + bfd_fatal ("bfd_set_section_flags"); + /* Requiring this is probably a bug in BFD. */ + mc_bfd.sec->output_section = mc_bfd.sec; + + block_count = mc_get_block_count (nl, elems); + + dta_off = (rc_uint_type) ((BIN_MESSAGETABLE_BLOCK_SIZE * block_count) + BIN_MESSAGETABLE_SIZE - 4); + dta_start = dta_off = (dta_off + 3) & ~3; + mi = xmalloc (sizeof (mc_msg_item) * elems); + mtbl = xmalloc (dta_start); + + /* Clear header region. */ + memset (mtbl, 0, dta_start); + target_put_32 (mtbl->cblocks, block_count); + /* Prepare items section for output. */ + for (i = 0; i < elems; i++) + { + mi[i].res_off = dta_off; + mi[i].res = mc_generate_bin_item (nl[i], &mi[i].res_len); + dta_off += mi[i].res_len; + } + sec_length = (dta_off + 3) & ~3; + if (! bfd_set_section_size (mc_bfd.abfd, mc_bfd.sec, sec_length)) + bfd_fatal ("bfd_set_section_size"); + /* Make sure we write the complete block. */ + set_windmc_bfd_content ("\0", sec_length - 1, 1); + + /* Write block information. */ + mc_write_blocks (mtbl, nl, mi, elems); + + set_windmc_bfd_content (mtbl, 0, dta_start); + + /* Write items. */ + for (i = 0; i < elems; i++) + set_windmc_bfd_content (mi[i].res, mi[i].res_off, mi[i].res_len); + + free (mtbl); + free (mi); + bfd_close (mc_bfd.abfd); + mc_bfd.abfd = NULL; + mc_bfd.sec = NULL; +} + +static void +write_bin (void) +{ + mc_node_lang *n = NULL; + int i, c; + + if (! mc_nodes_lang_count) + return; + + i = 0; + while (i < mc_nodes_lang_count) + { + char *nd; + char *filename; + + if (n && n->lang == mc_nodes_lang[i]->lang) + { + i++; + continue; + } + n = mc_nodes_lang[i]; + c = i + 1; + while (c < mc_nodes_lang_count && n->lang == mc_nodes_lang[c]->lang) + c++; + nd = convert_unicode_to_ACP (n->lang->sval); + + /* Prepare filename for binary output. */ + filename = xmalloc (strlen (nd) + 4 + 1 + strlen (mcset_mc_basename) + 1 + strlen (mcset_rc_dir)); + strcpy (filename, mcset_rc_dir); + if (mcset_prefix_bin) + sprintf (filename + strlen (filename), "%s_", mcset_mc_basename); + strcat (filename, nd); + strcat (filename, ".bin"); + + /* Write message file. */ + windmc_write_bin (filename, &mc_nodes_lang[i], (c - i)); + + free (filename); + i = c; + } +} + +static void +write_rc (FILE *fp) +{ + mc_node_lang *n; + int i, l; + + fprintf (fp, + "/* Do not edit this file manually.\n" + " This file is autogenerated by windmc. */\n\n"); + if (! mc_nodes_lang_count) + return; + n = NULL; + i = 0; + for (l = 0; l < mc_nodes_lang_count; l++) + { + if (n && n->lang == mc_nodes_lang[l]->lang) + continue; + ++i; + n = mc_nodes_lang[l]; + fprintf (fp, "\n// Country: %s\n// Language: %s\n#pragma code_page(%u)\n", + n->lang->lang_info.country, n->lang->lang_info.name, + (unsigned) n->lang->lang_info.wincp); + fprintf (fp, "LANGUAGE 0x%lx, 0x%lx\n", (long) (n->lang->nval & 0x3ff), + (long) ((n->lang->nval & 0xffff) >> 10)); + fprintf (fp, "1 MESSAGETABLE \""); + if (mcset_prefix_bin) + fprintf (fp, "%s_", mcset_mc_basename); + unicode_print (fp, n->lang->sval, unichar_len (n->lang->sval)); + fprintf (fp, ".bin\"\n"); + } +} + +static void +write_dbg (FILE *fp) +{ + mc_node *h; + + fprintf (fp, + "/* Do not edit this file manually.\n" + " This file is autogenerated by windmc.\n\n" + " This file maps each message ID value in to a text string that contains\n" + " the symbolic name used for it. */\n\n"); + + fprintf (fp, + "struct %sSymbolicName\n" + "{\n ", mcset_mc_basename); + if (mcset_msg_id_typedef) + unicode_print (fp, mcset_msg_id_typedef, unichar_len (mcset_msg_id_typedef)); + else + fprintf (fp, "DWORD"); + fprintf (fp, + " MessageId;\n" + " char *SymbolicName;\n" + "} %sSymbolicNames[] =\n" + "{\n", mcset_mc_basename); + h = mc_nodes; + while (h != NULL) + { + if (h->symbol) + write_dbg_define (fp, h->symbol, mcset_msg_id_typedef); + h = h->next; + } + fprintf (fp, " { ("); + if (mcset_msg_id_typedef) + unicode_print (fp, mcset_msg_id_typedef, unichar_len (mcset_msg_id_typedef)); + else + fprintf (fp, "DWORD"); + fprintf (fp, + ") 0xffffffff, NULL }\n" + "};\n"); +} + +static void +write_header (FILE *fp) +{ + char *s; + int i; + const mc_keyword *key; + mc_node *h; + + fprintf (fp, + "/* Do not edit this file manually.\n" + " This file is autogenerated by windmc. */\n\n" + "//\n// The values are 32 bit layed out as follows:\n//\n" + "// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1\n" + "// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0\n" + "// +---+-+-+-----------------------+-------------------------------+\n" + "// |Sev|C|R| Facility | Code |\n" + "// +---+-+-+-----------------------+-------------------------------+\n//\n" + "// where\n//\n" + "// C - is the Customer code flag\n//\n" + "// R - is a reserved bit\n//\n" + "// Code - is the facility's status code\n//\n"); + + h = mc_nodes; + + fprintf (fp, "// Sev - is the severity code\n//\n"); + if (mc_severity_codes_count != 0) + { + for (i = 0; i < mc_severity_codes_count; i++) + { + key = mc_severity_codes[i]; + fprintf (fp, "// %s - %02lx\n", convert_unicode_to_ACP (key->usz), + (unsigned long) key->nval); + if (key->sval && key->sval[0] != 0) + { + if (! mcset_out_values_are_decimal) + fprintf (fp, "#define %s 0x%lx\n", convert_unicode_to_ACP (key->sval), + (unsigned long) key->nval); + else + fprintf (fp, "#define %s 0x%lu\n", convert_unicode_to_ACP (key->sval), + (unsigned long) key->nval); + } + } + fprintf (fp, "//\n"); + } + fprintf (fp, "// Facility - is the facility code\n//\n"); + if (mc_facility_codes_count != 0) + { + for (i = 0; i < mc_facility_codes_count; i++) + { + key = mc_facility_codes[i]; + fprintf (fp, "// %s - %04lx\n", convert_unicode_to_ACP (key->usz), + (unsigned long) key->nval); + if (key->sval && key->sval[0] != 0) + { + if (! mcset_out_values_are_decimal) + fprintf (fp, "#define %s 0x%lx\n", convert_unicode_to_ACP (key->sval), + (unsigned long) key->nval); + else + fprintf (fp, "#define %s 0x%lu\n", convert_unicode_to_ACP (key->sval), + (unsigned long) key->nval); + } + } + fprintf (fp, "//\n"); + } + fprintf (fp, "\n"); + while (h != NULL) + { + if (h->user_text) + { + s = convert_unicode_to_ACP (h->user_text); + if (s) + fprintf (fp, "%s", s); + } + if (h->symbol) + write_header_define (fp, h->symbol, h->vid, mcset_msg_id_typedef, h->sub); + h = h->next; + } +} + +static const char * +mc_unify_path (const char *path) +{ + char *end; + char *hsz; + + if (! path || *path == 0) + return "./"; + hsz = xmalloc (strlen (path) + 2); + strcpy (hsz, path); + end = hsz + strlen (hsz); + if (hsz[-1] != '/' && hsz[-1] != '\\') + strcpy (end, "/"); + while ((end = strchr (hsz, '\\')) != NULL) + *end = '/'; + return hsz; +} + +int main (int, char **); + +int +main (int argc, char **argv) +{ + FILE *h_fp; + int c; + char *target, *input_filename; + int verbose; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif +#if defined (HAVE_SETLOCALE) + setlocale (LC_CTYPE, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = argv[0]; + xmalloc_set_program_name (program_name); + + expandargv (&argc, &argv); + + bfd_init (); + set_default_bfd_target (); + + target = NULL; + verbose = 0; + input_filename = NULL; + + res_init (); + + while ((c = getopt_long (argc, argv, "C:F:O:h:e:m:r:x:aAbcdHunoUvV", long_options, + (int *) 0)) != EOF) + { + switch (c) + { + case 'b': + mcset_prefix_bin = 1; + break; + case 'e': + { + mcset_header_ext = optarg; + if (mcset_header_ext[0] != '.' && mcset_header_ext[0] != 0) + { + char *hsz = xmalloc (strlen (mcset_header_ext) + 2); + + sprintf (hsz, ".%s", mcset_header_ext); + mcset_header_ext = hsz; + } + } + break; + case 'h': + mcset_header_dir = mc_unify_path (optarg); + break; + case 'r': + mcset_rc_dir = mc_unify_path (optarg); + break; + case 'a': + mcset_text_in_is_unicode = 0; + break; + case 'x': + if (*optarg != 0) + mcset_dbg_dir = mc_unify_path (optarg); + break; + case 'A': + mcset_bin_out_is_unicode = 0; + break; + case 'd': + mcset_out_values_are_decimal = 1; + break; + case 'u': + mcset_text_in_is_unicode = 1; + break; + case 'U': + mcset_bin_out_is_unicode = 1; + break; + case 'c': + mcset_custom_bit = 1; + break; + case 'n': + mcset_automatic_null_termination = 1; + break; + case 'o': + mcset_use_hresult = 1; + fatal ("option -o is not implemented until yet.\n"); + break; + case 'F': + target = optarg; + break; + case 'v': + verbose ++; + break; + case 'm': + mcset_max_message_length = strtol (optarg, (char **) NULL, 10); + break; + case 'C': + mcset_codepage_in = strtol (optarg, (char **) NULL, 10); + break; + case 'O': + mcset_codepage_out = strtol (optarg, (char **) NULL, 10); + break; + case '?': + case 'H': + usage (stdout, 0); + break; + case 'V': + print_version ("windmc"); + break; + + default: + usage (stderr, 1); + break; + } + } + if (input_filename == NULL && optind < argc) + { + input_filename = argv[optind]; + ++optind; + } + + set_endianess (NULL, target); + + if (input_filename == NULL) + { + fprintf (stderr, "Error: No input file was specified.\n"); + usage (stderr, 1); + } + mc_set_inputfile (input_filename); + + if (!probe_codepage (&mcset_codepage_in, &mcset_text_in_is_unicode, "codepage_in", 0)) + usage (stderr, 1); + if (mcset_codepage_out == 0) + mcset_codepage_out = 1252; + if (! unicode_is_valid_codepage (mcset_codepage_out)) + fatal ("Code page 0x%x is unknown.", (unsigned int) mcset_codepage_out); + if (mcset_codepage_out == CP_UTF16) + fatal ("UTF16 is no valid text output code page."); + if (verbose) + { + fprintf (stderr, "// Default target is %s and it is %s endian.\n", + def_target_arch, (target_is_bigendian ? "big" : "little")); + fprintf (stderr, "// Input codepage: 0x%x\n", (unsigned int) mcset_codepage_in); + fprintf (stderr, "// Output codepage: 0x%x\n", (unsigned int) mcset_codepage_out); + } + + if (argc != optind) + usage (stderr, 1); + + /* Initialize mcset_mc_basename. */ + { + const char *bn, *bn2; + char *hsz; + + bn = strrchr (input_filename, '/'); + bn2 = strrchr (input_filename, '\\'); + if (! bn) + bn = bn2; + if (bn && bn2 && bn < bn2) + bn = bn2; + if (! bn) + bn = input_filename; + else + bn++; + mcset_mc_basename = hsz = xstrdup (bn); + + /* Cut of right-hand extension. */ + if ((hsz = strrchr (hsz, '.')) != NULL) + *hsz = 0; + } + + /* Load the input file and do code page transformations to UTF16. */ + { + unichar *u; + rc_uint_type ul; + char *buff; + long flen; + FILE *fp = fopen (input_filename, "rb"); + + if (!fp) + fatal (_("unable to open file ,%s' for input.\n"), input_filename); + + fseek (fp, 0, SEEK_END); + flen = ftell (fp); + fseek (fp, 0, SEEK_SET); + buff = malloc (flen + 3); + memset (buff, 0, flen + 3); + fread (buff, 1, flen, fp); + fclose (fp); + if (mcset_text_in_is_unicode != 1) + { + unicode_from_codepage (&ul, &u, buff, mcset_codepage_in); + if (! u) + fatal ("Failed to convert input to UFT16\n"); + mc_set_content (u); + } + else + { + if ((flen & 1) != 0) + fatal (_("input file does not seems to be UFT16.\n")); + mc_set_content ((unichar *) buff); + } + free (buff); + } + + while (yyparse ()) + ; + + do_sorts (); + + h_fp = mc_create_path_text_file (mcset_header_dir, mcset_header_ext); + write_header (h_fp); + fclose (h_fp); + + h_fp = mc_create_path_text_file (mcset_rc_dir, ".rc"); + write_rc (h_fp); + fclose (h_fp); + + if (mcset_dbg_dir != NULL) + { + h_fp = mc_create_path_text_file (mcset_dbg_dir, ".dbg"); + write_dbg (h_fp); + fclose (h_fp); + } + write_bin (); + + if (mc_nodes_lang) + free (mc_nodes_lang); + if (mc_severity_codes) + free (mc_severity_codes); + if (mc_facility_codes) + free (mc_facility_codes); + + xexit (0); + return 0; +} diff --git a/binutils/windmc.h b/binutils/windmc.h new file mode 100644 index 0000000000..08a7706260 --- /dev/null +++ b/binutils/windmc.h @@ -0,0 +1,99 @@ +/* windmc.h -- header file for windmc program. + Copyright 2007 + Free Software Foundation, Inc. + Written by Kai Tietz, Onevision. + + This file is part of GNU Binutils. + + 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 + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include "ansidecl.h" + +/* This is the header file for the windmc program. It defines + structures and declares functions used within the program. */ + +#include "winduni.h" + +#ifndef WINDMC_HXX +#define WINDMC_HXX + +/* Global flag variables (set by windmc.c file. */ +extern int mcset_custom_bit; +extern int mcset_out_values_are_decimal; +extern rc_uint_type mcset_max_message_length; +extern unichar *mcset_msg_id_typedef; + +/* Lexer keyword definition and internal memory structures. */ + +typedef struct mc_keyword +{ + struct mc_keyword *next; + const char *group_name; + size_t len; + unichar *usz; + int rid; + rc_uint_type nval; + unichar *sval; + wind_language_t lang_info; +} mc_keyword; + +typedef struct mc_node_lang +{ + struct mc_node_lang *next; + rc_uint_type vid; + const mc_keyword *lang; + unichar *message; +} mc_node_lang; + +typedef struct mc_node +{ + struct mc_node *next; + unichar *user_text; + const mc_keyword *facility; + const mc_keyword *severity; + unichar *symbol; + rc_uint_type id; + rc_uint_type vid; + mc_node_lang *sub; +} mc_node; + +extern mc_node *mc_nodes; + +void mc_add_keyword (unichar *, int, const char *, rc_uint_type, unichar *); +const mc_keyword *enum_facility (int); +const mc_keyword *enum_severity (int); + +mc_node_lang *mc_add_node_lang (mc_node *, const mc_keyword *, rc_uint_type); +mc_node *mc_add_node (void); + +/* Standard yacc/flex stuff. */ +int yyerror (const char *, ...); +int yylex (void); +int yyparse (void); + +/* mclex.c */ +void mc_set_inputfile (const char *); +void mc_set_content (const unichar *); + +/* Lexer control variables. Used by mcparser.y file. */ +extern bfd_boolean mclex_want_nl; +extern bfd_boolean mclex_want_line; +extern bfd_boolean mclex_want_filename; + +void mc_fatal (const char *, ...); +void mc_warn (const char *, ...); + +#endif -- cgit v1.2.1