// // ParseArguments // // Creates var items from command line arguments // void CmdParse::ParseArguments(void *context, Bool rawVar, Bool rawData) { U32 argCount = 0; VarPathIdent argPath; VarPathIdent argOffsetPath; VNode *node; // Reset argument count argCount = 0; // Delete the current scope if it exists (may exit this function via exception) DeleteArguments(); // Store command name in first argument MakeArgName(CmdParse::StackLevel(), argPath, argCount); VarSys::CreateString(argPath.str, tBuf.lastToken, VarSys::DEFAULT); MakeArgOffset(CmdParse::StackLevel(), argOffsetPath, argCount++); VarSys::CreateInteger(argOffsetPath.str, 0); if (rawData) { // Store rest of command line in second argument MakeArgName(CmdParse::StackLevel(), argPath, argCount); VarSys::CreateString(argPath.str, tBuf.CurrentStr()); MakeArgOffset(CmdParse::StackLevel(), argOffsetPath, argCount++); VarSys::CreateInteger(argOffsetPath.str, argCount); // Finished parsing while (tBuf.NextToken() != TR_EOF) {} } else { Bool done = FALSE; // Parse all arguments while (!done) { // Save the position of this argument U32 argPos = tBuf.CurrentPos(); // Generate argument name MakeArgName(CmdParse::StackLevel(), argPath, argCount); // Generate argument index name MakeArgOffset(CmdParse::StackLevel(), argOffsetPath, argCount); // Parse the VNode data if ((node = StdParse::ParseAtomicVNode(&tBuf)) != NULL) { // Create the offset var VarSys::CreateInteger(argOffsetPath.str, argPos); switch (node->aType) { case VNode::AT_INTEGER: VarSys::CreateInteger(argPath.str, node->GetInteger()); break; case VNode::AT_FPOINT: VarSys::CreateFloat(argPath.str, node->GetFPoint()); break; case VNode::AT_STRING: VarSys::CreateString(argPath.str, node->GetString()); break; default: ERR_FATAL(("Invalid node type!")); } // Successfully made an arg argCount++; // Delete the temporary VNode delete node; } else { // Examine what we've got switch (tBuf.PeekToken()) { case TR_OK : { VarSys::VarItem *varItem; // Create the offset var VarSys::CreateInteger(argOffsetPath.str, argPos); // Accept the identifier tBuf.AcceptIdent(); // Are we in raw var mode or is this argument a var item if (!rawVar && (varItem = VarSys::FindVarItem(tBuf.lastToken, context)) != NULL) { switch(varItem->type) { // Able to copy these types case VarSys::VI_STRING: case VarSys::VI_INTEGER: case VarSys::VI_FPOINT: VarSys::CopyVarItem(argPath.str, varItem); break; // Invalid item type default: { // Convert single token into a string argument VarSys::CreateString(argPath.str, tBuf.lastToken); } } } else { // Convert single token into a string argument VarSys::CreateString(argPath.str, tBuf.lastToken); } // Successfully made an arg argCount++; break; } case TR_PUN: switch (*tBuf.peekToken) { // Continue to next argument case ',': tBuf.AcceptPunct(); continue; // We're finished case ';': done = TRUE; break; // Ignore brackets case '(': case ')': tBuf.AcceptPunct(); continue; default : tBuf.TokenError("Unexpected punctuation '%c'", *tBuf.peekToken); break; } case TR_EOF: done = TRUE; break; default: ERR_FATAL(("Missing case")); break; } } } } // Create argCount item (only created when successful) MakeArgCount(CmdParse::StackLevel(), argPath); VarSys::CreateInteger(argPath.str, argCount); }
// // ParseAssignment // // Parse an item value assignment // Bool CmdParse::ParseAssignment(void *context, VarSys::VarItem *item) { ASSERT(item); // Peek at the next token switch (tBuf.PeekToken()) { case TR_OK: break; case TR_PUN: { switch (*tBuf.peekToken) { case '=': tBuf.AcceptPunct(); break; case ';': return (FALSE); break; } break; } case TR_EOF: return (FALSE); break; default: ERR_FATAL(("Missing case")); } // Allow editing in a development build #ifdef DEVELOPMENT // But give a warning if (item->flags & VarSys::NOEDIT) { CON_ERR(("Warning! Can not be modified in a release build")) } #else // Check that this item can be edited from the console if (item->flags & VarSys::NOEDIT) { tBuf.TokenError("This item can not be modified"); } #endif VNode *node; // See if we are assigning one var to another if (ParseVarAssignment(context, item)) { return (TRUE); } // Parse the VNode data if ((node = StdParse::ParseAtomicVNode(&tBuf)) == NULL) { // Convert a single identifier to a string value if (tBuf.PeekToken() == TR_OK) { tBuf.AcceptIdent(); node = new VNode; node->SetupString(tBuf.lastToken); } else { tBuf.TokenError("Invalid value"); } } // Assign the new value switch (item->type) { // Changing an integer item case VarSys::VI_INTEGER: switch (node->aType) { case VNode::AT_INTEGER: item->SetInteger(node->GetInteger()); break; case VNode::AT_FPOINT: item->SetInteger((S32)node->GetFPoint()); break; default: delete node; tBuf.TokenError("Expected %s value", VarSys::GetTypeString(item->type)); } break; // Changing a floating point item case VarSys::VI_FPOINT: switch (node->aType) { case VNode::AT_INTEGER: item->SetFloat((F32)node->GetInteger()); break; case VNode::AT_FPOINT: item->SetFloat(node->GetFPoint()); break; default: delete node; tBuf.TokenError("Expected %s value", VarSys::GetTypeString(item->type)); } break; // Changing a string item case VarSys::VI_STRING: switch (node->aType) { case VNode::AT_STRING: item->SetStr(node->GetString()); break; default: delete node; tBuf.TokenError("Expected %s value", VarSys::GetTypeString(item->type)); } break; // Unable to change this type of item default : delete node; tBuf.TokenError("Unable to modify items of this type"); } // Delete the temporary VNode delete node; // Success return (TRUE); }