A Grail Millennium Project

White Paper

History | Preface | TOC

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.

Preface | TOC


OCI/Spec | S C R I P T

DESIGNER

Lewis A. Sellers (aka Minimalist) lsellers@usit.net

CRITIQUED BY

DRAFTS

TOC


(a0.03)


Table of Contents

Legal NoticesWho gets sued and why
HistoryChanges and who made them
PrefaceAbout this document and the people that make it

OverviewAn Overview of the Script

TOC


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.

TOC


Keywords and Directives

BY | Lewis A. Sellers lsellers@usit.net
Grail Script Declarations, Keywords, and Operands

As 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.

TOC


Script Class Functions

BY | Lewis A. Sellers lsellers@usit.net
__SCRIPT_Creation

Doesn'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.

TOC


EXAMPLES

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.