* Injecting trace code under GNAT
@ 2013-07-17 7:33 wrostek
2013-07-17 8:00 ` Georg Bauhaus
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: wrostek @ 2013-07-17 7:33 UTC (permalink / raw)
Hi forum,
I'm starting new to a fairly large GNAT project.
Is the GNAT environment providing help to inject trace code
on entry/exit of each subroutine?
It doesn't matter if it is a one go over the whole codebase
or by pre-processing prior to each compilation.
I need to hook into my own routines to optimize things for
perfomance reasons.
thanks in advance
Wolfagng R.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Injecting trace code under GNAT
2013-07-17 7:33 Injecting trace code under GNAT wrostek
@ 2013-07-17 8:00 ` Georg Bauhaus
2013-07-17 8:40 ` wrostek
2013-07-17 8:15 ` Niklas Holsti
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Georg Bauhaus @ 2013-07-17 8:00 UTC (permalink / raw)
On 17.07.13 09:33, wrostek wrote:
> Hi forum,
>
> I'm starting new to a fairly large GNAT project.
>
> Is the GNAT environment providing help to inject trace code
> on entry/exit of each subroutine?
>
> It doesn't matter if it is a one go over the whole codebase
> or by pre-processing prior to each compilation.
>
> I need to hook into my own routines to optimize things for
> perfomance reasons.
If it is about measuring relative performance of subprograms,
then one good approximation is kcachegrind.
(With compiler switch -fno-inline in particular).
If you can target the JVM using JGNAT, too, then this target
might allow injecting something.
The -fprofile* compiler switches might be interesting.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Injecting trace code under GNAT
2013-07-17 7:33 Injecting trace code under GNAT wrostek
2013-07-17 8:00 ` Georg Bauhaus
@ 2013-07-17 8:15 ` Niklas Holsti
2013-07-17 23:38 ` Randy Brukardt
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Niklas Holsti @ 2013-07-17 8:15 UTC (permalink / raw)
On 13-07-17 10:33 , wrostek wrote:
> Hi forum,
>
> I'm starting new to a fairly large GNAT project.
>
> Is the GNAT environment providing help to inject trace code
> on entry/exit of each subroutine?
>
> It doesn't matter if it is a one go over the whole codebase
> or by pre-processing prior to each compilation.
>
> I need to hook into my own routines to optimize things for
> perfomance reasons.
It seems that GNAT can be used with gprof:
http://gcc.gnu.org/onlinedocs/gcc-4.8.1/gnat_ugn_unw/Profiling-an-Ada-Program-using-gprof.html
For something more advanced, you could try the RapiTime tool,
http://www.rapitasystems.com/products/RapiTime.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Injecting trace code under GNAT
2013-07-17 8:00 ` Georg Bauhaus
@ 2013-07-17 8:40 ` wrostek
0 siblings, 0 replies; 10+ messages in thread
From: wrostek @ 2013-07-17 8:40 UTC (permalink / raw)
Thank you both for your quick feedback
...
> If it is about measuring relative performance of subprograms,
>
> then one good approximation is kcachegrind.
>
> (With compiler switch -fno-inline in particular).
No, it's about understanding the program flow.
I'm very much preferring tracing over debugging.
Means instrumenting code with minor impact on runtime.
Of course this is bulk data and needs specific care.
As an example I trace simple IDs and only integer values
to shared memory and stream it to disk by another process.
All formatting is off-line. This way I can inject a fairly
huge number of traces by low runtime penalties. My personal
taste is to accept up to ~3% runtime increase but have
this trace all time available. This did help me a lot in the
past to speed up turn-around time for error analysis.
But I'm aware that this approach isn't accepted by everybody ;)
>
>
>
> If you can target the JVM using JGNAT, too, then this target
>
> might allow injecting something.
Yes, in my Java days there was this nice API interface
to the JVM to hook methods in.
>
>
>
> The -fprofile* compiler switches might be interesting.
I will elaborate all your proposals.
Wolfgang R.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Injecting trace code under GNAT
2013-07-17 7:33 Injecting trace code under GNAT wrostek
2013-07-17 8:00 ` Georg Bauhaus
2013-07-17 8:15 ` Niklas Holsti
@ 2013-07-17 23:38 ` Randy Brukardt
2013-07-18 6:03 ` J-P. Rosen
2013-07-23 6:59 ` wrostek
4 siblings, 0 replies; 10+ messages in thread
From: Randy Brukardt @ 2013-07-17 23:38 UTC (permalink / raw)
"wrostek" <wolfgang.rostek@gmx.de> wrote in message
news:07cb9baf-902c-4870-bfd1-aa8018e9d5c5@googlegroups.com...
> Hi forum,
>
> I'm starting new to a fairly large GNAT project.
>
> Is the GNAT environment providing help to inject trace code
> on entry/exit of each subroutine?
>
> It doesn't matter if it is a one go over the whole codebase
> or by pre-processing prior to each compilation.
There was a tool for doing such preprocessing that was created during the
very early days of Ada, and it was found in one of the repositories. (I
remember it because we used it as the basis for an in-house tool for
coverage analysis.) You might look in the on-line version of the old ASE
cd-roms (lots of very old software that still might be useful for
something): http://archive.adaic.com/ase/
Randy.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Injecting trace code under GNAT
2013-07-17 7:33 Injecting trace code under GNAT wrostek
` (2 preceding siblings ...)
2013-07-17 23:38 ` Randy Brukardt
@ 2013-07-18 6:03 ` J-P. Rosen
2013-07-23 6:59 ` wrostek
4 siblings, 0 replies; 10+ messages in thread
From: J-P. Rosen @ 2013-07-18 6:03 UTC (permalink / raw)
Le 17/07/2013 09:33, wrostek a écrit :
> Is the GNAT environment providing help to inject trace code
> on entry/exit of each subroutine?
>
You might be interested in package Debug
(http://www.adalog.fr/compo2.htm#Debug). It provides a very
sophisticated tracing facility, but no automatic insertion of trace calls.
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Injecting trace code under GNAT
2013-07-17 7:33 Injecting trace code under GNAT wrostek
` (3 preceding siblings ...)
2013-07-18 6:03 ` J-P. Rosen
@ 2013-07-23 6:59 ` wrostek
2013-07-23 13:43 ` Marc C
4 siblings, 1 reply; 10+ messages in thread
From: wrostek @ 2013-07-23 6:59 UTC (permalink / raw)
Sorry all. I thought I was under email notification and didn't
see the latest comments. Thanks for these links.
Thinking about the features I need it should have been quite
simple to write a quick and dirty parsing by hand.
This would give me more flexibility in instrumenting the
code in different sections. Mixing between generated and
hand written trace statements could be easier this way
as well.
I decided to go with python and learn a bit more this
language along the script.
It took me 2 days and works quite well for me. Here my
experiences.
Looking at the subroutine structure I thought it must
be quite easy to extract begin, end and return tokens.
Almost through the implementation I encountered a wrong
assumption of mine that the subroutine designatore must
be repeated in the end-clause. A shame that this is
optional (had in mind that this is one of the nice
things Ada forces to have readable printouts) ;) But
fortunately only 5 places had to be fixed to have
it all over the place now.
Half a day it took me to enhance parsing for more
sophisticated structures. (it covers only things
seen in my code base)
In the end there were 3 locations remaining where the
effort isn't justified to enhance the parsing further.
One is a task body and two places where keywords are
part of a variable/attribute. Here I use an IGNORE_ON/
IGNORE_OFF comment to skip them. I'll need the ignore
anyway in the future.
The script comes to some 800 lines. It is filtering
200 package bodies and 300 kloc. For now it is injecting
a null statement but passes the compiler.
Wolfgang R.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Injecting trace code under GNAT
2013-07-23 6:59 ` wrostek
@ 2013-07-23 13:43 ` Marc C
2013-07-23 15:44 ` wrostek
0 siblings, 1 reply; 10+ messages in thread
From: Marc C @ 2013-07-23 13:43 UTC (permalink / raw)
On Tuesday, July 23, 2013 1:59:57 AM UTC-5, wrostek wrote:
> The script comes to some 800 lines. It is filtering
> 200 package bodies and 300 kloc. For now it is injecting
> a null statement but passes the compiler.
I think a lot of people would be interested in the functionality of this script. Kindly post it when you get a chance, even if it's just a quick & dirty version.
Thanks!
Marc
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Injecting trace code under GNAT
2013-07-23 13:43 ` Marc C
@ 2013-07-23 15:44 ` wrostek
2013-07-24 9:10 ` wrostek
0 siblings, 1 reply; 10+ messages in thread
From: wrostek @ 2013-07-23 15:44 UTC (permalink / raw)
Hi Marc
yes I can do so. But it needs a least a bit of adapting correct names and
comments. Otherwise I will get blamed all over the place. That doesn't mean
it will become nice;)
I'm no longer in the office but I can cleanup and attach it tomorrow.
Wolfgang R.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Injecting trace code under GNAT
2013-07-23 15:44 ` wrostek
@ 2013-07-24 9:10 ` wrostek
0 siblings, 0 replies; 10+ messages in thread
From: wrostek @ 2013-07-24 9:10 UTC (permalink / raw)
Here we are. I hope it will survive formatting issues.
Wolfgang R.
-------------------------------------------------------
#!/usr/bin/python
#######################################################################
# This script is a very simple approach parsing and
# adding trace statements to each entry/exit of a subroutine.
#
# Some more background is discussed here
# https://groups.google.com/forum/#!topic/comp.lang.ada/vSNunYeX6GY
#
# It is by no way intended to be a complete useful parser rather than
# a good bad example for students not coding this way. I will admit.
# My only excuse is that it fits +my+ needs, my time budget and my
# limited knowledge of python.
#
# The script is relying on the subroutine denominator repeated in the
# end-clause. Don't read any further if this isn't given in your codebase.
#
# It will modify the source code files in the working directory given
# by the mandatory single parameter! Be careful to not check them in
# and use this tmp directory for creating patched executables only.
#
# The script will not change line numbers but modify within the same
# line. If the injected trace statement reports its line number this
# will be identical to the unmodified file.
#
# I assume to run on Unix and having access to /tmp.
#
# The script will probably fail the first time and tweaking for your
# needs is needed. But do not try to go beyond the complexity this
# simple script is able to handle. As an example only one nested
# subroutine level is supported.
#
# Here my iterations to fix problems in the script
#
# ./inject_ada /my/path/to/tmp/dir > ~/x
#
# tail -3 ~/x
# ...
# ERROR: not cleared by end of file package: ... // not ok
#
# // look how far we got
# egrep -Hn "processing file" /tmp/x_ada
#
# // open the failed file (/tmp/x_ada) and the log (~/x)
#
# // From my experience it is better to check the failed file top down.
# // If the parser assumes to open a level 2 subroutine (look for first 'level2')
# // then the subroutine (or lines) before this point are a good candidate
# // having trouble.
# // The extensive trace of the script has given me a good turnaround time
# // tracking down the problem.
#######################################################################
from sys import exit
import sys
import string
import os, glob
import shutil
def trace() :
return True
def exttrace() :
return True and trace()
####################################################################
## we handle parsing a subroutine by a large number of globals
## (this might be better moved to classes later)
##
## top frame stack storage area
_subroutineIdentifierFound = False
_subroutineNameFound = False
_subroutineIsFound = False
_subroutineBeginFound = False
_subroutineEndFound = False
_subroutineEndSemicolonFound = False
_subroutineIsFunction = False # procedure or function
_subroutineName = ''
_paramBracketCount = 0
tmp_filename = '/tmp/_x_ada'
tmp_file = open(tmp_filename, 'w')
currentLineOrig = ''
currentLineOut = ''
outputModifiedLine = False
currentLineWoComment = '' # lower case
currentColumnIndex = 0
# status (must all be reset)
subroutineIdentifierFound = False
subroutineNameFound = False
subroutineIsFound = False
subroutineBeginFound = False
subroutineEndFound = False
subroutineEndSemicolonFound = False
subroutineIsFunction = False # procedure or function
paramBracketCount = 0
# we are on the second level?
is_sub_frame = False
# we are inside an IGNORE_ section
ignore_active = False
# for use by inject_xxx()
packageName = ''
subroutineName = ''
curr_line_num = 0
# statistics
inject_count = 1
##
## end globals
####################################################################
def clear_status() :
global subroutineIdentifierFound
global subroutineNameFound
global subroutineIsFound
global subroutineBeginFound
global subroutineEndFound
global subroutineEndSemicolonFound
global paramBracketCount
if exttrace() : print 'clear_status()'
subroutineIdentifierFound = False
subroutineNameFound = False
subroutineIsFound = False
subroutineBeginFound = False
subroutineEndFound = False
subroutineEndSemicolonFound = False
paramBracketCount = 0
return
def push_frame() :
global _subroutineIdentifierFound
global _subroutineNameFound
global _subroutineIsFound
global _subroutineBeginFound
global _subroutineEndFound
global _subroutineEndSemicolonFound
global _subroutineIsFunction # procedure or function
global _subroutineName
global _paramBracketCount
global subroutineIdentifierFound
global subroutineNameFound
global subroutineIsFound
global subroutineBeginFound
global subroutineEndFound
global subroutineEndSemicolonFound
global subroutineIsFunction # procedure or function
global subroutineName
global paramBracketCount
if exttrace() : print 'push_frame()'
_subroutineIdentifierFound = subroutineIdentifierFound
_subroutineNameFound = subroutineNameFound
_subroutineIsFound = subroutineIsFound
_subroutineBeginFound = subroutineBeginFound
_subroutineEndFound = subroutineEndFound
_subroutineEndSemicolonFound = subroutineEndSemicolonFound
_subroutineIsFunction = subroutineIsFunction # procedure or function
_subroutineName = subroutineName
_paramBracketCount = paramBracketCount
subroutineIdentifierFound = False
subroutineNameFound = False
subroutineIsFound = False
subroutineBeginFound = False
subroutineEndFound = False
subroutineEndSemicolonFound = False
subroutineName = ''
paramBracketCount = 0
return
def pop_frame() :
global _subroutineIdentifierFound
global _subroutineNameFound
global _subroutineIsFound
global _subroutineBeginFound
global _subroutineEndFound
global _subroutineEndSemicolonFound
global _subroutineIsFunction # procedure or function
global _subroutineName
global _paramBracketCount
global subroutineIdentifierFound
global subroutineNameFound
global subroutineIsFound
global subroutineBeginFound
global subroutineEndFound
global subroutineEndSemicolonFound
global subroutineIsFunction # procedure or function
global subroutineName
global paramBracketCount
if exttrace() : print 'pop_frame()'
subroutineIdentifierFound = _subroutineIdentifierFound
subroutineNameFound = _subroutineNameFound
subroutineIsFound = _subroutineIsFound
subroutineBeginFound = _subroutineBeginFound
subroutineEndFound = _subroutineEndFound
subroutineEndSemicolonFound = _subroutineEndSemicolonFound
subroutineIsFunction = _subroutineIsFunction # procedure or function
subroutineName = _subroutineName
paramBracketCount = _paramBracketCount
return
# are we inside a parameter block?
def isInsideParam() :
global paramBracketCount
return paramBracketCount > 0
# ignore sections between IGNORE_ON/IGNORE_OFF
def check_ignore() :
global currentLineOrig
global ignore_active
index = currentLineOrig.find('IGNORE_ON')
if index >= 0 :
if ignore_active :
print 'FATAL: ignore is activate already while active request'
exit(1)
if exttrace() : print 'ignore activated'
ignore_active = True
index = currentLineOrig.find('IGNORE_OFF')
if index >= 0 :
if not ignore_active :
print 'FATAL: ignore is not active while deactivate request'
exit(1)
if exttrace() : print 'ignore deactivated'
ignore_active = False
return
def check_for_new() :
global currentLineWoComment
global currentColumnIndex
global is_sub_frame
if exttrace() : print 'check_for_new()'
# special case for package
packageIndex = currentLineWoComment[currentColumnIndex:].find('package ')
if packageIndex >= 0 :
return
# special case for vars
newIndex = currentLineWoComment[currentColumnIndex:].find('new_')
if newIndex >= 0 :
return
newIndex = currentLineWoComment[currentColumnIndex:].find('new')
if newIndex >= 0 :
if exttrace() : print 'new found'
clear_status()
if is_sub_frame :
pop_frame()
is_sub_frame = False
return
def check_for_separate() :
global currentLineWoComment
global currentColumnIndex
global is_sub_frame
if exttrace() : print 'check_for_separate()'
separateIndex = currentLineWoComment[currentColumnIndex:].find('separate')
if separateIndex >= 0 :
if exttrace() : print 'separate found'
clear_status()
if is_sub_frame :
pop_frame()
is_sub_frame = False
return
def check_for_semicolon() :
global currentLineWoComment
global currentColumnIndex
global subroutineEndSemicolonFound
if exttrace() : print 'check_for_semicolon()'
semicolonIndex = currentLineWoComment[currentColumnIndex:].find(';')
if semicolonIndex >= 0 :
if exttrace() : print 'semicolon found'
subroutineEndSemicolonFound = True
return
def handle_semicolon() :
global subroutineEndSemicolonFound
global subroutineIdentifierFound
global subroutineIsFound
global is_sub_frame
if exttrace() : print 'handle_semicolon()'
if not subroutineIdentifierFound :
return
if isInsideParam() :
return
if subroutineIsFound :
return
check_for_semicolon()
if subroutineIdentifierFound and not subroutineIsFound and subroutineEndSemicolonFound :
if exttrace() : print 'clear by semicolon found()'
clear_status()
if is_sub_frame :
pop_frame()
is_sub_frame = False
return
# do we have a local subroutine?
def handle_second_level_entry() :
global currentLineWoComment
global currentColumnIndex
global is_sub_frame
global subroutineIdentifierFound
subroutineIdentifierP = 'procedure'
subroutineIdentifierF = 'function'
if exttrace() : print 'handle_second_level...'
if currentColumnIndex >= len(currentLineWoComment) :
if exttrace() : print '...handle_second_level -1-'
return
if exttrace() : print 'currentColumnIndex: ' + str(currentColumnIndex)
# we assume a blank after subroutine token
myIndex = currentLineWoComment[currentColumnIndex:].find(subroutineIdentifierP + ' ')
if myIndex >= 0 :
if trace() : print 'token found: procedure -level2-'
push_frame()
subroutineIsFunction = False
currentColumnIndex = myIndex
currentColumnIndex += len(subroutineIdentifierP)
else :
myIndex = currentLineWoComment[currentColumnIndex:].find(subroutineIdentifierF + ' ')
if myIndex >= 0 :
if trace() : print 'token found: function -level2-'
push_frame()
subroutineIsFunction = True
currentColumnIndex = myIndex
currentColumnIndex += len(subroutineIdentifierF)
if exttrace() : print 'myindex: ' + str(myIndex)
if exttrace() : print 'currentColumnIndex: ' + str(currentColumnIndex)
if myIndex >= 0 :
if exttrace() : print 'is_sub_frame = True'
is_sub_frame = True
subroutineIdentifierFound = True
find_identifier()
if exttrace() : print '...handle_second_level -e-'
return
# remove and ignore parameter block
def strip_parameters() :
global currentLineWoComment
global paramBracketCount
currIndex = 0
# forward
while currIndex < len(currentLineWoComment) :
if isInsideParam() :
if currentLineWoComment[currIndex] == ')' :
currentLineWoComment = currentLineWoComment[0:currIndex] + " " + currentLineWoComment[currIndex+1:]
paramBracketCount -= 1
else :
if currentLineWoComment[currIndex] == '(' :
paramBracketCount += 1
if isInsideParam() :
currentLineWoComment = currentLineWoComment[0:currIndex] + " " + currentLineWoComment[currIndex+1:]
currIndex += 1
# backward
currIndex = len(currentLineWoComment) - 1
while currIndex >= 0 :
if isInsideParam():
if currentLineWoComment[currIndex] == '(' :
currentLineWoComment = currentLineWoComment[0:currIndex] + " " + currentLineWoComment[currIndex+1:]
paramBracketCount -= 1
else :
if currentLineWoComment[currIndex] == ')' :
paramBracketCount += 1
if isInsideParam() :
currentLineWoComment = currentLineWoComment[0:currIndex] + " " + currentLineWoComment[currIndex+1:]
currIndex -= 1
if exttrace() : print '...strip_parameters >' + currentLineWoComment + '<'
return
# we assume it is allowed injecting at the beginning of first line
def inject_with() :
global outputModifiedLine
global currentLineOrig
global currentLineOut
# remove this to do something useful
if True :
return
if exttrace() : print 'inject_with'
outputModifiedLine = True
currentLineOut = 'with text_io; use text_io; ' + currentLineOrig
return
def inject_begin() :
global outputModifiedLine
global currentLineWoComment
global currentLineOut
global inject_count
outputModifiedLine = True
inject_count += 1
currentLineOut = currentLineWoComment + ' null; '
if exttrace() : print 'inject_begin >' + currentLineOut + '<'
return
def inject_end() :
global outputModifiedLine
global currentLineWoComment
global currentLineOut
global inject_count
outputModifiedLine = True
inject_count += 1
currentLineOut = 'null; ' + currentLineWoComment
if exttrace() : print 'inject_end >' + currentLineOut + '<'
return
def find_end() :
global subroutineEndFound
global currentLineWoComment
global currentColumnIndex
global subroutineName
global is_sub_frame
subroutineEnd = 'end'
subroutineReturn = 'return'
if exttrace() : print 'find_end...'
if currentColumnIndex >= len(currentLineWoComment) :
if exttrace() : print '...find_end -1-'
return
if exttrace() : print 'currentColumnIndex: ' + str(currentColumnIndex)
if subroutineEndFound :
print 'ERROR: must not come to this line'
return
# we are inside a subroutine body and may have optional returns
returnIndex = currentLineWoComment[currentColumnIndex:].find(subroutineReturn + ' ')
if returnIndex < 0 :
returnIndex = currentLineWoComment[currentColumnIndex:].find(subroutineReturn + ';')
if returnIndex < 0 :
returnIndex = currentLineWoComment[currentColumnIndex:].find(subroutineReturn + '(')
if returnIndex > 0 :
returnIndex = currentLineWoComment[currentColumnIndex:].find(' ' + subroutineReturn)
if returnIndex >= 0 :
returnIndex += 1
if returnIndex >= 0 :
if trace() : print 'token found: return'
currentColumnIndex = returnIndex
currentColumnIndex += len(subroutineReturn)
inject_end()
find_end() # we may have something still on the line
if exttrace() : print '...find_end -2-'
return
nameIndex = currentLineWoComment[currentColumnIndex:].find(' ' + subroutineName)
if nameIndex < 0 :
if exttrace() : print '...find_end -3-'
return
endIndex = currentLineWoComment[currentColumnIndex:].find(subroutineEnd + ' ')
if endIndex >= 0 :
testIndex = endIndex + len(subroutineEnd)
while testIndex < nameIndex :
if currentLineWoComment[testIndex] != ' ' :
if exttrace() : print 'not blank between end and name'
if exttrace() : print '...find_end -4-'
return
testIndex += 1
if trace() : print 'token found: end'
subroutineEndFound = True
currentColumnIndex = endIndex
currentColumnIndex += len(subroutineEnd)
inject_end()
clear_status()
if is_sub_frame :
pop_frame()
is_sub_frame = False
if exttrace() : print '...find_end -e-'
return
def find_begin() :
global subroutineBeginFound
global currentLineWoComment
global currentColumnIndex
subroutineBegin = 'begin'
if exttrace() : print 'find_begin...'
if currentColumnIndex >= len(currentLineWoComment) :
if exttrace() : print '...find_begin -1-'
return
if exttrace() : print 'currentColumnIndex: ' + str(currentColumnIndex)
if subroutineBeginFound :
find_end()
if exttrace() : print '...find_begin -2-'
return
beginIndex = currentLineWoComment[currentColumnIndex:].find(subroutineBegin)
if beginIndex >= 0 :
if beginIndex + len(subroutineBegin) < len(currentLineWoComment) :
beginIndex2 = currentLineWoComment[currentColumnIndex:].find(subroutineBegin + ' ')
if beginIndex2 < 0 :
if exttrace() : print '...find_begin -3-'
return
if trace() : print 'token found: begin'
subroutineBeginFound = True
currentColumnIndex = beginIndex
currentColumnIndex += len(subroutineBegin)
inject_begin()
find_end()
if exttrace() : print '...find_begin -e-'
return
def find_is() :
global subroutineIsFound
global currentLineWoComment
global currentColumnIndex
subroutineIs = 'is'
if exttrace() : print 'find_is...'
if currentColumnIndex >= len(currentLineWoComment) :
if exttrace() : print '...find_is -1-'
return
if exttrace() : print 'currentColumnIndex: ' + str(currentColumnIndex)
if not subroutineIsFound :
strip_parameters()
if isInsideParam() :
return
if subroutineIsFound :
check_for_new()
check_for_separate()
if subroutineIsFound :
find_begin()
if exttrace() : print '...find_is -2-'
return
isIndex = currentLineWoComment[currentColumnIndex:].find(subroutineIs)
if isIndex > 0 :
isIndex2 = currentLineWoComment[currentColumnIndex:].find(' is')
if isIndex2 < 0 :
if exttrace() : print '...find_is -3-'
return
if isIndex >= 0 :
if trace() : print 'token found: is'
subroutineIsFound = True
currentColumnIndex = isIndex
currentColumnIndex += len(subroutineIs)
check_for_new()
check_for_separate()
if subroutineIsFound :
find_begin()
if exttrace() : print '...find_is -e-'
return
def find_name() :
global subroutineNameFound
global currentLineWoComment
global subroutineName
global currentColumnIndex
if exttrace() : print 'find_name...'
if currentColumnIndex >= len(currentLineWoComment) :
if exttrace() : print '...find_name -1-'
return
if exttrace() : print 'currentColumnIndex: ' + str(currentColumnIndex)
if subroutineNameFound :
find_is()
if exttrace() : print '...find_name -2-'
return
myIndex1 = -1
while currentColumnIndex < len(currentLineWoComment) :
if ' ' == currentLineWoComment[currentColumnIndex] :
currentColumnIndex += 1
continue
else :
myIndex1 = currentColumnIndex
break
if myIndex1 < 0 :
if exttrace() : print '...find_name -3-'
return
myIndex2 = len(currentLineWoComment)
while currentColumnIndex < len(currentLineWoComment) :
if ' ' != currentLineWoComment[currentColumnIndex] \
and '(' != currentLineWoComment[currentColumnIndex] \
and chr(31) < currentLineWoComment[currentColumnIndex]:
currentColumnIndex += 1
continue
else :
myIndex2 = currentColumnIndex
break
subroutineName = currentLineWoComment[myIndex1:myIndex2]
subroutineNameFound = True
if trace() : print 'subroutine name >' + subroutineName + '<'
find_is()
if exttrace() : print '...find_name -e-'
return
# lookup the subroutine identifier
def find_identifier() :
global subroutineIdentifierFound
global currentLineWoComment
global subroutineIsFunction
global currentColumnIndex
subroutineIdentifierP = 'procedure'
subroutineIdentifierF = 'function'
if exttrace() : print 'find_identifier...'
if currentColumnIndex >= len(currentLineWoComment) :
if exttrace() : print '...line end'
return
if exttrace() : print 'currentColumnIndex: ' + str(currentColumnIndex)
if subroutineIdentifierFound :
handle_second_level_entry()
if subroutineIdentifierFound :
find_name()
if exttrace() : print '...find_identifier -1-'
return
# we assume one blank after the identifier (and no immmediate line break)
myIndex = currentLineWoComment[currentColumnIndex:].find(subroutineIdentifierP + ' ')
if myIndex >= 0 :
if trace() : print 'token found: procedure'
subroutineIsFunction = False
currentColumnIndex = myIndex
currentColumnIndex += len(subroutineIdentifierP)
else :
myIndex = currentLineWoComment[currentColumnIndex:].find(subroutineIdentifierF + ' ')
if myIndex >= 0 :
if trace() : print 'token found: function'
subroutineIsFunction = True
currentColumnIndex = myIndex
currentColumnIndex += len(subroutineIdentifierF)
if exttrace() : print 'myindex: ' + str(myIndex)
if exttrace() : print 'currentColumnIndex: ' + str(currentColumnIndex)
if myIndex >= 0 :
subroutineIdentifierFound = True
find_name()
if exttrace() : print '...find_identifier -e-'
return
def process_file(src_name):
global tmp_file
global currentLineWoComment
global currentLineOrig
global currentLineOut
global currentColumnIndex
global curr_line_num
global outputModifiedLine
global packageName
global subroutineIdentifierFound
global is_sub_frame
global ignore_active
global subroutineEndSemicolonFound
if exttrace() : print 'process_file...'
# reset
curr_line_num = 0
is_sub_frame = False
ignore_active = False
myfile = open(src_name)
# extract package name
index_underscore = src_name.rfind('.');
index_slash = src_name.rfind('/');
packageName = src_name[index_slash+1:index_underscore]
if trace() : print 'packageName >' + packageName + '<'
# process all lines
while 1:
line = myfile.readline()
if len(line) == 0 :
break
curr_line_num += 1
# without \n
currentLineOrig = line[:-1]
# reset
outputModifiedLine = False
if curr_line_num == 1 :
inject_with()
check_ignore()
if ignore_active :
if exttrace() : print '[' + str(curr_line_num) + ']' + ' ignore_active '
tmp_file.write(line)
continue
## handle comment part
hyphen_index = currentLineOrig.find('--')
# strip comment and lower case the string to work on
if hyphen_index >= 0 :
currentLineWoComment = currentLineOrig[:hyphen_index].lower()
else :
currentLineWoComment = currentLineOrig.lower()
if exttrace() : print '[' + str(curr_line_num) + ']' + ' >' + currentLineWoComment + '<'
currentColumnIndex = 0
subroutineEndSemicolonFound = False
find_identifier()
handle_semicolon()
if outputModifiedLine :
if trace() : print 'modified line >' + currentLineOut + '<'
tmp_file.write(currentLineOut)
else :
tmp_file.write(currentLineOrig)
tmp_file.write('\n')
# while 1
myfile.close()
if subroutineIdentifierFound :
if exttrace() : print 'ERROR: not cleared by end of file package: ' + packageName
exit(1)
if exttrace() : print '...process_file'
return
# iterate all Ada package bodies
def process_files(working_path):
global tmp_file
global tmp_filename
processed_files_count = 0
if exttrace() : print 'process_files...'
for currentFile in glob.glob( os.path.join(working_path, '*') ):
if os.path.isdir(currentFile):
if exttrace() : print 'got a directory: ' + currentFile
process_files(currentFile)
for currentFile in glob.glob( os.path.join(working_path, '*.ada') ):
# drop specs
if currentFile.find('_.ada') >= 0 :
continue
if trace() : print "processing file: " + currentFile
tmp_file = open(tmp_filename, 'w')
process_file(currentFile)
tmp_file.close()
shutil.copyfile(tmp_filename, currentFile)
processed_files_count += 1
if trace() : print '...process_files processed_files_count: ' + str(processed_files_count)
return
#######################################################################
## init
#######################################################################
use = "\nUsage : ./inject_ada <working_dir>\n" + \
"Filter Ada subroutines and inject trace code.\n" + \
"Refer to the script header info for details.\n" + \
"<working_dir> The directory root to do the conversion.\n" + \
" NOTE: The content of this directory gets modified!\n\n"
if len(sys.argv) != 2 :
print use
exit(0)
working_path = sys.argv[1]
if trace() : print 'working_path: ' + working_path
#######################################################################
## main
#######################################################################
process_files(working_path)
exit(0)
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-07-24 9:10 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-17 7:33 Injecting trace code under GNAT wrostek
2013-07-17 8:00 ` Georg Bauhaus
2013-07-17 8:40 ` wrostek
2013-07-17 8:15 ` Niklas Holsti
2013-07-17 23:38 ` Randy Brukardt
2013-07-18 6:03 ` J-P. Rosen
2013-07-23 6:59 ` wrostek
2013-07-23 13:43 ` Marc C
2013-07-23 15:44 ` wrostek
2013-07-24 9:10 ` wrostek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox