expand.c 4.39 KB
/*
 *  expand simple range syntax into individual numbers
 *  syntax:
 *      item,item,... where item is either a single number or 
 *      of numbers in the form 'num0-numn'.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

/*
   globals 
 */

int Fargc = 0;		/*

				   count of filename args 
				 */
char **Fargv = NULL;	/*

				   filename args 
				 */



/*
 *  isnumber()
 */
static int
isnumber (char c)
{
   if (c >= '0' && c <= '9')
      return 1;
   else
      return 0;
}



/*
 *  add_number_to_list()
 */
static void
add_number_to_list (char *number)
{
   if (Fargv)
      Fargv = (char **) realloc ((char *) Fargv, (Fargc + 1) * sizeof (char *));

   else
      Fargv = (char **) calloc ((Fargc + 1), sizeof (char *));

   if (Fargv)
      Fargv[Fargc] = (char *) calloc (1, strlen (number) + 1);

   if (Fargv[Fargc])
      strcpy (Fargv[Fargc++], number);

}

/*
 *  clear_number_list()
 */
static void
clear_number_list (void)
{
   int     i;

   for (i = 0; i < Fargc; i++)
     {
	free (Fargv[i]);
	Fargv[i] = NULL;
     }
   free (Fargv);
   Fargv = NULL;
   Fargc = 0;
}


/*
 *  range_expand - exapnd simple range expression
 *
 *  returns NULL terminated list of numeric strings
 */

void
range_expand (char *range)
{
   char   *exp, start_num[20], stop_num[20], prnt_num[20];
   int     n, state, next_state, start_n, stop_n, sindx, pindx, cindx;

   sindx = 0;
   pindx = 0;
   cindx = 0;

   for (state = 0, exp = range; *exp != '\0'; exp++)
     {
	switch (state)
	   {
	   case 0:
	      if (isnumber (*exp))
		{
		   start_num[sindx++] = *exp;
		   next_state = 1;
		}
	      else
		{
		   fprintf (stderr, "Syntax Error: character #%d (%c), state = %d\n", cindx, *exp, state);
		   exit (1);
		}
	      break;
	   case 1:
	      if (isnumber (*exp))
		{
		   start_num[sindx++] = *exp;
		   next_state = 1;
		}
	      else if (*exp == ',')
		{
		   start_num[sindx] = '\0';	/*
						   terminate start number 
						 */
		   sindx = 0;	/*
				   reset start number 
				 */
		   start_n = atoi (start_num);
		   sprintf (prnt_num, "%03d\0", start_n);
		   add_number_to_list (prnt_num);
		   next_state = 0;
		}
	      else if (*exp == '-')
		{
		   start_num[sindx] = '\0';	/*
						   terminate start number 
						 */
		   start_n = atoi (start_num);
		   next_state = 2;
		}
	      else
		{
		   fprintf (stderr, "Syntax Error: character #%d (%c), state = %d\n", cindx, *exp, state);
		   exit (1);
		}
	      break;
	   case 2:
	      if (isnumber (*exp))
		{
		   stop_num[pindx++] = *exp;
		   next_state = 3;
		}
	      else
		{
		   fprintf (stderr, "Syntax Error: character #%d (%c), state = %d\n", cindx, *exp, state);
		   exit (1);
		}
	      break;
	   case 3:
	      if (isnumber (*exp))
		{
		   stop_num[pindx++] = *exp;
		   next_state = 3;
		}
	      else if (*exp == ',')
		{
		   stop_num[pindx] = '\0';	/*
						   terminate stop number 
						 */
		   sindx = 0;	/*
				   reset start number 
				 */
		   pindx = 0;	/*
				   reset stop number 
				 */
		   stop_n = atoi (stop_num);
		   if (start_n >= stop_n)
		     {
			fprintf (stderr, "Syntax Error: in range first number(%d) must be smaller than second(%d)\n", start_n, stop_n);
			exit (1);
		     }
		   for (n = start_n; n <= stop_n; n++)
		     {
			sprintf (prnt_num, "%03d\0", n);
			add_number_to_list (prnt_num);
		     }
		   next_state = 0;
		}
	      else
		{
		   fprintf (stderr, "Syntax Error: character #%d (%c), state = %d\n", cindx, *exp, state);
		   exit (1);
		}
	      break;
	   }
	state = next_state;
	cindx++;
     }

   /*
    *  Cleanup
    */
   start_num[sindx] = '\0';
   start_n = atoi (start_num);

   if (pindx)
     {
	stop_num[pindx] = '\0';
	stop_n = atoi (stop_num);
     }

   if (sindx && !pindx)
     {
	sprintf (prnt_num, "%03d\0", start_n);
	add_number_to_list (prnt_num);
     }
   else if (sindx && pindx)
     {
	if (start_n >= stop_n)
	  {
	     fprintf (stderr, "Syntax Error: in range first number(%d) must be smaller than second(%d)\n", start_n, stop_n);
	     exit (1);
	  }
	for (n = start_n; n <= stop_n; n++)
	  {
	     sprintf (prnt_num, "%03d\0", n);
	     add_number_to_list (prnt_num);
	  }
     }

}


#ifdef DEBUG_EXPAND
/*
 *  Main
 */
main (int argc, char **argv)
{
   int     n;

   if (argc != 2)
     {
	printf ("Usage: %s <reg exp>\n", argv[0]);
	exit (0);
     }

   range_expand (argv[1]);

   for (n = 0; n < Fargc; n++)
      printf ("%s\n", Fargv[n]);
}

#endif /* DEBUG_EXPAND */