FreeCalypso > hg > freecalypso-tools
view ffstools/tiaud/compile.c @ 465:003e48f8ebe1
rvinterf/etmsync/fsnew.c: cast 0 to (char *) for execl sentinel
I generally don't use NULL and use plain 0 instead, based on a "NULL
considered harmful" discussion on the classiccmp mailing list many aeons
ago (I couldn't find it, and I reason that it must have been 2005 or
earlier), but a recent complaint by a packager sent me searching, and I
found this:
https://ewontfix.com/11/
While I don't give a @#$% about "modern" systems and code-nazi tools,
I realized that passing a plain 0 as a pointer sentinel in execl is wrong
because it will break on systems where pointers are longer than the plain
int type. Again, I don't give a @#$% about the abomination of x86_64 and
the like, but if anyone ever manages to port my code to something like a
PDP-11 (16-bit int, 32-bit long and pointers), then passing a plain 0
as a function argument where a pointer is expected most definitely won't
work: if the most natural stack slot and SP alignment unit is 16 bits,
fitting an int, with longs and pointers taking up two such slots, then
the call stack will be totally wrong with a plain 0 passed for a pointer.
Casting the 0 to (char *) ought to be the most kosher solution for the
most retro systems possible.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 11 Feb 2019 00:00:19 +0000 |
parents | 2abc086b13ed |
children | c458e33060bf |
line wrap: on
line source
/* * This utility compiles a TI audio mode config file from our ASCII source * format into the binary for uploading into Calypso device FFS. */ #include <sys/types.h> #include <sys/file.h> #include <ctype.h> #include <string.h> #include <strings.h> #include <stdio.h> #include <stdint.h> #include <endian.h> #include <stdlib.h> #include <unistd.h> #include "binstruct.h" struct audio_cfg_bin bin; char *infname; FILE *inf; int lineno; init_nonzero_defaults() { bin.mic_bytes[0] = 3; bin.mic_fir[0] = 0x4000; bin.speaker_fir[0] = 0x4000; bin.sidetone_gain = -5; } static long strtol_wrap(arg) char *arg; { char *endptr; long ret; ret = strtol(arg, &endptr, 0); if (*endptr) { fprintf(stderr, "%s line %d: \"%s\" is not a valid number\n", infname, lineno, arg); exit(1); } return(ret); } static void mic_gain_setting(args) char *args; { char *cp, *np; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: mic gain setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: mic gain setting takes only one argument\n", infname, lineno); exit(1); } bin.mic_bytes[0] = strtol_wrap(np); } static void mic_extra_gain_setting(args) char *args; { char *cp, *np; if (bin.mic_mode != AUDIO_MICROPHONE_HANDFREE) { fprintf(stderr, "%s line %d: mic extra-gain setting is only valid in aux mode\n", infname, lineno); exit(1); } for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: mic extra-gain setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: mic extra-gain setting takes only one argument\n", infname, lineno); exit(1); } bin.mic_bytes[1] = strtol_wrap(np); } static void mic_output_bias_setting(args) char *args; { char *cp, *np; int idx; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: mic output-bias setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: mic output-bias setting takes only one argument\n", infname, lineno); exit(1); } if (bin.mic_mode != AUDIO_MICROPHONE_HANDFREE) idx = 1; else idx = 2; bin.mic_bytes[idx] = strtol_wrap(np); } static void mic_fir_setting(args) char *args; { char *cp, *np; int idx, start_idx; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { missing_arg: fprintf(stderr, "%s line %d: mic fir setting requires two or more arguments\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; start_idx = strtol_wrap(np); if (start_idx < 0 || start_idx > 30) { fprintf(stderr, "%s line %d: FIR coefficient number must be between 0 and 30\n", infname, lineno); exit(1); } for (idx = start_idx; ; idx++) { while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') { if (idx == start_idx) goto missing_arg; break; } if (idx > 30) { fprintf(stderr, "%s line %d: spill past FIR coefficient 30\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; bin.mic_fir[idx] = htole16(strtol_wrap(np)); } } static void mic_head_line(args) char *args; { char linebuf[512]; char *cp, *np; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: mic setting requires a mode argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(np, "default")) bin.mic_mode = AUDIO_MICROPHONE_HANDHELD; else if (!strcmp(np, "aux")) bin.mic_mode = AUDIO_MICROPHONE_HANDFREE; else if (!strcmp(np, "headset")) bin.mic_mode = AUDIO_MICROPHONE_HEADSET; else { fprintf(stderr, "%s line %d: unknown mic mode \"%s\"\n", infname, lineno, np); exit(1); } while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') return; if (*cp != '{') { fprintf(stderr, "%s line %d: invalid syntax on the mic head line\n", infname, lineno); exit(1); } for (;;) { if (!fgets(linebuf, sizeof linebuf, inf)) { fprintf(stderr, "%s: unexpected EOF in mic section\n", infname); exit(1); } lineno++; for (cp = linebuf; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') continue; for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(np, "gain")) mic_gain_setting(cp); else if (!strcmp(np, "extra-gain")) mic_extra_gain_setting(cp); else if (!strcmp(np, "output-bias")) mic_output_bias_setting(cp); else if (!strcmp(np, "fir")) mic_fir_setting(cp); else if (!strcmp(np, "}")) break; else { fprintf(stderr, "%s line %d: unknown mic setting \"%s\"\n", infname, lineno, np); exit(1); } } } static void speaker_gain_setting(args) char *args; { char *cp, *np; if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { fprintf(stderr, "%s line %d: speaker gain setting is not valid in buzzer mode\n", infname, lineno); exit(1); } for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: speaker gain setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: speaker gain setting takes only one argument\n", infname, lineno); exit(1); } bin.speaker_bytes[0] = strtol_wrap(np); } static void speaker_audio_filter_setting(args) char *args; { char *cp, *np; if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { fprintf(stderr, "%s line %d: speaker audio-filter setting is not valid in buzzer mode\n", infname, lineno); exit(1); } for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: speaker audio-filter setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: speaker audio-filter setting takes only one argument\n", infname, lineno); exit(1); } bin.speaker_bytes[1] = strtol_wrap(np); } static void speaker_fir_setting(args) char *args; { char *cp, *np; int idx, start_idx; if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { fprintf(stderr, "%s line %d: speaker fir setting is not valid in buzzer mode\n", infname, lineno); exit(1); } for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { missing_arg: fprintf(stderr, "%s line %d: speaker fir setting requires two or more arguments\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; start_idx = strtol_wrap(np); if (start_idx < 0 || start_idx > 30) { fprintf(stderr, "%s line %d: FIR coefficient number must be between 0 and 30\n", infname, lineno); exit(1); } for (idx = start_idx; ; idx++) { while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') { if (idx == start_idx) goto missing_arg; break; } if (idx > 30) { fprintf(stderr, "%s line %d: spill past FIR coefficient 30\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; bin.speaker_fir[idx] = htole16(strtol_wrap(np)); } } static void speaker_activate_setting(args) char *args; { char *cp, *np; if (bin.speaker_mode != AUDIO_SPEAKER_BUZZER) { fprintf(stderr, "%s line %d: speaker activate setting is only valid in buzzer mode\n", infname, lineno); exit(1); } for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: speaker activate setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: speaker activate setting takes only one argument\n", infname, lineno); exit(1); } bin.speaker_bytes[0] = strtol_wrap(np); } static void speaker_head_line(args) char *args; { char linebuf[512]; char *cp, *np; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: speaker setting requires a mode argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(np, "ear")) bin.speaker_mode = AUDIO_SPEAKER_HANDHELD; else if (!strcmp(np, "aux")) bin.speaker_mode = AUDIO_SPEAKER_HANDFREE; else if (!strcmp(np, "headset")) bin.speaker_mode = AUDIO_SPEAKER_HEADSET; else if (!strcmp(np, "buzzer")) bin.speaker_mode = AUDIO_SPEAKER_BUZZER; else if (!strcmp(np, "ear+aux")) bin.speaker_mode = AUDIO_SPEAKER_HANDHELD_HANDFREE; else { fprintf(stderr, "%s line %d: unknown speaker mode \"%s\"\n", infname, lineno, np); exit(1); } while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') return; if (*cp != '{') { fprintf(stderr, "%s line %d: invalid syntax on the speaker head line\n", infname, lineno); exit(1); } for (;;) { if (!fgets(linebuf, sizeof linebuf, inf)) { fprintf(stderr, "%s: unexpected EOF in speaker section\n", infname); exit(1); } lineno++; for (cp = linebuf; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') continue; for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(np, "gain")) speaker_gain_setting(cp); else if (!strcmp(np, "audio-filter")) speaker_audio_filter_setting(cp); else if (!strcmp(np, "fir")) speaker_fir_setting(cp); else if (!strcmp(np, "activate")) speaker_activate_setting(cp); else if (!strcmp(np, "}")) break; else { fprintf(stderr, "%s line %d: unknown speaker setting \"%s\"\n", infname, lineno, np); exit(1); } } } static void voice_path_setting(args) char *args; { char *cp, *np; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: voice-path setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: voice-path setting takes only one argument\n", infname, lineno); exit(1); } bin.voice_path = strtol_wrap(np); } static void sidetone_setting(args) char *args; { char *cp, *np; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: sidetone setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: sidetone setting takes only one argument\n", infname, lineno); exit(1); } bin.sidetone_gain = strtol_wrap(np); } static void aec_setting(args) char *args; { char *cp, *np; int n; cp = args; for (n = 0; n < 5; n++) { while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') { argcount_err: fprintf(stderr, "%s line %d: aec setting takes 5 arguments\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; bin.aec_words[n] = htole16(strtol_wrap(np)); } while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') goto argcount_err; } read_input_main() { char linebuf[512]; char *cp, *np; for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) { for (cp = linebuf; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') continue; for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(np, "voice-path")) voice_path_setting(cp); else if (!strcmp(np, "mic")) mic_head_line(cp); else if (!strcmp(np, "speaker")) speaker_head_line(cp); else if (!strcmp(np, "sidetone")) sidetone_setting(cp); else if (!strcmp(np, "aec")) aec_setting(cp); else { fprintf(stderr, "%s line %d: unknown top-level setting \"%s\"\n", infname, lineno, np); exit(1); } } } write_bin_output(filename) char *filename; { int fd; fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0) { perror(filename); exit(1); } write(fd, &bin, sizeof bin); close(fd); } main(argc, argv) char **argv; { if (argc != 3) { fprintf(stderr, "usage: %s infile outfile\n", argv[0]); exit(1); } if (strcmp(argv[1], "-")) { infname = argv[1]; inf = fopen(infname, "r"); if (!inf) { perror(infname); exit(1); } } else { inf = stdin; infname = "stdin"; } init_nonzero_defaults(); read_input_main(); write_bin_output(argv[2]); exit(0); }