227 lines
14 KiB
Plaintext
227 lines
14 KiB
Plaintext
$WW,1$$FG,5$$TX+CX,"TempleOS C+"$$FG$
|
|
|
|
* See $LK,"Scoping and Linkages","FI:::/TempleOS/Doc/ImportExports.TXT"$ for details on $FG,2$extern$FG$, $FG,2$import$FG$, $FG,2$_extern$FG$, $FG,2$_import$FG$, etc.
|
|
|
|
* See $LK-A,"::/TempleOS/Doc/Directives.TXT"$.
|
|
|
|
* Built-in types include $FG,2$I0,I8,I16,I32,I64$FG$ for signed 0-8 byte ints and $FG,2$U0,U8,U16,U32,I64$FG$ for unsigned 0-8 byte ints and $FG,2$F64$FG$ for 8 byte floats.
|
|
|
|
$FG,2$ U0 void
|
|
I8 char
|
|
U8 unsigned char
|
|
I16 short
|
|
U16 unsigned short
|
|
I32 int
|
|
U32 unsigned int
|
|
I64 long (64-bit)
|
|
I64 unsigned long (64-bit)
|
|
F64 double$FG$
|
|
$FG,4$no F32 float.$FG$
|
|
|
|
* 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:
|
|
$ID,2$$FG,2$U0 Test(I64 i=4,I64 j,I64 k=5)
|
|
{
|
|
PrintF("%X %X %X\n",i,j,k);
|
|
}
|
|
|
|
Test(,3);$FG$
|
|
$ID,-2$
|
|
* A string or char constant all alone is sent to $LK,"PutS","MN:PutS"$() or $LK,"PutChar","MN:PutChar"$(). A string with args is sent to $LK,"PrintF","MN:PrintF"$(). An empty string literal signals a variable fmt_str follows.
|
|
|
|
$ID,2$$FG,2$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;
|
|
'*';
|
|
}
|
|
$FG$$ID,-2$
|
|
* When dealing with function addresses, precede the name with "$FG,2$&$FG$".
|
|
|
|
* There is no $FG,2$main()$FG$ function. Any code outside of functions gets executed on start-up, in order.
|
|
|
|
* You can access bytes or words within any int. $FG,2$i.u8[2]$FG$ returns bits 24-27 in the variable, $FG,2$i$FG$. See $LK,"I64 declaration","MN:I64"$. The real feature is that a class can be accessed as a whole, if you put a type in front of the $FG,2$class$FG$ declaration.
|
|
|
|
* Variable arg count functions ($FG,2$...$FG$) can access their args with built-in variables similar to '$FG,2$this$FG$' in C++. They are '$FG,2$I64 argc$FG$' and '$FG,2$I64 argv[]$FG$'.
|
|
$ID,2$$WW,0$
|
|
$FG,2$U0 GrPrintF(CDC *dc,I64 x,I64 y,U8 *fmt,...)
|
|
{
|
|
U8 *buf=SPrintFJoin(NULL,fmt,argc,argv);
|
|
GrPutS(dc,x,y,buf);
|
|
Free(buf);
|
|
}
|
|
$WW,1$$FG$$ID,-2$
|
|
* Allows "$FG,2$5<i<j+1<20$FG$" instead of "$FG,2$5<i && i<j+1 && j+1<20$FG$".
|
|
$ID,2$
|
|
$FG,2$if (13<=age<20)
|
|
"Teen-ager";
|
|
$FG$$ID,-2$
|
|
* $FG,2$switch$FG$ statements always use a jump table. Don't use them with cases with really big, sparse ranges.
|
|
|
|
* Allows ranges like "$FG,2$case 4...7:$FG$" in $FG,2$switch$FG$ statements.
|
|
|
|
* $FG,2$nobound_switch$FG$ 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.
|
|
|
|
* $FG,2$noreg$FG$ or $FG,2$reg$FG$ can be placed before a function local var name. You can, optionally, specify a register after the $FG,2$reg$FG$ keyword.
|
|
|
|
* $FG,2$interrupt$FG$, $FG,2$public$FG$, $FG,2$argpop$FG$ or $FG,2$noargpop$FG$ are function flags.
|
|
|
|
* A $FG,2$nounusedwarn$FG$ statement will suppress an unused var warning.
|
|
|
|
* You can have multiple member vars of a class named "$FG,2$pad$FG$" or "$FG,2$reserved$FG$", and it won't issue warnings.
|
|
|
|
* Type casting is postfix. To typecast int or F64, use $LK,"ToI64","MN:ToI64"$(), $LK,"ToBool","MN:ToBool"$() or $LK,"ToF64","MN:ToF64"$(). (TempleOS 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 "$FG,2$`$FG$" operator raises a base to a power.
|
|
|
|
* A single quote can encompass multiple characters. $FG,2$'ABC'$FG$ is equal to $FG,2$0x434241$FG$.
|
|
|
|
* $AN,"","OP_precedence"$TempleOS $LK,"operator precedence","FA:::/TempleOS/Compiler/CmpInit.CPP,OP_precedence"$
|
|
$FG,2$`$FG$,$FG,2$>>$FG$,$FG,2$<<$FG$
|
|
$FG,2$*$FG$,$FG,2$/$FG$,$FG,2$%$FG$
|
|
$FG,2$&$FG$
|
|
$FG,2$^$FG$
|
|
$FG,2$|$FG$
|
|
$FG,2$+$FG$,$FG,2$-$FG$
|
|
$FG,2$$FG,2$<$FG$,$FG,2$>$FG$,$FG,2$<=$FG$,$FG,2$>=$FG$
|
|
$FG,2$==$FG$,$FG,2$!=$FG$
|
|
$FG,2$&&$FG$
|
|
$FG,2$$FG,2$^^$FG$
|
|
$FG,2$||$FG$$FG$
|
|
$FG,2$:$FG$,$FG,2$?$FG$
|
|
$FG,2$=$FG$,$FG,2$<<=$FG$,$FG,2$>>=$FG$,$FG,2$*=$FG$,$FG,2$/=$FG$,$FG,2$&=$FG$,$FG,2$|=$FG$,$FG,2$^=$FG$,$FG,2$+=$FG$,$FG,2$-=$FG$
|
|
|
|
* You can use $LK,"OptOn","MN:OptOn"$($LK,"OPTf_WARN_PAREN","MN:OPTf_WARN_PAREN"$) to find unnecessary parentheses in code.
|
|
|
|
* You can use $LK,"OptOn","MN:OptOn"$($LK,"OPTf_WARN_DUP_TYPES","MN:OPTf_WARN_DUP_TYPES"$) to find dup local var type statements.
|
|
|
|
* With the $FG,2$#exe{}$FG$ feature in your src code, you can place programs that insert text into the stream of code being compiled. See $LK,"#exe {}","FF:::/TempleOS/Kernel/KEnd.CPP,#exe {"$ for an example where the date/time and compile-time prompting for cfguration data is placed into a program. The $LK,"StreamPrintF","MN:StreamPrintF"$() and $LK,"StreamPutS","MN:StreamPutS"$() place text into a src program stream following the conclusion of the $FG,2$#exe{}$FG$ blk.
|
|
|
|
* No $FG,2$#define$FG$ functions exist (I'm not a fan)
|
|
|
|
* No $FG,2$typedef$FG$, use $FG,2$class$FG$.
|
|
|
|
* No type-checking
|
|
|
|
* Can't use $FG,2$<>$FG$ with $FG,2$#include$FG$, use $FG,2$""$FG$.
|
|
|
|
* "$FG,2$$$$FG$" is an escape character. Two dollar signs signify an ordinary $$. See $LK-A,"::/TempleOS/Doc/Dollar.TXT"$. In $FG,2$asm$FG$ or $FG,2$C+$FG$ code, it also refers to the instruction's addr.
|
|
|
|
* $FG,2$union$FG$ is more like a class, so you don't reference it with a $FG,2$union$FG$ label after you define it. Some common unions are declared in $LK,"Adam1a.HPP","MN:U16"$ 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 $LK-A,"::/TempleOS/Demo/SubIntAccess.CPP"$.
|
|
|
|
* $FG,2$class$FG$ member vars can have meta data. $FG,2$fmtstr$FG$ and $FG,2$fmtdata$FG$ 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 $LK-A,"::/TempleOS/Demo/ClassMeta.CPP"$ and $LK,"DocFormDo","MN:DocFormDo"$().
|
|
|
|
* See $LK-A,"::/TempleOS/Demo/Exceptions.CPP"$. $FG,2$try{} catch{}$FG$ and $FG,2$throw$FG$ are different from C++. $FG,2$throw$FG$ is a function with var ("$FG,2$...$FG$") args. The values passed in $FG,2$throw()$FG$ can be accessed from within a $FG,2$catch{}$FG$ using the $FG,2$Fs->except_argc$FG$ and $FG,2$Fs->except_argv[]$FG$ vars. Within a $FG,2$catch {}$FG$ blk, set the var $FG,2$Fs->catch_except$FG$ to $FG,2$TRUE$FG$ if you want to terminate the search for a handler. By convention, the first arg of $FG,2$except_argv[]$FG$ specifies the exception type num. A list of assigned exception types can be found at $LK,"EXCEPT_LOCAL","MN:EXCEPT_LOCAL"$. For a handler that will catch all excepts, you can use $LK,"CatchAll","MN:CatchAll"$().
|
|
|
|
* A function is available similar to $FG,2$sizeof$FG$ which provides the offset of a member of a class. It's called $FG,2$offset$FG$. You place the class name and member inside as in $FG,2$offset(classname.membername)$FG$. It has nothing to do with 16-bit code. Both $FG,2$sizeof$FG$ and $FG,2$offset$FG$ only accept one level of member vars. That is, you can't do $FG,2$sizeof(classname.membername.submembername)$FG$.$FG$
|
|
|
|
* There is no $FG,2$continue$FG$ statement. Use $FG,2$goto$FG$.
|
|
|
|
* No bit field support, but there are bit access $LK,"library routines","HI:Bit"$.
|
|
|
|
* $FG,2$lock{}$FG$ can be used to apply asm $FG,2$LOCK$FG$ prefixes to code for safe multicore read-modify-write accesses. The code bracked with have $FG,2$LOCK$FG$ asm prefix's applied to relevant instructions within. It's a little shoddy. See $LK-A,"::/TempleOS/Demo/MultiCore/Lock.CPP"$.
|
|
|
|
* There is a function called $LK,"MSize","MN: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 $FG,2$MSize()$FG$ lets you know the real size and you can take full advantage of it.
|
|
|
|
* You can $LK,"Free","MN:Free"$() a $FG,2$NULL$FG$ ptr. Useful variants of $LK,"MAlloc","MN:MAlloc"$() can be found $LK,"Here","MN:CAlloc"$. Each task has a heap and you can $FG,2$MAlloc$FG$ and $FG,2$Free$FG$ off of other task's heaps, or make an independent heap with $LK,"HeapCtrlIndependentInit","MN:HeapCtrlIndependentInit"$().
|
|
|
|
* The stk does not grow because virtual mem is not used. I recommend allocating large local vars from the heap. You can change $LK,"DFT_STK","MN:DFT_STK"$ and recompile $FG,2$Kernel$FG$ or request more when doing a $LK,"Spawn","MN:Spawn"$(). You can use $LK,"CallStkGrow","MN:CallStkGrow"$(), but it's odd. See $LK-A,"::/TempleOS/Demo/StkGrow.CPP"$.
|
|
|
|
* Only one base class is allowed.
|
|
|
|
* All values are extended to 64-bit when accessed. Intermediate calculations are done with 64-bit values.
|
|
|
|
$ID,2$The follow examples should be inserted in a function, so that register variables are used. (Global vars are never register.)
|
|
|
|
$FG,2$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
|
|
|
|
I64 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
|
|
|
|
$ID,-2$$FG$
|
|
$FG,5$$TX+CX,"PrintF Family"$$FG$
|
|
|
|
$LK,"MSPrintF","MN:MSPrintF"$() is like $LK,"SPrintF","MN:SPrintF"$() but it returns a $LK+S,"MAlloc","MN:MAlloc"$ated str. It is vary handy because you don't have to worry about overflow.
|
|
|
|
$LK,"PutS","MN:PutS"$() doesn't print a new line.
|
|
|
|
$LK,"Auto","MN:Auto"$(U8 *fmtstr,...) sends text to the current task's input buffer.
|
|
$LK,"AutoStr","MN:AutoStr"$(U8 *fmtstr,...) sends text of an $LK,"AutoFile","FF:::/TempleOS/Doc/Glossary.TXT,AutoFile"$ to the keyboard stream of the current TASK but can also do mouse cmds.
|
|
|
|
$LK,"XTalk","MN:XTalk"$(CTask *task,U8 *fmtstr,...) and text to another task's input buffer.
|
|
$LK,"XTalkStr","MN:XTalkStr"$(CTask *task,U8 *fmtstr,...) sends text of an $LK,"AutoFile","FF:::/TempleOS/Doc/Glossary.TXT,AutoFile"$ to the keyboard stream of another TASK but can also do mouse cmds.
|
|
|
|
|
|
$LK,"DocPutS","MN:DocPutS"$(CDoc *doc,U8 *src) and $LK,"DocPrintF","MN:DocPrintF"$(CDoc *doc,U8 *fmtstr,...) send text to a linked text file. You can buffer to a Doc and save it, providing the functionality of $FG,2$fprintf$FG$. See $LK-A,"::/TempleOS/Demo/Dsk/FPrintF.CPP"$.
|
|
|
|
$LK,"Adam","MN:Adam"$(U8 *fmtstr,...) send text to the adam task to be compiled and run.
|
|
$LK,"AdamLog","MN:AdamLog"$(U8 *fmtstr,...) and $LK,"AdamErr","MN:AdamErr"$(U8 *fmtstr,...) send text to the adam task to be displayed.
|
|
|
|
$LK,"StreamPrintF","MN:StreamPrintF"$(U8 *fmtstr,...) and $LK,"StreamPutS","MN:StreamPutS"$(U8 *src) send text to the stream of code being compiled and must reside in a $FG,2$#exe{}$FG$ blk.
|
|
|
|
$LK,"GrPrintF","MN:GrPrintF"$(CDC *dc,I64 x,I64 y,U8 *fmtstr,...) and $LK,"GrPutS","MN:GrPutS"$(CDC *dc,I64 x,I64 y,U8 *src) plots text in graphics mode. $LK,"GrVPrintF","MN:GrVPrintF"$() and $LK,"GrVPutS","MN:GrVPutS"$() will print vertically.
|
|
|
|
$LK,"ExePrintF","MN:ExePrintF"$(U8 *fmtstr,...) and $LK,"ExePutS","MN:ExePutS"$(U8 *src) compile and execute a string. Note: It returns the result of the last executed expression.
|
|
|
|
$BK,1$Note:$BK,0$ If no $FG,2$PutS$FG$ variant is available, you can use $FG,2$PrintF("%s",src)$FG$.
|
|
|
|
|
|
$AN,"","PrintF_Codes"$The $LK,"PrintF","MN:PrintF"$() family supports extended format codes. See $LK,"SPrintFJoin","MN:SPrintFJoin"$().
|
|
$ID,2$$FG,2$%$FG$[$FG,2$-$FG$][$FG,2$0$FG$][$FG,5$width$FG$][$FG,2$.$FG,5$decimals$FG$][$FG,5$flags$FG$][$FG,2$h$FG,5$sub_fmt$FG$][$FG,5$main_fmt$FG$]
|
|
|
|
$FG,5$flags:$FG$
|
|
$ID,2$* $FG,2$'t'$FG$ is a flag which will truncate to field width.
|
|
* $FG,2$','$FG$ is a flag which will add commas every three digits in a $FG,2$%d$FG$, $FG,2$%f$FG$,$FG,2$ %g$FG$,$FG,2$ %e$FG$ and $FG,2$%n$FG$ entries.
|
|
* $FG,2$'$$'$FG$ is a flag which affects the $FG,2$%Q$FG$ entry, converting $FG,2$'$$'$FG$ to $FG,2$"\044"$FG$.
|
|
* $FG,2$'k'$FG$ is a flag which forces 1000 instead of 1024 on integer with $FG,5$sub_fmts$FG$.
|
|
$ID,-2$
|
|
$FG,5$sub_fmt:$FG$
|
|
$ID,2$On date or time entries, the sub_format specifies the format. See $LK-A,"::/TempleOS/Demo/DateTime.CPP"$.
|
|
|
|
$AN,"","sub_fmt"$On $FG,2$"%n"$FG$, $FG,2$"%d"$FG$ or $FG,2$"%u"$FG$, the sub_fmt causes thousands mode.
|
|
$FG,2$"%h?n"$FG$ will pick a var exponent multiples of three unit, while $FG,2$"%h-3n"$FG$, for example, will display milli units or $FG,2$"%h6n"$FG$ will display mega units. The $FG,2$'k'$FG$ flag is always on for $FG,2$"%n"$FG$. See $LK-A,"::/TempleOS/Demo/PrintF.CPP"$.
|
|
$ID,-2$
|
|
* $FG,2$"%n"$FG$ will print a floating point in engineering notation, exponents being multiples of three. If it has a $FG,5$sub_fmt$FG$ code, it will display scientific units letters.
|
|
|
|
* $FG,2$"%S"$FG$ will print a Define entry.
|
|
|
|
* $FG,2$"%C"$FG$ will print a ToUpper character.
|
|
|
|
* $FG,2$"%F"$FG$ will print a text file.
|
|
|
|
* $FG,2$"%P"$FG$ will display a PSECT expression which is good for ptrs or addresses.
|
|
|
|
* $FG,2$"%T"$FG$ and $FG,2$"%D"$FG$ will display a date or time and the format is selected with a subcode, entered after a "$FG,2$h$FG$". Example: "$FG,2$%20h1D$FG$" uses date format code "1". See $LK-A,"::/TempleOS/Demo/DateTime.CPP"$, $LK,"MSPrintFDate","MN:MSPrintFDate"$() and $LK,"MSPrintFTime","MN:MSPrintFTime"$() for subcodes.
|
|
|
|
* $FG,2$"%z"$FG$ will display a subentry of an enumerated list of text entries. It calls $LK+S,"LstEntryPt","MN:LstEntryPt"$(). Pass entry_num first, list second.
|
|
|
|
* $FG,2$"%Z"$FG$ will display a Define subentry. Pass entry_num first, lst_systext second.
|
|
|
|
* $FG,2$"%Q"$FG$ will convert "\" to "\\" and quote to backslash quote. (For use in creating strs in strs.)
|
|
|
|
* $FG,2$"%q"$FG$ will reverse a $FG,2$"%Q"$FG$.
|
|
$ID,-2$
|