int reader_skipline ( struct reader *r ) { int k = 0; /* Check inputs. */ if ( r == NULL ) return error(r,reader_err_null); /* Has an EOF already been reached? */ if ( r->flags & reader_flag_eof ) return error(r,reader_err_eof); /* Skip any input util a comment_start is hit. */ while ( r->c != EOF && r->c != '\n' && r->c != '\r' ) { /* Get the next char. */ k += 1; reader_getc( r ); } /* Skip the newline character. */ reader_getc( r ); /* Return the number of read characters. */ return k; }
/* Consume remaining whitespace on line, including linefeed. */ static void consume_whitespace (reader_t * r) { int c = reader_getc (r); while (strchr (" \t\r", c) != NULL) c = reader_getc (r); if (c != '\n') reader_putc (r, c); }
/* Consume remaining characters on line, including linefeed. */ static void consume_line (reader_t * r) { int c = reader_getc (r); while (c != '\n' && c != EOF) c = reader_getc (r); if (c != '\n') reader_putc (r, c); }
int reader_getcomment ( struct reader *r , char *buff , int buff_size ) { int k = 0; /* Check inputs. */ if ( r == NULL || buff == NULL ) return error(r,reader_err_null); /* Has an EOF already been reached? */ if ( r->flags & reader_flag_eof ) return error(r,reader_err_eof); /* Skip any input util a comment_start is hit. */ while ( !reader_iscomm_start( r , r->c ) ) if ( reader_getc( r ) == EOF ) return error(r,reader_err_eof); /* Skip the comment start character. */ if ( reader_getc( r ) == EOF ) { buff[0] = 0; return 0; } /* Write the input to the buffer until a comm_stop is reached. */ while ( r->c != EOF && !reader_iscomm_stop( r , r->c ) ) { /* Check buffer length. */ if ( k < buff_size-1 ) { /* Store the current char to the buff. */ buff[k] = r->c; k += 1; /* Get the next char. */ reader_getc( r ); } else return error(r,reader_err_buff); } /* Read comment into buffer. */ /* Terminate the comment. */ buff[k] = 0; /* Read the next char. */ reader_getc( r ); /* Return the comment length. */ return k; }
int reader_skiptoken ( struct reader *r ) { int k = 0; /* Check inputs. */ if ( r == NULL ) return error(r,reader_err_null); /* Has an EOF already been reached? */ if ( r->flags & reader_flag_eof ) return error(r,reader_err_eof); /* Skim-off whitespace and/or comments. */ while ( 1 ) { /* Skip whitespace. */ if ( reader_isws( r , r->c ) ) { if ( reader_getc( r ) == EOF ) return error(r,reader_err_eof); } /* Skip comments. */ else if ( reader_iscomm_start( r , r->c ) ) { do { if ( reader_getc( r ) == EOF ) return error(r,reader_err_eof); } while ( !reader_iscomm_stop( r , r->c ) ); if ( reader_getc( r ) == EOF ) return error(r,reader_err_eof); } else break; } /* get ws and comments. */ /* Read the token. */ while ( r->c != EOF && !reader_isws( r , r->c ) && !reader_iscomm_start( r , r->c ) ) { /* Get the next char. */ k += 1; reader_getc( r ); } /* Read the token. */ /* Return the token length. */ return k; }
int reader_getline ( struct reader *r , char *buff , int buff_size ) { int k = 0; /* Check inputs. */ if ( r == NULL || buff == NULL ) return error(r,reader_err_null); /* Has an EOF already been reached? */ if ( r->flags & reader_flag_eof ) return error(r,reader_err_eof); /* Skip any input util a comment_start is hit. */ while ( r->c != EOF && r->c != '\n' && r->c != '\r' ) { /* Is there room in the buffer? */ if ( k < buff_size-1 ) { /* Store this character. */ buff[k] = r->c; k += 1; /* Get the next char. */ reader_getc( r ); } /* Otherwise, buffer full. */ else return error(r,reader_err_buff); } /* Skip the newline character. */ reader_getc( r ); /* Terminate the buffer. */ buff[k] = 0; /* Return the number of read characters. */ return k; }
int reader_skipcomment ( struct reader *r ) { int k = 0; /* Check inputs. */ if ( r == NULL ) return error(r,reader_err_null); /* Has an EOF already been reached? */ if ( r->flags & reader_flag_eof ) return error(r,reader_err_eof); /* Skip any input util a comment_start is hit. */ while ( !reader_iscomm_start( r , r->c ) ) if ( reader_getc( r ) == EOF ) return error(r,reader_err_eof); /* Skip the comment start character. */ if ( reader_getc( r ) == EOF ) return 0; /* Read the input until a comm_stop is reached. */ while ( r->c != EOF && !reader_iscomm_stop( r , r->c ) ) { /* Get the next char. */ k += 1; reader_getc( r ); } /* Read comment into buffer. */ /* Read the next char. */ reader_getc( r ); /* Return the comment length. */ return k; }
/* Load into buffer until character, ignoring escaped ones. */ static int buf_read (reader_t * r, char *halt) { int esc = 0; int c = reader_getc (r); esc = 0; if (c == '\\') { c = reader_getc (r); esc = 1; } while ((esc || strchr (halt, c) == NULL) && (c != EOF)) { buf_append (r, c); c = reader_getc (r); esc = 0; if (c == '\\') { c = reader_getc (r); esc = 1; } } reader_putc (r, c); return !esc; }
/* Read a single sexp from the reader. */ object_t *read_sexp (reader_t * r) { /* Check for a shebang line. */ if (r->shebang == -1) { char str[2]; str[0] = reader_getc (r); str[1] = reader_getc (r); if (str[0] == '#' && str[1] == '!') { /* Looks like a she-bang line. */ r->shebang = 1; consume_line (r); } else { r->shebang = 0; reader_putc (r, str[1]); reader_putc (r, str[0]); } } r->done = 0; r->error = 0; push (r); print_prompt (r); while (!r->eof && !r->error && (list_empty (r) || stack_height (r) > 1)) { int nc, c = reader_getc (r); switch (c) { case EOF: r->eof = 1; break; /* Comments */ case ';': consume_line (r); break; /* Dotted pair */ case '.': nc = reader_getc (r); if (strchr (" \t\r\n()", nc) != NULL) { if (r->state->dotpair_mode > 0) read_error (r, "invalid dotted pair syntax"); else if (r->state->vector_mode > 0) read_error (r, "dotted pair not allowed in vector"); else { r->state->dotpair_mode = 1; reader_putc (r, nc); } } else { /* Turn it into a decimal point. */ reader_putc (r, nc); reader_putc (r, '.'); reader_putc (r, '0'); } break; /* Whitespace */ case '\n': r->linecnt++; print_prompt (r); case ' ': case '\t': case '\r': break; /* Parenthesis */ case '(': push (r); break; case ')': if (r->state->quote_mode) read_error (r, "unbalanced parenthesis"); else if (r->state->vector_mode) read_error (r, "unbalanced brackets"); else addpop (r); break; /* Vectors */ case '[': push (r); r->state->vector_mode = 1; break; case ']': if (r->state->quote_mode) read_error (r, "unbalanced parenthesis"); else if (!r->state->vector_mode) read_error (r, "unbalanced brackets"); else addpop (r); break; /* Quoting */ case '\'': push (r); add (r, quote); if (!r->error) r->state->quote_mode = 1; break; /* strings */ case '"': buf_read (r, "\""); add (r, parse_str (r)); reader_getc (r); /* Throw away other quote. */ break; /* numbers and symbols */ default: buf_append (r, c); buf_read (r, " \t\r\n()[];"); object_t *o = parse_atom (r); if (!r->error) add (r, o); break; } } if (!r->eof && !r->error) consume_whitespace (r); if (r->error) return err_symbol; /* Check state */ r->done = 1; if (stack_height (r) > 1 || r->state->quote_mode || r->state->dotpair_mode == 1) { read_error (r, "premature end of file"); return err_symbol; } if (list_empty (r)) { obj_destroy (pop (r)); return NIL; } object_t *wrap = pop (r); object_t *sexp = UPREF (CAR (wrap)); obj_destroy (wrap); return sexp; }
int reader_init ( struct reader *r , int fd , char *ws , char *comm_start , char *comm_stop , int buffsize ) { /* Check inputs. */ if ( r == NULL ) return error(r,reader_err_null); /* Init the flags. */ r->flags = reader_flag_none; /* Set the file. */ r->fd = fd; /* Init the buffer. */ if ( ( r->buff = (char *)malloc( buffsize ) ) == NULL ) return error(r,reader_err_malloc); r->first = 0; r->last = 0; r->size = buffsize; /* Re-set the line and column counts. */ r->line = 1; r->col = 0; /* Read the first character. */ if ( reader_getc( r ) == EOF ) r->flags = reader_flag_eof; else r->flags |= reader_flag_ready; /* Did the user supply whitespace? */ if ( ws != NULL ) { r->ws = ws; for ( r->nr_ws = 0 ; ws[r->nr_ws] != 0 ; r->nr_ws++ ); } else { r->ws = " \f\n\r\t\v"; r->nr_ws = 6; } /* Did the user supply comment start/stop? */ if ( comm_start != NULL ) { r->comm_start = comm_start; for ( r->nr_comm_start = 0 ; comm_start[r->nr_comm_start] != 0 ; r->nr_comm_start++ ); } else { r->comm_start = ""; r->nr_comm_start = 0; } if ( comm_stop != NULL ) { r->comm_stop = comm_stop; for ( r->nr_comm_stop = 0 ; comm_stop[r->nr_comm_stop] != 0 ; r->nr_comm_stop++ ); } else { r->comm_stop = "\n\r"; r->nr_comm_stop = 2; } /* We're all set. */ return reader_err_ok; }
int reader_gettoken ( struct reader *r , char *buff , int buff_size ) { int k = 0; /* Check inputs. */ if ( r == NULL || buff == NULL ) return error(r,reader_err_null); /* Has an EOF already been reached? */ if ( r->flags & reader_flag_eof ) return error(r,reader_err_eof); /* Skim-off whitespace and/or comments. */ while ( 1 ) { /* Skip whitespace. */ if ( reader_isws( r , r->c ) ) { if ( reader_getc( r ) == EOF ) return error(r,reader_err_eof); } /* Skip comments. */ else if ( reader_iscomm_start( r , r->c ) ) { do { if ( reader_getc( r ) == EOF ) return error(r,reader_err_eof); } while ( !reader_iscomm_stop( r , r->c ) ); if ( reader_getc( r ) == EOF ) return error(r,reader_err_eof); } else break; } /* get ws and comments. */ /* Read the token. */ while ( r->c != EOF && !reader_isws( r , r->c ) && !reader_iscomm_start( r , r->c ) ) { /* Check buffer length. */ if ( k < buff_size-1 ) { /* Store the current char to the buff. */ buff[k] = r->c; k += 1; /* Get the next char. */ reader_getc( r ); } else return error(r,reader_err_buff); } /* Read the token. */ /* Terminate the token. */ buff[k] = 0; /* Return the token length. */ return k; }