aboutsummaryrefslogblamecommitdiffstats
path: root/src/mds-kbdc/parsed.c
blob: bebd4ab9b583e847d15df0f8fe73ae6a6c11910d (plain) (tree)
1
2
3
                                 
                                                                           
















                                                                        
                    





















                                                                 
                          
                                              




                                               


                                                           

                                                     



                                             










                                                                  






                                                                                 









                                                                         
                                                    
  
















                                                                                                              
                                           


















                                                                                
                                                     




                                                   
                                                                          

               
      






                                        
/**
 * mds — A micro-display server
 * Copyright © 2014, 2015, 2016  Mattias Andrée (maandree@member.fsf.org)
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "parsed.h"

#include <stdlib.h>
#include <string.h>
#include <strings.h>



/**
 * Initialise a `mds_kbdc_parsed_t*`
 * 
 * @param  this  The `mds_kbdc_parsed_t*`
 */
void mds_kbdc_parsed_initialise(mds_kbdc_parsed_t* restrict this)
{
  memset(this, 0, sizeof(mds_kbdc_parsed_t));
}


/**
 * Release all resources allocated in a `mds_kbdc_parsed_t*`
 * 
 * @param  this  The `mds_kbdc_parsed_t*`
 */
void mds_kbdc_parsed_destroy(mds_kbdc_parsed_t* restrict this)
{
  mds_kbdc_tree_free(this->tree);
  mds_kbdc_source_code_destroy(this->source_code);
  free(this->source_code);
  free(this->pathname);
  mds_kbdc_parse_error_free_all(this->errors);
  while (this->languages_ptr--)
    free(this->languages[this->languages_ptr]);
  free(this->languages);
  while (this->countries_ptr--)
    free(this->countries[this->countries_ptr]);
  free(this->countries);
  free(this->variant);
  while (this->assumed_strings_ptr--)
    free(this->assumed_strings[this->assumed_strings_ptr]);
  free(this->assumed_strings);
  while (this->assumed_keys_ptr--)
    free(this->assumed_keys[this->assumed_keys_ptr]);
  free(this->assumed_keys);
  memset(this, 0, sizeof(mds_kbdc_parsed_t));
}


/**
 * Check whether a fatal errors has occurred
 * 
 * @param   this  The parsing result
 * @return        Whether a fatal errors has occurred
 */
int mds_kbdc_parsed_is_fatal(mds_kbdc_parsed_t* restrict this)
{
  return this->severest_error_level >= MDS_KBDC_PARSE_ERROR_ERROR;
}


/**
 * Print all encountered errors
 * 
 * @param  this    The parsing result
 * @param  output  The output file
 */
void mds_kbdc_parsed_print_errors(mds_kbdc_parsed_t* restrict this, FILE* output)
{
  mds_kbdc_parse_error_t** errors = this->errors;
  char* env = getenv("MDS_KBDC_ERRORS_ORDER");
  if (errors == NULL)
    return;
  if (env && (strcasecmp(env, "reversed") || strcasecmp(env, "reverse")))
    {
      while (*errors)
	errors++;
      while (errors-- != this->errors)
	mds_kbdc_parse_error_print(*errors, output);
    }
  else
    while (*errors)
      mds_kbdc_parse_error_print(*errors++, output);
  
}


/**
 * Add a new error to the list
 * 
 * @param   this              The parsing result
 * @param   severity          A `MDS_KBDC_PARSE_ERROR_*` to indicate severity
 * @param   error_is_in_file  Whether the error is in the layout code
 * @param   line              The line where the error occurred, zero-based
 * @param   start             The byte where the error started, on the line, inclusive, zero-based
 * @param   end               The byte where the error ended, on the line, exclusive, zero-based
 * @return                    The new error on success, `NULL` on error
 */
mds_kbdc_parse_error_t* mds_kbdc_parsed_new_error(mds_kbdc_parsed_t* restrict this, int severity,
						  int error_is_in_file, size_t line, size_t start, size_t end)
{
  mds_kbdc_parse_error_t* error = NULL;
  size_t old_errors_ptr = this->errors_ptr;
  int saved_errno;
  
  if (this->errors_ptr + 1 >= this->errors_size)
    {
      size_t new_errors_size = this->errors_size ? (this->errors_size << 1) : 2;
      mds_kbdc_parse_error_t** new_errors = this->errors;
      
      fail_if (xrealloc(new_errors, new_errors_size, mds_kbdc_parse_error_t*));
      this->errors = new_errors;
      this->errors_size = new_errors_size;
    }
  
  fail_if (xcalloc(error, 1, mds_kbdc_parse_error_t));
  this->errors[this->errors_ptr + 0] = error;
  this->errors[this->errors_ptr + 1] = NULL;
  this->errors_ptr++;
  
  error->severity = severity;
  if (this->severest_error_level < severity)
    this->severest_error_level = severity;
  
  fail_if (xstrdup(error->pathname, this->pathname));
  
  if ((error->error_is_in_file = error_is_in_file))
    {
      error->line = line;
      error->start = start;
      error->end = end;
      fail_if (xstrdup(error->code, this->source_code->real_lines[line]));
    }
  
  return error;
 fail:
  saved_errno = errno;
  free(error);
  this->errors_ptr = old_errors_ptr;
  this->errors[this->errors_ptr] = NULL;
  errno = saved_errno;
  return NULL;
}