📄 pragma.gml
字号:
.np
.ix 'symbol attributes'
.ix 'pragmas' 'auxiliary'
.ix 'auxiliary pragma'
Auxiliary pragmas are used to describe attributes that affect
.if '&cmpclass' eq 'load-n-go' .do begin
the method used for passing arguments.
.do end
.el .do begin
code generation.
.do end
Initially, the compiler defines a default set of attributes.
Each auxiliary pragma refers to one of the following.
.autopoint
.point
.if '&cmpclass' = 'load-n-go' .do begin
a symbol (such as a subroutine or function)
.do end
.el .do begin
a symbol (such as a variable or function)
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.point
a type definition that resolves to a function type
.do end
.point
the default set of attributes defined by the compiler
.endpoint
.np
When an auxiliary pragma refers to a particular symbol, a copy of the
current set of default attributes is made and merged with the
attributes specified in the auxiliary pragma.
The resulting attributes are assigned to the specified symbol and can
only be changed by another auxiliary pragma that refers to the same
symbol.
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.np
An example of a type definition that resolves to a function type is the
following.
.millust begin
typedef void (*func_type)();
.millust end
.pc
When an auxiliary pragma refers to a such a type definition, a copy of the
current set of default attributes is made and merged with the
attributes specified in the auxiliary pragma.
The resulting attributes are assigned to each function whose type matches
the specified type definition.
.do end
.np
When "default" is specified instead of a symbol name,
the attributes specified by the auxiliary pragma change the default
set of attributes.
The resulting attributes are used by all symbols that have not been
specifically referenced by a previous auxiliary pragma.
.np
.if '&cmpclass' ne 'load-n-go' .do begin
Note that all auxiliary pragmas are processed before code generation
begins.
.do end
Consider the following example.
.millust begin
code in which symbol x is referenced
&pragma aux y <attrs_1>&epragma
code in which symbol y is referenced
code in which symbol z is referenced
&pragma aux default <attrs_2>&epragma
&pragma aux x <attrs_3>&epragma
.millust end
.np
Auxiliary attributes are assigned to
.id x,
.id y
and
.id z
in the following way.
.autonote
.note
Symbol
.id x
is assigned the initial default attributes merged with the attributes
specified by
.id <attrs_2>
and
.id <attrs_3>.
.note
Symbol
.id y
is assigned the initial default attributes merged with the attributes
specified by
.id <attrs_1>.
.note
Symbol
.id z
is assigned the initial default attributes merged with the attributes
specified by
.id <attrs_2>.
.endnote
.*
.section Alias Names
.*
.np
.ix 'alias name (pragma)'
When a symbol referred to by an auxiliary pragma includes an alias name,
the attributes of the alias name are also assumed by the specified symbol.
.np
There are two methods of specifying alias information.
In the first method, the symbol assumes only the attributes of the
alias name; no additional attributes can be specified.
The second method is more general since it is possible to specify
an alias name as well as additional auxiliary information.
In this case, the symbol assumes the attributes of the alias name as well as
the attributes specified by the additional auxiliary information.
.np
The simple form of the auxiliary pragma used to specify an alias is as
follows.
.if '&lang' eq 'C' or '&lang' eq 'C/C++' and '&machine' eq '80386' .do begin
.mbox begin
:prgbeg. aux ( :id.sym:eid., :op.far16:eop. :id.alias:eid. ) :prgend.
.mbox end
.do end
.el .do begin
.mbox begin
:prgbeg. aux ( :id.sym:eid., :id.alias:eid. ) :prgend.
.mbox end
.do end
.synote
.note sym
is any valid &lang identifier.
.note alias
is the alias name and is any valid &lang identifier.
.esynote
.if '&lang' eq 'C' or '&lang' eq 'C/C++' and '&machine' eq '80386' .do begin
.im prag16
.do end
.np
Consider the following example.
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.millust begin
&pragma aux push_args parm [] &epragma
&pragma aux ( rtn, push_args ) &epragma
.millust end
.do end
.el .do begin
.millust begin
&pragma aux value_args parm (value) &epragma
&pragma aux ( rtn, value_args ) &epragma
.millust end
.do end
.pc
The routine
.id rtn
assumes the attributes of the alias name
.id push_args
which specifies that the arguments to
.id rtn
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
are passed on the stack.
.np
Let us look at an example in which the symbol is a type definition.
.millust begin
typedef void (func_type)(int);
#pragma aux push_args parm [];
#pragma aux ( func_type, push_args );
extern func_type rtn1;
extern func_type rtn2;
.millust end
.pc
The first auxiliary pragma defines an alias name called
.id push_args
that specifies the mechanism to be used to pass arguments.
The mechanism is to pass all arguments on the stack.
The second auxiliary pragma associates the attributes specified
in the first pragma with the type definition
.id func_type.
Since
.id rtn1
and
.id rtn2
are of type
.id func_type,
arguments to either of those functions will be passed on the stack.
.do end
.el .do begin
are passed by value.
.do end
.np
The general form of an auxiliary pragma that can be used to specify an
alias is as follows.
.ix 'pragmas' 'alias name'
.mbox begin
:prgbeg. aux ( :id.alias:eid. ) :id.sym:eid. :id.aux_attrs:eid. :prgend.
.mbox end
.synote
.note alias
is the alias name and is any valid &lang identifier.
.note sym
is any valid &lang identifier.
.note aux_attrs
are attributes that can be specified with the auxiliary pragma.
.esynote
.pc
Consider the following example.
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.if '&machine' eq '8086' .do begin
.ix 'Microsoft' 'C calling convention'
.ix 'calling convention' 'Microsoft C'
.millust begin
#pragma aux MS_C "_*" \
parm caller [] \
value struct float struct routine [ax]\
modify [ax bx cx dx es];
#pragma aux (MS_C) rtn1;
#pragma aux (MS_C) rtn2;
#pragma aux (MS_C) rtn3;
.millust end
.do end
.if '&machine' eq '80386' .do begin
.ix 'MetaWare' 'High C calling convention'
.ix 'calling convention' 'MetaWare High C'
.millust begin
#pragma aux HIGH_C "*" \
parm caller [] \
value no8087 \
modify [eax ecx edx fs gs];
#pragma aux (HIGH_C) rtn1;
#pragma aux (HIGH_C) rtn2;
#pragma aux (HIGH_C) rtn3;
.millust end
.do end
.do end
.if '&lang' eq 'FORTRAN 77' .do begin
.millust begin
*$pragma aux WC "*_" parm (value)
*$pragma aux (WC) rtn1
*$pragma aux (WC) rtn2
*$pragma aux (WC) rtn3
.millust end
.do end
.pc
The routines
.id rtn1,
.id rtn2
and
.id rtn3
assume the same attributes as the
alias name
.id &alias_name
which defines the calling convention used by the &other_cmp compiler.
.if '&lang' eq 'C' or '&lang' eq 'C/C++' and '&machine' eq '80386' .do begin
Note that register ES must also be specified in the "modify" register
set when using a memory model that is not a small data model.
.do end
Whenever calls are made to
.id rtn1,
.id rtn2
and
.id rtn3,
the &other_cmp calling convention will be used.
.if '&lang' eq 'FORTRAN 77' .do begin
Note that arguments must be passed by value.
.ix 'passing arguments by value'
By default, &cmpname passes arguments by reference.
.do end
.np
Note that if the attributes of
.id &alias_name
change, only one pragma needs to be changed.
If we had not used an alias name and specified the attributes in each
of the three pragmas for
.id rtn1,
.id rtn2
and
.id rtn3,
we would have to change all three pragmas.
This approach also reduces the amount of memory required by the
compiler to process the source file.
.warn
The alias name
.id &alias_name
is just another symbol.
If
.id &alias_name
appeared in your source code, it would assume the attributes specified
in the pragma for
.id &alias_name..
.ewarn
.*
.if '&cmpclass' ne 'load-n-go' .do begin
.*
.section Predefined Aliases
.*
.np
A number of symbols are predefined by the compiler with a set of
attributes that describe a particular calling convention.
These symbols can be used as aliases.
The following is a list of these symbols.
.*
.begnote
.note __cdecl
.ix 'alias names' '__cdecl'
.ix '__cdecl alias name'
.kwm __cdecl
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
or
.ix 'alias names' 'cdecl'
.ix 'cdecl alias name'
.kwm cdecl
.do end
defines the calling convention used by Microsoft compilers.
.note __fastcall
.ix 'alias names' '__fastcall'
.ix '__fastcall alias name'
.kwm __fastcall
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
or
.ix 'alias names' 'fastcall'
.ix 'fastcall alias name'
.kwm fastcall
.do end
defines the calling convention used by Microsoft compilers.
.note __fortran
.ix 'alias names' '__fortran'
.ix '__fortran alias name'
.kwm __fortran
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
or
.ix 'alias names' 'fortran'
.ix 'fortran alias name'
.kwm fortran
.do end
defines the calling convention used by &company. FORTRAN compilers.
.note __pascal
.kwm __pascal
.ix 'alias names' '__pascal'
.ix '__pascal alias name'
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
or
.ix 'alias names' 'pascal'
.ix 'pascal alias name'
.kwm pascal
.do end
defines the calling convention used by OS/2 1.x and Windows 3.x API
functions.
.note __stdcall
.ix 'alias names' '__stdcall'
.ix '__stdcall alias name'
.kwm __stdcall
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
or
.ix 'alias names' 'stdcall'
.ix 'stdcall alias name'
.kwm stdcall
.do end
.if '&machine' eq '80386' .do begin
defines a special calling convention used by the Win32 API functions.
.do end
.el .do begin
defines the calling convention used by Microsoft compilers.
.do end
.if '&machine' eq '80386' .do begin
.note __syscall
.ix 'alias names' '__syscall'
.ix '__syscall alias name'
.kwm __syscall
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
or
.ix 'alias names' 'syscall'
.ix 'syscall alias name'
.kwm syscall
.do end
defines the calling convention used by the 32-bit OS/2 API functions.
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' and '&machine' eq '80386' .do begin
.note __system
.ix 'alias names' '__system'
.ix '__system alias name'
.kwm __system
or
.ix 'alias names' 'system'
.ix 'system alias name'
.kwm system
are identical to
.kwm __syscall.
.do end
.note __watcall
.ix 'alias names' '__watcall'
.ix '__watcall alias name'
.kwm __watcall
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
or
.ix 'alias names' 'watcall'
.ix 'watcall alias name'
.kwm watcall
.do end
defines the calling convention used by &company compilers.
.endnote
.pc
The following describes the attributes of the above alias names.
.*
.beglevel
.*
.section Predefined "__cdecl" Alias
.*
.millust begin
&pragma aux __cdecl "_*" \
&pragcont parm caller [] \
&pragcont value struct float struct routine [&ax] \
.if '&machine' eq '80386' .do begin
&pragcont modify [eax ecx edx]
.do end
.if '&machine' eq '8086' .do begin
&pragcont modify [ax bx cx dx es]
.do end
.millust end
.autonote Notes:
.note
All symbols are preceded by an underscore character.
.note
Arguments are pushed on the stack from right to left.
That is, the last argument is pushed first.
The calling routine will remove the arguments from the stack.
.note
Floating-point values are returned in the same way as structures.
When a structure is returned, the called routine allocates space
for the return value and returns a pointer to the return value in register
&axup..
.if '&machine' eq '8086' .do begin
.note
Registers AX, BX, CX and DX, and segment register ES are not saved and
restored when a call is made.
.do end
.if '&machine' eq '80386' .do begin
.note
Registers EAX, ECX and EDX are not saved and restored when a call is
made.
.do end
.endnote
.*
.section Predefined "__pascal" Alias
.*
.millust begin
&pragma aux __pascal "^" \
&pragcont parm reverse routine [] \
&pragcont value struct float struct caller [] \
.if '&machine' eq '8086' .do begin
&pragcont modify [ax bx cx dx es]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -