| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628 |
- #ident "@(#)parser.c 1.5 01/04/11"
- /** BEGIN COPYRIGHT BLOCK
- * 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; version 2 of the License.
- *
- * 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, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2006 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /*
- FILE : parser.c
- AUTHOR : Jean-Luc SCHWING
- VERSION : 1.0
- DATE : 19 March 2001
- DESCRIPTION :
- This file contains the parser functions of ldclt
- LOCAL : None.
- HISTORY :
- ---------+--------------+------------------------------------------------------
- dd/mm/yy | Author | Comments
- ---------+--------------+------------------------------------------------------
- 19/03/01 | JL Schwing | Creation
- ---------+--------------+------------------------------------------------------
- 21/03/01 | JL Schwing | 1.2 : Implements variables in "-e object=filename"
- ---------+--------------+------------------------------------------------------
- 23/03/01 | JL Schwing | 1.3 : Implements data file list support in variants.
- | Bug fix : close the file !
- | Implements "-e rdn=value".
- ---------+--------------+------------------------------------------------------
- 28/03/01 | JL Schwing | 1.4 : Support -e commoncounter with -e rdn/object
- ---------+--------------+------------------------------------------------------
- 11/04/01 | JL Schwing | 1.5 : Implement [INCRFROMFILE<NOLOOP>(myfile)]
- | Improved error message.
- ---------+--------------+------------------------------------------------------
- */
- #include <stdio.h> /* printf(), etc... */
- #include <string.h> /* strcpy(), etc... */
- #include <errno.h> /* errno, etc... */
- #include <stdlib.h> /* malloc(), etc... */
- #include <lber.h> /* ldap C-API BER declarations */
- #include <ldap.h> /* ldap C-API declarations */
- #ifdef LDAP_H_FROM_QA_WKA
- #include <proto-ldap.h> /* ldap C-API prototypes */
- #endif
- #ifndef _WIN32
- #include <unistd.h> /* close(), etc... */
- #include <pthread.h> /* pthreads(), etc... */
- #endif
- #include "port.h" /* Portability definitions */
- #include "ldclt.h" /* This tool's include file */
- #include "utils.h" /* Utilities functions */
- /* ****************************************************************************
- FUNCTION : decodeHow
- PURPOSE : Decode the how field
- INPUT : how = field to decode
- OUTPUT : None.
- RETURN : -1 if error, how value else.
- DESCRIPTION :
- *****************************************************************************/
- int
- decodeHow (
- char *how)
- {
- if (mctx.mode & VERY_VERBOSE)
- printf ("decodeHow: how=\"%s\"\n", how);
- if (!strcmp (how, "INCRFROMFILE")) return (HOW_INCR_FROM_FILE);
- if (!strcmp (how, "INCRFROMFILENOLOOP")) return (HOW_INCR_FROM_FILE_NL);
- if (!strcmp (how, "INCRN")) return (HOW_INCR_NB);
- if (!strcmp (how, "INCRNNOLOOP")) return (HOW_INCR_NB_NOLOOP);
- if (!strcmp (how, "RNDFROMFILE")) return (HOW_RND_FROM_FILE);
- if (!strcmp (how, "RNDN")) return (HOW_RND_NUMBER);
- if (!strcmp (how, "RNDS")) return (HOW_RND_STRING);
- return (-1);
- }
- /* ****************************************************************************
- FUNCTION : parseVariant
- PURPOSE : Parse a variant definition.
- INPUT : variant = string to parse
- fname = file name
- line = source line
- obj = object we are parsing and building
- OUTPUT : field = field parsed
- RETURN : -1 if error, 0 else.
- DESCRIPTION :
- *****************************************************************************/
- int
- parseVariant (
- char *variant,
- char *fname,
- char *line,
- vers_object *obj,
- vers_field *field)
- {
- int start, end; /* For the loops */
- char how[MAX_FILTER]; /* To parse the variant : */
- char first[MAX_FILTER]; /* how(first) */
- char second[MAX_FILTER]; /* how(first,second) */
- char third[MAX_FILTER]; /* how(first,second,third) */
- int ret; /* ldclt_mutex_init() return value */
- if (mctx.mode & VERY_VERBOSE)
- printf ("parseVariant: variant=\"%s\"\n", variant);
- /*
- * Maybe a variable ?
- */
- if (variant[1] == '\0')
- {
- if ((variant[0] < VAR_MIN) || (variant[0] > VAR_MAX))
- {
- fprintf (stderr, "Error: bad variable in %s : \"%s\"\n", fname, line);
- fprintf (stderr, "Error: must be in [%c-%c]\n", VAR_MIN, VAR_MAX);
- return (-1);
- }
- field->how = HOW_VARIABLE;
- field->var = variant[0] - VAR_MIN;
- return (0);
- }
- /*
- * Maybe a variable definition ?
- */
- if (variant[1] != '=')
- field->var = -1;
- else
- {
- if ((variant[0] < VAR_MIN) || (variant[0] > VAR_MAX))
- {
- fprintf (stderr, "Error: bad variable in %s : \"%s\"\n", fname, line);
- fprintf (stderr, "Error: must be in [%c-%c]\n", VAR_MIN, VAR_MAX);
- return (-1);
- }
- field->var = variant[0] - VAR_MIN;
- variant++; /* Skip variable name */
- variant++; /* Skip '=' */
- /*
- * We need a variable !
- */
- if (obj->var[field->var] == NULL)
- obj->var[field->var] = (char *) malloc (MAX_FILTER);
- }
- /*
- * Find how definition
- */
- for (end=0 ; (variant[end]!='\0') && (variant[end]!='(') ; end++);
- if (variant[end]=='\0')
- {
- fprintf (stderr, "Error: bad variant in %s : \"%s\"\n", fname, line);
- fprintf (stderr, "Error: missing '('\n");
- return (-1);
- }
- strncpy (how, variant, end);
- how[end] = '\0';
- /*
- * Parse the first parameter
- */
- end++; /* Skip '(' */
- for (start=end ; (variant[end]!='\0') && (variant[end]!=';')
- && (variant[end]!=')') ; end++);
- if (variant[end]=='\0')
- {
- fprintf (stderr, "Error: bad variant in %s : \"%s\"\n", fname, line);
- fprintf (stderr, "Error: missing ')'\n");
- return (-1);
- }
- strncpy (first, variant+start, end-start);
- first[end-start] = '\0';
- /*
- * Parse the second parameter
- */
- if (variant[end] == ')')
- second[0] = '\0';
- else
- {
- end++; /* Skip ';' */
- for (start=end ; (variant[end]!='\0') && (variant[end]!=';')
- && (variant[end]!=')') ; end++);
- if (variant[end]=='\0')
- {
- fprintf (stderr, "Error: bad variant in %s : \"%s\"\n", fname, line);
- fprintf (stderr, "Error: missing ')'\n");
- return (-1);
- }
- strncpy (second, variant+start, end-start);
- second[end-start] = '\0';
- }
- /*
- * Parse the third parameter
- */
- if (variant[end]==')')
- third[0]='\0';
- else
- {
- end++; /* Skip ';' */
- for (start=end ; (variant[end]!='\0') && (variant[end]!=')') ; end++);
- if (variant[end]=='\0')
- {
- fprintf (stderr, "Error: bad variant in %s : \"%s\"\n", fname, line);
- fprintf (stderr, "Error: missing ')'\n");
- return (-1);
- }
- strncpy (third, variant+start, end-start);
- third[end-start] = '\0';
- }
- /*
- * Analyse it
- * Note : first parameter always exist (detected when parsing) while
- * second and third may not have been provided by the user.
- */
- switch (field->how = decodeHow (how))
- {
- case HOW_INCR_FROM_FILE:
- case HOW_INCR_FROM_FILE_NL:
- case HOW_RND_FROM_FILE:
- if ((field->dlf = dataListFile (first)) == NULL)
- {
- fprintf (stderr, "Error : bad file in %s : \"%s\"\n", fname, line);
- return (-1);
- }
- /*
- * Useless for HOW_RND_FROM_FILE
- */
- field->cnt = 0;
- field->low = 0;
- field->high = field->dlf->strNb - 1;
- /*
- * Maybe common counter ?
- */
- if ((mctx.mode & COMMON_COUNTER) &&
- ((field->how == HOW_INCR_FROM_FILE) ||
- (field->how == HOW_INCR_FROM_FILE_NL)))
- {
- if ((ret = ldclt_mutex_init (&(field->cnt_mutex))) != 0)
- {
- fprintf (stderr, "ldclt: %s\n", strerror (ret));
- fprintf (stderr, "Error: cannot initiate cnt_mutex in %s for %s\n",
- fname, line);
- fflush (stderr);
- return (-1);
- }
- }
- break;
- case HOW_INCR_NB:
- case HOW_INCR_NB_NOLOOP:
- case HOW_RND_NUMBER:
- if (third[0] == '\0')
- {
- fprintf (stderr, "Error : missing parameters in %s : \"%s\"\n",
- fname, line);
- return (-1);
- }
- field->cnt = atoi (first);
- field->low = atoi (first);
- field->high = atoi (second);
- field->nb = atoi (third);
- /*
- * Maybe common counter ?
- */
- if ((mctx.mode & COMMON_COUNTER) &&
- ((field->how == HOW_INCR_NB) || (field->how == HOW_INCR_NB_NOLOOP)))
- {
- if ((ret = ldclt_mutex_init (&(field->cnt_mutex))) != 0)
- {
- fprintf (stderr, "ldclt: %s\n", strerror (ret));
- fprintf (stderr, "Error: cannot initiate cnt_mutex in %s for %s\n",
- fname, line);
- fflush (stderr);
- return (-1);
- }
- }
- break;
- case HOW_RND_STRING:
- field->nb = atoi (first);
- break;
- case -1:
- fprintf (stderr, "Error: illegal keyword \"%s\" in %s : \"%s\"\n",
- how, fname, line);
- return (-1);
- break;
- }
- return (0);
- }
- /* ****************************************************************************
- FUNCTION : parseAttribValue
- PURPOSE : Parse the right part of attribname: attribvalue.
- INPUT : fname = file name
- obj = object where variables are.
- line = value to parse.
- OUTPUT : attrib = attribute where the value should be stored
- RETURN : -1 if error, 0 else.
- DESCRIPTION :
- *****************************************************************************/
- int
- parseAttribValue (
- char *fname,
- vers_object *obj,
- char *line,
- vers_attribute *attrib)
- {
- char variant[MAX_FILTER]; /* To process the variant */
- int start, end; /* For the loops */
- vers_field *field; /* To build the fields */
- if (mctx.mode & VERY_VERBOSE)
- printf ("parseAttribValue: line=\"%s\"\n", line);
- /*
- * We will now parse this line for the different fields.
- */
- field = NULL;
- end = start = 0;
- while (line[end]!='\0')
- {
- /*
- * Allocate a new field
- */
- if (field == NULL)
- {
- field = (vers_field *) malloc (sizeof (vers_field));
- field->next = NULL;
- attrib->field = field;
- }
- else
- {
- field->next = (vers_field *) malloc (sizeof (vers_field));
- field = field->next;
- field->next = NULL;
- }
- /*
- * Is it a variant field ?
- */
- if (line[end] == '[')
- {
- /*
- * Extract the variant definition
- */
- end++; /* Skip '[' */
- for (start=end ; (line[end]!='\0') && (line[end]!=']') ; end++);
- strncpy (variant, line+start, end-start);
- variant[end-start] = '\0';
- if (line[end]=='\0')
- {
- fprintf (stderr, "Error: missing ']' in %s : \"%s\"\n", fname, line);
- return (-1);
- }
- if (parseVariant (variant, fname, line, obj, field) < 0)
- return (-1);
- end++; /* Skip ']' */
- /*
- * We need to allocate a buffer in this attribute !
- */
- if (attrib->buf == NULL)
- {
- attrib->buf = (char *) malloc (MAX_FILTER);
- if (mctx.mode & VERY_VERBOSE)
- printf ("parseAttribValue: buffer allocated\n");
- }
- }
- else
- {
- /*
- * It is a constant field. Find the end : [ or \0
- */
- for (start=end ; (line[end]!='\0') && (line[end]!='[') ; end++);
- field->how = HOW_CONSTANT;
- field->cst = (char *) malloc (1+end-start);
- strncpy (field->cst, line+start, end-start);
- field->cst[end-start] = '\0';
- }
- }
- /*
- * Attribute value is parsed !
- */
- return (0);
- }
- /* ****************************************************************************
- FUNCTION : parseLine
- PURPOSE : Parse the given line to find an attribute definition.
- INPUT : line = line to parse
- fname = file name
- OUTPUT : obj = object where the attribute should be added
- RETURN : -1 if error, 0 else.
- DESCRIPTION :
- *****************************************************************************/
- int
- parseLine (
- char *line,
- char *fname,
- vers_object *obj)
- {
- int end; /* For the loops */
- if (mctx.mode & VERY_VERBOSE)
- printf ("parseLine: line=\"%s\"\n", line);
- /*
- * Empty line ? Comment ?
- * No more place for new attributes ?
- */
- if ((line[0]=='\0') || (line[0]=='#'))
- return (0);
- if (obj->attribsNb == MAX_ATTRIBS)
- {
- fprintf (stderr, "Error: too many attributes in %s, max is %d\n",
- fname, MAX_ATTRIBS);
- return (-1);
- }
- /*
- * Find the attribute name
- * name:
- */
- for (end=0 ; (line[end]!='\0') && (line[end]!=':') ; end++);
- if (line[end]!=':')
- {
- fprintf (stderr, "Error: can't find attribute name in %s : \"%s\"\n",
- fname, line);
- return (-1);
- }
- /*
- * Initiate the attribute
- */
- obj->attribs[obj->attribsNb].buf = NULL;
- obj->attribs[obj->attribsNb].src = strdup (line);
- obj->attribs[obj->attribsNb].name = (char *) malloc (1+end);
- strncpy (obj->attribs[obj->attribsNb].name, line, end);
- obj->attribs[obj->attribsNb].name[end] = '\0';
- for (end++ ; line[end]==' ' ; end++); /* Skip the leading ' ' */
- /*
- * We will now parse the value of this attribute
- */
- if (parseAttribValue(fname,obj, line+end, &(obj->attribs[obj->attribsNb]))<0)
- return (-1);
- /*
- * Do not forget to increment attributes number !
- */
- obj->attribsNb++;
- return (0);
- }
- /* ****************************************************************************
- FUNCTION : readObject
- PURPOSE : This function will read an object description from the
- file given in argument.
- The object should be already initiated !!!
- INPUT : None.
- OUTPUT : obj = parsed object.
- RETURN : -1 if error, 0 else.
- DESCRIPTION :
- *****************************************************************************/
- int
- readObject (
- vers_object *obj)
- {
- FILE *ifile; /* The file that contains the object to read */
- char line[MAX_FILTER]; /* To read ifile */
- int rc = 0;
- /*
- * Open the file
- */
- ifile = fopen (obj->fname, "r");
- if (ifile == NULL)
- {
- perror (obj->fname);
- fprintf (stderr, "Error: cannot open file \"%s\"\n", obj->fname);
- rc = -1;
- goto done;
- }
- /*
- * Process each line of the input file.
- * Reminder : the object is initiated by the calling function !
- */
- while (fgets (line, MAX_FILTER, ifile) != NULL)
- {
- if ((strlen (line) > 0) && (line[strlen(line)-1]=='\n'))
- line[strlen(line)-1] = '\0';
- if (parseLine (line, obj->fname, obj) < 0) {
- rc = -1;
- goto done;
- }
- }
- done:
- /*
- * Do not forget to close the file !
- */
- if (ifile && fclose (ifile) != 0)
- {
- perror (obj->fname);
- fprintf (stderr, "Error: cannot fclose file \"%s\"\n", obj->fname);
- rc = -1;
- }
- /*
- * End of function
- */
- if (obj->attribsNb == 0)
- {
- fprintf (stderr, "Error: no object found in \"%s\"\n", obj->fname);
- rc = -1;
- }
- return rc;
- }
- /* End of file */
|