# include "opihi.h"

/**********************************************************************/
/* returns a pointer to an isolated string containing the first word,
   removing leading whitespace.  A "word" is a contiguous set of 
   characters from the set: alphanumerics, and any of: / . _ -
   Any other single, non-whitespace characters are considered to be 
   complete words in themselves.  Any characters surrounded by quotes 
   make a single word 
*/

char *thisword (char *string) {

  int i, j, N;
  char *word;

  if (string == (char *) NULL) return ((char *) NULL);

  for (i = 0; whitespace (string[i]); i++);
  if (string[i] == 0) return ((char *)NULL);
  if (string[i] == ';') {
    word = strncreate (&string[i], 1);
    return (word);
  }

  /* a string of characters contained within double quotes is 
      a single entry.  check that there are pairs of quotes,
      return only the string between the quotes */
  if (string[i] == '"') { 
    i++;
    if (string[i] == 0) return ((char *) NULL);
    for (j = i; (string[j] != 0) && (string[j] != '"'); j++);
    if (string[j] == 0) {
      fprintf (stderr, "misbalanced quotes\n");
      return ((char *)NULL);
    }
    word = strncreate (&string[i], j - i);
    return (word);
  } 

  /* a string of characters contained within parentheses is 
      a single entry.  check that there are matched pairs of
      parentheses, return string, including exterior parentheses */
  if (string[i] == '(') { 
    i++;
    N = 1;
    if (string[i] == 0) return ((char *) NULL);
    for (j = i; (string[j] != 0) && (N > 0); j++) {
      if (string[j] == '(') {
	N++;
      }
      if (string[j] == ')') {
	N--;
      }
    }
    if ((string[j] == 0) && (N != 0)) {
      fprintf (stderr, "misbalanced parenthesis\n");
      return ((char *)NULL);
    }
    word = strncreate (&string[i-1], j - i + 1);
    return (word);
  } 


  for (j = i; (string[j] != 0) && (string[j] != ';') && !whitespace(string[j]); j++);
  word = strncreate (&string[i], j - i);
  return (word);

}

/* returns a pointer to an isolated string containing the first command,
   removing leading whitespace.  A command ends with the first non whitespace */
char *thiscomm (char *string) {

  int i, j;
  char *word;

  if (string == (char *) NULL) return ((char *) NULL);

  for (i = 0; whitespace (string[i]); i++);
  if (string[i] == 0) return ((char *)NULL);

  for (j = i; ((string[j] != 0) && !whitespace (string[j])); j++);
  if (i == j) return ((char *) NULL);

  word = strncreate (&string[i], j - i);
  return (word);

}

/* take a pointer to the beginning of a variable (ie $foo)
and extract only the variable name (eg, foo) */

char *thisvar (char *string) {

  int i;
  char *word;

  if (string == (char *) NULL) return ((char *) NULL);
  if (string[0] != '$') return ((char *) NULL);

  for (i = 1; ISVAR(string[i]); i++);
  if (i == 1) return ((char *) NULL);

  word = strncreate (&string[1], i - 1);
  return (word);

}


/**********************************************************************/
/* returns a pointer to the next word, or (char *) NULL if there is not a next word */
char *nextword (char *string) {

  int i, j;

  if (string == (char *) NULL) return ((char *) NULL);

  for (i = 0; whitespace (string[i]); i++);
  if (string[i] == 0) return ((char *)NULL);

  if (string[i] == '"') { 
    i++;
    if (string[i] == 0) return ((char *) NULL);
    for (; (string[i] != 0) && (string[i] != '"'); i++);
    if (string[i] == 0) {
      fprintf (stderr, "misbalanced quotes\n");
      return ((char *)NULL);
    }
    i++;
    for (; (string[i] != 0) && whitespace (string[i]); i++);
    if (string[i] == 0) return ((char *) NULL);
    return (&string[i]);
  } 

  if (string[i] == '(') { 
    i++; 
    j = 1;
    if (string[i] == 0) return ((char *) NULL);
    for (; (string[i] != 0) && (j > 0); i++) {
      if (string[i] == '(') {
	j++;
      }
      if (string[i] == ')') {
	j--;
      }
    }
    if ((string[i] == 0) && (j != 0)) {
      fprintf (stderr, "misbalanced parenthesis\n");
      return ((char *)NULL);
    }
    for (; (string[i] != 0) && whitespace (string[i]); i++);
    if (string[i] == 0) return ((char *) NULL);
    return (&string[i]);
  } 

  if (string[i] == ';') i++;
  for (; (string[i] != 0) && (string[i] != ';') && !whitespace(string[i]); i++);
  for (; (string[i] != 0) && whitespace (string[i]); i++);
  if (string[i] == 0) return ((char *) NULL);

  return (&string[i]);
}

/* returns a pointer to the next command, or (char *) NULL 
   if there is not a next command.  A command is bounded by whitespace */
char *nextcomm (char *string) {

  int i;

  if (string == (char *) NULL) return ((char *) NULL);
  
  for (i = 0; (string[i] != 0) && !whitespace (string[i]); i++);
  if (string[i] == 0) return ((char *) NULL);
  
  for (; whitespace (string[i]); i++);
  if (string[i] == 0) return ((char *) NULL);

  return (&string[i]);
}

/* returns a pointer to the previous word,
   or (char *) NULL if there is not a previous word
*/
char *lastword (char *string, char *c) {

  if (string == (char *) NULL) return ((char *) NULL);
  if (c == (char *) NULL) return ((char *) NULL);

  for (; !whitespace(*c) && (c >= string); c--);
  if (c < string) return ((char *)NULL);

  for (; whitespace(*c) && (c >= string); c--);
  if (c < string)
    return ((char *)NULL);
  for (; !whitespace(*c) && (c >= string); c--);
  c++;
  return (c);
}



/* take a pointer to the beginning of a variable (ie $fred) and return
   a pointer to the next thing (non whitespace) which is not part of the
   variable extract only the variable name */

char *aftervar (char *string) {

  int i, j;

  if (string == (char *) NULL) return ((char *) NULL);
  if (string[0] != '$') return ((char *) NULL);

  for (i = 1; ISVAR(string[i]); i++);
  if (i == 1) return ((char *) NULL);

  for (j = i; whitespace (string[j]); j++);
  if (string[j] == 0) return ((char *)NULL);

  return (&string[j]);

}


/* returns a pointer to the previous var, 
   or (char *) NULL if there is not a previous word
*/
char *lastvar (char *string, char *c) {

  if (string == (char *) NULL) return ((char *) NULL);
  if (c == (char *) NULL) return ((char *) NULL);

  for (; (c >= string) && whitespace(*c); c--);
  if (c < string) return ((char *)NULL);

  for (; (c >= string) && ISVAR(*c) ; c--);
  if ((c < string) || (*c != '$')) return ((char *)NULL);

  return (c);
}
