From 9a0f186f29aec56952e89b1312ba6f81d31ba86b Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Sat, 18 Apr 2026 15:44:14 +0100 Subject: [PATCH] Things working much better now. `assoc` works. Currently printing of string-like-things does not work, but I suspect that's shallow. --- docs/shipnames.md | 268 +++++++++++++++++++++++++++++++++++++++++ src/c/debug.c | 2 +- src/c/io/io.c | 16 ++- src/c/io/io.h | 5 + src/c/io/print.c | 86 ++++++++++--- src/c/io/print.h | 9 +- src/c/memory/destroy.c | 2 +- src/c/memory/pso.c | 17 ++- src/c/ops/eq.c | 10 +- src/c/ops/repl.c | 5 +- src/c/payloads/cons.c | 2 +- src/c/psse.c | 14 ++- src/c/version.h | 2 +- 13 files changed, 400 insertions(+), 38 deletions(-) create mode 100644 docs/shipnames.md diff --git a/docs/shipnames.md b/docs/shipnames.md new file mode 100644 index 0000000..b5186c2 --- /dev/null +++ b/docs/shipnames.md @@ -0,0 +1,268 @@ +# Ship names from Iain M Banks' Culture series + +This list is culled from the Wikipedia page. I don't know if it's comprehensive (although it looks it), and I haven't checked that all the names are either present in the books or spelled correctly here. I *think* they are, and that's good enough. + +Note that these names are not all Culture ships; and I think I should probably prefer only to select ones that are. + +The reason the list is here is that I propose to assign a codename taken from the list to each point release of Post Scarcity. starting from 0.1.0, which will be `A Momentary Lapse Of Sanity`. Names that have already been selected are **highlighted**. + +I think my plan is to assign 0.1.X point releases names starting with `A`, 0.2.X releases names starting with `B`, and so on; but I reserve the right to change my mind or just be wildly inconsistent. + +----- + +- 5Gelish-Oplule +- 7Uagren +- 8401.00 Partial Photic Boundary +- 8Churkun +- Abalule-Sheliz +- Ablation +- Abundance Of Onslaught +- Advanced Case Of Chronic Patheticism +- A Fine Disregard For Awkward Facts +- All The Same, I Saw It First +- **A Momentary Lapse Of Sanity** +- Another Fine Product From The Nonsense Factory +- Anticipation Of A New Lover's Arrival, The +- Anything Legal Considered +- Appeal To Reason +- Arbitrary +- Armchair Traveller +- Arrested Development +- A Series Of Unlikely Explanations +- A Ship With A View +- Attitude Adjuster +- Awkward Customer +- Bad For Business +- Beastly To The Animals +- Beats Working +- Big Sexy Beast +- Bodhisattva, OAQS +- Boo! +- Bora Horza Gobuchul +- Break Even +- But Who's Counting? +- Caconym +- Cantankerous +- Cargo Cult +- CH2OH.(CHOH)4.CHO +- Charitable View +- Charming But Irrational +- Clear Air Turbulence or CAT for short +- Congenital Optimist +- Contents May Differ +- Control Surface +- Conventional Wisdom +- Credibility Problem +- Death And Gravity +- Demented But Determined +- Determinist +- Different Tan +- Displacement Activity +- Don't Try This At Home +- Dramatic Exit +- Dressed Up To Party +- Eight Rounds Rapid +- Empiricist +- Eschatologist (temporary name) +- Ethics Gradient +- Exaltation-Parsimony III +- Excuses And Accusations +- Experiencing A Significant Gravitas Shortfall +- Experiencing A Significant Gravitas Shortfall +- Falling Outside The Normal Moral Constraints +- “Fasilyce, Upon Waking” +- Fate Amenable To Change +- Fine Till You Came Along +- Fixed Grin +- Flexible Demeanour +- Fractious Person +- Frank Exchange Of Views +- Frightspear +- Fulanya-Guang +- Full Refund (formerly MBU 604) +- Funny, It Worked Last Time... +- Furious Purpose +- Gellemtyan-Asool-Anafawaya +- Germane Riposte +- God Told Me To Do It +- Grey Area (aka Meatfucker) +- Grey Area (aka Meatfucker) +- Gunboat Diplomat +- Halation Effect +- Hand Me The Gun And Ask Me Again +- Happy Idiot Talk +- Headcrash +- Heavy Messing +- Helpless In The Face Of Your Beauty +- Hence the Fortress +- Heresiarch +- Hidden Income +- Highpoint +- Honest Mistake +- Hundredth Idiot, The +- Hylozoist +- Iberre +- I Blame My Mother +- I Blame The Parents +- I Blame Your Mother +- Inappropriate Response +- Injury Time +- In One Ear +- Inspiral, Coalescence, Ringdown +- Invincible +- Irregular Apocalypse +- I Said, I've Got A Big Stick +- I Thought He Was With You +- It'll Be Over By Christmas +- It's Character Forming +- It's My Party And I'll Sing If I Want To +- Jaundiced Outlook +- Joiler Veppers (provisional name) +- Just Another Victim Of The Ambient Morality +- Just Passing Through +- Just Read The Instructions +- Just Testing +- Just The Washing Instruction Chip In Life's Rich Tapestry +- Kakistocrat +- Killing Time +- Kiss My Ass +- Kiss The Blade +- Kiss This Then +- Labtebricolephile +- Lacking That Small Match Temperament +- Lapsed Pacifist +- Laskuil-Hliz +- Lasting Damage +- Lasting Damage I +- Lasting Damage II +- later Sleeper Service +- Learned Response +- Lightly Seared On The Reality Grill +- Limiting Factor +- Limivorous +- Little Rascal +- Liveware Problem“Now, Turning to Reason, & its Just Sweetness” +- Long View +- Lucid Nonsense +- Me, I'm Counting +- Melancholia Enshrines All Triumph +- Messenger Of Truth +- Minority Report +- Misophist +- Mistake Not… +- Nervous Energy +- Never Talk To Strangers +- New Toy +- No Fixed Abode +- No More Mr Nice Guy +- No One Knows What The Dead Think +- Not Invented Here +- Not Wanted On Voyage +- Now Look What You've Made Me Do +- Now We Try It My Way +- Nuisance Value +- Oceanic Dissonance +- Of Course I Still Love You +- “On First Seeing Jhiriit” +- Only Slightly Bent +- Outstanding Contribution To The Historical Process +- Passing By And Thought I'd Drop In +- Peace Makes Plenty +- Pelagian +- Perfidy +- Piety +- Poke It With A Stick +- Pressure Drop +- Pride Comes Before A Fall +- Prime Mover +- Problem Child +- Profit Margin +- Prosthetic Conscience +- Pure Big Mad Boat Man +- Qualifier +- Questionable Ethics +- Quiatrea-Anang +- Quietly Confident, +- Rapid Random Response Unit +- Ravished By The Sheer Implausibility Of That Last Statement +- Reasonable Excuse +- Recent Convert +- Reformed Nice Guy +- Refreshingly Unconcerned With The Vulgar Exigencies Of Veracity +- Resistance Is Character-Forming +- Revisionist +- Riptalon +- Rubric Of Ruin +- Sacrificial Victim +- SacSlicer II +- Sanctioned Parts List +- Scar Glamour +- Screw Loose +- Seed Drill +- Sense Amid Madness, Wit Amidst Folly +- Serious Callers Only +- Shoot Them Later +- Size Isn't Everything +- Smile Tolerantly +- Sober Counsel +- Someone Else's Problem +- So Much For Subtlety +- Soulhaven +- Space Monster +- Steely Glint +- Stranger Here Myself +- Subtle Shift In Emphasis +- Sweet and Full of Grace +- Synchronize Your Dogmas +- T3OU 118 +- T3OU 4 +- T3OU 736 +- Tactical Grace +- Teething Problems +- Thank You And Goodnight +- The Ends Of Invention +- The Hand of God 137 +- The Precise Nature Of The Catastrophe +- The Usual But Etymologically Unsatisfactory +- Thorough But... Unreliable +- Total Internal Reflection +- Trade Surplus +- Transient Atmospheric Phenomenon +- Ucalegon +- Ultimate Ship The Second +- Unacceptable Behaviour +- Undesirable Alien +- Unfortunate Conflict Of Evidence +- Uninvited Guest +- Unreliable Witness +- Unwitting Accomplice +- Use Psychology +- Value Judgement +- Very Little Gravitas Indeed +- Vision Of Hope Surpassed +- Vulgarian +- Warm, Considering +- We Haven't Met But You're A Great Fan Of Mine +- Well I Was In The Neighbourhood +- What Are The Civilian Applications? +- What Is The Answer And Why? +- Wingclipper +- Winter Storm +- Wisdom Like Silence +- Within Reason +- Xenoclast +- Xenocrat +- Xenoglossicist +- Xenophobe +- Yawning Angel +- You Call This Clean? +- You'll Clean That Up Before You Leave +- You'll Thank Me Later +- You May Not Be The Coolest Person Here +- You Naughty Monsters +- Youthful Indiscretion +- You Would If You Really Loved Me +- Zealot +- Zero Credibility +- Zero Gravitas +- Zoologist diff --git a/src/c/debug.c b/src/c/debug.c index 637d889..3665459 100644 --- a/src/c/debug.c +++ b/src/c/debug.c @@ -143,7 +143,7 @@ void debug_print_object( struct pso_pointer pointer, int level, int indent ) { if ( level & verbosity ) { URL_FILE *ustderr = file_to_url_file( stderr ); fwide( stderr, 1 ); - in_print( pointer, ustderr ); + in_write( pointer, ustderr, PRINT_VARIANT_PRINT ); free( ustderr ); } #endif diff --git a/src/c/io/io.c b/src/c/io/io.c index 35bd0b1..e23b512 100644 --- a/src/c/io/io.c +++ b/src/c/io/io.c @@ -89,7 +89,7 @@ struct pso_pointer lisp_io_out; struct pso_pointer lisp_stdout; /** - * @brief bound to the Lisp symbol representing C_IO_log in initialisation. + * @brief bound to the Lisp symbol representing C_IO_LOG in initialisation. */ struct pso_pointer lisp_io_log; @@ -99,6 +99,11 @@ struct pso_pointer lisp_io_log; */ struct pso_pointer lisp_stderr; +/** + * @brief bound to the Lisp symbol representing C_IO_PROMPT in initialisation + */ +struct pso_pointer lisp_io_prompt; + /** * Allow a one-character unget facility. This may not be enough - we may need * to allocate a buffer. @@ -147,11 +152,16 @@ struct pso_pointer initialise_default_streams( struct pso_pointer env ) { lisp_io_in = c_string_to_lisp_symbol( C_IO_IN ); lisp_io_out = c_string_to_lisp_symbol( C_IO_OUT ); lisp_io_log = c_string_to_lisp_symbol( C_IO_LOG ); + lisp_io_prompt = c_string_to_lisp_symbol( C_IO_PROMPT ); debug_print( L"In initialise_default_streams; environment is: ", DEBUG_IO, 0 ); debug_print_object( env, DEBUG_IO, 0 ); + env = + c_bind( lisp_io_prompt, c_string_to_lisp_string( INITIAL_PROMPT ), + env ); + lisp_stdin = lock_object( make_read_stream( file_to_url_file( stdin ), c_cons( c_cons ( c_string_to_lisp_keyword @@ -367,8 +377,8 @@ struct pso_pointer push_back_character( struct pso_pointer c, if ( characterp( c ) && readp( r ) ) { if ( url_ungetwc( ( wint_t ) - ( pointer_to_object( c )->payload.character. - character ), + ( pointer_to_object( c )->payload. + character.character ), pointer_to_object( r )->payload.stream.stream ) >= 0 ) { result = t; diff --git a/src/c/io/io.h b/src/c/io/io.h index 7b04d75..a2b733c 100644 --- a/src/c/io/io.h +++ b/src/c/io/io.h @@ -33,6 +33,11 @@ extern struct pso_pointer lisp_stdin; extern struct pso_pointer lisp_stdout; extern struct pso_pointer lisp_stderr; +#define INITIAL_PROMPT L"psse ]" +#define C_IO_PROMPT L"*prompt*" + +extern struct pso_pointer lisp_io_prompt; + URL_FILE *file_to_url_file( FILE * f ); wint_t url_fgetwc( URL_FILE * input ); wint_t url_ungetwc( wint_t wc, URL_FILE * input ); diff --git a/src/c/io/print.c b/src/c/io/print.c index f65d9aa..ed097a3 100644 --- a/src/c/io/print.c +++ b/src/c/io/print.c @@ -11,6 +11,7 @@ * Licensed under GPL version 2.0, or, at your option, any later version. */ +#include #include #include #include @@ -26,6 +27,7 @@ #include "io/fopen.h" #include "io/io.h" +#include "io/print.h" #include "memory/node.h" #include "memory/pointer.h" @@ -33,22 +35,26 @@ #include "memory/pso2.h" #include "memory/tags.h" +#include "ops/string_ops.h" #include "payloads/character.h" #include "payloads/cons.h" +#include "payloads/exception.h" #include "payloads/integer.h" #include "ops/truth.h" -struct pso_pointer in_print( struct pso_pointer p, URL_FILE * output ); +struct pso_pointer in_write( struct pso_pointer p, URL_FILE * output, + bool escape ); struct pso_pointer print_string_like_thing( struct pso_pointer p, - URL_FILE *output ) { + URL_FILE *output, bool escape ) { switch ( get_tag_value( p ) ) { case KEYTV: url_fputwc( L':', output ); break; case STRINGTV: - url_fputwc( L'"', output ); + if ( !escape ) + url_fputwc( L'"', output ); break; } @@ -61,18 +67,20 @@ struct pso_pointer print_string_like_thing( struct pso_pointer p, } if ( stringp( p ) ) { - url_fputwc( L'"', output ); + if ( !escape ) + url_fputwc( L'"', output ); } } -struct pso_pointer print_list_content( struct pso_pointer p, URL_FILE *output ) { +struct pso_pointer print_list_content( struct pso_pointer p, URL_FILE *output, + bool escape ) { struct pso_pointer result = nil; if ( consp( p ) ) { for ( ; consp( p ); p = c_cdr( p ) ) { struct pso2 *object = pointer_to_object( p ); - result = in_print( object->payload.cons.car, output ); + result = in_write( object->payload.cons.car, output, escape ); if ( exceptionp( result ) ) break; @@ -85,7 +93,8 @@ struct pso_pointer print_list_content( struct pso_pointer p, URL_FILE *output ) break; default: url_fputws( L" . ", output ); - result = in_print( object->payload.cons.cdr, output ); + result = + in_write( object->payload.cons.cdr, output, escape ); } } } else { @@ -95,7 +104,18 @@ struct pso_pointer print_list_content( struct pso_pointer p, URL_FILE *output ) return result; } -struct pso_pointer in_print( struct pso_pointer p, URL_FILE *output ) { +/** + * This is kind of modelled after the implementation of PRIN* variants on page + * 383 of the aluminium book. It is the inner workings of all PRIN* functions. + * + * @param p pointer to the object to print. + * @param output stream to print to. + * @param escape if true, print everything so that it can be read by the Lisp + * reader; otherwise, print it appropriately for human readers. + * @return p on success, exception on failure. + */ +struct pso_pointer in_write( struct pso_pointer p, URL_FILE *output, + bool escape ) { struct pso2 *object = pointer_to_object( p ); struct pso_pointer result = nil; @@ -107,7 +127,7 @@ struct pso_pointer in_print( struct pso_pointer p, URL_FILE *output ) { break; case CONSTV: url_fputwc( L'(', output ); - result = print_list_content( p, output ); + result = print_list_content( p, output, escape ); url_fputwc( L')', output ); break; case INTEGERTV: @@ -117,7 +137,7 @@ struct pso_pointer in_print( struct pso_pointer p, URL_FILE *output ) { case KEYTV: case STRINGTV: case SYMBOLTV: - print_string_like_thing( p, output ); + print_string_like_thing( p, output, escape ); break; case NILTV: url_fputws( L"nil", output ); @@ -126,7 +146,7 @@ struct pso_pointer in_print( struct pso_pointer p, URL_FILE *output ) { case WRITETV: url_fwprintf( output, L"<%s stream: ", v == READTV ? "read" : "write" ); - in_print( object->payload.stream.meta, output ); + in_write( object->payload.stream.meta, output, escape ); url_fputwc( L'>', output ); break; case TRUETV: @@ -143,13 +163,19 @@ struct pso_pointer in_print( struct pso_pointer p, URL_FILE *output ) { } /** - * @brief Simple print for bootstrap layer. + * This is kind of modelled after the implementation of PRIN* variants on page + * 383 of the aluminium book. It is the inner workings of all PRIN* functions. * * @param p pointer to the object to print. - * @param stream if a pointer to an open write stream, print to there. - * @return struct pso_pointer `nil`, or an exception if some erroe occurred. + * @param output stream to print to. + * @param escape if true, print everything so that it can be read by the Lisp + * reader; otherwise, print it appropriately for human readers. + * @param nl_before if true, print a newline *before* printing `p`. + * @param nl_after if true, print a newline *after* printing `p`; else a space. + * @return p on success, exception on failure. */ -struct pso_pointer c_print( struct pso_pointer p, struct pso_pointer stream ) { +struct pso_pointer write( struct pso_pointer p, struct pso_pointer stream, + bool escape, bool nl_before, bool nl_after ) { struct pso_pointer result = p; URL_FILE *output = writep( stream ) ? pointer_to_object( stream )->payload.stream.stream @@ -158,10 +184,38 @@ struct pso_pointer c_print( struct pso_pointer p, struct pso_pointer stream ) { if ( writep( stream ) ) { inc_ref( stream ); - result = in_print( p, output ); + if ( nl_before ) + url_fputwc( L'\n', output ); + + result = in_write( p, output, true ); + + url_fputwc( nl_after ? L'\n' : L' ', output ); dec_ref( stream ); + } else { + result = + make_exception( c_string_to_lisp_string + ( L"Bad write stream passed to write." ), nil, nil, + nil ); } return result; } + +/** + * @brief Simple print for bootstrap layer. + * + * @param p pointer to the object to print. + * @param stream if a pointer to an open write stream, print to there. + * @return struct pso_pointer `nil`, or an exception if some erroe occurred. + */ +struct pso_pointer c_print( struct pso_pointer p, struct pso_pointer stream ) { + return write( p, stream, true, true, false ); +} + +/** + * @brief princ is pretty much like print except things are printed `unescaped` + */ +struct pso_pointer c_princ( struct pso_pointer p, struct pso_pointer stream ) { + return write( p, stream, false, true, false ); +} diff --git a/src/c/io/print.h b/src/c/io/print.h index 39b7d41..d239913 100644 --- a/src/c/io/print.h +++ b/src/c/io/print.h @@ -13,10 +13,17 @@ #ifndef __psse_io_print_h #define __psse_io_print_h +#include #include "io/fopen.h" struct pso_pointer c_print( struct pso_pointer p, struct pso_pointer stream ); +struct pso_pointer c_princ( struct pso_pointer p, struct pso_pointer stream ); -struct pso_pointer in_print( struct pso_pointer p, URL_FILE * output ); +#define PRINT_VARIANT_PRINT 0 +#define PRINT_VARIANT_PRIN1 1 +#define PRINT_VARIANT_PRINC 2 + +struct pso_pointer in_write( struct pso_pointer p, URL_FILE * output, + bool variant ); #endif diff --git a/src/c/memory/destroy.c b/src/c/memory/destroy.c index d8c0db4..41adcb6 100644 --- a/src/c/memory/destroy.c +++ b/src/c/memory/destroy.c @@ -55,7 +55,7 @@ struct pso_pointer destroy( struct pso_pointer p ) { destroy_string( f, nil ); break; case STACKTV: - destroy_stack_frame( f, nil ); +// destroy_stack_frame( f, nil ); break; // TODO: others. } diff --git a/src/c/memory/pso.c b/src/c/memory/pso.c index c925906..4b7ba2c 100644 --- a/src/c/memory/pso.c +++ b/src/c/memory/pso.c @@ -14,7 +14,9 @@ * Licensed under GPL version 2.0, or, at your option, any later version. */ +#include #include +#include #include #include @@ -92,10 +94,15 @@ struct pso_pointer allocate( char *tag, uint8_t size_class ) { return result; } -uint32_t payload_size( struct pso2 *object ) { +int payload_size( struct pso2 *object ) { // TODO: Unit tests DEFINITELY needed! - return ( ( 1 << object->header.tag.bytes.size_class ) - - sizeof( struct pso_header ) ); + int sc = object->header.tag.bytes.size_class; + int hs = sizeof( struct pso_header ) / sizeof( uint64_t ); + int p = pow( 2, sc ); + + int result = abs( p - hs ); + + return result; } /** @@ -190,8 +197,8 @@ struct pso_pointer lock_object( struct pso_pointer pointer ) { struct pso_pointer free_object( struct pso_pointer p ) { struct pso_pointer result = nil; struct pso2 *obj = pointer_to_object( p ); - uint32_t array_size = payload_size( obj ); - uint8_t size_class = obj->header.tag.bytes.size_class; + uint32_t array_size = ( uint32_t ) payload_size( obj ); + uint8_t size_class = ( obj->header.tag.bytes.size_class ); result = destroy( p ); diff --git a/src/c/ops/eq.c b/src/c/ops/eq.c index d5b348e..101ea51 100644 --- a/src/c/ops/eq.c +++ b/src/c/ops/eq.c @@ -41,7 +41,7 @@ bool c_eq( struct pso_pointer a, struct pso_pointer b ) { } bool c_equal( struct pso_pointer a, struct pso_pointer b ) { - bool result = false; + bool result = true; if ( c_eq( a, b ) ) { result = true; @@ -66,15 +66,19 @@ bool c_equal( struct pso_pointer a, struct pso_pointer b ) { case KEYTV: case STRINGTV: case SYMBOLTV: - while ( !nilp( a ) && !nilp( b ) ) { + while ( result && !nilp( a ) && !nilp( b ) ) { if ( pointer_to_object( a )->payload.string.character == pointer_to_object( b )->payload.string.character ) { a = c_cdr( a ); b = c_cdr( b ); + } else { + result = false; } } - result = nilp( a ) && nilp( b ); + result = result && nilp( a ) && nilp( b ); break; + default: + result = false; } } diff --git a/src/c/ops/repl.c b/src/c/ops/repl.c index 09e34aa..24067c6 100644 --- a/src/c/ops/repl.c +++ b/src/c/ops/repl.c @@ -47,7 +47,7 @@ void int_handler( int dummy ) { /** * Very simple read/eval/print loop for bootstrapping. */ -void c_repl( ) { +void c_repl( bool show_prompt ) { signal( SIGINT, int_handler ); debug_print( L"Entered repl\n", DEBUG_REPL, 0 ); @@ -68,6 +68,9 @@ void c_repl( ) { while ( readp( input_stream ) && !url_feof( stream_get_url_file( input_stream ) ) ) { + if ( show_prompt ) + c_princ( c_assoc( lisp_io_prompt, env ), output_stream ); + /* bottom of stack */ struct pso_pointer frame_pointer = make_frame( 1, nil, input_stream ); diff --git a/src/c/payloads/cons.c b/src/c/payloads/cons.c index 0df03b5..4338468 100644 --- a/src/c/payloads/cons.c +++ b/src/c/payloads/cons.c @@ -50,7 +50,7 @@ struct pso_pointer c_cons( struct pso_pointer car, struct pso_pointer cdr ) { */ struct pso_pointer c_car( struct pso_pointer cons ) { struct pso_pointer result = nil; - struct pso2 *object = pointer_to_object( result ); + struct pso2 *object = pointer_to_object( cons ); if ( consp( cons ) ) { result = object->payload.cons.car; diff --git a/src/c/psse.c b/src/c/psse.c index e49d614..f1f4e13 100644 --- a/src/c/psse.c +++ b/src/c/psse.c @@ -125,12 +125,16 @@ int main( int argc, char *argv[] ) { exit( 1 ); } - c_print( c_cons( c_string_to_lisp_keyword( L"a" ), - ( c_cons( c_string_to_lisp_keyword( L"b" ), - c_cons( c_string_to_lisp_keyword( L"c" ), - nil ) ) ) ), lisp_stdout ); + if ( show_prompt ) { + fwprintf( stdout, + L"Post-scarcity Software Environment version %s\n'%s'\n\n", + VERSION, VERSION_CODENAME ); + fputws + ( L"Licensed under GPL version 2.0, or, at your option, any later version\n\n", + stdout ); + } - // c_repl(); + c_repl( show_prompt ); exit( 0 ); } diff --git a/src/c/version.h b/src/c/version.h index d6b3f2b..1c99f9f 100644 --- a/src/c/version.h +++ b/src/c/version.h @@ -3,9 +3,9 @@ * * Just the version number. There's DEFINITELY a better way to do this! * - * * (c) 2026 Simon Brooke * Licensed under GPL version 2.0, or, at your option, any later version. */ #define VERSION "0.1.0-SNAPSHOT" +#define VERSION_CODENAME "A Momentary Lapse Of Sanity"