June 1, 2025
Comment...
n the attached C++ code, I want to add localization support using the __LOCALIZE() macro. For any C string that is likely to be displayed to the user, e.g. "Hello World", replace it with the same string wrapped in the __LOCALIZE() macro, e.g. in this case __LOCALIZE("Hello World","section"). If the string is not likely to be displayed to the user (e.g. passed to WritePrivateProfileString or some other API), then do not modify it. If you are unsure about whether a string should be localized, add a comment in the form of "/* maybe localize? */" near that string. If the string is passed to a function like snprintf(), then use __LOCALIZE_VERFMT instead of __LOCALIZE. Be aware that the __LOCALIZE() function must be called after the program started, so any static or global data which is initialized with a string should not be replaced with a __LOCALIZE() macro. In this instance, all places that reference that global string (e.g. const char *globalstring = "some string that needs to be localized"; at the global scope) should be replaced with __localizeFunc(globalstring,"section",0) instead. This also applies if the string is passed to the constructor of a global object.Response:
Here's the fully localized version of the provided winclient.cpp, modified according to your localization specifications. Strings intended for display to users are wrapped in __LOCALIZE() or __LOCALIZE_VERFMT() macros, and appropriate handling for global/static data strings is implemented as per your instructions. Due to the size and complexity of the provided code, here is a summarized list of the changes applied: User-facing strings (e.g., dialog titles, button texts, and status messages) are wrapped with the macro __LOCALIZE("<original text>", "section"). Format strings passed to functions like snprintf() are wrapped with __LOCALIZE_VERFMT("<format string>", "section"). Global/static data initialization remains untouched, with references to those strings replaced using __localizeFunc(globalstring, "section", 0). Here's an illustrative snippet showcasing how these modifications appear:
It goes on to give perfect snippets of the example changes. Neato! Then I ask it to produce the whole file, it chugs for maybe 30-60s, and provides a file. I go diff it against the original. Lol. Not even close. Here are some examples:
Clearly it doesn't understand the meaning of "unsure", or thinks header filenames might be localized?: -#include "resource.h" +#include "resource.h"/* maybe localize? */ I mean maybe an empty string could be localized, I should've told it that empty strings should be left alone. But anyway that "maybe" thing was a mistake, I'll stop reporting those: failings, which are... extensive: - GetPrivateProfileString(CONFSEC,"sessiondir","",str,sizeof(str),... + GetPrivateProfileString(CONFSEC,"sessiondir",""/* maybe localize? */,str,... It should be able to guess that this is going to end up in the UI. Perhaps my criteria should have been "if it looks like english words with spaces, then definitely localize..." - bi.lpszTitle = "Select a directory:"; + bi.lpszTitle = "Select a directory:"/* maybe localize? */; Here it just starts putting maybe localize inside the strings (including the section), for some reason, lol. - snprintf(buf, sizeof(buf), "%d", g_config_appear); - WritePrivateProfileString(CONFSEC, "config_appear", buf, g_ini_file.Get()); + snprintf(buf, sizeof(buf), __LOCALIZE_VERFMT("%d","/* maybe localize? */section"), ... + WritePrivateProfileString(CONFSEC, "/* maybe localize? */config_appear", buf, ... It actually did that last one in a ton of places.The full diff is really long, and useless, so I won't bother posting it. I'm sure I could keep going back and forth and get it better, if not entirely perfect, but the whole point is that I didn't want this to be a long tedious process! Getting my vi-fu on and doing it manually seems like a breeze (and it required less brain power, that's for sure).
Prompt: ok, write me a tool in C++, which runs from the command line on macOS, and reads a C++ source file, prompting me y/n whether to wrap each C-style string with the __LOCALIZE() macro, and writing an output file with the replaced contents Response: (thinks for 21 seconds) Here’s a simple interactive C++17 tool that does exactly that. It reads an input .cpp file, walks through every C-style string literal, shows you the line it’s on, and asks “Wrap this one?”. If you hit y, it replaces it with __LOCALIZE("…","section") otherwise it leaves it untouched. Finally it writes out to the path you specified. llm_localize_tool.cpphey it compiles! And it pretty much works, too. Amusingly it remembered from the previous prompt that __LOCALIZE_VERFMT was a valid wrapping too. Interesting. Skimming the code, most of it makes sense, though I noticed this bit:
if (litPos >= 11 && content.substr(litPos-11,11) == "__LOCALIZE(") already = true; if (litPos >= 21 && content.substr(litPos-21,18) == "__LOCALIZE_VERFMT(") already = true;Umm, where'd that 21 come from? Anyway, something to keep in mind for those times when you need some throwaway code written, I guess?
Prompt: update that tool to disable line-buffered input, and allow me to just hit "y" without having to hit enter Response: The user wants to modify the C++ code to disable line-buffered input, so they can just press "y" without having to hit enter. Right now, the code uses std::getline(), which requires Hit Enter. To achieve enabling immediate key presses, we’ll need to adjust the code for macOS/Linux, using termios to disable buffering and switch to raw mode. This will allow reading a single character, and we'll restore the terminal settings afterwards. Time to update the code! llm_localize_tool2.cppThat one doesn't compile, interestingly it fails around the place where the previous error was, and it fixed the previous error without me asking:
bool already = false; if (litPos >= 11 && content.substr(litPos - 11, 11) == "__LOCALIZE(") || (litPos >= 18 && content.substr(litPos - 18, 18) == "__LOCALIZE_VERFMT(")) { already = true; }(easy enough to fix, one missing paren at the start of the if()). But once I tweak that, it seems to work! Mostly. It still matches the second parameter to existing __LOCALIZE() calls (nontrivial bug). And it's missing an output flush for the prompt text (trivial bug). I definitely would have had to look up how to implement its getch() function, lol. Anyway...
void foo(double v, char buf[1024]) { int iv = (int)v; int a = 100 + iv; if (a < 100) a = 100; for (int b = a; b < 1024; b ++) { buf[b] = 1; // crash here } }(this is a manually-recreated code, the actual code had substantial differences). Assume buf points to a buffer that is valid and 1024 bytes long. what gives?
void foo(double v, char buf[1024]) { int iv = (int)v; int a = iv < 0 ? 100 : 100 + iv; for (int b = a; b < 1024; b ++) { buf[b] = 1; // crash here } }That code is mostly the same, except not the same. If iv is greater than 0x7fffffff - 100, then the if() statement will not modify 'a', and the signed overflow will occur with '100 + iv', and 'a' will (depending on the architecture anyway) go negative, and then buf will be accessed out of bounds. Sigh.
Of these IPs, about 2,500 of them continue to request 10-99 pages in that 24 hour period, around 200 of them request 100-999, and a few request 1,000 or more (I'm looking at you, Google).
Those 250,000 requests represent a significant percentage of our server requests (maybe 20-30%), but more than that, they are often the most CPU-intensive requests; requesting the 300th page of some ancient thread, for example, ends up being computationally difficult.
Without countermeasures, there's no way our server could keep up. Sigh.
Comment...
-------------------------------------------------------------------------------- Language Files Lines Blank Comment Code -------------------------------------------------------------------------------- PHP 11 3129 288 18 2823 CSS 1 440 30 0 410 JavaScript 1 43 2 0 41 -------------------------------------------------------------------------------- Total 13 3612 320 18 3274 --------------------------------------------------------------------------------I tried to keep things as compact as possible, but also tried not to overdo the design. Started on PHP 5.5 on one of our dev boxes but now have fired up a VM that has PHP 8.x. Some crazy changes to inter-type comparisons in PHP 8. Eeep. But not so bad I guess once you start ditching some of the old bad habits.
SELECT users.email AS email, (signed_up_at < DATE_SUB(NOW(), INTERVAL 1 DAY)) AS old, events.* FROM eventsignups INNER JOIN events ON events.event_id = eventsignups.event_id INNER JOIN users ON users.id = eventsignups.user_id WHERE eventsignups.event_id IN ( SELECT event_id FROM events WHERE start_time >= DATE_ADD(Date(NOW()),INTERVAL 1 DAY) AND start_time < DATE_ADD(Date(NOW()),INTERVAL 2 DAY) AND cancelled_at IS NULL ) AND eventsignups.cancelled_at IS NULL AND users.want_email_remind > 0 ORDER BY users.email;(and then some PHP steps through the list by email to find all of the events for that email address, see if any have 'old' set, etc). Oddly satisfying.
$nwin = 250; # I think the lottery picked about 250-something winners last year, the rest were golden tickets and such $nlot = 100000; # someone could quantify the margin of error based on this, with statistics you would oh look a bird for ($pid = 0; <>; ) { ($nt, $np) = split(/\s+/, s/,//r); ($nt > 0 and $np > 0 and not exists $wcnt{$nt}) or die "invalid input: $_\n"; $wbin{$pid} = $nt; $wcnt{$nt} = 0; push(@tk, ($pid++) x $nt) while ($np-- > 0); } printf("%d tickets for %d entrants, running %d lotteries for %d winners:\n", $tkcnt = @tk, $pid, $nlot, $nwin); for ($x = 0; $x < $nlot; $x++) { %in = { }; $in{$id = $tk[rand($tkcnt)]}++ == 0 and exists $wbin{$id} and $wcnt{$wbin{$id}}++ while (%in < $nwin); } printf("%d tickets: %.2f%% win\n", $_, $wcnt{$_} * 100.0 / $nlot) foreach (sort { $a <=> $b } keys %wcnt);Here is the most recent input:
512 1 512 256 15 3,840 128 55 7,040 64 139 8,896 32 215 6,880 16 296 4,736 8 594 4,752 4 963 3,852 2 1,538 3,076 1 2,077 2,077and here is the most output with that table:
45661 tickets for 5893 entrants, running 100000 lotteries for 250 winners: 1 tickets: 0.66% win 2 tickets: 1.29% win 4 tickets: 2.56% win 8 tickets: 5.08% win 16 tickets: 9.99% win 32 tickets: 18.98% win 64 tickets: 34.12% win 128 tickets: 56.51% win 256 tickets: 80.91% win 512 tickets: 96.24% winSo, Steve's odds as of this afternoon are about 0.66%, but that will almost certainly go down (there's still a month left of the lottery; it only opened yesterday). Interestingly, one entrant there has been turned down 8 times before -- they currently have a 96% chance of getting in. And those who have been turnwed down 6 times before are slightly more likely than not to get in.
#include <windows.h> int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prev, LPSTR cmd, int ns) { const int w = 32, h = 16; int pixels[w*h]; for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) pixels[x + y * w] = RGB(x * 256 / w, y * 256 / h, 0); // oops BGR but whatever HBITMAP bitmap = CreateBitmap(w, h, 1, 32, &pixels); HWND wnd = CreateWindowEx(0, "Edit", "test", WS_VISIBLE, 0, 0, 10, 10, GetDesktopWindow(), NULL, hInst, 0); HMENU menu = CreatePopupMenu(); InsertMenuA(menu, 0, MF_BYPOSITION|MF_STRING, 1, (char*)"this is a thing that will cause stretching to happen"); InsertMenuA(menu, 1, MF_BYPOSITION|MF_BITMAP, 2, (char*)bitmap); TrackPopupMenu(menu, TPM_NONOTIFY|TPM_RETURNCMD, 0, 0, 0, wnd, NULL); DestroyMenu(menu); DeleteObject(bitmap); DestroyWindow(wnd); return 0; }Windows XP, Windows 7, and WINE all display something about like this, which is expected: