FreeCalypso > hg > freecalypso-reveng
view dspanal/charparse.c @ 382:4307b57229d3
miscprog: tone-convert written, compiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 10 Nov 2021 00:04:12 +0000 |
parents | f8344bc4fd61 |
children |
line wrap: on
line source
/* * 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; }