#!/usr/bin/perl # # subst [IS] v=vaRiaBle V=SYMBOL Y=Re_Cord F=Field t=typ foo.F # # This is a program that transforms the "generic" chunks of text that are # scattered throughout the SNMP agent code, replacing several embedded # strings with our command-line args. The chunks are shown in the generic # text as letter triplets, such as "vvv" or "TTT"; the command-line argument # "x=fuBar" means to replace the "xxx" chunks with the string "fuBar". # # Thus for the command: # subst S v=swsfmptBar V=XSWSFMPTSBP7BAR Y=4_SFM_Perf_progress \ # F=SBBar7 o=28 l=4 t=sfm i=1 # the transformations that we make are: # vvv -> swsfmptBar (Symbolic name of SNMP variable) # VVV -> XSWSFMPTSBP7BAR (Symbolic name of variable's "magic" constant) # YYY -> 4_SFM_Perf_progress (Record's name, minus initial "CM" or "CT") # FFF -> SBBar7 (Field within record) # ooo -> 28 (Field offset) # lll -> 4 (Field length) # ttt -> sfm (Device type for pointers) # TTT -> SFM (Device type for messages) # iii -> 1 (Difference between DeviceID and SNMP index) # where vvv is the SNMP MIB variable name (which must also conform to C # variable-name rules), VVV is the #defined constant in mibtbl.h, and FFF is # the field name in the cm4_record.h header file for the record Rec_name. # Note that the file "icd.t" (produced as a side-effect of using icd-c to # make cm4record.h) contains a list of many of the fields you need for calls # on this program. # # The one-char field 'B', 'I' or 'S', if present, tells subst whether this is # is an Byte, Integer or String variable. This is used for a special kludge: # when the "RVAR;" command is encountered, it is expanded to the lines that # build the return variable. This code is different for integer and string # variables, and no template is feasible, so it is just generated in its # entirety. For integer variables, the value is loaded into the global # "rval"; for strings, the "bp" parameter is pointed directly at the value. # # The difference between 'B' and 'S' is that 'S' includes "[0]" after the # field name, while 'B' doesn't; this is solely to handle stupid C compiler # complaints about misuse of '&' before arrays. Depending on the version of # the ICD (and your compiler), 'B' may or may not be needed. # # Input lines with '|' in col 1 are dropped, so that we have a way to comment # the prototype code without the comments appearing in the output. C-style # comments are processed as code. # # The s, S, T and V chunks are special cases which, if omitted, will be built # from other chunks, as described below. require "cmagic.pl"; for $a (@ARGV) { if ($a =~ /^.$/) { $type = $a; } elsif ($a =~ /^(\w)=(.*)/) { $x{$1} = $2; } else { print STDERR "$0: Unknown arg \"$a\" ignored.\n"; } } $D = $x{'D'}; $d = $x{'d'}; $F = $x{'F'}; $i = $x{'i'}; $Y = $x{'Y'}; $o = $x{'o'}; $l = $x{'l'}; $S = $x{'S'}; $s = $x{'s'}; $T = $x{'T'}; $t = $x{'t'}; $V = $x{'V'}; $v = $x{'v'}; # The following variables can be calculated if not given on the # command line: if (!$D) { $D = $d; substr($D,0,1) =~ tr/a-z/A-Z/; $x{'D'} = $D; } if (!$V) { @V = &cmagic($v); # Magic number and (ignored) code. $x{'V'} = $V[0]; } if (!$T){ ($T = "$t") =~ tr/a-z/A-Z/; # The type of device this is for. $x{'T'} = $T; } if ($o eq 'P' || $o eq 'R') { # Shorthand for the offset in cm4_fields.h $o = 'CO4_' . $o . '_' . $v; $x{'o'} = $o; } if ($l eq 'P' || $l eq 'R') { # Shorthand for the length in cm4_fields.h $l = 'CL4_' . $l . '_' . $v; $x{'l'} = $l; } if (!$s) { $s = ($type eq 'S') ? "MinSS(p->$F)" : "sizeof(p->$F)"; # The size of the datum. $x{'s'} = $s; } if (!$S) { $S = "CS4_$Y"; # The size of the record. $x{'S'} = $S; } if (!$x{'i'}) { # Add to index to get DeviceID. $x{'i'} = '0'; } if (!$x{'p'}) { # PortID value for lookups. $x{'p'} = '0'; } for () { next if /^\|/; # Comment that doesn't appear in the C code. if (/^(\s+)RVAL;/){ # Generate return-val code depending on type. $ind = $1; # Preserve the indentation for readability. if (!$type) { # Complain if type arg omitted. print STDERR "Can't expand RVAL; need 1-char type arg.\n"; } elsif ($type eq 'I') { # Integer. print "${ind}rval = htonl(p->$F);\n"; print "${ind}rp = bp;\n"; print "${ind}rp->v = (BP) \&rval;\n"; print "${ind}rp->l = sizeof(rval);\n"; print "${ind}D5(\"Fld type I is offset %d size %d $Y.$F\"\n"; print "${ind}\t,Pdiff(&p->$F,p),sizeof(p->$F));\n"; } elsif ($type eq 'S') { # String. print "${ind}rp = bp;\n"; print "${ind}rp->v = (BP)\&(p->$F[0]);\n"; print "${ind}rp->l = $s;\n"; print "${ind}D5(\"Fld type S is offset %d size %d $Y.$F[0]\"\n"; print "${ind}\t,Pdiff(rp->v,p),rp->l);\n"; } elsif ($type eq 'B') { # Byte vector. print "${ind}rp = bp;\n"; print "${ind}rp->v = (BP) (p->$F);\n"; print "${ind}rp->l = $s;\n"; print "${ind}D5(\"Fld type B is offset %d size %d $Y.$F\"\n"; print "${ind}\t,Pdiff(rp->v,p),rp->l);\n"; } else { print STDERR "$0: RVAL type unknown; need [BSI] option.\n"; } } elsif (/^(\s+)RBAD;/){ # Generate bad--val code depending on type. $ind = $1; # Preserve the indentation for readability. if (!$type) { # Complain if type arg omitted. print STDERR "Can't expand RVAL; need 1-char type arg.\n"; } elsif ($type eq 'I') { # Integer. print "${ind}rval = htonl(f_value);\n"; print "${ind}rp = bp;\n"; print "${ind}rp->v = (BP) \&rval;\n"; print "${ind}rp->l = sizeof(rval);\n"; } elsif ($type eq 'S') { # String. print "${ind}rp = bp;\n"; print "${ind}rp->v = (BP)unknown;\n"; print "${ind}rp->l = Strlen(unknown);\n"; } elsif ($type eq 'B') { # Byte vector. print "${ind}rp = bp;\n"; print "${ind}rp->v = (BP)unknown;\n"; print "${ind}rp->l = Strlen(unknown);\n"; } else { print STDERR "$0: RBAD type unknown; need [BSI] option.\n"; } } elsif (/^(\s+)SVAL;/){ # Generate set-val code depending on type. $ind = $1; # Preserve the indentation for readability. $var = "${t}_${v}"; if (!$type) { # Complain if type arg omitted. print STDERR "Can't expand RVAL; need 1-char type arg.\n"; } elsif ($type eq 'I') { # Integer. print "${ind}$var = htonl(ap->v.i);\n"; print "${ind}D4(\"$var=%d.\",$var);\n"; } elsif ($type eq 'B') { # String. print "${ind}MakBlkM(&$var,ap->p.s.v,ap->p.s.l,\"$var\");\n"; print "${ind}D4(\"$var=%s len=%d.\",DspSV($var),ap->p.s.l);\n"; } elsif ($type eq 'S') { # String. print "${ind}MakBlkM(&$var,ap->p.s.v,ap->p.s.l,\"$var\");\n"; print "${ind}D4(\"$var=%s len=%d.\",DspSV($var),ap->p.s.l);\n"; } else { print STDERR "$0: SVAL type unknown; need [BSI] option.\n"; } } else { # Make all possible substitutions in the line. for $x (keys x) { $pat = "$x$x$x"; $rpl = "$x{$x}"; s/$pat/$rpl/g; } print; } }