/*
 * String handling
 */
#include "main.h"
#include "modify.h"

#ifdef LOG
#include <xlog.h>
#endif

#include <stdio.h>
#include <string.h>

/*
 * Read a number from a file.
 */
int fread_number( FILE *fp )
{
    int number;
    bool sign;
    char c;

    do
    {
        if ( feof(fp) )
        {
#ifdef LOG
          L( "Fread_Number", "EOF encountered on read.", 0 );
#endif
          return 0;
        }
	c = getc( fp );
    }
    while ( isspace(c) );

    number = 0;

    sign   = FALSE;
    if ( c == '+' )
    {
    	c = getc( fp );
    }
    else if ( c == '-' )
    {
    	sign = TRUE;
    	c = getc( fp );
    }

    if ( !isdigit(c) )
    {
#ifdef LOG
        L( "Fread_Number", "bad format. (%c)", c );
#endif
     	return 0;
    }

    while ( isdigit(c) )
    {
        if ( feof(fp) )
        {
#ifdef LOG
            L("Fread_Number", "EOF encountered on read.", 0 );
#endif
            return number;
        }
    	number = number * 10 + c - '0';
    	c      = getc( fp );
    }

    if ( sign )
    	number = 0 - number;

    if ( c == '|' )
    	number += fread_number( fp );
    else if ( c != ' ' )
    	ungetc( c, fp );

    return number;
}

/*
 * Read a letter from a file.
 */
char fread_letter( FILE *fp )
{
    char c;

    do
    {
        if ( feof(fp) )
        {
#ifdef LOG
          L( "Fread_letter", "EOF encountered on read.", 0 );
#endif
          return '\0';
        }
	c = getc( fp );
    }
    while ( isspace(c) );

    return c;
}
 
/*
 * Read a string from file fp using strdup
 */
char *fread_string( FILE *fp )
{
    char buf[MSL];
    char *plast;
    char c;
    int ln;

    plast = buf;
    buf[0] = '\0';
    ln = 0;

    /*
     * Skip blanks.
     * Read first char.
     */
    do
    {
    	if ( feof(fp) )
    	{
#ifdef LOG
            L( "Fread_String", "EOF encountered on read.", 0 );
#endif
    	    return strdup("");
    	}
	c = getc( fp );
    }
    while ( isspace(c) );

    if ( ( *plast++ = c ) == '~' )
  	  return strdup( "" );

    for ( ;; )
    {
    	if ( ln >= (MSL - 1) )
    	{
#ifdef LOG
           L( "Fread_String", "String too long", 0 );
#endif
    	   *plast = '\0';
    	   return strdup( buf );
    	}
    	switch ( *plast = getc( fp ) )
    	{
        	default:
        	    plast++; ln++;
        	    break;

        	case EOF:
#ifdef LOG
                L( "Fread_String", "EOF", 0 );
#endif
        	    *plast = '\0';
        	    return strdup(buf);
        	    break;

        	case '\n':
        	    plast++;  ln++;
        	    *plast++ = '\r';  ln++;
        	    break;

        	case '\r':
        	    break;

        	case '~':
        	    *plast = '\0';
        	    return strdup( buf );
    	}
    }
}

/*
 * Read to end of line into static buffer			-Thoric
 */
char *fread_line( FILE *fp )
{
    static char line[MSL];
    char *pline;
    char c;
    int ln;

    pline = line;
    line[0] = '\0';
    ln = 0;

    /*
     * Skip blanks.
     * Read first char.
     */
    do
    {
    	if ( feof(fp) )
    	{
#ifdef LOG
            L( "Fread_Line", "EOF encountered on read.", 0 );
#endif
    	    strcpy(line, "");
    	    return line;
    	}
    	c = getc( fp );
    }
    while ( isspace(c) );

    ungetc( c, fp );
    do
    {
    	if ( feof(fp) )
    	{
#ifdef LOG
            L( "Fread_Line", "EOF encountered on read.", 0 );
#endif
    	    *pline = '\0';
    	    return line;
    	}
    	c = getc( fp );
    	*pline++ = c; ln++;
    	if ( ln >= (MSL - 1) )
    	{
#ifdef LOG
            L( "Fread_Line", "line too long!", 0 );
#endif
    	    break;
    	}
    }
    while ( c != '\n' && c != '\r' );

    do
    {
    	c = getc( fp );
    }
    while ( c == '\n' || c == '\r' );

    ungetc( c, fp );
    *pline = '\0';
    return line;
}

/*
 * Read one word (into static buffer).
 */
char *fread_word( FILE *fp )
{
    static char word[MSL];
    char *pword;
    char cEnd;

    do
    {
    	if ( feof(fp) )
    	{
#ifdef LOG
            L( "Fread_Word", "EOF encountered on read.", 0 );
#endif
    	    word[0] = '\0';
    	    return word;
    	}
    	cEnd = getc( fp );
    }
    while ( isspace( cEnd ) );

    if ( cEnd == '\'' || cEnd == '"' )
    {
    	pword   = word;
    }
    else
    {
    	word[0] = cEnd;
    	pword   = word+1;
    	cEnd    = ' ';
    }

    for ( ; pword < word + MIL; pword++ )
    {
    	if ( feof(fp) )
    	{
#ifdef LOG
            L( "Fread_Word", "EOF encountered on read.", 0 );
#endif
    	    *pword = '\0';
    	    return word;
    	}
    	*pword = getc( fp );
    	if ( cEnd == ' ' ? isspace(*pword) : *pword == cEnd )
    	{
    	    if ( cEnd == ' ' )
    		ungetc( *pword, fp );
    	    *pword = '\0';
    	    return word;
    	}
    }


#ifdef LOG
    L( "Fread_Word", "Word too long.", 0 );
#endif

    word[0] = '\0';
    return word;
}