/* *------------------------------------------------------------------ * 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 #include #include #include #include #include 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; } } } }