⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mel.c

📁 C语言多种求最优的程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
---------------------------------------------------------------------------
filename: mel.c
author: g. m. crews
creation date: 28-Jul-1988
date of last revision: 19-Jul-1989

MEL is a comprehensive metalanguage input/output processor for engineering 
analysis programs. its purposes are 1) to save the programmer development time
when providing a user-friendly i/o interface, and 2) to establish a common
protocol for interprogram messaging. these routines can be used by any
analysis program for which a "dictionary" has been defined. see file
"mel.doc" for more information.

note: these functions will normally return 0 if no error was encountered, 
else a number (code) reflecting the type of error.

functions contained in this file:

    module #   name			 global scope?
    --------   -----------------------	 -------------
    1.0        meli_file		 yes
    1.1        end_of_data_in_file	 no
    1.2        meli			 yes
    1.2.1      compact_str		 no
    1.2.2      get_descrip_type 	 no
    1.2.2.1    name_match		 no
    1.2.3      get_param_name		 no
    1.2.4      get_param_values 	 no
    1.2.5      get_param_units		 no
    2.0        meli_descrip_type	 yes
    3.0        meli_num_params		 yes
    4.0        meli_param		 yes
    5.0        meli_data		 yes
    6.0        melo_init		 yes
    7.0        melo_data		 yes
    8.0        melo_file		 yes
    8.1        melo			 yes
    8.1.1      write_units_if_any	 no
---------------------------------------------------------------------------
*/

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

/*
---------------------------------------------------------------------------
the following include file declares the dictionary that is to be used for
MEL i/o.  note that this file will be unique for every program that uses
this method of i/o.  (again, see file "mel.doc" for more information on how
to further customize or modify this file.)

it also contains "public" (global) function prototyping and miscellaneous 
data structures.
---------------------------------------------------------------------------
*/

#define MEL_INPUT
#define MEL_OUTPUT
#define MEL_PRIVATE
#define MEL_INIT
#include "mel.h"

/* "private" function prototyping:
   (visible only to other routines in this file) */

static int end_of_data_in_file(int);
static void compact_str(void);
static int get_descrip_type(void);
static int name_match(char *, char *, int);
static int get_param_name(void);
static int get_param_values(void);
static int get_param_units(void);
static void write_units_if_any(int);

/* "private" (local external) storage: */

static char descrip_str[MELI_MAX_DESCRIP_STR_LEN+1];
    /* temp storage for descriptor string.
       (read from file or given by MEL user). */
static char *descrip_str_ptr;
    /* current point of interest in above string. it is used by several 
       routines that "translate" the string into MEL data structure. it points 
       to the next character needing to be "translated". */
static int curr_descrip_index;
    /* what is descriptor's index into meli_descrip[] array? this allows
       other local routines to know which parameters to check for. */
static int datum_param_index;
    /* where does this parameter's data go in meli_datum? */

/* the following variables are also local and deal with parameter handling: */

static int equals_sign_found_flag;
    /* will there be a need to try and read a parameter value? */
static int curr_param_index;
    /* what is parameter's index into meli_descrip.param[] array? */
static int param_name_found_flag;
    /* as a safety measure, note when a parameter name has been found
       for a descriptor (and do not let values without names follow). */
static int left_parenthesis_found_flag;
    /* will there be a need to try and read units? */

/*
---------------------------------------------------------------------------
module 1.0

get a descriptor string from a file and put data into structure for easy
access. that is:
    read a descriptor from a file into "private" storage (descrip_str).
    check for file read errors.
    stop reading after semicolon encountered.
    put a copy into meli_descriptor_string.
    translate this string into MEL data structure (meli_datum).

algorithm synopsis: read characters from input stream until semi-
colon (end-of-descriptor) is encountered, while putting them into
private storage string.
---------------------------------------------------------------------------
*/
int meli_file(
FILE *input_file_handle)
{
    static int curr_line_num = 1;
	/* assume that reading starts with the first line in a text file
	   and continues incrementally (one descriptor at a time). thus,
	   increment this variable everytime a newline character is
	   encountered. (that a descriptor may span several lines.) */

    int i;
	/* loop counter. */

    int ch;
	/* current char from input stream. */

    meli_datum.start_line = curr_line_num;
	/* save the starting line number for this descriptor. */

    /* read from the input stream one character at a time: */

    for (i = 0; i < MELI_MAX_DESCRIP_STR_LEN; i++) {
	ch = fgetc(input_file_handle);

	/* check for a file read error: */
	if (ferror(input_file_handle)) {
	    mel_err.type = mel_read_err;
	    mel_err.start_line = meli_datum.start_line;
	    mel_err.end_line = curr_line_num;
	    strcpy(mel_err.msg, "MEL input file");
	    return mel_read_err;
	};

	/* also error if unexpected end of file before semicolon: */
	if ((ch == EOF) || (feof(input_file_handle))) {

	    /* an exception is for the case of EOF right after a semicolon
	       (not counting any whitespace that might also have been read).
	       this is called the "end-of-data" error (which really isn't an
	       error at all, but a means of letting the caller know that no
	       more descriptors are in the file). */
	    if (end_of_data_in_file(i)) {
		mel_err.type = mel_end_of_data_err;
		mel_err.start_line = meli_datum.start_line;
		mel_err.end_line = curr_line_num;
		strcpy(mel_err.msg, "MEL input file");
		return mel_end_of_data_err;
	    } else {
		mel_err.type = mel_end_of_file_err;
		mel_err.start_line = meli_datum.start_line;
		mel_err.end_line = curr_line_num;
		strcpy(mel_err.msg, "Missing semicolon, MEL input file");
		return mel_end_of_file_err;
	    }
	};

	if (ch == ';') break;
	    /* break the loop if a semicolon is encountered. */

	if (ch == '\n') curr_line_num++;
	    /* increment line number count for a new line */

	/* now add this character to the descriptor string and go get the
	   next character: */
	descrip_str[i] = (char)ch;
    }

    /* the descriptor has now been successfully read into the descriptor
       string. time to tidy-up. */

    descrip_str[i++] = (char)ch;  /* tack on the semicolon */
    descrip_str[i] = '\0';
    meli_datum.end_line = curr_line_num;
    strcpy(meli_descriptor_string, descrip_str);
	/* make copy in case user wants to see it. */

    /* lastly, translate it (put data into meli_datum): */
    return meli();
}

/*
---------------------------------------------------------------------------
module 1.1

has all the data been read from the MEL input file?

this routine is called when an end of file has been encountered. we must make
sure that the user has not forgotten to append a semicolon on the last
descriptor.  thus, it is an error condition if anything except whitespace
has been read since the last semicolon (end-of-descriptor character).

return 1 if only whitespace has been read since last semicolon.
return 0 if other (data) characters have been read since last semicolon.
---------------------------------------------------------------------------
*/
static int end_of_data_in_file(
int str_len)
{
    descrip_str[str_len] = '\0';
	/* make string out of characters read since last semicolon. */

    compact_str();    /* remove whitespace from this string */

    if (strlen(descrip_str)) return 0;
    else return 1;
	/* if anything left over after compaction, then user has made
	   an error. */
}

/*
---------------------------------------------------------------------------
module 1.2

interpret a MEL descriptor:

this function scans a descriptor string and interprets it.

the results are put into the mel_data structure, or if an error occurs,
into the mel_err structure.

algorithm synopsis: first translate what kind of descriptor this is,
then loop while translating each parameter.

---------------------------------------------------------------------------
*/
int meli()
{
    int result;

    param_name_found_flag = 0;
	/* allow parameter values to be input, in order, without their
	   names (until a parameter name is encountered).  see
	   function get_param_name() for more info. */

    meli_datum.num_param = 0;
	/* how many parameter have been processed so far? */

    /* first place string into local storage, strip trailing semicolon,
       and "compact" it: */

    strncpy(descrip_str, meli_descriptor_string,
	(size_t) MELI_MAX_DESCRIP_STR_LEN);
    descrip_str[MELI_MAX_DESCRIP_STR_LEN+1] = '\0';
	/* ensure no overflow. */

    compact_str();

    /* next keep evaluating until an error is encountered or the end of
       the string is reached (functions return 0 if no err): */
	
    if (result = get_descrip_type()) return result;
	/* every descriptor must have a type. */

    /* there may be a variable number of parameters and values: */

    while (*descrip_str_ptr != '\0') {
	/* keep going until end of descrip_str reached */

	datum_param_index = meli_datum.num_param;
	    /* where will new parameter data go? */

	/* a parameter usually consists of its name, value, and units: */
	if (result = get_param_name()) return result;
	if (result = get_param_values()) return result;
	if (result = get_param_units()) return result;

	meli_datum.num_param++;
	    /* another parameter has been processed! */
    };

    return 0;
	/* the end of the descriptor string has been reached. */
}

/*
---------------------------------------------------------------------------
module 1.2.1

compact the descrip_str string:
    flush whitespace except blanks within single quotes or curly brackets
	(strings and arrays).
    flush comments (text within double quotes).

algorithm synopsis:  since the string can only shrink while being compacted,
use pointers to keep track of current positions and overwrite in place.
---------------------------------------------------------------------------
*/
static void compact_str()
{
    char *p;    /* pointer to current end of compacted string */
    char *q;    /* pointer to current end of uncompacted string */

    int single_quote_flag = 0;
    int curly_brackets_flag = 0;
	/* all blanks within a descriptor are flushed except those within
	   single quotes or curly brackets. */

    int double_quote_flag = 0;
	/* all text within double quotes are comments and are flushed. */

    p = q = descrip_str;    /* start at the beginning */

    do { /* look at current character, does it need to be flushed? */

	/* if the character is a double quote, flush all chars between it
	   and the next double quote: */
	if (*q == '"') {
	    double_quote_flag = !double_quote_flag;
	    q++;     /* has effect of flushing this character (typical) */
	    continue;   /* go to next character (typical) */
	}

	/* if the character is a newline, flush it */
	else if (*q == '\n') {
	    q++;
	    continue;
	}

	/* flush all chars if we are currently between double quotes: */
	else if (double_quote_flag) {
	    q++;
	    continue;
	}

	/* test for single quote or curly brackets and adjust flag value: */
	else if (*q == '\'') single_quote_flag = !single_quote_flag;
	else if (*q == '{') curly_brackets_flag = 1;
	else if (*q == '}') curly_brackets_flag = 0;

	/* if the character is some other whitespace char, except a blank,
	   also flush it: */
	else if ((*q == '\t') || (*q == '\v') || (*q == '\r') ||
	(*q == '\f')) {
	    q++;
	    continue;
	}

	/* if the character is a blank, flush it unless it is between
	   single quotes or curly brackets: */
	else if ((*q == ' ') && !single_quote_flag && !curly_brackets_flag) {
	    q++;
	    continue;
	}

	/* this character not to be flushed, so copy it in place */
	*p = *q;
	p++; q++;   /* get ready for next character */

    } while (*(q-1) != '\0');
	/* don't continue if last char was null terminator */
}

/*
---------------------------------------------------------------------------
module 1.2.2

determine current descriptor's index into meli_descrip array.
that is, which type of descriptor has just been read?
---------------------------------------------------------------------------
*/
static int get_descrip_type()
{

    int i;
	/* loop counter. */

    char temp_str[MELI_MAX_DESCRIP_STR_LEN+1];
	/* build up descriptor name here. */

    descrip_str_ptr = descrip_str;
	/* must reset current string position to start of string since
	   now time to start another descriptor. */

    /* create string to next comma or end of descrip string: */
    for (i = 0; i < MELI_MAX_DESCRIP_STR_LEN; i++) {
	if ((*descrip_str_ptr == ',') ||
	    (*descrip_str_ptr == ';') ||
	    (*descrip_str_ptr == '\0')) {
	    descrip_str_ptr++;	  /* get ready for next part */
	    temp_str[i] = '\0';
	    break;
	};

	temp_str[i] = *descrip_str_ptr++;
	/* add this char to temp string. */
    }

    /* find descrip name that matches this built up name: */

    for (i = 0; i < MELI_NUM_DESCRIP_NAMES; i++)
	if (name_match(meli_descrip[i].name, temp_str,
	    meli_descrip[i].min_name_len)) {
	    curr_descrip_index = meli_datum.descrip_type = i;
	    return 0;     /* descriptor type has been found */
	};

    /* error if went through entire list without finding match: */

    mel_err.type = mel_unknown_descrip_name_err;
    mel_err.start_line = meli_datum.start_line;
    mel_err.end_line = meli_datum.end_line;
    strncpy(mel_err.msg, temp_str, MEL_MAX_ERR_MSG_LEN);
    mel_err.msg[MEL_MAX_ERR_MSG_LEN+1] = '\0';
    return mel_unknown_descrip_name_err;
}

/*
---------------------------------------------------------------------------
module 1.2.2.1

determine if the starting characters in a test string start off with all
the characters in a reference string. returns: 0 = no, 1 = yes.
---------------------------------------------------------------------------
*/
static int name_match(
char test_str[],
char ref_str[],
int ref_str_len)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -