mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 19:43:32 +00:00
128 lines
4.2 KiB
C
128 lines
4.2 KiB
C
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||
|
│ │
|
||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||
|
│ │
|
||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||
|
#include "libc/stdio/stdio.h"
|
||
|
#include "libc/str/str.h"
|
||
|
|
||
|
static bool isoctal(char c) {
|
||
|
return '0' <= c && c <= '7';
|
||
|
}
|
||
|
|
||
|
char *U(char *p) {
|
||
|
int c, i = 0, j = 0;
|
||
|
for (;;) {
|
||
|
switch ((c = p[i++] & 255)) {
|
||
|
case '\\':
|
||
|
switch ((c = p[i++] & 255)) {
|
||
|
case '0':
|
||
|
case '1':
|
||
|
case '2':
|
||
|
case '3':
|
||
|
case '4':
|
||
|
case '5':
|
||
|
case '6':
|
||
|
case '7':
|
||
|
if (isoctal(p[i])) {
|
||
|
if (isoctal(p[i + 1])) {
|
||
|
p[j++] = (c - '0') << 6 | (p[i] - '0') << 3 | (p[i + 1] - '0');
|
||
|
i += 2;
|
||
|
continue;
|
||
|
} else {
|
||
|
p[j++] = (c - '0') << 3 | (p[i++] - '0');
|
||
|
continue;
|
||
|
}
|
||
|
} else {
|
||
|
p[j++] = (c - '0');
|
||
|
continue;
|
||
|
}
|
||
|
case '\\':
|
||
|
p[j++] = '\\';
|
||
|
continue;
|
||
|
case 'a':
|
||
|
p[j++] = '\a';
|
||
|
continue;
|
||
|
case 'b':
|
||
|
p[j++] = '\b';
|
||
|
continue;
|
||
|
case 't':
|
||
|
p[j++] = '\t';
|
||
|
continue;
|
||
|
case 'f':
|
||
|
p[j++] = '\f';
|
||
|
continue;
|
||
|
case 'v':
|
||
|
p[j++] = '\v';
|
||
|
continue;
|
||
|
case 'e':
|
||
|
p[j++] = '\e';
|
||
|
continue;
|
||
|
case 'r':
|
||
|
p[j++] = '\r';
|
||
|
continue;
|
||
|
case 'n':
|
||
|
p[j++] = '\n';
|
||
|
continue;
|
||
|
case '"':
|
||
|
p[j++] = '"';
|
||
|
continue;
|
||
|
case '\'':
|
||
|
p[j++] = '\'';
|
||
|
continue;
|
||
|
}
|
||
|
// fallthrough
|
||
|
default:
|
||
|
p[j++] = c;
|
||
|
break;
|
||
|
case '\0':
|
||
|
p[j] = 0;
|
||
|
return p;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[]) {
|
||
|
switch (argc) {
|
||
|
case 2:
|
||
|
printf(U(argv[1]));
|
||
|
return 0;
|
||
|
case 3:
|
||
|
printf(U(argv[1]), argv[2]);
|
||
|
return 0;
|
||
|
case 4:
|
||
|
printf(U(argv[1]), argv[2], argv[3]);
|
||
|
return 0;
|
||
|
case 5:
|
||
|
printf(U(argv[1]), argv[2], argv[3], argv[4]);
|
||
|
return 0;
|
||
|
case 6:
|
||
|
printf(U(argv[1]), argv[2], argv[3], argv[4], argv[5]);
|
||
|
return 0;
|
||
|
case 7:
|
||
|
printf(U(argv[1]), argv[2], argv[3], argv[4], argv[5], argv[6]);
|
||
|
return 0;
|
||
|
case 8:
|
||
|
printf(U(argv[1]), argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
|
||
|
return 0;
|
||
|
default:
|
||
|
if (argc > 0) {
|
||
|
fprintf(stderr, "%s: %s format [arguments]\n", argv[0], argv[0]);
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
}
|