summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1997-06-16 21:30:07 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1997-06-16 21:30:07 +0000
commitd4bc481ded89c54759a5cd2c51565486d72312c6 (patch)
tree0c96a4f57f6d726ad7b8cd492c3d1fde8e4c0328 /doc
parentnew file (diff)
downloadrtems-d4bc481ded89c54759a5cd2c51565486d72312c6.tar.bz2
Initial revision
Diffstat (limited to 'doc')
-rw-r--r--doc/tools/pdl2texi/Drive.d890
-rw-r--r--doc/tools/pdl2texi/Makefile66
-rw-r--r--doc/tools/pdl2texi/afcc.texi94
-rw-r--r--doc/tools/pdl2texi/base.h116
-rw-r--r--doc/tools/pdl2texi/drive.d874
-rw-r--r--doc/tools/pdl2texi/main.c3256
-rw-r--r--doc/tools/pdl2texi/t1.d52
7 files changed, 5348 insertions, 0 deletions
diff --git a/doc/tools/pdl2texi/Drive.d b/doc/tools/pdl2texi/Drive.d
new file mode 100644
index 0000000000..82c3de020e
--- /dev/null
+++ b/doc/tools/pdl2texi/Drive.d
@@ -0,0 +1,890 @@
+OBJECT: Drive
+ DESCRIPTION:
+ This object provides an interface to the elevation/azimuth
+ drive system(ECA).
+ THEORY OF OPERATION:
+ This object encapsulates the turret drive. The object provides
+ an interface to control the turret drive. A method is provided
+ to set the azimuth and elevation rate of the drive. Methods are
+ provided to request the drive to run in stabilized or power mode
+ and set the drive speed to high or low. A method is also provided
+ to allow for drift adjust.
+
+ This object also tracks drive system on hours. It gets the hours
+ from the EEPROM data, allows the hours to be set, updates the
+ hours via the activation and deactivation of the drive, and
+ provides access to the hours.
+
+ + This is the first bullet.
+ + This is the second bullet.
+ + This is the third bullet.
+ + This is the fourth bullet.
+ + This is the fifth bullet.
+
+ The object also provides methods to access azimuth and elevation
+ displacement, and methods to process changes in the hardware
+ discretes drive on, stabilized mode, thermal fault and fault.
+
+ The object also provides methods to enable and disable
+ both the remote and turret power interlocks which determine if
+ the drive can be driven by the remote or turret handstation
+ respectively.
+
+ATTRIBUTE DESCRIPTIONS:
+
+
+ATTRIBUTE: Azimuth_displacement
+ DESCRIPTION:
+ This attribute represents the current azimuth displacement
+ of the turret.
+ TYPE: floating point
+ RANGE: 0-0
+ UNITS: degrees
+ REQUIREMENTS:
+ AFS 8.2.11 Receive Azimuth Displacement and Elevation Displacement
+ AIS 5.2.6 Azimuth Displacement analog
+
+
+ATTRIBUTE: Azimuth_rate
+ DESCRIPTION:
+ Azimuth rate command for movement of the turret.
+ TYPE: floating point
+ RANGE: X-Y
+ UNITS: degrees / second
+ DEFAULT: none
+ REQUIREMENTS:
+ AFS 8.2.3 Send Azimuth and Elevation Rate to ECA
+ AIS 5.3.4 Elevation Rate analog
+ AIS 5.3.5 Azimuth Rate analog
+
+
+ATTRIBUTE: Drift_adjust
+ DESCRIPTION:
+ This attribute represents the current drift adjustment mode
+ of the ECA turret drive.
+ TYPE: enumerated
+ MEMBERS:
+ ADJUST_OFF - drift adjust mode is OFF
+ ADJUST_ON - drift adjust mode is ON
+ REQUIREMENTS:
+ AFS 8.2.6 Capable of turret drift adjustment
+ AIS 5.3.1 Drift Adjust discrete
+
+
+ATTRIBUTE: Drive_on
+ DESCRIPTION:
+ Current status of the turret drive. The turret drive may either be
+ switched on or off.
+ TYPE: boolean
+ MEMBERS:
+ FALSE - turret drive is off
+ TRUE - turret drive is on
+ DEFAULT: FALSE
+ REQUIREMENTS:
+ AFS 8.2.9 Monitor Drive System On
+ AIS 5.2.1 Drive System On discrete
+
+
+ATTRIBUTE: Drive_system_hours
+ DESCRIPTION:
+ Total number of hours drive has been activated.
+ TYPE: integer
+ RANGE: 0 - +INFINITY
+ UNITS: seconds
+ REQUIREMENTS:
+ AFS 4.11 Respond to CDT elapsed time indicator key
+
+
+ATTRIBUTE: Elevation_displacement
+ DESCRIPTION:
+ This attribute represents the current elevation displacement
+ of the turret.
+ TYPE: floating point
+ RANGE: 0-0
+ UNITS: degrees
+ REQUIREMENTS:
+ AFS 8.2.11 Receive Azimuth Displacement and Elevation Displacement
+ AIS 5.2.7 Elevation Displacement analog
+
+
+ATTRIBUTE: Elevation_rate
+ DESCRIPTION:
+ Elevation rate command for movement of the turret.
+ TYPE: floating point
+ RANGE: X - Y
+ UNITS: degrees / second
+ DEFAULT: none
+ REQUIREMENTS:
+ AFS 8.2.3 Send Azimuth and Elevation Rate to ECA
+ AIS 5.3.4 Elevation Rate analog
+ AIS 5.3.5 Azimuth Rate analog
+
+
+ATTRIBUTE: Fault
+ DESCRIPTION:
+ This attribute denotes whether a turret malfunction has occurred.
+ TYPE: boolean
+ MEMBERS:
+ TRUE - a turret malfunction has occurred
+ FALSE - no turret malfunction has occurred
+ DEFAULT: FALSE
+ REQUIREMENTS:
+ AFS 8.2.7 Check for ECA failure indication
+ AIS 5.2.4 Turret Drive Malfunction discrete
+
+
+ATTRIBUTE: Mode
+ DESCRIPTION:
+ Current requested drive mode.
+ TYPE: enumerated
+ MEMBERS:
+ POWER - operate in POWER mode
+ STAB - operate in STABILIZED mode
+ DEFAULT: POWER
+ REQUIREMENTS:
+ bogus requirement
+
+
+ATTRIBUTE: Remote_power_interlock_position
+ DESCRIPTION:
+ This is the status of the remote's power interlock.
+ TYPE: enumerated
+ MEMBERS:
+ OPEN - relay is open
+ CLOSED - relay is closed
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+
+
+ATTRIBUTE: Speed
+ DESCRIPTION:
+ Current speed mode of the ECA turret drive.
+ TYPE: enumerated
+ MEMBERS:
+ LOW_SPEED - turret drive does not allow the maximum rate
+ HIGH_SPEED - turret drive allows the maximum rate
+ DEFAULT: HIGH
+ REQUIREMENTS:
+ AFS 8.2.5 Control Turret
+ AIS 5.3.3 Turret High Speed Mode discrete
+
+
+ATTRIBUTE: Stabilized_mode
+ DESCRIPTION:
+ Current drive mode indicating whether the ECA electronics are
+ operating in Stabilized mode or Power mode.
+ TYPE: boolean
+ MEMBERS:
+ FALSE - not operating in STABILIZED mode
+ TRUE - operating in STABILIZED mode
+ DEFAULT: FALSE
+ REQUIREMENTS:
+ AFS 8.2.8 Monitor Turret Stab Mode Indicate
+ AIS 5.2.3 Turret Stab Mode Indicate discrete
+
+
+ATTRIBUTE: State
+ DESCRIPTION:
+ Current state of the turret drive.
+ TYPE: enumerated
+ MEMBERS:
+ ACTIVATED - turret drive is ON and active
+ DEACTIVATED - turret drive is ON but deactivated
+ DEFAULT: DEACTIVATED
+ REQUIREMENTS:
+ AFS 8.2.4 Set Plam Grips Active
+ AIS 5.3.2 Palm Grips Active discrete
+
+
+ATTRIBUTE: Thermal_fault
+ DESCRIPTION:
+ This attribute denotes whether a turret thermal fault has occurred.
+ TYPE: boolean
+ MEMBERS:
+ TRUE - a turret thermal fault has occurred
+ FALSE - no turret thermal fault has occurred
+ DEFAULT: FALSE
+ REQUIREMENTS:
+ AFS 8.2.7 Check for ECA failure indication
+ AIS 5.2.2 Turret ECA Thermal Failure discrete
+
+
+ATTRIBUTE: Turret_power_interlock_position
+ DESCRIPTION:
+ This is the status of the turret's power interlock.
+ TYPE: enumerated
+ MEMBERS:
+ OPEN - relay is open
+ CLOSED - relay is closed
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+
+
+ASSOCIATION DESCRIPTIONS: none
+
+ABSTRACT TYPE DESCRIPTIONS:
+
+ABSTRACT TYPE: Drift_adjust_t
+ DESCRIPTION:
+ This abstract type represents the current drift adjustment mode
+ of the ECA turret drive.
+ VISIBILITY: public
+ DERIVATION: enumerated
+ MEMBERS:
+ ADJUST_OFF = 0 - drift adjust mode is OFF
+ ADJUST_ON = 1 - drift adjust mode is ON
+ REQUIREMENTS:
+ AIS 5.3.1 Drift Adjust discrete
+
+ABSTRACT TYPE: Interlock_status
+ DESCRIPTION:
+ An interlock state being OPEN or CLOSED.
+ VISIBILITY: private
+ DERIVATION: enumerated
+ MEMBERS:
+ OPEN - interlock relay is in the open state
+ CLOSED - interlock relay is in the closed state
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+
+ABSTRACT TYPE: Mode
+ DESCRIPTION:
+ This type specifies the drive mode of the ECA turret drive.
+ VISIBILITY: public
+ DERIVATION: enumerated
+ MEMBERS:
+ POWER - operate in POWER mode
+ STAB - operate in STABILIZED mode
+
+ABSTRACT TYPE: Speed
+ DESCRIPTION:
+ This type specifies the Speed mode of the ECA turret drive.
+ VISIBILITY: public
+ DERIVATION: enumerated
+ MEMBERS:
+ LOW_SPEED = 0 - turret drive does not allow the maximum rate
+ HIGH_SPEED = 1 - turret drive allows the maximum rate
+ REQUIREMENTS:
+ AIS 5.3.3 Turret High Speed Mode discrete
+
+ABSTRACT TYPE: State_t
+ DESCRIPTION:
+ This type specifies the state of the turret drive.
+ VISIBILITY: private
+ DERIVATION: enumerated
+ MEMBERS:
+ DEACTIVATED - turret drive is ON but deactivated
+ ACTIVATED - turret drive is ON and active
+
+DATA ITEM DESCRIPTIONS:
+
+DATA ITEM: Azimuth_displacement_control
+ DESCRIPTION:
+ This data item contains the Azimuth_displacement analog control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Azimuth_rate_control
+ DESCRIPTION:
+ This data item contains the Azimuth_rate analog control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Drift_adjust_control
+ DESCRIPTION:
+ This data item contains the Drift_adjust discrete control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Drive_activate_control
+ DESCRIPTION:
+ This data item contains the activate drive relay control information.
+ TYPE: handle
+
+
+DATA ITEM: Drive_activated_timestamp
+ DESCRIPTION:
+ This data item stores the timestamp of the last time the drive was
+ activated. It will be used to compute the activated time when a
+ deactivate is received.
+ TYPE: time_t
+ DEFAULT: none
+ NOTES:
+ see C library for data type information
+
+
+DATA ITEM: Drive_on
+ DESCRIPTION:
+ The current status of the turret drive representing whether
+ the drive is on or off.
+ TYPE: boolean
+ DEFAULT: FALSE
+
+
+DATA ITEM: Drive_on_control
+ DESCRIPTION:
+ This data item contains the Drive_on discrete flag control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Drive_system_hours
+ DESCRIPTION:
+ This data item stores the actual time the drive has been active.
+ This value will be output by the Get_time method and will be set
+ by the Set_time method.
+ TYPE: integer
+ RANGE: 0 - +INFINITY
+ UNITS: seconds
+ DEFAULT: 0
+
+
+DATA ITEM: Elevation_rate_control
+ DESCRIPTION:
+ This data item contains the Elevation_rate analog control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Elevation_displacement_control
+ DESCRIPTION:
+ This data item contains the Elevation_displacement analog control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Fault_control
+ DESCRIPTION:
+ This data item contains the Fault discrete flag control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Remote_power_interlock_control
+ DESCRIPTION:
+ This data item contains the Remote_power_interlock relay control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Stabilized_mode_control
+ DESCRIPTION:
+ This data item contains the Stabilized_mode discrete flag control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: State
+ DESCRIPTION:
+ The current state of the turret drive representing an activated or
+ deactivated drive.
+ TYPE: State_t
+ DEFAULT: DEACTIVATED
+
+
+DATA ITEM: Thermal_fault_control
+ DESCRIPTION:
+ This data item contains the Thermal_fault discrete flag control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Turret_power_interlock_control
+ DESCRIPTION:
+ This data item contains the Turret_power_interlock relay control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Turret_power_interlock_status
+ DESCRIPTION:
+ The accurate status of the turret power interlock relay. This value
+ will be used to control the relay during a transition from the remote
+ back to the turret console.
+ TYPE: Interlock_status
+ DEFAULT: none
+
+
+METHOD DESCRIPTIONS:
+
+METHOD: Activate
+ DESCRIPTION:
+ This method activates the turret drive system. A timestamp of the
+ activation is recorded to keep a running count of hours the drive has
+ been active.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.4 Set Palm Grips Active
+ AIS 5.3.2 Palm Grips Active discrete
+ PDL:
+
+ if Drive_on
+ if State is DEACTIVATED
+ close the Drive_activate_control relay using the Relay object
+ timestamp Drive_activated_timestamp for Drive_system_hours
+ running total
+ set State to ACTIVATED
+ else
+ already in the ACTIVATED state
+
+
+METHOD: Create
+ DESCRIPTION:
+ This method initializes the Turret Drive object. All monitors of
+ turret drive signals are initialized and/or registered. All turret
+ drive characteristics are set to their initial values.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ PDL:
+
+ set State to DEACTIVATED
+
+ get Drive_system_hours to initialize the elapsed drive time
+ from the Statistics (eeprom database) object - this is
+ stored upon shutdown in eeprom
+
+ create Fault_control using Discrete_flag object with the
+ following attributes
+ true_sense - DISCRETE_FLAG_TRUE_IS_1
+ is_buffered - false
+ is_monitored - true
+ period - 10ms
+ change_routine - Change_fault
+ change fault using initial value returned from create Fault_control
+
+ create Thermal_fault_control using Discrete_flag object with
+ the following attributes
+ true_sense - DISCRETE_FLAG_TRUE_IS_0
+ is_buffered - false
+ is_monitored - true
+ period - 10ms
+ change_routine - Change_thermal_fault
+ change thermal fault using initial value returned from create
+ Thermal_fault_control
+
+ create Stabilized_mode_control using Discrete_flag object with the
+ following attributes
+ true_sense - DISCRETE_FLAG_TRUE_IS_1
+ is_buffered - false
+ is_monitored - true
+ period - 10ms
+ change_routine - Change_stabilized_mode
+ change stabilized mode using initial value returned from create
+ Stabilized_mode_control
+
+ create Drive_on_control using Discrete_flag object with the
+ following attributes
+ true_sense - DISCRETE_FLAG_TRUE_IS_1
+ is_buffered - false
+ is_monitored - true
+ period - 10ms
+ change_routine - Change_drive_on
+ change drive on using initial value returned from create
+ Drive_on_control
+
+ create Azimuth_rate_control using the Linear_dac object
+ with the following attributes:
+ voltage_low - -10
+ voltage_high - +10
+ logical_low - -60
+ logical_high - +60
+ is_buffered - false
+ period - none
+ initial_value - 0
+
+ create Elevation_rate_control using the Linear_dac object with the
+ following attributes:
+ voltage_low - -10
+ voltage_high - +10
+ logical_low - -60
+ logical_high - +60
+ is_buffered - false
+ period - none
+ initial_value - 0
+
+ create Azimuth_displacement_control using the Linear_adc object with
+ the following attributes:
+ voltage low -
+ voltage high -
+ logical low -
+ logical high -
+ is_buffered - false
+ is_monitored - false
+ period - none
+ change_routine - none
+ delta - none
+
+ create Elevation_displacement_control using the Linear_adc object
+ with the following attributes:
+ voltage low -
+ voltage high -
+ logical low -
+ logical high -
+ is_buffered - false
+ is_monitored - false
+ period - none
+ change_routine - none
+ delta - none
+
+ create Drive_activate_control using the Relay object with the
+ following attributes:
+ open_sense - RELAY_OPEN_IS_0
+ is_buffered - false
+ period - none
+ initial_state - RELAY_OPEN
+
+ create Turret_power_interlock_control using the Relay object with
+ the following attributes:
+ open_sense - RELAY_OPEN_IS_0
+ is_buffered - false
+ period - none
+ initial_state - RELAY_OPEN
+ set Turret_power_interlock_status to OPEN
+
+ create Remote_power_interlock_control using the Relay
+ object with the following attributes:
+ open_sense - RELAY_OPEN_IS_0
+ is_buffered - false
+ period - none
+ initial_state - RELAY_OPEN
+
+ create Drift_adjust_control using the Discrete_out object with
+ following attributes:
+ is_buffered - false
+ period - 10ms
+ initial_value - ADJUST_OFF
+
+
+METHOD: Deactivate
+ DESCRIPTION:
+ This method deactivates the turret drive system. A timestamp of the
+ activation is recorded to keep a running count of hours the drive
+ has been active.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.4 Set Plam Grips Active
+ AIS 5.3.2 Palm Grips Active discrete
+ PDL:
+
+ if Drive_on
+ if State is DEACTIVATED
+ timestamp deactivate for Drive_system_hours running total
+ deactivate drive by opening the Drive_activate_control relay
+ using the Relay object
+ compute running time since last activate
+ add running time to Drive_system_hours
+ set State to DEACTIVATED
+ else
+ already in the DEACTIVATED state
+
+
+METHOD: Disable_remote_power_interlock
+ DESCRIPTION:
+ This method disables the turret power interlock safety preventing
+ the turret from being driven by the remote's handstation.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+ PDL:
+
+ open the remote power interlock relay
+ return the turret relay to its designated state defined by the
+ Turret_power_interlock_status
+
+
+METHOD: Disable_turret_power_interlock
+ DESCRIPTION:
+ This method disables the turret power interlock safety preventing
+ the turret from being driven by the turret's handstation.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+ PDL:
+
+ Deactivate the Drive object
+ open the turret power interlock relay
+ set Turret_power_interlock_status to OPEN
+
+
+METHOD: Enable_remote_power_interlock
+ DESCRIPTION:
+ This method will enable the remote power interlock to allow
+ the turret to be driven from the remote station.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+ NOTES:
+ At this time the turret's power interlock is opened to avoid
+ having both relays closed at a time.
+ PDL:
+
+ if Drive_on
+ open the turret power interlock relay using the Relay object
+ close the remote power interlock relay using the Relay object
+
+
+METHOD: Enable_turret_power_interlock
+ DESCRIPTION:
+ This method will enable the turret power interlock to allow
+ the turret to be driven from the turret station.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+ NOTES:
+ At this time the closed state is saved to allow the correct state
+ to be returned to in the event a remote overrides the turret and the
+ remote gives up its control, we must return to the previous state of
+ the turret power interlock.
+ PDL:
+
+ if Drive_on
+ close the turret power interlock relay using the Relay object
+
+ set the Turret_power_interlock_status to CLOSED to return to
+ when remote gives up control
+
+
+METHOD: Get_AZ_EL_displacement
+ DESCRIPTION:
+ This method returns the current azimuth displacement and elevation
+ displacement from the ECA.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS:
+ current azimuth displacement value
+ current elevation displacement value
+ REQUIREMENTS:
+ AFS 8.2.11 Receive Azimuth Displacement and Elevation Displacement
+ AIS 5.2.6 Azimuth Displacement analog
+ AIS 5.2.7 Elevation Displacement analog
+ NOTES:
+ Currently supported as an on-demand type of signal. May change to a
+ monitored analog signal.
+ PDL:
+
+ if Drive_on
+ get and return current azimuth displacement and current elevation
+ displacement from ECA using the Linear_ADC object
+
+
+METHOD: Get_hours
+ DESCRIPTION:
+ This method returns the current value contained in the elapsed
+ turret drive active time.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS:
+ elapsed turret drive time - the current elasped turret drive time
+ REQUIREMENTS:
+ bogus requirements
+ REFERENCES:
+ AFS 4.11 Respond to CDT elapsed time indicator key
+ NOTES:
+ bogus notes
+ PDL:
+
+ return the current value for Drive_system_hours
+
+
+METHOD: Set_drift_adjust
+ DESCRIPTION:
+ This method provides the ability to set the drift adjust to the
+ value represented by the handstation. Drift adjust is either ON
+ or OFF.
+ VISIBILITY: public
+ INPUTS:
+ value - new drift adjust value
+ ADJUST_OFF - drift adjust mode is OFF
+ ADJUST_ON - drift adjust mode is ON
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.6 Capable of turret drift adjustment
+ AIS 5.3.1 Drift Adjust discrete
+ PDL:
+
+ if Drive_on
+ set drift adjust discrete to value using Discrete_out object
+
+METHOD: Set_hours
+ DESCRIPTION:
+ This method will set the turret drive activated elapsed time value
+ to the specified value.
+ VISIBILITY: public
+ INPUTS:
+ new_elapsed_time_value - specified turret drive elapsed time value
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 4.11 Respond to CDT elapsed time indicator key
+ PDL:
+
+ set the value of Drive_system_hours to the value specified by
+ new_elapsed_time_value
+
+
+METHOD: Set_mode
+ DESCRIPTION:
+ This method sets the requested mode of the turret drive.
+ VISIBILITY: public
+ INPUTS:
+ mode - new requested mode
+ POWER - operating in POWER mode
+ STAB - operating in STABILIZED mode
+ OUTPUTS: none
+ REQUIREMENTS:
+ bogus requirements
+ PDL:
+ if mode is POWER
+ set drive mode switchlight to PWR_LAMP using the Console object
+ else if mode is STAB
+ set drive mode switchlight to STB_LAMP using the Console object
+
+
+METHOD: Set_rate
+ DESCRIPTION:
+ This method provides the ability to send azimuth and elevation rates
+ to the drive. Two parameters are used as input to designate the
+ corresponding rates. These parameters must be in degrees per second.
+ VISIBILITY: public
+ INPUTS:
+ azimuth rate - new azimuth rate in degress per second
+ elevation rate - new elevation rate in degress per second
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.3 Send Azimuth and Elevation Rate to ECA
+ AIS 5.3.4 Elevation Rate analog
+ AIS 5.3.5 Azimuth Rate analog
+ NOTES:
+ May need to couple these analogs with an interface driver to close
+ the window between writes and conversions.
+ PDL:
+
+ if Drive_on
+ send the new azimuth rate to the Azimuth analog
+ send the new elevation rate to Elevation analog
+
+
+METHOD: Set_speed
+ DESCRIPTION:
+ This method sets the turret drive speed mode to the specified value
+ either high or low based on user input.
+ VISIBILITY: public
+ INPUTS:
+ new_speed_value - new value to set the turret speed to
+ LOW_SPEED - turret drive does not allow the maximum rate
+ HIGH_SPEED - turret drive allows the maximum rate
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.5 Control Turret
+ AIS 5.3.3 Turret High Speed Mode discrete
+ PDL:
+
+ if Drive_on
+ set turret drive high speed mode discrete to the new_speed_value
+ using Discrete_out object
+
+
+METHOD: Change_drive_on
+ DESCRIPTION:
+ This method will be used to report a transition of the drive system
+ on discrete.
+ VISIBILITY: private
+ INPUTS:
+ value - new drive system on value
+ FALSE - indicates drive not on
+ TRUE - indicates drive on
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.9 Monitor Drive System On
+ AIS 5.2.1 Drive System On discrete
+ REFERENCES:
+ bogus references
+ NOTES:
+ bogus notes
+ PDL:
+
+ set Drive_on to value
+ if Drive_on is FALSE
+ deactivate the turret drive using the Drive object
+
+
+METHOD: Change_fault
+ DESCRIPTION:
+ This method will be used to indicate that a turret malfunction
+ has been recognized by the turret drive.
+ VISIBILITY: private
+ INPUTS:
+ value - new value resulting from a fault discrete change
+ FALSE - indicates no fault
+ TRUE - indicates fault
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.7 Check for ECA failure indication
+ AIS 5.2.4 Turret Drive Malfunction discrete
+ PDL:
+
+ if value
+ send turret fault message using the Display object
+ else
+ return
+
+
+METHOD: Change_stabilized_mode
+ DESCRIPTION:
+ This method will determine a transition from STAB mode to POWER mode.
+ It will set the stab mode lamp on the console.
+ VISIBILITY: private
+ INPUTS:
+ value - new value resulting from a stab mode discrete change
+ FALSE - indicates not stabilized mode
+ TRUE - indicates stabilized mode
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.8 Monitor Turret Stab Mode Indicate
+ AIS 5.2.3 Turret Stab Mode Indicate discrete
+ PDL:
+
+ if value
+ set STAB mode light to LAMP_ON using the Console object
+ else value indicates not stabilized mode
+ set STAB mode light to LAMP_OFF using the Console object
+
+
+METHOD: Change_thermal_fault
+ DESCRIPTION:
+ This method will be used to indicate that a thermal fault has been
+ recognized by the turret drive.
+ VISIBILITY: private
+ INPUTS:
+ value - new value resulting from a thermal fault discrete change
+ FALSE - indicates no thermal fault
+ TRUE - indicates thermal fault
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.7 Check for ECA failure indication
+ AIS 5.2.2 Turret ECA Thermal Failure discrete
+ PDL:
+
+ if value
+ send thermal fault message using the Display object
+ else
+ return
+
+TASK DESCRIPTIONS: none
+
+ENDOBJECT: Drive
diff --git a/doc/tools/pdl2texi/Makefile b/doc/tools/pdl2texi/Makefile
new file mode 100644
index 0000000000..ed2a67c3ab
--- /dev/null
+++ b/doc/tools/pdl2texi/Makefile
@@ -0,0 +1,66 @@
+#
+# COPYRIGHT (c) 1996-1997.
+# On-Line Applications Research Corporation (OAR).
+# All rights reserved.
+#
+# $Id$
+#
+
+CC=gcc
+#CFLAGS=-O4 -fomit-frame-pointer
+CFLAGS=-g
+
+PROJECT=afcc
+TEXINPUTS=/home/gnu/work/binutils-2.6/texinfo:.
+BASE=Drive
+FILES=afcc.texi $(BASE).txt
+PROG=pdl2texi
+
+all: $(PROG)
+
+$(BASE).texi: $(BASE).d ./$(PROG)
+ ./$(PROG) $(BASE).d
+
+$(PROG): main.o chain.o
+ gcc -static main.o chain.o -o $(PROG)
+
+drive: Drive
+Drive: $(BASE).txt
+ /usr1/home/joel/tmp/makeinfo $(PROJECT).texi
+
+main.o: main.c base.h
+
+chain.o: chain.c
+
+dvi: $(PROJECT).dvi
+ps: $(PROJECT).ps
+info: Drive
+html: $(PROJECT).texi $(BASE).txt
+ ../textools/texi2html $(PROJECT).texi
+
+$(BASE).txt: $(BASE).d
+ ./$(PROG) -v -p "Turret Subsystem" -u "Turret Subsystem" $(BASE).d
+
+$(PROJECT).ps: $(PROJECT).dvi
+ dvips -o $(PROJECT).ps $(PROJECT).dvi
+
+$(PROJECT).dvi: $(FILES)
+ texi2dvi $(PROJECT).texi
+
+view:
+ test -r $(PROJECT).ps && ghostview $(PROJECT).ps
+
+tests: test test1
+
+test: $(PROG)
+ rm -f $(BASE).texi
+ ./$(PROG) -v -p "Turret Subsystem" -u "Turret Subsystem" $(BASE).d
+
+test1:
+ rm -f t1.txt
+ ./$(PROG) -v t1.d
+
+clean:
+ rm -f *.o $(PROG) *.txt core *.html $(PROJECT) Drive.texi
+ rm -f *.dvi *.ps *.log *.aux *.cp *.fn *.ky *.pg *.toc *.tp *.vr $(BASE)
+
diff --git a/doc/tools/pdl2texi/afcc.texi b/doc/tools/pdl2texi/afcc.texi
new file mode 100644
index 0000000000..ed5333b5be
--- /dev/null
+++ b/doc/tools/pdl2texi/afcc.texi
@@ -0,0 +1,94 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename afcc
+@settitle AFCC Internals Guide
+@paragraphindent 0
+@c %**end of header
+
+@c
+@c COPYRIGHT (c) 1996-1997.
+@c On-Line Applications Research Corporation (OAR).
+@c All rights reserved.
+@c
+
+@c This prevents a black box from being printed on "overflow" lines.
+@c The alternative is to rework a sentence to avoid this problem.
+@finalout
+
+@tex
+\global\parindent 0in
+\global\chapheadingskip = 15pt plus 4pt minus 2pt
+\global\secheadingskip = 12pt plus 4pt minus 2pt
+\global\subsecheadingskip = 9pt plus 4pt minus 2pt
+
+@ifclear smallbook
+\global\parskip 6pt plus 1pt
+@end ifclear
+@end tex
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* AFCC: . AFCC Objects
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+
+@c Joel's Questions
+@c
+@c 1. Why does paragraphindent only impact makeinfo?
+@c
+
+@setchapternewpage odd
+
+@c
+@c Master file for the C User's Guide
+@c
+@include Drive.texi
+@ifinfo
+
+@node Top, Turret Subsystem, Gunner Station Subsystem, (dir)
+@top afcc
+
+This is the info version of the object documentation for the AFCC.
+
+The following subsystems are in the AFCC:
+
+@menu
+* Turret Subsystem::
+* Vehicle Subsystem::
+* Gunner Station Subsystem::
+@end menu
+
+@node Turret Subsystem, , Top, Top
+
+The following objects are in the Turret Subsystem:
+
+@menu
+* Drive Object:: Drive Object
+@end menu
+
+@node Vehicle Subsystem, Gunner Station Subsystem, , Top
+
+@menu
+The following objects are in the Turret Subsystem:
+
+* ::
+@end menu
+
+@node Gunner Station Subsystem, Top, Vehicle Subsystem, Top
+@menu
+
+The following objects are in the Gunner Station Subsystem:
+
+* ::
+@end menu
+
+
+@end ifinfo
+@c
+@c
+@c Need to copy the emacs stuff and "trailer stuff" (index, toc) into here
+@c
+@bye
diff --git a/doc/tools/pdl2texi/base.h b/doc/tools/pdl2texi/base.h
new file mode 100644
index 0000000000..d570f1767d
--- /dev/null
+++ b/doc/tools/pdl2texi/base.h
@@ -0,0 +1,116 @@
+/*
+ * COPYRIGHT (c) 1997.
+ * On-Line Applications Research Corporation (OAR).
+ * All rights reserved.
+ *
+ * $Id$
+ */
+
+#ifndef __PDL2AMI_h
+#define __PDL2AMI_h
+
+#include "system.h"
+#include "chain.h"
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+/*
+ * Paragraph size should be kept down because it is allocated for each
+ * Line_Control. If this number is large, the memory requirements for
+ * the program increase significantly.
+ */
+
+#define BUFFER_SIZE (2 * 1024)
+#define PARAGRAPH_SIZE (2 * 1024)
+
+#define NUMBER_ELEMENTS( _x ) (sizeof(_x) / sizeof _x[0])
+
+void exit_application(
+ int status
+);
+
+void ProcessFile(
+ char *inname,
+ char *outname
+);
+
+void strtolower(
+ char *dest,
+ char *src
+);
+
+void strtoInitialCaps(
+ char *dest,
+ char *src
+);
+
+void StripBlanks( void );
+
+void MergeParagraphs( void );
+
+int CheckForIncomplete( void );
+
+int CheckOutline( void );
+
+int CheckSections( void );
+
+void GenerateLists( void );
+
+void GenerateAList(
+ char *section,
+ Chain_Control *the_list
+);
+
+void LookForInternalInconsistencies( void );
+
+int Match_Argument(
+ char **array,
+ int entries,
+ char *users
+);
+
+void usage( void );
+
+void ReadFileIntoChain(
+ char *inname
+);
+
+int MergeText( void );
+
+int CheckForBadWhiteSpace();
+
+void RemoveCopyright();
+
+void RemovePagebreaks();
+
+int RemoveExtraBlankLines();
+
+void FormatToTexinfo( void );
+
+void PrintFile(
+ char *out
+);
+
+void DumpList(
+ Chain_Control *the_list
+);
+
+void ReleaseFile();
+
+EXTERN boolean Verbose; /* status/debug msgs */
+EXTERN boolean Statistics; /* statistics msgs */
+EXTERN boolean IncompletesAreErrors;
+EXTERN boolean InsertTBDs;
+EXTERN Chain_Control Lines;
+
+EXTERN int NumberOfAttributes;
+EXTERN int NumberOfAssociations;
+EXTERN int NumberOfAbstractTypes;
+EXTERN int NumberOfDataItems;
+EXTERN int NumberOfMethods;
+EXTERN int NumberOfTasks;
+
+
+#endif
diff --git a/doc/tools/pdl2texi/drive.d b/doc/tools/pdl2texi/drive.d
new file mode 100644
index 0000000000..ff41d5ad38
--- /dev/null
+++ b/doc/tools/pdl2texi/drive.d
@@ -0,0 +1,874 @@
+OBJECT: Drive
+ DESCRIPTION:
+ This object provides an interface to the elevation/azimuth
+ drive system(ECA).
+ THEORY OF OPERATION:
+ This object encapsulates the turret drive. The object provides
+ an interface to control the turret drive. A method is provided
+ to set the azimuth and elevation rate of the drive. Methods are
+ provided to request the drive to run in stabilized or power mode
+ and set the drive speed to high or low. A method is also provided
+ to allow for drift adjust.
+
+ This object also tracks drive system on hours. It gets the hours
+ from the EEPROM data, allows the hours to be set, updates the
+ hours via the activation and deactivation of the drive, and
+ provides access to the hours.
+
+ The object also provides methods to access azimuth and elevation
+ displacement, and methods to process changes in the hardware
+ discretes drive on, stabilized mode, thermal fault and fault.
+
+ The object also provides methods to enable and disable
+ both the remote and turret power interlocks which determine if
+ the drive can be driven by the remote or turret handstation
+ respectively.
+
+ATTRIBUTE DESCRIPTIONS:
+
+
+ATTRIBUTE: Azimuth_displacement
+ DESCRIPTION:
+ This attribute represents the current azimuth displacement
+ of the turret.
+ TYPE: floating point
+ RANGE: ???
+ UNITS: degrees
+ REQUIREMENTS:
+ AFS 8.2.11 Receive Azimuth Displacement and Elevation Displacement
+ AIS 5.2.6 Azimuth Displacement analog
+
+
+ATTRIBUTE: Azimuth_rate
+ DESCRIPTION:
+ Azimuth rate command for movement of the turret.
+ TYPE: floating point
+ UNITS: degrees / second
+ DEFAULTS: none
+ REQUIREMENTS:
+ AFS 8.2.3 Send Azimuth and Elevation Rate to ECA
+ AIS 5.3.4 Elevation Rate analog
+ AIS 5.3.5 Azimuth Rate analog
+
+
+ATTRIBUTE: Drift_adjust
+ DESCRIPTION:
+ This attribute represents the current drift adjustment mode
+ of the ECA turret drive.
+ TYPE: enumerated
+ MEMBERS:
+ ADJUST_OFF - drift adjust mode is OFF
+ ADJUST_ON - drift adjust mode is ON
+ REQUIREMENTS:
+ AFS 8.2.6 Capable of turret drift adjustment
+ AIS 5.3.1 Drift Adjust discrete
+
+
+ATTRIBUTE: Drive_on
+ DESCRIPTION:
+ Current status of the turret drive. The turret drive may either be
+ switched on or off.
+ TYPE: boolean
+ MEMBERS:
+ FALSE - turret drive is off
+ TRUE - turret drive is on
+ DEFAULTS: FALSE
+ REQUIREMENTS:
+ AFS 8.2.9 Monitor Drive System On
+ AIS 5.2.1 Drive System On discrete
+
+
+ATTRIBUTE: Drive_system_hours
+ DESCRIPTION:
+ Total number of hours drive has been activated.
+ TYPE: integer
+ RANGE: 0 - +INFINITY
+ UNITS: seconds
+ REQUIREMENTS:
+ AFS 4.11 Respond to CDT elapsed time indicator key
+
+
+ATTRIBUTE: Elevation_displacement
+ DESCRIPTION:
+ This attribute represents the current elevation displacement
+ of the turret.
+ TYPE: floating point
+ RANGE: ???
+ UNITS: degrees
+ REQUIREMENTS:
+ AFS 8.2.11 Receive Azimuth Displacement and Elevation Displacement
+ AIS 5.2.7 Elevation Displacement analog
+
+
+ATTRIBUTE: Elevation_rate
+ DESCRIPTION:
+ Elevation rate command for movement of the turret.
+ TYPE: floating point
+ UNITS: degrees / second
+ DEFAULTS: none
+ REQUIREMENTS:
+ AFS 8.2.3 Send Azimuth and Elevation Rate to ECA
+ AIS 5.3.4 Elevation Rate analog
+ AIS 5.3.5 Azimuth Rate analog
+
+
+ATTRIBUTE: Fault
+ DESCRIPTION:
+ This attribute denotes whether a turret malfunction has occurred.
+ TYPE: boolean
+ MEMBERS:
+ TRUE - a turret malfunction has occurred
+ FALSE - no turret malfunction has occurred
+ DEFAULTS: FALSE
+ REQUIREMENTS:
+ AFS 8.2.7 Check for ECA failure indication
+ AIS 5.2.4 Turret Drive Malfunction discrete
+
+
+ATTRIBUTE: Mode
+ DESCRIPTION:
+ Current requested drive mode.
+ TYPE: enumerated
+ MEMBERS:
+ POWER - operate in POWER mode
+ STAB - operate in STABILIZED mode
+ DEFAULTS: POWER
+ REQUIREMENTS:
+
+
+ATTRIBUTE: Remote_power_interlock_position
+ DESCRIPTION:
+ This is the status of the remote's power interlock.
+ TYPE: enumerated
+ MEMBERS:
+ OPEN - relay is open
+ CLOSED - relay is closed
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+
+
+ATTRIBUTE: Speed
+ DESCRIPTION:
+ Current speed mode of the ECA turret drive.
+ TYPE: enumerated
+ MEMBERS:
+ LOW_SPEED - turret drive does not allow the maximum rate
+ HIGH_SPEED - turret drive allows the maximum rate
+ DEFAULTS: HIGH
+ REQUIREMENTS:
+ AFS 8.2.5 Control Turret
+ AIS 5.3.3 Turret High Speed Mode discrete
+
+
+ATTRIBUTE: Stabilized_mode
+ DESCRIPTION:
+ Current drive mode indicating whether the ECA electronics are
+ operating in Stabilized mode or Power mode.
+ TYPE: boolean
+ MEMBERS:
+ FALSE - not operating in STABILIZED mode
+ TRUE - operating in STABILIZED mode
+ DEFAULTS: FALSE
+ REQUIREMENTS:
+ AFS 8.2.8 Monitor Turret Stab Mode Indicate
+ AIS 5.2.3 Turret Stab Mode Indicate discrete
+
+
+ATTRIBUTE: State
+ DESCRIPTION:
+ Current state of the turret drive.
+ TYPE: enumerated
+ MEMBERS:
+ ACTIVATED - turret drive is ON and active
+ DEACTIVATED - turret drive is ON but deactivated
+ DEFAULTS: DEACTIVATED
+ REQUIREMENTS:
+ AFS 8.2.4 Set Plam Grips Active
+ AIS 5.3.2 Palm Grips Active discrete
+
+
+ATTRIBUTE: Thermal_fault
+ DESCRIPTION:
+ This attribute denotes whether a turret thermal fault has occurred.
+ TYPE: boolean
+ MEMBERS:
+ TRUE - a turret thermal fault has occurred
+ FALSE - no turret thermal fault has occurred
+ DEFAULTS: FALSE
+ REQUIREMENTS:
+ AFS 8.2.7 Check for ECA failure indication
+ AIS 5.2.2 Turret ECA Thermal Failure discrete
+
+
+ATTRIBUTE: Turret_power_interlock_position
+ DESCRIPTION:
+ This is the status of the turret's power interlock.
+ TYPE: enumerated
+ MEMBERS:
+ OPEN - relay is open
+ CLOSED - relay is closed
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+
+
+ASSOCIATION DESCRIPTIONS: none
+
+ABSTRACT TYPE DESCRIPTIONS:
+
+ABSTRACT TYPE: Drift_adjust_t
+ DESCRIPTION:
+ This abstract type represents the current drift adjustment mode
+ of the ECA turret drive.
+ VISIBILITY: public
+ DERIVATION: enumerated
+ MEMBERS:
+ ADJUST_OFF = 0 - drift adjust mode is OFF
+ ADJUST_ON = 1 - drift adjust mode is ON
+ REQUIREMENTS:
+ AIS 5.3.1 Drift Adjust discrete
+
+ABSTRACT TYPE: Interlock_status
+ DESCRIPTION:
+ An interlock state being OPEN or CLOSED.
+ VISIBILITY: private
+ DERIVATION: enumerated
+ MEMBERS:
+ OPEN - interlock relay is in the open state
+ CLOSED - interlock relay is in the closed state
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+
+ABSTRACT TYPE: Mode
+ DESCRIPTION:
+ This type specifies the drive mode of the ECA turret drive.
+ VISIBILITY: public
+ DERIVATION: enumerated
+ MEMBERS:
+ POWER - operate in POWER mode
+ STAB - operate in STABILIZED mode
+
+ABSTRACT TYPE: Speed
+ DESCRIPTION:
+ This type specifies the Speed mode of the ECA turret drive.
+ VISIBILITY: public
+ DERIVATION: enumerated
+ MEMBERS:
+ LOW_SPEED = 0 - turret drive does not allow the maximum rate
+ HIGH_SPEED = 1 - turret drive allows the maximum rate
+ REQUIREMENTS:
+ AIS 5.3.3 Turret High Speed Mode discrete
+
+ABSTRACT TYPE: State_t
+ DESCRIPTION:
+ This type specifies the state of the turret drive.
+ VISIBILITY: private
+ DERIVATION: enumerated
+ MEMBERS:
+ DEACTIVATED - turret drive is ON but deactivated
+ ACTIVATED - turret drive is ON and active
+
+DATA ITEM DESCRIPTIONS:
+
+DATA ITEM: Azimuth_displacement_control
+ DESCRIPTION:
+ This data item contains the Azimuth_displacement analog control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Azimuth_rate_control
+ DESCRIPTION:
+ This data item contains the Azimuth_rate analog control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Drift_adjust_control
+ DESCRIPTION:
+ This data item contains the Drift_adjust discrete control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Drive_activate_control
+ DESCRIPTION:
+ This data item contains the activate drive relay control information.
+ TYPE: handle
+
+
+DATA ITEM: Drive_activated_timestamp
+ DESCRIPTION:
+ This data item stores the timestamp of the last time the drive was
+ activated. It will be used to compute the activated time when a
+ deactivate is received.
+ TYPE: time_t
+ DEFAULT: none
+ NOTES:
+ see C library for data type information ???
+
+
+DATA ITEM: Drive_on
+ DESCRIPTION:
+ The current status of the turret drive representing whether
+ the drive is on or off.
+ TYPE: boolean
+ DEFAULT: FALSE
+
+
+DATA ITEM: Drive_on_control
+ DESCRIPTION:
+ This data item contains the Drive_on discrete flag control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Drive_system_hours
+ DESCRIPTION:
+ This data item stores the actual time the drive has been active.
+ This value will be output by the Get_time method and will be set
+ by the Set_time method.
+ TYPE: integer
+ RANGE: 0 - +INFINITY
+ UNITS: seconds
+ DEFAULT: 0
+
+
+DATA ITEM: Elevation_rate_control
+ DESCRIPTION:
+ This data item contains the Elevation_rate analog control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Elevation_displacement_control
+ DESCRIPTION:
+ This data item contains the Elevation_displacement analog control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Fault_control
+ DESCRIPTION:
+ This data item contains the Fault discrete flag control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Remote_power_interlock_control
+ DESCRIPTION:
+ This data item contains the Remote_power_interlock relay control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Stabilized_mode_control
+ DESCRIPTION:
+ This data item contains the Stabilized_mode discrete flag control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: State
+ DESCRIPTION:
+ The current state of the turret drive representing an activated or
+ deactivated drive.
+ TYPE: State_t
+ DEFAULT: DEACTIVATED
+
+
+DATA ITEM: Thermal_fault_control
+ DESCRIPTION:
+ This data item contains the Thermal_fault discrete flag control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Turret_power_interlock_control
+ DESCRIPTION:
+ This data item contains the Turret_power_interlock relay control
+ information.
+ TYPE: handle
+
+
+DATA ITEM: Turret_power_interlock_status
+ DESCRIPTION:
+ The accurate status of the turret power interlock relay. This value
+ will be used to control the relay during a transition from the remote
+ back to the turret console.
+ TYPE: Interlock_status
+ DEFAULT: none
+
+
+METHODS DESCRIPTIONS:
+
+METHOD: Activate
+ DESCRIPTION:
+ This method activates the turret drive system. A timestamp of the
+ activation is recorded to keep a running count of hours the drive has
+ been active.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.4 Set Palm Grips Active
+ AIS 5.3.2 Palm Grips Active discrete
+ PDL:
+
+ if Drive_on
+ if State is DEACTIVATED
+ close the Drive_activate_control relay using the Relay object
+ timestamp Drive_activated_timestamp for Drive_system_hours
+ running total
+ set State to ACTIVATED
+ else
+ already in the ACTIVATED state
+
+
+METHOD: Create
+ DESCRIPTION:
+ This method initializes the Turret Drive object. All monitors of
+ turret drive signals are initialized and/or registered. All turret
+ drive characteristics are set to their initial values.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ PDL:
+
+ set State to DEACTIVATED
+
+ get Drive_system_hours to initialize the elapsed drive time
+ from the Statistics (eeprom database ???) object - this is
+ stored upon shutdown in eeprom
+
+ create Fault_control using Discrete_flag object with the
+ following attributes
+ true_sense - DISCRETE_FLAG_TRUE_IS_1
+ is_buffered - false
+ is_monitored - true
+ period - 10ms
+ change_routine - Change_fault
+ change fault using initial value returned from create Fault_control
+
+ create Thermal_fault_control using Discrete_flag object with
+ the following attributes
+ true_sense - DISCRETE_FLAG_TRUE_IS_0
+ is_buffered - false
+ is_monitored - true
+ period - 10ms
+ change_routine - Change_thermal_fault
+ change thermal fault using initial value returned from create
+ Thermal_fault_control
+
+ create Stabilized_mode_control using Discrete_flag object with the
+ following attributes
+ true_sense - DISCRETE_FLAG_TRUE_IS_1
+ is_buffered - false
+ is_monitored - true
+ period - 10ms
+ change_routine - Change_stabilized_mode
+ change stabilized mode using initial value returned from create
+ Stabilized_mode_control
+
+ create Drive_on_control using Discrete_flag object with the
+ following attributes
+ true_sense - DISCRETE_FLAG_TRUE_IS_1
+ is_buffered - false
+ is_monitored - true
+ period - 10ms
+ change_routine - Change_drive_on
+ change drive on using initial value returned from create
+ Drive_on_control
+
+ create Azimuth_rate_control using the Linear_dac object
+ with the following attributes:
+ none voltage_low - -10
+ voltage_high - +10
+ logical_low - -60
+ logical_high - +60
+ is_buffered - false
+ period - none
+ initial_value - 0
+
+ create Elevation_rate_control using the Linear_dac object with the
+ following attributes:
+ voltage_low - -10
+ voltage_high - +10
+ logical_low - -60
+ logical_high - +60
+ is_buffered - false
+ period - none
+ initial_value - 0
+
+ create Azimuth_displacement_control using the Linear_adc object with
+ the following attributes:
+ voltage low -
+ voltage high -
+ logical low -
+ logical high -
+ is_buffered - false
+ is_monitored - false
+ period - none
+ change_routine - none
+ delta - none
+
+ create Elevation_displacement_control using the Linear_adc object
+ with the following attributes:
+ voltage low -
+ voltage high -
+ logical low -
+ logical high -
+ is_buffered - false
+ is_monitored - false
+ period - none
+ change_routine - none
+ delta - none
+
+ create Drive_activate_control using the Relay object with the
+ following attributes:
+ open_sense - RELAY_OPEN_IS_0
+ is_buffered - false
+ period - none
+ initial_state - RELAY_OPEN
+
+ create Turret_power_interlock_control using the Relay object with
+ the following attributes:
+ open_sense - RELAY_OPEN_IS_0
+ is_buffered - false
+ period - none
+ initial_state - RELAY_OPEN
+ set Turret_power_interlock_status to OPEN
+
+ create Remote_power_interlock_control using the Relay
+ object with the following attributes:
+ open_sense - RELAY_OPEN_IS_0
+ is_buffered - false
+ period - none
+ initial_state - RELAY_OPEN
+
+ create Drift_adjust_control using the Discrete_out object with
+ following attributes:
+ is_buffered - false
+ period - 10ms
+ initial_value - ADJUST_OFF
+
+
+METHOD: Deactivate
+ DESCRIPTION:
+ This method deactivates the turret drive system. A timestamp of the
+ activation is recorded to keep a running count of hours the drive
+ has been active.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.4 Set Plam Grips Active
+ AIS 5.3.2 Palm Grips Active discrete
+ PDL:
+
+ if Drive_on
+ if State is DEACTIVATED
+ timestamp deactivate for Drive_system_hours running total
+ deactivate drive by opening the Drive_activate_control relay
+ using the Relay object
+ compute running time since last activate
+ add running time to Drive_system_hours
+ set State to DEACTIVATED
+ else
+ already in the DEACTIVATED state
+
+
+METHOD: Disable_remote_power_interlock
+ DESCRIPTION:
+ This method disables the turret power interlock safety preventing
+ the turret from being driven by the remote's handstation.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+ PDL:
+
+ open the remote power interlock relay
+ return the turret relay to its designated state defined by the
+ Turret_power_interlock_status
+
+
+METHOD: Disable_turret_power_interlock
+ DESCRIPTION:
+ This method disables the turret power interlock safety preventing
+ the turret from being driven by the turret's handstation.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+ PDL:
+
+ Deactivate the Drive object
+ open the turret power interlock relay
+ set Turret_power_interlock_status to OPEN
+
+
+METHOD: Enable_remote_power_interlock
+ DESCRIPTION:
+ This method will enable the remote power interlock to allow
+ the turret to be driven from the remote station.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+ NOTES:
+ At this time the turret's power interlock is opened to avoid
+ having both relays closed at a time.
+ PDL:
+
+ if Drive_on
+ open the turret power interlock relay using the Relay object
+ close the remote power interlock relay using the Relay object
+
+
+METHOD: Enable_turret_power_interlock
+ DESCRIPTION:
+ This method will enable the turret power interlock to allow
+ the turret to be driven from the turret station.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.12 Control Power Interlock
+ NOTES:
+ At this time the closed state is saved to allow the correct state
+ to be returned to in the event a remote overrides the turret and the
+ remote gives up its control, we must return to the previous state of
+ the turret power interlock.
+ PDL:
+
+ if Drive_on
+ close the turret power interlock relay using the Relay object
+
+ set the Turret_power_interlock_status to CLOSED to return to
+ when remote gives up control
+
+
+METHOD: Get_AZ_EL_displacement
+ DESCRIPTION:
+ This method returns the current azimuth displacement and elevation
+ displacement from the ECA.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS:
+ current azimuth displacement value
+ current elevation displacement value
+ REQUIREMENTS:
+ AFS 8.2.11 Receive Azimuth Displacement and Elevation Displacement
+ AIS 5.2.6 Azimuth Displacement analog
+ AIS 5.2.7 Elevation Displacement analog
+ NOTES:
+ Currently supported as an on-demand type of signal. May change to a
+ monitored analog signal.
+ PDL:
+
+ if Drive_on
+ get and return current azimuth displacement and current elevation
+ displacement from ECA using the Linear_ADC object
+
+
+METHOD: Get_hours
+ DESCRIPTION:
+ This method returns the current value contained in the elapsed
+ turret drive active time.
+ VISIBILITY: public
+ INPUTS: none
+ OUTPUTS:
+ elapsed turret drive time - the current elasped turret drive time
+ REQUIREMENTS:
+ REFERENCES:
+ AFS 4.11 Respond to CDT elapsed time indicator key
+ NOTES:
+ PDL:
+
+ return the current value for Drive_system_hours
+
+
+METHOD: Set_drift_adjust
+ DESCRIPTION:
+ This method provides the ability to set the drift adjust to the
+ value represented by the handstation. Drift adjust is either ON
+ or OFF.
+ VISIBILITY: public
+ INPUTS:
+ value - new drift adjust value
+ ADJUST_OFF - drift adjust mode is OFF
+ ADJUST_ON - drift adjust mode is ON
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.6 Capable of turret drift adjustment
+ AIS 5.3.1 Drift Adjust discrete
+ PDL:
+
+ if Drive_on
+ set drift adjust discrete to value using Discrete_out object
+
+METHOD: Set_hours
+ DESCRIPTION:
+ This method will set the turret drive activated elapsed time value
+ to the specified value.
+ VISIBILITY: public
+ INPUTS:
+ new_elapsed_time_value - specified turret drive elapsed time value
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 4.11 Respond to CDT elapsed time indicator key
+ PDL:
+
+ set the value of Drive_system_hours to the value specified by
+ new_elapsed_time_value
+
+
+METHOD: Set_mode
+ DESCRIPTION:
+ This method sets the requested mode of the turret drive.
+ VISIBILITY: public
+ INPUTS:
+ mode - new requested mode
+ POWER - operating in POWER mode
+ STAB - operating in STABILIZED mode
+ OUTPUTS: none
+ REQUIREMENTS:
+ PDL:
+ if mode is POWER
+ set drive mode switchlight to PWR_LAMP using the Console object
+ else if mode is STAB
+ set drive mode switchlight to STB_LAMP using the Console object
+
+
+METHOD: Set_rate
+ DESCRIPTION:
+ This method provides the ability to send azimuth and elevation rates
+ to the drive. Two parameters are used as input to designate the
+ corresponding rates. These parameters must be in degrees per second.
+ VISIBILITY: public
+ INPUTS:
+ azimuth rate - new azimuth rate in degress per second
+ elevation rate - new elevation rate in degress per second
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.3 Send Azimuth and Elevation Rate to ECA
+ AIS 5.3.4 Elevation Rate analog
+ AIS 5.3.5 Azimuth Rate analog
+ NOTES:
+ May need to couple these analogs with an interface driver to close
+ the window between writes and conversions.
+ PDL:
+
+ if Drive_on
+ send the new azimuth rate to the Azimuth analog
+ send the new elevation rate to Elevation analog
+
+
+METHOD: Set_speed
+ DESCRIPTION:
+ This method sets the turret drive speed mode to the specified value
+ either high or low based on user input.
+ VISIBILITY: public
+ INPUTS:
+ new_speed_value - new value to set the turret speed to
+ LOW_SPEED - turret drive does not allow the maximum rate
+ HIGH_SPEED - turret drive allows the maximum rate
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.5 Control Turret
+ AIS 5.3.3 Turret High Speed Mode discrete
+ PDL:
+
+ if Drive_on
+ set turret drive high speed mode discrete to the new_speed_value
+ using Discrete_out object
+
+
+METHOD: Change_drive_on
+ DESCRIPTION:
+ This method will be used to report a transition of the drive system
+ on discrete.
+ VISIBILITY: private
+ INPUTS:
+ value - new drive system on value
+ FALSE - indicates drive not on
+ TRUE - indicates drive on
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.9 Monitor Drive System On
+ AIS 5.2.1 Drive System On discrete
+ REFERENCES:
+ NOTES:
+ PDL:
+
+ set Drive_on to value
+ if Drive_on is FALSE
+ deactivate the turret drive using the Drive object
+
+
+METHOD: Change_fault
+ DESCRIPTION:
+ This method will be used to indicate that a turret malfunction
+ has been recognized by the turret drive.
+ VISIBILITY: private
+ INPUTS:
+ value - new value resulting from a fault discrete change
+ FALSE - indicates no fault
+ TRUE - indicates fault
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.7 Check for ECA failure indication
+ AIS 5.2.4 Turret Drive Malfunction discrete
+ PDL:
+
+ if value
+ send turret fault message using the Display object
+ else
+ return
+
+
+METHOD: Change_stabilized_mode
+ DESCRIPTION:
+ This method will determine a transition from STAB mode to POWER mode.
+ It will set the stab mode lamp on the console.
+ VISIBILITY: private
+ INPUTS:
+ value - new value resulting from a stab mode discrete change
+ FALSE - indicates not stabilized mode
+ TRUE - indicates stabilized mode
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.8 Monitor Turret Stab Mode Indicate
+ AIS 5.2.3 Turret Stab Mode Indicate discrete
+ PDL:
+
+ if value
+ set STAB mode light to LAMP_ON using the Console object
+ else value indicates not stabilized mode
+ set STAB mode light to LAMP_OFF using the Console object
+
+
+METHOD: Change_thermal_fault
+ DESCRIPTION:
+ This method will be used to indicate that a thermal fault has been
+ recognized by the turret drive.
+ VISIBILITY: private
+ INPUTS:
+ value - new value resulting from a thermal fault discrete change
+ FALSE - indicates no thermal fault
+ TRUE - indicates thermal fault
+ OUTPUTS: none
+ REQUIREMENTS:
+ AFS 8.2.7 Check for ECA failure indication
+ AIS 5.2.2 Turret ECA Thermal Failure discrete
+ PDL:
+
+ if value
+ send thermal fault message using the Display object
+ else
+ return
+
+END OBJECT: Drive
diff --git a/doc/tools/pdl2texi/main.c b/doc/tools/pdl2texi/main.c
new file mode 100644
index 0000000000..1424499d36
--- /dev/null
+++ b/doc/tools/pdl2texi/main.c
@@ -0,0 +1,3256 @@
+/*
+ * main.c
+ *
+ * This program error checks the OAR PDL and converts it into
+ * It works by reading the input file into a linked list of lines
+ * and then performing sweeps on that list until all formatting is
+ * complete.
+ *
+ * FEATURES:
+ * + rudimentary statistics
+ * + forgiveness features
+ *
+ * CHECKS PERFORMED:
+ * + unable to open file
+ * + unexpected end of file
+ * + line should have a colon
+ * + basic text (to right or below) associated with keyword improperly placed
+ * + an "incomplete marker" is still in place
+ * + missing keywords within a subsection
+ * + duplicated keywords withing a subsection
+ * + subsections in correct order
+ * + section header indicates no subsections and there are subsections
+ * + section header indicates subsections and there are no subsections
+ * + inconsistent spacing in RAW text. This tends to be 1st line with
+ * text is indented further than a subsequent line.
+ * + missing components on line (incomplete)
+ * + invalid repitition of a subsection
+ * + type keyword validated for class, type, and spacing between
+ * + both members and range are present
+ * + neither members and range are present
+ * + enumerated types and attributes have members
+ * + non-enumerated types and attributes have ranges.
+ * + Object name and end object have the same name
+ * + booleans in attribute section list both true and false
+ * + task synchronization keyword is checked. There must be a valid
+ * type of synchronization primitive and a description when expected.
+ * + sections in correct order
+ *
+ * INTERNAL ERRORS:
+ * + attempting to reformat an already formatted line
+ * + end of processing reached and no formatting assigned to line
+ *
+ * CHECKS NOT PERFORMED:
+ *
+ * TODO:
+ *
+ * IDEAS NOT IMPLEMENTED:
+ * + smarter reporting of sections not in the right order
+ * + task which uses multiple synchronization types
+ * + improved error messages
+ * + no introductions inserted to sections
+ * + recognize special "symbols" like infinity, +-, etc.
+ *
+ * QUESTIONS:
+ * + "what do I know" is actually a table and should not be reformatted.
+ *
+ * COPYRIGHT (c) 1997.
+ * On-Line Applications Research Corporation (OAR).
+ * All rights reserved.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* XXX -- just for testing -- these should be set by options */
+char DocsNextNode[256] = "";
+char DocsPreviousNode[256] = "";
+char DocsUpNode[256] = "";
+
+extern int optind; /* Why is this not in <stdlib.h>? */
+extern char *optarg; /* Why is this not in <stdlib.h>? */
+
+#ifndef NAME_MAX
+#define NAME_MAX 14 /* Why is the one in limits.h not showing up? */
+#endif
+#define INIT_DATA
+#define EXTERN
+
+#include "base.h"
+
+FILE *OutFile = stdout;
+
+/*************************************************************************
+ *************************************************************************
+ ***** DATA TYPES AND CONSTANT TABLES *****
+ *************************************************************************
+ *************************************************************************/
+/*
+ * Usage Information
+ */
+
+char *Usage_Strings[] = {
+ "\n",
+ "usage: cmd [-vti?] [-p previous_node] [-u up_node] files ...\n",
+ "\n",
+ "EOF"
+};
+
+/*
+ * The page separator is not really a keyword and will be purged before
+ * it is seen elsewhere.
+ */
+
+#define PAGE_SEPARATOR "#PAGE"
+
+/*
+ * Section Delimiter Keywords
+ */
+
+#define MAXIMUM_KEYWORD_LENGTH 32
+
+/*
+ * Level indicates where in the format the delimiter is allowed to occur.
+ * 1 indicates a major section divider (e.g. "ATTRIBUTE DESCRIPTIONS:").
+ * 2 indicates a subsection (e.g. "ATTRIBUTE:").
+ * 3 indicates a heading (e.g. "DESCRIPTION:").
+ */
+
+#define TEXT 0
+#define SECTION 1
+#define SUBSECTION 2
+#define HEADING 3
+
+typedef enum {
+ UNUSED, /* dummy 0 slot */
+ OBJECT, /* sections */
+ ATTRIBUTE_DESCRIPTIONS,
+ ASSOCIATION_DESCRIPTIONS,
+ ABSTRACT_TYPE_DESCRIPTIONS,
+ DATA_ITEM_DESCRIPTIONS,
+ METHOD_DESCRIPTIONS,
+ TASK_DESCRIPTIONS,
+ END_OBJECT,
+
+ ATTRIBUTE, /* subsections */
+ ASSOCIATION,
+ ABSTRACT_TYPE,
+ DATA_ITEM,
+ METHOD,
+ TASK,
+
+ DESCRIPTION, /* headings */
+ COPYRIGHT,
+ PORTING,
+ THEORY_OF_OPERATION,
+ DERIVATION,
+ DEPENDENCIES,
+ NOTES,
+ TYPE,
+ RANGE,
+ MEMBERS,
+ UNITS,
+ SCALE_FACTOR,
+ DEFAULT,
+ TOLERANCE,
+ REQUIREMENTS,
+ REFERENCES,
+ VISIBILITY,
+ ASSOCIATED_WITH,
+ MULTIPLICITY,
+ INPUTS,
+ OUTPUTS,
+ PDL,
+ SYNCHRONIZATION,
+ TIMING
+} Keyword_indices_t;
+
+#define KEYWORD_FIRST OBJECT
+#define KEYWORD_LAST TIMING
+
+/*
+ * Line Management Structure
+ */
+
+typedef enum {
+ NO_EXTRA_FORMATTING_INFO,
+ RAW_OUTPUT,
+ PARAGRAPH_OUTPUT,
+ BULLET_OUTPUT,
+} ExtraFormat_info_t;
+
+typedef struct {
+ Chain_Node Node;
+ Keyword_indices_t keyword; /* unused is unknown/undecided */
+ ExtraFormat_info_t format;
+ int number;
+ char Contents[ PARAGRAPH_SIZE ];
+} Line_Control;
+
+typedef enum {
+ RT_FORBIDDEN, /* no text to right allowed */
+ RT_OPTIONAL, /* text to right optional -- none below */
+ RT_NONE, /* text to right is "none" or nothing -- none below */
+ RT_REQUIRED, /* text to right required -- none below */
+ RT_BELOW, /* text to right forbidden -- text below required */
+ RT_NONE_OR_BELOW, /* text to right is "none" OR there is text below */
+ RT_MAYBE_BELOW, /* text to right required -- text below optional */
+ RT_EITHER, /* text to right OR below */
+ RT_BOTH /* text to right AND below */
+} Keywords_text_mode_t;
+
+typedef enum {
+ BL_FORBIDDEN, /* text below forbidden */
+ BL_FORMATTED, /* text below is to be formatted as paragraphs */
+ BL_RAW, /* text below is to be unprocessed by this program */
+} Keywords_text_below_t;
+
+typedef int (*Keyword_validater_t)( Line_Control * );
+
+typedef struct {
+ char Name[ MAXIMUM_KEYWORD_LENGTH ];
+ int level;
+ Keywords_text_mode_t text_mode;
+ Keywords_text_below_t text_below_mode;
+ Keyword_validater_t keyword_validation_routine;
+} Keyword_info_t;
+
+/*
+ * Keyword Validation Routines
+ */
+
+int Validate_visibility(
+ Line_Control *line
+);
+
+int Validate_synchronization(
+ Line_Control *line
+);
+
+Keyword_info_t Keywords[] = {
+ { "unused",
+ 0, 0, 0, NULL }, /* so 0 can be invalid */
+ { "OBJECT:",
+ SECTION, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "ATTRIBUTE DESCRIPTIONS:",
+ SECTION, RT_NONE, BL_FORBIDDEN, NULL },
+ { "ASSOCIATION DESCRIPTIONS:",
+ SECTION, RT_NONE, BL_FORBIDDEN, NULL },
+ { "ABSTRACT TYPE DESCRIPTIONS:",
+ SECTION, RT_NONE, BL_FORBIDDEN, NULL },
+ { "DATA ITEM DESCRIPTIONS:",
+ SECTION, RT_NONE, BL_FORBIDDEN, NULL },
+ { "METHOD DESCRIPTIONS:",
+ SECTION, RT_NONE, BL_FORBIDDEN, NULL },
+ { "TASK DESCRIPTIONS:",
+ SECTION, RT_NONE, BL_FORBIDDEN, NULL },
+ { "ENDOBJECT:",
+ SECTION, RT_REQUIRED, BL_FORBIDDEN, NULL },
+
+ { "ATTRIBUTE:",
+ SUBSECTION, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "ASSOCIATION:",
+ SUBSECTION, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "ABSTRACT TYPE:",
+ SUBSECTION, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "DATA ITEM:",
+ SUBSECTION, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "METHOD:",
+ SUBSECTION, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "TASK:",
+ SUBSECTION, RT_REQUIRED, BL_FORBIDDEN, NULL },
+
+ { "DESCRIPTION:",
+ HEADING, RT_BELOW, BL_FORMATTED, NULL },
+ { "COPYRIGHT:",
+ HEADING, RT_BELOW, BL_FORMATTED, NULL },
+ { "PORTING:",
+ HEADING, RT_BELOW, BL_FORMATTED, NULL },
+ { "THEORY OF OPERATION:",
+ HEADING, RT_BELOW, BL_FORMATTED, NULL },
+ { "DERIVATION:",
+ HEADING, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "DEPENDENCIES:",
+ HEADING, RT_BELOW, BL_FORMATTED, NULL },
+ { "NOTES:",
+ HEADING, RT_BELOW, BL_FORMATTED, NULL },
+ { "TYPE:",
+ HEADING, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "RANGE:",
+ HEADING, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "MEMBERS:",
+ HEADING, RT_BELOW, BL_RAW, NULL },
+ { "UNITS:",
+ HEADING, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "SCALE FACTOR:",
+ HEADING, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "DEFAULT:",
+ HEADING, RT_EITHER, BL_RAW, NULL },
+ { "TOLERANCE:",
+ HEADING, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "REQUIREMENTS:",
+ HEADING, RT_BELOW, BL_RAW, NULL },
+ { "REFERENCES:",
+ HEADING, RT_BELOW, BL_RAW, NULL },
+ { "VISIBILITY:",
+ HEADING, RT_REQUIRED, BL_FORBIDDEN, Validate_visibility },
+ { "ASSOCIATED WITH:",
+ HEADING, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "MULTIPLICITY:",
+ HEADING, RT_REQUIRED, BL_FORBIDDEN, NULL },
+ { "INPUTS:",
+ HEADING, RT_NONE_OR_BELOW, BL_RAW, NULL },
+ { "OUTPUTS:",
+ HEADING, RT_NONE_OR_BELOW, BL_RAW, NULL },
+ { "PDL:",
+ HEADING, RT_BELOW, BL_RAW, NULL },
+ { "SYNCHRONIZATION:",
+ HEADING, RT_MAYBE_BELOW, BL_RAW, Validate_synchronization },
+ { "TIMING:",
+ HEADING, RT_REQUIRED, BL_FORBIDDEN, NULL }
+};
+
+#define NUMBER_OF_KEYWORDS \
+ ( sizeof( Keywords ) / sizeof( Keyword_info_t ) ) - 2
+
+/*
+ * Section Descriptions
+ */
+
+#define MAXIMUM_ELEMENTS 16
+
+typedef struct {
+ Keyword_indices_t keyword;
+ boolean is_required;
+} Element_info_t;
+
+typedef struct Section_info_struct_t Section_info_t;
+
+typedef (*Section_validater_t)(
+ Section_info_t *,
+ Line_Control *, /* start */
+ Line_Control * /* next_section */
+);
+
+struct Section_info_struct_t {
+ boolean repeats;
+ Keyword_indices_t This_section;
+ Keyword_indices_t Next_section;
+ Section_validater_t section_validation_routine;
+ Element_info_t Description[MAXIMUM_ELEMENTS];
+};
+
+int Validate_object(
+ Section_info_t *section,
+ Line_Control *start,
+ Line_Control *next_section
+);
+
+int Validate_attribute(
+ Section_info_t *section,
+ Line_Control *start,
+ Line_Control *next_section
+);
+
+int Validate_abstract_type(
+ Section_info_t *section,
+ Line_Control *start,
+ Line_Control *next_section
+);
+
+
+Section_info_t ObjectSection = {
+ FALSE, /* subsections repeat */
+ OBJECT, /* this section */
+ ATTRIBUTE_DESCRIPTIONS, /* next section */
+ Validate_object, /* validation routine */
+ {
+ { OBJECT, TRUE }, /* 0 */
+ { DESCRIPTION, TRUE }, /* 1 */
+ { COPYRIGHT, FALSE }, /* 2 */
+ { PORTING, FALSE }, /* 3 */
+ { THEORY_OF_OPERATION, TRUE }, /* 4 */
+ { DERIVATION, FALSE }, /* 5 */
+ { DEPENDENCIES, FALSE }, /* 6 */
+ { REQUIREMENTS, FALSE }, /* 7 */
+ { REFERENCES, FALSE }, /* 8 */
+ { NOTES, FALSE }, /* 9 */
+ { UNUSED, FALSE }, /* 10 */
+ { UNUSED, FALSE }, /* 11 */
+ { UNUSED, FALSE }, /* 12 */
+ { UNUSED, FALSE }, /* 13 */
+ { UNUSED, FALSE }, /* 14 */
+ { UNUSED, FALSE }, /* 15 */
+ }
+};
+
+Section_info_t AttributeSection = {
+ TRUE, /* subsections repeat */
+ ATTRIBUTE_DESCRIPTIONS, /* this section */
+ ASSOCIATION_DESCRIPTIONS, /* next section */
+ Validate_attribute, /* validation routine */
+ {
+ { ATTRIBUTE, TRUE }, /* 0 */
+ { DESCRIPTION, TRUE }, /* 1 */
+ { TYPE, TRUE }, /* 2 */
+ { MEMBERS, FALSE }, /* 3 */
+ { RANGE, FALSE }, /* 4 */
+ { UNITS, FALSE }, /* 5 */
+ { SCALE_FACTOR, FALSE }, /* 6 */
+ { DEFAULT, FALSE }, /* 7 */
+ { TOLERANCE, FALSE }, /* 8 */
+ { REQUIREMENTS, FALSE }, /* 9 */
+ { REFERENCES, FALSE }, /* 10 */
+ { NOTES, FALSE }, /* 11 */
+ { UNUSED, FALSE }, /* 12 */
+ { UNUSED, FALSE }, /* 13 */
+ { UNUSED, FALSE }, /* 14 */
+ { UNUSED, FALSE }, /* 15 */
+ }
+};
+
+Section_info_t AssociationSection = {
+ TRUE, /* subsections repeat */
+ ASSOCIATION_DESCRIPTIONS, /* this section */
+ ABSTRACT_TYPE_DESCRIPTIONS, /* next section */
+ NULL, /* validation routine */
+ {
+ { ASSOCIATION, TRUE }, /* 0 */
+ { DESCRIPTION, TRUE }, /* 1 */
+ { VISIBILITY, TRUE }, /* 2 */
+ { ASSOCIATED_WITH, TRUE }, /* 3 */
+ { MULTIPLICITY, TRUE }, /* 4 */
+ { REQUIREMENTS, FALSE }, /* 5 */
+ { REFERENCES, FALSE }, /* 6 */
+ { NOTES, FALSE }, /* 7 */
+ { UNUSED, FALSE }, /* 8 */
+ { UNUSED, FALSE }, /* 9 */
+ { UNUSED, FALSE }, /* 10 */
+ { UNUSED, FALSE }, /* 11 */
+ { UNUSED, FALSE }, /* 12 */
+ { UNUSED, FALSE }, /* 13 */
+ { UNUSED, FALSE }, /* 14 */
+ { UNUSED, FALSE }, /* 15 */
+ }
+};
+
+Section_info_t AbstractTypeSection = {
+ TRUE, /* subsections repeat */
+ ABSTRACT_TYPE_DESCRIPTIONS, /* this section */
+ DATA_ITEM_DESCRIPTIONS, /* next section */
+ Validate_abstract_type, /* validation routine */
+ {
+ { ABSTRACT_TYPE, TRUE }, /* 0 */
+ { DESCRIPTION, TRUE }, /* 1 */
+ { VISIBILITY, TRUE }, /* 2 */
+ { DERIVATION, TRUE }, /* 3 */
+ { MEMBERS, FALSE }, /* 4 */
+ { RANGE, FALSE }, /* 5 */
+ { UNITS, FALSE }, /* 6 */
+ { SCALE_FACTOR, FALSE }, /* 7 */
+ { DEFAULT, FALSE }, /* 8 */
+ { TOLERANCE, FALSE }, /* 9 */
+ { REQUIREMENTS, FALSE }, /* 10 */
+ { REFERENCES, FALSE }, /* 11 */
+ { NOTES, FALSE }, /* 12 */
+ { UNUSED, FALSE }, /* 13 */
+ { UNUSED, FALSE }, /* 14 */
+ { UNUSED, FALSE }, /* 15 */
+ }
+};
+
+Section_info_t DataItemSection = {
+ TRUE, /* subsections repeat */
+ DATA_ITEM_DESCRIPTIONS, /* this section */
+ METHOD_DESCRIPTIONS, /* next section */
+ NULL, /* validation routine */
+ {
+ { DATA_ITEM, TRUE }, /* 0 */
+ { DESCRIPTION, TRUE }, /* 1 */
+ { TYPE, TRUE }, /* 2 */
+ { UNITS, FALSE }, /* 3 */
+ { SCALE_FACTOR, FALSE }, /* 4 */
+ { DEFAULT, FALSE }, /* 5 */
+ { TOLERANCE, FALSE }, /* 6 */
+ { NOTES, FALSE }, /* 7 */
+ { UNUSED, FALSE }, /* 8 */
+ { UNUSED, FALSE }, /* 9 */
+ { UNUSED, FALSE }, /* 10 */
+ { UNUSED, FALSE }, /* 11 */
+ { UNUSED, FALSE }, /* 12 */
+ { UNUSED, FALSE }, /* 13 */
+ { UNUSED, FALSE }, /* 14 */
+ { UNUSED, FALSE }, /* 15 */
+ }
+};
+
+Section_info_t MethodSection = {
+ TRUE, /* subsections repeat */
+ METHOD_DESCRIPTIONS, /* this section */
+ TASK_DESCRIPTIONS, /* next section */
+ NULL, /* validation routine */
+ {
+ { METHOD, TRUE }, /* 0 */
+ { DESCRIPTION, TRUE }, /* 1 */
+ { VISIBILITY, TRUE }, /* 2 */
+ { INPUTS, TRUE }, /* 3 */
+ { OUTPUTS, TRUE }, /* 4 */
+ { REQUIREMENTS, FALSE }, /* 5 */
+ { REFERENCES, FALSE }, /* 6 */
+ { NOTES, FALSE }, /* 7 */
+ { PDL, TRUE }, /* 8 */
+ { UNUSED, FALSE }, /* 9 */
+ { UNUSED, FALSE }, /* 10 */
+ { UNUSED, FALSE }, /* 11 */
+ { UNUSED, FALSE }, /* 12 */
+ { UNUSED, FALSE }, /* 13 */
+ { UNUSED, FALSE }, /* 14 */
+ { UNUSED, FALSE }, /* 15 */
+ }
+};
+
+Section_info_t TaskSection = {
+ TRUE, /* subsections repeat */
+ TASK_DESCRIPTIONS, /* this section */
+ END_OBJECT, /* next section */
+ NULL, /* validation routine */
+ {
+ { METHOD, TRUE }, /* 0 */
+ { DESCRIPTION, TRUE }, /* 1 */
+ { VISIBILITY, TRUE }, /* 2 */
+ { INPUTS, TRUE }, /* 3 */
+ { SYNCHRONIZATION, TRUE }, /* 4 */
+ { TIMING, TRUE }, /* 5 */
+ { REQUIREMENTS, FALSE }, /* 6 */
+ { REFERENCES, FALSE }, /* 7 */
+ { NOTES, FALSE }, /* 8 */
+ { PDL, TRUE }, /* 9 */
+ { UNUSED, FALSE }, /* 10 */
+ { UNUSED, FALSE }, /* 11 */
+ { UNUSED, FALSE }, /* 12 */
+ { UNUSED, FALSE }, /* 13 */
+ { UNUSED, FALSE }, /* 14 */
+ { UNUSED, FALSE }, /* 15 */
+ }
+};
+
+
+Section_info_t *Sections[] = {
+ &ObjectSection,
+ &AttributeSection,
+ &AssociationSection,
+ &AbstractTypeSection,
+ &DataItemSection,
+ &MethodSection,
+ &TaskSection
+};
+
+/*
+ * exit_application
+ */
+
+void exit_application(
+ int status
+)
+{
+ fprintf( stderr, "*** Error encountered ***\n" );
+/*
+ fprintf( stderr, "*** Error encountered on line %d ***\n", CurrentLine );
+*/
+ fclose( OutFile );
+ exit( status );
+}
+
+/*************************************************************************
+ *************************************************************************
+ ***** LINE MANIPULATION ROUTINES *****
+ *************************************************************************
+ *************************************************************************/
+
+/*
+ * PrintLine
+ */
+
+void PrintLine(
+ Line_Control *line
+)
+{
+ assert( line );
+
+ if ( line->number == -1 )
+ fprintf( stderr, " " );
+ else
+ fprintf( stderr, "%5d", line->number );
+
+#if 0
+ fprintf( stderr, "%s\n", line->Contents );
+#else
+ /*
+ * Include some debugging information
+ */
+ fprintf(
+ stderr,
+ "<%d,%d>:%s\n",
+ line->keyword,
+ line->format,
+ line->Contents
+ );
+#endif
+}
+
+Chain_Control Line_Pool;
+
+/*
+ * FillLinePool
+ */
+
+void FillLinePool( void )
+{
+ void *pool;
+
+#define LINE_POOL_FILL_COUNT 100
+
+ pool = malloc( sizeof( Line_Control ) * LINE_POOL_FILL_COUNT );
+ assert( pool );
+
+ _Chain_Initialize(
+ &Line_Pool,
+ pool,
+ LINE_POOL_FILL_COUNT,
+ sizeof( Line_Control )
+ );
+}
+
+/*
+ * AllocateLine
+ */
+
+Line_Control *AllocateLine( void )
+{
+ Line_Control *new_line;
+
+ new_line = (Line_Control *) _Chain_Get( &Line_Pool );
+ if ( !new_line ) {
+ FillLinePool();
+ new_line = (Line_Control *) _Chain_Get( &Line_Pool );
+ assert( new_line );
+ }
+
+/*
+ * This is commented out because although it is helpful during debug,
+ * it consumes a significant percentage of the program's execution time.
+ */
+
+ memset( new_line->Contents, '\0', sizeof( new_line->Contents ) );
+ new_line->number = -1;
+
+ new_line->keyword = UNUSED;
+ new_line->format = NO_EXTRA_FORMATTING_INFO;
+
+ new_line->Node.next = NULL;
+ new_line->Node.previous = NULL;
+
+ return new_line;
+}
+
+/*
+ * FreeLine
+ */
+
+void FreeLine(
+ Line_Control *line
+)
+{
+ fflush( stdout );
+ _Chain_Append( &Line_Pool, &line->Node );
+}
+
+/*
+ * DeleteLine
+ */
+
+Line_Control *DeleteLine(
+ Line_Control *line
+)
+{
+ Line_Control *next;
+
+ next = (Line_Control *)line->Node.next;
+ _Chain_Extract( &line->Node );
+ FreeLine( line );
+ return next;
+}
+
+/*
+ * PrintSurroundingLines
+ */
+
+void PrintSurroundingLines(
+ Line_Control *line,
+ int backward,
+ int forward
+)
+{
+ int i;
+ int real_backward;
+ Line_Control *local;
+
+ for ( local=line, real_backward=0, i=1 ;
+ i<=backward ;
+ i++, real_backward++ ) {
+ if ( &local->Node == Lines.first )
+ break;
+ local = (Line_Control *) local->Node.previous;
+ }
+
+ for ( i=1 ; i<=real_backward ; i++ ) {
+ PrintLine( local );
+ local = (Line_Control *) local->Node.next;
+ }
+
+ PrintLine( local );
+
+ for ( i=1 ; i<=forward ; i++ ) {
+ local = (Line_Control *) local->Node.next;
+ if ( _Chain_Is_last( &local->Node ) )
+ break;
+ PrintLine( local );
+ }
+
+}
+
+/*
+ * SetLineFormat
+ */
+
+void SetLineFormat(
+ Line_Control *line,
+ ExtraFormat_info_t format
+)
+{
+ if ( line->format != NO_EXTRA_FORMATTING_INFO ) {
+ fprintf( stderr, "Line %d is already formatted\n", line->number );
+ PrintLine( line );
+ assert( FALSE );
+ }
+
+ line->format = format;
+}
+
+/*
+ * LineCopyFromRight
+ */
+
+void LineCopyFromRight(
+ Line_Control *line,
+ char *dest
+)
+{
+ char *p;
+
+ for ( p=line->Contents ; *p != ':' ; p++ )
+ ;
+ p++; /* skip the ':' */
+ for ( ; isspace( *p ) ; p++ )
+ ;
+
+ strcpy( dest, p );
+
+}
+
+/*
+ * LineCopySectionName
+ */
+
+void LineCopySectionName(
+ Line_Control *line,
+ char *dest
+)
+{
+ char *p;
+ char *d;
+
+ p = line->Contents;
+ d = dest;
+
+ if ( *p == '@' ) { /* skip texinfo command */
+ while ( !isspace( *p++ ) )
+ ;
+ }
+
+ for ( ; *p != ':' ; )
+ *d++ = *p++;
+
+ *d = '\0';
+}
+
+/*
+ * FormatParagraph
+ */
+
+Line_Control *FormatParagraph(
+ Line_Control *starting
+)
+{
+ Chain_Node *insert_after;
+ Line_Control *to_add;
+ Line_Control *new_line;
+ char Paragraph[ PARAGRAPH_SIZE ];
+ int starting_line;
+ char *src;
+ char *dest;
+ boolean do_loop;
+ boolean is_bullet;
+ int length;
+
+ length = 0;
+
+ starting_line = starting->number;
+ insert_after = starting->Node.previous;
+ to_add = starting;
+
+ dest = Paragraph;
+
+ is_bullet = FALSE;
+
+ for ( ; ; ) {
+ src = to_add->Contents;
+
+ for ( ; *src && isspace( *src ) ; src++ ); /* skip leading spaces */
+
+ if ( *src == '+' ) {
+ if ( is_bullet == TRUE )
+ break;
+ is_bullet = TRUE;
+ for ( src++ ; isspace(*src) ; src++ ) ;
+ }
+
+ do_loop = TRUE;
+ while ( *src && do_loop == TRUE ) {
+
+ if ( isspace( *src ) ) { /* convert multiple spaces to 1 */
+
+ if ( *(dest-1) == '.' ) { /* two spaces after period */
+ *dest++ = ' ';
+ length++;
+ }
+
+ assert( length < PARAGRAPH_SIZE );
+
+ *dest++ = ' ';
+ length++;
+
+ assert( length < PARAGRAPH_SIZE );
+
+ for ( ; isspace( *src ) ; src++ )
+ if ( !*src ) {
+ do_loop = FALSE;
+ break;
+ }
+
+ continue;
+
+ } else {
+ *dest++ = *src;
+ length++;
+ assert( length < PARAGRAPH_SIZE );
+ src++;
+ }
+ }
+
+ to_add = DeleteLine( to_add );
+
+ if ( _Chain_Is_last( &to_add->Node ) )
+ break;
+
+ if ( !strlen( to_add->Contents ) )
+ break;
+
+ if ( to_add->keyword )
+ break;
+
+ if ( !isspace( *(dest-1) ) ) {
+ if ( *(dest-1) == '.' ) {
+ *dest++ = ' ';
+ length++;
+ assert( length < PARAGRAPH_SIZE );
+ }
+ *dest++ = ' ';
+ length++;
+ assert( length < PARAGRAPH_SIZE );
+ }
+ }
+
+ new_line = AllocateLine();
+
+ SetLineFormat( new_line, (is_bullet) ? BULLET_OUTPUT : PARAGRAPH_OUTPUT );
+
+ *dest = '\0';
+
+ strcpy( new_line->Contents, Paragraph );
+
+ new_line->number = starting_line;
+
+ _Chain_Insert( insert_after, &new_line->Node );
+
+ return new_line;
+}
+
+/*
+ * FormatMultipleParagraphs
+ */
+
+Line_Control *FormatMultipleParagraphs(
+ Line_Control *starting
+)
+{
+ Line_Control *line = starting;
+
+ if ( _Chain_Is_last( &line->Node ) ) {
+ fprintf( stderr, "end of file reached when expecting text\n" );
+ exit_application( 0 );
+ }
+
+ if ( line->keyword ) {
+ line = (Line_Control *) line->Node.next;
+
+ if ( _Chain_Is_last( &line->Node ) ) {
+ fprintf( stderr, "end of file reached when expecting text\n" );
+ exit_application( 0 );
+ }
+ }
+
+ for ( ;; ) {
+ assert( line );
+
+ if ( _Chain_Is_last( &line->Node ) )
+ break;
+
+ if ( line->keyword )
+ break;
+
+ if ( !strlen( line->Contents ) ) {
+ line = DeleteLine( line );
+ continue;
+ }
+
+ line = FormatParagraph( line );
+ line = (Line_Control *) line->Node.next;
+ }
+}
+
+/*************************************************************************
+ *************************************************************************
+ ***** END OF LINE MANIPULATION ROUTINES *****
+ *************************************************************************
+ *************************************************************************/
+
+/*
+ * CountKeywordOccurrences
+ */
+
+int CountKeywordOccurrences(
+ Keyword_indices_t keyword
+)
+{
+ int count = 0;
+ Line_Control *line;
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ line = (Line_Control *) line->Node.next ) {
+ if ( line->keyword == keyword )
+ count += 1;
+ }
+
+ return count;
+}
+
+/*
+ * main
+ */
+
+int main(
+ int argc,
+ char **argv
+)
+{
+ int c;
+ int index;
+ boolean single_file_mode;
+
+ Verbose = FALSE;
+ Statistics = FALSE;
+ IncompletesAreErrors = TRUE;
+ InsertTBDs = FALSE;
+
+ while ((c = getopt(argc, argv, "istv?n:p:u:")) != EOF) {
+ switch (c) {
+ case 'i':
+ IncompletesAreErrors = FALSE;
+ break;
+ case 't':
+ InsertTBDs = TRUE;
+ break;
+ case 'v':
+ Verbose = TRUE;
+ break;
+ case 'n':
+ strcpy( DocsNextNode, optarg );
+ break;
+ case 'p':
+ strcpy( DocsPreviousNode, optarg );
+ break;
+ case 'u':
+ strcpy( DocsUpNode, optarg );
+ break;
+ case 's':
+ Statistics = TRUE;
+ break;
+ case '?':
+ usage();
+ return 0;
+ }
+ }
+
+ if ( Verbose ) {
+ fprintf( stderr, "Arguments successfully parsed\n" );
+ fprintf( stderr, "Next Node = (%s)\n", DocsNextNode );
+ fprintf( stderr, "Previous Node = (%s)\n", DocsPreviousNode );
+ fprintf( stderr, "Up Node = (%s)\n", DocsUpNode );
+ }
+
+ FillLinePool();
+
+ for ( index=optind ; index < argc ; index++ ) {
+ ProcessFile( argv[ index ], NULL );
+ }
+
+ if ( Verbose )
+ fprintf( stderr, "Exitting\n" );
+
+ return 0;
+}
+
+/*
+ * ProcessFile
+ */
+
+void ProcessFile(
+ char *inname,
+ char *outname
+)
+{
+ char out[ 256 ];
+ int index;
+ int out_index;
+
+ /*
+ * Automatically generate the output file name.
+ */
+
+ if ( outname == NULL ) {
+ out_index = 0;
+ for( index=0 ; inname[index] && inname[index] != '.' ; index++ ) {
+/*
+ if ( inname[ index ] != '_' )
+*/
+ out[ out_index++ ] = inname[ index ];
+ }
+
+ out[ out_index++ ] = '.';
+ out[ out_index++ ] = 't';
+ out[ out_index++ ] = 'e';
+ out[ out_index++ ] = 'x';
+ out[ out_index++ ] = 'i';
+ out[ out_index ] = '\0';
+
+ }
+
+ /*
+ * Read the file into our internal data structure
+ */
+
+ if ( Verbose )
+ printf( "Processing (%s) -> (%s)\n", inname, out );
+
+ ReadFileIntoChain( inname );
+
+ if ( Verbose )
+ fprintf( stderr, "-------->FILE READ IN\n" );
+
+ /*
+ * Remove any spaces before the keyword and mark each keyword line as
+ * such. Also remove extra white space at the end of lines.
+ */
+
+ StripBlanks();
+
+ if ( Verbose )
+ fprintf( stderr, "-------->BLANKS BEFORE KEYWORDS STRIPPED\n" );
+
+ /*
+ * Count the number of each type of thing
+ */
+
+ NumberOfAttributes = CountKeywordOccurrences( ATTRIBUTE );
+ NumberOfAssociations = CountKeywordOccurrences( ASSOCIATION );
+ NumberOfAbstractTypes = CountKeywordOccurrences( ABSTRACT_TYPE );
+ NumberOfDataItems = CountKeywordOccurrences( DATA_ITEM );
+ NumberOfMethods = CountKeywordOccurrences( METHOD );
+ NumberOfTasks = CountKeywordOccurrences( TASK );
+
+ if ( Verbose || Statistics ) {
+ fprintf( stderr, "NUMBER OF ATTRIBUTES = %d\n", NumberOfAttributes );
+ fprintf( stderr, "NUMBER OF ASSOCIATIONS = %d\n", NumberOfAssociations );
+ fprintf( stderr, "NUMBER OF ABSTRACT TYPES = %d\n", NumberOfAbstractTypes);
+ fprintf( stderr, "NUMBER OF DATA ITEMS = %d\n", NumberOfDataItems );
+ fprintf( stderr, "NUMBER OF METHODS = %d\n", NumberOfMethods );
+ fprintf( stderr, "NUMBER OF TASKS = %d\n", NumberOfTasks );
+ }
+
+ /*
+ * 1. Merge paragraphs entered as multiple lines into a single node
+ * on the chain.
+ * 2. Clean up "colon lines".
+ */
+
+ if ( MergeText() == -1 )
+ exit_application( 1 );
+
+ if ( Verbose )
+ fprintf( stderr, "-------->PARAGRAPHS MERGED\n" );
+
+ RemovePagebreaks();
+
+ /*
+ * Remove extraneous white space
+ */
+
+ if ( Verbose )
+ fprintf( stderr, "-------->PAGEBREAKS REMOVED\n" );
+
+ /*
+ * At this point, the only unmarked lines should be empty or errors.
+ * This deletes empty unmarked lines and flags the others as errors.
+ */
+
+ if ( RemoveExtraBlankLines() == -1 )
+ exit_application( 1 );
+
+ if ( Verbose )
+ fprintf( stderr, "-------->EXTRA BLANK LINES REMOVED\n" );
+
+ /*
+ * Now report which lines do not appear to be complete
+ */
+
+ if ( CheckForIncomplete() == -1 )
+ exit_application( 1 );
+
+ if ( Verbose )
+ fprintf( stderr, "-------->CHECKED FOR INCOMPLETE KEYWORDS\n" );
+
+ /*
+ * Check that all the required sections are present.
+ */
+
+ if ( CheckOutline() == -1 )
+ exit_application( 1 );
+
+ if ( Verbose )
+ fprintf( stderr, "-------->CHECKED FOR HIGH LEVEL SECTION PROBLEMS\n" );
+
+ /*
+ * Check for problems in each section.
+ */
+
+ if ( CheckSections() == -1 )
+ exit_application( 1 );
+
+ if ( Verbose )
+ fprintf( stderr, "-------->CHECKED FOR INTERNAL SECTION PROBLEMS\n" );
+
+ /*
+ * Look for Internal Consistencies
+ */
+
+ if ( Verbose )
+ fprintf( stderr, "-------->LOOKING FOR ERRORS\n" );
+
+ LookForInternalInconsistencies();
+
+ /*
+ * Formatting the file
+ */
+
+ FormatToTexinfo();
+
+ if ( Verbose )
+ fprintf( stderr, "-------->FILE FORMATTED TO TEXINFO\n" );
+
+ /*
+ * Print the file
+ */
+
+ PrintFile( out );
+
+ if ( Verbose )
+ fprintf( stderr, "-------->FILE PRINTED\n" );
+
+ /*
+ * Clean Up
+ */
+
+ ReleaseFile();
+
+ if ( Verbose )
+ fprintf( stderr, "-------->FILE RELEASED\n" );
+}
+
+/*
+ * LookForInternalInconsistencies
+ *
+ * This routine looks for lines with no formatting information and
+ * lines with too much formatting information.
+ */
+
+void LookForInternalInconsistencies( void )
+{
+ Line_Control *line;
+ int i;
+ int errors = 0;
+ char *src;
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ line = (Line_Control *)line->Node.next
+ ) {
+ if ( !line->keyword && line->format == NO_EXTRA_FORMATTING_INFO ) {
+ fprintf(
+ stderr,
+ "\nLine %d has no keyword or formatting:\n",
+ line->number
+ );
+ PrintSurroundingLines( line, 3, 3 );
+ errors++;
+ }
+ }
+
+ if ( errors )
+ exit_application( 1 );
+}
+
+/*
+ * usage
+ */
+
+void usage( void )
+{
+ int index;
+
+ for ( index=0 ; strcmp( Usage_Strings[ index ], "EOF" ) ; index++ )
+ fprintf( stderr, Usage_Strings[ index ] );
+}
+
+/*
+ * ReadFileIntoChain
+ */
+
+void ReadFileIntoChain(
+ char *inname
+)
+{
+ FILE *InFile;
+ int line_count;
+ int max_length;
+ char *line;
+ char Buffer[ BUFFER_SIZE ];
+ Line_Control *new_line;
+
+ InFile = fopen( inname, "r" );
+
+ if ( !InFile ) {
+ fprintf( stderr, "Unable to open (%s)\n", inname );
+ exit( 1 );
+ }
+ assert( InFile );
+
+ max_length = 0;
+ line_count = 0;
+
+ _Chain_Initialize_empty( &Lines );
+
+ for ( ;; ) {
+ line = fgets( Buffer, BUFFER_SIZE, InFile );
+ if ( !line )
+ break;
+
+ Buffer[ strlen( Buffer ) - 1 ] = '\0';
+
+ new_line = AllocateLine();
+
+ strcpy( new_line->Contents, Buffer );
+
+ new_line->number = ++line_count;
+
+ _Chain_Append( &Lines, &new_line->Node );
+ }
+
+ fclose( InFile );
+}
+
+/*
+ * StripBlanks
+ */
+
+void StripBlanks( void )
+{
+ Line_Control *line;
+ Keyword_indices_t index;
+ int indentation;
+ int length;
+ Keyword_info_t *key;
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ line = (Line_Control *) line->Node.next
+ ) {
+
+ /*
+ * Strip white space from the end of each line
+ */
+
+ length = strlen( line->Contents );
+
+ while ( isspace( line->Contents[ --length ] ) )
+ line->Contents[ length ] = '\0';
+
+ /*
+ * Strip white space from the front of each keyword line.
+ */
+
+ for ( index=KEYWORD_FIRST ; index <= KEYWORD_LAST ; index++ ) {
+ key = &Keywords[ index ];
+
+ switch ( key->level ) {
+ case SECTION: indentation = 0; break;
+ case SUBSECTION: indentation = 0; break;
+ case HEADING: indentation = 2; break;
+ default: assert( FALSE );
+ }
+
+ if ( !strncmp( &line->Contents[ indentation ], key->Name,
+ strlen( key->Name ) ) ) {
+ if ( indentation )
+ strcpy( line->Contents, &line->Contents[ indentation ] );
+ line->keyword = index;
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * CrunchRight
+ */
+
+boolean CrunchRight(
+ Line_Control *line
+)
+{
+ char Buffer[ PARAGRAPH_SIZE ];
+ char *src;
+ char *dest;
+ boolean is_text_to_right = FALSE;
+
+ src = line->Contents;
+ dest = Buffer;
+
+ while( *src != ':' ) {
+ if ( !*src ) {
+ fprintf(
+ stderr,
+ "Line %d should have had a colon\n",
+ line->number
+ );
+ exit_application( 1 );
+ }
+ *dest++ = *src++;
+ }
+
+ *dest++ = *src++; /* this is the ':' */
+
+ if ( *src ) {
+ *dest++ = ' ';
+ while ( *src && isspace( *src ) )
+ src++;
+
+ if ( *src )
+ is_text_to_right = TRUE;
+
+ while ( *src )
+ *dest++ = *src++;
+ }
+
+ *dest = '\0';
+
+ strcpy( line->Contents, Buffer );
+
+ return is_text_to_right;
+}
+
+/*
+ * CrunchBelow
+ */
+
+void CrunchBelow(
+ Line_Control *start_line,
+ Keywords_text_below_t text_below_mode
+)
+{
+ Line_Control *line;
+ int i;
+ int leading_white;
+ int length;
+
+ switch ( text_below_mode ) {
+ case BL_FORBIDDEN:
+ assert( FALSE );
+ case BL_FORMATTED:
+ (void) FormatMultipleParagraphs( start_line );
+ break;
+ case BL_RAW:
+ for ( line = (Line_Control *) start_line->Node.next;
+ !_Chain_Is_last( &line->Node ) ;
+ ) {
+ if ( strlen( line->Contents ) )
+ break;
+ line = DeleteLine( line );
+ }
+
+ for ( i=0 ; isspace( line->Contents[ i ] ) ; i++ )
+ ;
+
+ leading_white = i;
+
+ for ( ;
+ !_Chain_Is_last( &line->Node ) ;
+ ) {
+
+ assert( line );
+
+ if ( line->keyword )
+ break;
+
+ assert( !_Chain_Is_last( &line->Node ) );
+
+ length = strlen( line->Contents );
+
+ if ( length ) {
+ if ( length < leading_white ) {
+ fprintf(
+ stderr,
+ "\nLine %d %s:\n",
+ line->number,
+ "has inconsistent spacing -- is too short -- see 1st line of text"
+ );
+ PrintSurroundingLines( line, 0, 0 );
+ fprintf( stderr, "\n" );
+
+ }
+ for ( i=0 ; i < leading_white ; i++ ) {
+ if ( !isspace( line->Contents[ i ] ) ) {
+ fprintf(
+ stderr,
+ "\nLine %d %s:\n",
+ line->number,
+ "has inconsistent spacing -- see 1st line of text"
+ );
+ PrintSurroundingLines( line, 0, 0 );
+ fprintf( stderr, "\n" );
+ break;
+ }
+ }
+
+ strcpy( line->Contents, &line->Contents[ leading_white ] );
+
+ SetLineFormat( line, RAW_OUTPUT );
+ line = (Line_Control *) line->Node.next;
+ } else {
+ SetLineFormat( line, RAW_OUTPUT );
+ /* line = DeleteLine( line ); */
+ line = (Line_Control *) line->Node.next;
+ }
+ }
+ break;
+ }
+}
+
+/*
+ * MergeText
+ */
+
+/* XXX expand this and address the error numbers */
+char *Format_Errors[] = {
+ /* unused */ "no formatting error",
+ /* RT_FORBIDDEN */ "no text allowed to right or below",
+ /* RT_OPTIONAL */ "text to right optional -- none below",
+ /* RT_NONE */ "text to right is \"none\" or nothing -- none below",
+ /* RT_REQUIRED */ "text to right required -- none below",
+ /* RT_BELOW */ "text to right forbidden -- text below required",
+ /* RT_NONE_OR_BELOW */ "text to right is \"none\" OR there is text below",
+ /* RT_MAYBE_BELOW */ "text to right required -- text below optional",
+ /* RT_EITHER */ "text to right OR below",
+ /* RT_BOTH */ "text to right AND below"
+};
+
+
+int MergeText( void )
+{
+ Line_Control *line;
+ Line_Control *next;
+ Line_Control *new_line;
+ Keyword_info_t *key;
+ boolean is_text_to_right;
+ boolean is_text_below;
+ boolean add_text_to_right;
+ boolean add_text_below;
+ int errors = 0;
+ int error_code = 0;
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ ) {
+
+ if ( error_code ) {
+
+ fprintf(
+ stderr,
+ "\nLine %d %s:\n",
+ line->number,
+ Format_Errors[ error_code ]
+ );
+ PrintSurroundingLines( line, 0, 3 );
+ fprintf( stderr, "\n" );
+ error_code = 0;
+ line = (Line_Control *) line->Node.next;
+ }
+
+ key = &Keywords[ line->keyword ];
+
+ if ( !line->keyword ) {
+ line = (Line_Control *) line->Node.next;
+ continue;
+ }
+
+ /*
+ * Figure out where the text is for this keyword. It is a pretty
+ * ugly thing to look ahead for text below because of intermediate
+ * blank lines which we are not allowed to remove.
+ */
+
+ add_text_to_right = FALSE;
+ add_text_below = FALSE;
+
+ is_text_to_right = CrunchRight( line );
+
+ is_text_below = FALSE;
+
+ for ( next = (Line_Control *) line->Node.next ;
+ !_Chain_Is_last( &next->Node ) ;
+ next = (Line_Control *) next->Node.next ) {
+
+ if ( next->keyword )
+ break;
+
+ if ( strlen( next->Contents ) ) {
+ is_text_below = TRUE;
+ break;
+ }
+ }
+
+ switch ( key->text_mode ) {
+ case RT_FORBIDDEN: /* no text to right or below allowed */
+ if ( is_text_to_right || is_text_below ) {
+ error_code = 1;
+ errors++;
+ continue;
+ }
+ break;
+
+ case RT_OPTIONAL: /* text to right optional -- none below */
+ if ( is_text_below ) {
+ error_code = 2;
+ errors++;
+ continue;
+ }
+ break;
+
+ case RT_NONE: /* text to right is "none" or nothing -- none below */
+ if ( (is_text_to_right && !strstr( line->Contents, "none" )) ||
+ is_text_below ) {
+ error_code = 3;
+ errors++;
+ continue;
+ }
+ break;
+
+ case RT_REQUIRED: /* text to right required -- none below */
+ if ( is_text_below ) {
+ error_code = 4;
+ errors++;
+ continue;
+ }
+
+ if ( !is_text_to_right ) {
+ if ( !InsertTBDs ) {
+ error_code = 4;
+ errors++;
+ continue;
+ } else
+ add_text_to_right = TRUE;
+ }
+ break;
+
+ case RT_BELOW: /* text to right forbidden -- text below required */
+ if ( is_text_to_right ) {
+ error_code = 5;
+ errors++;
+ continue;
+ }
+
+ if ( !is_text_below ) {
+ if ( !InsertTBDs ) {
+ error_code = 5;
+ errors++;
+ continue;
+ } else
+ add_text_below = TRUE;
+ }
+ break;
+
+ case RT_NONE_OR_BELOW: /* text to right is "none" OR text below */
+
+ if ( is_text_to_right ) {
+ if ( strstr( line->Contents, "none" ) )
+ break;
+ error_code = 6;
+ errors++;
+ continue;
+ }
+
+ if ( !is_text_below ) {
+ if ( !InsertTBDs ) {
+ error_code = 6;
+ errors++;
+ continue;
+ } else
+ add_text_to_right = TRUE;
+ }
+ break;
+ /* text to right required -- text below optional */
+ case RT_MAYBE_BELOW:
+ if ( !is_text_to_right ) {
+ error_code = 7;
+ errors++;
+ continue;
+ }
+ break;
+
+ case RT_EITHER: /* text to right OR below */
+ if ( !(is_text_to_right || is_text_below) ) {
+ if ( !InsertTBDs ) {
+ error_code = 8;
+ errors++;
+ continue;
+ } else
+ add_text_to_right = TRUE;
+ }
+ break;
+
+ case RT_BOTH: /* text to right AND below */
+ if ( !(is_text_to_right && is_text_below) ) {
+ if ( !InsertTBDs ) {
+ error_code = 9;
+ errors++;
+ continue;
+ } else {
+ add_text_to_right = TRUE;
+ add_text_below = TRUE;
+ }
+ }
+ break;
+ }
+
+ if ( add_text_to_right )
+ strcat( line->Contents, " TBD" );
+
+ if ( add_text_below ) {
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "TBD" );
+ _Chain_Insert( &line->Node, &new_line->Node );
+ is_text_below = TRUE;
+ }
+
+ if ( is_text_below )
+ CrunchBelow( line, key->text_below_mode );
+
+ line = (Line_Control *) line->Node.next;
+ }
+ return (errors) ? -1 : 0;
+}
+
+/*
+ * CheckForIncomplete
+ */
+
+char *IncompleteMarkers[] = {
+ "??",
+ "xxx",
+ "XXX",
+ "xyz",
+ "XYZ"
+};
+
+int CheckForIncomplete()
+{
+ Line_Control *line;
+ int i;
+ int errors = 0;
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ line = (Line_Control *) line->Node.next
+ ) {
+ for ( i=0 ; i < NUMBER_ELEMENTS( IncompleteMarkers ) ; i++ ) {
+ if ( !strstr( line->Contents, IncompleteMarkers[ i ] ) )
+ continue;
+
+ fprintf(
+ stderr,
+ "\nLine %d %s:\n",
+ line->number,
+ "appears to be incomplete"
+ );
+ PrintSurroundingLines( line, 0, 0 );
+ fprintf( stderr, "\n" );
+ if ( IncompletesAreErrors )
+ errors++;
+ break;
+ }
+ }
+ return ( errors ) ? -1 : 0;
+}
+
+/*
+ * CheckOutline
+ *
+ * Insure all section headers are present.
+ * Check sections which say "none", really have subsections.
+ * Check sections which have subsections, don't say none.
+ */
+
+int CheckOutline( void )
+{
+ Line_Control *line;
+ int count;
+ int errors = 0;
+ void *none_present;
+ boolean KeywordsPresent[ KEYWORD_LAST + 1 ];
+ Keyword_indices_t keyword;
+
+ for ( keyword=0 ; keyword <= KEYWORD_LAST ; keyword++ )
+ KeywordsPresent[ keyword ] = FALSE;
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ line = (Line_Control *) line->Node.next
+ ) {
+
+ KeywordsPresent[ line->keyword ] = TRUE;
+
+ switch ( line->keyword ) {
+ case ATTRIBUTE_DESCRIPTIONS:
+ count = NumberOfAttributes;
+ break;
+ case ASSOCIATION_DESCRIPTIONS:
+ count = NumberOfAssociations;
+ break;
+ case ABSTRACT_TYPE_DESCRIPTIONS:
+ count = NumberOfAbstractTypes;
+ break;
+ case DATA_ITEM_DESCRIPTIONS:
+ count = NumberOfDataItems;
+ break;
+ case METHOD_DESCRIPTIONS:
+ count = NumberOfMethods;
+ break;
+ case TASK_DESCRIPTIONS:
+ count = NumberOfTasks;
+ break;
+ default:
+ count = -1;
+ break;
+ }
+ if ( count == -1 )
+ continue;
+
+ none_present = strstr( line->Contents, "none" );
+
+ /* valid cases are (none_present && !count) AND (!none_present && count) */
+ if ( none_present && count ) {
+ fprintf(
+ stderr,
+ "\nLine %d : %s\n",
+ line->number,
+ "section header says \"none\" and there are subsections"
+ );
+ PrintSurroundingLines( line, 0, 0 );
+ fprintf( stderr, "\n" );
+ errors++;
+ }
+ if ( !none_present && !count ) {
+ fprintf(
+ stderr,
+ "\nLine %d : %s\n",
+ line->number,
+ "section header does not say \"none\" and there are no subsections"
+ );
+ PrintSurroundingLines( line, 0, 0 );
+ fprintf( stderr, "\n" );
+ errors++;
+ }
+ }
+
+ for ( keyword=0 ; keyword <= KEYWORD_LAST ; keyword++ ) {
+ if ( Keywords[ keyword ].level != SECTION )
+ continue;
+
+ if ( !KeywordsPresent[ keyword ] ) {
+ fprintf(
+ stderr,
+ "Section (%s) is missing\n",
+ Keywords[ keyword ].Name
+ );
+ errors++;
+ }
+ }
+
+ return (errors) ? -1 : 0;
+}
+
+/*
+ * ReportMissingKeywords
+ */
+
+int ReportMissingKeywords(
+ Section_info_t *section,
+ Line_Control *line,
+ int elements_present[ MAXIMUM_ELEMENTS ]
+)
+{
+ int i;
+ int errors = 0;
+ int last_found;
+
+#ifdef SECTION_DEBUG
+ PrintLine( line );
+ for ( i=0 ; i < MAXIMUM_ELEMENTS ; i++ )
+ fprintf( stderr, "%d ", elements_present[ i ] );
+ fprintf( stderr, "\n" );
+#endif
+
+ /*
+ * Check for missing sections
+ */
+
+ for ( i=0 ; i < MAXIMUM_ELEMENTS ; i++ ) {
+ if ( section->Description[ i ].keyword == UNUSED )
+ break;
+
+#ifdef SECTION_DEBUG
+ fprintf(
+ stderr,
+ "%d %d %s\n",
+ section->Description[ i ].is_required,
+ elements_present[ i ],
+ Keywords[ section->Description[ i ].keyword ].Name
+ );
+#endif
+
+ if ( section->Description[ i ].is_required && elements_present[i] == -1 ) {
+ fprintf(
+ stderr,
+ "Section starting at line %d is missing the %s keyword\n",
+ line->number,
+ Keywords[ section->Description[ i ].keyword ].Name
+ );
+ errors++;
+ }
+ }
+
+ last_found = -1;
+
+ for ( i=0 ; i < MAXIMUM_ELEMENTS ; i++ ) {
+ if ( section->Description[ i ].keyword == UNUSED )
+ break;
+
+ if ( elements_present[i] == -1 )
+ continue;
+
+ if ( elements_present[i] > last_found ) {
+ last_found = elements_present[i];
+ continue;
+ }
+
+ fprintf(
+ stderr,
+ "Keywords in the section starting at line %d are in the wrong order\n",
+ line->number
+ );
+ errors++;
+ break;
+
+ }
+
+ return errors;
+}
+
+/*
+ * ScanForNextSection
+ */
+
+Line_Control *ScanForNextSection(
+ Line_Control *start_line,
+ Section_info_t *section
+)
+{
+ Line_Control *line;
+ Element_info_t *Elements;
+
+ line = start_line;
+ Elements = section->Description;
+
+ for ( ;; ) {
+ line = (Line_Control *) line->Node.next;
+
+ if ( line->keyword == END_OBJECT )
+ break;
+
+ assert( line );
+ assert( !_Chain_Is_last( &line->Node ) );
+
+ if ( Keywords[ line->keyword ].level == SECTION &&
+ section->Next_section != line->keyword ) {
+
+ fprintf(
+ stderr,
+ "Sections appear to be out of order at line %d\n",
+ start_line->number
+ );
+ return NULL;
+ }
+
+ if ( section->Next_section == line->keyword ) /* next section */
+ break;
+
+ if ( Elements[ 0 ].keyword == line->keyword ) /* repeating subsection */
+ break;
+ }
+
+ return line;
+}
+
+/*
+ * CheckSections
+ */
+
+int CheckSections( void )
+{
+ Line_Control *line;
+ Line_Control *scan_line;
+ Section_info_t *section;
+ Keyword_info_t *key;
+ Element_info_t *Elements;
+ int elements_present[ MAXIMUM_ELEMENTS ];
+ boolean stay_in_subsection;
+ int i;
+ int errors;
+ int subsection;
+ int element;
+ int keyword_count;
+ Line_Control *next_section;
+
+ errors = 0;
+ line = (Line_Control *) Lines.first;
+
+ for ( i=0 ; i < NUMBER_ELEMENTS( Sections ) ; i++ ) {
+ section = Sections[ i ];
+ Elements = section->Description;
+ subsection = 0;
+
+ if ( strstr( line->Contents, "none" ) ) {
+ next_section = ScanForNextSection( line, section );
+ if ( !next_section ) {
+ errors++;
+ goto end_object;
+ }
+ line = next_section;
+ if ( line->keyword == END_OBJECT )
+ goto end_object;
+ continue;
+ }
+
+ while ( Elements[ 0 ].keyword != line->keyword ) {
+ if ( line->keyword == END_OBJECT )
+ goto end_object;
+
+ if( !line || _Chain_Is_last( &line->Node ) ) {
+ fprintf( stderr, "out of sync -- aborting\n" );
+ errors++;
+ goto end_object;
+ }
+ line = (Line_Control *) line->Node.next;
+ }
+
+repeating_subsection:
+
+#ifdef SECTION_DEBUG
+ fprintf( stderr, "Checking Section %d Subsection %d\n", i, subsection );
+#endif
+ assert( line );
+ assert( !_Chain_Is_last( &line->Node ) );
+
+ /*
+ * Per Subsection Initialization
+ */
+
+ subsection++;
+
+ keyword_count = 0;
+
+ next_section = ScanForNextSection( line, section );
+ if ( !next_section ) {
+ errors++;
+ goto end_object;
+ }
+
+ for ( element=0 ; element < MAXIMUM_ELEMENTS ; element++ )
+ elements_present[ element ] = -1;
+
+ /*
+ * Do a subsection
+ */
+
+ /* validate each keyword */
+
+ for ( scan_line = line ; ; ) {
+
+ if ( !scan_line->keyword ) {
+ scan_line = (Line_Control *) scan_line->Node.next;
+ continue;
+ }
+
+ if ( scan_line == next_section )
+ break;
+
+ if ( *Keywords[ scan_line->keyword ].keyword_validation_routine ) {
+ if ( (*Keywords[ scan_line->keyword ].keyword_validation_routine )(
+ scan_line
+ ) ) errors++;
+ }
+
+ scan_line = (Line_Control *) scan_line->Node.next;
+ }
+
+ /* scan subsection for keywords */
+
+ for ( scan_line = line ; ; ) {
+
+ if ( !scan_line->keyword ) {
+ scan_line = (Line_Control *) scan_line->Node.next;
+ continue;
+ }
+
+ if ( scan_line == next_section )
+ break;
+
+ for ( element=0 ; element < MAXIMUM_ELEMENTS ; element++ ) {
+ if ( scan_line->keyword == Elements[ element ].keyword ) {
+ if ( elements_present[ element ] != -1 ) {
+ fprintf(
+ stderr,
+ "Section starting at line %d has the %s keyword more than once\n",
+ line->number,
+ Keywords[ Elements[ i ].keyword ].Name
+ );
+ errors++;
+ }
+
+#ifdef SECTION_DEBUG
+ fprintf( stderr, "FOUND %s %d %d\n",
+ Keywords[ Elements[ element ].keyword ].Name,
+ element, keyword_count );
+#endif
+ elements_present[ element ] = keyword_count++;
+ break;
+ }
+ if ( Elements[ element ].keyword == UNUSED )
+ break;
+ }
+
+ scan_line = (Line_Control *) scan_line->Node.next;
+ }
+ errors += ReportMissingKeywords( section, line, elements_present );
+
+ /*
+ * Validate the section as a whole
+ */
+
+ if ( section->section_validation_routine ) {
+ if ( (*section->section_validation_routine)(section, line, next_section) )
+ errors++;
+ }
+
+scan_for_next_section:
+ /*
+ * Scan forward until next subsection or next section
+ */
+
+#ifdef SECTION_DEBUG
+ fprintf( stderr, "End of Subsection\n" );
+#endif
+ line = next_section;
+ if ( line->keyword == END_OBJECT ) {
+ goto end_object;
+ }
+
+ if ( Elements[ 0 ].keyword == line->keyword ) { /* repeating subsection */
+ if ( !section->repeats ) {
+ fprintf(
+ stderr,
+ "Invalid repeating subsection starting at line %d\n",
+ line->number
+ );
+ errors++;
+ goto end_object;
+ }
+ goto repeating_subsection;
+ }
+
+ }
+
+end_object:
+ return (errors) ? -1 : 0;
+}
+/*
+ * RemovePagebreaks
+ */
+
+void RemovePagebreaks()
+{
+ Line_Control *line;
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ ) {
+ if ( !strcmp( line->Contents, PAGE_SEPARATOR ) )
+ line = DeleteLine( line );
+ else
+ line = (Line_Control *) line->Node.next;
+ }
+}
+
+/*
+ * strIsAllSpace
+ */
+
+boolean strIsAllSpace(
+ char *s
+)
+{
+ char *p;
+
+ for ( p = s ; *p ; p++ )
+ if ( !isspace( *p ) )
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * RemoveExtraBlankLines
+ *
+ * NOTE: Be careful not remove to remove white space in raw text.
+ */
+
+int RemoveExtraBlankLines()
+{
+ Line_Control *line;
+ Line_Control *previous;
+ int errors;
+
+ errors = 0;
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ line = (Line_Control *) line->Node.next
+ ) {
+ if ( line->keyword || line->format )
+ continue;
+
+ if ( !strlen( line->Contents ) ) {
+ line = DeleteLine( line );
+ line = (Line_Control *) line->Node.previous;
+ continue;
+ }
+
+ fprintf(
+ stderr,
+ "\nLine %d is not associated with a keyword:\n",
+ line->number
+ );
+ PrintSurroundingLines( line, 0, 0 );
+ fprintf( stderr, "\n" );
+ errors++;
+ }
+ return ( errors ) ? -1 : 0;
+}
+
+/*
+ * strCopyToColon
+ */
+
+void strCopyToColon(
+ char *src,
+ char *dest
+)
+{
+ char *s = src;
+ char *d = dest;
+
+ for ( ; *s && *s != ':' ; )
+ *d++ = *s++;
+ *d ='\0';
+}
+
+/*
+ * BuildTexinfoNodes
+ */
+
+void BuildTexinfoNodes( void )
+{
+ Line_Control *line;
+ Line_Control *new_line;
+ Line_Control *next_node;
+ char Buffer[ BUFFER_SIZE ];
+ char ObjectName[ BUFFER_SIZE ];
+ char NodeName[ BUFFER_SIZE ];
+ char NextNode[ BUFFER_SIZE ];
+ char NextNodeName[ BUFFER_SIZE ];
+ char PreviousNodeName[ BUFFER_SIZE ];
+ char UpNodeName[ BUFFER_SIZE ];
+ char SectionName[ BUFFER_SIZE ];
+ char MenuBuffer[ BUFFER_SIZE ];
+ Line_Control *menu_insert_point;
+ Line_Control *node_line;
+ boolean next_found;
+ int menu_items;
+
+ strcpy( PreviousNodeName, DocsPreviousNode );
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ line = (Line_Control *) line->Node.next
+ ) {
+ menu_insert_point = (Line_Control *) line->Node.next;
+
+ switch ( Keywords[ line->keyword ].level ) {
+ case TEXT:
+ case HEADING:
+ break;
+ case SECTION:
+ if ( line->keyword == END_OBJECT )
+ goto bottom;
+
+ if ( line->keyword == OBJECT ) {
+ LineCopyFromRight( line, Buffer );
+ sprintf( ObjectName, "%s Object", Buffer );
+ strcpy( NodeName, ObjectName );
+ strcpy( UpNodeName, DocsUpNode );
+ } else {
+ LineCopySectionName( line, Buffer );
+ sprintf( NodeName, "%s %s", ObjectName, Buffer );
+ strcpy( UpNodeName, ObjectName );
+ }
+ strtoInitialCaps( NULL, NodeName );
+ strtoInitialCaps( NULL, UpNodeName );
+ strcpy( SectionName, NodeName );
+
+ /*
+ * Go ahead and put it on the chain in the right order (ahead of
+ * the menu) and we can fill it in later (after the menu is built).
+ */
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@ifinfo" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+
+ node_line = AllocateLine();
+ _Chain_Insert( line->Node.previous, &node_line->Node );
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@end ifinfo" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+
+ menu_items = 0;
+
+ if ( line->keyword == OBJECT ) {
+ next_node = (Line_Control *) line->Node.next;
+ next_found = FALSE;
+ for ( ; ; ) {
+ if ( next_node->keyword == END_OBJECT )
+ break;
+ if ( Keywords[ next_node->keyword ].level == SECTION ) {
+ LineCopySectionName( next_node, Buffer );
+ strtoInitialCaps( NULL, Buffer );
+
+ if ( !next_found ) {
+ next_found = TRUE;
+ sprintf( NextNodeName, "%s %s", ObjectName, Buffer );
+ }
+ if ( menu_items == 0 ) {
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@ifinfo" );
+ _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@menu" );
+ _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
+ }
+
+ menu_items++;
+
+ new_line = AllocateLine();
+ sprintf( new_line->Contents, "* %s %s::", ObjectName, Buffer );
+ _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node);
+ }
+ next_node = (Line_Control *) next_node->Node.next;
+ }
+ } else {
+ next_node = (Line_Control *) line->Node.next;
+
+ next_found = FALSE;
+ for ( ; ; ) {
+ if ( Keywords[ next_node->keyword ].level == SECTION ) {
+ if ( !next_found ) {
+ if ( next_node->keyword == END_OBJECT ) {
+ strcpy( NextNodeName, DocsNextNode );
+ } else {
+ LineCopySectionName( next_node, Buffer );
+ sprintf( NextNodeName, "%s %s", ObjectName, Buffer );
+ strtoInitialCaps( NULL, NextNodeName );
+ }
+ next_found = TRUE;
+ }
+ break;
+ } else if ( Keywords[ next_node->keyword ].level == SUBSECTION ) {
+ LineCopySectionName( next_node, Buffer );
+ strtoInitialCaps( NULL, Buffer );
+ sprintf( MenuBuffer, "%s %s - ", ObjectName, Buffer );
+ LineCopyFromRight( next_node, Buffer );
+ strcat( MenuBuffer, Buffer );
+
+ if ( menu_items == 0 ) {
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@ifinfo" );
+ _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@menu" );
+ _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
+ }
+
+ menu_items++;
+
+ new_line = AllocateLine();
+ sprintf( new_line->Contents, "* %s::", MenuBuffer );
+ _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
+
+ if ( !next_found ) {
+ next_found = TRUE;
+ strcpy( NextNodeName, MenuBuffer );
+ }
+ }
+ next_node = (Line_Control *) next_node->Node.next;
+ }
+ }
+
+ if ( menu_items ) {
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@end menu" );
+ _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@end ifinfo" );
+ _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
+ }
+
+#if 0
+ fprintf(
+ stderr,
+ "@node %s, %s, %s, %s\n",
+ NodeName,
+ NextNodeName,
+ PreviousNodeName,
+ UpNodeName
+ );
+#endif
+ /* node_line was previously inserted */
+ sprintf(
+ node_line->Contents,
+ "@node %s, %s, %s, %s",
+ NodeName,
+ NextNodeName,
+ PreviousNodeName,
+ UpNodeName
+ );
+
+ strcpy( PreviousNodeName, NodeName );
+ break;
+
+ case SUBSECTION:
+ strcpy( UpNodeName, SectionName );
+
+ LineCopySectionName( line, Buffer );
+ strtoInitialCaps( NULL, Buffer );
+ sprintf( NodeName, "%s %s - ", ObjectName, Buffer );
+ LineCopyFromRight( line, Buffer );
+ strcat( NodeName, Buffer );
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@ifinfo" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+
+ next_node = (Line_Control *) line->Node.next;
+ for ( ; ; ) {
+ if ( Keywords[ next_node->keyword ].level == SECTION ) {
+ if ( next_node->keyword == END_OBJECT ) {
+ strcpy( NextNodeName, DocsNextNode );
+ } else {
+ LineCopySectionName( next_node, Buffer );
+ sprintf( NextNodeName, "%s %s", ObjectName, Buffer );
+ strtoInitialCaps( NULL, NextNodeName );
+ }
+ break;
+ } else if ( Keywords[ next_node->keyword ].level == SUBSECTION ) {
+ LineCopySectionName( next_node, Buffer );
+ strtoInitialCaps( NULL, Buffer );
+ sprintf( NextNodeName, "%s %s - ", ObjectName, Buffer );
+ LineCopyFromRight( next_node, Buffer );
+ strcat( NextNodeName, Buffer );
+ break;
+ }
+ next_node = (Line_Control *) next_node->Node.next;
+ }
+
+#if 0
+ fprintf(
+ stderr,
+ "@node %s, %s, %s, %s\n",
+ NodeName,
+ NextNodeName,
+ PreviousNodeName,
+ UpNodeName
+ );
+#endif
+ new_line = AllocateLine();
+ sprintf(
+ new_line->Contents,
+ "@node %s, %s, %s, %s",
+ NodeName,
+ NextNodeName,
+ PreviousNodeName,
+ UpNodeName
+ );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@end ifinfo" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+
+ strcpy( PreviousNodeName, NodeName );
+ break;
+ }
+ }
+bottom:
+}
+
+/*
+ * FormatToTexinfo
+ */
+
+char *Texinfo_Headers[] = {
+ "\\input texinfo @c -*-texinfo-*-",
+ "@c %**start of header",
+ "@setfilename ",
+ "@settitle ",
+ "@paragraphindent 0",
+ "@c %**end of header",
+ "",
+ "@c",
+ "@c COPYRIGHT (c) 1996.",
+ "@c On-Line Applications Research Corporation (OAR).",
+ "@c All rights reserved.",
+ "@c",
+ "@c This file is automatically generated. DO NOT EDIT!!",
+ "@c",
+ "",
+ "@c This prevents a black box from being printed on overfull lines.",
+ "@c The alternative is to rework a sentence to avoid this problem.",
+ "@finalout",
+ "",
+ "@tex",
+ "\\global\\parindent 0in",
+ "\\global\\chapheadingskip = 15pt plus 4pt minus 2pt",
+ "\\global\\secheadingskip = 12pt plus 4pt minus 2pt",
+ "\\global\\subsecheadingskip = 9pt plus 4pt minus 2pt",
+ "",
+ "@ifclear smallbook",
+ "\\global\\parskip 6pt plus 1pt",
+ "@end ifclear",
+ "@end tex",
+ "@setchapternewpage odd",
+ "@ifinfo",
+ "@top ",
+ "@node Top, (dir), (dir), (dir)",
+ "@end ifinfo",
+ "@c ",
+ "@c This is the end of the header block",
+ "@c "
+};
+
+void FormatToTexinfo( void )
+{
+ Line_Control *line;
+ Line_Control *new_line;
+ char Buffer[ PARAGRAPH_SIZE ];
+ int i;
+ char ChapterTitle[ PARAGRAPH_SIZE ];
+ char InfoFile[ PARAGRAPH_SIZE ];
+ char *p;
+ boolean new_section;
+ boolean in_bullets;
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ ) {
+
+ switch ( line->keyword ) {
+ case UNUSED:
+ line = (Line_Control *) line->Node.next;
+ break;
+
+ case OBJECT:
+ LineCopyFromRight( line, ChapterTitle );
+ strcpy( InfoFile, ChapterTitle );
+
+ for ( p=InfoFile ; *p ; *p++ ) /* turn this into a file name */
+ if ( isspace( *p ) )
+ *p = '_';
+
+ sprintf( Buffer, "@chapter %s", line->Contents );
+ strcpy( line->Contents, Buffer );
+ line = (Line_Control *) line->Node.next;
+ break;
+
+ case ATTRIBUTE_DESCRIPTIONS:
+ case ASSOCIATION_DESCRIPTIONS:
+ case ABSTRACT_TYPE_DESCRIPTIONS:
+ case DATA_ITEM_DESCRIPTIONS:
+ case METHOD_DESCRIPTIONS:
+ case TASK_DESCRIPTIONS:
+ sprintf( Buffer, "@section %s", line->Contents );
+ strcpy( line->Contents, Buffer );
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@page" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+
+ line = (Line_Control *) line->Node.next;
+ new_section = TRUE;
+ break;
+
+ case END_OBJECT:
+ line->Contents[ 0 ] = '\0';
+ goto bottom;
+
+ case ATTRIBUTE:
+ case ASSOCIATION:
+ case ABSTRACT_TYPE:
+ case DATA_ITEM:
+ if ( !new_section ) {
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@need 4000" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+ }
+ new_section = FALSE;
+ sprintf( Buffer, "@subsection %s", line->Contents );
+ strcpy( line->Contents, Buffer );
+ line = (Line_Control *) line->Node.next;
+ break;
+
+ case METHOD:
+ case TASK:
+ if ( !new_section ) {
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@page" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+ }
+ new_section = FALSE;
+ sprintf( Buffer, "@subsection %s", line->Contents );
+ strcpy( line->Contents, Buffer );
+ line = (Line_Control *) line->Node.next;
+ break;
+
+ case DESCRIPTION:
+ case COPYRIGHT:
+ case PORTING:
+ case THEORY_OF_OPERATION:
+ case DEPENDENCIES:
+ case NOTES:
+ sprintf( Buffer, "@subheading %s\n", line->Contents );
+ strcpy( line->Contents, Buffer );
+ line = (Line_Control *) line->Node.next;
+
+ /* now take care of the paragraphs which are here */
+
+ in_bullets = FALSE;
+ do {
+ line = (Line_Control *) line->Node.next;
+ if ( line->format == BULLET_OUTPUT ) {
+ if ( !in_bullets ) {
+ in_bullets = TRUE;
+
+ new_line = AllocateLine();
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@itemize @bullet" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+ }
+ sprintf( Buffer, "@item %s\n", line->Contents );
+ strcpy( line->Contents, Buffer );
+ } else if ( in_bullets ) {
+ in_bullets = FALSE;
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@end itemize" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+
+ new_line = AllocateLine();
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+ } else {
+ new_line = AllocateLine();
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+ }
+ } while ( !line->keyword );
+
+ break;
+
+ case DERIVATION:
+ case TYPE:
+ case RANGE:
+ case UNITS:
+ case SCALE_FACTOR:
+ case TOLERANCE:
+ case VISIBILITY:
+ case ASSOCIATED_WITH:
+ case MULTIPLICITY:
+ case TIMING:
+ sprintf( Buffer, "@subheading %s\n", line->Contents );
+ strcpy( line->Contents, Buffer );
+ line = (Line_Control *) line->Node.next;
+ break;
+
+ case MEMBERS:
+ case DEFAULT:
+ case REQUIREMENTS:
+ case REFERENCES:
+ case INPUTS:
+ case OUTPUTS:
+ case PDL:
+ case SYNCHRONIZATION:
+ sprintf( Buffer, "@subheading %s\n", line->Contents );
+ strcpy( line->Contents, Buffer );
+
+ /* now take care of the raw text which is here */
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@example" );
+ _Chain_Insert( &line->Node, &new_line->Node );
+
+ do {
+ line = (Line_Control *) line->Node.next;
+ if ( !strlen( line->Contents ) ) {
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@end example" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@example" );
+ _Chain_Insert( &line->Node, &new_line->Node );
+
+ }
+ } while ( !line->keyword );
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@end example" );
+ _Chain_Insert( line->Node.previous, &new_line->Node );
+ /* at this point line points to the next keyword */
+ break;
+ }
+ }
+
+bottom:
+#if 0
+ for ( i=NUMBER_ELEMENTS( Texinfo_Headers ) - 1 ; i >= 0 ; i-- ) {
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, Texinfo_Headers[ i ] );
+ if ( !strcmp( "@setfilename ", new_line->Contents ) )
+ strcat( new_line->Contents, ChapterTitle );
+ else if ( !strcmp( "@settitle ", new_line->Contents ) )
+ strcat( new_line->Contents, InfoFile );
+ else if ( !strcmp( "@top ", new_line->Contents ) )
+ strcat( new_line->Contents, InfoFile );
+ _Chain_Insert( _Chain_Head( &Lines ), &new_line->Node );
+ }
+
+ /*
+ * Remove the special end of object string. No one wants to see
+ * it in the printed output and the node is already marked "END_OBJECT".
+ */
+
+ ((Line_Control *)Lines.last)->Contents[ 0 ] = '\0';
+
+ new_line = AllocateLine();
+ strcpy( new_line->Contents, "@bye" );
+ _Chain_Append( &Lines, &new_line->Node );
+
+#endif
+ if ( Verbose )
+ fprintf( stderr, "-------->INSERTING TEXINFO MENUS\n" );
+
+ BuildTexinfoNodes();
+}
+
+/*
+ * PrintFile
+ */
+
+void PrintFile(
+ char *out
+)
+{
+ Line_Control *line;
+
+ OutFile = fopen( out, "w+" );
+
+ if ( !OutFile ) {
+ fprintf( stderr, "Unable to open (%s) for output\n", out );
+ exit_application( 1 );
+ }
+ assert( OutFile );
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ line = (Line_Control *) line->Node.next ) {
+ fprintf( OutFile, "%s\n", line->Contents );
+/*
+ fprintf(
+ OutFile,
+ "(%d,%d)%s\n",
+ line->keyword,
+ line->format,
+ line->Contents
+ );
+*/
+ }
+}
+
+/*
+ * DumpList
+ */
+
+void DumpList(
+ Chain_Control *the_list
+)
+{
+ Line_Control *line;
+
+ fprintf( stderr, "---> Dumping list (%p)\n", the_list );
+
+ for ( line = (Line_Control *) the_list->first ;
+ !_Chain_Is_last( &line->Node ) ;
+ line = (Line_Control *) line->Node.next ) {
+ fprintf( stderr, "%s\n", line->Contents );
+ }
+}
+
+/*
+ * ReleaseFile
+ */
+
+void ReleaseFile()
+{
+ Line_Control *line;
+ Line_Control *next;
+
+ for ( line = (Line_Control *) Lines.first ;
+ !_Chain_Is_last( &line->Node ) ;
+ ) {
+ next = (Line_Control *) line->Node.next;
+ line = next;
+ }
+}
+
+/*
+ * strtoInitialCaps
+ */
+
+void strtoInitialCaps(
+ char *dest,
+ char *src
+)
+{
+ char *source = src;
+ char *destination = dest;
+
+ if ( !dest )
+ return;
+ strcpy( dest, src );
+#if 0
+ source = src;
+ destination = (dest) ? dest : src;
+
+ while ( *source ) {
+ while ( isspace( *source ) )
+ *destination++ = *source++;
+
+ if ( !*source )
+ break;
+
+ *destination++ = toupper( *source++ );
+
+ for ( ; *source && !isspace( *source ) ; source++ )
+ *destination++ = tolower( *source );
+
+ if ( !*source )
+ break;
+ }
+
+ *destination = '\0';
+#endif
+}
+
+/*
+ * Validate_visibility
+ */
+
+char *Valid_visibilities[] = {
+ "public",
+ "private"
+};
+
+int Validate_visibility(
+ Line_Control *line
+)
+{
+ char *s;
+ char *d;
+ char Buffer[ BUFFER_SIZE ];
+ char Visibility[ BUFFER_SIZE ];
+ int i;
+ boolean found;
+ int errors = 0;
+
+ LineCopyFromRight( line, Buffer );
+
+ memset( Visibility, '\0', sizeof( Visibility ) );
+ s = Buffer;
+
+ for ( d=Visibility ; ; s++, d++ ) {
+ *d = *s;
+ if ( !*s || isspace(*s) )
+ break;
+ }
+ *d = '\0';
+
+ if ( isspace(*s) ) {
+ fprintf(
+ stderr,
+ "Unexpected white space on line %d -- are there multiple words?\n",
+ line->number
+ );
+ errors++;
+ }
+
+ /*
+ * Check out the type part of this keyword
+ */
+
+ for ( found=FALSE, i=0 ; i<NUMBER_ELEMENTS(Valid_visibilities) ; i++ ) {
+ if ( !strcmp( Valid_visibilities[ i ], Visibility ) ) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if ( !found ) {
+ if ( !(InsertTBDs && !strcmp( Visibility, "TBD" )) ) {
+ fprintf(
+ stderr,
+ "Invalid visibility type (%s) on line %d\n",
+ Visibility,
+ line->number
+ );
+ errors++;
+ }
+ }
+
+ return (errors) ? -1 : 0;
+}
+
+/*
+ * Validate_synchronization
+ */
+
+char *Valid_synchronization[] = {
+ "delay",
+ "event",
+ "mutex",
+ "semaphore",
+ "message",
+ "signal",
+ "period"
+};
+
+boolean Valid_synchronization_text_below[] = {
+ FALSE, /* delay */
+ TRUE, /* event */
+ TRUE, /* mutex */
+ TRUE, /* semaphore */
+ TRUE, /* message */
+ TRUE, /* signal */
+ FALSE /* period */
+};
+
+int Validate_synchronization(
+ Line_Control *line
+)
+{
+ char *s;
+ char *d;
+ char Buffer[ BUFFER_SIZE ];
+ char Synchronization[ BUFFER_SIZE ];
+ int i;
+ boolean found;
+ int errors = 0;
+
+ LineCopyFromRight( line, Buffer );
+
+ memset( Synchronization, '\0', sizeof( Synchronization ) );
+ s = Buffer;
+
+ for ( d=Synchronization ; ; s++, d++ ) {
+ *d = *s;
+ if ( !*s || isspace(*s) )
+ break;
+ }
+ *d = '\0';
+
+ if ( isspace(*s) ) {
+ fprintf(
+ stderr,
+ "Unexpected white space on line %d -- invalid use of multiple words\n",
+ line->number
+ );
+ errors++;
+ }
+
+ /*
+ * Check out the type part of this keyword
+ */
+
+ for ( found=FALSE, i=0 ; i<NUMBER_ELEMENTS(Valid_synchronization) ; i++ ) {
+ if ( !strcmp( Valid_synchronization[ i ], Synchronization ) ) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if ( !found ) {
+ fprintf(
+ stderr,
+ "Invalid synchronization type (%s) on line %d\n",
+ Synchronization,
+ line->number
+ );
+ errors++;
+ }
+
+ if ( line->keyword && !Valid_synchronization_text_below[ i ] ) {
+ fprintf(
+ stderr,
+ "Expected text below synchronization type (%s) on line %d\n",
+ Synchronization,
+ line->number
+ );
+ errors++;
+ }
+
+ return (errors) ? -1 : 0;
+}
+
+/*
+ * Validate_abstract_type
+ *
+ * presence of range or members but not both
+ */
+
+int Validate_abstract_type(
+ Section_info_t *section,
+ Line_Control *start,
+ Line_Control *next_section
+)
+{
+ boolean range_found = FALSE;
+ boolean members_found = FALSE;
+ boolean enumerated_found = FALSE;
+ boolean true_found = FALSE;
+ boolean false_found = FALSE;
+ Line_Control *line;
+ int errors = 0;
+
+ for ( line = start;
+ line != next_section ;
+ line = (Line_Control *) line->Node.next ) {
+ if ( line->keyword == RANGE )
+ range_found = TRUE;
+ else if ( line->keyword == MEMBERS ) {
+ members_found = TRUE;
+ } else if ( line->keyword == TYPE || line->keyword == DERIVATION ) {
+ if ( strstr( line->Contents, "enumerated" ) ||
+ strstr( line->Contents, "structure" ) )
+ enumerated_found = TRUE;
+ }
+ }
+
+ if ( !range_found && !members_found ) {
+ fprintf(
+ stderr,
+ "Neither range nor members keyword present in "
+ "subsection starting at line %d\n",
+ start->number
+ );
+ errors++;
+ }
+
+ if ( !InsertTBDs ) {
+ if ( range_found && members_found ) {
+ fprintf(
+ stderr,
+ "Both range and members keyword present in "
+ "subsection starting at line %d\n",
+ start->number
+ );
+ errors++;
+ }
+ }
+
+ if ( enumerated_found && !members_found ) {
+ fprintf(
+ stderr,
+ "Enumerated type without list of members in "
+ "subsection starting at line %d\n",
+ start->number
+ );
+ errors++;
+ }
+
+ if ( !enumerated_found && !range_found ) {
+ fprintf(
+ stderr,
+ "Type does not have range specified in "
+ "subsection starting at line %d\n",
+ start->number
+ );
+ errors++;
+ }
+
+ return (errors) ? -1 : 0;
+}
+
+/*
+ * Validate_attribute
+ *
+ * presence of range or members but not both
+ */
+
+int Validate_attribute(
+ Section_info_t *section,
+ Line_Control *start,
+ Line_Control *next_section
+)
+{
+ boolean range_found = FALSE;
+ boolean members_found = FALSE;
+ boolean enumerated_found = FALSE;
+ boolean boolean_found = FALSE;
+ boolean true_found = FALSE;
+ boolean false_found = FALSE;
+ Line_Control *line;
+ int errors = 0;
+
+ for ( line = start;
+ line != next_section ;
+ line = (Line_Control *) line->Node.next ) {
+ if ( line->keyword == RANGE )
+ range_found = TRUE;
+ else if ( line->keyword == MEMBERS ) {
+ members_found = TRUE;
+ if ( boolean_found == TRUE ) {
+ line = (Line_Control *) line->Node.next;
+ while ( !_Chain_Is_last( &line->Node ) ) {
+ if ( line->keyword )
+ break;
+ if ( strstr( line->Contents, "FALSE" ) )
+ false_found = TRUE;
+ else if ( strstr( line->Contents, "TRUE" ) )
+ true_found = TRUE;
+ line = (Line_Control *) line->Node.next;
+ }
+ line = (Line_Control *) line->Node.previous;
+ }
+ } else if ( line->keyword == TYPE || line->keyword == DERIVATION ) {
+ if ( strstr( line->Contents, "enumerated" ) )
+ enumerated_found = TRUE;
+ else if ( strstr( line->Contents, "boolean" ) ) {
+ enumerated_found = TRUE;
+ boolean_found = TRUE;
+ }
+ }
+ }
+
+ if ( !range_found && !members_found ) {
+ fprintf(
+ stderr,
+ "Neither range nor members keyword present in "
+ "subsection starting at line %d\n",
+ start->number
+ );
+ errors++;
+ }
+
+ if ( !InsertTBDs ) {
+ if ( range_found && members_found ) {
+ fprintf(
+ stderr,
+ "Both range and members keyword present in "
+ "subsection starting at line %d\n",
+ start->number
+ );
+ errors++;
+ }
+ }
+
+ if ( enumerated_found && !members_found ) {
+ fprintf(
+ stderr,
+ "Enumerated type without list of members in "
+ "subsection starting at line %d\n",
+ start->number
+ );
+ errors++;
+ }
+
+ if ( !enumerated_found && !range_found ) {
+ fprintf(
+ stderr,
+ "Type does not have range specified in "
+ "subsection starting at line %d\n",
+ start->number
+ );
+ errors++;
+ }
+
+ if ( boolean_found && !true_found ) {
+ fprintf(
+ stderr,
+ "Boolean without a TRUE case specified in "
+ "subsection starting at line %d\n",
+ start->number
+ );
+ errors++;
+ }
+
+ if ( boolean_found && !false_found ) {
+ fprintf(
+ stderr,
+ "Boolean without a FALSE case specified in "
+ "subsection starting at line %d\n",
+ start->number
+ );
+ errors++;
+ }
+
+ return (errors) ? -1 : 0;
+}
+
+/*
+ * Validate_object
+ *
+ * presence of range or members but not both
+ */
+
+int Validate_object(
+ Section_info_t *section,
+ Line_Control *start,
+ Line_Control *next_section
+)
+{
+ char ObjectName[ BUFFER_SIZE ];
+ char EndObjectName[ BUFFER_SIZE ];
+ Line_Control *line;
+ int errors = 0;
+
+
+ LineCopyFromRight( start, ObjectName );
+
+ for ( line = start;
+ !_Chain_Is_last( &line->Node ) ;
+ line = (Line_Control *) line->Node.next ) {
+ if ( line->keyword == END_OBJECT ) {
+ LineCopyFromRight( line, EndObjectName );
+ break;
+ }
+ }
+
+ if ( strcmp( ObjectName, EndObjectName ) ) {
+ fprintf(
+ stderr,
+ "Object and End Object names do not match\n"
+ );
+ errors++;
+ }
+
+ return (errors) ? -1 : 0;
+}
+
diff --git a/doc/tools/pdl2texi/t1.d b/doc/tools/pdl2texi/t1.d
new file mode 100644
index 0000000000..4f54e74738
--- /dev/null
+++ b/doc/tools/pdl2texi/t1.d
@@ -0,0 +1,52 @@
+OBJECT: Drive
+ DESCRIPTION:
+ This object provides an interface to the elevation/azimuth
+ drive system(ECA).
+ THEORY OF OPERATION:
+ This object encapsulates the turret drive. The object provides
+ an interface to control the turret drive. A method is provided
+ to set the azimuth and elevation rate of the drive. Methods are
+ provided to request the drive to run in stabilized or power mode
+ and set the drive speed to high or low. A method is also provided
+ to allow for drift adjust.
+
+ This object also tracks drive system on hours. It gets the hours
+ from the EEPROM data, allows the hours to be set, updates the
+ hours via the activation and deactivation of the drive, and
+ provides access to the hours.
+
+ The object also provides methods to access azimuth and elevation
+ displacement, and methods to process changes in the hardware
+ discretes drive on, stabilized mode, thermal fault and fault.
+
+ The object also provides methods to enable and disable
+ both the remote and turret power interlocks which determine if
+ the drive can be driven by the remote or turret handstation
+ respectively.
+
+ATTRIBUTE DESCRIPTIONS:
+
+
+ATTRIBUTE: Azimuth_displacement
+ DESCRIPTION:
+ This attribute represents the current azimuth displacement
+ of the turret.
+ TYPE: float constant
+ RANGE: 0-0
+ UNITS: degrees
+ REQUIREMENTS:
+ AFS 8.2.11 Receive Azimuth Displacement and Elevation Displacement
+ AIS 5.2.6 Azimuth Displacement analog
+
+
+ASSOCIATION DESCRIPTIONS: none
+
+ABSTRACT TYPE DESCRIPTIONS: none
+
+DATA ITEM DESCRIPTIONS: none
+
+METHOD DESCRIPTIONS: none
+
+TASK DESCRIPTIONS: none
+
+END OBJECT: Drive