LCOV - code coverage report
Current view: top level - src - args.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 110 125 88.0 %
Date: 2016-12-21 02:12:01 Functions: 15 16 93.8 %

          Line data    Source code
       1             : /***************************************************************************//**
       2             : 
       3             :   @file         args.c
       4             : 
       5             :   @author       Stephen Brennan
       6             : 
       7             :   @date         Created Thursday, 31 October 2013
       8             : 
       9             :   @brief        Implementations of "libstephen/ad.h".
      10             : 
      11             :   @copyright    Copyright (c) 2013-2016, Stephen Brennan.  Released under the
      12             :                 Revised BSD License.  See the LICENSE.txt file for details.
      13             : 
      14             : *******************************************************************************/
      15             : 
      16             : #include <stdio.h>
      17             : #include <string.h>
      18             : #include <assert.h>
      19             : #include <inttypes.h>
      20             : 
      21             : #include "libstephen/base.h"
      22             : #include "libstephen/list.h"
      23             : #include "libstephen/ad.h"
      24             : #include "libstephen/ll.h"
      25             : 
      26             : /*******************************************************************************
      27             : 
      28             :                                Private Functions
      29             : 
      30             : *******************************************************************************/
      31             : 
      32             : /**
      33             :    @brief Returns the index of a flag for a specific character.
      34             : 
      35             :    Currently, only alphabetical characters are allowed.  This could change.  See
      36             :    the top of the file for the todo entry on this.
      37             : 
      38             :    @param c The character to find the index of.
      39             :    @returns The index of the flag.
      40             :  */
      41         155 : int flag_index(char c)
      42             : {
      43             :   int idx;
      44         155 :   if (c >= 'A' && c <= 'Z') {
      45          60 :     idx = 26 + (c - 'A');
      46          95 :   } else if (c >= 'a' && c <= 'z') {
      47          78 :     idx = (c - 'a');
      48             :   } else {
      49          17 :     idx = -1;
      50             :   }
      51         155 :   return idx;
      52             : }
      53             : 
      54             : /**
      55             :    @brief Add regular flags (i.e. characters) to the smb_ad structure.
      56             : 
      57             :    @param pData The structure containing the arg data.
      58             :    @param cFlags The string of flags.  Null terminated.
      59             :    @returns The last flag in the string (for parameter purposes).
      60             :  */
      61          17 : char process_flag(smb_ad *pData, char *cFlags)
      62             : {
      63             :   char last;
      64             :   int idx;
      65             : 
      66          72 :   while (*cFlags != '\0') {
      67          38 :     if ((idx = flag_index(*cFlags)) != -1) {
      68          21 :       last = *cFlags;
      69          21 :       pData->flags |= UINT64_C(1) << idx;
      70             :     }
      71          38 :     cFlags++;
      72             :   }
      73          17 :   return last;
      74             : }
      75             : 
      76             : /**
      77             :    @brief Add the long flag to the data structure.
      78             : 
      79             :    @param pData The structure containing the arg data.
      80             :    @param sTitle The title of the long flag, including '--'
      81             :    @returns The adjusted pointer to the title, without '--'.
      82             :  */
      83           6 : char *process_long_flag(smb_ad *pData, char *sTitle)
      84             : {
      85             :   DATA d, e;
      86           6 :   d.data_ptr = sTitle + 2;
      87           6 :   ll_append(pData->long_flags, d); // Add the portion AFTER the "--"
      88             : 
      89           6 :   e.data_ptr = NULL;
      90           6 :   ll_append(pData->long_flag_strings, e);
      91           6 :   return sTitle + 2;
      92             : }
      93             : 
      94             : /**
      95             :    @brief Add the bare string to the data structure.
      96             : 
      97             :    This function will first attempt to add the string as an argument to the
      98             :    previous flag, then the previous long flag, and then, finally, it will add
      99             :    itself as just a bare string.
     100             : 
     101             :    @param pData The structure with argument data.
     102             :    @param sStr The string to add.
     103             :    @param previous_long_flag The last long flag encountered.
     104             :    @param previous_flag The last regular (character) flag encountered.
     105             :  */
     106          10 : void process_bare_string(smb_ad *pData, char *sStr, char *previous_long_flag,
     107             :                          int previous_flag)
     108             : {
     109          10 :   if (previous_long_flag) {
     110             :     DATA d;
     111           3 :     d.data_ptr = sStr;
     112             :     smb_status status;
     113           3 :     ll_set(pData->long_flag_strings, ll_length(pData->long_flag_strings) - 1, d,
     114             :            &status);
     115           3 :     assert(status == SMB_SUCCESS);
     116           7 :   } else if (previous_flag != EOF) {
     117           3 :     int idx = flag_index(previous_flag);
     118             :     // The flag index would be negative if the previous flag was not a
     119             :     // letter.  We'll accept the segfault as an error.
     120           3 :     pData->flag_strings[idx] = sStr;
     121             :   } else {
     122             :     DATA d;
     123           4 :     d.data_ptr = sStr;
     124           4 :     ll_append(pData->bare_strings, d);
     125             :   }
     126          10 : }
     127             : 
     128             : /**
     129             :    @brief Find the string in the list and return its index, or -1.
     130             : 
     131             :    @param toSearch Pointer to list to search.
     132             :    @param toFind String to find.
     133             :    @returns Index of the string.
     134             :    @retval -1 String is not in the list.
     135             :  */
     136          15 : int find_string(smb_ll *toSearch, char *toFind)
     137             : {
     138             :   DATA d;
     139             :   char *sCurr;
     140          15 :   smb_iter iter = ll_get_iter(toSearch);
     141          15 :   int retVal = -1;
     142             :   smb_status status;
     143          45 :   while (iter.has_next(&iter)) {
     144          29 :     d = iter.next(&iter, &status);
     145             :     // We are using 'has_next' to check first!
     146          29 :     assert(status == SMB_SUCCESS);
     147          29 :     sCurr = (char *)d.data_ptr;
     148          29 :     if (strcmp(toFind, sCurr) == 0) {
     149          14 :       retVal = iter.index-1; // previous index
     150          14 :       break;
     151             :     }
     152             :   }
     153          15 :   iter.destroy(&iter);
     154          15 :   return retVal;
     155             : }
     156             : 
     157             : /*******************************************************************************
     158             : 
     159             :                                 Public Functions
     160             : 
     161             : *******************************************************************************/
     162             : 
     163           8 : void arg_data_init(smb_ad *data)
     164             : {
     165           8 :   data->flags = 0;
     166         424 :   for (int i = 0; i < MAX_FLAGS; i++) {
     167         416 :     data->flag_strings[i] = NULL;
     168             :   }
     169             : 
     170           8 :   data->long_flags = ll_create();
     171           8 :   data->long_flag_strings = ll_create();
     172           8 :   data->bare_strings = ll_create();
     173           8 :   return;
     174             : }
     175             : 
     176           1 : smb_ad *arg_data_create()
     177             : {
     178           1 :   smb_ad *data = smb_new(smb_ad, 1);
     179           1 :   arg_data_init(data);
     180           1 :   return data;
     181             : }
     182             : 
     183           8 : void arg_data_destroy(smb_ad * data)
     184             : {
     185           8 :   ll_delete(data->long_flags);
     186           8 :   ll_delete(data->bare_strings);
     187           8 :   ll_delete(data->long_flag_strings);
     188           8 : }
     189             : 
     190           1 : void arg_data_delete(smb_ad *data)
     191             : {
     192           1 :   arg_data_destroy(data);
     193           1 :   smb_free(data);
     194           1 : }
     195             : 
     196           6 : void process_args(smb_ad *data, int argc, char **argv)
     197             : {
     198           6 :   char *previous_long_flag = NULL;
     199           6 :   int previous_flag = EOF;
     200             : 
     201          45 :   while (argc--) {
     202             :     // At the beginning of the loop, argc refers to number of remaining args,
     203             :     // and argv points at the pointer to the current arg.
     204          33 :     switch (**argv) {
     205             :     case '-':
     206             :       // Processing new flag type, so set previous variables to invalid.
     207          24 :       previous_long_flag = NULL;
     208          24 :       previous_flag = EOF;
     209          24 :       switch (*(*argv + 1)) {
     210             :       case '-':
     211             :         // Long flag
     212           6 :         previous_long_flag = process_long_flag(data, *argv);
     213           6 :         previous_flag = EOF;
     214           6 :         break;
     215             :       case '\0':
     216             :         // A single '-'...counts as a bare string in my book
     217           1 :         process_bare_string(data, *argv, previous_long_flag, previous_flag);
     218             : 
     219           1 :         previous_long_flag = NULL;
     220           1 :         previous_flag = EOF;
     221           1 :         break;
     222             :       default:
     223             :         // The input is a short flag
     224          17 :         previous_flag = process_flag(data, *argv);
     225          17 :         previous_long_flag = NULL;
     226          17 :         break;
     227             :       }
     228          24 :       break;
     229             : 
     230             :     default:
     231             :       // This is a raw string.  We first need to check if it belongs to a flag.
     232           9 :       process_bare_string(data, *argv, previous_long_flag, previous_flag);
     233           9 :       previous_long_flag = NULL;
     234           9 :       previous_flag = EOF;
     235           9 :       break;
     236             :     }
     237             : 
     238          33 :     argv++;
     239             :   }
     240           6 : }
     241             : 
     242         109 : int check_flag(smb_ad *pData, char flag)
     243             : {
     244             :   int signed_idx;
     245             :   uint64_t idx;
     246         109 :   signed_idx = flag_index(flag);
     247         109 :   idx = (uint64_t) signed_idx;
     248         109 :   if (signed_idx != -1) {
     249         109 :     idx =  pData->flags & (UINT64_C(1) << idx);
     250         109 :     if (idx) return 1;
     251             :   }
     252          88 :   return 0;
     253             : }
     254             : 
     255           7 : int check_long_flag(smb_ad *data, char *flag)
     256             : {
     257           7 :   return find_string(data->long_flags, flag) + 1;
     258             : }
     259             : 
     260           4 : int check_bare_string(smb_ad *data, char *string)
     261             : {
     262           4 :   return find_string(data->bare_strings, string) + 1;
     263             : }
     264             : 
     265           5 : char *get_flag_parameter(smb_ad *data, char flag)
     266             : {
     267           5 :   int index = flag_index(flag);
     268           5 :   if (index == -1)
     269           0 :     return NULL;
     270             :   else
     271           5 :     return data->flag_strings[index];
     272             : }
     273             : 
     274           4 : char *get_long_flag_parameter(smb_ad *data, char *string)
     275             : {
     276           4 :   int index = find_string(data->long_flags, string);
     277           4 :   if (index == -1)
     278           0 :     return NULL;
     279             :   else {
     280             :     DATA d;
     281             :     smb_status status;
     282           4 :     d = ll_get(data->long_flag_strings, index, &status);
     283           4 :     assert(status == SMB_SUCCESS);
     284           4 :     return (char*)d.data_ptr;
     285             :   }
     286             : }
     287             : 
     288           0 : void ad_print(smb_ad *data, FILE *f)
     289             : {
     290           0 :   fprintf(f, "Arg Data:\n");
     291           0 :   fprintf(f, "Flags: 0x%" PRIx64 "\n", data->flags);
     292           0 :   for (int i = 0; i < MAX_FLAGS; i++) {
     293           0 :     if (data->flag_strings[i] != NULL) {
     294           0 :       fprintf(f, "%d: \"%s\"\n", i, data->flag_strings[i]);
     295             :     }
     296             :   }
     297           0 :   fprintf(f, "Long Flags: ");
     298           0 :   iter_print(ll_get_iter(data->long_flags), f, &data_printer_string);
     299             : 
     300           0 :   fprintf(f, "Long Flag Strings: ");
     301           0 :   iter_print(ll_get_iter(data->long_flag_strings), f, &data_printer_string);
     302             : 
     303           0 :   fprintf(f, "Bare Strings: ");
     304           0 :   iter_print(ll_get_iter(data->bare_strings), f, &data_printer_string);
     305           0 : }

Generated by: LCOV version 1.11