{"id":13715613,"url":"https://github.com/Eelis/geordi","last_synced_at":"2025-05-07T04:30:54.858Z","repository":{"id":63573659,"uuid":"556657","full_name":"Eelis/geordi","owner":"Eelis","description":"IRC C++ eval bot","archived":false,"fork":false,"pushed_at":"2022-10-05T22:16:35.000Z","size":1979,"stargazers_count":183,"open_issues_count":2,"forks_count":37,"subscribers_count":17,"default_branch":"master","last_synced_at":"2024-11-14T03:34:32.764Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://www.eelis.net/geordi/","language":"Haskell","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Eelis.png","metadata":{"files":{"readme":"README.html","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-03-10T22:39:03.000Z","updated_at":"2024-01-13T23:50:00.000Z","dependencies_parsed_at":"2022-11-21T16:00:18.116Z","dependency_job_id":null,"html_url":"https://github.com/Eelis/geordi","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eelis%2Fgeordi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eelis%2Fgeordi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eelis%2Fgeordi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eelis%2Fgeordi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Eelis","download_url":"https://codeload.github.com/Eelis/geordi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252813702,"owners_count":21808374,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T00:01:01.138Z","updated_at":"2025-05-07T04:30:54.268Z","avatar_url":"https://github.com/Eelis.png","language":"Haskell","funding_links":[],"categories":["Haskell","Bots"],"sub_categories":["Self-hosted"],"readme":"\u003c!DOCTYPE html\u003e\n\u003chtml lang='en'\u003e\n  \u003chead\u003e\n    \u003ctitle\u003egeordi - C++ eval bot\u003c/title\u003e\n    \u003cmeta charset='UTF-8'/\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n\n    \u003cdiv style='text-align:center'\u003e\n      \u003ch1\u003egeordi - C++ eval bot\u003c/h1\u003e\n    \u003c/div\u003e\n\n    \u003chr/\u003e\u003ch2\u003eTable of Contents\u003c/h2\u003e\n\n    \u003col\u003e\n      \u003cli\u003e\u003ca href='#introduction'\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\n        \u003ca href='#using'\u003eUsing geordi\u003c/a\u003e\n        \u003col\u003e\n          \u003cli\u003e\u003ca href='#syntax'\u003eRequest syntax\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#flags'\u003eFlags\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#operational'\u003eOperational notes\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#prelude'\u003ePrelude\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#rules'\u003eRules\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#faq'\u003eFAQ\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#clutter'\u003eMinimizing clutter\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#edit'\u003eEdit commands\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#examples'\u003eExample snippets\u003c/a\u003e\u003c/li\u003e\n        \u003c/ol\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003ca href='#setup'\u003eSetting up a geordi\u003c/a\u003e\n        \u003col\u003e\n          \u003cli\u003e\u003ca href='#download'\u003eDownload\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#install'\u003eInstall\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#run'\u003eRun\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#nickserv'\u003eNickServ identification\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#nickless'\u003eNickless requests\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#autoreconnect'\u003eAuto-reconnect\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#multiplenetworks'\u003eConnecting to multiple networks\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href='#censor'\u003eCensoring phrases\u003c/a\u003e\u003c/li\u003e\n        \u003c/ol\u003e\n      \u003c/li\u003e\n    \u003c/ol\u003e\n\n    \u003chr/\u003e\u003ch2 id='introduction'\u003e1.\u0026emsp;Introduction\u003c/h2\u003e\n\n    \u003cp\u003eGeordi is an IRC bot program that compiles and runs C++ code snippets. It is intended to be used as a demonstration tool when teaching or discussing C++ on IRC.\u003c/p\u003e\n\n    \u003cp\u003eGeordi is public domain, free software.\u003c/p\u003e\n\n    \u003chr/\u003e\u003ch2 id='using'\u003e2.\u0026emsp;Using geordi\u003c/h2\u003e\n\n    \u003chr/\u003e\u003ch3 id='syntax'\u003e2.1\u0026emsp;Request syntax\u003c/h3\u003e\n\n    \u003cp\u003eGeordi has 3 main request syntaxes, demonstrated by example below.\u003c/p\u003e\n\n    \u003col\u003e\n      \u003cli\u003e\u003ch4\u003ePrinting things\u003c/h4\u003e\n        \u003cp\u003eTo print things, stream things to geordi as if he were std::cout:\u003c/p\u003e\n        \u003ccode\u003e\n          \u0026lt;Eelis\u003e geordi \u0026lt;\u0026lt; 3 * 2 \u0026lt;\u0026lt; \" foo \" \u0026lt;\u0026lt; (9 \u003e 4)\u003cbr/\u003e\n          \u0026lt;geordi\u003e 6 foo true\n        \u003c/code\u003e\n        \u003cp\u003eTo accommodate the use of nick completion, \"\u003ckbd\u003egeordi\u003c/kbd\u003e\" may be followed by a colon or comma.\u003c/p\u003e\n\n        \u003cp\u003eThe code may be followed by a semicolon followed by more code, which is then placed \u003cem\u003ebefore\u003c/em\u003e the definition of main (where the printing statement is put):\u003c/p\u003e\n\n        \u003ccode\u003e\n          \u0026lt;Eelis\u003e geordi \u0026lt;\u0026lt; f(3); int f(int x) { return x; }\u003cbr/\u003e\n          \u0026lt;geordi\u003e 3\n        \u003c/code\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003ch4\u003eStatement blocks\u003c/h4\u003e\n        \u003cp\u003eTo execute a block of statements, say for example:\u003c/p\u003e\n        \u003ccode\u003e\n          \u0026lt;Eelis\u003e geordi { string s = \"foo\"; cout \u0026lt;\u0026lt; s; }\u003cbr/\u003e\n          \u0026lt;geordi\u003e foo\n        \u003c/code\u003e\n        \u003cp\u003eHere, too, \"\u003ckbd\u003egeordi\u003c/kbd\u003e\" may be followed by a colon or comma.\u003c/p\u003e\n\n        \u003cp\u003eThe closing brace may be followed by more code, which is then placed \u003cem\u003ebefore\u003c/em\u003e the definition of main (where the statement block is put):\u003c/p\u003e\n\n        \u003ccode\u003e\n          \u0026lt;Eelis\u003e geordi { cout \u0026lt;\u0026lt; f(3); } int f(int x) { return x; }\u003cbr/\u003e\n          \u0026lt;geordi\u003e 3\n        \u003c/code\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003ch4\u003ePrograms\u003c/h4\u003e\n        \u003cp\u003eTo execute programs, say for example:\u003c/p\u003e\n        \u003ccode\u003e\n          \u0026lt;Eelis\u003e geordi: void f(int x) { cout \u0026lt;\u0026lt; x; } int main() { f(3); }\u003cbr/\u003e\n          \u0026lt;geordi\u003e 3\n        \u003c/code\u003e\n        \u003cp\u003eHere, a colon or comma after \"\u003ckbd\u003egeordi\u003c/kbd\u003e\" is required if the next non-space character is a letter, an asterisk, a slash, or a single quote.\u003c/p\u003e\n      \u003c/li\u003e\n    \u003c/ol\u003e\n\n    \u003ch4\u003eLine breaks\u003c/h4\u003e\n    \u003cp\u003eWhereas in ordinary C++ backslashes (outside of character/string literals) splice physical source lines to form a logical source line, in geordi snippets this behavior is inverted; backslashes split the physical source line into logical source lines.\u003c/p\u003e\n\n    \u003ch4\u003eTranslation unit breaks\u003c/h4\u003e\n    \u003cp\u003eTwo consecutive newlines (i.e. \\\\) split the snippet into multiple translation units.\u003c/p\u003e\n\n    \u003chr/\u003e\u003ch3 id='flags'\u003e2.2\u0026emsp;Flags\u003c/h3\u003e\n\n    \u003cp\u003eIn all three syntaxes described in the previous section, flags may be passed before any code. For the first two syntaxes, that means before \u003ckbd\u003e\u0026lt;\u0026lt;\u003c/kbd\u003e and \u003ckbd\u003e{\u003c/kbd\u003e, respectively.\u003c/p\u003e\n\n    \u003cdl\u003e\n      \u003cdt\u003e\u003ckbd\u003e-c\u003c/kbd\u003e / \u003ckbd\u003e--compile-only\u003c/kbd\u003e\u003c/dt\u003e\n      \u003cdd\u003e\n        \u003cp\u003eOnly compile; do not assemble, link, or run.\u003c/p\u003e\n        \u003cp\u003e\n          \u003ccode\u003e\n            \u0026lt;Eelis\u003e geordi -c void f (string \u0026amp; x) { reverse(x.begin(), x.end()); }\u003cbr/\u003e\n            \u0026lt;geordi\u003e Success\n          \u003c/code\u003e\n        \u003c/p\u003e\n        \u003cp\u003eThis better expresses your intent in demonstrations and produces a faster and more appropriate response from geordi. With \u003ckbd\u003e-c\u003c/kbd\u003e, a \u003ccode\u003emain\u003c/code\u003e function is optional.\u003c/p\u003e\n      \u003c/dd\u003e\n\n      \u003cdt\u003e\u003ckbd\u003e-w\u003c/kbd\u003e / \u003ckbd\u003e--no-warn\u003c/kbd\u003e\u003c/dt\u003e\n      \u003cdd\u003e\u003cp\u003eSuppress warnings.\u003c/p\u003e\u003c/dd\u003e\n\n      \u003cdt\u003e\u003ckbd\u003e--no-using-std\u003c/kbd\u003e\u003c/dt\u003e\n      \u003cdd\u003e\u003cp\u003eOmits the otherwise implicitly added \"\u003ccode\u003eusing namespace std;\u003c/code\u003e\".\u003c/p\u003e\u003c/dd\u003e\n\n      \u003cdt\u003e\u003ckbd\u003e-h\u003c/kbd\u003e / \u003ckbd\u003e--help\u003c/kbd\u003e\u003c/dt\u003e\n      \u003cdd\u003e\u003cp\u003eShows URL for this manual.\u003c/p\u003e\u003c/dd\u003e\n\n      \u003cdt\u003e\u003ckbd\u003e-v\u003c/kbd\u003e / \u003ckbd\u003e--version\u003c/kbd\u003e\u003c/dt\u003e\n      \u003cdd\u003e\u003cp\u003eShows the compiler version.\u003c/p\u003e\u003c/dd\u003e\n\n      \u003cdt\u003e\u003ckbd\u003e--make-type \u0026lt;type description\u0026gt;\u003c/kbd\u003e\u003c/dt\u003e\n      \u003cdd\u003e\n        \u003cp\u003eShows the type described in C++ syntax.\u003c/p\u003e\n        \u003cp\u003e\n          \u003ccode\u003e\n            \u0026lt;Eelis\u003e geordi --make-type pointer to function returning a reference to an array of three pointers to functions taking integers and returning doubles\u003cbr/\u003e\n            \u0026lt;geordi\u003e double(*(\u0026amp;(*)())[3])(int)\n          \u003c/code\u003e\n        \u003c/p\u003e\n      \u003c/dd\u003e\n\n      \u003cdt\u003e\u003ckbd\u003e--precedence \u0026lt;expression\u0026gt;\u003c/kbd\u003e\u003c/dt\u003e\n      \u003cdd\u003e\n        \u003cp\u003eShows the given expression with added parentheses to illustrate precedence and associativity of operators.\u003c/p\u003e\n        \u003cp\u003e\n          \u003ccode\u003e\n            \u0026lt;Eelis\u003e geordi --precedence a + b - c ? d : e+++f\u003cbr/\u003e\n            \u0026lt;geordi\u003e ((a + b) - c) ? d : ((e++) + f)\n          \u003c/code\u003e\n        \u003c/p\u003e\n      \u003c/dd\u003e\n\n      \u003cdt\u003e\u003ckbd\u003e--resume\u003c/kbd\u003e / \u003ckbd\u003e-r\u003c/kbd\u003e\u003c/dt\u003e\n      \u003cdd\u003e\n        \u003cp\u003eAdds the previous snippet's code, except for its main function (if any).\u003c/p\u003e\n        \u003cp\u003e\n          \u003ccode\u003e\n          \u0026lt;Eelis\u003e geordi \u0026lt;\u0026lt; f(); int f() { return 3; }\u003cbr/\u003e\n          \u0026lt;geordi\u003e 3\u003cbr/\u003e\n          \u0026lt;Eelis\u003e geordi -r \u0026lt;\u0026lt; f() + g(); double g() { return 1.2; }\u003cbr/\u003e\n          \u0026lt;geordi\u003e 4.2\u003cbr/\u003e\n          \u0026lt;Eelis\u003e geordi, show\u003cbr/\u003e\n          \u0026lt;geordi\u003e \u0026lt;\u0026lt; f() + g(); int f() { return 3; } double g() { return 1.2; }\n          \u003c/code\u003e\n        \u003c/p\u003e\n      \u003c/dd\u003e\n\n      \u003cdt\u003e\u003ckbd\u003e--clang\u003c/kbd\u003e\u003c/dt\u003e\n      \u003cdd\u003e\n        \u003cp\u003eUse Clang instead of GCC.\u003c/p\u003e\n      \u003c/dd\u003e\n\n      \u003cdt\u003e\u003ckbd\u003e--1998\u003c/kbd\u003e / \u003ckbd\u003e--2003\u003c/kbd\u003e / \u003ckbd\u003e--2011\u003c/kbd\u003e / \u003ckbd\u003e--2014\u003c/kbd\u003e\u003c/dt\u003e\n      \u003cdd\u003e\n      \u003cp\u003eUse version of the C++ standard published in the specified year.\u003c/p\u003e\n      \u003cp\u003eIf none is specified, geordi will encourage the compiler to approximate what the \u003cem\u003enext\u003c/em\u003e C++ standard might look like.\u003c/p\u003e\n      \u003c/dd\u003e\n\n    \u003c/dl\u003e\n\n    \u003chr/\u003e\u003ch3\u003e\u003ca id='operational'\u003e2.3\u0026emsp;Operational notes\u003c/a\u003e\u003c/h3\u003e\n    \u003cul\u003e\n      \u003cli\u003eRegardless of command syntax, geordi always implicitly #includes the \u003ca href='#prelude'\u003eprelude\u003c/a\u003e.\u003c/li\u003e\n      \u003cli\u003eWhen compilation fails, geordi shows the first error or warning only.\u003c/li\u003e\n      \u003cli\u003eWhen compilation succeeds and \u003ckbd\u003e-c\u003c/kbd\u003e was not specified, only the first 300 characters of the first line of program output are shown.\u003c/li\u003e\n      \u003cli\u003eStdout and stderr are merged.\u003c/li\u003e\n      \u003cli\u003eStdin is closed.\u003c/li\u003e\n      \u003cli\u003e__FILE__ can be used for file I/O demonstrations.\u003c/li\u003e\n      \u003cli\u003eFlags passed to the compiler and linker are listed in \u003ca href='http://github.com/Eelis/geordi/blob/master/compile-config'\u003ecompile-config\u003c/a\u003e.\u003c/li\u003e\n      \u003cli\u003eMost system calls are disabled.\u003c/li\u003e\n      \u003cli\u003eNon-printable characters are filtered out.\u003c/li\u003e\n      \u003cli\u003eThere are no headers to #include (except for the implicitly included \u003ca href='#prelude'\u003eprelude\u003c/a\u003e).\u003c/li\u003e\n    \u003c/ul\u003e\n\n    \u003chr/\u003e\u003ch3 id='prelude'\u003e2.4\u0026emsp;Prelude\u003c/h3\u003e\n\n    \u003cp\u003eThe implicitly included \u003ca href=\"http://github.com/Eelis/geordi/blob/master/prelude\"\u003eprelude\u003c/a\u003e includes all standard library headers, some namespace usings and aliases, and assorted miscellaneous utilities.\u003c/p\u003e\n\n    \u003cp\u003eDescriptions of a few selected utilities follow.\u003c/p\u003e\n\n    \u003ch4\u003e2.4.1\u0026emsp;Range and tuple printing\u003c/h4\u003e\n    \u003cp\u003eRanges (such as containers) and tuples have been made streamable:\u003c/p\u003e\n    \u003cpre\u003e   \u0026lt;Eelis\u003e geordi { vector\u0026lt;int\u003e v { 3, 5, 9, 4, 1 }; cout \u0026lt;\u0026lt; v; }\n   \u0026lt;geordi\u003e [3, 5, 9, 4, 1]\u003c/pre\u003e\n    \u003cp\u003eSee \u003ca href='http://github.com/Eelis/geordi/blob/master/prelude/more_ostreaming.hpp'\u003emore_ostreaming.hpp\u003c/a\u003e for details.\u003c/p\u003e\n\n    \u003ch4\u003e2.4.2\u0026emsp;Displaying types\u003c/h4\u003e\n\n    \u003cp\u003eStreaming \u003ccode\u003eTYPE\u0026lt;\u003c/code\u003e\u003ci\u003eT\u003c/i\u003e\u003ccode\u003e\u0026gt;\u003c/code\u003e prints the type \u003ci\u003eT\u003c/i\u003e.\u003c/p\u003e\n    \u003cp\u003e\u003ccode\u003eTYPE(\u003c/code\u003e\u003ci\u003ee\u003c/i\u003e\u003ccode\u003e)\u003c/code\u003e yields a string representation in C++ syntax of the static type of the expression \u003ci\u003ee\u003c/i\u003e.\u003c/p\u003e\n    \u003cp\u003e\u003ccode\u003eTYPE_DESC\u003c/code\u003e works the same, but yields string representations in verbose English.\u003c/p\u003e\n    \u003ch4\u003eExamples:\u003c/h4\u003e\n    \u003cpre\u003e   \u0026lt;Eelis\u003e geordi \u0026lt;\u0026lt; TYPE(\u0026amp;system)\n   \u0026lt;geordi\u003e int (*)(const char*)\u003c/pre\u003e\n    \u003cpre\u003e   \u0026lt;Eelis\u003e geordi \u0026lt;\u0026lt; TYPE_DESC\u0026lt; int(\u0026amp;(*)())[5] \u0026gt;\n   \u0026lt;geordi\u003e pointer to a function taking no arguments and\n     returning a reference to an array of 5 integers\u003c/pre\u003e\n    \u003cp\u003eSee \u003ca href=\"http://github.com/Eelis/geordi/blob/master/prelude/type_strings.hpp\"\u003etype_strings.hpp\u003c/a\u003e for details.\u003c/p\u003e\n\n    \u003ch4\u003e2.4.3\u0026emsp;Tracked objects\u003c/h4\u003e\n    \u003cp\u003e\u003ccode\u003etracked::B\u003c/code\u003e is a simple class whose constructors, destructor, assignment operator, etc. print a short message when called. Objects of type \u003ccode\u003etracked::B\u003c/code\u003e are also kept track of in a central registry, and leaks are reported if the program exits while \u003ccode\u003etracked::B\u003c/code\u003e objects are still around. For example:\u003c/p\u003e\n    \u003cpre\u003e   \u0026lt;Eelis\u003e geordi { using tracked::B; B x, * y = new B(x);\n     swap(x, *y); y-\u003ef(); }\n   \u0026lt;geordi\u003e B0* new(B) B1*(B0) B0=\u003eB2* B1=\u003eB0 B2=\u003eB1 B2~\n     B1.f() B0~ leaked: B1. Aborted\u003c/pre\u003e\n    \u003cp\u003eSee \u003ca href=\"http://github.com/Eelis/geordi/blob/master/prelude/tracked.hpp\"\u003etracked.hpp\u003c/a\u003e for a full list of tracked operations and additional tracked classes.\u003c/p\u003e\n\n    \u003ch4\u003e2.4.4\u0026emsp;Comma-delimited output\u003c/h4\u003e\n    \u003cp\u003eGeordi overloads the comma-operator to make it easy to print comma-delimited values:\u003c/p\u003e\n    \u003cpre\u003e   \u0026lt;Eelis\u003e geordi \u0026lt;\u0026lt; 3, \"oi\", sin(3.9)\n   \u0026lt;geordi\u003e 3, oi, -0.687766\u003c/pre\u003e\n\n    \u003ch4\u003e2.4.5\u0026emsp;Base-2 (binary) integer output.\u003c/h4\u003e\n    \u003cp\u003eGeordi adds \u003ccode\u003ebin\u003c/code\u003e to the \u003ccode\u003estd::hex\u003c/code\u003e/\u003ccode\u003estd::oct\u003c/code\u003e/\u003ccode\u003estd::dec\u003c/code\u003e family of I/O manipulators, with the semantics you would expect:\u003c/p\u003e\n    \u003cpre\u003e   \u0026lt;Eelis\u003e geordi \u0026lt;\u0026lt; showbase \u0026lt;\u0026lt; bin \u0026lt;\u0026lt; 38\n   \u0026lt;geordi\u003e 0b100110\u003c/pre\u003e\n    \u003cp\u003eSee \u003ca href='http://github.com/Eelis/geordi/blob/master/prelude/bin_iomanip.hpp'\u003ebin_iomanip.hpp\u003c/a\u003e for details.\u003c/p\u003e\n\n    \u003ch4\u003e2.4.6\u0026emsp;Labeled value display\u003c/h4\u003e\n    \u003cpre\u003e   \u0026lt;Eelis\u003e geordi { int x = 45, y = x * x; cout \u0026lt;\u0026lt; SHOW(x), SHOW(y),\n     SHOW(y - x); }\n   \u0026lt;geordi\u003e x = 45, y = 2025, y - x = 1980\u003c/pre\u003e\n\n    \u003ch4\u003e2.4.7\u0026emsp;[Begin, end)-range shorthand\u003c/h4\u003e\n    \u003cp\u003eThe RANGE macro expands \u003ccode\u003eRANGE(r)\u003c/code\u003e to\u0026emsp;\u003ccode\u003e(boost::begin(r)), (boost::end(r))\u003c/code\u003e\u0026emsp;, which saves some typing for common cases.\u003c/p\u003e\n    \u003cpre\u003e   \u0026lt;Eelis\u003e geordi { int a [40]; fill(RANGE(a), 6); cout \u0026lt;\u0026lt; a[31]; }\n   \u0026lt;geordi\u003e 6\u003c/pre\u003e\n    \u003cp\u003e(See \u003ca href='http://www.boost.org/libs/range/doc/range.html'\u003eBoost.Range\u003c/a\u003e.)\u003c/p\u003e\n\n    \u003ch4\u003e2.4.8\u0026emsp;\u003ccode\u003eBARK\u003c/code\u003e\u003c/h4\u003e\n    \u003cp\u003e\u003ccode\u003eBARK\u003c/code\u003e prints the name and signature of the function in which it appears:\u003c/p\u003e\n    \u003cpre\u003e   \u0026lt;Eelis\u003e geordi { f(3.2); f('x'); } void f(int) { BARK; } void f(double) { BARK; }\n   \u0026lt;geordi\u003e f(double) f(int)\u003c/pre\u003e\n\n    \u003chr/\u003e\u003ch3 id='rules'\u003e2.5\u0026emsp;Rules\u003c/h3\u003e\n    \u003col\u003e\n      \u003cli\u003e\u003cb\u003eDon't spam (i)\u003c/b\u003e\n        \u003cp\u003eOnly pass geordi snippets when you're trying to demonstrate something to somebody (except in #geordi, where you are free to experiment as much as you like).\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eDon't spam (ii)\u003c/b\u003e\n        \u003cp\u003eIf you make a mistake in your snippet when trying to demonstrate something, give yourself at most one more attempt to get it right. If you fail to get your snippet right in your second attempt, then /join #geordi, work out your snippet there until it works, and then show it in the other channel.\u003c/p\u003e\n      \u003c/li\u003e\n    \u003c/ol\u003e\n\n    \u003chr/\u003e\u003ch3 id='faq'\u003e2.6\u0026emsp;FAQ\u003c/h3\u003e\n\n    \u003col\u003e\n      \u003cli\u003e\u003cb\u003eHow can geordi safely allow execution of arbitrary code?\u003c/b\u003e\n        \u003cp\u003eGeordi uses Docker, seccomp, and ordinary resource limits and permissions\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eWhat language is geordi written in?\u003c/b\u003e\n        \u003cp\u003e\u003ca href='http://www.haskell.org/'\u003eHaskell\u003c/a\u003e.\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eCan you make your Freenode geordi join channel #foo?\u003c/b\u003e\n        \u003cp\u003eFirst, you can always run your own geordi instance, see \u003ca href='#download'\u003eDownload\u003c/a\u003e.\u003c/p\u003e\n        \u003cp\u003eThat said, if #foo is a serious programming channel on Freenode that is not just a place to hang out, \u003ckbd\u003e/join #geordi\u003c/kbd\u003e and talk to Eelis.\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eWhere can I play around with geordi?\u003c/b\u003e\n        \u003cp\u003e\u003ckbd\u003e/join #geordi\u003c/kbd\u003e. Please, please, do not spam other channels!\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eIs geordi suitable for small benchmarks?\u003c/b\u003e\n        \u003cp\u003eNO! Geordi uses various costly compiler flags and runtime aids to help diagnose ill-behaved code, making any kind of performance measure meaningless.\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eI have another question/suggestion.\u003c/b\u003e\n        \u003cp\u003eOn \u003ca href='http://freenode.net/irc_servers.shtml'\u003eFreenode\u003c/a\u003e, \u003ckbd\u003e/join #geordi\u003c/kbd\u003e and/or \u003ckbd\u003e/msg Eelis\u003c/kbd\u003e. Alternatively, mail to \u003ckbd\u003e\u0026lt;name-of-this-software\u003e@contacts.eelis.net\u003c/kbd\u003e .\u003c/p\u003e\n      \u003c/li\u003e\n    \u003c/ol\u003e\n\n    \u003chr/\u003e\u003ch3 id='clutter'\u003e2.7\u0026emsp;Minimizing clutter\u003c/h3\u003e\n    \u003cp\u003eNon-syntax-highlighted code with multiple statements all on a single line quickly becomes hard to read. Here are some tips to shave a few tokens off your snippets:\u003c/p\u003e\n    \u003col\u003e\n      \u003cli\u003e\n        \u003cp\u003eUse the \u003ca href='#syntax'\u003eshorthand syntaxes\u003c/a\u003e whenever possible. When you must use the \"\u003ccode\u003egeordi: ...\u003c/code\u003e\" syntax, don't list \u003ccode\u003emain\u003c/code\u003e's parameters if you don't need them. Finally, \u003ccode\u003ereturn 0;\u003c/code\u003e is implicit for \u003ccode\u003emain\u003c/code\u003e.\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003eUse the \u003ca href='#prelude'\u003eprelude utilities\u003c/a\u003e when appropriate.\u003c/li\u003e\n      \u003cli\u003e\u003cp\u003eDon't use \u003ccode\u003estd::\u003c/code\u003e qualification; namespace \u003ccode\u003estd\u003c/code\u003e has been \u003ccode\u003eusing\u003c/code\u003e'd. Yes, this is normally considered poor style, but our unique spatial constraints justify its use for geordi.\u003c/p\u003e\u003c/li\u003e\n      \u003cli\u003e\u003cp\u003eDon't bother with \u003ccode\u003eendl\u003c/code\u003e or \u003ccode\u003eflush\u003c/code\u003e; geordi only outputs the first line anyway, and cout is flushed automatically at the end of the program.\u003c/p\u003e\u003c/li\u003e\n      \u003cli\u003e\u003cp\u003eUse \u003ccode\u003estruct\u003c/code\u003e instead of \u003ccode\u003eclass\u003c/code\u003e to avoid having to type \u003ccode\u003epublic:\u003c/code\u003e for bases and members.\u003c/p\u003e\u003c/li\u003e\n    \u003c/ol\u003e\n\n    \u003chr/\u003e\u003ch3 id='edit'\u003e2.8\u0026emsp;Edit commands\u003c/h3\u003e\n\n    \u003cp\u003eGeordi provides a set of editing commands that modify and then retry the last snippet.\u003c/p\u003e\n\n    \u003ch4\u003e2.8.1\u0026emsp;Syntax:\u003c/h4\u003e\n\n    \u003cpre\u003e    command = (insert | append | prepend | erase | replace | move | swap | use | make | \"fix\")*\n\n    insert = (\"insert\" | \"add\") (... positions* | wrapping (\"around\" substrs*)*)\n    append = \"append\" ... [positions*]\n    prepend = \"prepend\" (options | ...) [positions*]\n    erase = (\"erase\" | \"remove\" | \"delete\" | \"cut\" | \"omit\" | \"kill\") (substrs | options)*\n    replace = \"replace\" (substrs* (\"with\" | \"by\") ... | options (\"with\" | \"by\") options)*\n    move = \"move\" (substrs \"to\" position)*\n    swap = \"swap\" (substr \"and\" substr)*\n\n    use = \"use\" (options | ... [relative])*\n    make = \"make\" declarator-id* type-description\n\n    wrapping = ... \"and\" ... | \"parentheses\" | \"parens\" | \"braces\" | \"curlies\"\n      | (\"square\" | \"angle\" | \"curly\" | \"round\") \"brackets\"\n      | (\"single\" | \"double\") \"quotes\"\n\n    position = limit | befaft (substr [relative])\n    positions = in-clause | befaft substrs\n\n    substr = \"everything\" | [ordinal] (named-entity | ...)\n    substrs = ((\"everything\" | rankeds (named-entity | ...)) [relative])*\n\n    befaft = \"before\" | \"after\"\n    limit = \"begin\" | \"front\" | \"end\" | \"back\"\n    ordinal = \"first\" | (\"second\" | \"third\" | etc) [\"last\"] | \"last\"\n    rankeds = \"all\" [(\"except\" | \"but\") ordinal*] | [\"each\" | \"every\" | \"any\" | ordinal*]\n\n    in-clause = \"in\" ([ordinal] (named-entity | declarator-id) [relative])*\n    named-entity = (\"declaration\" | \"body\") \"of\" declarator-id\n    relative = between | befaft [ranked] substr | in-clause\n    between = \"between\" (bound \"and\" relative-bound | ordinal \"and\" ordinal ...)\n    range = ([[\"everything\"] \"from\"] bound | \"everything\") (\"till\" | \"until\") relative-bound\n    bound = limit | [befaft] substr\n    relative-bound = limit | [befaft] substr [relative]\u003c/pre\u003e\n\n    \u003cp\u003eEllipsis denote simple verbatim strings without escaping, quoting, globbing, etc. The notation \u003ccode\u003e\u0026nbsp;x*\u0026nbsp;\u003c/code\u003e stands for \u003ccode\u003e\u0026nbsp;x [\"and\" x*]\u0026nbsp;\u003c/code\u003e.\u003c/p\u003e\n    \u003c!-- Todo: We /do/ have quoting, with backticks. Also missing above: EraseAround. It might also be worthwhile to note that declarator-id's are matched identically, so if one has X::f in the source, one needs to say \"X::f\". --\u003e\n\n    \u003ch4\u003e2.8.2\u0026emsp;Examples:\u003c/h4\u003e\n\n    \u003cp\u003e\u003ccode\u003e\n      \u0026lt;Johnny\u003e geordi: string s = \"foo\"; cin \u0026lt;\u0026lt; s; }\u003cbr/\u003e\n      \u0026lt;geordi\u003e error: expected constructor, destructor, or type conversion before '\u0026lt;\u0026lt;' token\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: prepend { and replace cin with cout\u003cbr/\u003e\n      \u0026lt;geordi\u003e foo\u003cbr/\u003e\n      \u0026lt;Johnny\u003e Ah, I see!\u003cbr/\u003e\n    \u003c/code\u003e\u003c/p\u003e\n\n    \u003cp\u003eFixing longer snippets this way is easier and more to the point than copy\u0026amp;paste-ing.\u003c/p\u003e\n\n    \u003cp\u003eThe last snippet can be edited and re-edited indefinitely. Use the \"\u003ccode\u003eshow\u003c/code\u003e\" command to show the snippet in its current form:\u003c/p\u003e\n    \u003cp\u003e\u003ccode\u003e\n      \u0026lt;Johnny\u003e So, what does the snippet look like with those changes?\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: show\u003cbr/\u003e\n      \u0026lt;geordi\u003e {string s = \"foo\"; cout \u0026lt;\u0026lt; s;}\u003cbr/\u003e\n      \u0026lt;Johnny\u003e Ah, I see!\u003cbr/\u003e\n    \u003c/code\u003e\u003c/p\u003e\n\n    \u003cp\u003eMore examples:\u003c/p\u003e\n\n    \u003cp\u003e\u003ccode\u003e\n      geordi, wrap parentheses around everything and erase second semicolon\u003cbr/\u003e\n      geordi, insert \u0026lt;\u0026lt; flush before second last \u0026lt;\u0026lt; and move int i; to before int j = 3 * i;\u003cbr/\u003e\n      geordi, move everything after int main() to front and erase int main()\u003cbr/\u003e\n    \u003c/code\u003e\u003c/p\u003e\n\n    \u003ch4\u003e2.8.3\u0026emsp;The \"use\" edit command\u003c/h4\u003e\n\n    \u003cp\u003eFor each given string, the \"use\" edit command searches the previous snippet for the substring that most resembles the given string, and replaces the former with the latter. This can be used to succinctly fix typos or make small adjustments:\u003c/p\u003e\n\n    \u003cp\u003e\u003ccode\u003e\n      \u0026lt;Johnny\u003e geordi: -c class X { void f() }; void main() { statc X x(); x-\u003ef(); }\u003cbr/\u003e\n      \u0026lt;geordi\u003e error: expected ';' before '}' token\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: use void f(); }\u003cbr/\u003e\n      \u0026lt;geordi\u003e error: '::main' must return 'int'\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: use int main\u003cbr/\u003e\n      \u0026lt;geordi\u003e error: 'statc' was not declared in this scope\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: use static\u003cbr/\u003e\n      \u0026lt;geordi\u003e error: 'static' specified invalid for function 'x' declared out of global scope\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: use X x;\u003cbr/\u003e\n      \u0026lt;geordi\u003e error: base operand of '-\u003e' has non-pointer type 'X'\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: use x.f\u003cbr/\u003e\n      \u0026lt;geordi\u003e error: 'void X::f()' is private\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: use struct\u003cbr/\u003e\n      \u0026lt;geordi\u003e Success\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: show\u003cbr/\u003e\n      \u0026lt;geordi\u003e -c struct X { void f(); }; int main() { static X x; x.f(); }\n    \u003c/code\u003e\u003c/p\u003e\n\n    \u003cp\u003eAlternatively, these edits could have been specified with a single command:\u003c/p\u003e\n\n    \u003cp\u003e\u003ccode\u003e\u0026lt;Eelis\u003e geordi: use void f(); } and int main and static and X x; and x.f and struct\u003c/code\u003e\u003c/p\u003e\n\n    \u003cp\u003eGeordi and the other users in the channel cannot read your mind, and the heuristics they use to determine which substring to replace are only \"best effort\". To prevent confusion (among geordi and the other users alike), it is therefore recommended to keep the modifications-to-context ratio of patterns low by being liberal with context, by not trying to simultaneously make multiple changes in a short code fragment, and by not trying to replace partial tokens (the heuristics have a strong bias in favour of whole-token replacements).\u003c/p\u003e\n\n    \u003ch4\u003e2.8.4\u0026emsp;The \"fix\" edit command\u003c/h4\u003e\n\n    \u003cp\u003eIf geordi prints \"\u003ccode\u003e(fix known)\u003c/code\u003e\" at the end of an error, it means the compiler told geordi how the error might be fixed, and you can ask geordi to apply that fix:\u003c/p\u003e\n\n    \u003cp\u003e\u003ccode\u003e\n      \u0026lt;Eelis\u003e geordi: struct A {} int main(){ cout \u0026lt;\u0026lt; sizeof(A); }\u003cbr/\u003e\n      \u0026lt;geordi\u003e error: expected ';' after struct definition (fix known)\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: fix\u003cbr/\u003e\n      \u0026lt;geordi\u003e 1\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi: show\u003cbr/\u003e\n      \u0026lt;geordi\u003e struct A {}; int main(){ cout \u0026lt;\u0026lt; sizeof(A); }\u003cbr/\u003e\n    \u003c/code\u003e\u003c/p\u003e\n\n    \u003ch4\u003e2.8.5\u0026emsp;The \"make\" edit command\u003c/h4\u003e\n\n    \u003cp\u003eThe \"make\" edit command changes properties (including type) of declarations:\u003c/p\u003e\n\n    \u003cp\u003e\u003ccode\u003e\n      \u0026lt;Eelis\u003e geordi -c struct X { int i; virtual void f(X * p) const = 0; };\u003cbr/\u003e\n      \u0026lt;geordi\u003e Success\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi, make f nonconst inline nonvirtual and make i a static reference to long and make p a const pointer to const\u003cbr/\u003e\n      \u0026lt;geordi\u003e Success\u003cbr/\u003e\n      \u0026lt;Eelis\u003e geordi, show\u003cbr/\u003e\n      \u0026lt;geordi\u003e -c struct X { long static int \u0026amp; i; inline void f(const X *const p) ; };\u003cbr/\u003e\n    \u003c/code\u003e\u003c/p\u003e\n\n    \u003cp\u003eProperty descriptions generally follow the same syntax as with \u003ckbd\u003e--make-type\u003c/kbd\u003e, with some additions.\u003c/p\u003e\n\n    \u003cp\u003e\"make\" edit commands currently have a number of severe limitations:\u003c/p\u003e\n    \u003cul\u003e\n      \u003cli\u003eThey do not work for snippets containing preprocessor directives.\u003c/li\u003e\n      \u003cli\u003eGeordi cannot parse use of certain macros (e.g. \"\u003ccode\u003eBOOST_FOREACH(int \u0026amp; i)\u003c/code\u003e\", because it looks like a function call, and \"\u003ccode\u003eint \u0026amp; i\u003c/code\u003e\" is not a valid function argument).\u003c/li\u003e\n      \u003cli\u003eAs an instance of the previous point, \"make\" edit commands do not work for snippets that use \u003ckbd\u003e--terse\u003c/kbd\u003e.\u003c/li\u003e\n      \u003cli\u003eThe given declarator-id(s) must exactly match the one in the intended declaration(s). No lookup of any kind is done.\u003c/li\u003e\n      \u003cli\u003eAs a consequence of the previous point, overloaded functions cannot be distinguished.\u003c/li\u003e\n      \u003cli\u003eOne cannot change a function's return type without also specifying its parameters.\u003c/li\u003e\n      \u003cli\u003eMember function definitions cannot be made pure, because geordi isn't smart enough to put separate definitions outside the class definition.\u003c/li\u003e\n      \u003cli\u003eThe \"\u003ckbd\u003enonconst\u003c/kbd\u003e\"/\"\u003ckbd\u003enonvolatile\u003c/kbd\u003e\" properties are only supported at top-level, so \"\u003ckbd\u003emake x a pointer to nonconst\u003c/kbd\u003e\" doesn't work.\u003c/li\u003e\n      \u003cli\u003eLocally ambiguous constructs are always parsed as declarations whenever possible. Hence, given \"\u003ccode\u003eint x; f(x);\u003c/code\u003e\", the command \"\u003ckbd\u003emake x const\u003c/kbd\u003e\" will produce \"\u003ccode\u003econst int x; const f(x);\u003c/code\u003e\" (because \"\u003ccode\u003ef(x);\u003c/code\u003e\" is parsed as a declaration of a variable named \u003ccode\u003ex\u003c/code\u003e).\u003c/li\u003e\n    \u003c/ul\u003e\n\n    \u003chr/\u003e\u003ch2 id='examples'\u003e2.9\u0026emsp;Example snippets\u003c/h2\u003e\n\n    \u003cul\u003e\n      \u003c!-- template:\n      \u003cli\u003e\u003cb\u003e\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003e\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      --\u003e\n\n      \u003c!-- CDATA would be nicer for the C++ code, but it seems to confuse the hell out of Firefox in text/html mode... --\u003e\n      \u003c!-- There must be no whitespace between \u003cp\u003e\u003ccode\u003e and the start of the code, for it has a tendency to pop up when copy-pasting snippets from one's browser. --\u003e\n\n      \u003cli\u003e\u003cb\u003eFirst thing everybody tries..\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi { for(;;) ; }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003eKilled\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n\n      \u003cli\u003e\u003cb\u003e\u003ca href='http://en.wikipedia.org/wiki/Reverse_Polish_notation'\u003eReverse Polish notation\u003c/a\u003e expression evaluator\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi { istringstream e (\"2 4 * 3 2.1 + / 9 -\"); stack\u0026lt;double\u003e s; char c; while (e \u003e\u003e c) if (isdigit(c)) { e.putback(c); s.push(0); e \u003e\u003e s.top(); } else { double const x = s.top(); s.pop(); if (c == '+') s.top() += x; else if (c == '*') s.top() *= x; else if (c == '-') s.top() -= x; else if (c == '/') s.top() /= x; } cout \u0026lt;\u0026lt; s.top(); }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e-7.43137\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eFloating-point arithmetic has errors\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi \u0026lt;\u0026lt; (3 * 0.1 == 0.3)\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003efalse\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eCustom sorting predicate\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: bool comp (string const \u0026amp; a, string const \u0026amp; b) { return a.size() \u0026lt; b.size(); } int main () { using namespace boost::assign; vector\u0026lt;string\u003e v; v += \"superman\", \"spiderman\", \"batman\", \"hulk\", \"iceman\", \"wolverine\"; sort(v.begin(), v.end(), comp); cout \u0026lt;\u0026lt; v; }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e[hulk, batman, iceman, superman, spiderman, wolverine]\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003erand()%N is flawed\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi { int const range = 1400000000, samples = 10000000; assert(range \u0026lt; RAND_MAX); int x = 0; for (int u = 0; u != samples; ++u) if ((rand() % range) \u0026lt; range / 2) ++x; cout \u0026lt;\u0026lt; x / double(samples) * 100 \u0026lt;\u0026lt; \"% of samples lie in lower half of chosen range\"; }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e65.1787% of samples lie in lower half of chosen range\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003c!-- broken:\n      \u003cli\u003e\u003cb\u003eInline assembly\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: extern \"C\" char const s [] = \"Hello world!\"; int main() { asm(\"push $12; push $s; push $1; call write; pop %eax; pop %eax; pop %eax\"); }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003eHello world!\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      --\u003e\n      \u003cli\u003e\u003cb\u003eJust an innocent string...\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi -tw {char const*p=\" weird yogurt craves most typical grayish germs covering my hyper hammer wheels arced underneath ugly cans \";while(*++p){uchar r=0;do r^=*p-'a'\u0026lt;\u0026lt;(*p\u0026amp;4);while(*++p!=' ');cout\u0026lt;\u0026lt;hex\u0026lt;\u0026lt;int(r)\u0026lt;\u0026lt;' ';}}\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e\u003ca href='http://en.wikipedia.org/wiki/AACS_encryption_key_controversy'\u003e9 f9 11 2 9d 74 e3 5b d8 41 56 c5 63 56 88 c0\u003c/a\u003e\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eFunction plotter (only works well in some fonts)\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: typedef double D;void plot(D(*f)(D),D ymin,D ymax,D xstart,D xstep,D xend){char c[]=\"_.,=-*'~`\"; for (D x=xstart;x\u0026lt;=xend;x+=xstep){size_t h=size_t((f(x)-ymin)/(ymax-ymin)*sizeof(c));cout\u0026lt;\u0026lt;(h\u0026lt;sizeof(c)?c[h]:' ');}}  int main() { plot(sin, -1, 1, 0, 0.3, 5 * M_PI); }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e*'~``~*-,.____.,=*'~``~*-,.____.,=*'~`'*\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eUntyped lambda calculus reducer\u003c/b\u003e\n        \u003cp\u003e(Calculates 1+1 using Church numerals, producing a weak head normal form of 2. Uses de Bruijn indices.)\u003c/p\u003e\n        \u003cp\u003e\u003ccode\u003egeordi -t \u0026lt;\u0026lt;m(\"(.(.(.(.3(210)0))))(.(.01))(.(.01))zs\");tpd str S;tpd S::iterator I;int p;I h(I i){do p+=*i==40,p-=*i++==41;wh(p);ret i;}S r(I i,I e,int x,S a){if(i==e)ret\"\";I o=h(i);ret *i-40?(*i-x?S(1,*i):a)+r(i+1,e,x,a):'('+(i[1]-46?r(i+1,o-1,x,a):'.'+r(i+2,o-1,x+1,a))+')'+r(o,e,x,a);}S m(S);S m(I i,I e){S q(i,e);I j=h(i);ret *i-40?q:i[1]-46?m(m(i+1,j-1)+S(j,e)):j-e?m(r(i+2,j-1,48,S(j,h(j)))+S(h(j),e)):q;}S m(S x){ret m(RANGE(x));}\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003es((.(.01))zs)\u003c/code\u003e\u003c/p\u003e\n        \u003c!-- notes\n          syntax:\n              expr := constant | var | expr expr | '(' expr ')' | '(.' expr ')'\n              var := 0 | 1 | ... | 9\n              constant := a | b | ... | z\n          crucial: every '.' has a '(' in front of it.\n          only reduces to WHNF.\n        --\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eThe \u003ca href='http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern'\u003eCuriously Recurring Template Pattern (CRTP)\u003c/a\u003e\u003c/b\u003e\n        \u003cp\u003e(In this snippet, X implements prefix increment, and obtains a canonically implemented postfix increment in terms of its prefix increment by inheriting postfix_incr\u0026lt;X\u0026gt;. Snippet based on \u003ca href='http://www.boost.org/libs/utility/operators.htm'\u003eBoost.Operators\u003c/a\u003e.)\u003c/p\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: template \u0026lt;typename Derived\u0026gt; struct postfix_incr { Derived * derived_this() { return static_cast\u0026lt;Derived *\u003e(this); } Derived operator++(int) { Derived const t(*derived_this()); ++*derived_this(); return t; } };  struct X: postfix_incr\u0026lt;X\u003e { int i; X \u0026amp; operator++() { ++i; return *this; } using postfix_incr\u0026lt;X\u0026gt;::operator++; };  int main() { X x; x.i = 2; x++; cout \u0026lt;\u0026lt; x.i; }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e3\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003e\u003ca href='http://en.wikipedia.org/wiki/Quine_%28computing%29'\u003eQuine\u003c/a\u003e using iostreams\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: { char y(34); stringstream i(\"geordi: { char y(34); stringstream i(!); string t; getline(i, t, '!'); cout \u0026lt;\u0026lt; t \u0026lt;\u0026lt; y \u0026lt;\u0026lt; i.str() \u0026lt;\u0026lt; y \u0026lt;\u0026lt; i.rdbuf(); }\"); string t; getline(i, t, '!'); cout \u0026lt;\u0026lt; t \u0026lt;\u0026lt; y \u0026lt;\u0026lt; i.str() \u0026lt;\u0026lt; y \u0026lt;\u0026lt; i.rdbuf(); }\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003e\u003ca href='http://en.wikipedia.org/wiki/Brainfuck'\u003eBrainfuck\u003c/a\u003e interpreter\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: char program[]=\"\u0026gt;\u0026gt;,[\u0026gt;\u0026gt;,]\u0026lt;\u0026lt;[[-\u0026lt;+\u0026lt;]\u003e[\u003e[\u003e\u003e]\u0026lt;[.[-]\u0026lt;[[\u003e\u003e+\u0026lt;\u0026lt;-]\u0026lt;]\u003e\u003e]\u003e]\u0026lt;\u0026lt;]\", input[]=\"dicekjhbagfl\", *i=input,m[512]={},*p=m;void b(char*c){for(;*c\u0026amp;\u0026amp;*c!=']';++c){(*((p+=*c=='\u003e')-=*c=='\u0026lt;')+=*c=='+') -=*c=='-';*c=='.'\u0026amp;\u0026amp;cout\u0026lt;\u0026lt;*p;if(*c==',')*p=*i++;if(*c=='['){ for(++c;*p;)b(c);for(int d=0;*c!=']'||d--;++c)d+=*c=='[';}}}int main(){b(program);}\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003eabcdefghijkl\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n\n      \u003cli\u003e\u003cb\u003e\u003ca href='http://en.wikipedia.org/wiki/Quicksort'\u003eQuicksort\u003c/a\u003e\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: { int a[] = { 2, 3, 7, 1, 5, 6, 4, 0 }; quicksort(RANGE(a)); cout \u0026lt;\u0026lt; a; }  template \u0026lt;typename I\u003e void quicksort(I const i, I const e) { if(i == e || boost::next(i) == e) return; I v(e); for(I u(boost::next(i)); u != v; ) if(*u \u0026lt;= *i) ++u; else swap(*u, *--v); swap(*i, *--v); quicksort(i, v); quicksort(++v, e); }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e[0, 1, 2, 3, 4, 5, 6, 7]\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003ePermutation sort ;-)\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: { int v[] = { 2, 3, 7, 1, 5, 6, 4, 0 }; while (!sorted(RANGE(v))) next_permutation(RANGE(v)); cout \u0026lt;\u0026lt; v; } template \u0026lt;typename I\u003e bool sorted (I b, I const e) { if (b == e) return true; I const c = b++; return b == e || (*c \u0026le; *b \u0026amp;\u0026amp; sorted(b, e)); }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e[0, 1, 2, 3, 4, 5, 6, 7]\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eGNU libc \u003ca href='http://www.gnu.org/software/libc/manual/html_node/Heap-Consistency-Checking.html#Heap-Consistency-Checking'\u003eheap consistency checking\u003c/a\u003e\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi { int * const p = new int[3]; for (int i = 0; i \u0026lt;= 3; ++i) p[i] = 8; delete[] p; }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003ememory clobbered past end of allocated block\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eGNU libstdc++ \u003ca href='http://gcc.gnu.org/onlinedocs/libstdc++/debug.html'\u003edebug mode\u003c/a\u003e diagnostics\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi { vector\u0026lt;int\u003e s (3); cout \u0026lt;\u0026lt; *(s.begin() + 4); }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003eattempt to advance a dereferenceable (start-of-sequence) iterator 4 steps, which falls outside its valid range.\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eMemory exhaustion\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi { int i = 0; while (new (nothrow) char [1024 * 1024]) ++i; cout \u0026lt;\u0026lt; i \u0026lt;\u0026lt; \" MiB\"; }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e188 MiB\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eFile size limit\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi { ofstream f (__FILE__); string const meg (1024 * 1024, 'x'); for (;;) { f \u0026lt;\u0026lt; meg \u0026lt;\u0026lt; flush; cout \u0026lt;\u0026lt; \"+ \" \u0026lt;\u0026lt; flush; } }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e+ + + + + File size limit exceeded\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eFile handle exhaustion\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: extern \"C\" int open (char const *, int); int main () { int i = 0; while (open(__FILE__, 0) != -1) ++i; cout \u0026lt;\u0026lt; strerror(errno), i; }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003eToo many open files, 23\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eStack protection (-fstack-protector-all)\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: { char buf [10]; fill(buf, buf+30, 'x'); }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003e*** stack smashing detected ***: /t terminated\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eNaive fork bomb attempt\u003c/b\u003e\n        \u003cp\u003e\u003ccode\u003egeordi: { for(;;) fork(); }\u003c/code\u003e\u003c/p\u003e\n        \u003cp\u003e\u003ci\u003eOutput:\u003c/i\u003e\u0026emsp;\u003ccode\u003eSYS_clone: Operation not permitted\u003c/code\u003e\u003c/p\u003e\n      \u003c/li\u003e\n    \u003c/ul\u003e\n\n    \u003chr/\u003e\u003ch2 id='setup'\u003e3\u0026emsp;Setting up a geordi\u003c/h2\u003e\n\n    \u003chr/\u003e\u003ch3 id='download'\u003e3.1\u0026emsp;Download\u003c/h3\u003e\n\n    \u003cp\u003eGeordi can be downloaded from \u003ca href='http://github.com/Eelis/geordi'\u003egithub\u003c/a\u003e.\u003c/p\u003e\n\n    \u003chr/\u003e\u003ch3 id='install'\u003e3.2\u0026emsp;Install\u003c/h3\u003e\n\n    \u003cp\u003egeordi runs as a \u003ca href='https://docs.docker.com/engine/userguide/'\u003eDocker\u003c/a\u003e container.\u003c/p\u003e\n    \u003cp\u003eTo build the image from which the container will be instantiated, in the directory where Dockerfile is, say:\u003c/p\u003e\n    \u003cpre\u003e  sudo docker build -t geordi .\u003c/pre\u003e\n    \u003cp\u003eSince this involves building GCC and Clang from source, it may take some time.\u003c/p\u003e\n\n    \u003chr/\u003e\u003ch3 id='run'\u003e3.3\u0026emsp;Run\u003c/h3\u003e\n    \n\n    \u003cp\u003eTo run a local interactive geordi session, say:\u003c/p\u003e\n    \u003cpre\u003e  sudo docker run -it geordi\u003c/pre\u003e\n    \u003cp\u003eTo run the IRC bot, edit \u003ckbd\u003eirc-config\u003c/kbd\u003e and then say:\u003c/p\u003e\n    \u003cpre\u003e  sudo docker run -i geordi geordi-irc \u0026lt; irc-config\u003c/pre\u003e\n\n    \u003chr/\u003e\u003ch3 id='nickserv'\u003e3.4\u0026emsp;NickServ identification\u003c/h3\u003e\n    \u003cp\u003eTo have the bot identify to NickServ, change the following line in \u003ckbd\u003eirc-config\u003c/kbd\u003e:\u003c/p\u003e\n    \u003cpre\u003e  , nick_pass = Nothing\u003c/pre\u003e\n    \u003cp\u003einto:\u003c/p\u003e\n    \u003cpre\u003e  , nick_pass = Just \"mypassword\"\u003c/pre\u003e\n\n    \u003chr/\u003e\u003ch3 id='nickless'\u003e3.5\u0026emsp;Nickless requests\u003c/h3\u003e\n    \u003cp\u003eTo have the bot respond to nickless requests (e.g. \"\u003ckbd\u003e\u0026lt;\u0026lt; 3\u003c/kbd\u003e\") in channels #foo, #bar, and #bas, use:\u003c/p\u003e\n    \u003cpre\u003e  , allow_nickless_requests_in = [\"#foo\", \"#bar\", \"#bas\"]\u003c/pre\u003e\n\n    \u003chr/\u003e\u003ch3 id='reconnect'\u003e3.6\u0026emsp;Auto-reconnect\u003c/h3\u003e\n    \u003cp\u003eGeordi does not auto-reconnect. For that, just use something like\u003c/p\u003e\n    \u003cpre\u003e  while true; do sudo docker run -i geordi geordi-irc \u0026lt; irc-config; sleep 120; done\u003c/pre\u003e\n\n    \u003chr/\u003e\u003ch3 id='multinetwork'\u003e3.7\u0026emsp;Connecting to multiple networks\u003c/h3\u003e\n    \u003cp\u003eMake config files for the different networks, and run an instance for each network.\u003c/p\u003e\n\n    \u003chr/\u003e\u003ch3 id='censor'\u003e3.8\u0026emsp;Censoring phrases\u003c/h3\u003e\n    \u003cp\u003eSome networks automatically kick or ban clients that utter certain phrases (like botnet commands). To prevent a geordi bot from uttering these, list regexes for them in irc-config. E.g.:\u003c/p\u003e\n    \u003cpre\u003e  , censor = [\"some naughty phrase\", \"some wicked utterance\"]\u003c/pre\u003e\n\n  \u003c/body\u003e\n\u003c/html\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEelis%2Fgeordi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FEelis%2Fgeordi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEelis%2Fgeordi/lists"}