File: callstack.F

package info (click to toggle)
aces3 3.0.6-7
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 82,460 kB
  • sloc: fortran: 225,647; ansic: 20,413; cpp: 4,349; makefile: 953; sh: 137
file content (175 lines) | stat: -rw-r--r-- 5,573 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

c The call stack is a list of routine names. Every time you call a routine,
c the name of that routine should be pushed onto the stack. When you exit,
c you should remove the name from the stack.

c This is useful for tracking down where errors occur, but it requires
c discipline since stack management is not automatic.

c The "stack" has two components: the array of strings ("invisible" to
c the rest of the code) and callstack_curr (from include/callstack.com).
c The reason is that in many routines, the overhead from calling push/pop
c would have a major impact on performance. Other times, it is completely
c negligible. You should try to use push/pop whenever possible and revert
c to setting callstack_curr manually when performance is critical. Using
c callstack_curr too deeply defeats the purpose of a stack, but it can
c be used as a tracer.

c Prototypes:
c    subroutine callstack_init(szRoutine)
c    subroutine callstack_push(szRoutine)
c    subroutine callstack_print
c    subroutine callstack_pop
c    subroutine callstack_term

#define _CALLSTACK_LEN 32 /* max length of routine name */
#define _CALLSTACK_NUM 100 /* max depth of stack */
c#define _CALLSTACK_TRACE /* for verbose program tracing */

#ifdef _FAIL_TO_COMPILE_
c Copy this block to each routine:
#undef _CALLSTACK_COM_
#include "callstack.com" /* for callstack_curr */
      external callstack_bd
      character*(_CALLSTACK_LEN) callstack(_CALLSTACK_NUM)
      integer csn
      common /callstack_com/ callstack, csn
      save   /callstack_com/
#endif /* _FAIL_TO_COMPILE_ */

c ----------------------------------------------------------------------

      blockdata callstack_bd
      implicit none
      character*(_CALLSTACK_LEN) callstack(_CALLSTACK_NUM)
      integer csn
      common /callstack_com/ callstack, csn
      save   /callstack_com/
      data callstack /_CALLSTACK_NUM*' '/
      data csn /0/
      end

c ----------------------------------------------------------------------

      subroutine callstack_init(szRoutine)
      implicit none
#undef _CALLSTACK_COM_
#include "callstack.com" /* for callstack_curr */
      external callstack_bd
      character*(_CALLSTACK_LEN) callstack(_CALLSTACK_NUM)
      integer csn
      common /callstack_com/ callstack, csn
      save   /callstack_com/
      character*(*) szRoutine
      integer i
      callstack_curr = szRoutine
      callstack(1)   = szRoutine
      do i = 2, _CALLSTACK_NUM
         callstack(i) = ' '
      end do
      csn = 1
#ifdef _CALLSTACK_TRACE
      write(*,*) '@CALLSTACK_INIT: initialized callstack for ',szRoutine
#endif
      return
      end

c ----------------------------------------------------------------------

      subroutine callstack_push(szRoutine)
      implicit none
#undef _CALLSTACK_COM_
#include "callstack.com" /* for callstack_curr */
      external callstack_bd
      character*(_CALLSTACK_LEN) callstack(_CALLSTACK_NUM)
      integer csn
      common /callstack_com/ callstack, csn
      save   /callstack_com/
      character*(*) szRoutine
#ifdef _CALLSTACK_TRACE
      write(*,*) '@CALLSTACK_PUSH: callstack(',csn+1,') = ',szRoutine
#endif
      callstack_curr = szRoutine
      csn = csn+1
      if (csn.le._CALLSTACK_NUM) then
         callstack(csn) = szRoutine
      else
         write(*,*) '@CALLSTACK_PUSH: stack length exceeded by ',
     &              szRoutine
      end if
      return
      end

c ----------------------------------------------------------------------

      subroutine callstack_print
      implicit none
#undef _CALLSTACK_COM_
#include "callstack.com" /* for callstack_curr */
      external callstack_bd
      character*(_CALLSTACK_LEN) callstack(_CALLSTACK_NUM)
      integer csn
      common /callstack_com/ callstack, csn
      save   /callstack_com/
      integer i, j
      write(*,*) '@CALLSTACK: ',callstack_curr
      j = csn
      if (callstack(csn).eq.callstack_curr) j = csn-1
      do i = j, 1, -1
         write(*,*) ' called by: ',callstack(i)
      end do
      return
      end

c ----------------------------------------------------------------------

      subroutine callstack_pop
      implicit none
#undef _CALLSTACK_COM_
#include "callstack.com" /* for callstack_curr */
      external callstack_bd
      character*(_CALLSTACK_LEN) callstack(_CALLSTACK_NUM)
      integer csn
      common /callstack_com/ callstack, csn
      save   /callstack_com/
      if (csn.le.0) then
         write(*,*) '@CALLSTACK_POP: callstack is empty.'
         call c_exit(1)
      end if
#ifdef _CALLSTACK_TRACE
      if (csn.le._CALLSTACK_NUM) then
         write(*,*) '@CALLSTACK_POP: popped ',callstack(csn)
      else
         write(*,*) '@CALLSTACK_POP: popping overflow level ',csn
      end if
#endif
      csn = csn-1
      callstack_curr = 'UNKNOWN'
      if (csn.le._CALLSTACK_NUM) callstack_curr = callstack(csn)
      return
      end

c ----------------------------------------------------------------------

      subroutine callstack_term
      implicit none
#undef _CALLSTACK_COM_
#include "callstack.com" /* for callstack_curr */
      external callstack_bd
      character*(_CALLSTACK_LEN) callstack(_CALLSTACK_NUM)
      integer csn
      common /callstack_com/ callstack, csn
      save   /callstack_com/
      if (csn.gt.1) then
         write(*,*) '@CALLSTACK_TERM: callstack is not empty.'
         call callstack_print
         call c_exit(1)
      end if
#ifdef _CALLSTACK_TRACE
      write(*,*) '@CALLSTACK_TERM: done with ',callstack(1)
#endif
      callstack(1) = ' '
      csn = 0
      return
      end