1/*
2 * Copyright (c) 1999, 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 * Mach Operating System
25 * Copyright (c) 1991,1990 Carnegie Mellon University
26 * All Rights Reserved.
27 *
28 * Permission to use, copy, modify and distribute this software and its
29 * documentation is hereby granted, provided that both the copyright
30 * notice and this permission notice appear in all copies of the
31 * software, derivative works or modified versions, and any portions
32 * thereof, and that both notices appear in supporting documentation.
33 *
34 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
35 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
36 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
37 *
38 * Carnegie Mellon requests users of this software to return to
39 *
40 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
41 *  School of Computer Science
42 *  Carnegie Mellon University
43 *  Pittsburgh PA 15213-3890
44 *
45 * any improvements or extensions that they make and grant Carnegie the
46 * rights to redistribute these changes.
47 */
48
49%token	sySkip
50%token	syRoutine
51%token	sySimpleRoutine
52
53%token	sySubsystem
54%token	syKernelUser
55%token	syKernelServer
56
57%token	syMsgOption
58%token	syMsgSeqno
59%token	syWaitTime
60%token	sySendTime
61%token	syNoWaitTime
62%token	syNoSendTime
63%token	syErrorProc
64%token	syServerPrefix
65%token	syUserPrefix
66%token	syServerDemux
67%token	syRCSId
68
69%token	syImport
70%token	syUImport
71%token	sySImport
72%token  syIImport
73%token  syDImport
74
75%token	syIn
76%token	syOut
77%token	syInOut
78%token	syUserImpl
79%token	syServerImpl
80%token	syRequestPort
81%token	syReplyPort
82%token	sySReplyPort
83%token	syUReplyPort
84
85%token	syType
86%token	syArray
87%token	syStruct
88%token	syOf
89
90%token	syInTran
91%token	syOutTran
92%token	syDestructor
93%token	syCType
94%token	syCUserType
95%token	syUserTypeLimit
96%token	syOnStackLimit
97%token	syCServerType
98%token  syPointerTo
99%token  syPointerToIfNot
100%token  syValueOf
101
102%token	syCString
103%token	sySecToken
104%token	syUserSecToken
105%token	syServerSecToken
106%token	syAuditToken
107%token	syUserAuditToken
108%token	syServerAuditToken
109%token	syServerContextToken
110
111%token	syColon
112%token	sySemi
113%token	syComma
114%token	syPlus
115%token	syMinus
116%token	syStar
117%token	syDiv
118%token	syLParen
119%token	syRParen
120%token	syEqual
121%token	syCaret
122%token	syTilde
123%token	syLAngle
124%token	syRAngle
125%token	syLBrack
126%token	syRBrack
127%token	syBar
128
129%token	syError			/* lex error */
130
131%token	<number>	syNumber
132%token	<symtype>	sySymbolicType
133%token	<identifier>	syIdentifier
134%token	<string>	syString syQString
135%token	<string>	syFileName
136%token	<flag>		syIPCFlag
137
138%left	syPlus syMinus
139%left	syStar syDiv
140
141
142%type	<statement_kind> ImportIndicant
143%type	<number> VarArrayHead ArrayHead StructHead IntExp
144%type	<type> NamedTypeSpec TransTypeSpec NativeTypeSpec TypeSpec
145%type	<type> CStringSpec
146%type	<type> BasicTypeSpec PrevTypeSpec ArgumentType
147%type   <identifier> TypePhrase
148%type	<symtype> PrimIPCType IPCType
149%type	<routine> RoutineDecl Routine SimpleRoutine
150%type	<direction> Direction TrImplKeyword
151%type	<argument> Argument Trailer Arguments ArgumentList
152%type	<flag> IPCFlags
153
154%{
155
156#include <stdio.h>
157#include "lexxer.h"
158#include "strdefs.h"
159#include "type.h"
160#include "routine.h"
161#include "statement.h"
162#include "global.h"
163#include "error.h"
164
165static char *import_name();
166extern int yylex(void);
167
168/* forward declaration */
169void yyerror(char *s);
170
171%}
172
173%union
174{
175    u_int number;
176    identifier_t identifier;
177    string_t string;
178    statement_kind_t statement_kind;
179    ipc_type_t *type;
180    struct
181    {
182      u_int innumber;		/* msgt_name value, when sending */
183      string_t instr;
184      u_int outnumber;	/* msgt_name value, when receiving */
185      string_t outstr;
186      u_int size;		/* 0 means there is no default size */
187    } symtype;
188    routine_t *routine;
189    arg_kind_t direction;
190    argument_t *argument;
191    ipc_flags_t flag;
192}
193
194%%
195
196Statements		:	/* empty */
197			|	Statements Statement
198			;
199
200Statement		:	Subsystem sySemi
201			|	WaitTime sySemi
202			|	SendTime sySemi
203			|	MsgOption sySemi
204                        |       UserTypeLimit sySemi
205                        |       OnStackLimit sySemi
206			|	Error sySemi
207			|	ServerPrefix sySemi
208			|	UserPrefix sySemi
209			|	ServerDemux sySemi
210			|	TypeDecl sySemi
211			|	RoutineDecl sySemi
212{
213    register statement_t *st = stAlloc();
214
215    st->stKind = skRoutine;
216    st->stRoutine = $1;
217    rtCheckRoutine($1);
218    if (BeVerbose)
219      rtPrintRoutine($1);
220}
221			|	sySkip sySemi
222				{ rtSkip(); }
223			|	Import sySemi
224			|	RCSDecl sySemi
225			|	sySemi
226			|	error sySemi
227				{ yyerrok; }
228			;
229
230Subsystem		:	SubsystemStart SubsystemMods
231				SubsystemName SubsystemBase
232{
233  if (BeVerbose) {
234    printf("Subsystem %s: base = %u%s%s\n\n",
235    SubsystemName, SubsystemBase,
236    IsKernelUser ? ", KernelUser" : "",
237    IsKernelServer ? ", KernelServer" : "");
238  }
239}
240			;
241
242SubsystemStart		:	sySubsystem
243{
244    if (SubsystemName != strNULL) {
245      warn("previous Subsystem decl (of %s) will be ignored", SubsystemName);
246      IsKernelUser = FALSE;
247      IsKernelServer = FALSE;
248      strfree(SubsystemName);
249    }
250}
251			;
252
253SubsystemMods		:	/* empty */
254			|	SubsystemMods SubsystemMod
255			;
256
257SubsystemMod		:	syKernelUser
258{
259    if (IsKernelUser)
260      warn("duplicate KernelUser keyword");
261    if (!UseMsgRPC) {
262      warn("with KernelUser the -R option is meaningless");
263      UseMsgRPC = TRUE;
264    }
265    IsKernelUser = TRUE;
266}
267			|	syKernelServer
268{
269    if (IsKernelServer)
270      warn("duplicate KernelServer keyword");
271    IsKernelServer = TRUE;
272}
273			;
274
275SubsystemName		:	syIdentifier	{ SubsystemName = $1; }
276			;
277
278SubsystemBase		:	syNumber	{ SubsystemBase = $1; }
279			;
280
281MsgOption		:	LookString syMsgOption syString
282{
283    if (streql($3, "MACH_MSG_OPTION_NONE")) {
284      MsgOption = strNULL;
285      if (BeVerbose)
286          printf("MsgOption: canceled\n\n");
287    }
288    else {
289      MsgOption = $3;
290      if (BeVerbose)
291          printf("MsgOption %s\n\n",$3);
292    }
293}
294			;
295
296UserTypeLimit           :       syUserTypeLimit syNumber
297				{UserTypeLimit = $2; }
298                        ;
299OnStackLimit            :       syOnStackLimit syNumber
300				{MaxMessSizeOnStack = $2; }
301                        ;
302
303WaitTime		:	LookString syWaitTime syString
304{
305    WaitTime = $3;
306    if (BeVerbose)
307      printf("WaitTime %s\n\n", WaitTime);
308}
309			|	syNoWaitTime
310{
311    WaitTime = strNULL;
312    if (BeVerbose)
313      printf("NoWaitTime\n\n");
314}
315			;
316
317SendTime		:	LookString sySendTime syString
318{
319    SendTime = $3;
320    if (BeVerbose)
321      printf("SendTime %s\n\n", SendTime);
322}
323			|	syNoSendTime
324{
325    SendTime = strNULL;
326    if (BeVerbose)
327      printf("NoSendTime\n\n");
328}
329			;
330
331Error			:	syErrorProc syIdentifier
332{
333    ErrorProc = $2;
334    if (BeVerbose)
335      printf("ErrorProc %s\n\n", ErrorProc);
336}
337			;
338
339ServerPrefix		:	syServerPrefix syIdentifier
340{
341    ServerPrefix = $2;
342    if (BeVerbose)
343      printf("ServerPrefix %s\n\n", ServerPrefix);
344}
345			;
346
347UserPrefix		:	syUserPrefix syIdentifier
348{
349    UserPrefix = $2;
350    if (BeVerbose)
351      printf("UserPrefix %s\n\n", UserPrefix);
352}
353			;
354
355ServerDemux		:	syServerDemux syIdentifier
356{
357    ServerDemux = $2;
358    if (BeVerbose)
359      printf("ServerDemux %s\n\n", ServerDemux);
360}
361			;
362
363Import			:	LookFileName ImportIndicant syFileName
364{
365    register statement_t *st = stAlloc();
366    st->stKind = $2;
367    st->stFileName = $3;
368
369    if (BeVerbose)
370      printf("%s %s\n\n", import_name($2), $3);
371}
372			;
373
374ImportIndicant		:	syImport	{ $$ = skImport; }
375			|	syUImport	{ $$ = skUImport; }
376			|	sySImport	{ $$ = skSImport; }
377			|	syIImport	{ $$ = skIImport; }
378			|	syDImport	{ $$ = skDImport; }
379			;
380
381RCSDecl			:	LookQString syRCSId syQString
382{
383    if (RCSId != strNULL)
384      warn("previous RCS decl will be ignored");
385    if (BeVerbose)
386      printf("RCSId %s\n\n", $3);
387    RCSId = $3;
388}
389			;
390
391TypeDecl		:	syType NamedTypeSpec
392{
393    register identifier_t name = $2->itName;
394
395    if (itLookUp(name) != itNULL)
396      warn("overriding previous definition of %s", name);
397    itInsert(name, $2);
398}
399			;
400
401NamedTypeSpec		:	syIdentifier syEqual TransTypeSpec
402				{ itTypeDecl($1, $$ = $3); }
403			;
404
405TransTypeSpec		:	TypeSpec
406				{ $$ = itResetType($1); }
407			|	TransTypeSpec syInTran syColon syIdentifier
408				syIdentifier syLParen syIdentifier syRParen
409{
410    $$ = $1;
411
412    if (($$->itTransType != strNULL) && !streql($$->itTransType, $4))
413      warn("conflicting translation types (%s, %s)", $$->itTransType, $4);
414    $$->itTransType = $4;
415
416    if (($$->itInTrans != strNULL) && !streql($$->itInTrans, $5))
417      warn("conflicting in-translation functions (%s, %s)", $$->itInTrans, $5);
418    $$->itInTrans = $5;
419
420    if (($$->itServerType != strNULL) && !streql($$->itServerType, $7))
421      warn("conflicting server types (%s, %s)", $$->itServerType, $7);
422    $$->itServerType = $7;
423}
424			|	TransTypeSpec syOutTran syColon syIdentifier
425				syIdentifier syLParen syIdentifier syRParen
426{
427    $$ = $1;
428
429    if (($$->itServerType != strNULL) && !streql($$->itServerType, $4))
430      warn("conflicting server types (%s, %s)", $$->itServerType, $4);
431    $$->itServerType = $4;
432
433    if (($$->itOutTrans != strNULL) && !streql($$->itOutTrans, $5))
434      warn("conflicting out-translation functions (%s, %s)", $$->itOutTrans, $5);
435    $$->itOutTrans = $5;
436
437    if (($$->itTransType != strNULL) && !streql($$->itTransType, $7))
438      warn("conflicting translation types (%s, %s)", $$->itTransType, $7);
439    $$->itTransType = $7;
440}
441			|	TransTypeSpec syDestructor syColon syIdentifier
442				syLParen syIdentifier syRParen
443{
444    $$ = $1;
445
446    if (($$->itDestructor != strNULL) && !streql($$->itDestructor, $4))
447      warn("conflicting destructor functions (%s, %s)", $$->itDestructor, $4);
448    $$->itDestructor = $4;
449
450    if (($$->itTransType != strNULL) && !streql($$->itTransType, $6))
451      warn("conflicting translation types (%s, %s)", $$->itTransType, $6);
452    $$->itTransType = $6;
453}
454			|	TransTypeSpec syCType syColon syIdentifier
455{
456    $$ = $1;
457
458    if (($$->itUserType != strNULL) && !streql($$->itUserType, $4))
459      warn("conflicting user types (%s, %s)", $$->itUserType, $4);
460    $$->itUserType = $4;
461
462    if (($$->itServerType != strNULL) && !streql($$->itServerType, $4))
463      warn("conflicting server types (%s, %s)", $$->itServerType, $4);
464    $$->itServerType = $4;
465}
466			|	TransTypeSpec syCUserType syColon syIdentifier
467{
468    $$ = $1;
469
470    if (($$->itUserType != strNULL) && !streql($$->itUserType, $4))
471      warn("conflicting user types (%s, %s)", $$->itUserType, $4);
472    $$->itUserType = $4;
473}
474			|	TransTypeSpec syCServerType
475				syColon syIdentifier
476{
477    $$ = $1;
478
479    if (($$->itServerType != strNULL) && !streql($$->itServerType, $4))
480	warn("conflicting server types (%s, %s)",
481	     $$->itServerType, $4);
482    $$->itServerType = $4;
483}
484			;
485
486TypeSpec		:	BasicTypeSpec
487				{ $$ = $1; }
488			|	PrevTypeSpec
489				{ $$ = $1; }
490			|	VarArrayHead TypeSpec
491				{ $$ = itVarArrayDecl($1, $2); }
492			|	ArrayHead TypeSpec
493				{ $$ = itArrayDecl($1, $2); }
494			|	syCaret TypeSpec
495				{ $$ = itPtrDecl($2); }
496			|	StructHead TypeSpec
497				{ $$ = itStructDecl($1, $2); }
498			|	CStringSpec
499				{ $$ = $1; }
500                        |       NativeTypeSpec
501				{ $$ = $1; }
502			;
503
504NativeTypeSpec          :       syPointerTo syLParen TypePhrase syRParen
505                                { $$ = itNativeType($3, TRUE, 0); }
506                        |       syPointerToIfNot syLParen TypePhrase syComma
507                                TypePhrase syRParen
508                                { $$ = itNativeType($3, TRUE, $5); }
509                        |       syValueOf syLParen TypePhrase syRParen
510                                { $$ = itNativeType($3, FALSE, 0); }
511			;
512
513BasicTypeSpec		:	IPCType
514{
515    $$ = itShortDecl($1.innumber, $1.instr,
516		     $1.outnumber, $1.outstr,
517		     $1.size);
518}
519			|	syLParen IPCType syComma IntExp
520				IPCFlags syRParen
521{
522    error("Long form type declarations aren't allowed any longer\n");
523}
524			;
525
526PrimIPCType		:	syNumber
527{
528    $$.innumber = $$.outnumber = $1;
529    $$.instr = $$.outstr = strNULL;
530    $$.size = 0;
531}
532			|	sySymbolicType
533				{ $$ = $1; }
534			;
535
536IPCType			:	PrimIPCType
537				{ $$ = $1; }
538			|	PrimIPCType syBar PrimIPCType
539{
540  if ($1.size != $3.size) {
541    if ($1.size == 0)
542      $$.size = $3.size;
543    else if ($3.size == 0)
544      $$.size = $1.size;
545    else {
546      error("sizes in IPCTypes (%d, %d) aren't equal",
547      $1.size, $3.size);
548      $$.size = 0;
549    }
550  }
551  else
552    $$.size = $1.size;
553  $$.innumber = $1.innumber;
554  $$.instr = $1.instr;
555  $$.outnumber = $3.outnumber;
556  $$.outstr = $3.outstr;
557}
558			;
559
560PrevTypeSpec		:	syIdentifier
561				{ $$ = itPrevDecl($1); }
562			;
563
564VarArrayHead		:	syArray syLBrack syRBrack syOf
565				{ $$ = 0; }
566			|	syArray syLBrack syStar syRBrack syOf
567				{ $$ = 0; }
568			|	syArray syLBrack syStar syColon IntExp
569				syRBrack syOf
570				{ $$ = $5; }
571			;
572
573ArrayHead		:	syArray syLBrack IntExp syRBrack syOf
574				{ $$ = $3; }
575			;
576
577StructHead		:	syStruct syLBrack IntExp syRBrack syOf
578				{ $$ = $3; }
579			;
580
581CStringSpec		:	syCString syLBrack IntExp syRBrack
582				{ $$ = itCStringDecl($3, FALSE); }
583			|	syCString syLBrack syStar syColon
584				IntExp syRBrack
585				{ $$ = itCStringDecl($5, TRUE); }
586			;
587
588TypePhrase              :       syIdentifier
589                                { $$ = $1; }
590                        |       TypePhrase syIdentifier
591                                { $$ = strphrase($1, $2); strfree($2); }
592			;
593
594IntExp			: 	IntExp	syPlus	IntExp
595				{ $$ = $1 + $3;	}
596			| 	IntExp	syMinus	IntExp
597				{ $$ = $1 - $3;	}
598			|	IntExp	syStar	IntExp
599				{ $$ = $1 * $3;	}
600			| 	IntExp	syDiv	IntExp
601				{ $$ = $1 / $3;	}
602			|	syNumber
603				{ $$ = $1;	}
604			|	syLParen IntExp syRParen
605				{ $$ = $2;	}
606			;
607
608
609RoutineDecl		:	Routine			{ $$ = $1; }
610			|	SimpleRoutine		{ $$ = $1; }
611			;
612
613Routine			:	syRoutine syIdentifier Arguments
614				{ $$ = rtMakeRoutine($2, $3); }
615			;
616
617SimpleRoutine		:	sySimpleRoutine syIdentifier Arguments
618				{ $$ = rtMakeSimpleRoutine($2, $3); }
619			;
620
621Arguments		:	syLParen syRParen
622				{ $$ = argNULL; }
623			|	syLParen ArgumentList syRParen
624				{ $$ = $2; }
625
626			;
627
628ArgumentList		:	Argument
629				{ $$ = $1; }
630			|       Trailer
631				{ $$ = $1; }
632			|	Argument sySemi ArgumentList
633{
634  $$ = $1;
635  $$->argNext = $3;
636}
637			|       Trailer sySemi ArgumentList
638{
639  $$ = $1;
640  $$->argNext = $3;
641}
642			;
643
644Argument		:	Direction syIdentifier ArgumentType IPCFlags
645{
646  $$ = argAlloc();
647  $$->argKind = $1;
648  $$->argName = $2;
649  $$->argType = $3;
650  $$->argFlags = $4;
651  if ($3 && $3->itNative) {
652      if ($1 != akIn && $1 != akOut && $1 != akInOut)
653        error("Illegal direction specified");
654
655      if (!($3->itNativePointer) && $1 != akIn)
656        error("ValueOf only valid for in");
657
658      if (($3->itBadValue) != NULL && $1 != akIn)
659        error("PointerToIfNot only valid for in");
660  }
661}
662			;
663
664Trailer			:	TrImplKeyword syIdentifier ArgumentType
665{
666    $$ = argAlloc();
667    $$->argKind = $1;
668    $$->argName = $2;
669    $$->argType = $3;
670}
671			;
672
673
674Direction		:	/* empty */	{ $$ = akNone; }
675			|	syIn		{ $$ = akIn; }
676			|	syOut		{ $$ = akOut; }
677			|	syInOut		{ $$ = akInOut; }
678			|	syRequestPort	{ $$ = akRequestPort; }
679			|	syReplyPort	{ $$ = akReplyPort; }
680			|	sySReplyPort	{ $$ = akSReplyPort; }
681			|	syUReplyPort	{ $$ = akUReplyPort; }
682			|	syWaitTime	{ $$ = akWaitTime; }
683			|	sySendTime 	{ $$ = akSendTime; }
684			|	syMsgOption	{ $$ = akMsgOption; }
685			|	sySecToken		{ $$ = akSecToken; }
686			|	syServerSecToken	{ $$ = akServerSecToken; }
687			|	syUserSecToken		{ $$ = akUserSecToken; }
688			|	syAuditToken		{ $$ = akAuditToken; }
689			|	syServerAuditToken	{ $$ = akServerAuditToken; }
690			|	syUserAuditToken	{ $$ = akUserAuditToken; }
691			|	syServerContextToken	{ $$ = akServerContextToken; }
692			|	syMsgSeqno	{ $$ = akMsgSeqno; }
693			;
694
695
696
697TrImplKeyword		:	syServerImpl	{ $$ = akServerImpl; }
698			|	syUserImpl	{ $$ = akUserImpl; }
699			;
700
701
702ArgumentType		:	syColon syIdentifier
703{
704  $$ = itLookUp($2);
705  if ($$ == itNULL)
706    error("type '%s' not defined", $2);
707}
708			|	syColon NamedTypeSpec
709				{ $$ = $2; }
710                        |       syColon NativeTypeSpec
711				{ $$ = $2; }
712			;
713
714IPCFlags		:	/* empty */
715				{ $$ = flNone; }
716			|	IPCFlags syComma syIPCFlag
717{
718  if ($1 & $3)
719    warn("redundant IPC flag ignored");
720  else
721    $$ = $1 | $3;
722}
723			|	IPCFlags syComma syIPCFlag syLBrack syRBrack
724{
725  if ($3 != flDealloc)
726    warn("only Dealloc is variable");
727  else
728    $$ = $1 | flMaybeDealloc;
729}
730
731LookString		:	/* empty */
732				{ LookString(); }
733			;
734
735LookFileName		:	/* empty */
736				{ LookFileName(); }
737			;
738
739LookQString		:	/* empty */
740				{ LookQString(); }
741			;
742
743%%
744
745void
746yyerror(char *s)
747{
748  error(s);
749}
750
751static char *
752import_name(statement_kind_t sk)
753{
754  switch (sk) {
755
756    case skImport:
757      return "Import";
758
759    case skSImport:
760      return "SImport";
761
762    case skUImport:
763      return "UImport";
764
765    case skIImport:
766      return "IImport";
767
768    case skDImport:
769      return "DImport";
770
771    default:
772      fatal("import_name(%d): not import statement", (int) sk);
773      /*NOTREACHED*/
774      return strNULL;
775  }
776}
777