diff options
author | chin <none@none> | 2007-08-17 12:01:52 -0700 |
---|---|---|
committer | chin <none@none> | 2007-08-17 12:01:52 -0700 |
commit | da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968 (patch) | |
tree | 5280d3b78e289fe9551371ab6e7f15ef9944ea14 /usr/src/lib/libpp/common/ppbuiltin.c | |
parent | 073dbf9103ef2a2b05d8a16e2d26db04e0374b0e (diff) | |
download | illumos-joyent-da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968.tar.gz |
6437624 RFE: Add ksh93 (as /usr/bin/ksh93) and libshell.so to OS/Net
6505835 AST tools and library (libpp) required for creating l10n messages for ksh93
PSARC/2006/550 Korn Shell 93 Integration
PSARC/2006/587 /etc/ksh.kshrc for ksh93
PSARC/2007/035 ksh93 Amendments
Contributed by Roland Mainz <roland.mainz@nrubsig.org>
--HG--
rename : usr/src/lib/libcmd/common/mapfile-vers => deleted_files/usr/src/lib/libcmd/common/mapfile-vers
rename : usr/src/lib/libcmd/common/placeholder.c => deleted_files/usr/src/lib/libcmd/common/placeholder.c
Diffstat (limited to 'usr/src/lib/libpp/common/ppbuiltin.c')
-rw-r--r-- | usr/src/lib/libpp/common/ppbuiltin.c | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/usr/src/lib/libpp/common/ppbuiltin.c b/usr/src/lib/libpp/common/ppbuiltin.c new file mode 100644 index 0000000000..b9a906f657 --- /dev/null +++ b/usr/src/lib/libpp/common/ppbuiltin.c @@ -0,0 +1,397 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1986-2007 AT&T Knowledge Ventures * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Knowledge Ventures * +* * +* A copy of the License is available at * +* http://www.opensource.org/licenses/cpl1.0.txt * +* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * Glenn Fowler + * AT&T Research + * + * preprocessor builtin macro support + */ + +#include "pplib.h" + +#include <times.h> + +/* + * process a #(...) builtin macro call + * `#(' has already been seen + */ + +void +ppbuiltin(void) +{ + register int c; + register char* p; + register char* a; + + int n; + int op; + char* token; + char* t; + long number; + struct ppinstk* in; + struct pplist* list; + struct ppsymbol* sym; + Sfio_t* sp; + + number = pp.state; + pp.state |= DISABLE|FILEPOP|NOSPACE; + token = pp.token; + p = pp.token = pp.tmpbuf; + *(a = pp.args) = 0; + if ((c = pplex()) != T_ID) + { + error(2, "%s: #(<identifier>...) expected", p); + *p = 0; + } + switch (op = (int)hashget(pp.strtab, p)) + { + case V_DEFAULT: + n = 0; + p = pp.token = pp.valbuf; + if ((c = pplex()) == ',') + { + op = -1; + c = pplex(); + } + pp.state &= ~NOSPACE; + for (;;) + { + if (!c) + { + error(2, "%s in #(...) argument", pptokchr(c)); + break; + } + if (c == '(') n++; + else if (c == ')' && !n--) break; + else if (c == ',' && !n && op > 0) op = 0; + if (op) pp.token = pp.toknxt; + c = pplex(); + } + *pp.token = 0; + pp.token = token; + pp.state = number; + break; + case V_EMPTY: + p = pp.valbuf; + if ((c = pplex()) == ')') *p = '1'; + else + { + *p = '0'; + n = 0; + for (;;) + { + if (!c) + { + error(2, "%s in #(...) argument", pptokchr(c)); + break; + } + if (c == '(') n++; + else if (c == ')' && !n--) break; + c = pplex(); + } + } + *(p + 1) = 0; + pp.token = token; + pp.state = number; + break; + case V_ITERATE: + n = 0; + pp.token = pp.valbuf; + if ((c = pplex()) != T_ID || !(sym = ppsymref(pp.symtab, pp.token)) || !sym->macro || sym->macro->arity != 1 || (c = pplex()) != ',') + { + error(2, "#(%s <macro(x)>, ...) expected", p); + for (;;) + { + if (!c) + { + error(2, "%s in #(...) argument", pptokchr(c)); + break; + } + if (c == '(') n++; + else if (c == ')' && !n--) break; + c = pplex(); + } + *pp.valbuf = 0; + } + else while (c != ')') + { + p = pp.token; + if (pp.token > pp.valbuf) *pp.token++ = ' '; + STRCOPY(pp.token, sym->name, a); + *pp.token++ = '('; + if (!c || !(c = pplex())) + { + pp.token = p; + error(2, "%s in #(...) argument", pptokchr(c)); + break; + } + pp.state &= ~NOSPACE; + while (c) + { + if (c == '(') n++; + else if (c == ')' && !n--) break; + else if (c == ',' && !n) break; + pp.token = pp.toknxt; + c = pplex(); + } + *pp.token++ = ')'; + pp.state |= NOSPACE; + } + p = pp.valbuf; + pp.token = token; + pp.state = number; + break; + default: + pp.token = token; + while (c != ')') + { + if (!c) + { + error(2, "%s in #(...) argument", pptokchr(c)); + break; + } + if ((c = pplex()) == T_ID && !*a) + strcpy(a, pp.token); + } + pp.state = number; + switch (op) + { + case V_ARGC: + c = -1; + for (in = pp.in; in; in = in->prev) + if ((in->type == IN_MACRO || in->type == IN_MULTILINE) && (in->symbol->flags & SYM_FUNCTION)) + { + c = *((unsigned char*)(pp.macp->arg[0] - 2)); + break; + } + sfsprintf(p = pp.valbuf, MAXTOKEN, "%d", c); + break; + case V_BASE: + p = (a = strrchr(error_info.file, '/')) ? a + 1 : error_info.file; + break; + case V_DATE: + if (!(p = pp.date)) + { + time_t tm; + + time(&tm); + a = p = ctime(&tm) + 4; + *(p + 20) = 0; + for (p += 7; *p = *(p + 9); p++); + pp.date = p = strdup(a); + } + break; + case V_FILE: + p = error_info.file; + break; + case V_LINE: + sfsprintf(p = pp.valbuf, MAXTOKEN, "%d", error_info.line); + break; + case V_PATH: + p = pp.path; + break; + case V_SOURCE: + p = error_info.file; + for (in = pp.in; in->prev; in = in->prev) + if (in->prev->type == IN_FILE && in->file) + p = in->file; + break; + case V_STDC: + p = pp.valbuf; + p[0] = ((pp.state & (COMPATIBILITY|TRANSITION)) || (pp.mode & (HOSTED|HOSTEDTRANSITION)) == (HOSTED|HOSTEDTRANSITION)) ? '0' : '1'; + p[1] = 0; + break; + case V_TIME: + if (!(p = pp.time)) + { + time_t tm; + + time(&tm); + p = ctime(&tm) + 11; + *(p + 8) = 0; + pp.time = p = strdup(p); + } + break; + case V_VERSION: + p = (char*)pp.version; + break; + case V_DIRECTIVE: + pp.state |= NEWLINE; + pp.mode |= RELAX; + strcpy(p = pp.valbuf, "#"); + break; + case V_GETENV: + if (!(p = getenv(a))) p = ""; + break; + case V_GETMAC: + p = (sym = pprefmac(a, REF_NORMAL)) ? sym->macro->value : ""; + break; + case V_GETOPT: + sfsprintf(p = pp.valbuf, MAXTOKEN, "%ld", ppoption(a)); + break; + case V_GETPRD: + p = (list = (struct pplist*)hashget(pp.prdtab, a)) ? list->value : ""; + break; + case V__PRAGMA: + if ((c = pplex()) == '(') + { + number = pp.state; + pp.state |= NOSPACE|STRIP; + c = pplex(); + pp.state = number; + if (c == T_STRING || c == T_WSTRING) + { + if (!(sp = sfstropen())) + error(3, "temporary buffer allocation error"); + sfprintf(sp, "#%s %s\n", dirname(PRAGMA), pp.token); + a = sfstruse(sp); + if ((c = pplex()) == ')') + { + pp.state |= NEWLINE; + PUSH_BUFFER(p, a, 1); + } + sfstrclose(sp); + } + } + if (c != ')') + error(2, "%s: (\"...\") expected", p); + return; + case V_FUNCTION: + +#define BACK(a,p) ((a>p)?*--a:(number++?0:((p=pp.outbuf+PPBUFSIZ),(a=pp.outbuf+2*PPBUFSIZ),*--a))) +#define PEEK(a,p) ((a>p)?*(a-1):(number?0:*(pp.outbuf+2*PPBUFSIZ-1))) + + number = pp.outbuf == pp.outb; + a = pp.outp; + p = pp.outb; + op = 0; + while (c = BACK(a, p)) + { + if (c == '"' || c == '\'') + { + op = 0; + while ((n = BACK(a, p)) && n != c || PEEK(a, p) == '\\'); + } + else if (c == '\n') + { + token = a; + while (c = BACK(a, p)) + if (c == '\n') + { + a = token; + break; + } + else if (c == '#' && PEEK(a, p) == '\n') + break; + } + else if (c == ' ') + /*ignore*/; + else if (c == '{') /* '}' */ + op = 1; + else if (op == 1) + { + if (c == ')') + { + op = 2; + n = 1; + } + else + op = 0; + } + else if (op == 2) + { + if (c == ')') + n++; + else if (c == '(' && !--n) + op = 3; + } + else if (op == 3) + { + if (ppisidig(c)) + { + for (t = p, token = a; ppisidig(PEEK(a, p)); a--); + for (p = pp.valbuf + 1; a <= token; *p++ = *a++); + *p = 0; + p = pp.valbuf + 1; + if (streq(p, "for") || streq(p, "if") || streq(p, "switch") || streq(p, "while")) + { + op = 0; + p = t; + continue; + } + } + else + op = 0; + break; + } + } + if (op == 3) + strncpy(pp.funbuf, p, sizeof(pp.funbuf) - 1); + else if (*pp.funbuf) + p = pp.funbuf; + else + p = "__FUNCTION__"; + break; + default: + if (pp.builtin && (a = (*pp.builtin)(pp.valbuf, p, a))) + p = a; + break; + } + break; + } + if (strchr(p, MARK)) + { + a = pp.tmpbuf; + strcpy(a, p); + c = p != pp.valbuf; + p = pp.valbuf + c; + for (;;) + { + if (p < pp.valbuf + MAXTOKEN - 2) + switch (*p++ = *a++) + { + case 0: + break; + case MARK: + *p++ = MARK; + /*FALLTHROUGH*/ + default: + continue; + } + break; + } + p = pp.valbuf + c; + } + if (p == pp.valbuf) + PUSH_STRING(p); + else + { + if (p == pp.valbuf + 1) + *pp.valbuf = '"'; + else + { + if (strlen(p) > MAXTOKEN - 2) + error(1, "%-.16s: builtin value truncated", p); + sfsprintf(pp.valbuf, MAXTOKEN, "\"%-.*s", MAXTOKEN - 2, p); + } + PUSH_QUOTE(pp.valbuf, 1); + } +} |