Search
lxdream.org :: lxdream/src/tools/actparse.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/tools/actparse.c
changeset 979:2cc7b486ea6c
prev969:3f178ca1398c
next981:79fcace1ab43
author nkeynes
date Wed Feb 04 00:58:54 2009 +0000 (13 years ago)
permissions -rw-r--r--
last change Emit #line directives in output to make debugging a little easier
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 add_action( struct action *actions, struct ruleset *rules, char *operation, const char *file, int line, char *action )
    28 {
    29     char *act = g_strchomp(action);
    30     char opclean[strlen(operation)+1];
    31     char *p = operation, *q = opclean;
    32     int i;
    34     // Strip c-style comments 
    35     while( *p ) {
    36         if( *p == '/' && *(p+1) == '*' ) {
    37             p+=2;
    38             while( *p ) {
    39                 if( *p == '*' && *(p+1) == '/' ) {
    40                     p+=2;
    41                     break;
    42                 }
    43                 p++;
    44             }
    45         } else if( *p == '/' && *(p+1) == '/' ) {
    46             p+=2;
    47             while( *p && *p != '\n' ) {
    48                 p++;
    49             }
    50         } else {
    51             *q++ = *p++;
    52         }
    53     }
    54     *q = '\0';
    56     /* Drop any leading blank lines from the start of the action (and add them
    57      * to the line number ) */ 
    58     for( p=act; isspace(*p); p++ ) {
    59         if( *p == '\n' ) {
    60             act = p+1;
    61             line++;
    62         }
    63     }
    65     strcpy( operation, g_strstrip(opclean) );
    67     for( i=0; i<rules->rule_count; i++ ) {
    68         if( strcasecmp(rules->rules[i]->format, operation) == 0 ) {
    69             if( actions[i].text != NULL ) {
    70                 fprintf( stderr, "Duplicate actions for operation '%s'\n", operation );
    71                 return -1;
    72             }
    73             actions[i].filename = file;
    74             actions[i].lineno = line;
    75             actions[i].text = act;
    76             return 0;
    77         }
    78     }
    79     fprintf(stderr, "No operation found matching '%s'\n", operation );
    80     return -1;
    81 }
    83 struct actionfile {
    84     FILE *f;
    85     const char *filename;
    86     char *text;
    87     int length;
    88     int yyposn;
    89     int yyline;
    90     struct ruleset *rules;
    91     struct actiontoken token;
    92 };
    94 actionfile_t action_file_open( const char *filename, struct ruleset *rules )
    95 {
    96     struct stat st;
    97     FILE *f = fopen( filename, "ro" );
    98     if( f == NULL ) 
    99         return NULL;
   100     fstat( fileno(f), &st );
   102     actionfile_t af = malloc( sizeof(struct actionfile) );
   103     af->f = f;
   104     af->filename = filename;
   105     af->length = st.st_size+1;
   106     af->text = malloc( st.st_size+1 );
   107     fread( af->text, st.st_size, 1, f );
   108     af->text[st.st_size] = '\0';
   109     af->yyline = 1;
   110     af->yyposn = 0;
   111     af->rules = rules;
   112     af->token.symbol = NONE;
   113     af->token.lineno = 1;
   114     af->token.filename = filename;
   116     return af;
   117 }
   119 actiontoken_t action_file_next( actionfile_t af )
   120 {
   121     if( af->token.symbol == ACTIONS ) {
   122         /* Destroy previous actions */
   123         memset( af->token.actions, 0, sizeof(af->token.actions) );
   124     }
   125     af->token.lineno = af->yyline;
   126     if( af->yyposn == af->length ) {
   127         af->token.symbol = END;
   128     } else if( af->token.symbol == TEXT || /* ACTIONS must follow TEXT */ 
   129             (af->token.symbol == NONE && af->text[af->yyposn] == '%' && af->text[af->yyposn+1] == '%') ) {
   130         /* Begin action block */
   131         af->token.symbol = ACTIONS;
   133         char *operation = &af->text[af->yyposn];
   134         while( af->yyposn < af->length ) {
   135             if( af->text[af->yyposn] == '\n' ) {
   136                 af->yyline++;
   137                 if( af->text[af->yyposn+1] == '%' && af->text[af->yyposn+2] == '%' ) {
   138                     af->yyposn += 3;
   139                     break;
   140                 }
   141             }
   143             if( af->text[af->yyposn] == '{' && af->text[af->yyposn+1] == ':' ) {
   144                 af->text[af->yyposn] = '\0';
   145                 int line = af->yyline;
   146                 af->yyposn+=2;
   147                 char *action = &af->text[af->yyposn];
   148                 while( af->yyposn < af->length ) {
   149                     if( af->text[af->yyposn] == ':' && af->text[af->yyposn+1] == '}' ) {
   150                         af->text[af->yyposn] = '\0';
   151                         af->yyposn++;
   152                         if( add_action( af->token.actions, af->rules, operation, af->filename, line, action ) != 0 ) {
   153                             af->token.symbol = ERROR;
   154                             return &af->token;
   155                         }
   156                         operation = &af->text[af->yyposn+1];
   157                         break;
   158                     } else if( af->text[af->yyposn] == '\n' ) {
   159                         af->yyline++;
   160                     }
   161                     af->yyposn++;
   162                 }
   163             }
   164             af->yyposn++;
   165         }
   166     } else {
   167         /* Text block */
   168         af->token.symbol = TEXT;
   169         af->token.text = &af->text[af->yyposn]; 
   170         while( af->yyposn < af->length ) {
   171             af->yyposn++;
   172             if( af->text[af->yyposn-1] == '\n' ) {
   173                 af->yyline++;
   174                 if( af->text[af->yyposn] == '%' && af->text[af->yyposn+1] == '%' ) {
   175                     af->text[af->yyposn] = '\0';
   176                     af->yyposn += 2;
   177                     break;
   178                 }
   179             }
   180         }
   181     }
   182     return &af->token;
   183 }
   185 void action_file_close( actionfile_t af )
   186 {
   187     free( af->text );
   188     fclose( af->f );
   189     free( af );
   190 }
.