darling-bootstrap_cmds/migcom.tproj/parser.y
2023-01-28 13:25:04 -08:00

804 lines
18 KiB
Plaintext

/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
%token sySkip
%token syRoutine
%token sySimpleRoutine
%token sySubsystem
%token syKernelUser
%token syKernelServer
%token syMsgOption
%token syUseSpecialReplyPort
%token syConsumeOnSendError
%token syMsgSeqno
%token syWaitTime
%token sySendTime
%token syNoWaitTime
%token syNoSendTime
%token syErrorProc
%token syServerPrefix
%token syUserPrefix
%token syServerDemux
%token syRCSId
%token syImport
%token syUImport
%token sySImport
%token syIImport
%token syDImport
%token syIn
%token syOut
%token syInOut
%token syUserImpl
%token syServerImpl
%token syRequestPort
%token syReplyPort
%token sySReplyPort
%token syUReplyPort
%token syType
%token syArray
%token syStruct
%token syOf
%token syInTran
%token syOutTran
%token syDestructor
%token syCType
%token syCUserType
%token syUserTypeLimit
%token syOnStackLimit
%token syCServerType
%token syPointerTo
%token syPointerToIfNot
%token syValueOf
%token syCString
%token sySecToken
%token syUserSecToken
%token syServerSecToken
%token syAuditToken
%token syUserAuditToken
%token syServerAuditToken
%token syServerContextToken
%token syColon
%token sySemi
%token syComma
%token syPlus
%token syMinus
%token syStar
%token syDiv
%token syLParen
%token syRParen
%token syEqual
%token syCaret
%token syTilde
%token syLAngle
%token syRAngle
%token syLBrack
%token syRBrack
%token syBar
%token syError /* lex error */
%token <number> syNumber
%token <symtype> sySymbolicType
%token <identifier> syIdentifier
%token <string> syString syQString
%token <string> syFileName
%token <flag> syIPCFlag
%left syPlus syMinus
%left syStar syDiv
%type <statement_kind> ImportIndicant
%type <number> VarArrayHead ArrayHead StructHead IntExp
%type <type> NamedTypeSpec TransTypeSpec NativeTypeSpec TypeSpec
%type <type> CStringSpec
%type <type> BasicTypeSpec PrevTypeSpec ArgumentType
%type <identifier> TypePhrase
%type <symtype> PrimIPCType IPCType
%type <routine> RoutineDecl Routine SimpleRoutine
%type <direction> Direction TrImplKeyword
%type <argument> Argument Trailer Arguments ArgumentList
%type <flag> IPCFlags
%{
#include <stdio.h>
#include "lexxer.h"
#include "strdefs.h"
#include "type.h"
#include "routine.h"
#include "statement.h"
#include "global.h"
#include "error.h"
static char *import_name(statement_kind_t sk);
extern int yylex(void);
/* forward declaration */
void yyerror(char *s);
%}
%union
{
u_int number;
identifier_t identifier;
string_t string;
statement_kind_t statement_kind;
ipc_type_t *type;
struct
{
u_int innumber; /* msgt_name value, when sending */
string_t instr;
u_int outnumber; /* msgt_name value, when receiving */
string_t outstr;
u_int size; /* 0 means there is no default size */
} symtype;
routine_t *routine;
arg_kind_t direction;
argument_t *argument;
ipc_flags_t flag;
}
%%
Statements : /* empty */
| Statements Statement
;
Statement : Subsystem sySemi
| WaitTime sySemi
| SendTime sySemi
| MsgOption sySemi
| UseSpecialReplyPort sySemi
| ConsumeOnSendError sySemi
| UserTypeLimit sySemi
| OnStackLimit sySemi
| Error sySemi
| ServerPrefix sySemi
| UserPrefix sySemi
| ServerDemux sySemi
| TypeDecl sySemi
| RoutineDecl sySemi
{
statement_t *st = stAlloc();
st->stKind = skRoutine;
st->stRoutine = $1;
rtCheckRoutine($1);
if (BeVerbose)
rtPrintRoutine($1);
}
| sySkip sySemi
{ rtSkip(); }
| Import sySemi
| RCSDecl sySemi
| sySemi
| error sySemi
{ yyerrok; }
;
Subsystem : SubsystemStart SubsystemMods
SubsystemName SubsystemBase
{
if (BeVerbose) {
printf("Subsystem %s: base = %u%s%s\n\n",
SubsystemName, SubsystemBase,
IsKernelUser ? ", KernelUser" : "",
IsKernelServer ? ", KernelServer" : "");
}
}
;
SubsystemStart : sySubsystem
{
if (SubsystemName != strNULL) {
warn("previous Subsystem decl (of %s) will be ignored", SubsystemName);
IsKernelUser = FALSE;
IsKernelServer = FALSE;
strfree(SubsystemName);
}
}
;
SubsystemMods : /* empty */
| SubsystemMods SubsystemMod
;
SubsystemMod : syKernelUser
{
if (IsKernelUser)
warn("duplicate KernelUser keyword");
if (!UseMsgRPC) {
warn("with KernelUser the -R option is meaningless");
UseMsgRPC = TRUE;
}
IsKernelUser = TRUE;
}
| syKernelServer
{
if (IsKernelServer)
warn("duplicate KernelServer keyword");
IsKernelServer = TRUE;
}
;
SubsystemName : syIdentifier { SubsystemName = $1; }
;
SubsystemBase : syNumber { SubsystemBase = $1; }
;
MsgOption : LookString syMsgOption syString
{
if (streql($3, "MACH_MSG_OPTION_NONE")) {
MsgOption = strNULL;
if (BeVerbose)
printf("MsgOption: canceled\n\n");
}
else {
MsgOption = $3;
if (BeVerbose)
printf("MsgOption %s\n\n",$3);
}
}
;
UseSpecialReplyPort : syUseSpecialReplyPort syNumber
{
UseSpecialReplyPort = ($2 != 0);
HasUseSpecialReplyPort |= UseSpecialReplyPort;
}
;
ConsumeOnSendError : LookString syConsumeOnSendError syString
{
if (strcasecmp($3, "None") == 0) {
ConsumeOnSendError = ConsumeOnSendErrorNone;
} else if (strcasecmp($3, "Timeout") == 0) {
ConsumeOnSendError = ConsumeOnSendErrorTimeout;
HasConsumeOnSendError = TRUE;
} else if (strcasecmp($3, "Any") == 0) {
ConsumeOnSendError = ConsumeOnSendErrorAny;
HasConsumeOnSendError = TRUE;
} else {
error("syntax error");
}
}
;
UserTypeLimit : syUserTypeLimit syNumber
{UserTypeLimit = $2; }
;
OnStackLimit : syOnStackLimit syNumber
{MaxMessSizeOnStack = $2; }
;
WaitTime : LookString syWaitTime syString
{
WaitTime = $3;
if (BeVerbose)
printf("WaitTime %s\n\n", WaitTime);
}
| syNoWaitTime
{
WaitTime = strNULL;
if (BeVerbose)
printf("NoWaitTime\n\n");
}
;
SendTime : LookString sySendTime syString
{
SendTime = $3;
if (BeVerbose)
printf("SendTime %s\n\n", SendTime);
}
| syNoSendTime
{
SendTime = strNULL;
if (BeVerbose)
printf("NoSendTime\n\n");
}
;
Error : syErrorProc syIdentifier
{
ErrorProc = $2;
if (BeVerbose)
printf("ErrorProc %s\n\n", ErrorProc);
}
;
ServerPrefix : syServerPrefix syIdentifier
{
ServerPrefix = $2;
if (BeVerbose)
printf("ServerPrefix %s\n\n", ServerPrefix);
}
;
UserPrefix : syUserPrefix syIdentifier
{
UserPrefix = $2;
if (BeVerbose)
printf("UserPrefix %s\n\n", UserPrefix);
}
;
ServerDemux : syServerDemux syIdentifier
{
ServerDemux = $2;
if (BeVerbose)
printf("ServerDemux %s\n\n", ServerDemux);
}
;
Import : LookFileName ImportIndicant syFileName
{
statement_t *st = stAlloc();
st->stKind = $2;
st->stFileName = $3;
if (BeVerbose)
printf("%s %s\n\n", import_name($2), $3);
}
;
ImportIndicant : syImport { $$ = skImport; }
| syUImport { $$ = skUImport; }
| sySImport { $$ = skSImport; }
| syIImport { $$ = skIImport; }
| syDImport { $$ = skDImport; }
;
RCSDecl : LookQString syRCSId syQString
{
if (RCSId != strNULL)
warn("previous RCS decl will be ignored");
if (BeVerbose)
printf("RCSId %s\n\n", $3);
RCSId = $3;
}
;
TypeDecl : syType NamedTypeSpec
{
identifier_t name = $2->itName;
if (itLookUp(name) != itNULL)
warn("overriding previous definition of %s", name);
itInsert(name, $2);
}
;
NamedTypeSpec : syIdentifier syEqual TransTypeSpec
{ itTypeDecl($1, $$ = $3); }
;
TransTypeSpec : TypeSpec
{ $$ = itResetType($1); }
| TransTypeSpec syInTran syColon syIdentifier
syIdentifier syLParen syIdentifier syRParen
{
$$ = $1;
if (($$->itTransType != strNULL) && !streql($$->itTransType, $4))
warn("conflicting translation types (%s, %s)", $$->itTransType, $4);
$$->itTransType = $4;
if (($$->itInTrans != strNULL) && !streql($$->itInTrans, $5))
warn("conflicting in-translation functions (%s, %s)", $$->itInTrans, $5);
$$->itInTrans = $5;
if (($$->itServerType != strNULL) && !streql($$->itServerType, $7))
warn("conflicting server types (%s, %s)", $$->itServerType, $7);
$$->itServerType = $7;
}
| TransTypeSpec syOutTran syColon syIdentifier
syIdentifier syLParen syIdentifier syRParen
{
$$ = $1;
if (($$->itServerType != strNULL) && !streql($$->itServerType, $4))
warn("conflicting server types (%s, %s)", $$->itServerType, $4);
$$->itServerType = $4;
if (($$->itOutTrans != strNULL) && !streql($$->itOutTrans, $5))
warn("conflicting out-translation functions (%s, %s)", $$->itOutTrans, $5);
$$->itOutTrans = $5;
if (($$->itTransType != strNULL) && !streql($$->itTransType, $7))
warn("conflicting translation types (%s, %s)", $$->itTransType, $7);
$$->itTransType = $7;
}
| TransTypeSpec syDestructor syColon syIdentifier
syLParen syIdentifier syRParen
{
$$ = $1;
if (($$->itDestructor != strNULL) && !streql($$->itDestructor, $4))
warn("conflicting destructor functions (%s, %s)", $$->itDestructor, $4);
$$->itDestructor = $4;
if (($$->itTransType != strNULL) && !streql($$->itTransType, $6))
warn("conflicting translation types (%s, %s)", $$->itTransType, $6);
$$->itTransType = $6;
}
| TransTypeSpec syCType syColon syIdentifier
{
$$ = $1;
if (($$->itUserType != strNULL) && !streql($$->itUserType, $4))
warn("conflicting user types (%s, %s)", $$->itUserType, $4);
$$->itUserType = $4;
if (($$->itServerType != strNULL) && !streql($$->itServerType, $4))
warn("conflicting server types (%s, %s)", $$->itServerType, $4);
$$->itServerType = $4;
}
| TransTypeSpec syCUserType syColon syIdentifier
{
$$ = $1;
if (($$->itUserType != strNULL) && !streql($$->itUserType, $4))
warn("conflicting user types (%s, %s)", $$->itUserType, $4);
$$->itUserType = $4;
}
| TransTypeSpec syCServerType
syColon syIdentifier
{
$$ = $1;
if (($$->itServerType != strNULL) && !streql($$->itServerType, $4))
warn("conflicting server types (%s, %s)",
$$->itServerType, $4);
$$->itServerType = $4;
}
;
TypeSpec : BasicTypeSpec
{ $$ = $1; }
| PrevTypeSpec
{ $$ = $1; }
| VarArrayHead TypeSpec
{ $$ = itVarArrayDecl($1, $2); }
| ArrayHead TypeSpec
{ $$ = itArrayDecl($1, $2); }
| syCaret TypeSpec
{ $$ = itPtrDecl($2); }
| StructHead TypeSpec
{ $$ = itStructDecl($1, $2); }
| CStringSpec
{ $$ = $1; }
| NativeTypeSpec
{ $$ = $1; }
;
NativeTypeSpec : syPointerTo syLParen TypePhrase syRParen
{ $$ = itNativeType($3, TRUE, 0); }
| syPointerToIfNot syLParen TypePhrase syComma
TypePhrase syRParen
{ $$ = itNativeType($3, TRUE, $5); }
| syValueOf syLParen TypePhrase syRParen
{ $$ = itNativeType($3, FALSE, 0); }
;
BasicTypeSpec : IPCType
{
$$ = itShortDecl($1.innumber, $1.instr,
$1.outnumber, $1.outstr,
$1.size);
}
| syLParen IPCType syComma IntExp
IPCFlags syRParen
{
error("Long form type declarations aren't allowed any longer\n");
}
;
PrimIPCType : syNumber
{
$$.innumber = $$.outnumber = $1;
$$.instr = $$.outstr = strNULL;
$$.size = 0;
}
| sySymbolicType
{ $$ = $1; }
;
IPCType : PrimIPCType
{ $$ = $1; }
| PrimIPCType syBar PrimIPCType
{
if ($1.size != $3.size) {
if ($1.size == 0)
$$.size = $3.size;
else if ($3.size == 0)
$$.size = $1.size;
else {
error("sizes in IPCTypes (%d, %d) aren't equal",
$1.size, $3.size);
$$.size = 0;
}
}
else
$$.size = $1.size;
$$.innumber = $1.innumber;
$$.instr = $1.instr;
$$.outnumber = $3.outnumber;
$$.outstr = $3.outstr;
}
;
PrevTypeSpec : syIdentifier
{ $$ = itPrevDecl($1); }
;
VarArrayHead : syArray syLBrack syRBrack syOf
{ $$ = 0; }
| syArray syLBrack syStar syRBrack syOf
{ $$ = 0; }
| syArray syLBrack syStar syColon IntExp
syRBrack syOf
{ $$ = $5; }
;
ArrayHead : syArray syLBrack IntExp syRBrack syOf
{ $$ = $3; }
;
StructHead : syStruct syLBrack IntExp syRBrack syOf
{ $$ = $3; }
;
CStringSpec : syCString syLBrack IntExp syRBrack
{ $$ = itCStringDecl($3, FALSE); }
| syCString syLBrack syStar syColon
IntExp syRBrack
{ $$ = itCStringDecl($5, TRUE); }
;
TypePhrase : syIdentifier
{ $$ = $1; }
| TypePhrase syIdentifier
{ $$ = strphrase($1, $2); strfree($2); }
;
IntExp : IntExp syPlus IntExp
{ $$ = $1 + $3; }
| IntExp syMinus IntExp
{ $$ = $1 - $3; }
| IntExp syStar IntExp
{ $$ = $1 * $3; }
| IntExp syDiv IntExp
{ $$ = $1 / $3; }
| syNumber
{ $$ = $1; }
| syLParen IntExp syRParen
{ $$ = $2; }
;
RoutineDecl : Routine { $$ = $1; }
| SimpleRoutine { $$ = $1; }
;
Routine : syRoutine syIdentifier Arguments
{ $$ = rtMakeRoutine($2, $3); }
;
SimpleRoutine : sySimpleRoutine syIdentifier Arguments
{ $$ = rtMakeSimpleRoutine($2, $3); }
;
Arguments : syLParen syRParen
{ $$ = argNULL; }
| syLParen ArgumentList syRParen
{ $$ = $2; }
;
ArgumentList : Argument
{ $$ = $1; }
| Trailer
{ $$ = $1; }
| Argument sySemi ArgumentList
{
$$ = $1;
$$->argNext = $3;
}
| Trailer sySemi ArgumentList
{
$$ = $1;
$$->argNext = $3;
}
;
Argument : Direction syIdentifier ArgumentType IPCFlags
{
$$ = argAlloc();
$$->argKind = $1;
$$->argName = $2;
$$->argType = $3;
$$->argFlags = $4;
if ($3 && $3->itNative) {
if ($1 != akIn && $1 != akOut && $1 != akInOut)
error("Illegal direction specified");
if (!($3->itNativePointer) && $1 != akIn)
error("ValueOf only valid for in");
if (($3->itBadValue) != NULL && $1 != akIn)
error("PointerToIfNot only valid for in");
}
}
;
Trailer : TrImplKeyword syIdentifier ArgumentType
{
$$ = argAlloc();
$$->argKind = $1;
$$->argName = $2;
$$->argType = $3;
}
;
Direction : /* empty */ { $$ = akNone; }
| syIn { $$ = akIn; }
| syOut { $$ = akOut; }
| syInOut { $$ = akInOut; }
| syRequestPort { $$ = akRequestPort; }
| syReplyPort { $$ = akReplyPort; }
| sySReplyPort { $$ = akSReplyPort; }
| syUReplyPort { $$ = akUReplyPort; }
| syWaitTime { $$ = akWaitTime; }
| sySendTime { $$ = akSendTime; }
| syMsgOption { $$ = akMsgOption; }
| sySecToken { $$ = akSecToken; }
| syServerSecToken { $$ = akServerSecToken; }
| syUserSecToken { $$ = akUserSecToken; }
| syAuditToken { $$ = akAuditToken; }
| syServerAuditToken { $$ = akServerAuditToken; }
| syUserAuditToken { $$ = akUserAuditToken; }
| syServerContextToken { $$ = akServerContextToken; }
| syMsgSeqno { $$ = akMsgSeqno; }
;
TrImplKeyword : syServerImpl { $$ = akServerImpl; }
| syUserImpl { $$ = akUserImpl; }
;
ArgumentType : syColon syIdentifier
{
$$ = itLookUp($2);
if ($$ == itNULL)
error("type '%s' not defined", $2);
}
| syColon NamedTypeSpec
{ $$ = $2; }
| syColon NativeTypeSpec
{ $$ = $2; }
;
IPCFlags : /* empty */
{ $$ = flNone; }
| IPCFlags syComma syIPCFlag
{
if ($1 & $3)
warn("redundant IPC flag ignored");
else
$$ = $1 | $3;
}
| IPCFlags syComma syIPCFlag syLBrack syRBrack
{
if ($3 != flDealloc)
warn("only Dealloc is variable");
else
$$ = $1 | flMaybeDealloc;
}
LookString : /* empty */
{ LookString(); }
;
LookFileName : /* empty */
{ LookFileName(); }
;
LookQString : /* empty */
{ LookQString(); }
;
%%
void
yyerror(char *s)
{
error(s);
}
static char *
import_name(statement_kind_t sk)
{
switch (sk) {
case skImport:
return "Import";
case skSImport:
return "SImport";
case skUImport:
return "UImport";
case skIImport:
return "IImport";
case skDImport:
return "DImport";
default:
fatal("import_name(%d): not import statement", (int) sk);
/*NOTREACHED*/
return strNULL;
}
}