filename | src/tools/actparse.c |
changeset | 961:3541b280e0f1 |
prev | 948:545c85cc56f1 |
next | 969: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 }
.