I'm trying to work with some Visual FoxPro 9.0 code written years ago by programmers now long gone. There are several uses of ALLTRIM() that include a double-asterisk in front of the field name being passed, such as:
fred = ALLTRIM( **barney )
where Barney is a character field in a table. When I try running that line in a VFP session, it errors out with "Function is missing )". But I'm uncomfortable supporting code that I don't understand - what does the "**" do?
I've tried storing the field to a memvar, in case there's a SCATTER in the code that calls this, with no change in the resulting error. I've tried storing other data types (numeric and boolean) to the memvar, still no change. I've been programming in dBase, then FoxBase, then FoxPro, then VFP, for almost 35 years - and I don't remember ever coming across this before. And yet, the program runs without errors, I just don't understand what it is doing.
In case any of this matters, the code in question is stored in a memo field in a table, then invoked with an EXECSCRIPT() call. And some of the tables that the code is working with (but not the one containing the code) are SQL Server tables, accessed through cursor adapters - so "barney" in my example is very likely a field in a cursor adapter, not a .DBF.
I found my answer. Searching for asterisks in source code was useless, of course, because of comments. But I finally thought, after posting this question, of searching for the string with surrounding quotes, and found that, before the code I was looking at was called with EXECSCRIPT(), it was also run through STRTRAN(), which substituted "m." or "." or some other appropriate prefix for the "**" in the code.
So, the double asterisk was internal to the application, and meant nothing to VFP itself.
Related
Question
Is there any way to write a custom function that uses the same pattern as the Open function? Including the fluff keywords like For and As?
Background
I am working on migrating an old VB6 project to use online data via an API, as a first step I'd like to replace all instances of
Open SomeFilename For Binary Access Read As #39
With a custom OpenOnline function
OpenOnline SomeFilename For Binary Access Read As #39
But I do not know how to indicate those keywords are necessary when creating a function, or even if it's possible to do so.
Function openOnline(FileName As String) [For] (Optional Access As AccessType = Binary Access) [As] (Optional FileNumber As Integer) As Boolean
' Do the work of connecting to the online data equivalent of FileName with that access type
End Function
Qualifiers
I understand that these keywords are nonsensical in the context of an OpenOnline function. I also understand that I can use regular expressions to find and replace the syntax to remove keywords like "For" and "Read".
There are hundreds of thousands of instances of this Open function, the Put and Get functions and a few other file related functions, I realize that long term the correct solution is changing the mechanisms fundamentally to use online paradigms, and that work is in progress- on schedule to be completed with about 4 months of effort at the rate things are going.
Bonus Question
Secondarily, is there any way for me to pass a "User Defined Type" variable to the new Put/Get replacements in a way that I can access their fields directly without knowing the type beforehand? (I understand that variants are only available for .cls classes or public user defined types in dlls, neither of which apply in this situation)
As for 1), you can get close but you can't exactly replicate the VB Open statement. Which means you won't get around of some search & replace passes for the current Open statement lines with your newly created one.
For 2), can you illustrate that with an example? I'm trying to think of a situation where you know the UDT member's name in advance, but not its type.
That said, perhaps looking at VB's VarType function gives you an idea for solving that.
I'm converting a Foxpro app and I'm having a bit of trouble with database table referencing/selection. I'm not in a position to run the Foxpro code as I only have code dumps with which to work. If someone could help me understand what is happening here I'd be most grateful. Yes... I searched.
SELECT tblMyTable
Set Filter To Inlist(cbid,123)
SELECT tblMyTable
Does the second Select simply reselect tblMyTable and clear the filter?
If not is a second instance being opened so you have one that’s filtered and one that isn’t?
If so how do I reference each instance since they have no names? Automatically 1 and 2?
Lastly if I’ve got it completely wrong just give me a small clue and I’m on it. Thank you!
I see that you are being misguided.
Second select has no special meaning. That line is not needed at all, but wouldn't do an harm either.
If it were a view, then 'refreshing' a view is done by using Requery(), not by doing another 1 or more selects.
In fact, 'set filter' is on the list of (almost all VFP developers') "never to use commands" , exceptions like this might happen unfortunately.
If you are doing a conversion by only using code dumps and no VFP environment at all, then your task should be extremely hard. I would instead prefer a rewrite from scratch. That would be faster even for seasoned VFP developers.
I have some code which has worked in multiple installations for about a year. Today im doing a small change to a control and then another control seems to have developed an issue. When at runtime im getting a 91 error object variable or with block variable not set.
I therefore looked at the problem line which is: -
If Screen.ActiveForm.name = "frmFoutmelding" Then Exit Sub
so I noticed the name was lowercase. if i delete .name and rehit the "dot" then it shows me i can use .Name but as soon as i move from this line it drops back to .name
I've checked for instances of name and it appears everywhere in the code in different modules but i cant find if i have accidentally defined this lowercase name anywhere?
Googling doesn't seem to show much but i feel Im googling the wrong terms
chaps - thanks for your suggestions - this was the first instance of the lowercase name and searching as Jim suggested didn't reveal anything I'm afraid. What I did discover was that this was suddenly being run before any forms had actually been displayed and so the count was 0. I therefore, did an on error to check the form count and exit the sub if it =0 then if not to carry on with the line I thought I was having issues with.
It's likely that you did create a new variable or property called (lower case) name, or that some included reference did the same. It's possible to use reserved words as variable names in some cases, but it requires taking specific steps.
I would first search your code for instances of name As to see if you created a variable (this assumes you use Option Explicit, which is a must IMO). Then search for Property*name with * as a wildcard.
If those fail you could try unchecking references or components to see if any of them define name. If none of that finds anything, please post back here.
Jim Mack covers a lot of the potential issues. I think another is if you typed a lower case '.name' in association with Activeform at some point earlier in the same code module - the VB6 IDE checks in the current module and uses that to define what case to use. Look further up the same code module (sub or function).
Ultimately, check what changes you made by comparing the old source to the new in a file comparison tool like windiff - you do have backups, right?
I want to run a batch of queries, mostly creating and dropping indexes. In the batch call I also have a bunch of comments but the query parser keeps failing because of the comments. How do I write a comment?
I basically want to do this:
DROP INDEX oldIndex
/*
Comments
*/
CREATE INDEX newIndex ON Class (field) NOTUNIQUE
I have tried to comment with //, -- and #.
I also tried placing everything inside a transaction with begin and end but I can't drop an index inside a transaction.
Note that I'm using the studio. I made short test in the console but I still got problem with comments and lacked the overview to see any problems with my queries.
I am guessing the problem has to do with each row is seen as its own command. I suppose a command with only a comment doesn't make sense but is there any way around it?
In the meantime, use # comment-lines, that is, lines in which the first character (or the first non-blank character) is #.
I have used this in console.sh scripts in Version 2.1.x, e.g. 2.1.9, 2.1.10, and 2.1.11.
I have tried from Studio
I have found this issue https://github.com/orientechnologies/orientdb/issues/4651 about your problem with comments.
If the problem persists, you can reopen the issue.
Hope it helps.
I have compiled a list of db object names, one name per line, in a text file. I want to know for each names, where it is being used. The target search is a group of folders containing sub-folders of source codes.
Before I give up looking for a tool to do this and start creating my own, perhaps you can help to point to me an existing one.
Ideally, it should be a Windows desktop application. I have not used grep before.
use grep (there are tons of port of this command to windows, search the web).
eventually, use AgentRansack.
See our Source Code Search Engine. It indexes a large code base according to the atoms (tokens) of the language(s) of interest, and then uses that index to quickly execute structured queries stated in terms of language elememnts. It is a kind of super-grep, but it isn't fooled by comments or string literals, and it automatically ignores whitespace. This means you get a lot fewer false positive hits than you get with grep.
If you had an identifier "foo", the following query would find all mentions:
I=foo
For C and Java, you can constrain the types of identifier accesses to Use, Read, Write or Defines.
D=bar*
would find only declarations of identifiers which started with the letters "bar".
You can write more complex queries using sequences of language tokens:
'int' I=*baz* '['
for C, would find declarations of any variable name that contained the letters "baz" and apparantly declared an array.
You can see the hits in a GUI, and one-click navigate to a source code view of any hit.
It is a Windows application. It handles a wide variety of languages: C#, C++, Java, ... and many more.
I had created an SSIS package to load my 500+ source code files that is distributed into some depth of folders belongs to several projects, into a table, with 1 row as 1 line from the files (total is 10K+ lines).
I then made a select statement against it, by cross-applying the table that keeps the list of 5K+ keywords of db objects, with the help of RegEx for MS-SQL, http://www.simple-talk.com/sql/t-sql-programming/clr-assembly-regex-functions-for-sql-server-by-example/. The query took almost 1.5 hr to complete.
I know it's a long winded, but this is exactly what I need. I thank you for your efforts in guiding me. I would be happy to explain the details further, should anyone gets interested using my method.
insert
dbo.DbObjectUsage
select
do.Id as DbObjectId,
fl.Id as FileLineId
from
dbo.FileLine as fl -- 10K+
cross apply
dbo.DbObject as do -- 5K+
where
dbo.RegExIsMatch('\b' + do.name + '\b', fl.Line, 0) != 0