Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warn fixes #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions ApgLib/Operators.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,15 @@

//NOTE: returns phrase length on success, APG_UNDEFINED on failure
apg_uint uiALT(struct parserctx* spCtx, struct opcode* spOp, apg_uint uiOffset){
apg_uint uiHaveAst;
APG_AST_CTX* spAstCtx = (APG_AST_CTX*)spCtx->vpAstCtx;
apg_uint uiPhraseLength = APG_UNDEFINED;
apg_uint uiAstRecord = APG_UNDEFINED;
APG_OPCODE* spChildOp;
apg_uint* uipChildList = spOp->sUnion.sAlt.uipChildList;
apg_uint* uipEnd = uipChildList + spOp->sUnion.sAlt.uiChildCount;
APG_TRACE(spCtx, spOp, TRACE_ACTION_DOWN, P_ALT, uiOffset, 0);
uiHaveAst = spAstCtx && !spAstCtx->uiIgnoreRecords;
for(; uipChildList < uipEnd; uipChildList++){
if(uiHaveAst){uiAstRecord = spAstCtx->uiRecordCount;}
spChildOp = spCtx->spOpcodes + *uipChildList;
uiPhraseLength = spChildOp->pfnOp(spCtx, spChildOp, uiOffset);
if(uiPhraseLength != APG_UNDEFINED){break;}
if(uiHaveAst){uiAstRecord = spAstCtx->uiRecordCount;}
}
APG_TRACE(spCtx, spOp, TRACE_ACTION_UP, P_ALT, uiOffset, uiPhraseLength);
APG_STATS(spCtx, STATS_ACTION_COLLECT, uiPhraseLength, P_ALT, 0);
Expand Down
3 changes: 0 additions & 3 deletions ApgLib/Parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,19 +321,16 @@ void vParserAstInitCallbacks(void* vpCtx, APG_CALLBACK* pfnRuleCallbacks, APG_CA
vAstDtor(spCtx);
vAstCtor(spCtx);
spAstCtx = (APG_AST_CTX*)spCtx->vpAstCtx;
APG_CALLBACK pfnTemp;
if(pfnRuleCallbacks){
for(i = 0; i < spCtx->uiRuleCount; i++){
if(pfnRuleCallbacks[i]){spAstCtx->pfnCallbacks[i] = pfnRuleCallbacks[i];}
else{spAstCtx->pfnCallbacks[i] = NULL;}
pfnTemp = spAstCtx->pfnCallbacks[i];
}
}
if(spCtx->uiUdtCount && pfnUdtCallbacks){
for(i = 0; i < spCtx->uiUdtCount; i++){
if(pfnUdtCallbacks[i]){spAstCtx->pfnCallbacks[i + spCtx->uiRuleCount] = pfnUdtCallbacks[i];}
else{spAstCtx->pfnCallbacks[i + spCtx->uiRuleCount] = NULL;}
pfnTemp = spAstCtx->pfnCallbacks[i + spCtx->uiRuleCount];
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions ApgLib/Stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ static void vStatsGetNameAddresses(APG_PARSER_CTX* spParserCtx, APG_PARSER_STATS

static apg_uint uiStatsGetNames(APG_PARSER_CTX* spParserCtx, APG_PARSER_STATS* spPublicStats){
apg_uint uiSize = 0;
apg_uint i, j, uiLen;
apg_uint i,uiLen;
char* cpNameBuffer = spPublicStats ? spPublicStats->cpNames : NULL;
for(i = 0; i < spParserCtx->uiRuleCount; i++){
uiLen = strlen(spParserCtx->spRules[i].cpRuleName) + 1;
Expand All @@ -145,7 +145,6 @@ static apg_uint uiStatsGetNames(APG_PARSER_CTX* spParserCtx, APG_PARSER_STATS* s
uiSize += uiLen;
if(cpNameBuffer){
strcpy(cpNameBuffer, spParserCtx->spUdts[i].cpUdtName);
j = i + spParserCtx->uiRuleCount;
cpNameBuffer += uiLen;
}
}
Expand Down
2 changes: 0 additions & 2 deletions ApgLib/Tools.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,11 @@ apg_uint uiACharToString(char* cpChars, apg_uint uiCLen, const apg_achar* acpACh
apg_uint i = 0;
apg_achar acChar;
char* cpNextChar;
const apg_achar* cpBufferEnd;
apg_uint uiCharLen, uiStrLen;
apg_uint uiCLenMax;
apg_uint uiSize = sizeof(apg_achar);
cpNextChar = cpChars;
if(acpAChars && uiALen && cpChars && uiCLen){
cpBufferEnd = acpAChars + uiALen;
uiCLenMax = uiCLen - 1;
uiStrLen = 0;
for(i = 0; i < uiALen && uiStrLen < uiCLenMax; i++){
Expand Down
20 changes: 3 additions & 17 deletions ApgLib/Trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,8 @@ void vTraceAdmin(APG_PARSER_CTX* spParserCtx, apg_uint uiAction, apg_uint uiId,

void vTrace(APG_PARSER_CTX* spParserCtx, APG_OPCODE* spOp, apg_uint uiAction, apg_uint uiId, apg_uint uiOffset, apg_uint uiPhraseLen){
APG_TRACE_CTX* spCtx = (APG_TRACE_CTX*)spParserCtx->vpTraceCtx;
apg_uint uiState, uiStrLen;
const apg_achar* acpPhrase;

if(spParserCtx->vpTraceCtx){
if(uiPhraseLen == APG_UNDEFINED){uiState = NOMATCH;}
else if(uiPhraseLen == 0){uiState = EMPTY;}
else{uiState = MATCH;}
uiStrLen = (uiOffset < spParserCtx->uiInputStringLen) ? spParserCtx->uiInputStringLen - uiOffset: 0;
acpPhrase = spParserCtx->acpInputString + uiOffset;
switch(uiAction){
case TRACE_ACTION_BEGIN:
vTraceBegin(spCtx);
Expand Down Expand Up @@ -364,7 +357,7 @@ static void vTraceDown(APG_TRACE_CTX* spCtx, APG_OPCODE* spOp, apg_uint uiId, ap
apg_uint uiIsTruncated = APG_FALSE;
char caIndentBuf[APG_DISPLAY_MAX_LINE];
char caScratchBuf[2*APG_DISPLAY_MAX_LINE];
apg_uint uiAChars, uiPrintChars;
apg_uint uiAChars;
void* vpTest;
const apg_achar* acpPhrase;
apg_uint uiPhraseLen;
Expand Down Expand Up @@ -416,10 +409,8 @@ static void vTraceDown(APG_TRACE_CTX* spCtx, APG_OPCODE* spOp, apg_uint uiId, ap
TASSERT(APG_FALSE);
break;
}
uiPrintChars = uiStrBufCat(vpPrtBuf, ": :");
if(uiStrBufIsTruncated(vpPrtBuf)){uiIsTruncated = APG_TRUE;break;}
uiAChars = uiACharToString(&caScratchBuf[0], sizeof(caScratchBuf), acpPhrase, uiPhraseLen);
uiPrintChars = uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
if(uiAChars < uiPhraseLen){uiIsTruncated = APG_TRUE;break;}
if(uiStrBufIsTruncated(vpPrtBuf)){uiIsTruncated = APG_TRUE;break;}
spCtx->uiTreeDepth++;
Expand All @@ -439,7 +430,7 @@ static void vTraceUp(APG_TRACE_CTX* spCtx, APG_OPCODE* spOp, apg_uint uiId, apg_
apg_uint uiIsTruncated = APG_FALSE;
char caIndentBuf[APG_DISPLAY_MAX_LINE];
char caScratchBuf[2*APG_DISPLAY_MAX_LINE];
apg_uint uiAChars, uiPrintChars;
apg_uint uiAChars;
int uiState;
const apg_achar* acpPhrase;
apg_uint* uipOtherRecord;
Expand Down Expand Up @@ -496,13 +487,8 @@ static void vTraceUp(APG_TRACE_CTX* spCtx, APG_OPCODE* spOp, apg_uint uiId, apg_
break;
}
if(uiStrBufIsTruncated(vpPrtBuf)){uiIsTruncated = APG_TRUE;break;}
if(uiPhraseLen == APG_UNDEFINED){
uiPrintChars = uiStrBufCat(vpPrtBuf, ": :");
} else{
sprintf(&caScratchBuf[0], ":%lu:", (unsigned long int)uiPhraseLen);
uiPrintChars = uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
if(uiPhraseLen != APG_UNDEFINED){sprintf(&caScratchBuf[0], ":%lu:", (unsigned long int)uiPhraseLen);
uiAChars = uiACharToString(&caScratchBuf[0], sizeof(caScratchBuf), acpPhrase, uiPhraseLen);
uiPrintChars = uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
if(uiAChars < uiPhraseLen){uiIsTruncated = APG_TRUE;break;}
if(uiStrBufIsTruncated(vpPrtBuf)){uiIsTruncated = APG_TRUE;break;}
}
Expand Down
2 changes: 0 additions & 2 deletions ApgUtilities/Utilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ and one for the POST_AST or upward direction visit.
void vDisplayAstRecords(FILE* spOut, void* vpParserCtx){
APG_PARSER_CTX* spParserCtx = (APG_PARSER_CTX*)vpParserCtx;
if(spParserCtx->vpAstCtx){
apg_uint uiCharLen;
apg_uint uiBufLen = 128;
char cpBuffer[uiBufLen];

Expand Down Expand Up @@ -225,7 +224,6 @@ void vDisplayAstRecords(FILE* spOut, void* vpParserCtx){
sprintf(&caScratchBuf[0], "%s%s:%lu:%lu:", cpBuffer, spUdt->cpUdtName,
(printf_uint)spRecord->uiPhraseOffset, (printf_uint)spRecord->uiPhraseLength);
uiStrBufCat(vpPrtBuf, &caScratchBuf[0]);
uiCharLen = uiACharToString(cpBuffer, uiBufLen, acpPhrase, uiPhraseLen);
uiStrBufCat(vpPrtBuf, cpBuffer);
} else{
APG_RULE* spRule= spParserCtx->spRules + spRecord->uiId;
Expand Down
64 changes: 46 additions & 18 deletions Generator/Generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static int iCompNames(const void* vpLhs, const void* vpRhs);
static void vPrintOriginalGrammar(FILE* spFile, char* cpGrammar);
static void vToUpper(char* cpString, char* cpToUpper, G_UINT uiLen);
static G_UINT uiMinIntSize(G_UINT uiSize);
static void vNoHyphen(char* cpString, char* cpNoHyphen, G_UINT uiLen);

void vGenerateCppHeader(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName, char* cpGrammar, char* cpFileName, apg_uint uiFileNameLen){
char caHeaderDefine[1024];
Expand Down Expand Up @@ -183,24 +184,28 @@ void vGenerateCppHeader(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
fprintf(spOut, " // SYNTAX CALL BACK FUNCTIONS\n");
for(i = 0; i < uiRuleCount; i++){
cpName = spRuleSort[i].cpName;
fprintf(spFile, " static apg_uint uiSyn_%s(APG_CBDATA* spData);\n", cpName);
vNoHyphen(cpName, caBuffer2, sizeof(caBuffer2));
fprintf(spFile, " static apg_uint uiSyn_%s(APG_CBDATA* spData);\n", caBuffer2);
}
if(uiUdtCount){
for(i = 0; i < uiUdtCount; i++){
cpName = spUdtSort[i].cpName;
fprintf(spFile, " static apg_uint uiSyn_%s(APG_CBDATA* spData);\n", cpName);
vNoHyphen(cpName, caBuffer2, sizeof(caBuffer2));
fprintf(spFile, " static apg_uint uiSyn_%s(APG_CBDATA* spData);\n", caBuffer2);
}
}
fprintf(spFile, "\n");
fprintf(spFile, " // AST CALL BACK FUNCTIONS\n");
for(i = 0; i < uiRuleCount; i++){
cpName = spRuleSort[i].cpName;
fprintf(spFile, " static apg_uint uiAst_%s(APG_CBDATA* spData);\n", cpName);
vNoHyphen(cpName, caBuffer2, sizeof(caBuffer2));
fprintf(spFile, " static apg_uint uiAst_%s(APG_CBDATA* spData);\n", caBuffer2);
}
if(uiUdtCount){
for(i = 0; i < uiUdtCount; i++){
cpName = spUdtSort[i].cpName;
fprintf(spFile, " static apg_uint uiAst_%s(APG_CBDATA* spData);\n", cpName);
vNoHyphen(cpName, caBuffer2, sizeof(caBuffer2));
fprintf(spFile, " static apg_uint uiAst_%s(APG_CBDATA* spData);\n", caBuffer2);
}
}
fprintf(spFile, "};");
Expand All @@ -220,6 +225,7 @@ void vGenerateCppHeader(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
void vGenerateCppSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName, char* cpFileName, apg_uint uiFileNameLen){
char caBuffer[1024];
char caBuffer2[1024];
char caBuffer3[1024];
FILE* spFile;
FILE* spOut;
G_UINT i;
Expand Down Expand Up @@ -300,7 +306,7 @@ void vGenerateCppSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
fprintf(spFile, "// The largest integer refers only to the grammar's data. Other Parser integer's may,\n");
fprintf(spFile, "// and likely will, have larger requirements. Parser may fail unpredictably.\n");
fprintf(spFile, "\n");
fprintf(spFile, "static unsigned long int ulData[%lu] = {\n", (unsigned long int)uiVecSize(vpVecData));
fprintf(spFile, "static signed long int ulData[%lu] = {\n", (unsigned long int)uiVecSize(vpVecData));
vWriteGrammarData(spFile, vpVecData);
fprintf(spFile, "\n");
fprintf(spFile, "};\n");
Expand Down Expand Up @@ -390,12 +396,13 @@ void vGenerateCppSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
for(i = 0; i < uiRuleCount; i++){
cpName = spRuleSort[i].cpName;
vToUpper(cpName, caBuffer2, sizeof(caBuffer2));
vNoHyphen(cpName, caBuffer3, sizeof(caBuffer3));
if(spRuleSort[i].uiIndex == 0){
fprintf(spFile, " sppRuleCallbacks[%s::RULEID_%s] = %s::uiSyn_%s;\n",
cpProjectName, caBuffer2, cpProjectName, cpName);
cpProjectName, caBuffer2, cpProjectName, caBuffer3);
} else{
fprintf(spFile, "// sppRuleCallbacks[%s::RULEID_%s] = %s::uiSyn_%s;\n",
cpProjectName, caBuffer2, cpProjectName, cpName);
cpProjectName, caBuffer2, cpProjectName, caBuffer3);
}
}
fprintf(spOut, " }\n");
Expand All @@ -404,12 +411,13 @@ void vGenerateCppSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
for(i = 0; i < uiUdtCount; i++){
cpName = spUdtSort[i].cpName;
vToUpper(cpName, caBuffer2, sizeof(caBuffer2));
vNoHyphen(cpName, caBuffer3, sizeof(caBuffer3));
if(spUdtSort[i].uiIndex == 0){
fprintf(spFile, " sppUdtCallbacks[%s::UDTID_%s] = %s::uiSyn_%s;\n",
cpProjectName, caBuffer2, cpProjectName, cpName);
cpProjectName, caBuffer2, cpProjectName, caBuffer3);
} else{
fprintf(spFile, "// sppUdtCallbacks[%s::UDTID_%s] = %s::uiSyn_%s;\n",
cpProjectName, caBuffer2, cpProjectName, cpName);
cpProjectName, caBuffer2, cpProjectName, caBuffer3);
}
}
fprintf(spOut, " }\n");
Expand All @@ -427,12 +435,13 @@ void vGenerateCppSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
for(i = 0; i < uiRuleCount; i++){
cpName = spRuleSort[i].cpName;
vToUpper(cpName, caBuffer2, sizeof(caBuffer2));
vNoHyphen(cpName, caBuffer3, sizeof(caBuffer3));
if(spRuleSort[i].uiIndex == 0){
fprintf(spFile, " sppRuleCallbacks[%s::RULEID_%s] = %s::uiAst_%s;\n",
cpProjectName, caBuffer2, cpProjectName, cpName);
cpProjectName, caBuffer2, cpProjectName, caBuffer3);
} else{
fprintf(spFile, "// sppRuleCallbacks[%s::RULEID_%s] = %s::uiAst_%s;\n",
cpProjectName, caBuffer2, cpProjectName, cpName);
cpProjectName, caBuffer2, cpProjectName, caBuffer3);
}
}
fprintf(spOut, " }\n");
Expand All @@ -441,12 +450,13 @@ void vGenerateCppSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
for(i = 0; i < uiUdtCount; i++){
cpName = spUdtSort[i].cpName;
vToUpper(cpName, caBuffer2, sizeof(caBuffer2));
vNoHyphen(cpName, caBuffer3, sizeof(caBuffer3));
if(spUdtSort[i].uiIndex == 0){
fprintf(spFile, " sppUdtCallbacks[%s::UDTID_%s] = %s::uiAst_%s;\n",
cpProjectName, caBuffer2, cpProjectName, cpName);
cpProjectName, caBuffer2, cpProjectName, caBuffer3);
} else{
fprintf(spFile, "// sppUdtCallbacks[%s::UDTID_%s] = %s::uiAst_%s;\n",
cpProjectName, caBuffer2, cpProjectName, cpName);
cpProjectName, caBuffer2, cpProjectName, caBuffer3);
}
}
fprintf(spOut, " }\n");
Expand Down Expand Up @@ -493,8 +503,9 @@ void vGenerateCppSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
break;
}
}
vNoHyphen(cpName, caBuffer3, sizeof(caBuffer3));
fprintf(spOut, "// template for Rule syntax callback functions\n");
fprintf(spOut, "apg_uint %s::uiSyn_%s(APG_CBDATA* spData){\n", cpProjectName, cpName);
fprintf(spOut, "apg_uint %s::uiSyn_%s(APG_CBDATA* spData){\n", cpProjectName, caBuffer3);
fprintf(spOut, " apg_uint uiRet = APG_FALSE;\n");
fprintf(spOut, "// uncomment to access the phrase to be parsed by this function\n");
fprintf(spOut, "// const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;\n");
Expand All @@ -520,10 +531,11 @@ void vGenerateCppSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
break;
}
}
vNoHyphen(cpName, caBuffer3, sizeof(caBuffer3));
fprintf(spOut, "\n");
fprintf(spOut, "// template for UDT syntax callback functions\n");
fprintf(spOut, "// Copy and override for each required UDT syntax callback functions\n");
fprintf(spOut, "apg_uint %s::uiSyn_%s(APG_CBDATA* spData){\n", cpProjectName, cpName);
fprintf(spOut, "apg_uint %s::uiSyn_%s(APG_CBDATA* spData){\n", cpProjectName, caBuffer3);
fprintf(spOut, "// uncomment to access the phrase to be parsed by this function\n");
fprintf(spOut, "// const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;\n");
fprintf(spOut, "// apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;\n");
Expand All @@ -541,8 +553,9 @@ void vGenerateCppSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
break;
}
}
vNoHyphen(cpName, caBuffer3, sizeof(caBuffer3));
fprintf(spOut, "// template for Rule AST callback functions\n");
fprintf(spOut, "apg_uint %s::uiAst_%s(APG_CBDATA* spData){\n", cpProjectName, cpName);
fprintf(spOut, "apg_uint %s::uiAst_%s(APG_CBDATA* spData){\n", cpProjectName, caBuffer3);
fprintf(spOut, "// uncomment to access the phrase to be parsed by this function\n");
fprintf(spOut, "// const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;\n");
fprintf(spOut, "// apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;\n");
Expand All @@ -563,8 +576,9 @@ void vGenerateCppSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName,
break;
}
}
vNoHyphen(cpName, caBuffer3, sizeof(caBuffer3));
fprintf(spOut, "// template for UDT AST callback functions\n");
fprintf(spOut, "apg_uint %s::uiAst_%s(APG_CBDATA* spData){\n", cpProjectName, cpName);
fprintf(spOut, "apg_uint %s::uiAst_%s(APG_CBDATA* spData){\n", cpProjectName, caBuffer3);
fprintf(spOut, "// uncomment to access the phrase to be parsed by this function\n");
fprintf(spOut, "// const apg_achar* acpPhrase = spData->acpSrc + spData->uiPhraseOffset;\n");
fprintf(spOut, "// apg_uint uiMaxPhraseLength = spData->uiSrcLen - spData->uiPhraseOffset;\n");
Expand Down Expand Up @@ -735,7 +749,7 @@ void vGenerateCSource(CALLBACK_CTX* spCtx, char* cpPath, char* cpProjectName, ch
fprintf(spFile, "// The largest integer refers only to the grammar's data. Other Parser integer's may,\n");
fprintf(spFile, "// and likely will, have larger requirements. Parser may fail unpredictably.\n");
fprintf(spFile, "\n");
fprintf(spFile, "static unsigned long int ulData[%lu] = {\n", (unsigned long int)uiVecSize(vpVecData));
fprintf(spFile, "static signed long int ulData[%lu] = {\n", (unsigned long int)uiVecSize(vpVecData));
vWriteGrammarData(spFile, vpVecData);
fprintf(spFile, "\n");
fprintf(spFile, "};\n");
Expand Down Expand Up @@ -854,6 +868,20 @@ static void vToUpper(char* cpString, char* cpToUpper, G_UINT uiLen){
*cpToUpper = 0;
}

static void vNoHyphen(char* cpString, char* cpNoHyphen, G_UINT uiLen){
GASSERT(cpString);
GASSERT(cpNoHyphen);
GASSERT(uiLen);
uiLen++;
uiLen = min(uiLen, (G_UINT)(strlen(cpString)+1));
char* cpEnd = cpString + uiLen - 1;
for(; cpString < cpEnd; cpString++, cpNoHyphen++){
if(*cpString == '-'){*cpNoHyphen = '_';}
else{*cpNoHyphen = *cpString;}
}
*cpNoHyphen = 0;
}

static G_UINT uiMinIntSize(G_UINT uiSize){
G_UINT uiRet = 0;
G_UINT uiTest;
Expand Down