aboutsummaryrefslogblamecommitdiffstats
path: root/calendar/lexer.c
blob: 264808a75da01fbc278653085d8d18dac874c48a (plain) (tree)




































































































































































































































































































































































































                                                                                                 
/*
 * lexer.c: Reads in the .calendar files
 */
#include <stdio.h>
#include <glib.h>


#define opener "["
#define closer "]"
#define VersionMajor 2


int skip_chars(FILE *fp, char *terminator)
{
    int c;
    int cnt;

    cnt = 0;
    while( (c = fgetc(fp)) != EOF) {
        if (c == terminator[cnt]) {
            cnt++;
            if (terminator[cnt] == '\0')
                return TRUE;
        } else
            cnt = 0;
    }
    return FALSE;
}

int peek_char(FILE *fp, char *c)
{
    if ( ((*c) = fgetc(fp)) != EOF) {
        ungetc((*c), fp);
        return TRUE;
    } else  
        return FALSE;
}

int skip_whitespace(FILE *fp)
{
    int c;

    while( (c = fgetc(fp)) != EOF)
        if (!isspace(c)) {
            ungetc(c, fp);
            return TRUE;
        }
    return FALSE;
}

int get_until(FILE *fp, char terminator, char *buf) 
{
    int c;

    while( (c = fgetc(fp)) != EOF) {
        if (c == terminator)
            return TRUE;
        *buf = (char)c;
        buf++;
    }
    return FALSE;
}

int get_number(FILE *fp, int *x) 
{
    char buf[50];
    int c;
    int cnt;

    cnt = 0;
    buf[cnt] = '\0';
    while( (c= fgetc(fp)) != EOF) {
       if (!isdigit(c)) {
        ungetc(c, fp);
        *x = atoi(buf);
        return TRUE;
       }
       buf[cnt++] = (char)c;
       buf[cnt] = '\0';
    }
    *x = atoi(buf);
    return FALSE;
}   

int get_string(FILE *fp, char *string)
{
    int c;
    int cnt;

    cnt = 0;
    while ( (c = fgetc(fp)) != EOF) {
        if (c == closer[0]) {
            string[cnt] = '\0';
            ungetc((char)c, fp);
            return TRUE;
        }
        string[cnt++] = (char)c;
    }   
    return FALSE;
}

int getid(FILE *fp, char *string)
{
    int c;
    int cnt;

    cnt = 0;
    while( (c =fgetc(fp)) != EOF) {
        if (isalnum(c)) 
            string[cnt++] = (char)c;
        else {
            string[cnt] = '\0';
            return TRUE;
        }
    }
    string[cnt] = '\0';
    return FALSE;
}

int parse_appointment(FILE *fp, char keyword[])
{
    char buf[50];
    int x,y,c;

    if (strcmp(keyword, "Start") == 0) {
        if ( ! skip_whitespace(fp) || ! get_number(fp, &x) ) {
            g_error("Unable to get start time");
            return FALSE;
        }
        g_print ("Appointment start = %d\n", x);
        return TRUE;
    }

    if (strcmp(keyword, "Length") == 0) {
        if ( ! skip_whitespace(fp) || ! get_number(fp, &x) ) {
            g_error("Unable to get length");
            return FALSE;
        }
        g_print ("Appointment length = %d\n", x);
        return TRUE;
    }

    if (strcmp(keyword, "Alarms") == 0) {
        while(TRUE) {
            skip_whitespace(fp);
            if (!peek_char(fp, (char*)&c)) {
                g_error("Cannot read alarm list");
                return FALSE;
            }
            if (!isdigit(c))
                break;

            if (! get_number(fp, &x))
                return FALSE;

            g_print("New alarm %d\n", x);
        }
        return TRUE;
    }

    g_print("Unknown keyword %s\n", keyword);
    return FALSE;
}
            
int parse_item(FILE *fp, char keyword[]) 
{
    char buf[50];
    int x, y, c;

    if (strcmp(keyword, "Remind") == 0) {
        if (! skip_whitespace(fp) || ! get_number(fp, &x)) {
            g_error("Cannot get remind level");
            return FALSE;
        }
        g_print("Remind level = %d\n", x);
        return TRUE;
    }

    if (strcmp(keyword, "Owner") == 0) {
        if (!get_string(fp, buf)) {
            g_error("Cannot get owner information");
            return FALSE;
        }
        g_print("Owner = %s\n", buf);
        return TRUE;
    }

    if (strcmp(keyword, "Uid") == 0) {
        if (!skip_whitespace(fp) || !get_until(fp, *closer, buf)) {
            g_error("Cannot get unique ID");
            return FALSE;
        }
        g_print("UID = %s\n", buf);
        return TRUE;
    }

    if (strcmp(keyword, "Contents") == 0) {
        if (!get_string(fp, buf)) {
            g_error("Cannot get item text");
            return FALSE;
        }
        g_print("Contents = %s\n", buf);
        return TRUE;
    }

    if (strcmp(keyword, "Text") == 0) {
        if (! skip_whitespace(fp) || ! get_number(fp, &x) ||
            (x < 0) || ! skip_whitespace(fp) || ! skip_chars(fp, opener) ) {
            g_error("Cannot get item text");
            return FALSE;
        }
        y = 0;
        while(y < x) {
            if ( (c = fgetc(fp)) == EOF) {
                g_error("Short item text");
                return FALSE;
            }
            buf[y++] = (char)c;
        }
        buf[y] = '\0';
        g_print("Text = %s\n", buf);
        return TRUE;
    }
    
    if (strcmp(keyword, "Dates") == 0) {
        if (! get_string(fp, buf)) {
            g_error("Cannot get date");
            return FALSE;
        }
        g_print("Date = %s\n", buf);
        return TRUE;
    }

    if (strcmp(keyword, "Deleted") == 0) {
        if (! skip_whitespace(fp) || ! get_number(fp, &x)) {
            g_error("Cannot get deleted day");
            return FALSE;
        }
        g_print("%d/", x);
        if (! skip_whitespace(fp) || ! get_number(fp, &x)) {
            g_error("Cannot get deleted month");
            return FALSE;
        }
        g_print("%d/", x);
        if (! skip_whitespace(fp) || ! get_number(fp, &x)) {
            g_error("Cannot get deleted year");
            return FALSE;
        }
        g_print("%d\n", x);
        return TRUE;
    }

    if (strcmp(keyword, "Hilite") == 0) {
        if (! get_string(fp, buf) ) {
            g_error("Cannot get hilite data");
            return FALSE;
        }
        g_print("Hilite = %s\n", buf);
        return  TRUE;
    }

    if (strcmp(keyword, "Todo") == 0) {
        g_print("Todo\n");
        return TRUE;
    }


    if (strcmp(keyword, "Done") == 0) {
        g_print("Done\n");
        return TRUE;
    }

    return FALSE;
}

void parse_ical_file(char const *file)
{
    FILE *fp;
    int finished;
    char keyword[50];
    int file_major, file_minor;
    char c;
    int item_type;
    int incomplete_item;


    if ( (fp = fopen(file, "r")) == NULL) {
        g_error("couldn't open file");
        return;
    }

    finished = FALSE;

    if (!skip_whitespace(fp))
        return;

    if (! skip_chars(fp, "Calendar") || ! skip_whitespace(fp) ) {
        g_error("unable to find calendar file");
        fclose(fp);
        return;
    }

    if (! skip_chars(fp, opener) || ! skip_chars(fp, "v") ) {
        g_error("Unable to get version line");
        fclose(fp);
        return;
    }
    if (! get_number(fp, &file_major) || ! (file_major >=0) || (file_major > VersionMajor)) {
        g_error("Missing/bad major version");
        fclose(fp);
        return;
    }

    if (! skip_chars(fp, ".") || ! get_number(fp, &file_minor) ||
        ! skip_chars(fp, "]") || ! skip_whitespace(fp) ) {
        g_error("Missing  minor version");
        fclose(fp);
        return;
    }
    if (file_minor > 0) {
        g_error("Bad  minor version");
        fclose(fp);
        return;
    }

    while(TRUE) {
        g_print("----------------------------------------\n");
        item_type= 0;
        skip_whitespace(fp);
        if (! getid(fp,keyword) || ! skip_whitespace(fp) ||
            ! skip_chars(fp, opener) || ! skip_whitespace(fp) ) {
            fclose(fp);
            return;
        }

        if (strcmp(keyword, "Appt") == 0) {
            g_print("New Appointment\n");
            item_type = 1;

        } else if (strcmp(keyword, "Note") == 0) {
            g_print("New Note\n");
            item_type = 2;
        } else 
            g_print("New ??? (%s)\n", keyword);

        incomplete_item = TRUE;
        while(incomplete_item) {
            if (! skip_whitespace(fp) || ! peek_char(fp, &c)) {
                g_warning("Incomplete item\n");
                fclose(fp);
                return;
            }
            if (c == closer[0]) {
                (void)fgetc(fp);
                g_print("done!\n");
                incomplete_item = FALSE;
                break;
            }
        
            if (! getid(fp,keyword) || ! skip_whitespace(fp) ||
                ! skip_chars(fp, opener) ) {
                g_error("Error reading item property name");
                fclose(fp);
                return;
            }
            if ( ! parse_item(fp, keyword) && ! parse_appointment(fp, keyword) ) {
                g_warning("Unable to parse line\n");
                fclose(fp);
                return;
            }
            if ( ! skip_whitespace(fp) || ! skip_chars(fp, closer)) {
                g_error("Error reading item property");
                fclose(fp);
                return;
            }
        } /* while */
    } /* while */
}
        
    


int main(int argc, char *argv[])
{

    parse_ical_file("/home/csmall/.calendar");
    return 0;
}