Skip to content
Snippets Groups Projects
Select Git revision
  • 8ad154c081549f94da9e7c4fe6a713b53d46fad8
  • master default
  • wip-slh-dsa-sha2-128s
  • master-updates
  • release-3.10-fixes
  • getopt-prototype
  • fix-bcrypt-warning
  • refactor-hmac
  • wip-use-alignas
  • trim-sha3-context
  • fix-gitlab-ci
  • check-fat-emulate
  • delete-digest_func-size
  • slh-dsa-shake-128f-nettle
  • slh-dsa-shake-128s-nettle
  • slh-dsa-shake-128s
  • delete-openpgp
  • ppc64-sha512
  • delete-md5-compat
  • cleanup-hmac-tests
  • ppc64-sha256
  • nettle_3.10.2_release_20250626
  • nettle_3.10.1_release_20241230
  • nettle_3.10_release_20240616
  • nettle_3.10rc2
  • nettle_3.10rc1
  • nettle_3.9.1_release_20230601
  • nettle_3.9_release_20230514
  • nettle_3.8.1_release_20220727
  • nettle_3.8_release_20220602
  • nettle_3.7.3_release_20210606
  • nettle_3.7.2_release_20210321
  • nettle_3.7.1_release_20210217
  • nettle_3.7_release_20210104
  • nettle_3.7rc1
  • nettle_3.6_release_20200429
  • nettle_3.6rc3
  • nettle_3.6rc2
  • nettle_3.6rc1
  • nettle_3.5.1_release_20190627
  • nettle_3.5_release_20190626
41 results

testutils.c

Blame
  • parser.c 10.72 KiB
    /*
     * $Id: parser.c,v 0.4 1991/09/21 12:04:23 ceder Exp $
     * Copyright (C) 1991  Lysator Academic Computer Association.
     *
     * This file is part of the LysKOM server.
     * 
     * LysKOM 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 1, or (at your option) 
     * any later version.
     * 
     * LysKOM 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 LysKOM; see the file COPYING.  If not, write to
     * Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
     * or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
     * MA 02139, USA.
     *
     * Please mail bug reports to bug-lyskom@lysator.liu.se. 
     */
    /*
     *  client/parser.c  --  Routines to parse commands
     *
     *
     *  Copyright (C) 1990	Lysator Computer Club,
     *			Linkoping University,  Sweden
     *
     *  Everyone is granted permission to copy, modify and redistribute
     *  this code, provided the people they give it to can.
     *
     *
     *  Author:	Thomas Bellman
     *		Lysator Computer Club
     *		Linkoping University
     *		Sweden
     *
     *  email:	Bellman@Lysator.LiU.SE
     *
     *
     *  Any opinions expressed in this code are the author's PERSONAL opinions,
     *  and does NOT, repeat NOT, represent any official standpoint of Lysator,
     *  even if so stated.
     */
    
    
    static char *rcsid = "$Id: parser.c,v 0.4 1991/09/21 12:04:23 ceder Exp $";
    
    #include <stddef.h>
    
    #include <s-string.h>
    #include <s-collat-tabs.h>
    
    #include <misc-types.h>
    
    #include "parser.h"
    
    
    #define EXPORT			/* To emphasize export of objects */
    #define PRIVATE		static
    
    
    #if defined (SERVER)
    #	include <server/smalloc.h>
    #	define	MALLOC	smalloc
    #	define	REALLOC	srealloc
    #	define	FREE	sfree
    #elif defined (CLIENT)
    #	include	<zmalloc.h>
    #	define	MALLOC	zmalloc
    #	define	REALLOC	zrealloc
    #	define	FREE	zfree
    #else
    #	include	<malloc.h>
    #	define  MALLOC  malloc
    #	define  REALLOC realloc
    #	define  FREE	free
    #endif
    
    
    
    /*
     *  Remove paranthesized "expressions" from the string STR.
     *  E g if STR is "Foo (Bar (vfslck)) Gazonk", then it is reduced
     *  to "Foo _ Gazonk", where '_' is the character in SEPARATOR.
     *  Superflous close paranthesis are disregarded.
     */
    EXPORT  void
    remove_parenthesis (String	* str,
    		    char	  blanker)
    
    {
        String_size		  i;	/* Index in loop */
        int			  nesting_depth;
        
    
        /* Match parantheses.  Remove text inside parantheses. */
        nesting_depth = 0;
        for ( i = 0 ;  i < s_strlen(*str) ;  i++ )
        {
    	if (str->string[i] == '(')
    	    nesting_depth++;
    
    	if (str->string[i] == ')')
    	{
    	    nesting_depth--;
    	    str->string[i] = blanker;		/* Don't forget that... */
    	    if (nesting_depth < 0)
    		nesting_depth = 0;
    	}
    
    	if (nesting_depth > 0)
    	    str->string[i] = blanker;
        }
    
        return;
    }
    
    
    
    
    /*
     *  Convert a String to a list of tokens (words).  This list is
     *  easier to parse than a string (since the string would have to
     *  be tokenized first anyway).  The last entry is EMPTY_STRING.
     *  Returns NULL if any error occured (couldn't allocate memory).
     *  The result from this function should be freed when it is no longer
     *  used by a FREE(Parse_token *).  Note that String (Parse_token *)[X].word
     *  points into source, and should thus not be freed. 
     */
    EXPORT  Parse_token *
    tokenize (const String	  source,
    	  const String	  separators)
    
    {
        Parse_token		* tokens		= NULL;
        Parse_token		* temp_list;		/* Temporary */
        String		  work_string		= EMPTY_STRING;
        String		  a_token;
        String		  a_temp_token;		/* More temporaries... */
        int			  no_of_tokens;
        int			  list_size;
        String_size		  pos_in_string;
        const int		  chunk_size		= 10;
    
    
    
        /* Copy string to working area */
        if (s_strcpy(&work_string, source) == FAILURE)
        {
    	/* Couldn't allocate space for temporary string. */
    	return  NULL;
        }
    
        remove_parenthesis (&work_string, separators.string[0]);
    
        no_of_tokens = 0;
        list_size = 0;
        pos_in_string = 0;
    
        while ( ! s_empty(a_token
    		      = s_strtok (work_string, &pos_in_string,
    				  separators)))
        {
    	/* Make the token point into the original source string
    	 * instead of the working string			*/
    	a_temp_token = s_fsubstr (source,
    				  pos_in_string - s_strlen (a_token),
    				  pos_in_string - 1);
    #if 0
    // *	/* Get a real copy of the word */
    // *	a_temp_token = EMPTY_STRING;
    // *	if (s_strcpy(&a_temp_token, a_token) == FAILURE)
    // *	{
    // *	    /* Grumble... */
    // *	    free_tokens (tokens);
    // *	    s_clear(&work_string);
    // *	    return  NULL;
    // *	}
    #endif
    
    	/* Is the allocated list large enough? */
    	if (no_of_tokens++ >= list_size)
    	{
    	    /* No, allocate more */
    	    temp_list = REALLOC (tokens, (list_size += chunk_size)
    					  * sizeof(Parse_token));
    	    if (temp_list == NULL)
    	    {
    		/* Sigh. Out of memory. */
    		free_tokens (tokens);
    		s_clear (&work_string);
    		return  NULL;
    	    }
    	    else
    	    {
    		/* OK, we got what we asked for */
    		tokens = temp_list;
    	    }
    	}
    
    	/* Insert the new token in the list */
    	tokens [no_of_tokens-1].word = a_temp_token;
    	tokens [no_of_tokens-1].start_in_string =
    	    pos_in_string - s_strlen(a_temp_token);
        }
    
        s_clear (&work_string);
    
        /* Is there room in the list for the 'stop' element? */
        if (list_size <= no_of_tokens)
        {
    	/* No, get some more memory */
    	temp_list = REALLOC (tokens, (++list_size) * sizeof(Parse_token));
    	if (temp_list == NULL)
    	{
    	    /* Sigh. Out of memory. */
    	    free_tokens (tokens);
    	    return  NULL;
    	}
    	else
    	{
    	    /* OK, we got what we asked for */
    	    tokens = temp_list;
    	}
        }
    
        /* OK, insert the 'stop' element. */
        tokens [no_of_tokens].word = EMPTY_STRING;
        tokens [no_of_tokens].start_in_string = END_OF_STRING;
    
        return  tokens;
    }
    
    
    
    
    /*
     *  Count the number of tokens (words) in TOKEN_LIST.  Used to
     *  set the NUMBER_OF_WORDS field in a 'Matching_info' object.
     */
    extern  int
    count_words (const Parse_token   * token_list)
    
    {
        int		no_of_words;
    
        no_of_words = 0;
        while (! s_empty(token_list++ -> word))
    	no_of_words++;
    
        return  no_of_words;
    }
    
    
    
    
    /*
     *  Free the list of tokens (// and the strings they are pointing to //).
     *  Free:ing NULL is a no-op.
     */
    EXPORT  void
    free_tokens (Parse_token   * token_list)
    
    {
        if (token_list != NULL)
        {
    	FREE (token_list);
        }
    }
    
    
    
    
    /*
     *  Returns the number of the first word of SOURCE that does
     *  not match PATTERN.  A word "foo" in SOURCE matches "foobar"
     *  in PATTERN, but not vice versa.
     */
    EXPORT  int
    match (Parse_token	* source,
           Parse_token	* pattern,
           char		  collat_tab [ COLLAT_TAB_SIZE ] )
    
    {
        int		word_no;
    
        word_no = 0;
        while (   (! s_streq (pattern[word_no].word, EMPTY_STRING))
    	   && (! s_streq (source[word_no].word, EMPTY_STRING))
    	   && (s_usr_strhead (source[word_no].word,
    			      pattern[word_no].word,
    			      collat_tab)))
        {
    	word_no++;
        }
    
        return  word_no;
    }
    
    
    
    
    /*
     *  Searches for a matching string in the table 'match_table'.
     *  Some weird pattern matching is done.
     *  parse().no_of_matches is -1 if an error occured (out of
     *  memory).
     *
     *  What?  You want a description of how it matches?  Forget it!   BUG!
     *  Try for yourself, and you'll find out!
     */
    
    EXPORT  Parse_info
    parse (String		  source_string,
           Matching_info	* match_table,
           Bool		  allow_trailing_words,
           Bool		  number_of_words_must_match,
           String		  separators,
           char		  collat_tab [ COLLAT_TAB_SIZE ] )
    
    {
        Parse_info		  answer;
        int			* temp_indexes;
        int			  index;
        int			  size_of_index_list;
        Parse_token		* source_words;
        int			  no_of_source_words;
        int			  first_non_matching;
        int			  best_match;
        int			  highest_priority;
    
        const int		  chunk_size	= 20;
    
        
    
        source_words = tokenize(source_string, separators);
        if (source_words == NULL)
        {
    	answer.no_of_matches = -1;
    	return  answer;
        }
    
        no_of_source_words = count_words(source_words);
    
        /* Check if SOURCE_STRING was empty of words */
        if (no_of_source_words == 0)
        {
    	FREE (source_words);
    	answer.indexes = MALLOC (1 * sizeof(int));
    	if (answer.indexes == NULL)
    	{
    	    /* Gahh! Someone eats memory! */
    	    answer.no_of_matches = -1;
    	    return  answer;
    	}
    	answer.indexes[0] = -1;
    	answer.no_of_matches = 1;
    	return  answer;
        }
    
    
        answer.no_of_matches = 0;
        answer.indexes = NULL;
        size_of_index_list = 0;
        index = -1;
        best_match = 1;			/* At least one word */
        highest_priority = 1;
        while (! s_empty (match_table[++index].name))
        {
    	first_non_matching = match (source_words, match_table[index].tokens,
    				    collat_tab);
    
    	if (   (    ! allow_trailing_words
    		&&  first_non_matching < no_of_source_words)
    	    || (    number_of_words_must_match
    		&&  first_non_matching != count_words (match_table[index].tokens)))
    	{
    	    continue;			/* Try next entry in table */
    	}
    
    	if (first_non_matching < best_match)
    	    continue;			/* Try next entry in table */
    
    	if (    first_non_matching == best_match
    	    &&  highest_priority > match_table[index].priority)
    	    continue;
    
    	/*  If we reach this far, then we have a match that should be
    	 *  inserted in the table.  But if it is a better match than any
    	 *  before, then we clear the table first.			*/
    	if (    first_non_matching > best_match
    	    ||  match_table[index].priority > highest_priority)
    	{
    	    highest_priority = match_table[index].priority;
    	    best_match = first_non_matching;
    	    answer.no_of_matches = 0;
    	}
    
    	/* Insert the match in the table */
    
    	/* Increase the size if necessary */
    	if (answer.no_of_matches >= size_of_index_list)
    	{
    	    temp_indexes = REALLOC (answer.indexes,
    				    (size_of_index_list += chunk_size)
    				    * sizeof(answer.indexes));
    	    if (temp_indexes == NULL)
    	    {
    		/* Grumble!  Out of memory. */
    		FREE (source_words);
    		FREE (answer.indexes);
    		answer.no_of_matches = -1;
    		return  answer;
    	    }
    
    	    answer.indexes = temp_indexes;
    	}
    
    	highest_priority = match_table [index].priority;
    	answer.indexes[answer.no_of_matches] = index;
    	/*  Find out where the arguments start.
    	 *  This value should not be used if more than one match is found.
    	 */
    	/* Special hack needed if no parameters */
    	if (s_empty (source_words [first_non_matching].word))
    	    answer.arguments = EMPTY_STRING;
    	else
    	    answer.arguments =
    		s_fsubstr(source_string,
    			  source_words[first_non_matching].
    			  start_in_string,
    			  END_OF_STRING);
    	answer.no_of_matches++;
        }
    
        /* All matches found by now */
    
        /* Strip trailing blanks from the argument */
        if (answer.no_of_matches == 1)
    	answer.arguments = s_strip_trailing (answer.arguments, separators);
    
        FREE (source_words);
        return  answer;
    
    }   /* END: parse() */