/* * Scyther : An automatic verifier for security protocols. * Copyright (C) 2007-2013 Cas Cremers * * 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ %option yylineno %{ /* scanner for security protocols language */ #include #include #include "pheading.h" #include "tac.h" #include "switches.h" #include "error.h" /* tokens for language */ #include "parser.h" void mkname(char *name); void mkval(void); void mktext(void); int yyerror(char *s); Symbol mkstring(char *name); struct stringlist { char* string; struct stringlist* next; }; typedef struct stringlist* Stringlist; static Stringlist allocatedStrings = NULL; int mylineno = 0; %} comment1 "//".* comment2 "#".* delimiter [ \t\r\n] whitespace {delimiter}+ uc_letter [A-Z] lc_letter [a-z] letter {lc_letter}|{uc_letter} digit [0-9] ascii_char [^\"\n] escaped_char \\n|\\\" integer {digit}+ text \"({ascii_char}|{escaped_char})*\" id @?({letter}|{digit}|[\^\-!'])+ /* the "incl" state is used for picking up the name of an include file */ %x incl inclend %{ #define MAX_INCLUDE_DEPTH 10 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; %} %% include BEGIN(incl); [ \t]*\" /* eat the whitespace */ [^\"]+ { /* got the include file name */ if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) { printfstderr( "Includes nested too deeply" ); exit( 1 ); } include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER; /* try to open, using scytherdirs environment variable as well. */ yyin = openFileSearch (yytext, NULL); if (! yyin) { error ("could not open include file %s.", yytext); } yy_switch_to_buffer( yy_create_buffer( yyin, YY_BUF_SIZE ) ); BEGIN(INITIAL); } \";? { /* eat the closing things */ BEGIN(INITIAL); } <> { if ( --include_stack_ptr < 0 ) { yyterminate(); } else { yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer( include_stack[include_stack_ptr] ); BEGIN(inclend); } } "/*" { register int c; for ( ; ; ) { while ( (c = input()) != '*' && c != '\n' && c != EOF ) ; /* eat up text of comment */ if ( c == '*' ) { while ( (c = input()) == '*' ) ; if ( c == '/' ) break; /* found the end */ } if (c == '\n') mylineno++; if ( c == EOF ) { yyerror( "EOF in comment" ); break; } } } \n { mylineno++; } {whitespace} { } {comment1} { } {comment2} { } protocol { return PROTOCOL; } role { return ROLE; } read { return READT; } recv { return RECVT; } send { return SENDT; } match { return MATCH; } not { return NOT; } macro { return MACRO; } var { return VAR; } const { return CONST; } fresh { return FRESH; } claim { return CLAIMT; } run { return RUN; } secret { return SECRET; } inversekeys { return INVERSEKEYS; } inversekeyfunctions { return INVERSEKEYFUNCTIONS; } untrusted { return UNTRUSTED; } compromised { return COMPROMISED; } usertype { return USERTYPE; } singular { return SINGULAR; } function { return FUNCTION; } hashfunction { return HASHFUNCTION; } knows { return KNOWS; } trusted { return TRUSTED; } option { return OPTION; } {text} { int len; char *dest; char *src; if (strlen(yytext) >= 2) { // Make a copy without the surrounding // double-quotes. // TODO: Allow to unescape quotes inside string if // needed later. len = strlen(yytext)-2; src = yytext+1; } else { // If only one character, then simply copy len = strlen(yytext); src = yytext; } // Copy dest = (char *)malloc(len+1); strncpy(dest,src,len); dest[len] = EOS; yylval.str = dest; return TEXT; } {id} { yylval.symb = mkstring(yytext); return ID; } . { return yytext[0]; } %% Symbol mkstring(char *name) { Symbol t; char* s; Stringlist sl; int len; if (( t = lookup(name)) != NULL) { return t; } // make new name len = strlen(name); s = (char *)malloc(len+1); sl = (Stringlist) malloc(sizeof(struct stringlist)); strncpy(s,name,len); sl->next = allocatedStrings; allocatedStrings = sl; sl->string = s; s[len] = EOS; t = get_symb(); t->lineno = yylineno; t->type = T_UNDEF; t->text = s; insert(t); return t; } void scanner_cleanup(void) { yy_delete_buffer (YY_CURRENT_BUFFER); } void strings_cleanup(void) { Stringlist sl; while (allocatedStrings != NULL) { sl = allocatedStrings; allocatedStrings = sl->next; free(sl->string); free(sl); } } int yywrap (void) { /* signal true to let lex know that nothing else is coming */ return 1; } /* void mkval(void); void mktext(void); */ // vim:ft=lex: