Skip to content

Commit daceda3

Browse files
author
Quirin Schroll
committed
Specify D and C main in prose; provide grammar as an approximation
1 parent c386b33 commit daceda3

File tree

1 file changed

+123
-42
lines changed

1 file changed

+123
-42
lines changed

spec/function.dd

+123-42
Original file line numberDiff line numberDiff line change
@@ -3420,82 +3420,120 @@ $(H2 $(LNAME2 main, The $(D main) Function))
34203420
It gets called after all the $(DDSUBLINK spec/module, staticorder, module initializers)
34213421
are run, and after any $(DDLINK spec/unittest, Unit Tests, unittests) are run.
34223422
After it returns, all the module destructors are run.
3423-
The $(D main) function typically is declared as follows:
34243423
)
34253424

3426-
$(INFORMATIVE_GRAMMAR
3427-
$(GNAME MainFunction):
3428-
$(GLINK MainReturnDecl) $(D main) $(LPAREN) $(RPAREN) $(GLINK FunctionBody)
3429-
$(GLINK MainReturnDecl) $(D main) $(LPAREN) $(D string) $(D [) $(D ]) $(GLINK_LEX Identifier)$(OPT) $(RPAREN) $(GLINK FunctionBody)
3430-
3431-
$(GNAME MainReturnDecl):
3432-
$(D void)
3433-
$(D int)
3434-
$(GLINK2 type, noreturn)
3435-
$(RELATIVE_LINK2 auto-functions, $(D auto))
3436-
$(GLINK_LEX Identifier)
3425+
$(P The `main` function must be named `main`. Other names are not possible,
3426+
not even using `pragma(mangle)` to change the mangling to the expected one.
3427+
)
34373428

3438-
$(GNAME MainFunctionBody):
3439-
$(GLINK ShortenedFunctionBody)
3440-
$(GLINK SpecifiedFunctionBody)
3441-
)
3429+
$(P The return type of `main` must be a possibly qualified version of `void`, `int`,
3430+
any `enum` type backed by `int`, or `noreturn`.
34423431

34433432
$(UL
34443433
$(LI If `main` returns `void`, the OS will receive a zero value on success.)
34453434
$(LI If `main` returns `void` or `noreturn`, the OS will receive a non-zero
34463435
value on abnormal termination, such as an uncaught exception.)
3436+
$(LI If `main` returns `int` or an `enum` type backed by `int`,
3437+
the OS will receive the returned value on success
3438+
and a non-zero value on abnormal termination.)
34473439
$(LI If `main` is declared as `auto`, the inferred return type must be
3448-
one of `void`, `int` and `noreturn`.)
3440+
one of the allowed types.)
3441+
)
3442+
3443+
$(P The `main` function must have either no parameters or a single parameter.
3444+
If provided, the parameter must be a qualified version of `char[][]`,
3445+
and can optionally have the $(GLINK ParameterAttributes) `in`, `return` or `scope`.
3446+
It is customary to use `immutable(char)[][]`, i.e. `string[]`,
3447+
but, e.g., `char[][]` and `immutable(string)[]` are also allowed.
3448+
The argument passed to a `main` function with parameter is mutable and unique,
3449+
which is why it converts to `immutable`, `inout`, or `shared`.
34493450
)
34503451

34513452
$(P If the parameter is declared, it will hold
3452-
arguments passed to the program by the OS. The index-0 element is typically
3453+
arguments passed to the program by the operating system.
3454+
The index-0 element is typically
34533455
the executable name, followed by any command-line arguments.)
34543456

34553457
$(NOTE The runtime can remove any arguments prefixed `--DRT-`.)
34563458

3457-
$(NOTE The aforementioned return / parameter types may be annotated with $(D const) or
3458-
$(D immutable), or carry $(GLINK ParameterAttributes).
3459-
They may also be replaced by $(D enum) types with matching base types.)
3460-
34613459
$(P The main function must have D linkage.)
34623460

34633461
$(P Attributes may be added as needed, e.g. `@safe`, `@nogc`, `nothrow`, etc.)
34643462

3463+
$(P The following grammar specification is an approximation of what is allowed for a D `main` function:)
3464+
3465+
$(INFORMATIVE_GRAMMAR
3466+
$(GNAME MainFunction):
3467+
$(GLINK2 declaration, StorageClasses)$(OPT) $(GLINK MainReturnType) main $(D $(LPAREN)) $(GLINK MainParameters) $(D $(RPAREN)) $(GLINK FunctionAttributes)$(OPT) $(GLINK MainFunctionBody)
3468+
$(GLINK2 declaration, StorageClasses) main $(D $(LPAREN)) $(GLINK MainParameters) $(D $(RPAREN)) $(GLINK FunctionAttributes)$(OPT) $(GLINK MainFunctionBody)
3469+
3470+
$(GNAME MainReturnType):
3471+
$(GLINK MainReturnBasicType)
3472+
$(GLINK2 type, TypeCtor) $(D $(LPAREN)) $(GLINK2 type, TypeCtors)$(OPT) $(GLINK MainReturnBasicType) $(D $(RPAREN))
3473+
3474+
$(GNAME MainReturnBasicType):
3475+
$(D void)
3476+
$(D int)
3477+
$(GLINK_LEX Identifier)
3478+
3479+
$(GNAME MainParameters):
3480+
$(GLINK MainParameter)
3481+
$(GLINK MainParameter) $(D ,)
3482+
3483+
$(GNAME MainParameter):
3484+
$(GLINK MainParameterDeclaration)
3485+
$(GLINK MainParameterDeclaration) = $(GLINK2 expression, AssignExpression)
3486+
3487+
$(GNAME MainParameterDeclaration):
3488+
$(GLINK ParameterAttributes)$(OPT) $(GLINK MainParameterBasicType) $(GLINK MainParameterTypeSuffixes)$(OPT) $(GLINK_LEX Identifier)$(OPT)
3489+
3490+
$(GNAME MainParameterBasicType):
3491+
$(D char)
3492+
$(GLINK2 type, TypeCtor) $(D $(LPAREN)) $(GLINK2 type, TypeCtors)$(OPT) $(GLINK MainParameterBasicType) $(GLINK MainParameterTypeSuffixes)$(OPT) $(D $(RPAREN))
3493+
$(GLINK_LEX Identifier)
3494+
3495+
$(GNAME MainParameterTypeSuffixes):
3496+
$(D [) $(D ])
3497+
$(D [) $(D ]) $(D [) $(D ])
3498+
3499+
$(GNAME MainFunctionBody):
3500+
$(GLINK SpecifiedFunctionBody)
3501+
$(GLINK ShortenedFunctionBody)
3502+
)
3503+
3504+
$(NOTE For $(GLINK MainReturnBasicType), the options of returning `noreturn` or an `enum` type are both covered by $(GLINK_LEX Identifier).)
3505+
34653506
$(H2 $(LNAME2 betterc-main, $(D extern(C)) $(D main) Function))
34663507

3467-
$(P Programs may define an $(D extern(C) main) function as an alternative to the
3508+
$(P Programs may define a `main` function with $(D extern(C)) linkage as an alternative to the
34683509
standard $(RELATIVE_LINK2 main, entry point). This form is required for
34693510
$(DDLINK spec/betterc, Better C, $(B BetterC)) programs.)
34703511

3471-
$(P A C $(D main) function is typically declared as follows:)
3512+
$(P A C `main` function differs from a D `main` function as follows:)
34723513

3473-
$(INFORMATIVE_GRAMMAR
3474-
$(GNAME CMainFunction):
3475-
$(D extern) $(LPAREN) $(D C) $(RPAREN) $(GLINK MainReturnDecl) $(D main) $(LPAREN) $(GLINK CMainParameters)$(OPT) $(RPAREN) $(GLINK2 statement, BlockStatement)
3476-
3477-
$(GNAME CMainParameters):
3478-
$(D int) $(GLINK_LEX Identifier)$(OPT) $(D ,) $(D char**) $(GLINK_LEX Identifier)$(OPT)
3479-
$(D int) $(GLINK_LEX Identifier)$(OPT) $(D ,) $(D char**) $(GLINK_LEX Identifier)$(OPT) $(D ,) $(D char**) $(GLINK_LEX Identifier)$(OPT)
3480-
)
3514+
$(UL
3515+
$(LI It has `extern(C)` linkage.)
3516+
$(LI If it has parameters, it has C `main` parameters instead of the D `main` parameter.)
3517+
$(LI No setup or teardown runs before or after a C `main` function.)
3518+
)
34813519

3482-
$(P When defined, the first two parameters denote a C-style array (length + pointer)
3483-
that holds the arguments passed to the program by the OS. The third parameter is a POSIX
3484-
extension called $(D environ) and holds information about the current environment variables.)
3520+
$(P All other rules for a D `main` function apply to C `main` functions.)
34853521

3486-
$(NOTE The exemption for storage classes / $(D enum)'s defined for a D $(D main) function
3487-
also applies to C $(D main) functions.)
3522+
$(P A C `main` function may have no parameters, two parameters, or three parameters.
3523+
When defined, the first two parameters denote a C-style array (length and pointer)
3524+
that holds the arguments passed to the program by the operating system. The third parameter, if present,
3525+
holds information about the current environment variables.)
34883526

3489-
$(P This function takes the place of the C main function and is executed immediately without
3490-
any setup or teardown associated with a D $(D main) function. Programs reliant on module
3491-
constructors, module destructors, or unittests need to manually perform (de)initialization
3527+
$(P A C `main` function is executed immediately without
3528+
any setup or teardown associated with a D `main` function. Programs reliant on module
3529+
constructors, module destructors, or unittests need to manually perform (de-)initialization
34923530
using the appropriate $(DDSUBLINK phobos/core_runtime, Runtime, runtime functions).)
34933531

34943532
$(IMPLEMENTATION_DEFINED Other system-specific entry points may exist, such as
34953533
`WinMain` and `DllMain` on Windows systems.
34963534
)
34973535

3498-
$(NOTE Programs targeting platforms which require a different signature for $(D main) can use
3536+
$(NOTE Programs targeting platforms which require a different signature for `main` can use
34993537
a function with $(DDSUBLINK spec/pragma, mangle, explicit mangling):
35003538

35013539
---
@@ -3505,9 +3543,52 @@ $(GNAME CMainParameters):
35053543
return 0;
35063544
}
35073545
---
3508-
35093546
)
35103547

3548+
$(P The following grammar specification is an approximation of what is allowed for a C `main` function:)
3549+
3550+
$(INFORMATIVE_GRAMMAR
3551+
$(GNAME CMainFunction):
3552+
$(GLINK2 declaration, StorageClasses)$(OPT) $(GLINK MainReturnType) main $(D $(LPAREN)) $(GLINK CMainParameters)$(OPT) $(D $(RPAREN)) $(GLINK FunctionAttributes)$(OPT) $(GLINK MainFunctionBody)
3553+
3554+
$(GNAME CMainParameters):
3555+
$(GLINK CMainParameterList)
3556+
$(GLINK CMainParameterList) $(D ,)
3557+
3558+
$(GNAME CMainParameterList):
3559+
$(GLINK CMainFirstParameter) $(D ,) $(GLINK CMainNextParameter)
3560+
$(GLINK CMainFirstParameter) $(D ,) $(GLINK CMainNextParameter) $(D ,) $(GLINK CMainNextParameter)
3561+
3562+
$(GNAME CMainFirstParameter):
3563+
$(GLINK CMainFirstParameterDeclaration)
3564+
$(GLINK CMainFirstParameterDeclaration) = $(GLINK2 expression, AssignExpression)
3565+
3566+
$(GNAME CMainNextParameter):
3567+
$(GLINK CMainNextParameterDeclaration)
3568+
$(GLINK CMainNextParameterDeclaration) = $(GLINK2 expression, AssignExpression)
3569+
3570+
$(GNAME CMainFirstParameterDeclaration):
3571+
$(GLINK ParameterAttributes)$(OPT) $(GLINK CMainFirstParameterBasicType) $(GLINK_LEX Identifier)$(OPT)
3572+
3573+
$(GNAME CMainFirstParameterBasicType):
3574+
$(D int)
3575+
$(GLINK2 type, TypeCtor) $(D $(LPAREN)) $(GLINK2 type, TypeCtors)$(OPT) $(GLINK CMainFirstParameterBasicType) $(D $(RPAREN))
3576+
$(GLINK_LEX Identifier)
3577+
3578+
$(GNAME CMainNextParameterDeclaration):
3579+
$(GLINK ParameterAttributes)$(OPT) $(GLINK CMainNextParameterBasicType) $(GLINK CMainParameterTypeSuffixes)$(OPT) $(GLINK_LEX Identifier)$(OPT)
3580+
3581+
$(GNAME CMainNextParameterBasicType):
3582+
$(D char)
3583+
$(GLINK2 type, TypeCtor) $(LPAREN) $(GLINK2 type, TypeCtors)$(OPT) $(GLINK CMainNextParameterBasicType) $(GLINK CMainParameterTypeSuffixes)$(OPT) $(RPAREN)
3584+
$(GLINK_LEX Identifier)
3585+
3586+
$(GNAME CMainParameterTypeSuffixes):
3587+
$(D *)
3588+
$(D *) $(D *)
3589+
)
3590+
3591+
$(NOTE For $(GLINK MainReturnBasicType), the options of returning `noreturn` or an `enum` type are both covered by $(GLINK_LEX Identifier).)
35113592

35123593
$(H2 $(LNAME2 function-templates, Function Templates))
35133594

0 commit comments

Comments
 (0)