LoseThos C+

* See Scoping and Linkages for details on extern, import, LTextern, LTimport, 
etc.

* See ::/LT/Doc/Directives.TXZ.

* See the demo::/LT/Demo/OldSchool/Demo1/Compatibility1.SPP, 
::/LT/Demo/OldSchool/Demo2/Compatibility2.SPP and 
::/LT/Demo/GameStarters/EagleDive.CPZ if you want to operate conventionally (old 
school).

* Built-in types include I0,I8,I16,I32,I64 for signed 0-8 byte ints and U0,U8,U1
6,U32,U64 for unsigned 0-8 byte ints and F64 for 8 byte floats.

        U0      void
        I8      char
        U8      unsigned char
        I16     short
        U16     unsigned short
        I32     int
        U32     unsigned int
        I64     long (64-bit)
        U64     unsigned long (64-bit)
        F64     double
        no F32 float.

* Function with no, or just default args can be called without parentheses. 

* Default args don't have to be on the end.  This code is valid:
  U0 Test(I64 i=4,I64 j,I64 k=5)
  {
    PrintF("%X %X %X\n",i,j,k);
  }
  
  Test(,3);

* A string or char constant all alone is sent to PutS() or PutChar().  A string 
with args is sent to PrintF().   An empty string literal signals a variable 
fmt_str follows.

  U0 Demo1(U8 drv,U8 *fmt,U8 *name,I64 age)
  {
    PutS("Hello World!\n");
    PrintF("%s age %d\n",name,age);
    PrintF(fmt,name,age);
    PutChar(drv);
    PutChar('*');
  }
  
  U0 Demo2(U8 drv,U8 *fmt,U8 *name,I64 age)
  {
    "Hello World!\n";
    "%s age %d\n",name,age;
    "" fmt,name,age;
    '' drv;
    '*';
  }

* When dealing with function addresses, precede the name with "&".

* There is no main() function.  Any code outside of functions gets executed on 
start-up, in order.

* Var arg cnts (...) are accessed with argc and argv[] which are predefined 
invisible local var in any function with "..." as args.

* Allows "5<i<j+1<20" instead of "5<i && i<j+1 && j+1<20".

* switch statements always use a jump table.  Don't use them with cases with 
really big, sparse ranges.

* Allows ranges like "case 4...7:" in switch statements. 

* nobound_switch can be used if you know a switch statement will not exceed the 
lowest or highest case values.  It's a little faster because it doesn't check.

* noreg or reg can be placed before a function local var name.  You can, 
optionally, specify a register after the reg keyword.

* interrupt, public, argpop or noargpop are function flags.

* A nounusedwarn statement will suppress an unused var warning.

* You can have multiple member vars of a class named "pad" or "reserved", and it 
won't issue warnings. 

* Type casting is done with ><(classname) and is postfix.  To typecast int or 
F64, use ToI64(), ToBool() or ToF64(). (LoseThos follows normal C float<-->int 
conversion, but sometimes you want to override.  These functions are better than 
multiplying by "1.0" to convert to float.) 

* The "`" operator raises a base to a power.

* A single quote can encompass multiple characters.  'ABC' is equal to 0x434241.

* LoseThos operator precedence
  `,>>,<<
  *,/,%
  &
  ^
  |
  +,-
  <,>,<=,>=
  ==,!=
  &&
  ^^
  ||
  :,?
  =,<<=,>>=,*=,/=,&=,|=,^=,+=,-=

* Use OptOn(OPTf_STD_C) to use C precedence.

* You can use OptOn(OPTf_PAREN_WARN) to find unnecessary parentheses in code.

* With the #exe{} feature in your src code, you can place programs that insert 
text into the stream of code being compiled.  See #exe {} for an example where 
the date/time and compile-time prompting for cfguration data is placed into a 
program.  The StreamPrintF() and StreamPutS() place text into a src program 
stream following the conclusion of the #exe{} blk.

* No #define functions exist (I'm not a fan)

* No type-checking

* Can't use <> with #include, use "".

* "$" is an escape character.  Two dollar signs signify an ordinary $.  See 
::/LT/Doc/Dollar.TXZ.  In asm or C+ code, it also refers to the instruction's 
addr. 

* union is more like a class, so you don't referrence it with a union label 
after you define it.  Some common unions are declared in Adam1a.HPZ for 1,2,4 
and 8 byte objects.  If you place a type in front of a union declaration, that 
is the type when used by itself.  See ::/LT/Demo/SubIntAccess.CPZ. 

* class member vars can have meta data. fmtstr and fmtdata are two meta data 
types now used.  All compiler structures are saved and you can access the 
compiler's info about classes and vars.  See ::/LT/Demo/ClassMeta.CPZ and  
LtfFormDo().

* See ::/LT/Demo/Exceptions.CPZ.  try{} catch{} and throw are different from 
C++. throw is a function with var ("...") args.  The values passed in throw() 
can be accessed from within a catch{} using the Fs->except_argc and Fs->except_a
rgv[] vars.  Within a catch {} blk, set the var Fs->catch_except to TRUE if you 
want to terminate the search for a handler.  By convention, the first arg of exc
ept_argv[] specifies the exception type num.  A list of assigned exception types 
can be found at EXCEPT_LOCAL.  For a handler that will catch all excepts, you 
can use CatchAll().

* A function is available similar to sizeof which provides the offset of a 
member of a class.  It's called offset.  You place the class name and member 
inside as in offset(classname.membername).  It has nothing to do with 16-bit 
code.  Both sizeof and offset only accept one level of member vars.  That is, 
you can't do sizeof(classname.membername.submembername).

* There is no continue statement.  Use goto.

* No bit field support, but there are bit access library routines.

* lock{} can be used to apply asm LOCK prefixes to code for safe multicore 
read-modify-write accesses.  The code bracked with have LOCK asm prefix's 
applied to relevant instructions within.  It's a little shoddy.  See 
::/LT/Demo/MultiCore/Lock.CPZ.

* There is a function called MSize() which gives the size of an object allocated 
off the heap.  For larger size allocations, the system rounds-up to a power of 
two, so MSize() lets you know the real size and you can take full advantage of 
it.

* You can Free() a NULL ptr.  Useful variants of MAlloc() can be found Here.  
Each task has a heap and you can MAlloc and Free off of other task's heaps, or 
make an independent heap with IndependentHeapCtrlInit().

* The stk does not grow because virtual mem is not used.  I recommend allocating 
large local vars from the heap.  You can change DFT_STK and recompile OSMain or 
request more when doing a Spawn().  You can use CallStkGrow(), but it's odd.  
See ::/LT/Demo/StkGrow.CPZ. 

* Only one base class is allowed.

* All values are extended to 64-bit when accessed.  Intermediate calculations 
are done with 64-bit values.

  The follow examples should be inserted in a function, so that register 
  variables are used.  (Global vars are never register.)
  
  I16 i;
  I32 j;
  j=i=0x12345678; //Resulting i is 0x5678 but j is 0x12345678
  
  I64 i=0x8000000000000000;
  PrintF("%X\n",i>>1);  //Result is 0xC000000000000000 as expected
  
  U64 u=0x8000000000000000;
  PrintF("%X\n",u>>1);  //Result is 0x4000000000000000 as expected
  
  I32 i=0x80000000;       //constant is loaded into a 64-bit register var.
  PrintF("%X\n",i>>1);  //Result is 0x40000000
  
  I32 i=-0x80000000;
  PrintF("%X\n",i>>1);  //Result is 0xC0000000 as expected
  

                                 PrintF Family

MSPrintF() is like SPrintF() but it returns a MAllocated str.  It is vary handy 
because you don't have to worry about overflow.

PutS() doesn't print a new line.

Auto(U8 *fmtstr,...) sends text to the current task's input buffer.
AutoStr(U8 *fmtstr,...) sends text of an AutoFile to the keyboard stream of the 
current TASK but can also do mouse cmds.

XTalk(TaskStruct *task,U8 *fmtstr,...) and text to another task's input buffer.
XTalkStr(TaskStruct *task,U8 *fmtstr,...) sends text of an AutoFile to the 
keyboard stream of another TASK but can also do mouse cmds.


LtfPutS(Ltf *l,U8 *src) and LtfPrintF(Ltf *l,U8 *fmtstr,...) send text to a 
linked text file.  You can buffer to a Ltf and save it, providing the 
functionality of fprintf.  See ::/LT/Demo/Dsk/FPrintF.CPZ.

Adam(U8 *fmtstr,...) send text to the adam task to be compiled and run.
AdamLog(U8 *fmtstr,...) and AdamErr(U8 *fmtstr,...) send text to the adam task 
to be displayed.

StreamPrintF(U8 *fmtstr,...) and StreamPutS(U8 *src) send text to the stream of 
code being compiled and must reside in a #exe{} blk.

GrPrintF(GrDC *dc,I64 x,I64 y,U8 *fmtstr,...) and GrPutS(GrDC *dc,I64 x,I64 y,U8 
*src) plots text in graphics mode.  GrVPrintF() and GrVPutS() will print 
vertically.

ExePrintF(U8 *fmtstr,...) and ExePutS(U8 *src) compile and execute a string.  
Note: It returns the result of the last executed expression.

Note: If no PutS variant is available, you can use PrintF("%s",src).


The PrintF() family supports extended format codes.  See SPrintFJoin().
  %[-][0][width][.decimals][flags][hsub_fmt][main_fmt]
  
  flags:
    * 't' is a flag which will truncate to field width.
    * ',' is a flag which will add commas every three digits in a %d, %f, %g, %e 
    and %n entries.
    * '$' is a flag which affects the %Q entry, converting '$' to "\044".
    * 'k' is a flag which forces 1000 instead of 1024 on integer with sub_fmts.
  
  sub_fmt:
    On date or time entries, the sub_format specifies the format.  See 
    ::/LT/Demo/DateTime.CPZ.
    
    On "%n", "%d" or "%u", the sub_fmt causes thousands mode.
      "%h?n" will pick a var exponent multiples of three unit, while "%h-3n", 
    for example, will display milli units or "%h6n" will display mega units.  
    The 'k' flag is always on for "%n".  See ::/LT/Demo/PrintF.CPZ.
  
  *  "%n" will print a floating point in engineering notation, exponents being 
  multiples of three.  If it has a sub_fmt code, it will display scientific 
  units letters.
  
  * "%S" will print a Define entry.
  
  * "%C" will print a ToUpper character.
  
  * "%F" will print a text file.
  
  * "%P" will display a PSECT expression which is good for ptrs or addresses.
  
  * "%T" and "%D" will display a date or time and the format is selected with a 
  subcode, entered after a "h".  Example: "%20h1D" uses date format code "1". 
  See ::/LT/Demo/DateTime.CPZ, MSPrintFDate() and MSPrintFTime() for subcodes.
  
  * "%z" will display a subentry of an enumerated list of text entries. It calls 
  ListEntryPoint().  Pass entry_num first, list second.
  
  * "%Z" will display a Define subentry.  Pass entry_num first, list_systext 
  second.
  
  * "%Q" will convert "\" to "\\" and quote to backslash quote. (For use in 
  creating strs in strs.)
  
  * "%q" will reverse a "%Q".