void makeMacro() { STRINGLIST *q; char *t; if (_tcschr(name, '$')) { // expand name q = macros; t = expandMacros(name, ¯os); // name holds result if (!*t) // error if macro to left of = is undefined makeError(currentLine, SYNTAX_NO_MACRO_NAME); while ((macros = q)) { q = q->next; FREE_STRINGLIST(macros); } FREE(name); name = t; } for (t = name; *t && MACRO_CHAR(*t); t = _tcsinc (t)) // Check for illegal chars ; if (*t) makeError(currentLine, SYNTAX_BAD_CHAR, *t); fInheritUserEnv = (BOOL)TRUE; // Put Env Var in Env & macros in table. if (!putMacro(name, string, 0)) { FREE(name); FREE(string); } name = string = NULL; }
BOOL defineMacro( char *s, // commandline or env definitions char *t, UCHAR flags ) { char *u; for (u = s; *u && MACRO_CHAR(*u); u = _tcsinc(u)) // check for illegal ; if (*u) { if (ON(flags, M_ENVIRONMENT_DEF)) { // ignore bad macros return(FALSE); } makeError(currentLine, SYNTAX_BAD_CHAR, *u); // chars, bad syntax } return(putMacro(s, t, flags)); // put macro in table }
void getName( char *s, char *end // pts to end of s ) { int c; UCHAR state; UCHAR input=DEFAULT_; BOOL seenBackSlash = FALSE; BOOL fQuoted = FALSE; char *beg = s - 1; BOOL parsechar; // flag to examine char. type switch (*(s-1)) { case '$': state = (UCHAR) 2; break; case '{': state = (UCHAR) 8; break; case '"': fQuoted = TRUE; state = (UCHAR)16; break; default: state = (UCHAR) 0; break; } for (;;) { c = lgetc(); parsechar = 1; // Default is examine char. if (c == ESCH) { c = lgetc(); switch (c) { case '{': // Special characters; must case '}': // not elide esch from string case '(': case ')': case '$': case ESCH: *s++ = ESCH; case '#': // elide esch right now! case '\n': case '\\': input = DEFAULT_; parsechar = 0; // DON'T examine character break; default: break; // DO examine character. } } if (parsechar) { switch (c) { case '#' : input = COMMENT_; break; case '=' : input = EQUALS_; break; case ';' : input = SEMICOLON_; break; case ':' : input = COLON_; break; case '$' : input = DOLLAR_; break; case '(' : input = OPENPAREN_; break; case ')' : input = CLOSEPAREN_; break; case '{' : input = OPENCURLY_; break; case '}' : input = CLOSECURLY_; break; case ' ' : case '\t': input = (UCHAR)((fQuoted) ? DEFAULT_ : WHITESPACE_); break; case '\n': case EOF : input = NEWLINE_; break; case '\\': input = BKSLSH_; break; case '"' : input = QUOTE_; if (state == 18) { // found a quote after a path list {...} // handle as quoted name fQuoted = 1; } break; // Add support for $* and $@ on the dependency line default : if (ON(actionFlags, A_DEPENDENT)) input = (UCHAR)((MACRO_CHAR(c) || c == '*' || c == '@') ?MACROCHAR_:DEFAULT_); else input = (UCHAR)(MACRO_CHAR(c)?MACROCHAR_:DEFAULT_); break; } } state = nameStates[state][input]; // Cheat lex table to think that you are handling quoted string case if (fQuoted && state == 1) state = 16; // seenBackSlash is used to provide lookahead when \ is seen on a // dependency line if (seenBackSlash) // if \ followed by \n then use it as a continuation if (input == NEWLINE_) { ++line; colZero = TRUE; c = lgetc(); colZero = FALSE; if (WHITESPACE(c)) { state = OK; do { c = lgetc(); } while (WHITESPACE(c)); } else state = (UCHAR)((s == buf + 1) ? BEG : DEF); } else *s++ = '\\'; seenBackSlash = FALSE; if (s >= end) makeError(line,NAME_TOO_LONG); if (state == OK) { UngetTxtChr(c,file); *s = '\0'; removeTrailChars(beg); return; } else if (ON(state,ERROR_MASK)) makeError(line,(state&~ERROR_MASK)+FATAL_ERR,c); if (state == BKS) { seenBackSlash = TRUE; //set lookahead flag } else *s++ = (char) c; } }
void getString( UCHAR type, // build string or macro value? char *s, char *end ) { int c; // buffer UCHAR state; UCHAR input = DEFAULT_; int tempC; unsigned size=0; // whenever state char *begin; // is 0, we're in // column zero BOOL parsechar; // flag to examine char. type BOOL inQuotes = (BOOL) FALSE; // flag when inside quote marks begin = s; c = lgetc(); if (type == STRING) state = (UCHAR) 2; else if (WHITESPACE(c)) { state = (UCHAR) 2; c = skipWhiteSpace(FROMLOCAL); } else if (c == ESCH) { c = lgetc(); if (WHITESPACE(c)) { state = (UCHAR) 2; c = skipWhiteSpace(FROMLOCAL); } else { UngetTxtChr(c, file); state = (UCHAR) 1; // default state c = ESCH; } } else state = (UCHAR) 1; // default state for (;;c = lgetc()) { if (c == '\"') inQuotes = (BOOL) !inQuotes; parsechar = 1; // Default is examine character. if (c == ESCH && !inQuotes && type == VALUE) { c = lgetc(); switch (c) { case '$': case ESCH: // Special characters; must case '{': case '}': // not elide esch from string case '(': case ')': case '!': case '-': case '@': *s++ = ESCH; if (s == end) { if (string == NULL) { // Increase size of s string = (char *) allocate(MAXBUF<<1); _tcsncpy(string,begin,MAXBUF); s = string + MAXBUF; size = MAXBUF << 1; end = string + size; } else { if ((size + MAXBUF < size) // overflow error || !(string = (char *) REALLOC(string,size+MAXBUF))) makeError(line, MACRO_TOO_LONG); s = string + size; size += MAXBUF; end = string + size; } begin = string; } case '#': case '\n': // elide esch right now! case '\\': case '\"': input = DEFAULT_; parsechar = 0; // DON'T examine character break; default: break; // DO examine character. } } else if (c == ESCH) { c = lgetc(); UngetTxtChr(c, file); c = ESCH; } if (parsechar) { switch (c) { case '#': input = COMMENT_; break; case '=': input = EQUALS_; break; case ':': input = COLON_; break; case '$': input = DOLLAR_; break; case '(': input = OPENPAREN_; break; case ')': input = CLOSEPAREN_; break; case '\\': input = BACKSLASH_; break; case '\n': case EOF: input = NEWLINE_; break; case ' ': case '\t': input = WHITESPACE_; break; case '*': input = STAR_; break; case '@': case '<': case '?': input = SPECIAL1_; break; case 'F': case 'D': case 'B': case 'R': input = SPECIAL2_; break; case ';': input = (UCHAR) (!state && init ? COMMENT_ : DEFAULT_); break; /* Handle comments in tools.ini */ default: input = (UCHAR) (MACRO_CHAR(c) ? MACROCHAR_:DEFAULT_); break; } } if (input == SPECIAL1_ && type == STRING && c == '<') { if ((tempC = lgetc()) == '<') { // << means start s = makeInlineFiles(s, &begin, &end); // an inline file input = NEWLINE_; c = '\n'; line--; // adding a '\n', we need to remove a line to compensate } else { UngetTxtChr(tempC,file); } state = stringStates[state][input]; } else if (input == COMMENT_) { // Handle comments if (!state) { inQuotes = (BOOL) FALSE; skipComments(FROMLOCAL); ++line; continue; } else if (type == VALUE) state = OK; // don't elide from command else state = stringStates[state][input]; } else state = stringStates[state][input]; if (state == OK) { // Accept end of string inQuotes = (BOOL) FALSE; UngetTxtChr(c,file); // Strip trailing whitespace from string. Easier to do it here, // else we have to treat a multi-string value (OBJS=a b c) as // separate tokens. while (s > begin && _istspace(s[-1])) --s; *s = '\0'; if (string) { if ((s = (char *) REALLOC(string, (size_t) (s - string + 1)))) string = s; } else string = makeString(begin); return; } else if (ON(state,ERROR_MASK)) // Error code from table makeError(line,(state&~ERROR_MASK)+FATAL_ERR,c); if (!state) { // Col 0; we just hit \nl *--s = ' '; // so treat it like white- ++s; ++line; // space; overwrite the colZero = TRUE; // backslash with a space. c = lgetc(); colZero = FALSE; if (WHITESPACE(c)) { state = 2; do { c = lgetc(); } while (WHITESPACE(c)); } UngetTxtChr(c,file); } else { // Keep storing string *s++ = (char) c; if (s == end) { if (!string) { // Increase size of s string = (char *) allocate(MAXBUF<<1); _tcsncpy(string,begin,MAXBUF); s = string + MAXBUF; size = MAXBUF << 1; end = string + size; } else { if ((size + MAXBUF < size) // overflow error || !(string = (char *) REALLOC(string,size+MAXBUF))) makeError(line, MACRO_TOO_LONG); s = string + size; size += MAXBUF; end = string + size; } } } } }