Search
lxdream.org :: lxdream/src/tools/actparse.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/tools/actparse.c
changeset 981:79fcace1ab43
prev979:2cc7b486ea6c
next1169:23a9613aceb1
author nkeynes
date Sun Feb 08 23:38:41 2009 +0000 (13 years ago)
permissions -rw-r--r--
last change Clear the action set immediately prior to parsing them in - fix case where
set is actually uninitialized the first time around
Add line numbers to error messages in actparse.c
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, "gendec:%d: Duplicate actions for operation '%s' (previous action on line %d)\n", line, operation,
    71                          actions[i].lineno );
    72                 return -1;
    73             }
    74             actions[i].filename = file;
    75             actions[i].lineno = line;
    76             actions[i].text = act;
    77             return 0;
    78         }
    79     }
    80     fprintf(stderr, "gendec:%d: No operation found matching '%s'\n", line, operation );
    81     return -1;
    82 }
    84 struct actionfile {
    85     FILE *f;
    86     const char *filename;
    87     char *text;
    88     int length;
    89     int yyposn;
    90     int yyline;
    91     struct ruleset *rules;
    92     struct actiontoken token;
    93 };
    95 actionfile_t action_file_open( const char *filename, struct ruleset *rules )
    96 {
    97     struct stat st;
    98     FILE *f = fopen( filename, "ro" );
    99     if( f == NULL ) 
   100         return NULL;
   101     fstat( fileno(f), &st );
   103     actionfile_t af = malloc( sizeof(struct actionfile) );
   104     af->f = f;
   105     af->filename = filename;
   106     af->length = st.st_size+1;
   107     af->text = malloc( st.st_size+1 );
   108     fread( af->text, st.st_size, 1, f );
   109     af->text[st.st_size] = '\0';
   110     af->yyline = 1;
   111     af->yyposn = 0;
   112     af->rules = rules;
   113     af->token.symbol = NONE;
   114     af->token.lineno = 1;
   115     af->token.filename = filename;
   117     return af;
   118 }
   120 actiontoken_t action_file_next( actionfile_t af )
   121 {
   122     af->token.lineno = af->yyline;
   123     if( af->yyposn == af->length ) {
   124         af->token.symbol = END;
   125     } else if( af->token.symbol == TEXT || /* ACTIONS must follow TEXT */ 
   126             (af->token.symbol == NONE && af->text[af->yyposn] == '%' && af->text[af->yyposn+1] == '%') ) {
   127         /* Begin action block */
   128         af->token.symbol = ACTIONS;
   129         memset( af->token.actions, 0, sizeof(af->token.actions) );
   131         char *operation = &af->text[af->yyposn];
   132         while( af->yyposn < af->length ) {
   133             if( af->text[af->yyposn] == '\n' ) {
   134                 af->yyline++;
   135                 if( af->text[af->yyposn+1] == '%' && af->text[af->yyposn+2] == '%' ) {
   136                     af->yyposn += 3;
   137                     break;
   138                 }
   139             }
   141             if( af->text[af->yyposn] == '{' && af->text[af->yyposn+1] == ':' ) {
   142                 af->text[af->yyposn] = '\0';
   143                 int line = af->yyline;
   144                 af->yyposn+=2;
   145                 char *action = &af->text[af->yyposn];
   146                 while( af->yyposn < af->length ) {
   147                     if( af->text[af->yyposn] == ':' && af->text[af->yyposn+1] == '}' ) {
   148                         af->text[af->yyposn] = '\0';
   149                         af->yyposn++;
   150                         if( add_action( af->token.actions, af->rules, operation, af->filename, line, action ) != 0 ) {
   151                             af->token.symbol = ERROR;
   152                             return &af->token;
   153                         }
   154                         operation = &af->text[af->yyposn+1];
   155                         break;
   156                     } else if( af->text[af->yyposn] == '\n' ) {
   157                         af->yyline++;
   158                     }
   159                     af->yyposn++;
   160                 }
   161             }
   162             af->yyposn++;
   163         }
   164     } else {
   165         /* Text block */
   166         af->token.symbol = TEXT;
   167         af->token.text = &af->text[af->yyposn]; 
   168         while( af->yyposn < af->length ) {
   169             af->yyposn++;
   170             if( af->text[af->yyposn-1] == '\n' ) {
   171                 af->yyline++;
   172                 if( af->text[af->yyposn] == '%' && af->text[af->yyposn+1] == '%' ) {
   173                     af->text[af->yyposn] = '\0';
   174                     af->yyposn += 2;
   175                     break;
   176                 }
   177             }
   178         }
   179     }
   180     return &af->token;
   181 }
   183 void action_file_close( actionfile_t af )
   184 {
   185     free( af->text );
   186     fclose( af->f );
   187     free( af );
   188 }
.