1 /* 2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 25 * OF SUCH DAMAGE. 26 * 27 * This file is part of the lwIP TCP/IP stack. 28 * 29 * Author: Martin Hentschel <info@cl-soft.de> 30 * 31 */ 32 33 using System; 34 using System.Collections.Generic; 35 using System.Text; 36 using CCodeGeneration; 37 38 namespace LwipSnmpCodeGeneration 39 { 40 public class SnmpTreeNode: SnmpScalarAggregationNode 41 { 42 private readonly List<SnmpNode> childNodes = new List<SnmpNode>(); 43 private readonly List<SnmpScalarNode> childScalarNodes = new List<SnmpScalarNode>(); 44 private string fullOid = ""; 45 SnmpTreeNode(SnmpTreeNode parentNode)46 public SnmpTreeNode(SnmpTreeNode parentNode) 47 : base(parentNode) 48 { 49 } 50 51 public override string FullNodeName 52 { 53 get { return this.Name.ToLowerInvariant() + "_treenode"; } 54 } 55 56 public string FullOid 57 { 58 get { return this.fullOid; } 59 set { this.fullOid = value; } 60 } 61 62 public List<SnmpNode> ChildNodes 63 { 64 get { return this.childNodes; } 65 } 66 67 protected override IEnumerable<SnmpScalarNode> AggregatedScalarNodes 68 { 69 get { return this.childScalarNodes; } 70 } 71 GenerateAggregatedCode(MibCFile mibFile, bool generateDeclarations, bool generateImplementations)72 private void GenerateAggregatedCode(MibCFile mibFile, bool generateDeclarations, bool generateImplementations) 73 { 74 VariableType instanceType = new VariableType("instance", LwipDefs.Vt_StNodeInstance, "*"); 75 base.GenerateAggregatedCode( 76 mibFile, 77 instanceType, 78 String.Format("{0}->node->oid", instanceType.Name), 79 generateDeclarations, 80 generateImplementations); 81 } 82 GenerateAggregateMethodDeclarations(MibCFile mibFile)83 private void GenerateAggregateMethodDeclarations(MibCFile mibFile) 84 { 85 if (LwipOpts.GenerateSingleAccessMethodsForTreeNodeScalars && (this.childScalarNodes.Count > 1)) 86 { 87 GenerateAggregatedCode(mibFile, true, false); 88 } 89 } 90 GenerateCode(MibCFile mibFile)91 public override void GenerateCode(MibCFile mibFile) 92 { 93 string nodeInitialization; 94 95 if (LwipOpts.GenerateSingleAccessMethodsForTreeNodeScalars && (this.childScalarNodes.Count > 1)) 96 { 97 GenerateAggregatedCode(mibFile, false, true); 98 } 99 100 // create and add node declaration 101 if (this.childNodes.Count > 0) 102 { 103 StringBuilder subnodeArrayInitialization = new StringBuilder(); 104 105 for (int i=0; i<this.childNodes.Count; i++) 106 { 107 subnodeArrayInitialization.Append(" &"); 108 subnodeArrayInitialization.Append(this.childNodes[i].FullNodeName); 109 subnodeArrayInitialization.Append(".node"); 110 if (!(this.childNodes[i] is SnmpTreeNode)) 111 { 112 subnodeArrayInitialization.Append(".node"); 113 } 114 115 if (i < (this.childNodes.Count - 1)) 116 { 117 subnodeArrayInitialization.Append(",\n"); 118 } 119 } 120 121 VariableDeclaration subnodeArray = new VariableDeclaration( 122 new VariableType(this.Name.ToLowerInvariant() + "_subnodes", LwipDefs.Vt_StNode, "*", ConstType.Both, String.Empty), 123 "{\n" + subnodeArrayInitialization + "\n}", 124 isStatic: true); 125 126 mibFile.Declarations.Add(subnodeArray); 127 128 nodeInitialization = String.Format("SNMP_CREATE_TREE_NODE({0}, {1})", this.Oid, subnodeArray.Type.Name); 129 } 130 else 131 { 132 nodeInitialization = String.Format("SNMP_CREATE_EMPTY_TREE_NODE({0})", this.Oid); 133 } 134 135 mibFile.Declarations.Add(new VariableDeclaration( 136 new VariableType(this.FullNodeName, LwipDefs.Vt_StTreeNode, null, ConstType.Value), 137 nodeInitialization, 138 isStatic: true)); 139 } 140 Analyze()141 public override void Analyze() 142 { 143 this.childScalarNodes.Clear(); 144 145 // delegate analyze (don't use enumerator because the child node may change our child collection by e.g. removing or replacing itself) 146 for (int i=this.ChildNodes.Count-1; i>=0; i--) 147 { 148 this.ChildNodes[i].Analyze(); 149 } 150 151 // collect scalar nodes 152 foreach (SnmpNode childNode in this.childNodes) 153 { 154 SnmpScalarNode scalarNode = childNode as SnmpScalarNode; 155 if (scalarNode != null) 156 { 157 this.childScalarNodes.Add(scalarNode); 158 } 159 } 160 161 base.Analyze(); 162 163 // check if we can merge this node to a scalar array node (all childs need to be scalars) 164 if (this.childNodes.Count > 0) 165 { 166 if (LwipOpts.GenerateScalarArrays && (this.childScalarNodes.Count == this.childNodes.Count) && (this.ParentNode != null)) 167 { 168 SnmpScalarArrayNode scalarArrayNode = new SnmpScalarArrayNode(this.childScalarNodes, this.ParentNode); 169 scalarArrayNode.Oid = this.Oid; 170 scalarArrayNode.Name = this.Name; 171 scalarArrayNode.Analyze(); 172 173 for (int i=0; i<this.ParentNode.ChildNodes.Count; i++) 174 { 175 if (this.ParentNode.ChildNodes[i] == this) 176 { 177 this.ParentNode.ChildNodes.RemoveAt(i); 178 this.ParentNode.ChildNodes.Insert(i, scalarArrayNode); 179 break; 180 } 181 } 182 } 183 else if (LwipOpts.GenerateSingleAccessMethodsForTreeNodeScalars && (this.childScalarNodes.Count > 1)) 184 { 185 foreach (SnmpScalarNode scalarNode in this.childScalarNodes) 186 { 187 scalarNode.UseExternalMethods = true; 188 scalarNode.ExternalGetMethod = this.GetMethodName; 189 scalarNode.ExternalTestMethod = this.TestMethodName; 190 scalarNode.ExternalSetMethod = this.SetMethodName; 191 } 192 } 193 } 194 else // if (this.childNodes.Count == 0) 195 { 196 if (!LwipOpts.GenerateEmptyFolders && (this.ParentNode != null)) 197 { 198 // do not generate this empty folder because it only waste (static) memory 199 for (int i=0; i<this.ParentNode.ChildNodes.Count; i++) 200 { 201 if (this.ParentNode.ChildNodes[i] == this) 202 { 203 this.ParentNode.ChildNodes.RemoveAt(i); 204 break; 205 } 206 } 207 } 208 } 209 } 210 Generate(MibCFile generatedFile, MibHeaderFile generatedHeaderFile)211 public override void Generate(MibCFile generatedFile, MibHeaderFile generatedHeaderFile) 212 { 213 // generate code of child nodes 214 foreach (SnmpNode childNode in this.childNodes) 215 { 216 if (childNode is SnmpTreeNode) 217 { 218 childNode.Generate(generatedFile, generatedHeaderFile); 219 } 220 } 221 222 Comment dividerComment = new Comment( 223 String.Format("--- {0} {1} -----------------------------------------------------", this.Name, this.fullOid), 224 singleLine: true); 225 226 generatedFile.Declarations.Add(dividerComment); 227 generatedFile.Implementation.Add(dividerComment); 228 229 this.GenerateAggregateMethodDeclarations(generatedFile); 230 231 foreach (SnmpNode childNode in this.childNodes) 232 { 233 if (!(childNode is SnmpTreeNode)) 234 { 235 childNode.Generate(generatedFile, generatedHeaderFile); 236 } 237 } 238 239 base.Generate(generatedFile, generatedHeaderFile); 240 } 241 } 242 } 243