Keeping track of original line numbers through macro expansion - yacc

I'm working on a assembler for fun, written in C,flex,bison. I'd like to add macros, includes and repeating blocks and was thinking of doing this with a separate preprocessing stage parser.
My question is, how might I keep track of original source line numbers (and filenames)? This is for producing useful error messages, pretty printing, and generating debug information.
yylineno in the second parser after preprocessing is complete will presumably be offset after macro expansion and so on.

you can add
;#file filename.asm
;#line 5
to the preprocessed assembler so
foo:
PUSHREG(A,B,C)
;--10 lines of code
POPREG(A,B,C)
set PC,POP
turns into
foo:
;#file functionmacros.asm
;#line 10
set push,A
set push,B
set push,C
;#file yourfile.asm
;#line 5
;--10 lines of code
;#file functionmacros.asm
;#line 30
set C,pop
set B,POP
set C,POP
;#file yourfile.asm
;#line 16
set PC,POP

Related

In MS Access VBA get Number of Processor Cores

I need to get the number of processor cores available on a computer programmatically from within MS Access. As an example, the computer I work from most frequently has one processor with 6 cores. I want to grab the number '6' through VBA.
Thus far, I have found two ways to find this information through CMD. (1) I can execute the line echo %NUMBER OF PROCESSORS% and the result is 6 (simple and clean, I like it). (2) I have also tried wmic cpu get numberorcores, but the result of that prompt is as follows:
NumberOfCores
6
I intend to pipe the output to and read from the clipboard. The reason I use the clipboard is to avoid creating, reading, and deleting little text files of data. Prompt (2) works, I can successfully pipe the output to the clipboard and read it into a variable in VBA, but it's messy and I would have to parse the result to get the information I need. I would much prefer using prompt (1), but it's not working and the problem seems to be echo. I have tried using shell() and CreateObject(WScript.Shell).Run without success. The strings I have used to try to execute the echo prompt are as follows:
str = "echo %NUMBER OF PROCESSORS% | clip"
str = "cmd ""echo %NUMBER OF PROCESSORS% | clip"""
So, is there a way to successfully send an echo prompt to CMD through VBA and get a result?
Alternatively, is there a different way in VBA to get the number of cores?
TIA!
Why not keep it simple like this:
Dim result As Variant
result = Environ("NUMBER_OF_PROCESSORS")
Debug.Print "Number of processors is " & result

non-advancing WRITE...but not intentionally?

I have a brief snippet of code from a Fortran 95 program that should, in theory, spit out my results into some text files. It would be convenient, for readability if nothing else, for the data to be written in columns (so, one column for variable X, one for Y, etc.). In the first set of WRITE commands below (i.e., those associated with the first OPEN command), the idea is to have a text identifier for the user to read, followed by a numeric value. In the second write command, I just dump out four columns of data, each specific to a given variable.
open(unit=10,file='outs_sum.txt',status='replace')
do i=1,1
write(10,'(a12,f5.4)') 'Min. sigma: ',sigma_low
end do
do i=1,1
write(10,'(a12,f5.4)') 'Max. sigma: ',sigma_high
end do
write(10,'(a11,f5.4)') 'Sigma inc: ',0.005
write(10,*) '# of sigmas: ',ii
write(10,'(a9,f5.1)') 'Min. DL: ',dl_low
write(10,'(a9,f5.1)') 'Max. DL: ',dl_high
write(10,*) 'DL inc: ',1
write(10,*) '# of DLs: ',i
write(10,*) 'Total rows: ',(i*ii)
close(unit=10)
open(unit=10,file='outs.txt',status='replace')
do i=1,dls
do ii=1,sigmas
write(10,*) gtow_out(i,ii),ctsig_out(i,ii),sigout(i,ii),dlout(i,ii)
end do
end do
close(unit=10)
However, what happens on the output side is this: the latter WRITE does exactly what I'd expect and spits out the data in column form...but the former insists on writing everything to the same row. At least when I open things in Notepad. If I use GVIM, it looks as it should.
Why does the first set of WRITE commands write to the same row, and how can I force it to insert a line break after each command instead? Alternatively, is Notepad just showing me something that isn't really there?

while [[ condition ]] stalls on loop exit

I have a problem with ksh in that a while loop is failing to obey the "while" condition. I should add now that this is ksh88 on my client's Solaris box. (That's a separate problem that can't be addressed in this forum. ;) I have seen Lance's question and some similar but none that I have found seem to address this. (Disclaimer: NO I haven't looked at every ksh question in this forum)
Here's a very cut down piece of code that replicates the problem:
1 #!/usr/bin/ksh
2 #
3 go=1
4 set -x
5 tail -0f loop-test.txt | while [[ $go -eq 1 ]]
6 do
7 read lbuff
8 set $lbuff
9 nwords=$#
10 printf "Line has %d words <%s>\n" $nwords "${lbuff}"
11 if [[ "${lbuff}" = "0" ]]
12 then
13 printf "Line consists of %s; time to absquatulate\n" $lbuff
14 go=0 # Violate the WHILE condition to get out of loop
15 fi
16 done
17 printf "\nLooks like I've fallen out of the loop\n"
18 exit 0
The way I test this is:
Run loop-test.sh in background mode
In a different window I run commands like "echo some nonsense >>loop_test.txt" (w/o the quotes, of course)
When I wish to exit, I type "echo 0 >>loop-test.txt"
What happens? It indeed sets go=0 and displays the line:
Line consists of 0; time to absquatulate
but does not exit the loop. To break out I append one more line to the txt file. The loop does NOT process that line and just falls out of the loop, issuing that "fallen out" message before exiting.
What's going on with this? I don't want to use "break" because in the actual script, the loop is monitoring the log of a database engine and the flag is set when it sees messages that the engine is shutting down. The actual script must still process those final lines before exiting.
Open to ideas, anyone?
Thanks much!
-- J.
OK, that flopped pretty quick. After reading a few other posts, I found an answer given by dogbane that sidesteps my entire pipe-to-while scheme. His is the second answer to a question (from 2013) where I see neeraj is using the same scheme I'm using.
What was wrong? The pipe-to-while has always worked for input that will end, like a file or a command with a distinct end to its output. However, from a tail command, there is no distinct EOF. Hence, the while-in-a-subshell doesn't know when to terminate.
Dogbane's solution: Don't use a pipe. Applying his logic to my situation, the basic loop is:
while read line
do
# put loop body here
done < <(tail -0f ${logfile})
No subshell, no problem.
Caveat about that syntax: There must be a space between the two < operators; otherwise it looks like a HEREIS document with bad syntax.
Er, one more catch: The syntax did not work in ksh, not even in the mksh (under cygwin) which emulates ksh93. But it did work in bash. So my boss is gonna have a good laugh at me, 'cause he knows I dislike bash.
So thanks MUCH, dogbane.
-- J
After articulating the problem and sleeping on it, the reason for the described behavior came to me: After setting go=0, the control flow of the loop still depends on another line of data coming in from STDIN via that pipe.
And now that I have realized the cause of the weirdness, I can speculate on an alternative way of reading from the stream. For the moment I am thinking of the following solution:
Open the input file as STDIN (Need to research the exec syntax for that)
When the condition occurs, close STDIN (Again, need to research the syntax for that)
It should then be safe to use the more intuitive:while read lbuffat the top of the loop.
I'll test this out today and post the result. I'd hope someone else benefit from the method (if it works).

Batch IF statement variable inside another variable

I'm having a problem with a framework for a batch game I'm trying to create. I want to check if a variable is something other than a blank space. However, which variable I'm trying to check is in itself defined by two variables. For example:
if not %px%xplayerlocation%y%yplayerlocation%%==%blank% goto wherever
As you can see, the variable to be checked is determined by the values of %xplayerlocation% and %yplayerlocation%. To my knowledge, only the outermost %% signs are being read as being a variable and the inner ones are being read as literal percent signs. Does anyone know a way around this problem? I'll give any additional information if anyone needs it. Thanks.
#ECHO OFF
SETLOCAL
SET "blank= "
SET xplayerlocation=3
SET yplayerlocation=4
ECHO test with blank================
SET px3y4=%blank%
CALL SET varval=%%px%xplayerlocation%y%yplayerlocation%%%
if not "%varval%"=="%blank%" ECHO goto wherever - NOT blank
ECHO test with "Q"================
SET px3y4=Q
CALL SET varval=%%px%xplayerlocation%y%yplayerlocation%%%
if not "%varval%"=="%blank%" ECHO goto wherever - NOT blank
GOTO :EOF
This should get you out of trouble.
You have recognized the source of the problem, but your description of the behavior is incorrect. The parser will attempt to expand variables named px and y, and it will convert the final %% into %.
The Magoo solution will work, but using CALL is quite slow. That may not be a problem for many small scripts, but for a batch game it can kill performance.
You want delayed expansion. Include setlocal enableDelayedExpansion near the beginning of your script. Then use the following:
if not !px%xplayerlocation%y%yplayerlocation%!==%blank% goto wherever
Normal %var% expansion occurs early at parse time, and !var! expansion occurs late at execution time, so you get the proper result.
The above will not work if the value of %blank% is a space. The simplest solution would be to use delayed expansion for !blank! as well.
You might find yourself in a situation where the coordinate values need to be set and expanded within the same block of code, like in a FOR loop or IF statement:
setlocal enableDelayedExpansion
...
REM This does not work
for ... in (...) do (
...
set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
if not !px%xplayerlocation%y%yplayerlocation%!==!blank! REM doSomething
...
)
The above will not work because %var% expansion occurs at parse time, and the entire parenthesized block of code is parsed before any code is executed. So the expanded value is constant - it will expand to the value that existed before the loop started.
The solution is to transfer the coordinate values to FOR variables using delayed expansion:
setlocal enableDelayedExpansion
...
REM This works
for ... in (...) do (
...
set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
for %%X in (!xPlayerLocation!) do for %%Y in (!yPlayerLocation!) do (
if not !px%%X%y%%Y!==%blank% REM doSomething
)
...
)
or
setlocal enableDelayedExpansion
...
REM This also works
for ... in (...) do (
...
set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
for /f "tokens=1,2" %%X in ("!xPlayerLocation! !yPlayerLocation!") do (
if not !px%%X%y%%Y!==%blank% REM doSomething
)
...
)
If you are serious about developing a high quality game using batch, then you may be interested in studying the techniques I used in developing SNAKE.BAT - an arcade style game using only native batch commands. The beginning of the post is a bunch of code, but afterwards I describe a number of techniques I used for improving performance. It is advanced stuff, so don't try to absorb everything at once. Absorb what you can, and then revisit the post later on after you gain more experience.

valgrind give error when printing the second line to file

I'm using valgrind to find faults in my code. The command I use is
valgrind --leak-check=yes ./a.out
and I compile the code with -g code alone. I get many errors pointing to a single write line (The three printed values are initialized and well defined).
write (22,*) avlength, stdlength, avenergy
All with the Conditional jump or move depends on uninitialised value(s) error. The said line is the second line from a bunch of lines printing to a single file. At the end of the errors, I get two more, one pointing to the line opening the file
resStep = int(conf*100/iterate)
if (resStep.lt.10) then
write (resFile, "(A5,I1)") "res00",resStep
elseif (ResStep.lt.100) then
write (resFile, "(A4,I2)") "res0",resStep
else
write (resFile, "(A3,I1)") "res",resStep
endif
open (unit=22,file=trim(resFile),status='replace',
c action='write')
resStep is integer. The error is Syscall param write(buf) points to uninitialised byte(s). Finally, I get an error Address 0x52d83f4 is 212 bytes inside a block of size 8,344 alloc'd when I flush the file (before closing it).
I can't find any logic here. If the problem is with opening the file in a faulty way, wouldn't I get the error at the first line?
I use f95 to compile this and my gcc version is 4.1.2. I can't upgrade any of it.
Wild guess: check the data type of resFile. Is it a string or a unit number?
My Fortran 95 is beyond rusty but try moving the call to open() before the calls to write() and pass an integer resUnit instead of resFile as the first argument to write():
CHARACTER(LEN=20):: resFile
INTEGER(KIND=2) :: resUnit, resStep
resStep = 1
resFile = 'MY-results'
resUnit = 22
open (unit=resUnit, file=trim(resFile), status='replace', action='write')
write(resUnit, "(A5,I1)") "res00", resStep
END