diff --git a/src/dbHost/DBD/Base.pm b/src/dbHost/DBD/Base.pm index 1c545bd1c..e58d9bc26 100644 --- a/src/dbHost/DBD/Base.pm +++ b/src/dbHost/DBD/Base.pm @@ -76,11 +76,14 @@ sub identifier { sub escapeCcomment { ($_) = @_; - s/\*\//**/; + s/\*\//**/g; return $_; } sub escapeCstring { + ($_) = @_; + # How to do this? + return $_; } diff --git a/src/dbHost/DBD/Menu.pm b/src/dbHost/DBD/Menu.pm index 10fff09e5..a96690cdb 100644 --- a/src/dbHost/DBD/Menu.pm +++ b/src/dbHost/DBD/Menu.pm @@ -39,12 +39,28 @@ sub legal_choice { sub toDeclaration { my $this = shift; + my $name = $this->name; my @choices = map { "\t" . @{$_}[0] . "\t/* " . escapeCcomment(@{$_}[1]) . " */" } $this->choices; return "typedef enum {\n" . - join(",\n", @choices) . - "\n} " . $this->name . ";\n"; + join(",\n", @choices) . + "\n\t${name}_NUM_CHOICES\n" . + "} $name;\n"; +} + +sub toDefinition { + my $this = shift; + my $name = $this->name; + my @strings = map { + "\t\"" . escapeCstring(@{$_}[1]) . "\"" + } $this->choices; + return "static const char * const ${name}MenuData = {\n" . + join(",\n", @strings) . "};\n\n" . + "dbMenu ${name}MenuData = {\n" . + "\t\"" . escapeCstring(name) . "\",\n" . + "\t${name}_NUM_CHOICES,\n" . + "\t${name}ChoiceStrings\n};\n"; } 1; diff --git a/src/dbHost/DBD/Recfield.pm b/src/dbHost/DBD/Recfield.pm index 63d7d0d59..9b3b76ee6 100644 --- a/src/dbHost/DBD/Recfield.pm +++ b/src/dbHost/DBD/Recfield.pm @@ -29,7 +29,7 @@ our %field_attrs = ( promptgroup => qr/^GUI_\w+$/, prompt => qr/^.*$/, special => qr/^(?:SPC_\w+|\d{3,})$/, - pp => qr/^(?:YES|NO|TRUE|FALSE)$/, + pp => qr/^(?:TRUE|FALSE)$/, interest => qr/^\d+$/, base => qr/^(?:DECIMAL|HEX)$/, size => qr/^\d+$/, @@ -102,9 +102,9 @@ sub check_valid { sub toDeclaration { my ($this, $ctype) = @_; my $name = lc $this->name; - my $result = "$ctype $name;"; + my $result = sprintf " %-19s %-12s", $ctype, "$name;"; my $prompt = $this->attribute('prompt'); - $result .= "\t/* $prompt */" if defined $prompt; + $result .= "/* $prompt */" if defined $prompt; return $result; } @@ -133,9 +133,9 @@ sub toDeclaration { my ($this) = @_; my $name = lc $this->name; my $size = $this->attribute('size'); - my $result = "char ${name}[${size}];"; + my $result = sprintf " %-19s %-12s", 'char', "${name}[${size}];"; my $prompt = $this->attribute('prompt'); - $result .= "\t/* $prompt */" if defined $prompt; + $result .= "/* $prompt */" if defined $prompt; return $result; } @@ -416,10 +416,10 @@ sub check_valid { sub toDeclaration { my ($this) = @_; - my $name = lc $this->name; - my $result = $this->attribute('extra') . ";"; + my $extra = $this->attribute('extra'); + my $result = sprintf " %-32s", "$extra;"; my $prompt = $this->attribute('prompt'); - $result .= "\t/* $prompt */" if defined $prompt; + $result .= "/* $prompt */" if defined $prompt; return $result; } diff --git a/src/dbHost/DBD/Recordtype.pm b/src/dbHost/DBD/Recordtype.pm index 3160a70f2..dd361ce47 100644 --- a/src/dbHost/DBD/Recordtype.pm +++ b/src/dbHost/DBD/Recordtype.pm @@ -79,8 +79,8 @@ sub toDeclaration { } $this->fields; my $name = $this->name; $name .= "Record" unless $name eq "dbCommon"; - return "typedef struct $name {\n\t" . - join("\n\t", @fields) . + return "typedef struct $name {\n" . + join("\n", @fields) . "\n} $name;\n"; } diff --git a/src/dbHost/dbToMenuH b/src/dbHost/dbToMenuH index 953160743..4f5b31748 100755 --- a/src/dbHost/dbToMenuH +++ b/src/dbHost/dbToMenuH @@ -48,6 +48,11 @@ if ($opt_D) { while (($name, $menu) = each %{$menus}) { print OUTFILE $menu->toDeclaration; } - print OUTFILE "\n#endif /* $guard_name */\n"; + print OUTFILE "\n#ifdef GEN_MENU_CHOICES\n\n"; + while (($name, $menu) = each %{$menus}) { + print OUTFILE $menu->toDefinition; + } + print OUTFILE "\n#endif /* GEN_MENU_CHOICES */\n", + "#endif /* $guard_name */\n"; close OUTFILE; } diff --git a/src/dbHost/dbToRecordtypeH b/src/dbHost/dbToRecordtypeH index a009fec43..c4a2e2b78 100755 --- a/src/dbHost/dbToRecordtypeH +++ b/src/dbHost/dbToRecordtypeH @@ -49,12 +49,7 @@ if ($opt_D) { # Output dependencies only, to stdout print OUTFILE "/* $outfile generated from $infile */\n\n", "#ifndef $guard_name\n", "#define $guard_name\n\n", - "#include \"ellLib.h\"\n", - "#include \"epicsMutex.h\"\n", - "#include \"link.h\"\n", - "#include \"epicsTime.h\"\n", - "#include \"epicsTypes.h\"\n", - "#include \"epicsExport.h\"\n\n", + "#include \"recDecls.h\"\n\n", "#ifdef __cplusplus\n", "extern \"C\" {\n", "#endif\n\n"; @@ -69,18 +64,94 @@ if ($opt_D) { # Output dependencies only, to stdout print OUTFILE $rtyp->toDeclaration; unless ($rn eq 'dbCommon') { - print OUTFILE "\nenum {\n", - join(",\n", map { "\t${rn}Record$_" } $rtyp->field_names), - "\n};\n\n"; - + my $n=0; + print OUTFILE "\ntypedef enum {\n", + join(",\n", map { "\t${rn}Record$_ = " . $n++ } $rtyp->field_names), + "\n} ${rn}FieldIndex;\n\n"; print OUTFILE "#ifdef GEN_SIZE_OFFSET\n", - "static int ${rn}RecordSizeOffset(dbRecordType *pdbRecordType)\n", - "{\n"; - # ... FIXME: add size-offset data, etc. - print OUTFILE "}\n\n", - "epicsExportRegistrar(${rn}RecordSizeOffset);\n\n"; + join("\n", + map { "static const char ${rn}FieldName$_\[] = \"$_\";" } + $rtyp->field_names), + "\n\n"; + $n=0; + print OUTFILE "static const dbRecordData ${rn}RecordRecordData;\n\n", + "static dbFldDes ${rn}RecordFieldData[] = {\n", + join(",\n", map { + my $fn = $_->name; + " { ${rn}RecordFieldName$fn," . + $_->dbf_type . ',"' . + $_->attribute('initial') . '",' . + ($_->attribute('special') || '0') . ',' . + ($_->attribute('pp') || 'FALSE') . ',' . + ($_->attribute('interest') || '0') . ',' . + ($_->attribute('asl') || 'ASL0') . ',' . + $n++ . ",\n\t\&${rn}RecordRecordData," . + "GEOMETRY_DATA(${rn}Record," . lc($fn) . ') }'; + } $rtyp->fields), + "\n};\n\n"; + print OUTFILE "static const short ${rn}RecordFieldLinks[] = {\n", + join(",\n", map { + " ${rn}Record" . $_->name; + } grep { + $_->dbf_type =~ m/^DBF_(IN|OUT|FWD)LINK/; + } $rtyp->fields), + "\n};\n\n"; + my @sorted_names = sort $rtyp->field_names; + print OUTFILE "static const char * const ${rn}RecordFieldSortedNames[] = {\n", + join(",\n", map { + " ${rn}RecordFieldName$_" + } @sorted_names), + "\n};\n\n"; + print OUTFILE "static const short ${rn}RecordFieldSortedIndex[] = {\n", + join(",\n", map { + " ${rn}Record$_" + } @sorted_names), + "\n};\n\n"; + print OUTFILE "extern rset ${rn}RSET;\n\n", + "static const dbRecordData ${rn}RecordRecordData = {\n", + " \"$rn\",\n", + " sizeof(${rn}Record),\n", + " NELEMENTS(${rn}RecordFieldData),\n", + " ${rn}RecordFieldData,\n", + " ${rn}RecordVAL,\n", + " \&${rn}RecordFieldData[${rn}RecordVAL],\n", + " NELEMENTS(${rn}RecordFieldLinks),\n", + " ${rn}RecordFieldLinks,\n", + " ${rn}RecordFieldSortedNames,\n", + " ${rn}RecordFieldSortedIndex,\n", + " \&${rn}RSET\n", + "};\n\n"; + my @menu_fields = grep { + $_->dbf_type eq 'DBF_MENU' + } $rtyp->fields; + my %menu_uniq; + my @menu_names = grep { + !$menu_uniq{$_}++ + } map { + $_->attribute('menu') + } @menu_fields; + print OUTFILE join ("\n", map { + "extern dbMenu ${_}MenuData;" + } @menu_names), "\n\n"; + print OUTFILE "dbRecordType * ${rn}RecordRegistrar(dbBase *pbase, int nDevs)\n", + "{\n", + " dbRecordType *prt;\n"; + print OUTFILE map { + " dbRegisterMenu(pbase, \&${_}MenuData);\n" + } @menu_names; + print OUTFILE map { + " ${rn}RecordFieldData[${rn}Record" . + $_->name . + "].typDat.pmenu = \&" . + $_->attribute('menu') . + "MenuData;\n" + } @menu_fields; + # ... FIXME ... Missing prt, devMenu, CT_HEX/CT_DECIMAL + print OUTFILE " return prt;\n}\n\n", + "epicsExportRegistrar(${rn}RecordSizeOffset);\n", + "#endif\n"; } - print OUTFILE "#ifdef __cplusplus\n", + print OUTFILE "\n#ifdef __cplusplus\n", "} /* extern \"C\" */\n", "#endif\n\n", "#endif /* $guard_name */\n"; diff --git a/src/dbHost/macLib.pm b/src/dbHost/macLib.pm index 22020acc7..e4065483c 100644 --- a/src/dbHost/macLib.pm +++ b/src/dbHost/macLib.pm @@ -39,23 +39,8 @@ sub new ($@) { return $this; } -sub putValue ($$$) { - my ($this, $name, $raw) = @_; - if (exists $this->{macros}[0]{$name}) { - if (!defined $raw) { - delete $this->{macros}[0]{$name}; - } else { - $this->{macros}[0]{$name}{raw} = $raw; - } - } else { - my $entry = macLib::entry->new($name, 'macro'); - $entry->{raw} = $raw; - $this->{macros}[0]{$name} = $entry; - } - $this->{dirty} = 1; -} - sub installList ($@) { + # Argument is a list of strings which are arguments to installMacros my $this = shift; while (@_) { $this->installMacros(shift); @@ -63,11 +48,12 @@ sub installList ($@) { } sub installMacros ($$) { + # Argument is a string: a=1,b="2",c,d='hello' my $this = shift; $_ = shift; until (defined pos($_) and pos($_) == length($_)) { m/\G \s* /xgc; # Skip whitespace - if (m/\G ( \w+ ) \s* /xgc) { + if (m/\G ( [A-Za-z0-9_-]+ ) \s* /xgc) { my ($name, $val) = ($1); if (m/\G = \s* /xgc) { # The value follows, handle quotes and escapes @@ -93,6 +79,22 @@ sub installMacros ($$) { } } +sub putValue ($$$) { + my ($this, $name, $raw) = @_; + if (exists $this->{macros}[0]{$name}) { + if (!defined $raw) { + delete $this->{macros}[0]{$name}; + } else { + $this->{macros}[0]{$name}{raw} = $raw; + } + } else { + my $entry = macLib::entry->new($name, 'macro'); + $entry->{raw} = $raw; + $this->{macros}[0]{$name} = $entry; + } + $this->{dirty} = 1; +} + sub pushScope ($) { my ($this) = @_; unshift @{$this->{macros}}, {};