• Arnavion 2 hours ago

    I was thinking `NOT (1|2)` and `NOT () 2` could make sense if the parser just has a `not_in_effect` flag that gets set to true when a `NOT` is encountered and then applies to the next integer as soon as one is parsed. So `NOT (1|2)` sets the flag, then starts parsing `(1|2)`. Once it's parsed the `1`, it notices a NOT is in effect so it applies it to the 1 as if it had just parsed `NOT 1` (which leaves 0 unchanged), then parses `| 2`, so the result is 2.

    `NOT () 2` would be the same logic. `)` signifies the end of an expression and thus evaluates to the current integral result, which is 0 (for the same reason that unary - is zero), and a NOT is in effect so it's treated as `NOT 0` which is a no-op ("unset no bits"). Then the next `2` makes the result `2`. This assumes that `x y` is parsed the same as `x | y` (maybe only if a `NOT` has been parsed at any point first) or as `y` (the same stack-like "the last number that was parsed becomes the result" behavior described in other items).

    This doesn't explain the `7 NOT NOT 4 NOT 2 NOT NOT 1 = 2` case though. If the parser just *sets* the `not_in_effect` flag when it encounters a `NOT` (instead of *toggling* it), then this would be `7 | NOT 4 | NOT 2 | NOT 1` which would be 0. If the parser does toggle the flag, this would be `7 | 4 | NOT 2 | 1` which would be 1 or 5. If the parser treats a `NOT` as ending the previous expression (if any), this would be `7 | NOT 0 | NOT 4 | NOT 2 | NOT 0 | NOT 1` which would be 0.

    • squeek502 3 hours ago

      I'm the author if anyone has questions

      • 1f60c 2 hours ago

        Resinator's error messages look amazing! I also feel like I’ve gained a lot of cursed but useless (to me) knowledge, so thanks for that. :-)

        I don't have a horse in this race, but regarding FONT resources, I would like to humbly suggest not supporting them at all. Radical, but from what you wrote, they do seem pretty weird and ripe for accidental misuse. Plus, they are obsolete and it seems like Resinator already intentionally diverges from rc.exe in a few cases anyway.

        • squeek502 2 hours ago

          Thanks!

          I'm actually pretty okay with where I've landed with FONT resources. The legwork has already been done in figuring things out, and with the strategy I've chosen, resinator doesn't even need to parse .fnt files at all, so the implementation is pretty simple (I wrote a .fnt parser, but it's now unused[1]).

          [1] https://github.com/squeek502/resinator/blob/master/src/fnt.z...

      • immibis 2 hours ago

        That's a crazy amount of work and a crazy amount of quirks indeed. Very much illustrates a mindset where the user is at fault if they provide bad input - and development effort for everything was multiplied compared to today. In 1985, of course, nobody cared about things like security from untrusted inputs, and reproducible builds.

        My favourite bug from this list is that the compiler expands tabs to spaces in string literals and puts them at tab stops based on the string literal's horizontal position in the source file.

        I think that being able to directly define resource type 6 is not a bug. You got exactly what you asked for - an invalid resource. Crashing when loading it isn't a bug, either.

        I suppose that style flag arguments are parsed as |-separated lists of numeric or NOT expressions, rather than single expressions where | serves as bitwise-or.

        > If the truncated value is >= 0x80, add 0xFF00 and write the result as a little-endian u32. If the truncated value is < 0x80 but not zero, write the value as a little-endian u32.

        This is sign-extension: s8 -> s16 -> u16 -> u32. The examples below this also seem to have reversed the order of the input byte and the FF.

        Visual C++ 6, at least, includes a toolbar resource editor. IIRC it shows the toolbar metadata and the bitmap together in one editor, and you edit each button's image individually even though they are concatenated into one bitmap in the resource file.

        "GROUPBOX can only be used in DIALOGEX" might refer to some limitation other than the resource compiler. For example, perhaps Windows versions that don't support DIALOGEX also don't support GROUPBOX.

        A lot of them could be caused by memory safety errors. For example the fact that "1 ICON {" treats "ICON" as the filename is probably because the tokenizer doesn't set the Microsoft equivalent of yytext for tokens where it's not supposed to be relevant. Maybe it would even crash (null pointer) if { could be the first token (which it can't).

        • squeek502 an hour ago

          Appreciate the added context!

          > |-separated lists of numeric or NOT

          Note that | is not the only operator that can be used in style parameters, & + and - are all allowed too.

          > perhaps Windows versions that don't support DIALOGEX also don't support GROUPBOX

          Seems possible for sure. From [1]:

          > The 16-bit extended dialog template is purely historical. The only operating systems to support it were the Windows 95/98/Me series.

          [1] https://devblogs.microsoft.com/oldnewthing/20040622-00/?p=38...

          > The examples below this also seem to have reversed the order of the input byte and the FF.

          Good catch, fixed