Blame tools/fortopat.c

Packit Service 9ccfef
/*
Packit Service 9ccfef
 * fortopat.c --
Packit Service 9ccfef
 *
Packit Service 9ccfef
 *      Implementation of format string to xsd pattern conversion.
Packit Service 9ccfef
 *
Packit Service 9ccfef
 * Copyright (c) 2001 J. Schoenwaelder, Technical University of Braunschweig.
Packit Service 9ccfef
 *           (c) 2002 T. Klie, Technical University of Braunschweig.
Packit Service 9ccfef
 *           (c) 2002 F. Strauss, Technical University of Braunschweig.
Packit Service 9ccfef
 *           (c) 2007 T. Klie, Technical University of Braunschweig.
Packit Service 9ccfef
 *	     (c) 2007 J. Schoenwaelder, Jacobs University Bremen.
Packit Service 9ccfef
 *
Packit Service 9ccfef
 * See the file "COPYING" for information on usage and redistribution
Packit Service 9ccfef
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Packit Service 9ccfef
 *
Packit Service 9ccfef
 * @(#) $Id: dump-xsd.c 7372 2007-10-17 15:26:40Z tklie $
Packit Service 9ccfef
 */
Packit Service 9ccfef
Packit Service 9ccfef
#include <config.h>
Packit Service 9ccfef
Packit Service 9ccfef
#include <stdlib.h>
Packit Service 9ccfef
#include <stdio.h>
Packit Service 9ccfef
#include <stdarg.h>
Packit Service 9ccfef
#include <string.h>
Packit Service 9ccfef
#include <ctype.h>
Packit Service 9ccfef
#include <time.h>
Packit Service 9ccfef
#ifdef HAVE_WIN_H
Packit Service 9ccfef
#include "win.h"
Packit Service 9ccfef
#endif
Packit Service 9ccfef
Packit Service 9ccfef
#include "smi.h"
Packit Service 9ccfef
#include "smidump.h"
Packit Service 9ccfef
Packit Service 9ccfef
#include "fortopat.h"
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
#ifndef MIN
Packit Service 9ccfef
#define MIN(a,b) ((a)) < ((b)) ? ((a)) : ((b))
Packit Service 9ccfef
#endif
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
/* definition of commonly used display hints */
Packit Service 9ccfef
#define LIBSMI_DH_TP_IPV4Z_ADDR "1d.1d.1d.1d%4d:2d"
Packit Service 9ccfef
#define LIBSMI_DH_UDP_IPV4 "1d.1d.1d.1d/2d"
Packit Service 9ccfef
#define LIBSMI_DH_IPV4Z_ADDR "1d.1d.1d.1d%4d"
Packit Service 9ccfef
#define LIBSMI_DH_IPV4_ADDR "1d.1d.1d.1d"
Packit Service 9ccfef
#define LIBSMI_DH_LDP_ID "1d.1d.1d.1d:2d"
Packit Service 9ccfef
#define LIBSMI_DH_IPV6_ADDR "2x:2x:2x:2x:2x:2x:2x:2x"
Packit Service 9ccfef
#define LIBSMI_DH_IPV6Z_ADDR "2x:2x:2x:2x:2x:2x:2x:2x%4d"
Packit Service 9ccfef
#define LIBSMI_DH_TP_IPV6_ADDR "0a[2x:2x:2x:2x:2x:2x:2x:2x]0a:2d"
Packit Service 9ccfef
#define LIBSMI_DH_TP_IPV6Z_ADDR "0a[2x:2x:2x:2x:2x:2x:2x:2x%4d]0a:2d"
Packit Service 9ccfef
#define LIBSMI_DH_HEX "1x"
Packit Service 9ccfef
#define LIBSMI_DH_HEX_COLON "1x:"
Packit Service 9ccfef
#define LIBSMI_DH_DOUBLE_HEX_COLON "2x:"
Packit Service 9ccfef
#define LIBSMI_DH_ASCII "255a"
Packit Service 9ccfef
#define LIBSMI_DH_UTF8 "255t"
Packit Service 9ccfef
#define LIBSMI_DH_ASCII_CHAR "1a"
Packit Service 9ccfef
#define LIBSMI_DH_DATETIME "2d-1d-1d,1d.1d.1d,1a1d:1d"
Packit Service 9ccfef
#define LIBSMI_DH_DATETIME2 "2d-1d-1d,1d:1d:1d.1d,1a1d:1d"
Packit Service 9ccfef
#define LIBSMI_DH_IPX_ADDR "4x.1x:1x:1x:1x:1x:1x.2d"
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
/* list of parts of a display hint */
Packit Service 9ccfef
typedef struct DH {
Packit Service 9ccfef
    unsigned int number;
Packit Service 9ccfef
/*    int repeat;    //  repeat not yet supported */
Packit Service 9ccfef
    char type;
Packit Service 9ccfef
    char separator[3];
Packit Service 9ccfef
/*    char repTerm;  // repeat not yet supported */
Packit Service 9ccfef
    struct DH *next;
Packit Service 9ccfef
} DH;
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
static int
Packit Service 9ccfef
smiPow(int base, unsigned int exponent)
Packit Service 9ccfef
{
Packit Service 9ccfef
    unsigned int i;
Packit Service 9ccfef
    int ret = 1;
Packit Service 9ccfef
    
Packit Service 9ccfef
    if (exponent == 0) {
Packit Service 9ccfef
	return 1;
Packit Service 9ccfef
    }
Packit Service 9ccfef
    
Packit Service 9ccfef
    for (i = 0; i < exponent; i++) {
Packit Service 9ccfef
	ret *= base;
Packit Service 9ccfef
    }
Packit Service 9ccfef
    return ret;
Packit Service 9ccfef
}
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
static unsigned int
Packit Service 9ccfef
numDigits(unsigned int val)
Packit Service 9ccfef
{
Packit Service 9ccfef
    int ret = 1;
Packit Service 9ccfef
Packit Service 9ccfef
    for (; val / 10; val = val / 10) {
Packit Service 9ccfef
	ret++;
Packit Service 9ccfef
    }
Packit Service 9ccfef
    
Packit Service 9ccfef
    return ret;
Packit Service 9ccfef
}
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
static int
Packit Service 9ccfef
getBracketLevel(char *bracketString)
Packit Service 9ccfef
{
Packit Service 9ccfef
    int level = 0;
Packit Service 9ccfef
    char *c = bracketString;
Packit Service 9ccfef
Packit Service 9ccfef
    while(level >= 0 && *c != '\0') {
Packit Service 9ccfef
	switch(*c) {
Packit Service 9ccfef
	case '(':
Packit Service 9ccfef
	    level++;
Packit Service 9ccfef
	    break;
Packit Service 9ccfef
	case ')':
Packit Service 9ccfef
	    level--;
Packit Service 9ccfef
	    break;
Packit Service 9ccfef
	default:
Packit Service 9ccfef
	    break;
Packit Service 9ccfef
	}
Packit Service 9ccfef
	c++;
Packit Service 9ccfef
    }
Packit Service 9ccfef
Packit Service 9ccfef
    return level;
Packit Service 9ccfef
}
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
/* parse a display hint and create a list of DHs */
Packit Service 9ccfef
static struct DH*
Packit Service 9ccfef
parseDH(const char *hint)
Packit Service 9ccfef
{
Packit Service 9ccfef
    struct DH *iterDH = (struct DH *)malloc( sizeof( struct DH ) );
Packit Service 9ccfef
    struct DH *ret = iterDH;
Packit Service 9ccfef
    struct DH *oldIterDH = iterDH;
Packit Service 9ccfef
    unsigned int pos = 0;
Packit Service 9ccfef
    
Packit Service 9ccfef
    if (!ret) {
Packit Service 9ccfef
	return NULL;
Packit Service 9ccfef
    }
Packit Service 9ccfef
    
Packit Service 9ccfef
    memset(iterDH, 0, sizeof(struct DH));
Packit Service 9ccfef
    
Packit Service 9ccfef
    while( pos < strlen( hint ) ) {
Packit Service 9ccfef
Packit Service 9ccfef
	if( ! iterDH ) {
Packit Service 9ccfef
	    iterDH = (struct DH *)malloc( sizeof( struct DH ) );
Packit Service 9ccfef
	    if( ! iterDH ) return NULL;
Packit Service 9ccfef
	    memset(iterDH, 0, sizeof(struct DH));
Packit Service 9ccfef
	    oldIterDH->next = iterDH;
Packit Service 9ccfef
	    oldIterDH = iterDH;
Packit Service 9ccfef
	}
Packit Service 9ccfef
Packit Service 9ccfef
	switch( hint[ pos ] ) {
Packit Service 9ccfef
	    
Packit Service 9ccfef
	case '0':
Packit Service 9ccfef
	case '1':
Packit Service 9ccfef
	case '2':
Packit Service 9ccfef
	case '3':
Packit Service 9ccfef
	case '4':
Packit Service 9ccfef
	case '5':
Packit Service 9ccfef
	case '6':
Packit Service 9ccfef
	case '7':
Packit Service 9ccfef
	case '8':
Packit Service 9ccfef
	case '9': {
Packit Service 9ccfef
	    unsigned int endPos;
Packit Service 9ccfef
	    char *strNum;
Packit Service 9ccfef
	    
Packit Service 9ccfef
	    /* find end of number */
Packit Service 9ccfef
	    for( endPos = pos; isdigit( hint[ endPos ] ); endPos++ );
Packit Service 9ccfef
	    
Packit Service 9ccfef
	    /* parse number */
Packit Service 9ccfef
	    strNum = (char *)malloc( endPos - pos );
Packit Service 9ccfef
	    strncpy( strNum, &hint[ pos ], endPos - pos );
Packit Service 9ccfef
	    strNum[ endPos - pos ] = '\0';
Packit Service 9ccfef
	    iterDH->number = atoi( strNum );
Packit Service 9ccfef
	    free( strNum );
Packit Service 9ccfef
	    
Packit Service 9ccfef
	    /* forward the position pointer */
Packit Service 9ccfef
	    pos = endPos;
Packit Service 9ccfef
	    break;
Packit Service 9ccfef
	}
Packit Service 9ccfef
	
Packit Service 9ccfef
	case 'a':
Packit Service 9ccfef
	case 'b':
Packit Service 9ccfef
	case 'd':
Packit Service 9ccfef
	case 'o':
Packit Service 9ccfef
	case 't':
Packit Service 9ccfef
	case 'x':
Packit Service 9ccfef
	    iterDH->type = hint[ pos++ ];
Packit Service 9ccfef
	    if( isdigit( hint[ pos ] ) || hint[ pos ] == '*' ) {
Packit Service 9ccfef
		iterDH = iterDH->next;
Packit Service 9ccfef
	    }
Packit Service 9ccfef
	    break;
Packit Service 9ccfef
	    
Packit Service 9ccfef
	case '*':
Packit Service 9ccfef
	    /* repeat not supported */
Packit Service 9ccfef
	    return NULL;
Packit Service 9ccfef
	    
Packit Service 9ccfef
	default:
Packit Service 9ccfef
	    if( iterDH->separator ) {
Packit Service 9ccfef
		/* iterDH->repTerm = hint[ pos++ ]; // repeat not supported */
Packit Service 9ccfef
	      pos++;
Packit Service 9ccfef
	    }
Packit Service 9ccfef
	    else {
Packit Service 9ccfef
              iterDH->separator[0] = hint[ pos++ ];
Packit Service 9ccfef
	      if (iterDH->separator[0] == '.' ) {
Packit Service 9ccfef
		iterDH->separator[0] = '\\';
Packit Service 9ccfef
		iterDH->separator[1] = '.';
Packit Service 9ccfef
	      }
Packit Service 9ccfef
	    }
Packit Service 9ccfef
	    if( isdigit( hint[ pos ] ) || hint[ pos ] == '*' ) {
Packit Service 9ccfef
		iterDH = iterDH->next;
Packit Service 9ccfef
	    }
Packit Service 9ccfef
	    break;
Packit Service 9ccfef
	}	
Packit Service 9ccfef
    }
Packit Service 9ccfef
    return ret;
Packit Service 9ccfef
}
Packit Service 9ccfef
Packit Service 9ccfef
static char*
Packit Service 9ccfef
getSimpleCharFacet_XSD(char dhType, unsigned int number, 
Packit Service 9ccfef
		       unsigned int minL, unsigned int maxL)
Packit Service 9ccfef
{
Packit Service 9ccfef
    char *ret;
Packit Service 9ccfef
    char *baseRegExp;
Packit Service 9ccfef
    
Packit Service 9ccfef
    /* determine base regular expression, depending on display hint type */
Packit Service 9ccfef
    switch( dhType ) {
Packit Service 9ccfef
    case 'a':
Packit Service 9ccfef
	baseRegExp = "\\p{IsBasicLatin}";
Packit Service 9ccfef
	break;
Packit Service 9ccfef
    case 't':
Packit Service 9ccfef
	baseRegExp = ".";
Packit Service 9ccfef
	break;
Packit Service 9ccfef
    default:
Packit Service 9ccfef
	/* XXX - fix this to use the normal error reporting mechanism XXX */
Packit Service 9ccfef
	fprintf(stderr, 
Packit Service 9ccfef
		"displayHint.c: Error: unknown display hint type\n");
Packit Service 9ccfef
	return NULL;
Packit Service 9ccfef
    } 
Packit Service 9ccfef
    
Packit Service 9ccfef
    smiAsprintf( &ret, "%s{%d,%d}", baseRegExp, minL, MIN( number, maxL));
Packit Service 9ccfef
    return ret;
Packit Service 9ccfef
}
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
/* check if the hint is known and (if so) return the XSD translation */
Packit Service 9ccfef
static char*
Packit Service 9ccfef
getKnownDisplayHint_XSD(const char *hint,
Packit Service 9ccfef
			SmiUnsigned32 *lengths, unsigned int numSubranges)
Packit Service 9ccfef
{
Packit Service 9ccfef
    int i;
Packit Service 9ccfef
    char *ret = "";
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_TP_IPV4Z_ADDR ) )
Packit Service 9ccfef
	/* this is a simplyfied restriction. 
Packit Service 9ccfef
	 * We could restrict more, 
Packit Service 9ccfef
	 * but then, the pattern will be very hard to read / understand */
Packit Service 9ccfef
	return xstrdup("(\\d{1,3}.){3}\\d{1,3})%\\d{1,10}:\\d{1,5}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_UDP_IPV4 ) ) 
Packit Service 9ccfef
	return xstrdup("(\\d{1,3}.){3}\\d{1,3}/\\d{1,5}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_IPV4Z_ADDR ) )
Packit Service 9ccfef
	return xstrdup("(\\d{1,3}.){3}\\d{1,3}%\\d{1,10}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_IPV4_ADDR ) )
Packit Service 9ccfef
	return xstrdup("(\\d{1,3}.){3}\\d{1,3}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_LDP_ID ) )
Packit Service 9ccfef
	return xstrdup("(\\d{1,3}.){3}\\d{1,3}:\\d{1,5}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_IPV6_ADDR ) )
Packit Service 9ccfef
	return xstrdup("([\\dA-Fa-f]{2}:){7}[\\dA-Fa-f]{2}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_IPV6Z_ADDR ) )
Packit Service 9ccfef
	return xstrdup("([\\dA-Fa-f]{2}:){7}[\\dA-Fa-f]{2}%\\d{1,10}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_TP_IPV6_ADDR ) )
Packit Service 9ccfef
	return xstrdup("\\[([\\dA-Fa-f]{2}:){7}[\\dA-Fa-f]{2}\\]:\\d{1,5}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_TP_IPV6Z_ADDR ) )
Packit Service 9ccfef
	return xstrdup("\\[([\\dA-Fa-f]{2}:){7}[\\dA-Fa-f]{2}%\\d{1,10}\\]:\\d{1,5}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_HEX ) )
Packit Service 9ccfef
	return xstrdup("[0-9A-Fa-f]{2}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_HEX_COLON ) )
Packit Service 9ccfef
	return xstrdup("[0-9A-Fa-f]{2}:");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_DOUBLE_HEX_COLON ) )
Packit Service 9ccfef
	return xstrdup("[0-9A-Fa-f]{4}:");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_ASCII ) ) {
Packit Service 9ccfef
	switch( numSubranges ) { 		
Packit Service 9ccfef
	case 0: 
Packit Service 9ccfef
	    return getSimpleCharFacet_XSD( 'a', 255, 0, 255 );
Packit Service 9ccfef
	case 1: 			
Packit Service 9ccfef
	    return getSimpleCharFacet_XSD( 'a', 255, lengths[0], lengths[1] );
Packit Service 9ccfef
	default:
Packit Service 9ccfef
	    ret = "("; 
Packit Service 9ccfef
	    for( i=0; i < numSubranges * 2; i+=2 ) {
Packit Service 9ccfef
		if( i ) smiAsprintf(&ret, "%s)|(", ret);
Packit Service 9ccfef
		smiAsprintf(&ret, "%s%s", ret,
Packit Service 9ccfef
			    getSimpleCharFacet_XSD('a', 255, 
Packit Service 9ccfef
						   lengths[i], lengths[i+1]));
Packit Service 9ccfef
		
Packit Service 9ccfef
	    }
Packit Service 9ccfef
	    smiAsprintf(&ret, "%s)", ret);
Packit Service 9ccfef
	    return ret;
Packit Service 9ccfef
	}
Packit Service 9ccfef
    }
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp(hint, LIBSMI_DH_UTF8 )) {
Packit Service 9ccfef
	switch( numSubranges ) { 		
Packit Service 9ccfef
	case 0: 
Packit Service 9ccfef
	    return getSimpleCharFacet_XSD( 't' , 255, 0, 255 );
Packit Service 9ccfef
	case 1: 			
Packit Service 9ccfef
	    return getSimpleCharFacet_XSD( 't' , 255, lengths[0], lengths[1]);
Packit Service 9ccfef
	default:
Packit Service 9ccfef
	    ret = "("; 
Packit Service 9ccfef
	    for( i=0; i < numSubranges * 2; i+=2 ) {
Packit Service 9ccfef
		if( i ) smiAsprintf( &ret, "%s)|(", ret );
Packit Service 9ccfef
		smiAsprintf(&ret, "%s%s", 
Packit Service 9ccfef
			    ret, getSimpleCharFacet_XSD('t', 255,
Packit Service 9ccfef
							lengths[i], 
Packit Service 9ccfef
							lengths[i+1]));
Packit Service 9ccfef
	    }
Packit Service 9ccfef
	    smiAsprintf( &ret, "%s)", ret );
Packit Service 9ccfef
	    return ret;
Packit Service 9ccfef
	}
Packit Service 9ccfef
    }
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_ASCII_CHAR ))
Packit Service 9ccfef
	return xstrdup("\\p{IsBasicLatin}{0,1}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    /* we assume here date-time-value, i.e. the number of digits are fixed */
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_DATETIME ) )
Packit Service 9ccfef
	return xstrdup("\\d{4}-\\d{2}-\\d{2},(\\d{2}.){2}\\d{2},\\p{IsBasicLatin}\\d{2}:\\d{2}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    if( ! strcmp( hint, LIBSMI_DH_DATETIME2 ) ) {
Packit Service 9ccfef
	if( numSubranges >1 )
Packit Service 9ccfef
	    /* there are more subranges, 
Packit Service 9ccfef
	     * assume: lengths = 8 | lengths = 11 
Packit Service 9ccfef
	     * thus: last 3 octets (time zone info) is optional */ 
Packit Service 9ccfef
	    return xstrdup("\\d{4}-\\d{2}-\\d{2},(\\d{2}:){2}\\d{2}(,[\\+\\-]\\d{2}:\\d{2}){0,1}");
Packit Service 9ccfef
	return xstrdup("\\d{4}-\\d{2}-\\d{2},(\\d{2}:){2}\\d{2},[\\+\\-]\\d{2}:\\d{2}");
Packit Service 9ccfef
    }
Packit Service 9ccfef
    if( !strcmp( hint, LIBSMI_DH_IPX_ADDR ) )
Packit Service 9ccfef
	return xstrdup("[0-9A-Fa-f]{8}.([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}.\\d{1,4}");
Packit Service 9ccfef
    
Packit Service 9ccfef
    else return NULL;		
Packit Service 9ccfef
}
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
Packit Service 9ccfef
/* build a regexp pattern from a display hint 
Packit Service 9ccfef
 * 
Packit Service 9ccfef
 * Some documentation: First of all, it is checked whether the display hint 
Packit Service 9ccfef
 * matches againts one of the well known display hints. If so, a direct mapping 
Packit Service 9ccfef
 * is applied. Note that most cases ignore any additional length information 
Packit Service 9ccfef
 * (except DATETIME and ASCII / UTF8).
Packit Service 9ccfef
 * If no match can be found, the display hint is parsed and seperated 
Packit Service 9ccfef
 * into a list of blocks (DH struct). A display hint block consists of 
Packit Service 9ccfef
 * o the number of octets to be used (unsigned int "number"),
Packit Service 9ccfef
 * o a charakter representing the type (char "type"),
Packit Service 9ccfef
 * o the separator (char[3] "separator"),
Packit Service 9ccfef
 * o a pointer to the next display hint block in the list.
Packit Service 9ccfef
 * 
Packit Service 9ccfef
 * Then, it is checked whether it is a "simple" display hint, 
Packit Service 9ccfef
 * i.e. is hint that consists only of a single block and 
Packit Service 9ccfef
 * ASCII / UTF-8 restriction (type 'a' or 't'; as in 100a, 127t).
Packit Service 9ccfef
 * (Maybe this can be extended for other simple hints.)
Packit Service 9ccfef
 * 
Packit Service 9ccfef
 * If all of the above matches fail, the hints blocks are converted 
Packit Service 9ccfef
 * step by step using the these Mappings:
Packit Service 9ccfef
 * o ASCII: \p{IsBasicLatin}
Packit Service 9ccfef
 * o UTF-8: .
Packit Service 9ccfef
 * o Binary: (0|1){8} (8 digits (0 or 1))
Packit Service 9ccfef
 * o Decimal: [0-9]{3} (3 decimal digits)
Packit Service 9ccfef
 * o Octal: [0-7]{3} (3 octal digits)
Packit Service 9ccfef
 * o Hexadecimal: [0-9A-Fa-f]{2} (2 hexadecimal digits)
Packit Service 9ccfef
 * The conversion is not straight forward, 
Packit Service 9ccfef
 * because there may be also (even several) length restrictions 
Packit Service 9ccfef
 * and we have to count (or try to estimate) the used octets. Thus, 
Packit Service 9ccfef
 * it is sometimes necessary to generate multiple patterns 
Packit Service 9ccfef
 * with different length specification.
Packit Service 9ccfef
 * 
Packit Service 9ccfef
 * Unfortunately, the conversion still is quite difficult to understand 
Packit Service 9ccfef
 * although I added some comments. The good news is, that all IETF MIBs 
Packit Service 9ccfef
 * (and all other MIBs coming with libsmi) can be converted "the easy way" 
Packit Service 9ccfef
 * (i.e. without the difficult conversion loop).*/
Packit Service 9ccfef
Packit Service 9ccfef
char* getStrDHType(const char *hint,
Packit Service 9ccfef
		   SmiUnsigned32 *lengths, unsigned int numSubranges)
Packit Service 9ccfef
{
Packit Service 9ccfef
    unsigned int i = 0;
Packit Service 9ccfef
    char *ret = lengths[ i ] ? "(" : "((";
Packit Service 9ccfef
    char *r2 = getKnownDisplayHint_XSD( hint, lengths, numSubranges );
Packit Service 9ccfef
    DH *dh;
Packit Service 9ccfef
    int bl;
Packit Service 9ccfef
    
Packit Service 9ccfef
    r2 = NULL;
Packit Service 9ccfef
  
Packit Service 9ccfef
    if( r2 ) {
Packit Service 9ccfef
    /*	if( lengths[ i ] && lengths[i+1] < 65535 ) {    		
Packit Service 9ccfef
    		fputs( "LENGTH: ", stdout );
Packit Service 9ccfef
    		fprintf( stdout, "min: %d, max: %d ; ", lengths[i], lengths[i+1] );
Packit Service 9ccfef
    		fprintf( stdout, "hint was: %s\n", hint );
Packit Service 9ccfef
    	} 
Packit Service 9ccfef
    	if( numSubranges >  1 ) fputs( "MORE_SUBRANGES\n", stdout );*/
Packit Service 9ccfef
    	return r2;	
Packit Service 9ccfef
    }
Packit Service 9ccfef
    dh = parseDH( hint );
Packit Service 9ccfef
    bl = 0;
Packit Service 9ccfef
    
Packit Service 9ccfef
    if(! dh ) return NULL;
Packit Service 9ccfef
    
Packit Service 9ccfef
    /* check if we have a "simple" display hint (e.g. "100a") */
Packit Service 9ccfef
    if( !dh->next && ( dh->type == 'a' || dh->type == 't' ) ) {
Packit Service 9ccfef
    	switch( numSubranges ) { 		
Packit Service 9ccfef
	case 0: 
Packit Service 9ccfef
	    return getSimpleCharFacet_XSD( dh->type , dh->number, 0, dh->number );
Packit Service 9ccfef
	case 1: 			
Packit Service 9ccfef
	    return getSimpleCharFacet_XSD( dh->type , dh->number, lengths[0], lengths[1]);
Packit Service 9ccfef
	default:
Packit Service 9ccfef
	    ret = "("; 
Packit Service 9ccfef
	    for( i=0; i < numSubranges * 2; i+=2 ) {
Packit Service 9ccfef
		if( i ) smiAsprintf( &ret, "%s)|(", ret );
Packit Service 9ccfef
		smiAsprintf( &ret, "%s%s", 
Packit Service 9ccfef
			     ret, getSimpleCharFacet_XSD(dh->type, dh->number,
Packit Service 9ccfef
							 lengths[i], 
Packit Service 9ccfef
							 lengths[i+1]));
Packit Service 9ccfef
	    }
Packit Service 9ccfef
	    smiAsprintf(&ret, "%s)", ret);
Packit Service 9ccfef
	    return ret;
Packit Service 9ccfef
	}   		
Packit Service 9ccfef
    }
Packit Service 9ccfef
Packit Service 9ccfef
    /* no "easy match was possible, so start the "hard" loop */
Packit Service 9ccfef
    do {
Packit Service 9ccfef
	unsigned int octetsUsed = 0;
Packit Service 9ccfef
	DH *iterDH;
Packit Service 9ccfef
	
Packit Service 9ccfef
	for( iterDH = dh; iterDH; iterDH = iterDH->next ) {
Packit Service 9ccfef
	    char *baseRegexp = NULL;
Packit Service 9ccfef
	    
Packit Service 9ccfef
	    switch( iterDH->type ) {
Packit Service 9ccfef
		
Packit Service 9ccfef
	    case 'a':
Packit Service 9ccfef
		/* ascii character */
Packit Service 9ccfef
		baseRegexp = "(\\p{IsBasicLatin})";
Packit Service 9ccfef
		break;
Packit Service 9ccfef
		
Packit Service 9ccfef
	    case 't':
Packit Service 9ccfef
		/* utf-8 character */
Packit Service 9ccfef
		baseRegexp = ".";
Packit Service 9ccfef
		break;
Packit Service 9ccfef
		
Packit Service 9ccfef
	    case 'b':
Packit Service 9ccfef
		/* binary number */
Packit Service 9ccfef
		baseRegexp = "((0|1){8})";
Packit Service 9ccfef
		break;
Packit Service 9ccfef
		
Packit Service 9ccfef
	    case 'd':
Packit Service 9ccfef
		/* decimal number */
Packit Service 9ccfef
		baseRegexp = "([0-9]{3})";
Packit Service 9ccfef
		break;
Packit Service 9ccfef
		
Packit Service 9ccfef
	    case 'o':
Packit Service 9ccfef
		/* octal number */
Packit Service 9ccfef
		baseRegexp = "([0-7]{3})";
Packit Service 9ccfef
		break;
Packit Service 9ccfef
		
Packit Service 9ccfef
	    case 'x':
Packit Service 9ccfef
		/* hexadecimal number */
Packit Service 9ccfef
		baseRegexp = "([0-9A-Fa-f]{2})";
Packit Service 9ccfef
		break;
Packit Service 9ccfef
		
Packit Service 9ccfef
	    default:
Packit Service 9ccfef
		fputs( "smidump: Warning: unknown type of display-hint",
Packit Service 9ccfef
		       stderr );
Packit Service 9ccfef
	    }	   
Packit Service 9ccfef
	    
Packit Service 9ccfef
	    
Packit Service 9ccfef
	    if( iterDH->number < lengths[ i ] ) {
Packit Service 9ccfef
		/* there are more octets to come */
Packit Service 9ccfef
		if( iterDH->type == 'd' ) {
Packit Service 9ccfef
		    /* decimal number needs to be treated differently */
Packit Service 9ccfef
		    if( iterDH->next ){
Packit Service 9ccfef
			/* we still have another diplay hint block coming */
Packit Service 9ccfef
			smiAsprintf( &ret, "%s(0|[1-9](([0-9]){0,%d}))",
Packit Service 9ccfef
				     ret,
Packit Service 9ccfef
				     numDigits(smiPow(255,
Packit Service 9ccfef
						      iterDH->number ))-1 );
Packit Service 9ccfef
			
Packit Service 9ccfef
			/* adjust number of used digits */
Packit Service 9ccfef
			octetsUsed += iterDH->number;
Packit Service 9ccfef
			
Packit Service 9ccfef
			if( octetsUsed >= lengths[ i + 1 ] ) {
Packit Service 9ccfef
			    /* maximum number of octets used,
Packit Service 9ccfef
			       we must exit the loop */			    
Packit Service 9ccfef
			    break;
Packit Service 9ccfef
			}
Packit Service 9ccfef
			
Packit Service 9ccfef
			/* add separator char */
Packit Service 9ccfef
			if( iterDH->separator ) {
Packit Service 9ccfef
			    smiAsprintf( &ret, "%s%s",ret, iterDH->separator );
Packit Service 9ccfef
			}
Packit Service 9ccfef
		    }
Packit Service 9ccfef
		    else {
Packit Service 9ccfef
			/* no orther display hint coming up. 
Packit Service 9ccfef
			 * we are at the last iteration */		
Packit Service 9ccfef
			smiAsprintf( &ret, "%s((0|[1-9](([0-9]){0,%d})",
Packit Service 9ccfef
				     ret,
Packit Service 9ccfef
				     numDigits( smiPow( 255,
Packit Service 9ccfef
							iterDH->number ) ) - 1 );			
Packit Service 9ccfef
			/* add separator char */
Packit Service 9ccfef
			if( iterDH->separator ) {
Packit Service 9ccfef
			    smiAsprintf( &ret, "%s%s",
Packit Service 9ccfef
					 ret, iterDH->separator );
Packit Service 9ccfef
			}
Packit Service 9ccfef
			if( lengths[ i+1 ] - 1 - octetsUsed ) {
Packit Service 9ccfef
			    /* not all digits for maximum string length (length[i+1 ])
Packit Service 9ccfef
			     * have been used, so we have to add some digits */
Packit Service 9ccfef
			    smiAsprintf(&ret,
Packit Service 9ccfef
					"%s){%u,%u})(0|[1-9](([0-9]){0,%d}))",
Packit Service 9ccfef
					ret, lengths[ i ] - 1 - octetsUsed,
Packit Service 9ccfef
					lengths[ i+1 ] - 1 - octetsUsed,
Packit Service 9ccfef
					numDigits(
Packit Service 9ccfef
					    smiPow( 255, iterDH->number ))- 1 );							
Packit Service 9ccfef
			}
Packit Service 9ccfef
			else {
Packit Service 9ccfef
			    /* maximum number of digets have been used,
Packit Service 9ccfef
			     * so let's terminate the pattern for this round*/
Packit Service 9ccfef
			    smiAsprintf( &ret, "%s)", ret );
Packit Service 9ccfef
			}
Packit Service 9ccfef
			
Packit Service 9ccfef
			/* adjust the used digit counter */
Packit Service 9ccfef
			octetsUsed += iterDH->number;
Packit Service 9ccfef
			
Packit Service 9ccfef
			if( octetsUsed >= lengths[ i + 1 ] ) {
Packit Service 9ccfef
			    /* maximum number of octets used, we must exit the loop */
Packit Service 9ccfef
			    break;
Packit Service 9ccfef
			}
Packit Service 9ccfef
		    }
Packit Service 9ccfef
		}
Packit Service 9ccfef
		else {
Packit Service 9ccfef
		    /* type other than decimal */
Packit Service 9ccfef
		    if( iterDH->next ){
Packit Service 9ccfef
			/* there will be another display hint block */
Packit Service 9ccfef
			smiAsprintf( &ret, "%s(%s{%d})",
Packit Service 9ccfef
				     ret,
Packit Service 9ccfef
				     baseRegexp, iterDH->number );
Packit Service 9ccfef
			
Packit Service 9ccfef
			/* adjust number of used octets */
Packit Service 9ccfef
			octetsUsed += iterDH->number;
Packit Service 9ccfef
			if( octetsUsed >= lengths[ i + 1 ] ) {
Packit Service 9ccfef
			    /* maximum number of octets used,
Packit Service 9ccfef
			       we must exit the loop */			    
Packit Service 9ccfef
			    break;
Packit Service 9ccfef
			}
Packit Service 9ccfef
			
Packit Service 9ccfef
			/* add separator char */
Packit Service 9ccfef
			if( iterDH->separator ) {
Packit Service 9ccfef
			    smiAsprintf( &ret, "%s%s", ret, iterDH->separator );
Packit Service 9ccfef
			}
Packit Service 9ccfef
		    }
Packit Service 9ccfef
		    else {
Packit Service 9ccfef
			/* we are the last display hint block */			
Packit Service 9ccfef
			smiAsprintf( &ret, "%s(%s",
Packit Service 9ccfef
				     ret, baseRegexp );
Packit Service 9ccfef
			
Packit Service 9ccfef
			/* add separator char */
Packit Service 9ccfef
			if( iterDH->separator ) {
Packit Service 9ccfef
			    smiAsprintf( &ret, "%s%s", ret, iterDH->separator );
Packit Service 9ccfef
			}
Packit Service 9ccfef
			
Packit Service 9ccfef
			smiAsprintf( &ret, "(%s){%u,%u})%s",
Packit Service 9ccfef
				     ret, lengths[ i ] - 1, lengths[ i+1 ] - 1,
Packit Service 9ccfef
				     baseRegexp );
Packit Service 9ccfef
			
Packit Service 9ccfef
			/* adjust the number of used octets */
Packit Service 9ccfef
			octetsUsed += iterDH->number;
Packit Service 9ccfef
			if( octetsUsed >= lengths[ i + 1 ] ) {
Packit Service 9ccfef
			    /* maximum number of octets used,
Packit Service 9ccfef
			       we must exit the loop */			    
Packit Service 9ccfef
			    break;
Packit Service 9ccfef
			}
Packit Service 9ccfef
		    }
Packit Service 9ccfef
		}
Packit Service 9ccfef
	    }
Packit Service 9ccfef
	    else {
Packit Service 9ccfef
		/* might be the last one */
Packit Service 9ccfef
		
Packit Service 9ccfef
		if( iterDH->type == 'd' ) {
Packit Service 9ccfef
		    /* decimal number needs to be treated differently */
Packit Service 9ccfef
		    if( iterDH->number < lengths[ i+1 ] ) {
Packit Service 9ccfef
			/* we are not using the maximun number of octets */
Packit Service 9ccfef
			smiAsprintf( &ret, "%s(0|[1-9]([0-9]{0,%d}))",
Packit Service 9ccfef
				     ret,
Packit Service 9ccfef
				     numDigits( smiPow( 255, iterDH->number ) ) );
Packit Service 9ccfef
			
Packit Service 9ccfef
			/* adjust the number of used octets */
Packit Service 9ccfef
			octetsUsed += lengths[ i ];
Packit Service 9ccfef
			if( octetsUsed >= lengths[ i + 1 ] ) {
Packit Service 9ccfef
			    /* the maximum number of octets have been reached,
Packit Service 9ccfef
			       we must exit the loop */
Packit Service 9ccfef
			    break;
Packit Service 9ccfef
			}
Packit Service 9ccfef
			
Packit Service 9ccfef
			/* add separator char */
Packit Service 9ccfef
			if( iterDH->separator ) {
Packit Service 9ccfef
			    smiAsprintf( &ret, "%s%s", ret, iterDH->separator );
Packit Service 9ccfef
			}						
Packit Service 9ccfef
		    }
Packit Service 9ccfef
		    else {
Packit Service 9ccfef
			/* we have used the maximum number of octets */
Packit Service 9ccfef
			smiAsprintf( &ret, "%s(0|[1-9]([0-9]{0,%d})",
Packit Service 9ccfef
				     ret,
Packit Service 9ccfef
				     numDigits( smiPow( 255, lengths[ i+1 ] ) ) );
Packit Service 9ccfef
		    }
Packit Service 9ccfef
		}
Packit Service 9ccfef
		else {
Packit Service 9ccfef
		    /* type is not decimal */
Packit Service 9ccfef
		    smiAsprintf( &ret, "%s(%s",  ret, baseRegexp );
Packit Service 9ccfef
		    if( iterDH->next ) {
Packit Service 9ccfef
			/* there will be another display hint block */
Packit Service 9ccfef
			if( iterDH->separator ) {
Packit Service 9ccfef
			    smiAsprintf( &ret, "%s%s", ret, iterDH->separator );
Packit Service 9ccfef
			}
Packit Service 9ccfef
			if( ! lengths[ i ] && lengths[ i+1 ] == 65535 ) {
Packit Service 9ccfef
			    /* minLength = 0, maxLength = 65535, 
Packit Service 9ccfef
			     * i.e. no restriction at all */
Packit Service 9ccfef
			    smiAsprintf( &ret, "%s)*",ret );
Packit Service 9ccfef
			}
Packit Service 9ccfef
			else{
Packit Service 9ccfef
			    /* we have a different length restriction */
Packit Service 9ccfef
			    smiAsprintf( &ret, "%s){%u,%u}",ret, lengths[ i ],
Packit Service 9ccfef
					 MIN( iterDH->number,
Packit Service 9ccfef
					      lengths[ i + 1] ) - 1 );
Packit Service 9ccfef
			}
Packit Service 9ccfef
			
Packit Service 9ccfef
			/* adjust the number of used octets */
Packit Service 9ccfef
			octetsUsed += lengths[ i ];
Packit Service 9ccfef
			if( octetsUsed >= lengths[ i + 1 ] ) {
Packit Service 9ccfef
			    /* the maximum number of octets have been reached,
Packit Service 9ccfef
			       we must exit the loop */
Packit Service 9ccfef
			    break;
Packit Service 9ccfef
			}						
Packit Service 9ccfef
		    }
Packit Service 9ccfef
		    else {
Packit Service 9ccfef
			/* we are the ast display hint block */
Packit Service 9ccfef
			octetsUsed += lengths[ i ];
Packit Service 9ccfef
			if( iterDH->separator &&
Packit Service 9ccfef
			    octetsUsed < lengths[ i + 1 ] ) {
Packit Service 9ccfef
			    /* we have a separator char and 
Packit Service 9ccfef
			     * still not reached the maximum number of octets */
Packit Service 9ccfef
			    if( ! lengths[ i ] && lengths[ i+1 ] == 65535 ) {
Packit Service 9ccfef
				/* we have no length restriction */
Packit Service 9ccfef
				smiAsprintf( &ret, "%s%s)*%s",
Packit Service 9ccfef
					     ret, iterDH->separator, baseRegexp );
Packit Service 9ccfef
			    }
Packit Service 9ccfef
			    else {
Packit Service 9ccfef
				/* we have a length restriction */
Packit Service 9ccfef
				smiAsprintf( &ret, "%s%s){%u,%u}%s",
Packit Service 9ccfef
					     ret, iterDH->separator,
Packit Service 9ccfef
					     lengths[ i ], lengths[ i + 1] - 1,
Packit Service 9ccfef
					     baseRegexp );
Packit Service 9ccfef
			    }
Packit Service 9ccfef
			}
Packit Service 9ccfef
			else {
Packit Service 9ccfef
			    /* we don't have a separator char or
Packit Service 9ccfef
			     * have used the maximum number of octets */
Packit Service 9ccfef
			    if( ! lengths[ i ] && lengths[ i+1 ] == 65535 ) {
Packit Service 9ccfef
				/* no lengths restriction */
Packit Service 9ccfef
				smiAsprintf( &ret, "%s)*%s",
Packit Service 9ccfef
					     ret, iterDH->separator ); 
Packit Service 9ccfef
				/* TBD: what, if there is no separator ??? */
Packit Service 9ccfef
			    }
Packit Service 9ccfef
			    else {
Packit Service 9ccfef
				/* we have a length restriction */
Packit Service 9ccfef
				smiAsprintf( &ret, "%s){%u,%u}%s",
Packit Service 9ccfef
					     ret, lengths[ i ],
Packit Service 9ccfef
					     lengths[ i + 1],
Packit Service 9ccfef
					     iterDH->separator );
Packit Service 9ccfef
				/* TBD: what, if there is no separator ??? */
Packit Service 9ccfef
			    }			    
Packit Service 9ccfef
			}
Packit Service 9ccfef
		    }
Packit Service 9ccfef
		}
Packit Service 9ccfef
		
Packit Service 9ccfef
		if( octetsUsed >= lengths[ i + 1 ] ) {
Packit Service 9ccfef
		    /* the maximum number of octets have been reached,
Packit Service 9ccfef
		       we must exit the loop */
Packit Service 9ccfef
		    break;
Packit Service 9ccfef
		}
Packit Service 9ccfef
	    }
Packit Service 9ccfef
	}
Packit Service 9ccfef
	/* adjust the "pointer" for the lenghts array */
Packit Service 9ccfef
	i += 2;
Packit Service 9ccfef
	
Packit Service 9ccfef
	if( i < numSubranges  * 2 ) {
Packit Service 9ccfef
	    /* we are not the last subrange, so we have to extend the pattern */
Packit Service 9ccfef
	    smiAsprintf( &ret, "%s)|(", ret );
Packit Service 9ccfef
	}
Packit Service 9ccfef
	else {
Packit Service 9ccfef
	    /* we are the last subrange */
Packit Service 9ccfef
	    smiAsprintf( &ret, "%s)", ret );
Packit Service 9ccfef
	    if( ! lengths[ 0 ] ) {
Packit Service 9ccfef
		smiAsprintf( &ret, "%s){0,1}", ret );
Packit Service 9ccfef
	    }
Packit Service 9ccfef
	}
Packit Service 9ccfef
    } while( i < numSubranges * 2 );
Packit Service 9ccfef
    
Packit Service 9ccfef
    /* check if all brackets have been closed */
Packit Service 9ccfef
    if( getBracketLevel( ret ) ) {
Packit Service 9ccfef
	bl = getBracketLevel( ret );
Packit Service 9ccfef
      	fprintf( stderr, "%d\n", bl );
Packit Service 9ccfef
      	if( bl > 0 ) {
Packit Service 9ccfef
	    /* TODO: add a warning that brackets have been added */
Packit Service 9ccfef
	    for(; bl; bl--) {
Packit Service 9ccfef
		smiAsprintf( &ret, "%s)", ret );
Packit Service 9ccfef
	    }
Packit Service 9ccfef
      	}
Packit Service 9ccfef
      	else {
Packit Service 9ccfef
	    /* TODO: some error handling */
Packit Service 9ccfef
      	}
Packit Service 9ccfef
    }
Packit Service 9ccfef
    return ret;
Packit Service 9ccfef
}
Packit Service 9ccfef
Packit Service 9ccfef
/*
Packit Service 9ccfef
 * Perhaps we should introduce another parameter (flags) which
Packit Service 9ccfef
 * controls whether shortcuts are taken and such things...
Packit Service 9ccfef
 */
Packit Service 9ccfef
Packit Service 9ccfef
extern char*
Packit Service 9ccfef
smiFormatToPattern(const char *format, SmiRange *smiRange)
Packit Service 9ccfef
{
Packit Service 9ccfef
    SmiRange *range = smiRange;
Packit Service 9ccfef
    SmiUnsigned32 *lengths = NULL;
Packit Service 9ccfef
    int num = 0, lp;
Packit Service 9ccfef
    char *pattern;
Packit Service 9ccfef
Packit Service 9ccfef
    for (range = smiRange; range; range = smiGetNextRange(range)) {
Packit Service 9ccfef
	num++;
Packit Service 9ccfef
    }
Packit Service 9ccfef
Packit Service 9ccfef
    /* copy ranges to array (no clue why this is being done) */
Packit Service 9ccfef
    
Packit Service 9ccfef
    if (num) {
Packit Service 9ccfef
	lengths = xmalloc(2 * num * sizeof(SmiUnsigned32));
Packit Service 9ccfef
	for (range = smiRange, lp = 0; range; range = smiGetNextRange(range)) {
Packit Service 9ccfef
	    lengths[lp++] = range->minValue.value.unsigned32;
Packit Service 9ccfef
	    lengths[lp++] = range->maxValue.value.unsigned32;
Packit Service 9ccfef
	}
Packit Service 9ccfef
    } else {
Packit Service 9ccfef
	lengths = xmalloc( 2 * sizeof(SmiUnsigned32));
Packit Service 9ccfef
	lengths[0] = 0;
Packit Service 9ccfef
	lengths[1] = 65535;
Packit Service 9ccfef
    }
Packit Service 9ccfef
Packit Service 9ccfef
    pattern = getStrDHType(format, lengths, num);
Packit Service 9ccfef
    xfree(lengths);
Packit Service 9ccfef
Packit Service 9ccfef
    return pattern;
Packit Service 9ccfef
}