If you're lucky, the rewrite of reg and mlist will not require looking at the existing code at all and this whole page can be ignored. If you're not lucky or just curious, this page serves to give a quick overview of the elements of the language. The code is neither pretty nor elegant. As I came to FoxPro/dBase III+ as a C programmer I mostly used the low level elements which in the end made it quite labor-intensive. This may have kept the implementation easier to understand. Not sure.
FoxPro is a very simple, but adequate language for making
customized database applications like reg and mlist.
Here we mostly explain by example because
it is assumed that the audience is composed of competent software engineers.
This is a quick overview. The most authoritative documentation
is, of course, the FoxPro on-line help. Invoke 'foxpro -t' at the unix shell
and type 'help <topicname>' in the command window.
There is a 'See Also' choice which is helpful.
Ask Sahadev about anything as well.
As usual, only a small subset of the language is used.
Since reg and mlist were originally written in dBase III+
many/most of the FoxPro extensions and higher level tools
were not used. In part, this is because the work was
done as a volunteer.
Point and pick menus:
Tables (known as databases in FoxPro - kept in .dbf files)
are created with a nifty full screen dialog:
Multiple tables can be 'active' at the same time in different work areas.
Set them with this:
Perhaps unique to dBase (and descendants) applications
there is the concept of a 'current table' and within each
table there is a 'current record'. People used to using SQL
to access the data may find this odd or too low level or
too labor intensive. Surely it is more fragile than
using SQL!
In any case, continuing with the description ...
The pointer to the current record can be moved around with:
File Names
Source files end in ".prg". They are 'compiled' into ".fxp" files.
This compilation happens automatically if the source is out of date
or you can at any time manually issue the "comp" command in the command window.

Variables and Arithmetic
Variable are undeclared and typeless (Perl-like) (or more accurately
dynamically typed), case-insensitive, and composed of
letters, digits and underscores. Only the first 10 characters matter.
So these two lines have the same effect:

x123456789 = 10
x123456789012345 = 10
Scoping? Not precisely sure. I use the language in an 'empirical' way.
Variables can be declared 'public' to make them globally available
across files.
Those declared 'private' are scoped within a proc.
Flow of Control and Procedures

if nrec = 3
j = 4
endif
*
* calculation of k:
*
if total > 4 .and. sum < 23
k = 5
else
k = 6 && not seven
endif
do case
case type <> 2 .or. ans = 'yes'
...
case type = 3
...
case type >= 4
...
otherwise
...
endcase
sum = 1 + 2 + 3 + ;
4 + 5 + 6 + ;
7
**********************
*
*
proc check_it
parameter x
return x > maxnum
**********************
*
*
proc dumpout
parameter s, i
? trim(s)
? i*3
return
done = .f.
i = 1
do while i <= 10 .and. .not. done
? i
i = i + 1
do dumpout with "hello", 34+i
done = check_it(i)
do case
case k = 4
loop && next iteration
case k = 5
exit && out of the loop
case k = 6
quit && program ends
endcase
enddo
String Manipulation
+ is the concatenation operator.
Constant strings use either a single or double quote.
These functions do pretty much what their names say:
trim, alltrim, len, str, at, substr, upper, lower, empty, replicate.
Look them up in the online help.
str and val are inverses of each other.

Dates
Look up these date related functions:
date, dtoc, ctod, year, month, day, cdow, cmonth, dmy, ymd.

Screen Drawing and Input
Basics:

clear
@10,25 say "Hi there"
@11,20 && clear from 11,20 to end of line
@10,10 clear to @12,20 && clear a rectangular region
Simple screen input:
ans = 'N'
@10,10 say "Are you sure?" get ans picture '!'
read
More details in the FoxPro online help topic 'help @ ... get'.
dimension fruit(4) && an array
fruit(1) = "banana"
fruit(2) = "apple"
fruit(3) = "orange"
fruit(4) = "plum"
@10,10 menu fruit, 4 title " Which Fruit? "
j = 3 && default to oranges
read menu to j
Database Access
Access to the data is nicely integrated into
the FoxPro language. SQL access was implmented in later
releases of FoxPro but since it was not present in dBase III+
it is not used much (if at all) within reg/mlist.
Also, the few times I tried to use the FoxPro SQL it unfortunately
(and inexplicably) proved somewhat unreliable.

create people
And modified with this:
use people
modify struct && abbreviated 'modi stru'
Both dialogs are terminated with Control-W (write) and aborted
with Escape.
Data types include: Character, Numeric, Logical, Date, Memo.
select 1
use people
select 2
use roles
select 3
use pets
'select 0' will use the first unused work area.
skip
if eof() && are we at the end?
...
endif
skip 10
skip -1 && go backwards
go top
go bottom
Tables are ordered with the 'index' command.
Once the index is defined it is maintained
as records are edited, inserted and deleted.
use people
index on last+first tag name
index on age tag age
set order to name
set exact off
seek "SMITH"
if found()
...
endif
Filters limit which records can be seen:
select people && makes 'people' the current table
set filter to age > 20
go top && this actually sets the filter
Relations between tables help to give FoxPro the title of
a 'relational database'. As you move through one table
the current record pointer for a related table also moves.
Unfortunately, this is not so easy
to maintain properly by hand. SQL is a good idea!
select 0
use car
set order to id
select 0
use people
set order to name
set relation to p_car_id into car
do while .not. eof()
? p_name + " => " + car->c_make + ;
" " + car->c_model
skip
enddo
Multi-user access to a table/record is protected by using
the rlock, flock and unlock functions. If this is done
consistently (and voluntarily) before any additions, replacements
or deletions then all will be okay
when multiple users simultaneously access the same table/record.
If not, all will not be okay!
select people
if flock()
append blank
gather memvar
unlock
endif
File I/O
These are the functions to do file I/O:
fcreate, fopen, fgets, fputs, feof. Read about them in
the online FoxPro help. Here's an example:

F = fcreate("program")
if F = 0
return
endif
use prog
do while .not. eof()
=fputs(F, "name " + p_name)
=fputs(F, "sdate " + dtoc(p_sdate))
skip
enddo
=fclose(F)
G = fopen(fname)
do while .not. feof()
line = fgets(G)
...
enddo
=fclose(G)
FoxPro can't deal with files whose names are longer than 8 characters
for compatibility with DOS (remember DOS?).
Other Conventions
I have consistently followed indentation conventions of
4 spaces (not tabs).
I have aligned screen coordinates like this:

@ 9, 8 say "hi"
@10,20 say "bye"
Database (table) field names have a unique prefix
(mlist => m_, reg => r_, prog => p_).
I was mostly consistent in the way I implemented access to a table.
Simple menus at row 23 with "Next, Back, Search, Add, Edit, Delete, Quit"
menu choices. Records are shown on the screen with procs named using
the above prefix: r_paint, r_show, r_get. Sometimes the x_get proc
needed to have individual 'read' statements for each field to be
able to include a point and pick menu. This complicated things
considerably. If I had used the FoxPro screen and menu generator
it wouldn't have been so labor-intensive... but I didn't ... for a variety
of reasons.
Getting data out of a table record and into memory variables (m.*)
is done with 'scatter memvar'. Putting it back (after modification or
at insert time) is done with 'gather memvar'.
What Else?
Ask Sahadev.
