@@ -21,6 +21,8 @@ typedef enum {
21
21
22
22
static backend * current_backend = NULL ;
23
23
static instance * current_instance = NULL ;
24
+ static size_t noverrides = 0 ;
25
+ static config_override * overrides = NULL ;
24
26
25
27
#ifdef _WIN32
26
28
#define GETLINE_BUFFER 4096
@@ -312,13 +314,179 @@ static int config_map(char* to_raw, char* from_raw){
312
314
return rv ;
313
315
}
314
316
317
+ static int config_line (char * line ){
318
+ map_type mapping_type = map_rtl ;
319
+ char * separator = NULL ;
320
+ size_t u ;
321
+
322
+ line = config_trim_line (line );
323
+ if (* line == ';' || strlen (line ) == 0 ){
324
+ //skip comments
325
+ return 0 ;
326
+ }
327
+ if (* line == '[' && line [strlen (line ) - 1 ] == ']' ){
328
+ if (!strncmp (line , "[backend " , 9 )){
329
+ //backend configuration
330
+ parser_state = backend_cfg ;
331
+ line [strlen (line ) - 1 ] = 0 ;
332
+ current_backend = backend_match (line + 9 );
333
+
334
+ if (!current_backend ){
335
+ fprintf (stderr , "Cannot configure unknown backend %s\n" , line + 9 );
336
+ return 1 ;
337
+ }
338
+
339
+ //apply overrides
340
+ for (u = 0 ; u < noverrides ; u ++ ){
341
+ if (!overrides [u ].handled && overrides [u ].type == override_backend
342
+ && !strcmp (overrides [u ].target , current_backend -> name )){
343
+ if (current_backend -> conf (overrides [u ].option , overrides [u ].value )){
344
+ fprintf (stderr , "Configuration override for %s failed for backend %s\n" ,
345
+ overrides [u ].option , current_backend -> name );
346
+ return 1 ;
347
+ }
348
+ overrides [u ].handled = 1 ;
349
+ }
350
+ }
351
+ }
352
+ else if (!strcmp (line , "[map]" )){
353
+ //mapping configuration
354
+ parser_state = map ;
355
+ }
356
+ else {
357
+ //backend instance configuration
358
+ parser_state = instance_cfg ;
359
+
360
+ //trim braces
361
+ line [strlen (line ) - 1 ] = 0 ;
362
+ line ++ ;
363
+
364
+ //find separating space and terminate
365
+ for (separator = line ; * separator && * separator != ' ' ; separator ++ ){
366
+ }
367
+ if (!* separator ){
368
+ fprintf (stderr , "No instance name specified for backend %s\n" , line );
369
+ return 1 ;
370
+ }
371
+ * separator = 0 ;
372
+ separator ++ ;
373
+
374
+ current_backend = backend_match (line );
375
+ if (!current_backend ){
376
+ fprintf (stderr , "No such backend %s\n" , line );
377
+ return 1 ;
378
+ }
379
+
380
+ if (instance_match (separator )){
381
+ fprintf (stderr , "Duplicate instance name %s\n" , separator );
382
+ return 1 ;
383
+ }
384
+
385
+ //validate instance name
386
+ if (strchr (separator , ' ' ) || strchr (separator , '.' )){
387
+ fprintf (stderr , "Invalid instance name %s\n" , separator );
388
+ return 1 ;
389
+ }
390
+
391
+ current_instance = current_backend -> create ();
392
+ if (!current_instance ){
393
+ fprintf (stderr , "Failed to instantiate backend %s\n" , line );
394
+ return 1 ;
395
+ }
396
+
397
+ current_instance -> name = strdup (separator );
398
+ current_instance -> backend = current_backend ;
399
+ fprintf (stderr , "Created %s instance %s\n" , line , separator );
400
+
401
+ //apply overrides
402
+ for (u = 0 ; u < noverrides ; u ++ ){
403
+ if (!overrides [u ].handled && overrides [u ].type == override_instance
404
+ && !strcmp (overrides [u ].target , current_instance -> name )){
405
+ if (current_backend -> conf_instance (current_instance , overrides [u ].option , overrides [u ].value )){
406
+ fprintf (stderr , "Configuration override for %s failed for instance %s\n" ,
407
+ overrides [u ].option , current_instance -> name );
408
+ return 1 ;
409
+ }
410
+ overrides [u ].handled = 1 ;
411
+ }
412
+ }
413
+ }
414
+ }
415
+ else if (parser_state == map ){
416
+ mapping_type = map_rtl ;
417
+ //find separator
418
+ for (separator = line ; * separator && * separator != '<' && * separator != '>' ; separator ++ ){
419
+ }
420
+
421
+ switch (* separator ){
422
+ case '>' :
423
+ mapping_type = map_ltr ;
424
+ //fall through
425
+ case '<' : //default
426
+ * separator = 0 ;
427
+ separator ++ ;
428
+ break ;
429
+ case 0 :
430
+ default :
431
+ fprintf (stderr , "Not a channel mapping: %s\n" , line );
432
+ return 1 ;
433
+ }
434
+
435
+ if ((mapping_type == map_ltr && * separator == '<' )
436
+ || (mapping_type == map_rtl && * separator == '>' )){
437
+ mapping_type = map_bidir ;
438
+ separator ++ ;
439
+ }
440
+
441
+ line = config_trim_line (line );
442
+ separator = config_trim_line (separator );
443
+
444
+ if (mapping_type == map_ltr || mapping_type == map_bidir ){
445
+ if (config_map (separator , line )){
446
+ fprintf (stderr , "Failed to map channel %s to %s\n" , line , separator );
447
+ return 1 ;
448
+ }
449
+ }
450
+ if (mapping_type == map_rtl || mapping_type == map_bidir ){
451
+ if (config_map (line , separator )){
452
+ fprintf (stderr , "Failed to map channel %s to %s\n" , separator , line );
453
+ return 1 ;
454
+ }
455
+ }
456
+ }
457
+ else {
458
+ //pass to parser
459
+ //find separator
460
+ separator = strchr (line , '=' );
461
+ if (!separator ){
462
+ fprintf (stderr , "Not an assignment: %s\n" , line );
463
+ return 1 ;
464
+ }
465
+
466
+ * separator = 0 ;
467
+ separator ++ ;
468
+ line = config_trim_line (line );
469
+ separator = config_trim_line (separator );
470
+
471
+ if (parser_state == backend_cfg && current_backend -> conf (line , separator )){
472
+ fprintf (stderr , "Failed to configure backend %s\n" , current_backend -> name );
473
+ return 1 ;
474
+ }
475
+ else if (parser_state == instance_cfg && current_backend -> conf_instance (current_instance , line , separator )){
476
+ fprintf (stderr , "Failed to configure instance %s\n" , current_instance -> name );
477
+ return 1 ;
478
+ }
479
+ }
480
+
481
+ return 0 ;
482
+ }
483
+
315
484
int config_read (char * cfg_filepath ){
316
485
int rv = 1 ;
317
486
size_t line_alloc = 0 ;
318
487
ssize_t status ;
319
- map_type mapping_type = map_rtl ;
320
488
FILE * source = NULL ;
321
- char * line_raw = NULL , * line , * separator ;
489
+ char * line_raw = NULL ;
322
490
323
491
//create heap copy of file name because original might be in readonly memory
324
492
char * source_dir = strdup (cfg_filepath ), * source_file = NULL ;
@@ -355,146 +523,88 @@ int config_read(char* cfg_filepath){
355
523
}
356
524
357
525
for (status = getline (& line_raw , & line_alloc , source ); status >= 0 ; status = getline (& line_raw , & line_alloc , source )){
358
- line = config_trim_line (line_raw );
359
- if (* line == ';' || strlen (line ) == 0 ){
360
- //skip comments
361
- continue ;
526
+ if (config_line (line_raw )){
527
+ goto bail ;
362
528
}
363
- if (* line == '[' && line [strlen (line ) - 1 ] == ']' ){
364
- if (!strncmp (line , "[backend " , 9 )){
365
- //backend configuration
366
- parser_state = backend_cfg ;
367
- line [strlen (line ) - 1 ] = 0 ;
368
- current_backend = backend_match (line + 9 );
369
-
370
- if (!current_backend ){
371
- fprintf (stderr , "Cannot configure unknown backend %s\n" , line + 9 );
372
- goto bail ;
373
- }
374
- }
375
- else if (!strcmp (line , "[map]" )){
376
- //mapping configuration
377
- parser_state = map ;
378
- }
379
- else {
380
- //backend instance configuration
381
- parser_state = instance_cfg ;
382
-
383
- //trim braces
384
- line [strlen (line ) - 1 ] = 0 ;
385
- line ++ ;
386
-
387
- //find separating space and terminate
388
- for (separator = line ; * separator && * separator != ' ' ; separator ++ ){
389
- }
390
- if (!* separator ){
391
- fprintf (stderr , "No instance name specified for backend %s\n" , line );
392
- goto bail ;
393
- }
394
- * separator = 0 ;
395
- separator ++ ;
529
+ }
396
530
397
- current_backend = backend_match (line );
398
- if (!current_backend ){
399
- fprintf (stderr , "No such backend %s\n" , line );
400
- goto bail ;
401
- }
531
+ //TODO check whether all overrides have been applied
402
532
403
- if (instance_match (separator )){
404
- fprintf (stderr , "Duplicate instance name %s\n" , separator );
405
- goto bail ;
406
- }
533
+ rv = 0 ;
534
+ bail :
535
+ free (source_dir );
536
+ if (source ){
537
+ fclose (source );
538
+ }
539
+ free (line_raw );
540
+ return rv ;
541
+ }
407
542
408
- //validate instance name
409
- if (strchr (separator , ' ' ) || strchr (separator , '.' )){
410
- fprintf (stderr , "Invalid instance name %s\n" , separator );
411
- goto bail ;
412
- }
543
+ int config_add_override (override_type type , char * data_raw ){
544
+ int rv = 1 ;
545
+ //heap a copy because the original data is probably not writable
546
+ char * data = strdup (data_raw );
413
547
414
- current_instance = current_backend -> create ();
415
- if (!current_instance ){
416
- fprintf (stderr , "Failed to instantiate backend %s\n" , line );
417
- goto bail ;
418
- }
548
+ if (!data ){
549
+ fprintf (stderr , "Failed to allocate memory\n" );
550
+ goto bail ;
551
+ }
419
552
420
- current_instance -> name = strdup (separator );
421
- current_instance -> backend = current_backend ;
422
- fprintf (stderr , "Created %s instance %s\n" , line , separator );
423
- }
424
- }
425
- else if (parser_state == map ){
426
- mapping_type = map_rtl ;
427
- //find separator
428
- for (separator = line ; * separator && * separator != '<' && * separator != '>' ; separator ++ ){
429
- }
553
+ char * option = strchr (data , '.' );
554
+ char * value = strchr (data , '=' );
430
555
431
- switch (* separator ){
432
- case '>' :
433
- mapping_type = map_ltr ;
434
- //fall through
435
- case '<' : //default
436
- * separator = 0 ;
437
- separator ++ ;
438
- break ;
439
- case 0 :
440
- default :
441
- fprintf (stderr , "Not a channel mapping: %s\n" , line );
442
- goto bail ;
443
- }
556
+ if (!option || !value ){
557
+ fprintf (stderr , "Override %s is not a valid assignment\n" , data_raw );
558
+ goto bail ;
559
+ }
444
560
445
- if ((mapping_type == map_ltr && * separator == '<' )
446
- || (mapping_type == map_rtl && * separator == '>' )){
447
- mapping_type = map_bidir ;
448
- separator ++ ;
449
- }
561
+ //terminate strings
562
+ * option = 0 ;
563
+ option ++ ;
450
564
451
- line = config_trim_line ( line ) ;
452
- separator = config_trim_line ( separator ) ;
565
+ * value = 0 ;
566
+ value ++ ;
453
567
454
- if (mapping_type == map_ltr || mapping_type == map_bidir ){
455
- if (config_map (separator , line )){
456
- fprintf (stderr , "Failed to map channel %s to %s\n" , line , separator );
457
- goto bail ;
458
- }
459
- }
460
- if (mapping_type == map_rtl || mapping_type == map_bidir ){
461
- if (config_map (line , separator )){
462
- fprintf (stderr , "Failed to map channel %s to %s\n" , separator , line );
463
- goto bail ;
464
- }
465
- }
466
- }
467
- else {
468
- //pass to parser
469
- //find separator
470
- separator = strchr (line , '=' );
471
- if (!separator ){
472
- fprintf (stderr , "Not an assignment: %s\n" , line );
473
- goto bail ;
474
- }
568
+ config_override new = {
569
+ .type = type ,
570
+ .handled = 0 ,
571
+ .target = strdup (config_trim_line (data )),
572
+ .option = strdup (config_trim_line (option )),
573
+ .value = strdup (config_trim_line (value ))
574
+ };
475
575
476
- * separator = 0 ;
477
- separator ++ ;
478
- line = config_trim_line ( line ) ;
479
- separator = config_trim_line ( separator );
576
+ if (! new . target || ! new . option || ! new . value ){
577
+ fprintf ( stderr , "Failed to allocate memory\n" ) ;
578
+ goto bail ;
579
+ }
480
580
481
- if (parser_state == backend_cfg && current_backend -> conf (line , separator )){
482
- fprintf (stderr , "Failed to configure backend %s\n" , current_backend -> name );
483
- goto bail ;
484
- }
485
- else if (parser_state == instance_cfg && current_backend -> conf_instance (current_instance , line , separator )){
486
- fprintf (stderr , "Failed to configure instance %s\n" , current_instance -> name );
487
- goto bail ;
488
- }
489
- }
581
+ overrides = realloc (overrides , (noverrides + 1 ) * sizeof (config_override ));
582
+ if (!overrides ){
583
+ noverrides = 0 ;
584
+ fprintf (stderr , "Failed to allocate memory\n" );
585
+ goto bail ;
490
586
}
587
+ overrides [noverrides ] = new ;
588
+ noverrides ++ ;
491
589
492
590
rv = 0 ;
493
591
bail :
494
- free (source_dir );
495
- if (source ){
496
- fclose (source );
497
- }
498
- free (line_raw );
592
+ free (data );
499
593
return rv ;
500
594
}
595
+
596
+ void config_free (){
597
+ size_t u ;
598
+
599
+ for (u = 0 ; u < noverrides ; u ++ ){
600
+ free (overrides [u ].target );
601
+ free (overrides [u ].option );
602
+ free (overrides [u ].value );
603
+ }
604
+
605
+ noverrides = 0 ;
606
+ free (overrides );
607
+ overrides = NULL ;
608
+
609
+ parser_state = none ;
610
+ }
0 commit comments