FreeCalypso > hg > freecalypso-reveng
diff dspanal/charparse.c @ 308:f8344bc4fd61
dspanal: char2coff utility written, compiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 28 Oct 2019 05:20:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dspanal/charparse.c Mon Oct 28 05:20:50 2019 +0000 @@ -0,0 +1,297 @@ +/* + * This module reads C char array files; it will be linked into programs + * that do further processing. + */ + +#include <sys/types.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +/* lexer tokens */ +#define WORD 256 +#define NUMBER 257 +#define HEXBYTE 258 + +/* limits */ +#define MAXWORD 63 +#define MAXDIGITS 5 + +static char *parser_filename; +static FILE *parser_readF; +static int parser_lineno; +static char parser_read_word[MAXWORD+1]; +static int parser_read_number; + +static void +parse_error(msg) + char *msg; +{ + fprintf(stderr, "%s line %d: %s\n", parser_filename, parser_lineno, + msg); + exit(1); +} + +static +my_getchar() +{ + register int c; + + c = getc(parser_readF); + if (c < 0) + return(c); + if (!isascii(c)) + parse_error("non-ASCII character"); + if (iscntrl(c) && c != '\n' && c != '\t') + parse_error("invalid control character"); + return(c); +} + +static void +handle_trad_comment() +{ + register int c, flag; + + for (flag = 0; ; ) { + c = my_getchar(); + if (c < 0) + parse_error("/* comment ends in EOF"); + if (c == '\n') + parser_lineno++; + if (c == '/' && flag) + return; + flag = (c == '*'); + } +} + +static void +handle_line_comment() +{ + register int c; + + for (;;) { + c = my_getchar(); + if (c < 0) + parse_error("// comment ends in EOF"); + if (c == '\n') { + parser_lineno++; + return; + } + } +} + +static void +handle_comment() +{ + int c; + + c = my_getchar(); + switch (c) { + case '*': + /* traditional C comment style */ + handle_trad_comment(); + return; + case '/': + /* new-fangled double slash comment style */ + handle_line_comment(); + return; + default: + parse_error("character after '/' is not '*' or '/'"); + exit(1); + } +} + +static void +handle_num_token(first_digit) +{ + register int c, n; + + parser_read_number = first_digit - '0'; + for (n = 1; ; n++) { + c = my_getchar(); + if (!isdigit(c)) + break; + parser_read_number *= 10; + parser_read_number += c - '0'; + } + if (c >= 0) { + if (isalpha(c) || c == '_') + parse_error( + "digits followed by letters: neither word nor number"); + ungetc(c, parser_readF); + } + if (n > MAXDIGITS) + parse_error("number is too long (MAXDIGITS exceeded)"); +} + +static int +decode_hex_digit(c) + register int c; +{ + if (isdigit(c)) + return(c - '0'); + else if (isupper(c)) + return(c - 'A' + 10); + else + return(c - 'a' + 10); +} + +static void +handle_hex_token() +{ + register int c, n; + + c = my_getchar(); + if (c != 'x' && c != 'X') + parse_error("\'0\' not followed by \'x\'"); + parser_read_number = 0; + for (n = 0; n < 2; n++) { + c = my_getchar(); + if (!isxdigit(c)) + parse_error("0x not followed by two hex digits"); + parser_read_number <<= 4; + parser_read_number += decode_hex_digit(c); + } +} + +static void +handle_word_token(first_char) +{ + register int c; + register char *cp; + register int len; + + cp = parser_read_word; + *cp++ = first_char; + for (len = 1; ; ) { + c = my_getchar(); + if (!isalnum(c) && c != '_') + break; + if (len >= MAXWORD) + parse_error("text token is too long"); + *cp++ = c; + len++; + } + *cp = '\0'; + if (c < 0) + return; + ungetc(c, parser_readF); +} + +static int +get_token() +{ + register int c; + +loop: c = my_getchar(); + switch (c) { + case EOF: + return(0); + case ' ': + case '\t': + goto loop; + case '\n': + parser_lineno++; + goto loop; + case '/': + handle_comment(); + goto loop; + case ',': + case ';': + case '=': + case '[': + case ']': + case '{': + case '}': + return(c); + case '0': + handle_hex_token(); + return(HEXBYTE); + } + if (isdigit(c)) { + handle_num_token(c); + return(NUMBER); + } + if (isalpha(c) || c == '_') { + handle_word_token(c); + return(WORD); + } + fprintf(stderr, "%s line %d: bad character \'%c\'\n", parser_filename, + parser_lineno, c); + exit(1); +} + +unsigned +read_char_file(filename, outbuf, buflimit) + char *filename; + u_char *outbuf; + unsigned buflimit; +{ + register int t; + u_char *outptr; + unsigned bytecnt; + + parser_filename = filename; + parser_readF = fopen(parser_filename, "r"); + if (!parser_readF) { + perror(parser_filename); + exit(1); + } + parser_lineno = 1; + t = get_token(); + if (t != WORD || strcmp(parser_read_word, "const")) + parse_error("expected \"const\" keyword"); + t = get_token(); + if (t != WORD || strcmp(parser_read_word, "unsigned")) + parse_error("expected \"unsigned\" keyword"); + t = get_token(); + if (t != WORD || strcmp(parser_read_word, "char")) + parse_error("expected \"char\" keyword"); + t = get_token(); + if (t != WORD) + parse_error("expected char array name"); + t = get_token(); + if (t != '[') + parse_error("expected \'[\'"); + t = get_token(); + if (t == NUMBER) + t = get_token(); + if (t != ']') + parse_error("expected \']\'"); + t = get_token(); + if (t != '=') + parse_error("expected \'=\'"); + t = get_token(); + if (t != '{') + parse_error("expected \'{\'"); + /* get first hex byte */ + t = get_token(); + if (t != HEXBYTE) + parse_error("expected first hex byte"); + outptr = outbuf; + *outptr++ = parser_read_number; + bytecnt = 1; + for (;;) { + t = get_token(); + if (t == '}') + break; + if (t != ',') + parse_error("expected comma between bytes"); + t = get_token(); + if (t == '}') + break; + if (t != HEXBYTE) + parse_error("expected next hex byte"); + if (bytecnt >= buflimit) + parse_error("buffer limit exceeded"); + *outptr++ = parser_read_number; + bytecnt++; + } + t = get_token(); + if (t != ';') + parse_error("expected terminating \';\'"); + fclose(parser_readF); + return bytecnt; +}