/* * Parse and validate C declarations. * Copyright © 2011 Nick Bowler * * This program 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 3 of the License, or * (at your option) any later version. * * This program 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, see . */ #include #include #include "cdecl.h" #include "typemap.h" #include "parse.h" #include "scan.h" static int verify_declspecs(struct cdecl_declspec *s) { unsigned num_storage = 0; unsigned long typemap; typemap = cdecl__build_typemap(s); if (typemap == -1) return -1; for (struct cdecl_declspec *c = s; c; c = c->next) { switch (cdecl_spec_kind(c)) { case CDECL_SPEC_TYPE: continue; case CDECL_SPEC_STOR: if (++num_storage > 1) { fprintf(stderr, "too many storage-class specifiers\n"); return -1; } break; case CDECL_SPEC_QUAL: /* * Restrict qualifiers are only valid in the * pointer qualifier list, which isn't checked here. */ if (c->type == CDECL_QUAL_RESTRICT) { fprintf(stderr, "only pointer types can be restrict-qualified.\n"); return -1; } break; case CDECL_SPEC_FUNC: /* * We don't support functions yet. */ fprintf(stderr, "only function declarations may have function specifiers.\n"); return -1; default: assert(0); } } return 0; } static int verify_decl(struct cdecl *decl) { return verify_declspecs(decl->specifiers); } struct cdecl *cdecl_parse_decl(const char *declstr) { YY_BUFFER_STATE state; struct cdecl *decl; int rc; state = yy_scan_string(declstr); rc = yyparse(&decl); yy_delete_buffer(state); if (rc != 0) return NULL; rc = verify_decl(decl); if (rc != 0) { cdecl_free(decl); return NULL; } return decl; }