Defines | Functions

cbf_lex.c File Reference

#include "cbf.h"
#include "cbf_compress.h"
#include "cbf_lex.h"
#include "cbf_codes.h"
#include "cbf_file.h"
#include "cbf_string.h"
#include "cbf_read_binary.h"
#include "cbf_read_mime.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
Include dependency graph for cbf_lex.c:

Go to the source code of this file.

Defines

#define cbf_errornez(f, v)   { if (((v)->errorcode = (f)) != 0) return ERROR; }

Functions

int cbf_return_text (int code, YYSTYPE *val, const char *text, char type)
int cbf_lex (YYSTYPE *val, cbf_file *file)

Define Documentation

#define cbf_errornez (   f,
 
)    { if (((v)->errorcode = (f)) != 0) return ERROR; }

Definition at line 140 of file cbf_lex.c.

Referenced by cbf_lex().


Function Documentation

int cbf_lex ( YYSTYPE val,
cbf_file file 
)

Definition at line 162 of file cbf_lex.c.

References BINARY, bits(), CATEGORY, cbf_add_fileconnection(), cbf_cistrcmp(), cbf_delete_fileconnection(), cbf_errornez, CBF_FILEREAD, CBF_FORMAT, cbf_frombase64(), cbf_frombasex(), cbf_fromqp(), cbf_get_buffer(), cbf_get_filecoordinates(), cbf_get_fileposition(), cbf_is_base64digest(), cbf_md5digest(), cbf_nblen(), cbf_parse_binaryheader(), cbf_parse_mimeheader(), cbf_read_character(), cbf_reset_buffer(), cbf_return_text(), cbf_save_character(), cbf_set_fileposition(), CBF_TOKEN_BIN, CBF_TOKEN_DQSTRING, CBF_TOKEN_MIME_BIN, CBF_TOKEN_NULL, CBF_TOKEN_SCSTRING, CBF_TOKEN_SQSTRING, CBF_TOKEN_WORD, COLUMN, COMMENT, cbf_compress_nodestruct::count, DATA, ENC_BASE10, ENC_BASE16, ENC_BASE64, ENC_BASE8, ENC_NONE, ENC_QP, ERROR, YYSTYPE::errorcode, ITEM, cbf_file::last_read, LOOP, MSG_DIGESTNOW, cbf_file::read_headers, STRING, and WORD.

Referenced by cbf_lex_wrapper().

{
  int data, loop, item, column, comment, string, ascii, 
      l, c, count, reprocess, errorcode, mime, encoding, bits, sign,
      checked_digest;

  long id, position;
  
  unsigned int file_column, compression;
  
  size_t size, length, code_size;
  
  const char *line;
    
  char out_line [(((sizeof (void *) +
                    sizeof (long int) * 2 +
                    sizeof (int) * 3) * CHAR_BIT) >> 2) + 55];

  char digest [25], new_digest [25];


  cbf_errornez (cbf_reset_buffer (file), val)
  
  l = c = file->last_read;
  
  column = c == '.';
  
  comment = c == '#';
  
  reprocess = (column || comment);
  
  data = loop = item = string = !reprocess;
  
  comment = !column;
  
  do
  {
    cbf_errornez (cbf_get_buffer (file, &line, &length), val)
    
    if (reprocess)

      reprocess = 0;

    else
    {
      l = c;

      c = cbf_read_character (file);
    }
    

      /* Discard spaces ([[:space:]]+) */

    if (length == 0)

      if (isspace (c))

         continue;
            
        
       /* DATA ([Dd][Aa][Tt][Aa][_][^[:space:]]*) */
    
    if (data)

      if (length < 5)

         data = toupper (c) == "DATA_" [length];

      else

        if (isspace (c) || c == EOF)

          return cbf_return_text (DATA, val, &line [5], 0);
   
   
       /* LOOP ([Ll][Oo][Oo][Pp][_]) */
     
    if (loop)
    {
      loop = toupper (c) == "LOOP_" [length];

      if (loop && length == 4)

        return LOOP;
    }

   
       /* ITEM ([_][^[:space:]\.]+) */
     
    if (item)

      if (length == 0)

        item = c == '_';

      else
      {
        item = !isspace (c) && c != '.' && c != '#' && c != EOF;

        if (length >= 2 && !item)

          if (c == '.')

            return cbf_return_text (CATEGORY, val, &line [1], 0);
            
          else

            return cbf_return_text (ITEM, val, &line [1], 0);
      }

   
      /* COLUMN (\.[^[:space:]]+) */
     
    if (column)

      if (isspace (c) || c == EOF)

        return cbf_return_text (COLUMN, val, &line [1], 0);

  
      /* STRING ([\'][^'\n]*[\'\n])|(([\"][^"\n]*[\"\n])) */
     
    if (string)

      if (length == 0)

        string = c == '\'' || c == '"';

      else

        if (c == line [0] || c == '\n' || c == EOF)

          if (line [0] == '\'')

            return cbf_return_text (STRING, val, &line [1], 
                                                  CBF_TOKEN_SQSTRING);
            
          else

            return cbf_return_text (STRING, val, &line [1],
                                                  CBF_TOKEN_DQSTRING);


       /* COMMENT ([#][^\n]*) */
     
    if (comment)

      if (length == 0)

        comment = c == '#';

      else

        if (c == '\n' || c == EOF)

          return cbf_return_text (COMMENT, val, &line [1], 0);


       /* WORD ([^[:space:]]+) */
     
    if (!data && !loop && !item && !comment && !string && !column)

      if (length && (isspace (c) || c == EOF))

          /* Missing value? */

        if (length == 1 && (line [0] == '?' || line [0] == '.'))
          
          return cbf_return_text (WORD, val, &line [0], CBF_TOKEN_NULL);
          
        else
        
          return cbf_return_text (WORD, val, &line [0], CBF_TOKEN_WORD);


      /* semicolon-delimited STRING (^;[^\n]*[\n])([^;][^\n]*[\n])*(;) */
      
    if (length == 0 && c == ';')
    {
      cbf_errornez (cbf_get_filecoordinates (file, NULL, &file_column), val)

      if (file_column == 1)
      {
          /* Save the position */

        cbf_errornez (cbf_get_fileposition (file, &position), val)
        
        mime = 0;

        do
        {
            /* Save the character */
            
          cbf_errornez (cbf_save_character (file, c), val)
          
          
            /* Check for a Mime boundary */
            
          if (c == '-')
          {
            cbf_errornez (cbf_get_buffer (file, &line, &length), val)

            cbf_nblen (line, &length);
            
            if (length > 29)

              mime = cbf_cistrcmp (&line [length - 30], 
                                   "\n--CIF-BINARY-FORMAT-SECTION--")
                                    == 0;
          }


            /* Read the next character */
            
          l = c;
         
          c = cbf_read_character (file);
          
          ascii = isgraph (c) || isspace (c);
        }
        while ((l != '\n' || c != ';') && !mime && ascii);


          /* Plain ASCII string */
          
        if (!mime && ascii)
        {
          cbf_errornez (cbf_get_buffer (file, &line, &length), val)
        
          ((char *) line) [length - 1] = '\0';


            /* Convert "\n\\;" -> "\n;" */

          for (count = 0; line [count]; count++)

            if (strncmp (&line [count], "\n\\;", 3) == 0)

              memmove ((void *) &line [count + 1], 
                       (void *) &line [count + 2], length - count - 2);

          return cbf_return_text (STRING, val, &line [1], 
                                                  CBF_TOKEN_SCSTRING);
        }
    
        encoding = ENC_NONE;
          
        bits = 0;
        
        sign = -1;
        
        checked_digest = 0;
        

          /* Mime header */
          
        if (mime)
        {
            /* Position */
          
          cbf_errornez (cbf_get_fileposition (file, &position), val)
          
        
            /* Read the header */

          cbf_errornez (cbf_parse_mimeheader (file, &encoding,
                                                    &size,
                                                    &id,
                                                    digest,
                                                    &compression,
                                                    &bits,
                                                    &sign), val)


            /* Check the digest? */
            
          if ((file->read_headers & MSG_DIGESTNOW) && 
                                    cbf_is_base64digest (digest))
          {
              /* Recalculate the digest (note that this will decode the
                 binary section but not save the result so this section
                 is not very efficient) */
              
            code_size = 0;

            switch (encoding)
            {
              case ENC_QP:
    
                cbf_errornez (cbf_fromqp (file, NULL, size, &code_size, 
                                                         new_digest), val)

                break;
      
              case ENC_BASE64:
    
                cbf_errornez (cbf_frombase64 (file, NULL, size, &code_size, 
                                                         new_digest), val)

                break;
      
              case ENC_BASE8:
              case ENC_BASE10:
              case ENC_BASE16:
    
                cbf_errornez (cbf_frombasex (file, NULL, size, &code_size, 
                                                         new_digest),val)

                break;

              case ENC_NONE:

                cbf_errornez (cbf_parse_binaryheader (file, NULL, \
                                                            NULL, \
                                                            NULL, \
                                                            mime), val)

                code_size = size;

                cbf_errornez (cbf_get_fileposition (file, &position), val)

                cbf_errornez (cbf_md5digest (file, code_size, new_digest), 
                                                              val)
                                                                  
                break;

             default:
    
               cbf_errornez (CBF_FORMAT, val)
            }
            
            
              /* Check the number of characters read */

            if ((size && (size != code_size)) || code_size == 0)

              cbf_errornez (CBF_FORMAT, val)
              

              /* Compare the old digest to the new one */

            if (strcmp (digest, new_digest) != 0)
            
              cbf_errornez (CBF_FORMAT | 2, val)

            checked_digest = 1;
          }
          else
          {
              /* Calculate the minimum number of characters in the data */
              
            if (encoding == ENC_NONE)
            {
              cbf_errornez (cbf_parse_binaryheader (file, NULL, NULL, NULL, \
                                                                  mime), val)
        
              cbf_errornez (cbf_get_fileposition (file, &position), val)

              code_size = size;
            }
            else
            
              if (encoding == ENC_QP)

                code_size = size;
              
              else
            
                if (encoding == ENC_BASE64)
              
                  code_size = size * 8 / 6;
                
                else
          
                  code_size = size / 4;


              /* Skip to the end of the data */

            cbf_errornez (cbf_set_fileposition (file, code_size, SEEK_CUR), 
                                                      val)
          }
        }
        else
        {
            /* Simple binary */
                      
          cbf_errornez (cbf_parse_binaryheader (file, &size, \
                                                      &id,   \
                                                      &compression, mime), val)
        
          cbf_errornez (cbf_get_fileposition (file, &position), val)

          code_size = size;


            /* Skip to the end of the data */

          cbf_errornez (cbf_set_fileposition (file, code_size, SEEK_CUR), val)
        }


          /* Find the terminating semi-colon */

        c = 0;
          
        do
        {
          l = c;
        
          c = cbf_read_character (file);
          
          if (c == EOF)
          
            cbf_errornez (CBF_FILEREAD, val)
        }
        while (l != '\n' || c != ';');


          /* Check the element size and sign */
          
        if (bits < 0 || bits > 64)
        
          cbf_errornez (CBF_FORMAT, val)
        
        if (bits == 0)
        
          bits = 32;
          
        if (sign == -1)
        
          sign = 1;


          /* Add a connection */
          
        cbf_errornez (cbf_add_fileconnection (&file, NULL), val)
        
        
          /* Code the id, file, position, size and digest */
          
        if (!cbf_is_base64digest (digest))
        
          strcpy (digest, "------------------------");
          
        sprintf (out_line, "%x %p %lx %lx %d %s %x %d %u", 
                            id, file, position, size, checked_digest, 
                            digest, bits, sign, compression);
        
        if (encoding == ENC_NONE)
        
          errorcode = cbf_return_text (BINARY, val, out_line, 
                                                      CBF_TOKEN_BIN);
          
        else
        
          errorcode = cbf_return_text (BINARY, val, out_line, 
                                                      CBF_TOKEN_MIME_BIN);

        if (errorcode == ERROR)
        
          val->errorcode |= cbf_delete_fileconnection (&file);
          
        return errorcode;
      }
    }


      /* Add the character to the text */
      
    errorcode = cbf_save_character (file, c);
    
    cbf_errornez (errorcode, val);
  }
  while (c != EOF);
  
  return 0;
}
int cbf_return_text ( int  code,
YYSTYPE val,
const char *  text,
char  type 
)

Definition at line 145 of file cbf_lex.c.

References CBF_ALLOC, cbf_copy_string(), cbf_compress_nodestruct::code, ERROR, YYSTYPE::errorcode, and YYSTYPE::text.

Referenced by cbf_lex().

{
  val->text = cbf_copy_string (NULL, text, type);

  if (!val->text)
  {
    val->errorcode = CBF_ALLOC;

    return ERROR;
  }

  return code;
}