config.c

#define _GNU_SOURCE

#include "config.h"
#include "help.h"

#include <getopt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

float to_seconds(float val, const char *unit) {
  if (unit == NULL || unit[0] == '\0') {
    val = val;
  } else if (unit[0] == 'm') {
    val = val / 1000.0;
  } else if (unit[0] == 'u') {
    val = val / 1000000.0;
  } else {
    val = NAN;
  }
  return val;
}

void clean_line(FILE *file) {
  char buf[20];
  while (fscanf(file, "%20[^\n]", buf) > 0);
}
void clean_white_space(FILE *file) {
  char buf[20];
  while (fscanf(file, "%[ \t]", buf) > 0);
}

config_t* config_init(void) {
  return (config_t *) calloc(1, sizeof(config_t));
}

void config_read_cmdline(config_t *config, int argc, char *argv[]) {
  int opcja;
  opterr = 0;
  while((opcja = getopt(argc, argv, "o:O:r:d:h")) != -1) {
    switch (opcja) {
      case 'o':
        if (strcmp("dsp", optarg) == 0) {
          config->output_mode = OUTPUT_DSP;
        } else if (strcmp("alsa", optarg) == 0) {
          config->output_mode = OUTPUT_ALSA;
        } else if (strcmp("uC", optarg) == 0) {
          config->output_mode = OUTPUT_UC;
        }
        break;
      case 'O':
        config->output_device_name = malloc(strlen(optarg));
        stpcpy(config->output_device_name, optarg);
        break;
      case 'r':
        config->rate = atoi(optarg);
        break;
      case 'd':
        if (strcmp("-", optarg) == 0) {
          config->display_file = stdout;
        } else {
          config->display_file = fopen(optarg, "w+");
          if (config->display_file == NULL) {
            fprintf(stderr, "ERROR: Can't open %s file\n", optarg);
            exit(-1);
          }
        }
        break;
      case 'h':
        print_help(stdout, argv[0], 0);
      default:
        print_help(stderr, argv[0], -1);
    }
  }
  
  if (config->output_mode == 0 || config->rate == 0) {
    fprintf(stderr, "ERROR: Incorect -o or -r value\n");
    print_help(stderr, argv[0], -1);
  }
  
  if (optind < argc) {
    config->config_file = fopen(argv[optind], "r");
    if (config->config_file == NULL) {
      fprintf(stderr, "ERROR: Can't open %s file\n", argv[optind]);
      exit(-1);
    }
  } else {
    print_help(stderr, argv[0], -1);
  }
}

void config_parse_file(config_t *config) {
  char buf[1024], bufU[3];
  double bufV;
  int code, num, num_base;
  
  /// FIRST LINE
  bufU[0] = '\0';
  code = fscanf(
    config->config_file,
    "%20s %d %lf%[^0-9. \t\n]2s",
    buf,
    &(config->num_of_periods),
    &bufV,
    bufU
  );
  
  if (code < 3 || strcmp("TIME", buf) != 0) print_parse_error(1, NULL);
  
  config->one_period_time = to_seconds(bufV, bufU);
  if ( isnan(config->one_period_time) ) {
    print_parse_error(1, "Unknown SI prefix\n");
  }
  
  clean_line(config->config_file);
  
  
  /// SECOND LINE
  code = fscanf(config->config_file, "%20s", buf);
  if (code != 1) print_parse_error(2, "No macro name?\n");
  
  if (strcmp("SQUARE", buf) == 0) {
    config->macro = SQUARE;
    num = 1;
  } else if (strcmp("SIN", buf) == 0) {
    config->macro = SIN;
    num = 1;
  } else if (strcmp("SAW_R", buf) == 0) {
    config->macro = SAW_R;
    num = 1;
  } else if (strcmp("SAW_L", buf) == 0) {
    config->macro = SAW_L;
    num = 1;
  } else if (strcmp("TRIANGLE", buf) == 0) {
    config->macro = TRIANGLE;
    num = 2;
  } else if (strcmp("FUNCTION", buf) == 0) {
    config->macro = FUNCTION;
    num = -1;
  } else if (strcmp("PCM", buf) == 0) {
    config->macro = PCM;
    num = 0;
  } else {
    print_parse_error(2, "Unknown macro name\n");
  }
  
  num_base = num - 1;
  
  if (num < 0) {
    clean_white_space(config->config_file);
    code = fscanf(
      config->config_file,
      "%1023c",
      buf
    );
    if (code < 1) {
      print_parse_error(2, "Error parsing function string\n");
    }
    
    buf[1023] = '\0';
    char *tmp = index(buf, '\n');
    if (tmp == NULL) {
      print_parse_error(2, "too long or no new line at end function string\n");
    } else {
      // zaraz po znaku nowej linii kończymy napis
      *(tmp+1) = '\0';
    }
    
    config->function_len = (int)(tmp - buf) + 2;
    config->function = malloc(config->function_len);
    strncpy(config->function, buf, config->function_len);
  } else while (num-- > 0) {
    bufU[0] = '\0';
    
    code = fscanf(
      config->config_file,
      "%lf%[^0-9. \t\n]2s",
      &(config->macro_args[num_base-num]),
      bufU
    );
    
    if (code < 1) {
      if (num_base == 0) {
        fprintf(stderr, "WARNING: Use time_of_one_period instand of macro %d parametr\n", num);
        config->macro_args[0] = config->one_period_time;
        continue;
      } else {
        print_parse_error(2, "No macro parametr?\n");
      }
    }
    
    config->macro_args[num_base-num] = to_seconds(config->macro_args[num_base-num], bufU);
    if ( isnan(config->macro_args[num_base-num]) ) {
      print_parse_error(2, "Unknown SI prefix\n");
    }
  }
  
  clean_line(config->config_file);
}


void config_free(config_t *config) {
  fclose(config->config_file);
  if (config->function != NULL)
    free(config->function);
  if (config->output_device_name != NULL)
    free(config->output_device_name);
  free(config);
}

XHTML generated by highlight (http://www.andre-simon.de/) from config.c



Copyright (c) 1999-2015, Robert Paciorek (http://www.opcode.eu.org/), BSD/MIT-type license


Redystrybucja wersji źródłowych i wynikowych, po lub bez dokonywania modyfikacji JEST DOZWOLONA, pod warunkiem zachowania niniejszej informacji o prawach autorskich. Autor NIE ponosi JAKIEJKOLWIEK odpowiedzialności za skutki użytkowania tego dokumentu/programu oraz za wykorzystanie zawartych tu informacji.

This text/program is free document/software. Redistribution and use in source and binary forms, with or without modification, ARE PERMITTED provided save this copyright notice. This document/program is distributed WITHOUT any warranty, use at YOUR own risk.

Valid XHTML 1.1 Dokument ten (URL: http://www.opcode.eu.org/inne/other_projects/generator/config.c) należy do serwisu OpCode. Autorem tej strony jest Robert Paciorek, wszelkie uwagi proszę kierować na adres e-mail serwisu: webmaster@opcode.eu.org.
Data ostatniej modyfikacji artykulu: '2014-01-07 19:27:43 (UTC)' (data ta może być zafałszowana niemerytorycznymi modyfikacjami artykułu).