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
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@736
    70
                fprintf( stderr, "Duplicate actions for operation '%s'\n", operation );
nkeynes@736
    71
                return -1;
nkeynes@736
    72
            }
nkeynes@979
    73
            actions[i].filename = file;
nkeynes@979
    74
            actions[i].lineno = line;
nkeynes@979
    75
            actions[i].text = act;
nkeynes@736
    76
            return 0;
nkeynes@736
    77
        }
nkeynes@359
    78
    }
nkeynes@359
    79
    fprintf(stderr, "No operation found matching '%s'\n", operation );
nkeynes@359
    80
    return -1;
nkeynes@359
    81
}
nkeynes@736
    82
nkeynes@948
    83
struct actionfile {
nkeynes@948
    84
    FILE *f;
nkeynes@979
    85
    const char *filename;
nkeynes@948
    86
    char *text;
nkeynes@948
    87
    int length;
nkeynes@948
    88
    int yyposn;
nkeynes@948
    89
    int yyline;
nkeynes@948
    90
    struct ruleset *rules;
nkeynes@948
    91
    struct actiontoken token;
nkeynes@948
    92
};
nkeynes@359
    93
nkeynes@948
    94
actionfile_t action_file_open( const char *filename, struct ruleset *rules )
nkeynes@359
    95
{
nkeynes@359
    96
    struct stat st;
nkeynes@948
    97
    FILE *f = fopen( filename, "ro" );
nkeynes@948
    98
    if( f == NULL ) 
nkeynes@948
    99
        return NULL;
nkeynes@948
   100
    fstat( fileno(f), &st );
nkeynes@948
   101
    
nkeynes@948
   102
    actionfile_t af = malloc( sizeof(struct actionfile) );
nkeynes@948
   103
    af->f = f;
nkeynes@979
   104
    af->filename = filename;
nkeynes@948
   105
    af->length = st.st_size+1;
nkeynes@948
   106
    af->text = malloc( st.st_size+1 );
nkeynes@948
   107
    fread( af->text, st.st_size, 1, f );
nkeynes@948
   108
    af->text[st.st_size] = '\0';
nkeynes@979
   109
    af->yyline = 1;
nkeynes@948
   110
    af->yyposn = 0;
nkeynes@948
   111
    af->rules = rules;
nkeynes@948
   112
    af->token.symbol = NONE;
nkeynes@979
   113
    af->token.lineno = 1;
nkeynes@979
   114
    af->token.filename = filename;
nkeynes@948
   115
    
nkeynes@948
   116
    return af;
nkeynes@948
   117
}
nkeynes@736
   118
nkeynes@948
   119
actiontoken_t action_file_next( actionfile_t af )
nkeynes@948
   120
{
nkeynes@948
   121
    if( af->token.symbol == ACTIONS ) {
nkeynes@948
   122
        /* Destroy previous actions */
nkeynes@948
   123
        memset( af->token.actions, 0, sizeof(af->token.actions) );
nkeynes@948
   124
    }
nkeynes@979
   125
    af->token.lineno = af->yyline;
nkeynes@948
   126
    if( af->yyposn == af->length ) {
nkeynes@948
   127
        af->token.symbol = END;
nkeynes@948
   128
    } else if( af->token.symbol == TEXT || /* ACTIONS must follow TEXT */ 
nkeynes@961
   129
            (af->token.symbol == NONE && af->text[af->yyposn] == '%' && af->text[af->yyposn+1] == '%') ) {
nkeynes@948
   130
        /* Begin action block */
nkeynes@948
   131
        af->token.symbol = ACTIONS;
nkeynes@948
   132
nkeynes@948
   133
        char *operation = &af->text[af->yyposn];
nkeynes@948
   134
        while( af->yyposn < af->length ) {
nkeynes@948
   135
            if( af->text[af->yyposn] == '\n' ) {
nkeynes@979
   136
                af->yyline++;
nkeynes@948
   137
                if( af->text[af->yyposn+1] == '%' && af->text[af->yyposn+2] == '%' ) {
nkeynes@948
   138
                    af->yyposn += 3;
nkeynes@948
   139
                    break;
nkeynes@948
   140
                }
nkeynes@736
   141
            }
nkeynes@948
   142
nkeynes@948
   143
            if( af->text[af->yyposn] == '{' && af->text[af->yyposn+1] == ':' ) {
nkeynes@948
   144
                af->text[af->yyposn] = '\0';
nkeynes@979
   145
                int line = af->yyline;
nkeynes@948
   146
                af->yyposn+=2;
nkeynes@948
   147
                char *action = &af->text[af->yyposn];
nkeynes@948
   148
                while( af->yyposn < af->length ) {
nkeynes@948
   149
                    if( af->text[af->yyposn] == ':' && af->text[af->yyposn+1] == '}' ) {
nkeynes@948
   150
                        af->text[af->yyposn] = '\0';
nkeynes@948
   151
                        af->yyposn++;
nkeynes@979
   152
                        if( add_action( af->token.actions, af->rules, operation, af->filename, line, action ) != 0 ) {
nkeynes@948
   153
                            af->token.symbol = ERROR;
nkeynes@948
   154
                            return &af->token;
nkeynes@948
   155
                        }
nkeynes@948
   156
                        operation = &af->text[af->yyposn+1];
nkeynes@948
   157
                        break;
nkeynes@979
   158
                    } else if( af->text[af->yyposn] == '\n' ) {
nkeynes@979
   159
                        af->yyline++;
nkeynes@948
   160
                    }
nkeynes@948
   161
                    af->yyposn++;
nkeynes@948
   162
                }
nkeynes@948
   163
            }
nkeynes@948
   164
            af->yyposn++;
nkeynes@736
   165
        }
nkeynes@948
   166
    } else {
nkeynes@948
   167
        /* Text block */
nkeynes@948
   168
        af->token.symbol = TEXT;
nkeynes@948
   169
        af->token.text = &af->text[af->yyposn]; 
nkeynes@948
   170
        while( af->yyposn < af->length ) {
nkeynes@948
   171
            af->yyposn++;
nkeynes@948
   172
            if( af->text[af->yyposn-1] == '\n' ) {
nkeynes@948
   173
                af->yyline++;
nkeynes@948
   174
                if( af->text[af->yyposn] == '%' && af->text[af->yyposn+1] == '%' ) {
nkeynes@948
   175
                    af->text[af->yyposn] = '\0';
nkeynes@948
   176
                    af->yyposn += 2;
nkeynes@736
   177
                    break;
nkeynes@736
   178
                }
nkeynes@736
   179
            }
nkeynes@736
   180
        }
nkeynes@359
   181
    }
nkeynes@948
   182
    return &af->token;
nkeynes@948
   183
}
nkeynes@359
   184
nkeynes@948
   185
void action_file_close( actionfile_t af )
nkeynes@948
   186
{
nkeynes@948
   187
    free( af->text );
nkeynes@948
   188
    fclose( af->f );
nkeynes@948
   189
    free( af );
nkeynes@948
   190
}
nkeynes@736
   191
.