/* Stubby - Generate stubs for dynamic-link libraries. * Copyright 1999 Tom Rothamel * * Stubby is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. It is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * This program generates another computer program. I do not assert a * copyright on the generated program that is the normal output of this * program. This is _not_, however, an authorization for you to modify * this program to cause it to output more of itself than necessary for * its proper operation in order to circumvent my copyright. */ /* This file contains the parser for the c-like input file format. */ %{ #include "stubby.h" #include "string.h" #include "str.h" #define YYDEBUG 1 %} %union { PTE *pte; char *str; int i; } %token NAME %token TYPESTR %token STRING %token DEBUG %token INCLUDE %token LIBRARY %token TYPE %token VOID %token CONST %token LOAD %token STRUCT %type definition; %type proto; %type pointer; %% input: | input ';' | input statement ';' | input INCLUDE STRING ';' { /* This has to be here so the ';' is consumed before we begin parsing the new file. */ include($3); } ; statement: DEBUG STRING { debug("%s", $2); } | TYPE NAME { add_type($2); free($2); } | TYPE TYPESTR { warn("%s is already a type.", $2); } | LIBRARY NAME STRING { library($2, $3); } | LOAD STRING { load($2); } | definition { definition($1); } ; definition: proto NAME { if (!$1) { error("Variable name without type '%s'.", $2); YYERROR; } $1->type = PTE_VAR; $1->name = $2; $$ = $1; } | proto NAME '(' proto ')' { $$ = newPTE(); $$->type = PTE_FUNCTION; $$->fproto = $1; $$->name = $2; $$->args = $4; } | proto '(' pointer NAME ')' '(' proto ')' { $$ = newPTE(); $$->fproto = $1; $$->type = PTE_VARF; $$->name = $4; $$->args = $7; $$->pdepth = $3; } ; proto:{ $$ = NULL; } | VOID { $$ = NULL; } | VOID pointer { $$ = newPTE(); $$->type = PTE_PROTO; $$->proto = strdup("void "); $$->proto = straf($$->proto, strptr($2)); } | TYPESTR { $$ = newPTE(); $$->type = PTE_PROTO; $$->proto = strappend($1, " "); } | STRUCT TYPESTR { $$ = newPTE(); $$->type = PTE_PROTO; $$->proto = strdup("struct "); $$->proto = strappend($$->proto, $2); $$->proto = strappend($$->proto, " "); } | STRUCT NAME { $$ = newPTE(); $$->type = PTE_PROTO; $$->proto = strdup("struct "); $$->proto = strappend($$->proto, $2); $$->proto = strappend($$->proto, " "); } | CONST proto { char *oldproto; $$ = $2; oldproto = $$->proto; $$->proto = strdup("const "); $$->proto = straf($$->proto, oldproto); } | proto pointer { $$ = $1; $$->proto = straf($1->proto, strptr($2)); } | proto '(' pointer ')' '(' proto ')' { $$ = newPTE(); $$->type = PTE_PROTOF; $$->fproto = $1; $$->pdepth = $3; $$->args = $6; } | proto ',' proto { PTE *pte; pte = $1; while (pte->next) pte = pte->next; pte->next = $3; $$ = $1; } | definition { $$ = $1; } ; pointer: '*' { $$ = 1; } | pointer '*' { $$ = $1 + 1; } ; %% int yyerror(char *s) { error("%s", s); exit(-1); }