Search
lxdream.org :: lxdream/src/tools/actparse.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/tools/actparse.c
changeset 961:3541b280e0f1
prev948:545c85cc56f1
next969:3f178ca1398c
author nkeynes
date Thu Jan 15 00:53:39 2009 +0000 (13 years ago)
permissions -rw-r--r--
last change Fix off-by-one buffer overflow
Fix '\%' to '%'
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * gendec action file parser. 
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #include <stdlib.h>
    20 #include <stdio.h>
    21 #include <string.h>
    22 #include <ctype.h>
    23 #include <sys/stat.h>
    24 #include <glib/gstrfuncs.h>
    25 #include "tools/gendec.h"
    27 static int yyline;
    29 struct action *new_action() {
    30     struct action *action = malloc( sizeof( struct action ) );
    31     memset( action, 0, sizeof( struct action ) );
    32     return action;
    33 }
    35 int add_action( char **actions, struct ruleset *rules, char *operation, char *action )
    36 {
    37     char *act = g_strchomp(action);
    38     char opclean[strlen(operation)+1];
    39     char *p = operation, *q = opclean;
    40     int i;
    42     // Strip c-style comments 
    43     while( *p ) {
    44         if( *p == '/' && *(p+1) == '*' ) {
    45             p+=2;
    46             while( *p ) {
    47                 if( *p == '*' && *(p+1) == '/' ) {
    48                     p+=2;
    49                     break;
    50                 }
    51                 p++;
    52             }
    53         } else if( *p == '/' && *(p+1) == '/' ) {
    54             p+=2;
    55             while( *p && *p != '\n' ) {
    56                 p++;
    57             }
    58         } else {
    59             *q++ = *p++;
    60         }
    61     }
    62     *q = '\0';
    64     strcpy( operation, g_strstrip(opclean) );
    66     for( i=0; i<rules->rule_count; i++ ) {
    67         if( strcasecmp(rules->rules[i]->format, operation) == 0 ) {
    68             if( actions[i] != NULL ) {
    69                 fprintf( stderr, "Duplicate actions for operation '%s'\n", operation );
    70                 return -1;
    71             }
    72             actions[i] = act;
    73             return 0;
    74         }
    75     }
    76     fprintf(stderr, "No operation found matching '%s'\n", operation );
    77     return -1;
    78 }
    80 struct actionfile {
    81     FILE *f;
    82     char *text;
    83     int length;
    84     int yyposn;
    85     int yyline;
    86     struct ruleset *rules;
    87     struct actiontoken token;
    88 };
    90 actionfile_t action_file_open( const char *filename, struct ruleset *rules )
    91 {
    92     struct stat st;
    93     FILE *f = fopen( filename, "ro" );
    94     if( f == NULL ) 
    95         return NULL;
    96     fstat( fileno(f), &st );
    98     actionfile_t af = malloc( sizeof(struct actionfile) );
    99     af->f = f;
   100     af->length = st.st_size+1;
   101     af->text = malloc( st.st_size+1 );
   102     fread( af->text, st.st_size, 1, f );
   103     af->text[st.st_size] = '\0';
   104     af->yyline = 0;
   105     af->yyposn = 0;
   106     af->rules = rules;
   107     af->token.symbol = NONE;
   109     return af;
   110 }
   112 actiontoken_t action_file_next( actionfile_t af )
   113 {
   114     if( af->token.symbol == ACTIONS ) {
   115         /* Destroy previous actions */
   116         memset( af->token.actions, 0, sizeof(af->token.actions) );
   117     }
   119     if( af->yyposn == af->length ) {
   120         af->token.symbol = END;
   121     } else if( af->token.symbol == TEXT || /* ACTIONS must follow TEXT */ 
   122             (af->token.symbol == NONE && af->text[af->yyposn] == '%' && af->text[af->yyposn+1] == '%') ) {
   123         /* Begin action block */
   124         af->token.symbol = ACTIONS;
   126         char *operation = &af->text[af->yyposn];
   127         while( af->yyposn < af->length ) {
   128             if( af->text[af->yyposn] == '\n' ) {
   129                 yyline++;
   130                 if( af->text[af->yyposn+1] == '%' && af->text[af->yyposn+2] == '%' ) {
   131                     af->yyposn += 3;
   132                     break;
   133                 }
   134             }
   136             if( af->text[af->yyposn] == '{' && af->text[af->yyposn+1] == ':' ) {
   137                 af->text[af->yyposn] = '\0';
   138                 af->yyposn+=2;
   139                 char *action = &af->text[af->yyposn];
   140                 while( af->yyposn < af->length ) {
   141                     if( af->text[af->yyposn] == ':' && af->text[af->yyposn+1] == '}' ) {
   142                         af->text[af->yyposn] = '\0';
   143                         af->yyposn++;
   144                         if( add_action( af->token.actions, af->rules, operation, action ) != 0 ) {
   145                             af->token.symbol = ERROR;
   146                             return &af->token;
   147                         }
   148                         operation = &af->text[af->yyposn+1];
   149                         break;
   150                     }
   151                     af->yyposn++;
   152                 }
   153             }
   154             af->yyposn++;
   155         }
   156     } else {
   157         /* Text block */
   158         af->token.symbol = TEXT;
   159         af->token.text = &af->text[af->yyposn]; 
   160         while( af->yyposn < af->length ) {
   161             af->yyposn++;
   162             if( af->text[af->yyposn-1] == '\n' ) {
   163                 af->yyline++;
   164                 if( af->text[af->yyposn] == '%' && af->text[af->yyposn+1] == '%' ) {
   165                     af->text[af->yyposn] = '\0';
   166                     af->yyposn += 2;
   167                     break;
   168                 }
   169             }
   170         }
   171     }
   172     return &af->token;
   173 }
   175 void action_file_close( actionfile_t af )
   176 {
   177     free( af->text );
   178     fclose( af->f );
   179     free( af );
   180 }
.