home *** CD-ROM | disk | FTP | other *** search
/ hobbes.nmsu.edu 2008 / 2008-06-02_hobbes.nmsu.edu.zip / new / scummc-0.2.0-os2.zip / ScummC / src / scc_param.c < prev    next >
Encoding:
C/C++ Source or Header  |  2008-02-03  |  6.2 KB  |  262 lines

  1. /* ScummC
  2.  * Copyright (C) 2004-2006  Alban Bedel
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17.  *
  18.  */
  19.  
  20. /**
  21.  * @file scc_param.c
  22.  * @ingroup utils
  23.  * @brief Command line parser
  24.  */
  25.  
  26. #include "config.h"
  27.  
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <stdio.h>
  31. #include <inttypes.h>
  32.  
  33. #include "scc_util.h"
  34. #include "scc_param.h"
  35.  
  36.  
  37. typedef struct scc_param_parser_st {
  38.   int type;
  39.   int flags;
  40.   int (*parse)(scc_param_t* p,char* val);
  41. } scc_param_parser_t;
  42.  
  43. static int scc_parse_flag(scc_param_t* param,char* val) {
  44.   int* p = param->ptr;
  45.  
  46.   p[0] = param->max;
  47.  
  48.   return 0;
  49. }
  50.  
  51. static int scc_parse_int(scc_param_t* param,char* val) {
  52.   int* p = param->ptr;
  53.   char* end = NULL;
  54.   int n;
  55.   
  56.   n = strtol(val,&end,0);
  57.  
  58.   if(!end || end[0] != '\0') return SCC_PARAM_INVALID;
  59.   if(n < param->min || n > param->max) return SCC_PARAM_OUT_OF_RANGE;
  60.  
  61.   p[0] = n;
  62.  
  63.   return 1;
  64. }
  65.  
  66. static int scc_parse_double(scc_param_t* param,char* val) {
  67.   double* p = param->ptr;
  68.   char* end = NULL;
  69.   double n;
  70.   
  71.   n = strtod(val,&end);
  72.  
  73.   if(!end || end[0] != '\0') return SCC_PARAM_INVALID;
  74.   if(n < param->min || n > param->max) return SCC_PARAM_OUT_OF_RANGE;
  75.  
  76.   p[0] = n;
  77.  
  78.   return 1;
  79. }
  80.  
  81. static int scc_parse_str(scc_param_t* param,char* val) {
  82.   char** p = param->ptr;
  83.  
  84.   if(val[0] == '\0') return SCC_PARAM_INVALID;
  85.  
  86.   if(p[0]) free(p[0]);
  87.   p[0] = strdup(val);
  88.  
  89.   return 1;
  90. }
  91.  
  92. static int scc_parse_str_list(scc_param_t* param,char* val) {
  93.   char*** p = param->ptr;
  94.   int i = 0;
  95.  
  96.   if(val[0] == '\0') return SCC_PARAM_INVALID;
  97.  
  98.   if(p[0]) {
  99.     for( ; p[0][i] ; i++);
  100.     p[0] = realloc(p[0],(i+2)*sizeof(char*));
  101.   } else
  102.     p[0] = malloc(2*sizeof(char*));
  103.  
  104.   p[0][i] = strdup(val);
  105.   p[0][i+1] = NULL;
  106.  
  107.   return 1;
  108. }
  109.  
  110. static int scc_parse_int_list(scc_param_t* param,char* val) {
  111.   int** p = param->ptr;
  112.   char* end = NULL;
  113.   int n;
  114.   
  115.   n = strtol(val,&end,0);
  116.  
  117.   if(!end || end[0] != '\0') return SCC_PARAM_INVALID;
  118.   if(n < param->min || n > param->max) return SCC_PARAM_OUT_OF_RANGE;
  119.  
  120.   if(val[0] == '\0') return SCC_PARAM_INVALID;
  121.  
  122.   if(p[0]) {
  123.     p[0] = realloc(p[0],(p[0][0]+2)*sizeof(int));
  124.   } else {
  125.     p[0] = malloc(2*sizeof(int));
  126.     p[0][0] = 0;
  127.   }
  128.  
  129.   p[0][p[0][0]+1] = n;
  130.   p[0][0]++;
  131.  
  132.   return 1;
  133. }
  134.  
  135. static int scc_parse_help(scc_param_t* param,char* val) {
  136.   scc_print_help(param->ptr,0);
  137.   return 0;
  138. }
  139.  
  140.  
  141. scc_param_parser_t scc_param_parser[] = {
  142.   { SCC_PARAM_FLAG, SCC_PARAM_TYPE_NO_ARG, scc_parse_flag },
  143.   { SCC_PARAM_INT, 0, scc_parse_int },
  144.   { SCC_PARAM_DBL, 0, scc_parse_double },
  145.   { SCC_PARAM_STR, 0, scc_parse_str },
  146.   { SCC_PARAM_STR_LIST, 0, scc_parse_str_list },
  147.   { SCC_PARAM_INT_LIST, 0, scc_parse_int_list },
  148.   { SCC_PARAM_HELP, SCC_PARAM_TYPE_NO_ARG, scc_parse_help },
  149.   { 0, 0, NULL }
  150. };
  151.  
  152. static scc_param_parser_t* scc_param_get_parser(int type) {
  153.   int i;
  154.  
  155.   for(i = 0 ; scc_param_parser[i].type > 0 ; i++) {
  156.     if(scc_param_parser[i].type == type) return &scc_param_parser[i];
  157.   }
  158.   return NULL;
  159. }
  160.  
  161. int scc_param_parse(scc_param_t* params,char* k,char* v) {
  162.   scc_param_parser_t* parser;
  163.   int i;
  164.  
  165.   for(i = 0 ; params[i].name ; i++) {
  166.     if(!strcmp(params[i].name,k)) break;
  167.   }
  168.  
  169.   if(!params[i].name) return SCC_PARAM_UNKNOWN;
  170.  
  171.   parser = scc_param_get_parser(params[i].type);
  172.   if(!parser) return SCC_PARAM_INVALID_TYPE;
  173.  
  174.   if(!((parser->flags & SCC_PARAM_TYPE_NO_ARG) || v))
  175.     return SCC_PARAM_NEED_ARG;
  176.  
  177.   return parser->parse(¶ms[i],v);
  178. }
  179.  
  180. scc_cl_arg_t* scc_param_parse_argv(scc_param_t* params,int argc,char** argv) {
  181.   int n = 0,r,get_args = 1;
  182.   scc_cl_arg_t* list = NULL, *last = NULL, *arg;
  183.   
  184.   while(n < argc) {
  185.     if(get_args && argv[n][0] == '-') {
  186.       // end of param list
  187.       if(!strcmp(argv[n],"--")) {
  188.     get_args = 0;
  189.     n++;
  190.     continue;
  191.       }
  192.  
  193.       // that should be ok as argv must be NULL terminated
  194.       r = scc_param_parse(params,&argv[n][1],argv[n+1]);
  195.       if(r < 0) {
  196.     switch(r) {
  197.     case SCC_PARAM_UNKNOWN:
  198.       fprintf(stderr,"Unknown parameter: %s\n",argv[n]);
  199.       break;
  200.     case SCC_PARAM_NEED_ARG:
  201.       fprintf(stderr,"Parameter %s needs an argument.\n",argv[n]);
  202.       break;
  203.     case SCC_PARAM_INVALID:
  204.       fprintf(stderr,"Argument of %s is invalid: %s.\n",argv[n],argv[n+1]);
  205.       break;
  206.     case SCC_PARAM_OUT_OF_RANGE:
  207.       fprintf(stderr,"Argument of %s is out of range.\n",argv[n]);
  208.       break;
  209.     case SCC_PARAM_INVALID_TYPE:
  210.       fprintf(stderr,"Parameter %s have an invalid type.\n",argv[n]);
  211.       break;
  212.     default:
  213.       fprintf(stderr,"Error while parsing parameter %s.\n",argv[n]);
  214.       break;
  215.     }
  216.     // free list
  217.     return NULL;
  218.       }
  219.       n += 1+r;
  220.       continue;
  221.     }
  222.  
  223.     arg = calloc(1,sizeof(scc_cl_arg_t));
  224.     arg->val = strdup(argv[n]);
  225.     SCC_LIST_ADD(list,last,arg);
  226.     n++;
  227.   }
  228.  
  229.   return list;
  230. }
  231.  
  232. static void scc_param_print_help(scc_param_help_t* help, unsigned ident_size) {
  233.   char ident[ident_size+1];
  234.   if(ident_size > 0) memset(ident,' ',ident_size);
  235.   ident[ident_size] = 0;
  236.   if(help->group) {
  237.     int i;
  238.     scc_log(LOG_MSG,"\n%s%s:\n",ident,help->name);
  239.     for(i = 0 ; help->group[i].name ; i++)
  240.       scc_param_print_help(&help->group[i],ident_size+2);
  241.   } else {
  242.     int len = strlen(help->name) + (help->arg ? (2+strlen(help->arg)+1) : 0);
  243.     char tmp[len+1];
  244.     if(help->arg)
  245.       sprintf(tmp,"%s <%s>",help->name,help->arg);
  246.     else
  247.       sprintf(tmp,"%s",help->name);
  248.     scc_log(LOG_MSG,"%s-%-20s  %s\n",ident,tmp,help->desc);
  249.   }
  250. }
  251.  
  252. void scc_print_help(scc_help_t* help, int exit_code) {
  253.   scc_param_help_t* phelp;
  254.   scc_log(LOG_MSG,"Usage: %s %s\n",help->name,help->usage);
  255.   if(help->param_help) {
  256.     for(phelp = help->param_help ; phelp->name ; phelp++)
  257.       scc_param_print_help(phelp,0);
  258.     scc_log(LOG_MSG,"\n");
  259.   }
  260.   if(exit_code >= 0) exit(exit_code);
  261. }
  262.