Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

774 lines
23 KiB

Workitems for GPD parser:
----------------------
1) define data structures
a) optionextra data (see resolution options
as an example)
b) structures to hold data associated with defined keywords
2) harden the spec: for example what characters are allowed for
Symbols? What are the reserved chars and when
are they active?
3) implications for converter - what assumptions did Unidrv 4.0
make that need to be explicitly expressed in the GPD?
What data format differences will create conversion
problems? example: GPC used indexes to structures
a lot. These will no longer exist.
4) commands: we need a new set of commands and meta commands
that allow the GPD file to specify what is needed
to perform each task. Don't let driver
string together primitive commands to do this.
5) parsing and data storage constructs to accomodate
variable sized and structured data.
6) define parsing tasks.
--------------------------------------------
parsing tasks:
open file as memory? need to memcopy if *Includes exist.
*Include - insert contents of external file (nestable)
extracting included resources:
strings: we can add those to the heap.
icons: keep resource IDs and let UI code
extract the bitmaps when needed.
fontinfo: don't extract into GPD binary unless necessary.
issues of scope : redefinition of macros or globals.
may macros be defined/redefined inside of constructs?
if so how does this affect their scope? How does
the parser track this? Keep macros in a stack,
with each { pushing a bp marker onto a stack
and each } causing all macros defined since the { to
be cleared! Macros are resolved by looking at
the stack from newest to oldest, so if a macro has
been redefined, the newer redefinition will override
an older.
macro handling:
recognizing , converting hex substrings, storage in
temp buffers. Associating a scope (if needed.)
note: zhan specifies whitespace may bracket '='
forward references and resolution of.
Default initializers, reinitialization, global
initialization. Clarify these concepts and when
they occur. How does parser recognize them.
syntax definition: a set of rules for
the finite state machine.
Parsing methodology: not line based? maybe stream based?
character space, allowed characters for each syntax element,
special characters and their functions.
There will be lots of info stored in tables, like
lists of *Keywords, what type of values are allowed,
where the values will be stored, etc.
And dynamic lists like qualified names,
arrays of features.
Define the information needed, how it will be stored
and accessed.
Grouping constructs { and } when and where may they appear
how do they affect the syntax (substitute for newlines)
after which keywords, what state transition do they trigger?
*Feature
*Option
*Font
*UIGroup
*Switch / *Case
*Command
*Macros
*OEM
reconciliation of two concepts: syntax mirrors underlying
data structure to syntax allows user to define the
underlying data structure.
In general we can say the syntax mirrors the underlying data
but there are special operators and constructs which
can modify this default behavior and hence 'modify' the
effective format of the data.
concerns for a GPC to GPD converter.
---------------------------------------------------------------
Implementation of parser constructs:
How do we link everything
together?
even more parser constructs a generalized version of
our *group ing operators. The *switch construct can
be nested, and used almost anywhere, like
conditional macro constructs, it does not interfere
with the existing grouping. It does use the same
grouping operator {}, so you cannot have a switch statement
interwoven with other groups.
The *case group may contain one or more grouping constructs
in their entirety.
*switch:featureI
{
*case:optionA
{
*attribute:RASTER.*SpotDia:100
*OrderedCmd:drawdot
{
*invocation:"xlkdfow"
*OrderDependency:x y
}
}
*case:optionB
{
}
*case:*default
{
}
}
Note: only *case constructs allowed inside a *switch construct.
Almost anything is allowed inside a *case.
WRONG! only attributes and commands and FONTS
are allowed inside case constructs.
Note: the *switch and *case constructs serve to allow
attributes to be multivalued. For a specific configuration
you can 'evaluate' the *switch construct to see its
syntatical equivalent. That is the statements that
are actually executed.
Note: how do we implement the arbitrary complexity tree
that the switch construct permits?
Note all fields of internal structure would have to be mirrored
by a tag that says go consult tree for disposition of data.
a) decide what data gets to reside inside the optionextra structure.
b) decide what syntax we will use to make data multi-valued.
inside or outside of constructs?
*Feature:featureA
{
*Option:tat
{
standard attributes for this option
*attribute:RASTER.*
*Commands:RASTER.*Xmove:"lsdkfie"
*Switch:featureB
{
*case:option1
{
*standardattributes that are dependent on both
featureA and featureB
*attribute:RASTER.*SpotDia:100
}
*case:*default
{
*default values for attributes
}
}
}
}
merge switch constructs with *Feature/*Option constructs?
in the GPD syntax,
but regardless of the syntax, in the binary data, A
bunch of data structures of a type that is readable by the UI
is initialized at request time with the current configuration.
The source of all the data is a table mirroring
The data structures except where the data structures
have data the table has index/offset entries.
Wants a way to permit OEM customized data to be
stored in the binary structure. Do not attempt to
read special meanings into OEM section for backward
compatibility.
------
The simplest implementation of an arbitrary
treed data structure is to treat each data node in the
structure as not containing a value, but rather a tree
of values. Each node may have a different sized tree.
For example the node containing the modelname may have
a tree consisting of a pointer to the string.
On the other hand, the tree containg the spot diameter
may be 2 dimensional.
The tree is implemented by an array of structures
of the form:
struct TreeBranch
{
feature
option
DWORD nextOption ;
BOOL offsetmeans (NEXT_FEATURE, VALUE)
DWORD offset ;
}
No trees are shared between data nodes.
If a default initializer is supplied, this will appear
as feature #0 option 0 and appear in the front of the
list. So when the tree is searched for the current
config and this path does not exist, use the default
initializer.
the basic data element is that which is initialized by
a single statement. The tree shall point to a heap of
basic data elements. Each ptr shall point to just one
data element. Do not assume its an array of elements.
To minimize unecessary treeing, command structures
are treated as one unit.
Subfields of features need to be multi-valued.
(but currently the number and types of options will not change)
Subfields of options need to be multi-valued.
(command info inside options may be stored in the generic
command array!).
All commands and global attributes are treed.
Fonts etc. But the subfields of structures other than
feature and option are not treed. Thus the
nodes of the command tree are indicies to command
structures in an array of command structures.
Or offsets to the commands themselves. (to retain consistency
with other data.)
Tasks: define all data structures
and list functions and their purpose
in the goal of adding a data element
during parsing.
Default initializers, macro handling.
------ Installable option -----
The parser will synthesize a "configuration feature"
for every Installable option or feature. This
"configuration feature" tracks if the feature/option
is installed or not.
UI interface:
Installable Options:
UI constraints helper function will provide the
UI module with the info (for a given feature, which
options are disabled) needed to handle the
diabling/enabling of the installable option based
on the setting of the configuration feature associated
with the installable option.
InstallableFeature:
UI must be able to recognize an Installable Feature
since it must disable/enable it depending on the
state of the configuration feature. UI constraints
helper may return a special value to indicate this is
a disabled Installable Feature if the Feature is installed
it will treat the Feature as it would a normal feature
and provide info on the options.
Both:
UI must be able to identify the configuration features
and display them on the appropirate printer sticky property
page. Also these settings must be stored separately
from the doc sticky settings.
If User attempts to select a grayed out Feature or Option
UI must call the UI constraints helper function and
display an intelligble message based on the data returned
by the helper.
Tasks: define the UI constraints helper function.
There are several tasks:
a) given an option array from a devmode
check it for validity. If invalid, change some
settings to make everything consistent with
UI constraints.
b) given a feature index and the current options array,
return a boolean array indicating which options
are grayed out.
c) given a proposed option selection and the current options
array, explain what constraints the proposed option
conflicts with.
what parser does when encountering the *Installable
keyword in *Features construct:
a) synthesize a *Features construct that is used
to select whether the *Feature is installed or not.
Synthesize two options, "Installed" and "Not Installed".
This synthesized feature is called the configuration feature.
Establish a two way link between the configuration feature
and the *Feature that lead to its creation.
what parser does when encountering the *Installable
keyword in *Options construct:
a) synthesize a *Features construct that is used
to select whether the *Option is installed or not.
Synthesize two options, "Installed" and "Not Installed".
This synthesized feature is called the configuration feature.
Establish a two way link between the configuration feature
and the *Option that lead to its creation.
Tasks: add new fields to Features and Options that will
allow this link to be established.
sketch out code to parse and synthesize configration features.
To minimize updating of UI's version (snapshot)
of multi valued data, Parser supplies UI with
array of features marking those which if changed
can affect the snapshot. UI code can then call
the ssync function which returns an array of features
marking those which were affected.
Tasks: work out the specifics for this helper function.
What algorithm will you use to determine if the
snapshot needs to be updated? Which fields will be
updated?
-------
Implementation of switch inside Options and Features.
Switch and Case cannot enclose Options or Features.
Implementation of parsing in general
and Macros.
Data for UI code.
Command storage format.
OrderedCmds, simple commands.
Font info
UIGroup
Data Types.
-------------------------------------------------
Binary Data structures:
All internal data structures
are virtual. That is each element in the
structure actually points to a tree which points
to one or more nodes each containing a value
for that element which is valid under certain
conditions. (all values being mutually exclusive.)
Don't forget the default initializer. The one that exists
outside of any switch construct, which may in turn be overwritten
by the *Case:*Default entries.
The parser should provide a snapshot of all
GPD info for the control module to use.
Supply an entry pt. to allow control module to update
snapshot if devmode settings change like by ResetDC.
------
Implementation of *UIConstraints *Incompatible and *OrderDependency
see constraints for Installable options.
and NotUIConstraints and 2 parameter *InvalidCombinations
The option constraints imposed by *Constraints is stored in
a one dim array of contraint structures.
(also used to hold constraints defined by *InstalledConstrainsSelections
and *NotInstalledConstrainsSelections
in this case, feature may refer to the installed state of a feature
or option. Note also an installable option if not installed
will always constrain itself from being selected.)
{
WORD feature; // may reference an installable feature
WORD option ;
WORD next ; // 0xffff signifies end of constraint list.
}
The Constraints field in the options structure
may take on values like 0xffff to indicate this option
does not constrain any other . Otherwise this field contains
the index to start of constraints list for this option. The list is
interpreted as follows: if the option is selected, the following
list of options CANNOT be selected.
At parsing time, we must add two entries to the array for every
*constraints statement parsed since each statement is reflexive.
NotConstraints are parsed into multiple Constraints. Maybe
we can remove this construct since we have zhanw's LIST construct.
*InvalidCombinations:
{
WORD feature; // may reference an installable feature
WORD option ;
WORD nextElement ; // 0xffff signifies end of elements list.
WORD newCombination ; // 0xffff signifies no more constraints
// involving this element.
}INVALIDCOMBO ;
An element is a feature-option pair.
nextElement is the index to another INVALIDCOMBO structure
that contains another element which is incompatible with
the previous elements.
NewCombination points to the first element of another
invalidCombination list involving the element in question.
The first element in the new list is not necessarily the same
as the element in question.
Each option structure will contain an index to the
InvalidCombo array. A value of 0xffff indicates
this element is not involved in any invalidCombinations.
----- installable features and options ----
Whenever there are installable option or features
specified in the GPD file, the parser will create
a generic feature with two options "Installed" and
"Not Installed". The UI may display this set
of features during the printer sticky portion of setup.
This feature is also refered to as an "Installable Configuration
Feature" or a "synthesized feature".
Each installable option or feature structure
will have an index (say ConfigurationFeatureIndex)
that points to the synthesized feature.
The options array in the devmode should store the
state of the synthesized features as they
indicate whether the option is installed or not.
(ie: whether the env feeder is installed or not. Note this
is a separate bit of data from that indicating whether
the env feeder is Selected or not.)
If an option is marked *installable it will appear on
the selections UI as being enabled or grayed out.
If grayed out you can select it, else you cannot.
If all options in the feature are installable, there must
be one option that isn't. The default option will be
overridden if it points to an uninstalled option.
If a feature is marked installed, then all the options
enumerated there will be displayed just as if it were
a normal feature. If it is marked "Not Installed" then
the UI should consider the entire feature to be disabled.
There will still be a slot on the features array allocated
for its option selection however, but the control module
code should not access it.
-----
Constraints on Installation:
These are kept in a separate constraint array and
are defined by the keywords *InvalidInstallableCombination:
and *InstallRequires: .
The constraint array may only reference synthesized Features
indicies defining the configuration of installable options on the
printer.
The Constraints field in the option structure for
an Installable Configuration (synthesized) Feature will point to
this installConstraints array.
The InvalidCombo field will have no meaning for
an Installable Configuration Feature.
---------------------------------------------------------------------
Code emitting option invocations must check that the
Feature is Installed before emitting the strings.
Code checking for UI constraints may ignore entries
constraining Disabled Features.
Code evaluating all UI constraints must ignore effect
of Uninstalled Features.
Code displaying features must first check if the feature is
disabled.
-----
UIGroup: allowing the UI to group related features
together.
This may be implemented via A tree:
typedef struct
{
STRINGREF GroupName;
WORD NextGroup ; // (in same level)
WORD FirstSubGroups ;
BOOL SubGroupIsFeatureIndex ;
// set TRUE if there are no subgroups
// just a list of Features.
// this requires all Feature structures
// have a field called NextFeatureInGroup
// that holds the index of the next
// feature.
} GROUPTREE ;
lpGroupTree may be NULL if there are no grouping
constructs.
-------------------------------
Command storage format.
OrderedCmds, simple commands.
All Commands (regardless of the GPD syntax
used in their definition) will be stored in a structure
similiar to that shown below.
All command structures will be arranged as
a one dimensional array, accessible by an
array index. All Unidrv recognized commands
will be assigned a particular index value.
Other commands like option invocations may
be arbitrarily assigned index values outside
of the reserved range.
The reference to a command in the option structure
then becomes just a WORD - the index of the structure
containing that command.
Basic attributes for a command
based on Zhanw's GPD syntax.
typedef struct
{
STRINGREF invocation; // "binary string" %paramref "more binary string"
ORDERDEPENDENCY Order; // if defined, the command
// will end up enumerated in an order dependency list.
} BASIC_COMMAND
The invocation is of the form one or more binary strings
and parameter references concatenated together in any order.
White spaces may separate the binary strings from the parameter
reference.
(macros will have been resolved before storing the command.)
A binary string is of the form: any set of binary bytes
enclosed by double quotes. Note the % acts to escape itself
and the " in a binary string. Thus "%%" is really (%)
"%"" is really (") , "%%%"" is really (%"), "%a" is just (a).
A % preceeding any other character is ignored. All bytes between
the opening and closing " are part of the binary string.
A paramref is a % followed by one or more decimal digits representing
an index to the array of PARAMETERS.
Multiple PARAMETERS may be embedded into a command.
typedef struct
{
BYTE format; // The first letter after the %
BYTE digits; // only valid if format = 'd' or 'D'
BOOL MinUsed, MaxUsed , MaxRepeatUsed;
Long Min, Max ; // look here only if used.
DWORD MaxRepeat ;
WORD ValuesStack; // may contain refs to StandardVariables
// so Values may be composite of integer and boolean.
WORD OperatorStack; (Min, Max, +, -, *, / , MOD, HALT)
} PARAMETER
typedef struct
{
DWORD value;
BOOL valueIsSymbol ;
} VALUE ;
The value stack is an array of VALUEs.
The ValueStack field in PARAMETER is an index to the
an element in the Value stack. This value is considered
the top of the stack, the value at index n+1 is next on the stack
and so forth.
There is No end of stack indicator. You keep accessing the value
stack until the HALT operator is encountered.
Note if the value refers to an internal Unidrv variable
(valueIsSymbol == TRUE), you must use the current value of the
Unidrv varable.
The Operator Stack is simply an array of words.
Each operator is assigned an enumeration value.
Each operator starting from the top of the stack is
used to operate on the contents of the Value stack until
the HALT operator is encountered. The result on the
top of the value stack is formatted according to the
the format specifier and emitted in the command stream.
The orderDependency list is contained in an array of SEQUENCED_CMDS.
The structures in the array are arranged as 6 singly-linked
lists - one list for each section defined in the OrderDependency
construct. A command is referenced either by its Index in the
command array or if its an option invocation, by its FeatureIndex.
(If option invocation, the control module must determine
the correct option to emit. If its a pick many, it must
use the order specified in each option to emit the
options in the correct order.)
typedef struct
{
WORD IndexOfCommand ; (0xffff if not used)
WORD FeatureIndex ; (0xffff if not used)
WORD NextInSequence ;
}
SEQUENCED_CMDS
The following are indicies to the array of SEQUENCED_CMDS,
they point to the first Command to be emitted in each section.
WORD Job_Setup, Doc_Setup, Page_Setup, Page_Finish,
Doc_Finish, Job_Finish ;
----------------------------
Global Attributes: this refers to all
data not contained within *Feature, *Option constructs
or constructs not already discussed.
All Global Attributes will be stored in a single
structure and each element in the structure
will have a name similar to the description provided
in the GPD.
------------
Global attributes of type LIST()
will contain a WORD that indexes an array
of the proper data type.
Each element in the array will be
{
TYPE data ;
WORD nextItemInList;
} typeLIST_ELEMENT ;
where type is replaced by the required data type
WORDS, RECTS, POINTS etc. There will be one list
for each data type.
-----------------------------------------------
Parsing of variable data types:
is it a LIST or just one?
how do we anticipate a LIST appearing
in the middle of nowhere?
----------------------------
A note on use of *Switch/*Case constructs and nesting globals.
*Switch/*Case constructs may be used only within *Feature and
*Option constructs.
*Switch/*Case constructs may not contain *Option constructs.
Multiple *Switch/*Case constructs may be nested.
only Relocatable entries may be moved from their intrinsic
location to the inside of *Switch/*Case constructs.
Relocatable entries normally residing in a *Feature construct
may be moved inside a *Switch/*Case construct, but may not
be moved inside an *option construct.
Relocatable entries normally residing at the Root level
may be moved inside an *Option construct or inside a *Switch/*Case
construct that resides inside an *Option construct.
Zhanbing also wants relocateable Root entries to be placed inside
a *Switch/*Case construct that is at the root level.
Examples of non-relocatable entries include
any entries defining constraints, *Feature, *Option.
Note: making commands multi-valued implies OrderDependencies
must be resolved at runtime!