(file) Return to regfile.c CVS log (file) (dir) Up to [OMI] / omi / provreg

File: [OMI] / omi / provreg / regfile.c (download)
Revision: 1.1.1.1 (vendor branch), Wed May 30 21:47:49 2012 UTC (12 years, 1 month ago) by mike
Branch: TOG
CVS Tags: OMI_1_0_2_Branch, OMI_1_0_2, OMI_1_0_1_PRE, OMI_1_0_1, OMI_1_0_0
Changes since 1.1: +0 -0 lines
Initial Import

/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
** 
** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
** use this file except in compliance with the License. You may obtain a copy 
** of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
** MERCHANTABLITY OR NON-INFRINGEMENT. 
**
** See the Apache 2 License for the specific language governing permissions 
** and limitations under the License.
**
**==============================================================================
*/

#include <stdio.h>
#include <ctype.h>
#include <base/strings.h>
#include <base/list.h>
#include <base/io.h>
#include "regfile.h"

// Parse an identifies of the form "[A-Za-z_][A-Za-z_0-9]*"
static int _ParseIdentifier(char** pOut, char** start, char** end)
{
    char* p = *pOut;

    /* Skip leading whitespace */
    while (isspace((unsigned char)(*p)))
        p++;

    /* Set start of identifier */
    *start = p;

    /* Expect [A-Za-z_] characters */
    if (!isalpha((unsigned char)(*p)) && *p != '_')
        return -1;

    /* Skip [A-Za-z_0-9] characters */
    while (isalnum((unsigned char)(*p)) || *p == '_')
        p++;

    /* Set end of identifier */
    *end = p;

    *pOut = p;
    return 0;
}

// Parase class path of the form "CLASS1:CLASS2:CLASS3"
static int _ParseClassPath(char** pOut, char** start, char** end)
{
    char* p = *pOut;

    /* Skip leading whitespace */
    while (isspace((unsigned char)(*p)))
        p++;

    /* Set start of identifier */
    *start = p;

    /* Expect [A-Za-z_] characters */
    if (!isalpha((unsigned char)(*p)) && *p != '_')
        return -1;

    /* Skip [A-Za-z_0-9] characters */
    while (isalnum((unsigned char)(*p)) || *p == '_' || *p == ':')
        p++;

    /* Set end of identifier */
    *end = p;

    *pOut = p;
    return 0;
}

static int _ExpectChar(char** pOut, char ch)
{
    char* p = *pOut;

    /* Skip whitespace */
    while (isspace((unsigned char)(*p)))
        p++;

    /* Expect character */
    if (*p != ch)
        return -1;
    p++;

    *pOut = p;
    return 0;
}

// Parse a line of the form 'KEY=VALUE'
static int _ParseKeyValueLine(char** pOut, char** keyOut, char** valueOut)
{
    char* p = *pOut;
    char* keyEnd;

    /* Parse key */
    if (_ParseIdentifier(&p, keyOut, &keyEnd) != 0)
        return-1;

    /* If out of input, error out */
    if (!*p)
        return -1;

    /* Skip whitespace */
    if (_ExpectChar(&p, '=') != 0)
        return -1;

    /* Null-terminate the key */
    *keyEnd = '\0';

    /* Skip whitespace */
    while (isspace((unsigned char)(*p)))
        p++;

    /* Set value */
    *valueOut = p;

    *pOut = p;
    return 0;
}

static int _ParseClassValue(
    char** pOut, 
    char** nameOut, 
    char** refName1Out,
    char** refName2Out)
{
    char* p = *pOut;
    char* start;
    char* end;

    /* Expect class name */
    if (_ParseClassPath(&p, &start, &end) != 0)
        return -1;

    /* Skip whitespace */
    while (isspace((unsigned char)(*p)))
        p++;

    /* If end of line */
    if (!*p)
    {
        *nameOut = start;
        *end = '\0';
        *refName1Out = NULL;
        *refName2Out = NULL;
        *pOut = p;
        return 0;
    }

    /* Expect '{' character */
    if (_ExpectChar(&p, '{') != 0)
        return -1;

    /* Get 'name' */
    *nameOut = start;
    *end = '\0';

    /* Expect reference name */
    if (_ParseClassPath(&p, &start, &end) != 0)
        return -1;

    /* Expect ',' character */
    if (_ExpectChar(&p, ',') != 0)
        return -1;

    /* Get 'refName1' */
    *refName1Out = start;
    *end = '\0';

    /* Expect reference name */
    if (_ParseClassPath(&p, &start, &end) != 0)
        return -1;

    /* Expect '}' character */
    if (_ExpectChar(&p, '}') != 0)
        return -1;

    /* Get 'refName1' */
    *refName2Out = start;
    *end = '\0';

    *pOut = p;
    return 0;
}

RegFile* RegFile_New(const char* path)
{
    FILE* is;
    char buf[1024];
    int foundLibrary = 0;
    char* hosting = NULL;

    RegFile* self = 0;

    /* Open the file */
    is = Fopen(path, "rb");
    if (!is)
        return NULL;

    /* Allocate self structure */
    self = (RegFile*)calloc(1, sizeof(RegFile));
    if (!self)
    {
        fclose(is);
        return NULL;
    }

    /* Read line by line */
    while (fgets(buf, sizeof(buf), is) != NULL)
    {
        char* start = buf;
        char* p = start;
        char* key;
        char* value;

        /* Skip comment lines */
        if (*p == '#')
            continue;

        /* Remove trailing whitespace */
        {
            char* end = buf + strlen(buf);

            while (end != start && isspace((unsigned char)end[-1]))
                *--end = '\0';
        }

        /* Skip leading whitespace */
        while (isspace((unsigned char)(*p)))
            p++;

        /* Skip blank lines */
        if (*p == '\0')
            continue;

        /* Look for LIBRARY= */
        if (_ParseKeyValueLine(&p, &key, &value) != 0)
            goto failed;

        if (strcmp(key, "LIBRARY") == 0)
        {
            if (foundLibrary)
                goto failed;

            self->library = Strdup(value);

            if (!self->library)
                goto failed;

            foundLibrary = 1;
        }
        else if (strcmp(key, "HOSTING") == 0)
        {
            if (hosting)
                free(hosting);

            hosting = Strdup(value);
        }
        else if (strcmp(key, "CLASS") == 0)
        {
            char* name;
            char* refName1;
            char* refName2;
            RegClass* rc;

            if (_ParseClassValue(&p, &name, &refName1, &refName2) != 0)
                goto failed;

            rc = (RegClass*)calloc(1, sizeof(RegClass));
            if (!rc)
                goto failed;

            List_Append(
                (ListElem**)&self->classesHead,
                (ListElem**)&self->classesTail,
                (ListElem*)rc);

            rc->name = Strdup(name);
            if (!rc->name)
                goto failed;

            if (refName1)
            {
                rc->refName1 = Strdup(refName1);
                if (!rc->refName1)
                    goto failed;
            }

            if (refName2)
            {
                rc->refName2 = Strdup(refName2);
                if (!rc->refName2)
                    goto failed;
            }

            if (hosting)
                rc->hosting = Strdup(hosting);
        }
    }

    if (hosting)
        free(hosting);

    fclose(is);

    return self;

failed:
    if (self)
        RegFile_Delete(self);

    if (is)
        fclose(is);

    return NULL;
}

void RegFile_Delete(RegFile* self)
{
    RegClass* rc;
    RegClass* next;

    if (!self)
        return;

    if (self->library)
        free(self->library);

    for (rc = self->classesHead; rc; rc = next)
    {
        if (rc->name)
            free(rc->name);

        if (rc->refName1)
            free(rc->refName1);

        if (rc->refName2)
            free(rc->refName2);

        if (rc->hosting)
            free(rc->hosting);

        next = rc->next;
        free(rc);
    }

    free(self);
}

void RegFile_Print(RegFile* self, FILE* os)
{
    RegClass* rc;

    fprintf(os, "LIBRARY=%s\n", self->library);

    for (rc = self->classesHead; rc; rc = rc->next)
    {
        fprintf(os, "CLASS=%s", rc->name);

        if (rc->refName1 && rc->refName2)
        {
            fprintf(os, "{");
            fprintf(os, "%s", rc->refName1);
            fprintf(os, ",");
            fprintf(os, "%s", rc->refName2);
            fprintf(os, "}");
        }

        fprintf(os, "\n");
    }
}

ViewCVS 0.9.2