Skip to content

Macro expander fails on "X macro" AddMagickCoder in ImageMagick #616

Open
@mattmccutchen-cci

Description

@mattmccutchen-cci

ImageMagick has an "X macro" named AddMagickCoder that is defined differently in three different files (MagickCore/{coder,magic,static}.c) before including a header file (coders/coders-list.h) that makes many calls to AddMagickCoder.

The macro expander has a workaround where if it sees several different expansions of the same line, it keeps the original, unexpanded content. This workaround correctly handles most of the calls to AddMagickCoder. However, there are a few calls for which the coder.c and magic.c expansions are blank (due to the behavior of the particular definitions of AddMagickCoder in those files) but the static.c expansion is non-blank. In order to correctly handle preprocessor conditionals, the macro expander ignores blank expansions, so it accepts the static.c expansion of each of those lines as its unique valid expansion and copies it into coders/coders-list.h. That expansion then shows up in coder.c and magic.c, causing the verification to fail.

I don't see an obvious way to adjust the "different expansions" workaround to completely solve the AddMagickCoder problem without breaking other cases. --undef_macros doesn't help either because the macros are defined in the main source file (just like the printf recursive macros in some of the benchmarks in analyse-conv that are currently patched by an ad-hoc sed command in the makefile). So it seems we need some other way to prevent the AddMagickCoder calls from expanding. Some ideas:

  1. Apply ad-hoc patches to the source code before macro expansion. For example, we could have the macro expander define a special macro during its operation (e.g., -D_3C_MACRO_EXPANDER) and then put #ifndef _3C_MACRO_EXPANDER around problematic constructs. This is probably the most general approach (and users could actually leave those conditionals in their code during porting), but we may prefer a less invasive approach if possible.
  2. Add an option to convert_project that excludes a file from macro expansion (in this case, coders/coders-list.h).
  3. Add a --hide_macros option that temporarily deletes anything that looks like a #define of one of the specified macros during macro expansion and then adds the #defines back in at the end. This is likely the most work to implement, but it will handle the printf wrapper macros as well as AddMagickCoder, so it might be worth going ahead and doing it.

So: any thoughts?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions