blob: a23dc0504d2b8944757e2a1bd1b83e0825bd84ff [file] [log] [blame]
/*
*------------------------------------------------------------------
* Copyright (c) 1997-2016 Cisco and/or its affiliates.
* 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include <time.h>
#include <gtk/gtk.h>
#include <string.h>
static char *sxerox (char *s);
void exit(int);
#define NBUCKETS 97
typedef struct prop_ {
struct prop_ *next;
char *name;
char *value;
} prop_t;
static prop_t *buckets [NBUCKETS];
static int hash_shifts[4] = {24, 16, 8, 0};
/*
* getprop
*/
char *getprop (char *name)
{
unsigned char *cp;
unsigned long hash=0;
prop_t *bp;
int i=0;
for (cp = (unsigned char *) name; *cp; cp++)
hash ^= (*cp)<<(hash_shifts[(i++)&0x3]);
bp = buckets [hash%NBUCKETS];
while (bp && strcmp (bp->name, name)) {
bp = bp->next;
}
if (bp == NULL)
return (0);
else
return (bp->value);
}
/*
* getprop_default
*/
char *getprop_default (char *name, char *def)
{
char *rv;
rv = getprop (name);
if (rv)
return (rv);
else
return (def);
}
/*
* addprop
*/
void addprop (char *name, char *value)
{
unsigned char *cp;
unsigned long hash=0;
prop_t **bpp;
prop_t *bp;
int i=0;
bp = (prop_t *)g_malloc (sizeof (prop_t));
bp->next = 0;
bp->name = sxerox (name);
bp->value = sxerox (value);
for (cp = (unsigned char *)name; *cp; cp++)
hash ^= (*cp)<<(hash_shifts[(i++)&0x3]);
bpp = &buckets [hash%NBUCKETS];
if (*bpp == NULL)
*bpp = bp;
else {
bp->next = *bpp;
*bpp = bp;
}
}
/*
* sxerox
*/
static char *sxerox (char *s)
{
char *rv = (char *) g_malloc (strlen (s) + 1);
strcpy (rv, s);
return rv;
}
/*
* readprops
*/
#define START 0
#define READNAME 1
#define READVALUE 2
#define C_COMMENT 3
#define CPP_COMMENT 4
int readprops (char *filename)
{
FILE *ifp;
unsigned char c;
int state=START;
int linenum=1;
char namebuf [128];
char valbuf [512];
int i;
ifp = fopen (filename, "r");
if (ifp == NULL)
return (-1);
while (1) {
readchar:
c = getc (ifp);
again:
switch (state) {
case START:
if (feof (ifp)) {
fclose (ifp);
return (0);
}
if (c == ' ' || c == '\t')
goto readchar;
if (c == '\n') {
linenum++;
goto readchar;
}
if (isalpha (c) || (c == '_')) {
state = READNAME;
goto again;
}
if (c == '/') {
c = getc (ifp);
if (c == '/') {
state = CPP_COMMENT;
goto readchar;
} else if (c == '*') {
state = C_COMMENT;
goto readchar;
} else {
fprintf (stderr, "unknown token '/' line %d\n",
linenum);
exit (1);
}
}
fprintf (stderr, "unknown token '%c' line %d\n",
c, linenum);
exit (1);
break;
case CPP_COMMENT:
while (1) {
c = getc (ifp);
if (feof (ifp))
return (0);
if (c == '\n') {
linenum++;
state = START;
goto readchar;
}
}
break;
case C_COMMENT:
while (1) {
c = getc (ifp);
if (feof (ifp)) {
fprintf (stderr, "unterminated comment, line %d\n",
linenum);
exit (1);
}
if (c == '*') {
staragain:
c = getc (ifp);
if (c == '/') {
state = START;
goto readchar;
}
if (c == '*')
goto staragain;
}
}
break;
case READNAME:
i = 0;
namebuf[i++] = c;
while (1) {
c = getc (ifp);
if (feof (ifp)) {
fprintf (stderr, "EOF while reading a name, line %d\n",
linenum);
exit (1);
}
if ((!isalnum (c)) && (c != '_')) {
namebuf [i] = 0;
state = READVALUE;
goto again;
}
namebuf [i++] = c;
}
break;
case READVALUE:
i = 0;
while ((c == ' ') || (c == '\t') || (c == '=')) {
c = getc (ifp);
if (feof (ifp)) {
fprintf (stderr, "EOF while reading a value, line %d\n",
linenum);
exit (1);
}
}
goto firsttime;
while (1) {
c = getc (ifp);
firsttime:
if (c == '\\') {
c = getc (ifp);
if (feof (ifp)) {
fprintf (stderr, "EOF after '\\', line %d\n",
linenum);
exit (1);
}
valbuf[i++] = c;
continue;
}
if (c == '\n') {
linenum++;
while (valbuf [i-1] == ' ' || valbuf[i-1] == '\t')
i--;
valbuf[i] = 0;
addprop (namebuf, valbuf);
state = START;
goto readchar;
}
valbuf[i++] = c;
}
}
}
}