/******************************************************************************
 * Author:      Shawn Stoffer, storm@cs.unm.edu
 * 
 * Description: This program is a simple example of how to convert from 
 *              a hex number to a decimal number.  Using utilities already 
 *              present within the C-language.
 * 
 * Compiler:    gcc
 * 
 * Language:    C
 * 
 * Systems:     This was made on a Sun Solaris machine, but should have no 
 *              dependencies on this architecture, and should not require 
 *              a porting effort to be used on any other architectures.
 * 
 *****************************************************************************/
#include <stdio.h>  /* for scanf, printf, etc... */
#include <string.h> /* for strspn, sscanf */
#include <ctype.h>  /* for isspace and isalpha */

int main(int argc, char ** argv) {
  /* Make a 1k buffer in mem. */
  char buf[1024];

  char *tmpbuf; /* This is used to point to buf. */

  int num = 0; 

  if (argc <= 1 || strcmp(argv[1], "-nointro")) {
    /* Prompt the user. */
    printf("This program will not tell you if you give it invalid input, but\n");
    printf("will instead ignore it.  So watch what you type!\n");
    printf("Enter a string of numbers.  Each will be output as a hex number.\n");
    printf("Enter quit to finish.\n");
  }

  /* 
   * This is the main loop.  It consists of a main loop, controlling overall 
   * program repitition, and an inner loop controlling the actual conversions.
   */
  while (*buf != 'q' && *buf != 'Q') {
    /* 
     * Read the numbers.  The leading \n is due to the fact that the [^\n]
     * does not read the ending newline of a line, and therefore the program
     * will fall into an infinite loop, or wait for another input before 
     * processing the input, both of these are inappropriate behaviors and so
     * neither of the approaches have been used.
     */
    printf("\n");
    if (scanf("\n%[^\n]", buf) < 1) break;
    
    /* setup for the loop */
    tmpbuf = buf;
    do {
      /* 
       * we are going to start each iteration as if we are just past at a space,
       * or we are at the beginning of a line.
       */
      char tmpbuf2[128];
      /* 
       * First, we want to check if this is a number, so read up to a
       * whitespace, and then if this is a number, then we can output it, 
       * otherwise, output it as a string.
       */
      { int i;
      /* Check if this a valid number. */
      for (i = 0;
           i < 128 && *tmpbuf && 
           ((*tmpbuf >= 'a' && *tmpbuf <= 'f') ||
            (*tmpbuf >= 'A' && *tmpbuf <= 'F') ||
            (*tmpbuf >= '0' && *tmpbuf <= '9') ||
            (*tmpbuf == 'x'));
           tmpbuf++, i++)
        tmpbuf2[i] = *tmpbuf;
      tmpbuf2[i] = '\0';
      }
      if (*tmpbuf && !isspace((int)*tmpbuf)) {
        /*
         * We did not get a number, so simply output the string and then output
         * until we find another space.
         */
        printf(tmpbuf2);
        for (;*tmpbuf && !isspace((int)*tmpbuf); tmpbuf++) 
          putchar(*tmpbuf);
        if (*tmpbuf) {  /* This is a space...Just output all of them. */
          for (; *tmpbuf && isspace((int)*tmpbuf); tmpbuf++) putchar(*tmpbuf);
        }
        continue;  /* We are either at the end of the string or we are after
                    * the spaces. 
                    */
      }
     

      if (sscanf(tmpbuf2, "%x", &num) == 1)
        printf("%8.8x = %d", num, num);
      if (isspace((int)*tmpbuf)) 
        for (; *tmpbuf && isspace((int)*tmpbuf); tmpbuf++) putchar(*tmpbuf);

    } while (tmpbuf && *tmpbuf);

  }  /* End main loop. */

  /* 
   * A small note:  should there have been any catastrophic errors, then you
   * would have returned 1 or some non-zero value somewhere else in the 
   * program, to indicate failure, but since this program does not have a 
   * catastrophic error condition (something which set the program in a state
   * from which it could not perform correctly anymore), then we simply return
   * 0 all the time.
   */
  return 0;
}
