staden-lg/src/staden/tagdbparse.c

328 lines
6.7 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "tagdb.h"
/* TOKENS */
#define NULLTOKEN 0
#define END 1
#define ID 2
#define SEPARATOR 3
#define NL 4
#define EQ 5
static char *infile; /* file being parsed */
static char word[128];
static int lineno;
/* ---------------- private routines ----------------- */
static void spring_clean_text (s,t)
/* parse out normal escape characters bar hex and octal */
char *s;
char *t;
{
while (*s != '\0') {
if (*s == '\\')
switch (*++s) {
case 'a': *t++ = '\a'; s++; break;
case 'b': *t++ = '\b'; s++; break;
case 'f': *t++ = '\f'; s++; break;
case 'n': *t++ = '\n'; s++; break;
case 'r': *t++ = '\r'; s++; break;
case 't': *t++ = '\t'; s++; break;
case 'v': *t++ = '\v'; s++; break;
case '\n':
while (isspace(*++s));
break;
/*
case 'x' :
if (isxdigit(s[1]) && isxdigit(s[2])) {
#define ASCII_TO_HEX(A) (isdigit(A)?(A-'0'):(tolower(A)-'a'+10))
*t++ = ASCII_TO_HEX(s[1])*16 + ASCII_TO_HEX(s[2]);
s++;s++;s++;
}
break;
*/
case '\\':
case '\?':
case '\'':
case '\"':
case '\0': break;
} else *t++ = *s++;
}
*t = '\0';
}
static int next_word(FILE *fp)
/*
** lexical analyser
** Get's the next word from the input stream
*/
{
int a;
int token;
char *s;
token = NULLTOKEN;
s = word;
while (token == NULLTOKEN) {
switch (a = getc(fp)) {
case EOF:
token = END;
break;
case '\n':
lineno++;
token = NL;
break;
case '=':
token = EQ;
break;
case ':':
token = SEPARATOR;
break;
case '#':
/* comment: skip to end of line */
for(a=getc(fp); a!=EOF && a!='\n'; a=getc(fp));
if (a=='\n') lineno++;
if (a==EOF) token = END;
break;
case '\\':
/* back quoted newlines are skipped */
/* back quoted "anything else" is "anything else" */
a = getc(fp);
if (a != EOF && a != '\n') ungetc(a,fp);
break;
case '"':
/* quoted string */
for(a=getc(fp);a!=EOF && a!='"';a=getc(fp)) {
if (a=='\n') lineno++;
*s++ = a;
}
token = ID;
break;
default:
if (isalnum(a)) {
*s++ = a;
for(a=getc(fp);a!=EOF && isalnum(a);a=getc(fp)) *s++ = a;
if (a!=EOF) ungetc(a,fp);
token = ID;
}
break;
}
}
*s = '\0';
spring_clean_text(word,word);
return token;
}
static void parse_error(char *s)
{
fprintf( stderr, "%s on line %d of %s\n", s,lineno,infile);
}
static int snatch(char *s)
{
if (strcmp(s,"id")==0) return TAG_SEARCH_ID;
if (strcmp(s,"fg")==0) return TAG_FG_COLOUR;
if (strcmp(s,"bg")==0) return TAG_BG_COLOUR;
if (strcmp(s,"dt")==0) return TAG_DEFAULT_TEXT;
return TAG_UNKNOWN;
}
static void initTagDBFields(char *type)
{
tag_db[tag_db_count].type = (char *)malloc(strlen(type)+1);
strcpy(tag_db[tag_db_count].type,type);
tag_db[tag_db_count].search_id = NULL;
tag_db[tag_db_count].fg_colour = NULL;
tag_db[tag_db_count].bg_colour = NULL;
tag_db[tag_db_count].default_text = NULL;
}
static void tidyUpTagDBFields()
{
int len;
if (tag_db[tag_db_count].search_id == NULL) {
tag_db[tag_db_count].search_id = tag_db[tag_db_count].type;
}
len = strlen(tag_db[tag_db_count].search_id);
if (len < 4)
strncpy(tag_db[tag_db_count].id," ",4);
else
len = 4;
strncpy(tag_db[tag_db_count].id,tag_db[tag_db_count].search_id,len);
if (tag_db_count < (MAX_TAG_TYPES-1))
tag_db_count++;
}
static int parse_file(FILE *fp)
/*
** Parse file and load info into tag_db[]
*/
{
int at_end_of_file;
int at_end_of_entry;
/* for safe keeping */
int field;
char *WORD;
at_end_of_file = 0;
while (!at_end_of_file) {
switch (next_word(fp)) {
case END:
at_end_of_file = 1;
case NL:
break;
case ID:
/* the big time */
initTagDBFields(word);
switch(next_word(fp)) {
case END:
at_end_of_file = 1;
case NL:
break;
case SEPARATOR:
/* arglist */
at_end_of_entry = 0;
while (!at_end_of_entry) {
switch(next_word(fp)) {
case SEPARATOR:
break;
case ID:
field = snatch(word);
switch(next_word(fp)) {
case EQ:
switch(next_word(fp)) {
case ID:
WORD = (char *)malloc(strlen(word)+1);
strcpy(WORD,word);
switch (field) {
case TAG_SEARCH_ID :
tag_db[tag_db_count].search_id = WORD;
break;
case TAG_FG_COLOUR :
tag_db[tag_db_count].fg_colour = WORD;
break;
case TAG_BG_COLOUR :
tag_db[tag_db_count].bg_colour = WORD;
break;
case TAG_DEFAULT_TEXT :
tag_db[tag_db_count].default_text = WORD;
break;
default:
break;
}
switch(next_word(fp)) {
case END:
at_end_of_file = 1;
case NL:
at_end_of_entry = 1;
case SEPARATOR:
break;
default:
parse_error("Syntax error");
return ( 1 );
}
break;
default:
parse_error("Syntax error");
return ( 1 );
}
break;
case END:
at_end_of_file = 1;
case NL:
at_end_of_entry = 1;
case SEPARATOR:
break;
default:
parse_error("Syntax error");
return ( 1 );
}
break;
case END:
at_end_of_file = 1;
case NL:
at_end_of_entry = 1;
break;
default:
parse_error("Syntax error");
return ( 1 );
}
}
break;
default:
parse_error("Syntax error");
return 1;
}
tidyUpTagDBFields();
break;
default:
parse_error("Syntax error");
return 1;
}
}
return 0;
}
/* ------------------- exported routines ------------------ */
tag_db_struct tag_db[MAX_TAG_TYPES];
int tag_db_count;
void parse(char *file)
{
int parse_failed;
FILE *fp;
char *default_type = "Comment";
char *default_search_id = "DEFC";
char *default_fg_colour = NULL;
char *default_bg_colour = "yellow";
char *default_default_text = "Enter your comment here";
infile = file;
tag_db_count = 0;
if(fp = fopen(file,"r")) {
lineno = 1;
parse_failed = parse_file(fp);
if (parse_failed) {
fprintf (stderr,"Error encountered while parsing tag database\nGiving up\n");
tag_db_count = 0;
}
fclose(fp);
} else
fprintf (stderr,"Error parsing tag database\nFile `%s' does not exist\nGiving up\n",infile);
if (! tag_db_count) {
tag_db[tag_db_count].type = default_type;
tag_db[tag_db_count].search_id = default_search_id;
tag_db[tag_db_count].fg_colour = default_fg_colour;
tag_db[tag_db_count].bg_colour = default_bg_colour;
tag_db[tag_db_count].default_text = default_default_text;
tag_db_count++;
}
}