A Grail Millennium Project
White Paper
This document is maintained by the author, Lewis A. Sellers, somewhere in the mountains of East Tennessee, the United States of America. It is an informal technical document for a works in progress project called Grail Millennium, or fully, The Minimal Operating System of Object Class Interfaces Holy Grail for the Millennium. In other words, for a new, easy to use, long-lived operating system.
Copyright Notice
This document and all material therein, unless otherwise stated, is Copyright © 1995,1996, Lewis A. Sellers. All Rights Reserved. Permission to distribute this document, in part or full, via electronic means (emailed, posted or archived) or printed copy are granted providing that no charges are involved, reasonable attempt is made to use the most current version, and all credits and copyright notices are retained.
Distribution Rights
All requests for other distribution rights, including incorporation in commercial products, such as books, magazine articles, CD-ROMs, and or computer programs should be made to the primary author Lewis Sellers.
Warranty and disclaimer
This document is provided as is without any express or implied warranties. This is a work-in-progress, and as such will contain outdated or as yet uncorrected or substanstiated assumptions. The author, maintainer and/or contributors assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.
WWW Home Sites
You can currently find home sites to this project at If you can not reach them, or they seem to be down, do a key word search on AltaVista, Lycos, or the Web Crawler search engines.
Contact Email
The primary author of Grail Millennium should be reachable at lsellers@usit.net.
OCI/Spec | S C R I P T
DESIGNER
Lewis A. Sellers (aka Minimalist) lsellers@usit.net
CRITIQUED BY
- Akintunde Omitowoju tunde@housing.east-tenn-st.edu (a0.01)
- Luc Stepniewski stepniew@isty-info.uvsq.fr (a.001)
DRAFTS
- ? v0
- 1/24/96 revision 0.0
- 2/6/96 revision 0.01
- 2/16/96 revision 0.02 (redress)
- 7/31/96 revision 0.03 (begin for www 0.12...)
(a0.03)
Table of Contents
Legal Notices Who gets sued and why History Changes and who made them Preface About this document and the people that make it
Overview An Overview of the Script
An Overview of the Script
BY | Lewis A. Sellers lsellers@usit.net As you know by now Grail lives and dies on the concept of objects. Most the documents to this point have talked about precompiled object classes. But that is not all....
Down in current or default User Resource File there is an area called SCRIPT_LANGUAGES. There you can define file types that should be treated as executables even though they are not. GrailScript, as well as the familiar Perl, are script languages. That is, they are plaintext documents that contain code that is not precompiled. If you were try to load a GrailScript document like an object, the __SCRIPT object would be loaded and the name of the document passed to it. It would then be converted to assembly language and the Grail Assembler would finish compiling it into an object direct to memory.
This is not to say that a script language can not be interpreted (like BASIC) or other than plaintext (such as the byte-coded JAVA by Sun Microsystems), just that GrailScript is not.
With GrailScript the file is compiled into a binary executable which is left in memory just like, as was said, any other object. This compilation is temporary. If the object is discarded, then so is the binary image of the script. Thus, they are not the fastest thing on the earth, but they should be completely cross-platform portable and work on any Grail system. People who might write scripts are librarians, site maintainers, museums, governments, etc. :) People who don't write applications in script are generally in the entertainment field.
Further, the use of grail script is fairly ideal for those putting out CD-ROM's which are archival in nature (images, texts, etc) or that accompany movies with behind-the-scenes notes, images, sounds, etc. You can have write the presentation program in platform-neutral SCRIPT and have it work on anything that runs Grail.
The script language is a relatively simple thing being somewhat akin to C and Perl. You can declare variables that are scoped, as well as create functions for objects and call the functions of other objects. All objects and functions are references by their native nomenclature.
The function names creation, and destruction are special, and exist in all scripts. The main function exists only in object that are meant to run in and of themselves. The function creation is executed after an __OBJECT_Request and it's return value is passed back as the return. The __OBJECT_Discard executes the destruction function before preceding. The return value should ways be an integer. Creation and Destruction MUST exist or an __OBJECT_Request will abort.
On a side note: Around the beginning of 1996 I became aware of Java by Sun Microsystems and JavaScript by Sun and Netscape. After examining the documentation on them it became clear that much more work should go into allowing a task or object to be nearly hermetically isolated from the rest of the system. Though they did not influence the design of Grail significantly (the Grail APIs were near final solidification by the time they came about) their existence was responsible for the addition of the hermetic object policies.
Anyway, now you know why the Grail Assembler is included with all versions of Grail. After __SCRIPT (or __SCRIPT/PERL, etc) has converted code to assembly source, then GA creates a Grail compat binary in the current module format directly to memory.
I suppose it's a little strange to have script language support built directly into a kernel... but Grail is a little unusual anyway. (And he falls asleep on his christmas tree. :)
__SCRIPT Invocation
The object class __SCRIPT belongs to Grail Script. When a script file is ran, it is naturally brought into existence to compile the script, but it also stays around after, placing itself into the objects auto-discard list. The reasoning behind this is that __SCRIPT brings with it several very useful and commonly used functions that will make your life easier. See SCRIPT PUBLIC FUNCTIONS later in this document.
BY | Lewis A. Sellers lsellers@usit.net Grail Script Declarations, Keywords, and OperandsAs said, Grail Script is a slightly stripped-down C perl-ized language. If you're familiar with C and have read the rest of the kernel specs then learning GS should not pose a problem. Notice however that GS does allow for returning more than one parameter from a function. To call functions of other objects you must use the __OBJECT_Function function. To call functions within your current class you just directly call them.
As said, you can return either one variable (which can be pointers), a group of variables, or return a filled structure (that is, fill out a structure with data). The symbol for structure returns is =.
You can declare the following types of variables:
byte,sbyte
8 bits
word,sword
16 bits
dword,dword
32 bits
qword, sqword
64 bits
ptr
The pointer size depends on your implementation of Grail. Currently its 32-bits (dword) on the IBM PC platforms.
int
The default int is the most natural size for your platform. On the intels this is a 32-bit dword. There are also the modifiers fast and exact. A fast int on the intels is also 32-bit dword. The exact int is a 64-bit quad-word.
fixed
This performs balanced fixed point real operations. The default natural size is 16.16 or a 32-bit dword. The fast fixed is also 16.16. The exact fixed is 32.32.
float
These variables are real floating point. The default natural size is 80-bits. The fast float size is 80-bits. The exact float size is 80-bits.
Bitsizeof
Want to know what size the Grail Script is currently using? It has a built-in function called bitsizeof that can be used as:
n = bitsizeof exact fixed
that returns the total bits used in the variable type. N would be 64 in this case. There is also bitsizeofA and bitsizeofB that can be used to query fixed and floating variables for the size of their real and fractional components.
assignments, =
Same as in C, but be aware that Script fully supports passing full and complex structures. :) Passing back or assigning variables is as usual, but when structure are involved you must use a pointer to said structure.
pointer, *
When using a pointer, you can either use the C-ish * symbol or you can use the full word pointer.
******
and, &&
or, ||
xor, ^^
bitwise and, &
bitwise or, |
bitwise xor, ^
bitwise complement, ~
+=
-=
*=
%=
<<
>>
Auto-increment, ++
Auto-decrement, --
******
equals, ==
not equals, !=
less than, <
greater than, >
less than or equal, <=
greater than or equal, >=
not, !
********
for (initializes, while, opers)
Same as in C.
if () then {} else { }
Same as in C. If you only have one comparision, then parentheses are not required.
while () { }
Same as in C.
until () { }
Same as in C.
do { } until/while { }
Same as in C.
object
declares the name of the script. should be the same as the filename of the script.
objects
remarks, ;
This is the remark symbol. Same as in normal intel assembly. Remarks the rest of the line.
struct name {}
Can also use structure.
template name {}
defines the structure that is to follow as merely a template that may have many instances. Use the name of the template from now on like the struct keyword.
common /end
These variables and structures are allocated and deallocated automatically for the object.
function /end
Declares a function body. Use end to end the function body. You can, BTW, put an end in a conditional block to terminate the process early. If the keyword function is preceeded by public then the function is added to the publics list (PDL). By default all functions are private, ie local to it's object class.
alias
Allows you to specify that when you make a function call that it should actually use another of it's sibling functions. For when two or more functions are identical for a given object. The alias should be given after the function line and include the true sibling to use. See examples.
return
Defines what, if anything, is returned when the function ends. By default, if you do not specify a return, then NOTHING is returned. Any variable, set of variables or structures can be returned.
If you specify end without any args then you can return an immediate value (32-bits or dword on intel) as an arg to the end of a function.
parameter (object parameter definitions list)
Defines a list of parameter text aliases that can be used for an object function. It should be mentioned that Grail Script IS fully aware of the function parameter text lists that all object modules under Grail may possess. This is to say, instead of __VMODE_Use 0, you can say __VMODE_Use mono.
BY | Lewis A. Sellers lsellers@usit.net __SCRIPT_CreationDoesn't do much of anything.
__SCRIPT_Process ptr_filename
Takes a script file, converts it to assembly, calls the Grail Assembler and compiles it into memory.
__SCRIPT_Destruction
Doesn't do much of anything.
BY | Lewis A. Sellers lsellers@usit.net Script EXAMPLE 1 (fragment); sample of new metaphor structures....???
dptr win1
int r1, r2
win1 = __METAPHOR_WindowOpen
__METAPHOR_WindowSize win1, 100,480,0
__METAPHOR_WindowOrientation win1, 0,0,0
r1 = __METAPHOR_AddRegion win1, Title, 0,0,0, 99,19,0, NULL
r2 = __METAPHOR_AddRegion win1, Text, 0,20,0,99,479,0, NULL
__METAPHOR_WindowShow win1
__METAPHOR_WindowPrint win1, r1, "COME AND WASH AWAY THE RAIN"
__METAPHOR_WindowPrint win1, r2, "Hey there... this is a test.\n"
__KEYBOARD_ReadKey
__METAPHOR_WindowHide
__METAPHOR_WindowClose win1
Script EXAMPLE 2 (Full Program)
;-------------------------------------
;This little script opens a console window and prints out your computers memory.
;It does make use of someones helpful functions from an object called __SCRIPT. :)
;-------------------------------------
function Creation()
end
function Destruction()
end
public function Main()
ptr Wait
ptr OpenWin, Print, CloseWin
int total_memory, l1_cache, l2_cache, cmos_memory
__OBJECT_Request QUICK_KEY
Wait = __OBJECT_Function QUICK_KEY, Wait_For_Press
__OBJECT_Request __SCRIPT
OpenWin = __OBJECT_Function __SCRIPT, OpenWindow
Print = __OBJECT_Function __SCRIPT, Print
CloseWin = __OBJECT_Function __SCRIPT, CloseWindow
(total_memory, l1_cache, l2_cache, cmos_memory) = __KERNEL_Memory()
OpenWin()
Print("Total Memory:",total_memory,"\n")
Print("L1 Cache: ",l1_cache,"\n")
Print("L2 Cache: ",l2_cache,"\n")
Print("CMOS Memory: ",cmos_memory,'"\n")
Wait()
CloseWin()
__OBJECT_Discard __SCRIPT
__OBJECT_Discard QUICK_KEY
end
Script EXAMPLE 3 (Full Program)
function Creation()
end
function Destruction()
end
public function Main()
ptr Wait
ptr OpenWin, Print, CloseWin
ptr platform, processor, system
ptr block,n
Wait = __OBJECT_Function __SCRIPT, Wait_For_Press
OpenWin = __OBJECT_Function __SCRIPT, TextWindow_Open
Print = __OBJECT_Function __SCRIPT, TextWindow_Print
CloseWin = __OBJECT_Function __SCRIPT, TextWindow_Close
platform = __KERNEL_Platform_Name()
processor = __KERNEL_Processor_Name()
system = __KERNEL_System_Class()
(total_used_memory, total_used_secure, total_swapped_out, total_used_DMA) = __MMU_UsedSpace()
(largest_freespace, largest_DMA_freespace) = __MMU_Fragspaces()
(smallest_freespace, smallest_DMA_freespace) = __MMU_Fragspaces()
OpenWin()
;show us some stats....
Print("Platform: ", platform,"\n")
Print("Processor: ", processor, "\n")
Print("System: ", system,"\n")
Print("Total Used Memory:", total_used_memory, "\n")
Print("Total Used SECURE Memory:",total_used_secure, "\n')
Print("Total Used DMA Memory:", total_used_DMA, "\n")
Print("Total VMMU Swapped-out Memory:",total_swapped, "\n")
Print("Largest Freespace:", largest_freespace, "\n")
Print("Largest DMA Freespace:", largest_DMA_freespace, "\n")
Print("Smallest Freespace:", smallest_freespace, "\n")
Print("Smallest DMA Freespace:", smallest_DMA_freespace, "\n")
;allocate almost a meg of memory, write to it, and then kill it...
block = __MMU_Alloc 1000000, default, normal
for(n=block,count=1000000;count>0;n++,count--)
{
*n=0 ;set to 0
*n=1 ;then set to 1 for no reason...
}
__MMU_Free block
Wait();
CloseWin()
end
Script EXAMPLE 4 (Full Program)
;--------------------------
; This simple little script loads in a JPEG using the standard JPEG object,
; then blits the image to the graphics screen.
;--------------------------
function Creation()
end
function Destruction()
end
public function Main()
struct m
{
word zoom_x
word zoom_y
word aspect_x
word aspect_y
dword width
dword height
byte bitdepth
}
ptr dejpeg
ptr logo
struct jpeg_struct
{
word aspect_x
word aspect_y
dword width
dword height
byte bitdepth
}
struct bitBLT_form
{
word srcleft
word srctop
word srcright
word srcbottom
word srcpage/plane
word dstleft
word dsttop
word dstpage/plane
word x_type
word y_type
word bitdepth
}
m.zoom_x=1
m.zoom_y=1
m.aspect_x=4
m.aspect_y=3
m.width=640
m.height=480
m.bitdepth=8
__VMODE_Request_Mode normal, higher_color, m
__VMODE_Use mono
if m.bitdepth<8
end
endif
;grab the jpeg image into memory...
__OBJECT_Request JPEG
infojpeg = __OBJECT_Function JPEG, Essential_Info
dejpeg = __OBJECT_Function JPEG, Decode_to_Memory
jpeg_struct = infojpeg "Grail_Logo_1995_number_7"
logo = dejpeg "Grail_Logo_1995_number_7"
__OBJECT_Discard JPEG
; hmm. out of memory I guess...
if (logo==NULL)
end
endif
;now blit the thing out to the graphics screen
bitBLT_form.srcleft=0
bitBLT_form.srctop=0
bitBLT_form.srcright=infojpeg.width
bitBLT_form.srcbottom=infojpeg.height
bitBLT_form.dstleft=0
bitBLT_form.dsttop=0
bitBLT_form.bitdepth=infojpeg.bitdepth
__GOBJ_BitBLT bitBLT_form
while __KEYBOARD_ReadKey==0
{
}
;free the memory allocated for the JPEG by the jpeg object
__MMU_Free logo
__KERNEL_Reboot ; =)
end
Script EXAMPLE 5
;--------------
;This script is meant to be called to ask if a certain file is a specific graphics
;file format.
;--------------
object FILE_FORMAT
function Creation()
end
function Destruction()
end
public function Is?(ptr filename, word type)
return
{
int n
}
parameter type
{
1,"jpeg"
2,"tiff"
}
ptr func
word v
;jpeg
if (type==JPEG)
{
__OBJECT_Request JPEG
func = __OBJECT_Function JPEG, Verify
v = func filename
if (v==0)
n=0
else
n=1
endif
__OBJECT_Discard JPEG
}
;tiff
if (type==TIFF)
{
__OBJECT_Request TIFF
func = __OBJECT_Function TIFF, Verify
v = func filename
if (v==0)
{ n=0 }
else
{ n=1 }
endif
__OBJECT_Discard TIFF
}
end
Script EXAMPLE 6 (Full Program)
;--------------
; simple example of loading up the Quake Engine and tooling around in it....
;--------------
function Creation()
end
function Destruction()
end
public function Main()
instance PO
{
struct Point
{
word x, y, z
word roll, pitch, yawn
}
struct Vector
{
word x, y, z
word roll, pitch, yawn
}
}
PO POV, POB, POA, POAA
ptr mode, position
ptr glove, glove_command
__OBJECT_Request QUAKE_ENGINE ;we start up the engine and of course the creation function initializes it.
mode = __OBJECT_Function QUAKE_ENGINE, Global_Mode
position = __OBJECT_Function QUAKE_ENGINE, Point_of_View
; ok, switch to gods-eye mode
mode GodsEye
__VR_ABSTRACT_Reset
glove = __OJBECT_Function __VR_ABSTRACT, ReadPOV
glove_command = __OBJECT_Function __VR_ABSTRACT, ReadPOVCommand
while ( glove_command() == NULL )
{
POV = glove()
position(POV.x, POV.y, POV.z, POV.roll, POV.pitch, POV.yawn)
}
__OBJECT_Discard QUAKE_ENGINE
end
Script EXAMPLE 7 (Full Program)
; This is the __VR_ABSTRACT object for a hypothethical standard 4-button joystick. one button top, one trigger
; and two buttons on the side.
;
object __VR_ABSTRACT
common
struct s
{
word x, y, z
word roll, pitch, yawn
}
end
function Creation()
return
{
end
}
if (__JOYSTICK_Exist() == 0)
end 0
endif
__JOYSTICK_Reset()
s.x=0
s.y=0
s.z=0
s.roll=0
s.pitch=0
s.yawn=0
end 1
function Destruction()
end
public function Reset()
alias Creation
end
public function Info()
end
public function GetPOV()
return
{
word x,y,z
word roll, pitch, yawn
}
word jx, jy
x=s.x
y=s.y
z=0
roll=0
pitch=0
yawn=0
(jx, jy) = __JOYSTICK_xy_Acceleration()
x+=xj
y+=yj
s.x=x
s.y=y
end
public function GetPOB()
alias GetPOV
end
public function GetPOA()
alias GetPOV
end
public function GetPOAA()
alias GetPOV
end
public function Response()
return
{
end
}
end 0
public function Command()
return
{
word button
}
button = __JOYSTICK_Button 1 ;the trigger button is the 2nd one on our joystick
end
public function CommandMatrix()
return
{
word b[4]
}
b[1] = __JOYSTICK_Button 0
b[2] = __JOYSTICK_Button 1
b[3] = __JOYSTICK_Button 2
b[4] = __JOYSTICK_Button 3
end
Script EXAMPLE 8
;
; Load up some objects and then leave them.
;
if( __OBJECT_Verify("Generic TIFF")>0)
{
if(__OBJECT_Request("Generic TIFF")<0)
{
__OBJECT_Terminate()
}
__OBJECT_UnID()
}
if (__OBJECT_Verify("Generic PNG")>0)
{
if (__OBJECT_Request("Generic PNG")<0)
{
__OBJECT_Terminate()
}
__OBJECT_UnID()
}
Script EXAMPLE 9 (Full Program)
;
function Creation()
end
function Destruction()
end
function main()
ptr Debug, Info, Parameter, Language, Object, Decryption
template objs
{
dword Internal_Build
ptr Class_Name
ptr Instance_Name
ptr Associative_Name
}
ptr PrintVars
(Debug, Info, Parameter, Language, Object, Decryption)=__OBJECT_Area()
objs=object
__OBJECT_Request __SCRIPT
OpenWin = __OBJECT_Function __SCRIPT, TextWindow_Open
PrintVars = __OBJECT_Function __SCRIPT, TextWindow_PrintVars
CloseWin = __OBJECT_Function __SCRIPT, TextWindow_Close
PrintVars "Internal Build ",objs.Internal_Build, "\n"
__KEYBOARD_ReadKey()
__OBJECT_Discard __SCRIPT
end
Script EXAMPLE 10
;
template bitBLT_form {
dw srcwidth
dw srcheight
dw srcleft
dw srctop
dw srcright
dw srcbottom
dw srcpage/plane
dw dstleft
dw dsttop
dw dstpage/plane
dw x_type
dw y_type
db bitdepth
}
bitBLT_form yf
template Normal_Visual {
dw zoom_x
dw zoom_y
dw aspect_x
dw aspect_y
dd width
dd height
db bitdepth
}
Normal_Visual p
p.zoom_x=0
p.zoom_y=0
p.aspect_x=4
p.aspect_y=3
p.width=640
p.height=480
p.bitdepth=8
__VISUAL_Request_Mode normal, higher_size, p
; open a graphic we know is 100x200 256colors
yazref = __FS_LookuprefID "Yazzie_1994;7"
yaz__FS_OpenData yazref
yf.srcwidth=100
yf.srcheight=200
yf.srcleft=0
yf.srctop=0
yf.srcright=99
yf.srcbottom=199
yf.dstleft=0
yf.dsttop=0
yf.bitdepth=8
__GRAPHICS_BitBLT yf
__FS_CloseData yaz, flush
COMMENTARY
None yet.