static char * trim_quotes(char * arg) { switch (*arg) { case '"': case '\'': ao_string_cook(arg, NULL); } return arg; }
LOCAL void mungeString( char* pzTxt, tOptionLoadMode mode ) { char* pzE; if (mode == OPTION_LOAD_KEEP) return; if (isspace( (int)*pzTxt )) { char* pzS = pzTxt; char* pzD = pzTxt; while (isspace( (int)*++pzS )) ; while ((*(pzD++) = *(pzS++)) != NUL) ; pzE = pzD-1; } else pzE = pzTxt + strlen( pzTxt ); while ((pzE > pzTxt) && isspace( (int)pzE[-1] )) pzE--; *pzE = NUL; if (mode == OPTION_LOAD_UNCOOKED) return; switch (*pzTxt) { default: return; case '"': case '\'': break; } switch (pzE[-1]) { default: return; case '"': case '\'': break; } (void)ao_string_cook( pzTxt, NULL ); }
LOCAL void mungeString(char * txt, tOptionLoadMode mode) { char * pzE; if (mode == OPTION_LOAD_KEEP) return; if (IS_WHITESPACE_CHAR(*txt)) { char * pzS = SPN_WHITESPACE_CHARS(txt+1); size_t l = strlen(pzS) + 1; memmove(txt, pzS, l); pzE = txt + l - 1; } else pzE = txt + strlen(txt); pzE = SPN_WHITESPACE_BACK(txt, pzE); *pzE = NUL; if (mode == OPTION_LOAD_UNCOOKED) return; switch (*txt) { default: return; case '"': case '\'': break; } switch (pzE[-1]) { default: return; case '"': case '\'': break; } (void)ao_string_cook(txt, NULL); }
static tSuccess lex_backquote(void) { int line_no = pCurCtx->lineNo; char* pz = ao_string_cook(pCurCtx->pzScan, &line_no); if (pz == NULL) return FAILURE; pz_token = pCurCtx->pzScan; pCurCtx->pzScan = pz; lastToken = DP_EV_STRING; pz = runShell((char const*)pz_token); pCurCtx->lineNo = line_no; if (pz == NULL) return PROBLEM; TAGMEM(pz, "shell definition string"); pz_token = pz; manageAllocatedData(pz); return SUCCESS; }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LEXICAL SCANNER */ LOCAL te_dp_event yylex(void) { lastToken = DP_EV_INVALID; scanAgain: /* * Start the process of locating a token. * We branch here after skipping over a comment * or processing a directive (which may change our context). */ if (IS_WHITESPACE_CHAR(*pCurCtx->pzScan)) trim_whitespace(); switch (*pCurCtx->pzScan) { case NUL: /* * IF we are not inside an include context, * THEN go finish. */ if (pCurCtx->pCtx == NULL) goto lex_done; pop_context(); goto scanAgain; case '#': { extern char * processDirective(char*); char * pz = processDirective(pCurCtx->pzScan+1); /* * Ensure that the compiler doesn't try to save a copy of * "pCurCtx" in a register. It must be reloaded from memory. */ pCurCtx->pzScan = pz; goto scanAgain; } case '{': SET_LIT_TKN(O_BRACE); break; case '=': SET_LIT_TKN(EQ); break; case '}': SET_LIT_TKN(C_BRACE); break; case '[': SET_LIT_TKN(OPEN_BKT); break; case ']': SET_LIT_TKN(CLOSE_BKT); break; case ';': SET_LIT_TKN(SEMI); break; case ',': SET_LIT_TKN(COMMA); break; case '\'': case '"': { char* pz = ao_string_cook(pCurCtx->pzScan, &(pCurCtx->lineNo)); if (pz == NULL) goto NUL_error; pz_token = pCurCtx->pzScan; lastToken = DP_EV_STRING; pCurCtx->pzScan = pz; break; } case '<': switch (lex_here_string()) { case SUCCESS: break; case FAILURE: goto BrokenToken; case PROBLEM: return DP_EV_INVALID; } break; case '(': loadScheme(); break; case '\\': if (strncmp(pCurCtx->pzScan+1, "'(", (size_t)2) == 0) { alist_to_autogen_def(); goto scanAgain; } lex_escaped_char(); break; case '`': switch (lex_backquote()) { case FAILURE: goto NUL_error; case PROBLEM: goto scanAgain; case SUCCESS: break; } break; case '/': switch (lex_comment()) { case SUCCESS: goto scanAgain; default: break; } /* FALLTHROUGH */ /* to Invalid input char */ default: BrokenToken: pCurCtx->pzScan = assembleName(pCurCtx->pzScan, &lastToken); break; } /* switch (*pCurCtx->pzScan) */ return lastToken; NUL_error: AG_ABEND(aprf(zErrMsg, pzProg, "unterminated quote in definition", pCurCtx->pzCtxFname, pCurCtx->lineNo)); return DP_EV_INVALID; lex_done: /* * First time through, return the DP_EV_END token. * Second time through, we really finish. */ if (pCurCtx->pzScan == zNil) { pCurCtx->pCtx = pDoneCtx; pDoneCtx = pCurCtx; return DP_EV_INVALID; } pCurCtx->pzScan = (char*)zNil; return DP_EV_END; }
/** * We have an entry that starts with a name. Find the end of it, cook it * (if called for) and create the name/value association. */ static char const * scan_name(char const * name, tOptionValue * res) { tOptionValue * new_val; char const * pzScan = name+1; /* we know first char is a name char */ char const * pzVal; size_t nm_len = 1; size_t d_len = 0; /* * Scan over characters that name a value. These names may not end * with a colon, but they may contain colons. */ pzScan = SPN_VALUE_NAME_CHARS(name + 1); if (pzScan[-1] == ':') pzScan--; nm_len = (size_t)(pzScan - name); pzScan = SPN_HORIZ_WHITE_CHARS(pzScan); re_switch: switch (*pzScan) { case '=': case ':': pzScan = SPN_HORIZ_WHITE_CHARS(pzScan + 1); if ((*pzScan == '=') || (*pzScan == ':')) goto default_char; goto re_switch; case NL: case ',': pzScan++; /* FALLTHROUGH */ case NUL: add_string(&(res->v.nestVal), name, nm_len, NULL, (size_t)0); break; case '"': case '\'': pzVal = pzScan; pzScan = scan_q_str(pzScan); d_len = (size_t)(pzScan - pzVal); new_val = add_string(&(res->v.nestVal), name, nm_len, pzVal, d_len); if ((new_val != NULL) && (option_load_mode == OPTION_LOAD_COOKED)) ao_string_cook(new_val->v.strVal, NULL); break; default: default_char: /* * We have found some strange text value. It ends with a newline * or a comma. */ pzVal = pzScan; for (;;) { char ch = *(pzScan++); switch (ch) { case NUL: pzScan--; d_len = (size_t)(pzScan - pzVal); goto string_done; /* FALLTHROUGH */ case NL: if ( (pzScan > pzVal + 2) && (pzScan[-2] == '\\') && (pzScan[ 0] != NUL)) continue; /* FALLTHROUGH */ case ',': d_len = (size_t)(pzScan - pzVal) - 1; string_done: new_val = add_string(&(res->v.nestVal), name, nm_len, pzVal, d_len); if (new_val != NULL) remove_continuation(new_val->v.strVal); goto leave_scan_name; } } break; } leave_scan_name:; return pzScan; }
/* scanNameEntry * * We have an entry that starts with a name. Find the end of it, cook it * (if called for) and create the name/value association. */ static char const* scanNameEntry(char const* pzName, tOptionValue* pRes) { tOptionValue* pNV; char const * pzScan = pzName+1; /* we know first char is a name char */ char const * pzVal; size_t nameLen = 1; size_t dataLen = 0; /* * Scan over characters that name a value. These names may not end * with a colon, but they may contain colons. */ while (IS_VALUE_NAME_CHAR(*pzScan)) { pzScan++; nameLen++; } if (pzScan[-1] == ':') { pzScan--; nameLen--; } while (IS_HORIZ_WHITE_CHAR(*pzScan)) pzScan++; re_switch: switch (*pzScan) { case '=': case ':': while (IS_HORIZ_WHITE_CHAR( (int)*++pzScan )) ; if ((*pzScan == '=') || (*pzScan == ':')) goto default_char; goto re_switch; case '\n': case ',': pzScan++; /* FALLTHROUGH */ case NUL: addStringValue(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0); break; case '"': case '\'': pzVal = pzScan; pzScan = scanQuotedString( pzScan ); dataLen = pzScan - pzVal; pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, dataLen ); if ((pNV != NULL) && (option_load_mode == OPTION_LOAD_COOKED)) ao_string_cook( pNV->v.strVal, NULL ); break; default: default_char: /* * We have found some strange text value. It ends with a newline * or a comma. */ pzVal = pzScan; for (;;) { char ch = *(pzScan++); switch (ch) { case NUL: pzScan--; dataLen = pzScan - pzVal; goto string_done; /* FALLTHROUGH */ case '\n': if ( (pzScan > pzVal + 2) && (pzScan[-2] == '\\') && (pzScan[ 0] != NUL)) continue; /* FALLTHROUGH */ case ',': dataLen = (pzScan - pzVal) - 1; string_done: pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, dataLen ); if (pNV != NULL) removeLineContinue( pNV->v.strVal ); goto leave_scan_name; } } break; } leave_scan_name:; return pzScan; }