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