source: trunk/drmaa_utils/drmaa_utils/conf.c @ 1

Revision 1, 10.7 KB checked in by mmamonski, 13 years ago (diff)

Torque/PBS DRMAA initial commit

Line 
1/* $Id: conf.c 226 2010-05-25 10:47:18Z mamonski $ */
2/*
3 *  FedStage DRMAA utilities library
4 *  Copyright (C) 2006-2008  FedStage Systems
5 *
6 *  This program is free software: you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation, either version 3 of the License, or
9 *  (at your option) any later version.
10 *
11 *  This program is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifdef HAVE_CONFIG_H
21#       include <config.h>
22#endif
23
24#include <ctype.h>
25#include <stdarg.h>
26#include <string.h>
27
28#include <drmaa_utils/common.h>
29#include <drmaa_utils/conf_impl.h>
30#include <drmaa_utils/conf_tab.h>
31#include <drmaa_utils/logging.h>
32#include <drmaa_utils/util.h>
33
34#ifndef lint
35static char rcsid[]
36#       ifdef __GNUC__
37                __attribute__ ((unused))
38#       endif
39        = "$Id: conf.c 226 2010-05-25 10:47:18Z mamonski $";
40#endif
41
42
43fsd_conf_dict_t *
44fsd_conf_read(
45                fsd_conf_dict_t  * volatile configuration,
46                const char *filename, bool must_exist,
47                const char *content, size_t content_len
48                )
49{
50        fsd_conf_dict_t *volatile result = NULL;
51        fsd_conf_parser_t *parser = NULL;
52        fsd_conf_lexer_t *lexer = NULL;
53        char *file_content = NULL;
54        size_t file_content_len = 0;
55
56        fsd_log_enter((
57                "(filename=%s, must_exist=%s, content=%s)",
58                filename, must_exist ? "true" : "false", content
59                ));
60
61        TRY
62         {
63                fsd_malloc( parser, fsd_conf_parser_t );
64                fsd_malloc( lexer, fsd_conf_lexer_t );
65
66                parser->lexer = lexer;
67                parser->result = NULL;
68                parser->n_errors = 0;
69                parser->errors = NULL;
70
71                lexer->parser = parser;
72                lexer->filename = filename;
73                lexer->buffer = NULL;
74                lexer->buflen = 0;
75                lexer->pos = NULL;
76                lexer->lineno = 0;
77                lexer->cline = NULL;
78
79                if( filename )
80                        TRY
81                         {
82                                fsd_read_file(
83                                                filename, must_exist,
84                                                &file_content, &file_content_len
85                                                );
86                         }
87                        EXCEPT_DEFAULT
88                         {
89                                const fsd_exc_t *e = fsd_exc_get();
90                                if( must_exist )
91                                        fsd_exc_raise_fmt( e->code(e), "%s: %s", filename, e->message(e) );
92                                else
93                                 {
94                                        fsd_log_warning(( "%s: %s", filename, e->message(e) ));
95                                 }
96                         }
97                        END_TRY
98
99                if( file_content )
100                 {
101                        lexer->buffer = (const uchar*)file_content;
102                        lexer->buflen = file_content_len;
103                        fsd_log_trace(( "content from file" ));
104                 }
105                else if( content )
106                 {
107                        lexer->buffer = (const uchar*)content;
108                        lexer->buflen = content_len;
109                        fsd_log_trace(( "content from memory" ));
110                 }
111
112                if( lexer->buffer )
113                 {
114                        lexer->pos = lexer->cline = lexer->buffer;
115                        lexer->lineno = 1;
116
117                        fsd_conf_parse( parser, lexer );
118                        result = parser->result;
119                 }
120
121                if( parser->n_errors > 0 )
122                 {
123                        fsd_exc_raise(
124                                        fsd_exc_new(
125                                                        FSD_ERRNO_INTERNAL_ERROR,
126                                                        fsd_explode( (const char*const*)parser->errors, '\n',
127                                                                parser->n_errors ),
128                                                        true
129                                                        )
130                                        );
131                 }
132         }
133        ELSE
134         {
135                configuration = fsd_conf_dict_merge( configuration, result );
136                result = NULL;
137         }
138        FINALLY
139         {
140                if( parser )
141                 {
142                        if( parser->errors )
143                         {
144                                int i;
145                                for( i=0;  i < parser->n_errors;  i++ )
146                                        fsd_free( parser->errors[i] );
147                                fsd_free( parser->errors );
148                         }
149                        fsd_free( parser );
150                 }
151                fsd_free( lexer );
152                fsd_free( file_content );
153                fsd_conf_dict_destroy( result );
154         }
155        END_TRY
156
157        fsd_log_return(( "" ));
158        return configuration;
159}
160
161
162
163int
164fsd_conf_lex(
165                union YYSTYPE *lvalp, struct YYLTYPE *locp,
166                fsd_conf_lexer_t *lexer
167                )
168{
169        const uchar *c = lexer->pos;
170        const uchar *end = lexer->buffer + lexer->buflen;
171        const char *error = NULL;
172        int result;
173
174        while( c<end )
175                switch( *c )
176                 {
177                        case '#':  /* a comment */
178                                while( c<end && *c != '\n' )
179                                        c++;
180                        case '\n':  /* no break */
181                                lexer->lineno++;
182                                lexer->cline = c+1;
183                        case ' ':  case '\t':  case '\r':  /* no break */
184                                c++;
185                                break;
186                        default:
187                                goto token_begin;
188                 }
189
190token_begin:
191        locp->first_line = lexer->lineno;
192        locp->first_column = c - lexer->cline + 1;
193
194        if( c == end )
195                result = 0;
196        else
197                switch( *c )
198                 {
199                        case ':':  case ',':  case '{':  case '}':
200                                result = *c++;
201                                break;
202
203                        case '0':  case '1':  case '2':  case '3':  case '4':
204                        case '5':  case '6':  case '7':  case '8':  case '9':
205                         {
206                                int v = 0;
207                                while( c < end  &&  '0' <= *c  &&  *c <= '9' )
208                                 {
209                                        v *= 10;
210                                        v += *c - '0';
211                                        c++;
212                                 }
213                                lvalp->integer = v;
214                                result = INTEGER;
215                                break;
216                         }
217
218                        case '"':  case '\'':
219                         {
220                                uchar delimiter;
221                                const uchar *begin;
222                                delimiter = *c++;
223                                begin = c;
224                               
225                                while( c < end  &&  *c != delimiter )
226                                        c++;
227                                if( c == end )
228                                 {
229                                        error = "expected string delimiter but EOF found";
230                                        result = LEXER_ERROR;
231                                 }
232                                else
233                                 {
234                                        lvalp->string = fsd_strndup( (const char*)begin, c-begin );
235                                        result = STRING;
236                                        c++;
237                                 }
238                                break;
239                         }
240
241                        default:
242                         {
243                                const uchar *begin = c;
244                                while( c<end  &&  !isspace(*c) )
245                                        switch( *c )
246                                         {
247                                                case ':':  case ',':  case '{':  case '}':
248                                                        goto end_of_string;
249                                                default:
250                                                        c++;
251                                                        break;
252                                         }
253                        end_of_string:
254                                lvalp->string = fsd_strndup( (const char*)begin, c-begin );
255                                result = STRING;
256                                break;
257                         }
258                 }
259
260        locp->last_line = lexer->lineno;
261        locp->last_column = c - lexer->cline;
262        if( locp->last_column < locp->first_column )
263                locp->last_column = locp->first_column;
264        lexer->pos = c;
265
266        if( error )
267                fsd_conf_error( locp, lexer->parser, lexer, error );
268
269        return result;
270}
271
272
273
274void
275fsd_conf_error(
276                struct YYLTYPE *locp,
277                fsd_conf_parser_t *parser, fsd_conf_lexer_t *lexer,
278                const char *fmt, ...
279                )
280{
281        char *volatile message = NULL;
282        va_list args;
283
284        TRY
285         {
286                va_start( args, fmt );
287                message = fsd_vasprintf( fmt, args );
288                va_end( args );
289
290                fsd_realloc( parser->errors, parser->n_errors+1, char* );
291                parser->errors[ parser->n_errors ] = fsd_asprintf(
292                                "%s:%d:%d: %s",
293                                parser->lexer->filename, locp->first_line, locp->first_column,
294                                message );
295                fsd_log_error(("Parser error: %s:%d:%d: %s", parser->lexer->filename, locp->first_line, locp->first_column, message ));
296                parser->n_errors ++;
297         }
298        FINALLY
299         { fsd_free( message ); }
300        END_TRY
301}
302
303
304
305fsd_conf_option_t *
306fsd_conf_option_create( fsd_conf_type_t type, void *value )
307{
308        fsd_conf_option_t *o = NULL;
309
310        fsd_malloc( o, fsd_conf_option_t );
311        o->type = type;
312        switch( type )
313         {
314                case FSD_CONF_INTEGER:
315                        o->val.integer = *(int*)value;
316                        break;
317                case FSD_CONF_STRING:
318                        o->val.string = (char*)value;
319                        break;
320                case FSD_CONF_DICT:
321                        o->val.dict = (fsd_conf_dict_t*)value;
322                        break;
323                default:
324                        fsd_assert(false);
325                        break;
326         }
327        return o;
328}
329
330
331void
332fsd_conf_option_destroy( fsd_conf_option_t *option )
333{
334        if( option == NULL )
335                return;
336        switch( option->type )
337         {
338                case FSD_CONF_INTEGER:
339                        break;
340                case FSD_CONF_STRING:
341                        fsd_free( option->val.string );
342                        break;
343                case FSD_CONF_DICT:
344                        fsd_conf_dict_destroy( option->val.dict );
345                        break;
346                default:
347                        fsd_assert( false );
348         }
349        fsd_free( option );
350}
351
352
353fsd_conf_option_t *
354fsd_conf_option_merge( fsd_conf_option_t *lhs, fsd_conf_option_t *rhs )
355{
356        if( lhs->type == rhs->type  &&  rhs->type == FSD_CONF_DICT )
357         {
358                lhs->val.dict = fsd_conf_dict_merge( lhs->val.dict, rhs->val.dict );
359                fsd_free( rhs );
360                return lhs;
361         }
362        else
363         {
364                fsd_conf_option_destroy( lhs );
365                return rhs;
366         }
367}
368
369
370void
371fsd_conf_option_dump( fsd_conf_option_t *option )
372{
373        if( option == NULL )
374         {
375                printf( "(null)" );
376                return;
377         }
378        switch( option->type )
379         {
380                case FSD_CONF_STRING:
381                        printf( "\"%s\"", option->val.string );
382                        break;
383                case FSD_CONF_INTEGER:
384                        printf( "%d", option->val.integer );
385                        break;
386                case FSD_CONF_DICT:
387                        fsd_conf_dict_dump( option->val.dict );
388                        break;
389         }
390}
391
392
393
394struct fsd_conf_dict_s {
395        fsd_conf_dict_t *next;
396        char *key;
397        fsd_conf_option_t *value;
398};
399
400
401fsd_conf_dict_t *
402fsd_conf_dict_create(void)
403{
404        fsd_conf_dict_t *dict = NULL;
405        fsd_malloc( dict, fsd_conf_dict_t );
406        dict->next = NULL;
407        dict->key = NULL;
408        dict->value = NULL;
409        return dict;
410}
411
412
413void
414fsd_conf_dict_destroy( fsd_conf_dict_t *dict )
415{
416        fsd_conf_dict_t *i;
417        for( i = dict;  i != NULL;  )
418         {
419                fsd_conf_dict_t *c = i;
420                i = i->next;
421                fsd_free( c->key );
422                fsd_conf_option_destroy( c->value );
423                fsd_free( c );
424         }
425}
426
427
428fsd_conf_option_t *
429fsd_conf_dict_get(
430                fsd_conf_dict_t *dict, const char *key )
431{
432        fsd_conf_dict_t *i;
433        if( dict == NULL  ||  key == NULL )
434                return NULL;
435        for( i = dict->next;  i != NULL;  i = i->next )
436         {
437                if( !strcmp( i->key, key ) )
438                        return i->value;
439         }
440        return NULL;
441}
442
443
444void
445fsd_conf_dict_set(
446                fsd_conf_dict_t *dict, const char *key, fsd_conf_option_t *value
447                )
448{
449        fsd_conf_dict_t *i;
450        for( i = dict->next;  i != NULL;  i = i->next )
451         {
452                if( !strcmp( i->key, key ) )
453                        break;
454         }
455
456        if( i != NULL )
457         {
458                fsd_conf_option_destroy( i->value );
459                i->value = value;
460         }
461        else
462         {
463                fsd_conf_dict_t* volatile n = NULL;
464                TRY
465                 {
466                        fsd_malloc( n, fsd_conf_dict_t );
467                        n->key = fsd_strdup( key );
468                        n->value = value;
469                 }
470                EXCEPT_DEFAULT
471                 {
472                        fsd_free( n );
473                        fsd_exc_reraise();
474                 }
475                ELSE
476                 {
477                        n->next = dict->next;
478                        dict->next = n;
479                 }
480                END_TRY
481         }
482}
483
484
485fsd_conf_dict_t *
486fsd_conf_dict_merge( fsd_conf_dict_t *lhs, fsd_conf_dict_t *rhs )
487{
488        fsd_conf_dict_t *i, *j;
489
490        if( lhs == NULL )
491                return rhs;
492
493        if( rhs == NULL )
494                return lhs;
495
496        for( j = rhs->next;  j != NULL;  )
497         {
498                fsd_conf_dict_t *r = j;
499                j = j->next;
500
501                for( i = lhs->next;  i != NULL;  i = i->next )
502                        if( !strcmp( i->key, r->key ) )
503                                break;
504
505                if( i != NULL )
506                 {
507                        i->value = fsd_conf_option_merge( i->value, r->value );
508                        fsd_free( r->key );
509                        fsd_free( r );
510                 }
511                else
512                 {
513                        r->next = lhs->next;
514                        lhs->next = r;
515                 }
516         }
517
518        fsd_free( rhs );
519        return lhs;
520}
521
522
523void
524fsd_conf_dict_dump( fsd_conf_dict_t *dict )
525{
526        fsd_conf_dict_t *i;
527
528        if( dict == NULL )
529         {
530                printf( "(null)" );
531                return;
532         }
533        printf( "{" );
534        for( i=dict->next;  i;  i = i->next )
535         {
536                if( i != dict->next )
537                        printf( "," );
538                printf( " %s=", i->key );
539                fsd_conf_option_dump( i->value );
540         }
541        printf( " }" );
542}
543
544
545fsd_conf_option_t *
546fsd_conf_option_create_noraise( fsd_conf_type_t type, void *value )
547{
548        fsd_conf_option_t *volatile result = NULL;
549        TRY{ result = fsd_conf_option_create( type, value ); }
550        EXCEPT_DEFAULT{}
551        END_TRY
552        return result;
553}
554
555fsd_conf_dict_t *
556fsd_conf_dict_create_noraise(void)
557{
558        fsd_conf_dict_t *volatile result = NULL;
559        TRY{ result = fsd_conf_dict_create(); }
560        EXCEPT_DEFAULT{}
561        END_TRY
562        return result;
563}
564
565int
566fsd_conf_dict_set_noraise(
567                fsd_conf_dict_t *dict, const char *key, fsd_conf_option_t *value )
568{
569        volatile int rc = FSD_ERRNO_SUCCESS;
570        TRY{ fsd_conf_dict_set( dict, key, value ); }
571        EXCEPT_DEFAULT
572         {
573                const fsd_exc_t *e = fsd_exc_get();
574                rc = e->code(e);
575         }
576        END_TRY
577        return rc;
578}
579
Note: See TracBrowser for help on using the repository browser.