Linoleum Syntax Highlighter Source Code
|
|
URI:
|
http://herbert.gandraxa.com/herbert/lsh_src.asp
|
|
Link template:
|
<a href="http://herbert.gandraxa.com/herbert/lsh_src.asp">Linoleum Syntax Highlighter Source Code</a>
|
|
|
Link symbols:
|
On current page |
On this site |
On external site |
Wikipedia article |
ZIP archive |
PDF |
E-Mail
|
Article
Organization
Home »
Linoleum Source Code »
Linoleum Syntax Highlighter »
Linoleum Syntax Highlighter Source Code
Scope
This is the source code of the Linoleum Syntax Highlighter, implemented in the
Linoleum programming language.
Author
Herbert Glarner
Source Code
(Linoleum Syntax Higlighter. Version 1.0. Copyright 2007 Herbert Glarner.)
(Creates a valid XHMTL file suitable to publish your Linoleum source code on
any web page.)
(INSTRUCTIONS:
1. Tell the name "file.txt" of your source code file in variable "lsh source".
2. Compile and run lsh.txt
3. Result is file "file.htm". OVERWRITES ALREADY EXISTING FILE!)
(*****************************************************************************)
"libraries"
(*****************************************************************************)
"directors"
program name = { Linoleum Syntax Highlighter };
unit = 32;
(=========================================================================)
(Test screen reflecting what's allocated and what's free)
(-------------------------------------------------------------------------)
display width = LSH SCREEN WIDTH;
display height = LSH SCREEN HEIGHT;
(=========================================================================)
(*****************************************************************************)
"constants" (Convention: "LSH ...", UPPER CASE)
LSH SCREEN WIDTH = 512;
LSH SCREEN HEIGHT = 16;
LSH ACTUAL UNIT SIZE = 512; (Write 2 kB at a time)
(Parser states. Stored in [lsh states]. 1=Set, 0=Clear.)
LSH STATE LABEL = 00 00 00 01h; (Currently parsing label)
LSH STATE STRING = 00 00 00 02h; (Currently parsing string)
LSH STATE IS SYMBOL = 00 00 00 04h; (Currently parsing operators)
LSH STATE LINK TO START = 00 00 00 08h; (Link starts after whitespace)
LSH STATE LINK PENDING = 00 00 00 10h; (Link waits to be closed at ;)
LSH STATE IS PERIOD = 00 00 00 20h;
(*****************************************************************************)
"variables" (Convention: "lsh ...", lower case)
(Parser states which need to have matching nesting.)
lsh comment depth = 0; (Nesting level of brackets)
(=========================================================================)
(Name of the file with the source code.)
(-------------------------------------------------------------------------)
lsh source = { lsh.txt };
(=========================================================================)
(=========================================================================)
(File handling.)
(-------------------------------------------------------------------------)
lsh extension dot = 0;
lsh actual bit = 0; (Bit of lsh actual unit, is 0,8,16,24)
lsh actual unit offset = 0; (Byte of lsh actual unit)
lsh buffer size = LSH ACTUAL UNIT SIZE;
(=========================================================================)
(=========================================================================)
(Holds the address where the actual file is read into.)
(-------------------------------------------------------------------------)
lsh source code = 0; (Expanded format, 1 char/unit)
lsh source file = 0; (Actual file, 4 chars/unit)
(=========================================================================)
(=========================================================================)
(RAM pointer before memory allocation.)
(-------------------------------------------------------------------------)
lsh old ram top = 0;
(=========================================================================)
(=========================================================================)
(Progressbar counter. Counts from 0 to 511. Reflects portion done.)
(-------------------------------------------------------------------------)
lsh progress = 0;
(=========================================================================)
(=========================================================================)
(Parser States)
(-------------------------------------------------------------------------)
lsh states = 0; (see constants LST STATE XXX)
(=========================================================================)
(=========================================================================)
(Constant texts to stream out.)
(-------------------------------------------------------------------------)
(The header, consisting of the CSS and the top level tag <pre>.)
(-------------------------------------------------------------------------)
lsh out header = {
<style_type="text/css"> \cr \lf
\ta .linoleum_.cmt_{color:#008000; \cs \cr \lf
\ta .linoleum_.lbl_{color:#FF0000; \cs \cr \lf
\ta .linoleum_.str_{color:#808080; \cs \cr \lf
\ta .linoleum_.sym_{color:#800000; \cs \cr \lf
\ta .linoleum_a:link_{text-decoration:none; color:#0000FF; \cs \cr \lf
\ta .linoleum_a:visited_{text-decoration:none; color:#0000FF; \cs \cr \lf
\ta .linoleum_a:hover_{text-decoration:underline; color:#0000FF; \cs \cr \lf
\ta .linoleum_a:active_{text-decoration:none; color:#0000FF; \cs \cr \lf
\ta .linoleum_a:focus_{text-decoration:none; color:#0000FF; \cs \cr \lf
</style> \cr \lf
<pre_class="linoleum"> \cr \lf
};
(-------------------------------------------------------------------------)
(Tags)
(-------------------------------------------------------------------------)
lsh out spanend = { </span> };
lsh out cmt = { <span_class="cmt"> };
lsh out lbl = { <span_class="lbl"> };
lsh out str = { <span_class="str"> };
lsh out sym = { <span_class="sym"> };
lsh out name start = { <a_id=" };;
lsh out name end = { "></a> };
lsh out link start = { <a_href="# };
lsh out link end = { "> };
lsh out link close = { </a> };
lsh out bold start = { <b> };
lsh out bold end = { </b> };
(-------------------------------------------------------------------------)
(Entities)
(-------------------------------------------------------------------------)
lsh out smaller than = { < };
lsh out greater than = { > };
lsh out amp = { & };
(-------------------------------------------------------------------------)
(The footer, output ends with this.)
(-------------------------------------------------------------------------)
lsh out footer = {
</pre> \cr \lf
<p_class="smallprint"_style="margin-top:0px;">
Linoleum_Syntax_Highlighting_produced_with_
<a_href="lsh.asp">LSH</a>_
(©_2007_by_Herbert_Glarner)
</p> \cr \lf
};
(=========================================================================)
(=========================================================================)
(The names of the 'periods')
(-------------------------------------------------------------------------)
lsh periods = {libraries};
{stockfile};
{directors};
{constants};
{variables};
{workspace};
{programme};
(=========================================================================)
(=========================================================================)
(All symbols which qualify as operators, be it alone or together with
other symbols.)
(-------------------------------------------------------------------------)
lsh symbols = { !-<>=$+-~/|:&#@*%,^[] };
(=========================================================================)
(=========================================================================)
(A tab is replaced with 4 blanks - 8 blanks as by default in Firefox is
too much.)
(-------------------------------------------------------------------------)
lsh tab to blanks = { ____ };
(=========================================================================)
(*****************************************************************************)
"workspace" (Convention: "lsh ...", lower case)
(=========================================================================)
(Display area)
(-------------------------------------------------------------------------)
lsh window = LSH SCREEN WIDTH mtp LSH SCREEN HEIGHT;
(=========================================================================)
(=========================================================================)
(Output buffer)
(-------------------------------------------------------------------------)
lsh actual unit = LSH ACTUAL UNIT SIZE; (At 4 bytes per unit)
(=========================================================================)
(=========================================================================)
(Collecting label name. Lino can have arbitrary long names. I doubt that
someone uses more than 1000 characters though. Not even sure if technically
allowed. If it's less, we can give a shorter number here.)
(-------------------------------------------------------------------------)
lsh label name = 1000; (At 1 character per unit)
(=========================================================================)
(*****************************************************************************)
"programme" (Convention: "Lsh ...", Mixed case)
(=========================================================================)
(Screen init)
(-------------------------------------------------------------------------)
[Display Origin] = lsh window; (Defined in the workspace area)
(=========================================================================)
(=========================================================================)
(Expanding the source code file such, that it is held into a RAM area
occupying 1 unit per source code character.)
(-------------------------------------------------------------------------)
(Check if file exists.)
[File Name] = lsh source;
[File Command] = TEST;
isocall;
? ok -> Lsh Source File Found;
A = 100000; (Error Code)
-> Lsh Stop;
"Lsh Source File Found"
(-------------------------------------------------------------------------)
(Check if we may read the file)
? [File Status] + PERMIT TO READ -> Lsh Source File Readable;
A = 100001; (Error Code)
-> Lsh Stop;
"Lsh Source File Readable"
(-------------------------------------------------------------------------)
(Save the current TopOfRam before we reserve some space to read in the
source file. TopOfRam is reset to this on termination.)
[lsh old ram top] = [RAM Top];
(-------------------------------------------------------------------------)
(Reserve space to read in the source file. Reading in means 4 bytes/unit.
For efficiency, we want to process 1 character/unit, though. This means,
that we allocate 2 RAM-blocks: one for the compact form and one for the
expanded form. First the block for thr larger expanded form is reserved:
this one is to stay during program execution. The smaller compact form is
used only to convert the file into the larger expanded form: its memory is
returned to the OS after that is done.)
[lsh source code] = [RAM Top]; (To here we expand the file)
[RAM Top] + [File Size]; (One unit per source code character)
(Immediately after this the RAM for the actual file is reserved.)
[lsh source file] = [RAM Top]; (To here we read the source file)
(The source file requires {Bytes+3}/4 units of RAM.)
C = [File Size];
C + 3;
C > 2;
[RAM Top] + C; (4 source code chars per unit)
(Now allocate the RAM.)
isocall;
? ok -> Lsh Ram Allocated;
A = 100002; (Error Code)
-> Lsh Stop;
"Lsh Ram Allocated"
(-------------------------------------------------------------------------)
(The testfile is read into RAM, starting at 'lsh source file'.)
[Block Pointer] = [lsh source file]; (Buffer holding the whole file)
[File Command] = READ;
[File Position] = ZERO;
[Block Size] = [File Size]; (In Bytes)
isocall;
? ok -> Lsh File Read;
A = 100003; (Error Code)
-> Lsh Stop;
"Lsh File Read"
(-------------------------------------------------------------------------)
(Convert the file into the expanded format, i.e. 1 unit per source code
character. Since this is Little Endian, we process from right to left.)
A = 0; (No expanded bytes yet)
B = [lsh source code]; (Target address)
C = [lsh source file]; (Source address containing 4 bytes)
"Lsh Expand File"
D = [C]; (The 4 bytes)
(Store the 4 bytes into 4 units, LSB first.)
E = D; E & FFh; [B] = E; B + 1; D > 8;
E = D; E & FFh; [B] = E; B + 1; D > 8;
E = D; E & FFh; [B] = E; B + 1; D > 8;
E = D; E & FFh; [B] = E; B + 1;
(Next unit with up to 4 characters)
A + 4; (4 additional bytes were expanded)
C + 1; (Next source code unit with 4 chars)
? A < [File Size] -> Lsh Expand File;
(-------------------------------------------------------------------------)
(Starting at 'lsh source code' is the expanded file now, i.e. 1 unit per
character. The compact file is not needed any longer and its RAM could be
returned to the OS; however, we need some space to create the lines of the
output file, and that area seems to be suitable.)
(=========================================================================)
(=========================================================================)
(Processing the expanded source code file.)
(-------------------------------------------------------------------------)
(The outputfile's extwension changes from .txt to .htm. From 'lsh source'
search forward til a NUL unit is met and while doing so register the
position of the last found dot.)
A = pragma lsh source;
[lsh extension dot] = 0; (No dot so far)
"Lsh Search End Of Filename"
? [A] = 0 -> Lsh Found End Of Filename;
? [A] != 2Eh -> Lsh Not Extension Dot;
[lsh extension dot] = A; (Address of last found dot)
"Lsh Not Extension Dot"
A + 1;
-> Lsh Search End Of Filename;
"Lsh Found End Of Filename"
(Now replace the extension .txt with .htm while making sure that there
really is such an extension. If not we stop with error: only .txt files
will be processed.)
? [lsh extension dot] != 0 -> Lsh Has Extension Dot;
A = 100004; (Error Code)
-> Lsh Stop;
"Lsh Has Extension Dot"
A = [lsh extension dot];
? [A plus 1] != 74h -> Lsh Invalid Extension;
? [A plus 2] != 78h -> Lsh Invalid Extension;
? [A plus 3] != 74h -> Lsh Invalid Extension;
? [A plus 4] = 0 -> Lsh Valid Extension;
"Lsh Invalid Extension" (Must be '.txt')
A = 100005; (Error Code)
-> Lsh Stop;
"Lsh Valid Extension" (Is '.txt')
[A plus 1] = 68h; ('htm')
[A plus 2] = 74h;
[A plus 3] = 6Dh;
(-------------------------------------------------------------------------)
(Create an output file. The file name root is the same, only the extension
changes.)
[File Command] = WRITE; (creates new file if it doesn't exist)
[File Position] = ZERO; ([re]write from the beginning of the file)
[Block Pointer] = pragma lsh actual unit;
[Block Size] = ZERO; (Just creating, not writing yet)
isocall;
[File Command] = SET SIZE;
[File Size] = ZERO;
isocall;
[lsh actual bit] = 0; (Starting with rightmost byte)
(-------------------------------------------------------------------------)
(First writing the CSS styles and the opening <pre> tag. The text starts
in 'lsh out header'. It goes until a NUL is met.)
E = pragma lsh out header;
=> Lsh Out Preformatted;
(=========================================================================)
(=========================================================================)
(Parsing the file. Lino has no complex syntax, so we can refrain from
writing a real parser.)
(-------------------------------------------------------------------------)
(Let's process one character after the other. The first character is at
'lsh source code', the last character before 'lsh source file'. The
difference is the number of characters.)
B = [lsh source file];
B - [lsh source code]; (Number of characters in B)
C = B; (Total number of chars)
(B has the number of still unprocessed characters, C has the total number
of characters. B/C = 1...0 is still unprocessed. The width of the progress
bar is 512 pixels. To advance 1 pixel we need to process C/512 characters.
D counts chars from 0 on. At C/512 we update the progress bar, i.e. make it
1 pixel wider.)
C > 9; (So many characters per pixel)
D = 0; (0 chars processed.)
[lsh progress] = 0; (0 pixel width of done-Part)
E = [lsh source code]; (Address first character)
(show registers;)
(-------------------------------------------------------------------------)
(Depending on what syntactical element we are parsing, appropriate <span>
tags will surround the element.)
"Lsh Process Character"
(-------------------------------------------------------------------------)
(Does the actual character start a new syntactical element? If so, a span
is printed first.)
(If we currently process a label, then we output the character, whatever
it is.)
? [lsh states] + LSH STATE LABEL -> Lsh Only Character;
(If we currently process a string, then we output the character, whatever
it is.)
? [lsh states] + LSH STATE STRING -> Lsh Only Character;
(If we currently process a comment, then we output the character, whatever
it is.)
? [lsh comment depth] > 0 -> Lsh Only Character;
(If we wait for a link to start, then we start it as soon as the current
character is not a whitespace character.)
? [lsh states] - LSH STATE LINK TO START -> Lsh No Link To Start;
? [E] = 09h -> Lsh Only Character; (Tab)
? [E] = 0Ah -> Lsh Only Character; (LF)
? [E] = 0Dh -> Lsh Only Character; (CR)
? [E] = 20h -> Lsh Only Character; (Space)
-> Lsh Link Starts; (Before this char the link starts)
"Lsh No Link To Start"
(If we currently process a link, then we need to close the link when a ;
is met.)
? [lsh states] - LSH STATE LINK PENDING -> Lsh Not Processing Link;
? [E] != 3Bh -> Lsh Not Processing Link;
E -->; E = lsh out link close; => Lsh Out Preformatted; <-- E;
[lsh states] & FFFFFFFFh minus LSH STATE LINK PENDING;
-> Lsh Only Character;
"Lsh Not Processing Link"
(Do we start to process a label right now?)
? [E] = 22h -> Lsh Label Start; (")
(Do we start to process a string right now?)
? [E] = 7Bh -> Lsh String Start; ({)
(Do we start to process a comment right now?)
? [E] = 28h -> Lsh Comment Start; (Bracket Open)
(If we currently process a ">", then we check if it's a jump or call. If
it is, then the following name will become a link. After ^ there always
follows a link.)
? [E minus 1] = 5Eh -> Lsh Is Link; (^)
? [E] != 3Eh -> Lsh No Link;
? [E minus 1] = 2Dh -> Lsh Possibly Link; (->, but not for -->)
? [E minus 1] = 3Dh -> Lsh Is Link; (=>)
-> Lsh No Link;
"Lsh Possibly Link"
? [E minus 2] != 2Dh -> Lsh Is Link; (->, but not -->)
"Lsh No Link"
-> Lsh Only Character;
"Lsh Label Start"
(Starting to process a label. Format the string including the start quote.)
[lsh states] | LSH STATE LABEL;
=> Lsh Collect Label Name; (Copy name to 'lsh label name')
E -->; E = pragma lsh out lbl; => Lsh Out Preformatted; <-- E;
(If the collected name is one of the 'Periods', then it is output in bold.
The following testing routine sets the flag LSH STATE IS PERIOD in the
variable [lsh states] if this is so.)
=> Lsh Test For Period Name;
? [lsh states] - LSH STATE IS PERIOD -> Lsh No Period Start;
E -->; E = pragma lsh out bold start; => Lsh Out Preformatted; <-- E;
"Lsh No Period Start"
=> Lsh Pack Character; (Output the quote)
E -->; E = pragma lsh out name start; => Lsh Out Preformatted; <-- E;
E -->; E = pragma lsh label name; => Lsh Out Preformatted; <-- E;
E -->; E = pragma lsh out name end; => Lsh Out Preformatted; <-- E;
-> Lsh Next Character;
"Lsh Comment Start"
[lsh comment depth] = 1;
E -->; E = pragma lsh out cmt; => Lsh Out Preformatted; <-- E;
=> Lsh Pack Character; (Output the opening bracket)
-> Lsh Next Character;
"Lsh String Start"
E -->; E = pragma lsh out str; => Lsh Out Preformatted; <-- E;
=> Lsh Pack Character; (Output the opening bracket)
-> Lsh Next Character;
"Lsh Is Link" (-> or => encountered)
=> Lsh Pack Character; (Output the >)
=> Lsh Collect Label Name; (Copy name to 'lsh label name')
[lsh states] | LSH STATE LINK TO START; (Start after whiteblank)
-> Lsh Next Character;
"Lsh Link Starts"
E -->; E = pragma lsh out link start; => Lsh Out Preformatted; <-- E;
E -->; E = pragma lsh label name; => Lsh Out Preformatted; <-- E;
E -->; E = pragma lsh out link end; => Lsh Out Preformatted; <-- E;
=> Lsh Pack Character; (Output the character)
[lsh states] & FFFFFFFFh minus LSH STATE LINK TO START;
[lsh states] | LSH STATE LINK PENDING; (Close before next ;)
-> Lsh Next Character;
(-------------------------------------------------------------------------)
"Lsh Only Character"
(A tab is replaced with 4 blanks - 8 blanks as by default in Firefox is
too much.)
? [E] != 09h -> Lsh Is Not Tab;
E -->; E = pragma lsh tab to blanks; => Lsh Out Preformatted; <-- E;
-> Lsh Char Packed;
"Lsh Is Not Tab"
(A "<" is replaced by the HTML entiry "<")
? [E] != 3Ch -> Lsh Is Not Smaller Than;
E -->; E = pragma lsh out smaller than; => Lsh Out Preformatted; <-- E;
-> Lsh Char Packed;
"Lsh Is Not Smaller Than"
(And a ">" by the HTML entiry ">")
? [E] != 3Eh -> Lsh Is Not Greater Than;
E -->; E = pragma lsh out greater than; => Lsh Out Preformatted; <-- E;
-> Lsh Char Packed;
"Lsh Is Not Greater Than"
(Also, an "&" is replaced by the HTML entiry "&")
? [E] != 26h -> Lsh Simple Char;
E -->; E = pragma lsh out amp; => Lsh Out Preformatted; <-- E;
-> Lsh Char Packed;
"Lsh Simple Char"
(Output the character just as it is:)
=> Lsh Pack Character; (Output the character)
"Lsh Char Packed"
(-------------------------------------------------------------------------)
(Does the actual character end a begun syntactical element? If so, a span
is printed after it.)
(If we currently process a label and just output a quote, then this quote
ends the label, unless we are in a comment block.)
? [E] = 22h -> Lsh Label End; (")
(If we currently process a string and just output a }, then this bracket
ends the string, unless we are in a comment block.)
? [E] = 7Dh -> Lsh String End; (})
(If we currently are processing a comment, then we need to keep track of
the nested brackets. If it drops to 0, this ends the comment.)
? [E] = 28h -> Lsh Comment Deeper; (Additional nesting level)
? [E] = 29h -> Lsh Comment Shallower; (One nesting level less)
-> Lsh Next Character;
"Lsh String End"
(Not ending the string if we are in a comment)
? [lsh comment depth] > 0 -> Lsh Next Character;
[lsh states] & FFFFFFFFh minus LSH STATE STRING;
E -->; E = pragma lsh out spanend; => Lsh Out Preformatted; <-- E;
-> Lsh Next Character;
"Lsh Label End"
? [lsh comment depth] > 0 -> Lsh Next Character;
[lsh states] & FFFFFFFFh minus LSH STATE LABEL;
(If this label was a 'period' name, we need to end the bolding now.)
? [lsh states] - LSH STATE IS PERIOD -> Lsh No Period End;
E -->; E = pragma lsh out bold end; => Lsh Out Preformatted; <-- E;
[lsh states] & FFFFFFFFh minus LSH STATE IS PERIOD;
"Lsh No Period End"
(End of Label)
E -->; E = pragma lsh out spanend; => Lsh Out Preformatted; <-- E;
-> Lsh Next Character;
"Lsh Comment Deeper"
[lsh comment depth] + 1;
-> Lsh Next Character;
"Lsh Comment Shallower"
[lsh comment depth] - 1;
? [lsh comment depth] > 0 -> Lsh Next Character;
(Nesting level 0 now: this ends a nested comments block)
E -->; E = pragma lsh out spanend; => Lsh Out Preformatted; <-- E;
-> Lsh Next Character;
(-------------------------------------------------------------------------)
"Lsh Next Character"
D + 1;
? D < C -> Lsh No Progressbar Update;
(Draw vertical line at x coordinate [lsh progress] = 0...511. A vertical
line has 16 pixels.)
? [lsh progress] >= 512 -> Lsh No Progressbar Update; (No overflow)
A -->; B -->;
A = pragma lsh window;
A + [lsh progress];
B = LSH SCREEN HEIGHT;
"Lsh Progressbar Update"
[A] = 0000FFh;
A + LSH SCREEN WIDTH;
B ^ Lsh Progressbar Update;
<-- B; <-- A;
(Show the progressbar)
[Display Command] = RETRACE;
isocall;
[lsh progress] + 1; (1 pixel wider of done part.)
D = 0; (Start to count again)
"Lsh No Progressbar Update"
(-------------------------------------------------------------------------)
E + 1; (Next character to process)
B ^ Lsh Process Character; (Process if not end yet)
(=========================================================================)
(=========================================================================)
(Writing the closing </pre> tag. This ends the output file.)
(-------------------------------------------------------------------------)
E = pragma lsh out footer;
=> Lsh Out Preformatted;
(=========================================================================)
(=========================================================================)
(Write the last incomplete buffer portion)
(-------------------------------------------------------------------------)
[File Command] = WRITE;
A = [lsh actual unit offset]; A < 2; (Complete units at 4 bytes each)
B = [lsh actual bit]; B > 3; (0...3 bytes last unit)
A + B;
[Block Size] = A;
isocall;
(=========================================================================)
(Terminating. Let's fall through.)
(-> Lsh Exit;)
(*************************************************************************)
(IV. TERMINATING)
(*************************************************************************)
(=========================================================================)
(Address we jump to if all was fine.)
(-------------------------------------------------------------------------)
"Lsh Exit"
(-------------------------------------------------------------------------)
(Return the allocated memory to the OS.)
[RAM Top] = [lsh old ram top];
isocall;
(-------------------------------------------------------------------------)
(A = 0 = Everything Ok)
A = 0;
show registers;
(=========================================================================)
(=========================================================================)
(Address we jump to if there is an error. In A is the error code.)
(-------------------------------------------------------------------------)
"Lsh Stop"
show registers;
(=========================================================================)
(*****************************************************************************)
"Lsh Out Preformatted"
(=========================================================================)
(Input:
E: Start of outputstring, 1 unit per character, terminated with 0
Output:
String at 4 bytes/unit)
(-------------------------------------------------------------------------)
"Lsh Out Preformatted Process"
(Check if we have the NUL character. If so we're done.)
? [E] = 0 -> Lsh Out Preformatted Exit;
(Compress 32-bit-character in [E] into appropriate byte in unit [D].)
=> Lsh Pack Character;
(Continue with next character)
E + 1;
-> Lsh Out Preformatted Process;
"Lsh Out Preformatted Exit"
leave;
(=========================================================================)
(*****************************************************************************)
"Lsh Pack Character"
(=========================================================================)
(Input:
E: Address of unit with 32-bit-Character in it
[lsh actual unit]:
Address of unit into which a byte is selected to take char in [E]
Note that [lsh actual unit] has LSH ACTUAL UNIT SIZE units and is
effectively written when all units at 4 bytes each have been packed,
i.e. when [lsh actual bit] overflows from 24 to 0 and [lsh actual
unit offset] is on max.
[lsh actual bit]:
The appropriate byte of [lsh actual unit] is selected as per
content of [lsh actual bit], which contains 0, 8, 16, 24, 0 ...
Output:
String at 4 bytes/unit)
(-------------------------------------------------------------------------)
A -->; B -->;
(Format character for output)
A = [E]; (Character to write)
A & FFh; (Make sure it's an ANSI character)
A < [lsh actual bit]; (Put into position)
B = pragma lsh actual unit;
B + [lsh actual unit offset];
[B] | A; (Mix into output unit)
(-------------------------------------------------------------------------)
(Prepare for next character in unit)
[lsh actual bit] + 8; (8 bits to the left)
(-------------------------------------------------------------------------)
(If we already have 4 bytes in [lsh actual unit] then we switch to the
next unit.)
? [lsh actual bit] < 32 -> Lsh Pack Character Exit;
(Next time we use the next Unit)
[lsh actual bit] = 0;
[lsh actual unit offset] + 1;
(However, if the just done write filled the whole buffer, i.e. its last
byte of the last unit, then we output that buffer now.)
? [lsh actual unit offset] < [lsh buffer size]
-> Lsh Pack Character Exit;
[lsh actual unit offset] = 0;
(Write the buffer.)
[File Command] = WRITE;
A = [lsh buffer size]; A < 2; (In bytes)
[Block Size] = A;
isocall;
(Next time skip the just written bytes before writing again.)
[File Position] + A; (In bytes)
(Clear the whole buffer for next batch)
B = [lsh buffer size];
A = pragma lsh actual unit;
"Lsh Pack Character Clear Buffer"
[A] = 0;
A + 1;
B ^ Lsh Pack Character Clear Buffer;
"Lsh Pack Character Exit"
<-- B; <-- A;
leave;
(=========================================================================)
(*****************************************************************************)
"Lsh Collect Label Name"
(=========================================================================)
A -->; B -->;
(E currently points on a quote " or a greater sign >. We want to start with
the position after that symbol.)
A = E;
A + 1;
(From A we copy characters as long as we either meet a " to close a label,
a ; to close a jump or sub instruction, or an opening bracket to open a
comment. We copy all character except Tabs and Blanks. We copy into the
workspace area 'lsh label name'.)
B = pragma lsh label name;
"Lsh Collect Label Name Copy"
? [A] = 22h -> Lsh Collect Label Name Exit; (Quote)
? [A] = 28h -> Lsh Collect Label Name Exit; (Semicolon)
? [A] = 3Bh -> Lsh Collect Label Name Exit; (Opening bracket)
? [A] = 09h -> Lsh Collect Label Name Next; (Tab)
? [A] = 20h -> Lsh Collect Label Name Next; (Space)
[B] = [A]; (Copy character)
B + 1; (Next target position)
"Lsh Collect Label Name Next"
A + 1; (Next source character)
-> Lsh Collect Label Name Copy;
"Lsh Collect Label Name Exit"
[B] = 0; (Last character of copied name)
<-- B; <-- A;
leave;
(=========================================================================)
(*****************************************************************************)
"Lsh Test For Period Name"
(=========================================================================)
(If the collected name is one of the 'Periods', then it is output in bold.
The following testing routine sets the flag LSH STATE IS PERIOD in the
variable [lsh states] if this is so.)
(-------------------------------------------------------------------------)
A -->; B -->; C -->; D -->; E -->;
B = pragma lsh periods; (Address of first 'period' name)
(Check [A] with [B] until no match or 10 matching chars. In the latter case
it is a 'period' name, in the former it is not and the next period name is
checked.)
E = 0; ('Period' names counter)
"Lsh Test For Period Check Period"
A = pragma lsh label name; (Name to test)
C = B; (Start of current period name)
D = 0; (No matching chars so far)
"Lsh Test For Period Check Character"
? [A] != [C] -> Lsh Test For Period Name No Period;
(A character matched. Check if next matches as well. 10 chars must match
for the two to be identical.)
D + 1; (One more matching char)
A + 1; C + 1; (Next addresses to check)
? D < 10 -> Lsh Test For Period Check Character;
(10 characters matched. This name is a period name.)
[lsh states] | LSH STATE IS PERIOD;
-> Lsh Test For Period Name Exit;
"Lsh Test For Period Name No Period"
(Check next period if any. There are only 7 periods.)
E + 1; (A period more. There are 7.)
B + 10; (10 characters later)
? E < 7 -> Lsh Test For Period Check Period;
"Lsh Test For Period Name Exit"
<-- E; <-- D; <-- C; <-- B; <-- A;
leave;
(=========================================================================)
(*****************************************************************************)
"Lsh Test For Symbol"
(=========================================================================)
(If the actual character in [E] is an operator symbol, then the flag
LSH STATE IS SYMBOL in the variable [lsh states], else the flag is cleared.
The symbols are in the variable [lsh symbols], 1 unit per symbol,
terminated with NUL.)
(-------------------------------------------------------------------------)
A -->;
A = pragma lsh symbols;
"Lsh Test For Symbol Check Symbol"
? A = 0 -> Lsh Test For Symbol No Symbol; (Is not a symbol)
? [A] = [E] -> Lsh Test For Symbol Is Symbol; (Is a symbol)
A + 1; (Check next symbol)
-> Lsh Test For Symbol Check Symbol;
"Lsh Test For Symbol Is Symbol"
[lsh states] | LSH STATE IS SYMBOL;
-> Lsh Test For Symbol Exit;
"Lsh Test For Symbol No Symbol"
[lsh states] & FFFFFFFFh minus LSH STATE IS SYMBOL;
(-> Lsh Test For Symbol Exit;)
"Lsh Test For Symbol Exit"
<-- A;
leave;
(=========================================================================)
(*****************************************************************************)
Linoleum Syntax Highlighting produced with LSH (© 2007 by Herbert Glarner)