nkeynes@561: /** nkeynes@561: * $Id$ nkeynes@561: * nkeynes@561: * gendec action file parser. nkeynes@561: * nkeynes@561: * Copyright (c) 2005 Nathan Keynes. nkeynes@561: * nkeynes@561: * This program is free software; you can redistribute it and/or modify nkeynes@561: * it under the terms of the GNU General Public License as published by nkeynes@561: * the Free Software Foundation; either version 2 of the License, or nkeynes@561: * (at your option) any later version. nkeynes@561: * nkeynes@561: * This program is distributed in the hope that it will be useful, nkeynes@561: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@561: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@561: * GNU General Public License for more details. nkeynes@561: */ nkeynes@561: nkeynes@359: #include nkeynes@359: #include nkeynes@359: #include nkeynes@359: #include nkeynes@359: #include nkeynes@359: #include nkeynes@359: #include "tools/gendec.h" nkeynes@359: nkeynes@359: static int yyline; nkeynes@359: nkeynes@420: struct action *new_action() { nkeynes@359: struct action *action = malloc( sizeof( struct action ) ); nkeynes@359: memset( action, 0, sizeof( struct action ) ); nkeynes@359: return action; nkeynes@359: } nkeynes@359: nkeynes@948: int add_action( char **actions, struct ruleset *rules, char *operation, char *action ) nkeynes@359: { nkeynes@359: char *act = g_strchomp(action); nkeynes@359: nkeynes@359: char opclean[strlen(operation)]; nkeynes@359: char *p = operation, *q = opclean; nkeynes@359: int i; nkeynes@359: nkeynes@359: // Strip c-style comments nkeynes@359: while( *p ) { nkeynes@736: if( *p == '/' && *(p+1) == '*' ) { nkeynes@736: p+=2; nkeynes@736: while( *p ) { nkeynes@736: if( *p == '*' && *(p+1) == '/' ) { nkeynes@736: p+=2; nkeynes@736: break; nkeynes@736: } nkeynes@736: p++; nkeynes@736: } nkeynes@736: } else if( *p == '/' && *(p+1) == '/' ) { nkeynes@736: p+=2; nkeynes@736: while( *p && *p != '\n' ) { nkeynes@736: p++; nkeynes@736: } nkeynes@736: } else { nkeynes@736: *q++ = *p++; nkeynes@736: } nkeynes@359: } nkeynes@359: *q = '\0'; nkeynes@359: strcpy( operation, g_strstrip(opclean) ); nkeynes@359: nkeynes@359: for( i=0; irule_count; i++ ) { nkeynes@736: if( strcasecmp(rules->rules[i]->format, operation) == 0 ) { nkeynes@948: if( actions[i] != NULL ) { nkeynes@736: fprintf( stderr, "Duplicate actions for operation '%s'\n", operation ); nkeynes@736: return -1; nkeynes@736: } nkeynes@948: actions[i] = act; nkeynes@736: return 0; nkeynes@736: } nkeynes@359: } nkeynes@359: fprintf(stderr, "No operation found matching '%s'\n", operation ); nkeynes@359: return -1; nkeynes@359: } nkeynes@736: nkeynes@948: struct actionfile { nkeynes@948: FILE *f; nkeynes@948: char *text; nkeynes@948: int length; nkeynes@948: int yyposn; nkeynes@948: int yyline; nkeynes@948: struct ruleset *rules; nkeynes@948: struct actiontoken token; nkeynes@948: }; nkeynes@359: nkeynes@948: actionfile_t action_file_open( const char *filename, struct ruleset *rules ) nkeynes@359: { nkeynes@359: struct stat st; nkeynes@948: FILE *f = fopen( filename, "ro" ); nkeynes@948: if( f == NULL ) nkeynes@948: return NULL; nkeynes@948: fstat( fileno(f), &st ); nkeynes@948: nkeynes@948: actionfile_t af = malloc( sizeof(struct actionfile) ); nkeynes@948: af->f = f; nkeynes@948: af->length = st.st_size+1; nkeynes@948: af->text = malloc( st.st_size+1 ); nkeynes@948: fread( af->text, st.st_size, 1, f ); nkeynes@948: af->text[st.st_size] = '\0'; nkeynes@948: af->yyline = 0; nkeynes@948: af->yyposn = 0; nkeynes@948: af->rules = rules; nkeynes@948: af->token.symbol = NONE; nkeynes@948: nkeynes@948: return af; nkeynes@948: } nkeynes@736: nkeynes@948: actiontoken_t action_file_next( actionfile_t af ) nkeynes@948: { nkeynes@948: if( af->token.symbol == ACTIONS ) { nkeynes@948: /* Destroy previous actions */ nkeynes@948: memset( af->token.actions, 0, sizeof(af->token.actions) ); nkeynes@948: } nkeynes@948: nkeynes@948: if( af->yyposn == af->length ) { nkeynes@948: af->token.symbol = END; nkeynes@948: } else if( af->token.symbol == TEXT || /* ACTIONS must follow TEXT */ nkeynes@948: (af->token.symbol == NONE && af->text[af->yyposn] == '\%' && af->text[af->yyposn+1] == '%') ) { nkeynes@948: /* Begin action block */ nkeynes@948: af->token.symbol = ACTIONS; nkeynes@948: nkeynes@948: char *operation = &af->text[af->yyposn]; nkeynes@948: while( af->yyposn < af->length ) { nkeynes@948: if( af->text[af->yyposn] == '\n' ) { nkeynes@948: yyline++; nkeynes@948: if( af->text[af->yyposn+1] == '%' && af->text[af->yyposn+2] == '%' ) { nkeynes@948: af->yyposn += 3; nkeynes@948: break; nkeynes@948: } nkeynes@736: } nkeynes@948: nkeynes@948: if( af->text[af->yyposn] == '{' && af->text[af->yyposn+1] == ':' ) { nkeynes@948: af->text[af->yyposn] = '\0'; nkeynes@948: af->yyposn+=2; nkeynes@948: char *action = &af->text[af->yyposn]; nkeynes@948: while( af->yyposn < af->length ) { nkeynes@948: if( af->text[af->yyposn] == ':' && af->text[af->yyposn+1] == '}' ) { nkeynes@948: af->text[af->yyposn] = '\0'; nkeynes@948: af->yyposn++; nkeynes@948: if( add_action( af->token.actions, af->rules, operation, action ) != 0 ) { nkeynes@948: af->token.symbol = ERROR; nkeynes@948: return &af->token; nkeynes@948: } nkeynes@948: operation = &af->text[af->yyposn+1]; nkeynes@948: break; nkeynes@948: } nkeynes@948: af->yyposn++; nkeynes@948: } nkeynes@948: } nkeynes@948: af->yyposn++; nkeynes@736: } nkeynes@948: } else { nkeynes@948: /* Text block */ nkeynes@948: af->token.symbol = TEXT; nkeynes@948: af->token.text = &af->text[af->yyposn]; nkeynes@948: while( af->yyposn < af->length ) { nkeynes@948: af->yyposn++; nkeynes@948: if( af->text[af->yyposn-1] == '\n' ) { nkeynes@948: af->yyline++; nkeynes@948: if( af->text[af->yyposn] == '%' && af->text[af->yyposn+1] == '%' ) { nkeynes@948: af->text[af->yyposn] = '\0'; nkeynes@948: af->yyposn += 2; nkeynes@736: break; nkeynes@736: } nkeynes@736: } nkeynes@736: } nkeynes@359: } nkeynes@948: return &af->token; nkeynes@948: } nkeynes@359: nkeynes@948: void action_file_close( actionfile_t af ) nkeynes@948: { nkeynes@948: free( af->text ); nkeynes@948: fclose( af->f ); nkeynes@948: free( af ); nkeynes@948: } nkeynes@736: