--- title: "Name Address Files" id: 71759 type: "computer_media" slug: "name-address-files" url: "http://localhost/computer_media/name-address-files/" markdown_url: "http://localhost/computer_media/name-address-files.md" published_at: "2026-10-05T21:06:47+00:00" modified_at: "2026-10-05T21:06:48+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/10/name-address-files.png" excerpt: "A full menu-driven name-and-address database supporting up to 150 five-field records, with search, edit, delete, and tape save/load — all in BASIC." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "1983" slug: "year-1983" taxonomy: "post_tag" url: "http://localhost/tag/year-1983/" - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Al Laity" slug: "a-laity" taxonomy: "indiv" url: "http://localhost/indiv/a-laity/" genre: - name: "Database" slug: "database" taxonomy: "genre" url: "http://localhost/type/database/" media_type: "Program" programmers: - name: "Al Laity" slug: "a-laity" taxonomy: "indiv" url: "http://localhost/indiv/a-laity/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Name%20Address%20Files%20(1983)(Laity%2C%20Al)(TS2068)(US)(Program).zip" mediadate: "1983" images: - url: "http://localhost/wp-content/uploads/2026/10/name-address-files.png" media_type_tags: "Database" --- # Name Address Files Name Address Files is a menu-driven personal database program that stores up to 150 records, each with five 32-character fields, in a three-dimensional string array declared as DIM F$(150,5,32). The first record of the array (F$(1,1)) is used as a metadata slot to track the current file count as a string, which is converted back to a number with VAL. Deleted records are flagged by writing an asterisk into their first field rather than compacting the array, and a subroutine at line 9000 scans for these slots to reuse them when new entries are added. The program supports both screen and printer output, toggled by prefixing a menu choice with the letter “P,” and uses RANDOMIZE USR 100 before SAVE and LOAD operations, suggesting a machine-code routine is present at that address. Search functionality performs a prefix match by comparing a user-supplied string against the leading characters of a chosen field using the TO slice syntax. ### Program Structure The program is organized into well-separated subroutines and sections addressed by `GO TO` or `GO SUB` from a central menu dispatcher at line `1000`. Lines `1–5` initialize global state. Line `90` jumps immediately to the menu. Lines `100–150` draw a title banner as a reusable subroutine. The functional blocks are: | Lines | Function | | --- | --- | | 1000–1180 | Main menu and dispatch | | 1800–1840 | Printer header subroutine | | 1900–1940 | Screen header subroutine | | 2000–2900 | Enter new record | | 3000–3560 | Edit existing record | | 4000–4690 | Search records | | 5000–5600 | List all records | | 6000–6100 | Save to tape | | 7000–7050 | Load from tape | | 8000–8300 | Delete a record | | 9000–9070 | Find a deleted slot for reuse | | 9800–9810 | Common “press ENTER” return to index | ### Data Storage Design The central data structure is `DIM F$(150,5,32)` — a three-dimensional string array holding up to 150 records, each with 5 fields of up to 32 characters. This is a compact way to simulate a flat-file database entirely within BASIC’s string array facilities. Record 1 (`F$(1,1)`) is repurposed as a metadata cell: it stores the current highest file index as a string, read back with `VAL F$(1,1)` at lines `1090`, `4250`, and elsewhere. This avoids needing a separate numeric variable that might be lost on a program break. ### Deletion and Slot Reuse Deleted records are marked by writing `"*"` into `F$(N+1,1)` (line `8100`). The array is never compacted. Instead, subroutine `9000` scans from index 2 upward, looking for a record whose first field begins with `"*"`, and if found, stores that index in `flag` and clears fields 2–5 of that slot. The entry routine at line `2026` then uses the reclaimed slot index instead of incrementing `FL`, preventing unbounded growth of the in-use counter. ### Printer Toggle via Prefix Character The program implements a dual screen/printer output mode using a single global variable `P$`. At the menu input (line `1100`), if the user enters a two-character string, the first character is treated as a “P” prefix flag: `P$` is set to `"1"` and the actual menu digit is taken from `A$(2)` (line `1105`). Throughout the listing and search routines, `IF P$="1"` branches to `LPRINT` paths rather than `PRINT` paths. This is an economical approach that avoids duplicating entire routines. ### Search Implementation The search at lines `4000–4690` performs a prefix match using BASIC’s string-slice syntax. Line `4280` reads: `IF F$(X,FI, TO LEN S$)=S$ THEN GO SUB 4500` This takes the first `LEN S$` characters of the chosen field and compares them to the user’s search string, so the search is always a leading-substring (prefix) match rather than a full-field or anywhere-in-field match. The user is informed of this behavior at line `4160`. ### Machine Code Hook Both the save (line `6090`) and load (line `7045`) routines call `RANDOMIZE USR 100` before the tape operation. This implies a machine-code routine is expected to reside at address 100. The purpose is not explained in the listing, but a commented-out line at `9992` also references `RANDOMIZE USR 100` alongside a `SAVE` with a `LINE 1` autostart parameter, suggesting the routine may relate to tape or system initialization. ### Key BASIC Idioms - `VAL F$(1,1)` — reading a stored integer back from a string array cell, used as a record count. - `STR$ FL` — converting the updated count back to a string for storage in `F$(1,1)`. - `IF INKEY$="C" ... / IF INKEY$="" THEN GO TO 7027` — a polling loop waiting for a specific keypress at lines `7027–7028`. - `INVERSE 1 / INVERSE 0` — used for highlighted prompts and status messages on screen. - `FLASH 1 / FLASH 0` — used at line `7025` to draw attention to a data-loss warning before loading. ### Bugs and Anomalies - Line `4600` is referenced by `GO TO 4600` at line `4505`, but the actual code for the printer output path begins at line `4610`. Line `4600` does not exist, so the printer branch in the search-found subroutine silently falls into `4610` — this works only because there is no code between `4600` and `4610` that would cause an error, but it is fragile. - Line `3560` (`LET Z= VAL Z$+1:IF Z>NF THEN GO TO 3530`) is unreachable dead code: the `GO TO 3060` at line `3550` always transfers control before reaching it, and `NF` is never defined anywhere in the program. - Lines `4210` and `4230` are both present, but line `4210` uses `GO TO 4230` after the `LPRINT` statements, meaning both the printer and screen paths always print to screen as well — the printer path falls through into the screen output at line `4230`. - The `IF` condition at line `3040` (`IF Z$="" THEN GO TO 3040`) is duplicated at line `3045`, which is redundant but harmless. ## Source Code ``` 1 LET fl=1 2 DIM F$(150,5,32) 3 LET F$(1,1)="1" 5 LET P$="" 90 GO TO 1000 100 BORDER 5:PAPER 6:INK 0:CLS 110 FOR x=1 TO 2:PRINT "********************************":NEXT x 120 PRINT "***** NAME ADDRESS FILES *****" 130 PRINT "*** copyright 1983 Al Laity ***" 140 FOR x=1 TO 2:PRINT "********************************":NEXT x 150 RETURN 1000 GO SUB 100 1010 PRINT :PRINT :PRINT 1020 PRINT AT 8,0;"1. LIST ALL NAME/ADDRESS FILES" 1030 PRINT "2. ENTER NEW INFORMATION" 1040 PRINT "3. SEARCH FOR INFORMATION" 1050 PRINT "4. MAKE CHANGES TO CURRENT FILES" 1060 PRINT "5. DELETE A FILE" 1070 PRINT "6. LOAD FILES FROM TAPE" 1075 PRINT "7. SAVE FILES TO TAPE" 1080 PRINT :PRINT :INVERSE 1:PRINT "PRECEDE NO. BY 'P' FOR PRINTER":INVERSE 0 1085 PRINT :PRINT "IF you should break program in error -- type GO TO 1000 to ensure that files are not lost" 1090 LET FL= VAL F$(1,1) 1100 INPUT "CHOOSE BY NUMBER ";A$:IF LEN A$>2 THEN GO TO 1100 1101 IF a$="" THEN GO TO 1100 1102 IF LEN A$<2 THEN LET A= VAL A$:LET P$="":GO TO 1110 1105 LET P$="1":LET A= VAL A$(2) 1110 IF A=1 THEN GO TO 5000 1111 IF A=0 THEN GO TO 9998 1120 IF A=2 THEN GO TO 2000 1130 IF A=3 THEN GO TO 4000 1140 IF A=4 THEN GO TO 3000 1150 IF A=5 THEN GO TO 8000 1160 IF A=6 THEN GO TO 7000 1170 IF A=7 THEN GO TO 6000 1180 GO TO 1000 1800 FOR X=1 TO 3:PRINT "\{20}\{1} DATA TO PRINTER ":NEXT x\{20}\{0} 1805 FOR X=1 TO 2:LPRINT "********************************":NEXT X 1810 LPRINT A$ 1820 FOR X=1 TO 2:LPRINT "********************************":NEXT X 1830 LPRINT 1840 RETURN 1900 CLS 1910 FOR X=1 TO 2:PRINT "********************************":NEXT X 1920 PRINT A$ 1930 FOR X=1 TO 2:PRINT "********************************":NEXT X 1940 PRINT :PRINT :RETURN 2000 REM MAKE ENTRIES 2010 LET A$="******** MAKING ENTRIES ********":GO SUB 1900 2020 LET fl= VAL F$(1,1)+1:LET g=fl-2 2025 GO SUB 9000 2026 IF flag <>0 THEN LET fl=flag 2030 PRINT "NEW FILE BEING CREATED WILL BE":PRINT "FILE NUMBER - ";FL-1:PRINT "there are ";g;" files open":PRINT "including deleted files which (will be filled as you open new files)" 2035 FOR X=1 TO 5 2037 PRINT INVERSE 1;"FIELD ";X; INVERSE 0 2040 INPUT "TYPE FIELD ";X$ 2050 IF LEN X$>32 THEN GO TO 2040 2055 LET F$(FL,X)=X$ 2060 PRINT F$(FL,X) 2065 IF F$(FL,X, TO 4)="QUIT" THEN GO TO 1000 2070 NEXT X 2100 IF FLAG=0 THEN LET F$(1,1)= STR$ FL 2900 GO TO 9800 3000 REM MAKE CHANGES 3010 LET A$="*** MAKING CHANGES TO FILES ****":GO SUB 1900 3015 IF FL=1 THEN PRINT "THERE ARE NO FILES ":GO TO 9800 3020 PRINT "ENTER FILE NUMBER" 3030 PRINT "PRESS 'U' IF UNKNOWN" 3040 INPUT Z$:IF Z$="" THEN GO TO 3040 3045 IF Z$="" THEN GO TO 3040 3050 IF z$="u" OR Z$="U" THEN GO TO 3500 3055 IF z$(1)="q" OR Z$(1)="Q" THEN GO TO 1000 3060 LET Z= VAL Z$+1:IF Z>FL THEN GO TO 3000 3065 CLS :PRINT "\{20}\{1}FILE NUMBER ";Z-1;" \{20}\{0}" 3070 FOR X=1 TO 5 3080 PRINT X;"..";F$(Z,X) 3090 NEXT X 3100 INPUT "FIELD # TO BE CHANGED";Z$:IF Z$="" THEN GO TO 3100 3101 IF Z$(1)="Q" OR Z$(1)="q" THEN GO TO 1000 3105 LET J= VAL Z$:IF J<1 OR J>5 THEN GO TO 3100 3110 PRINT "\{20}\{1}NEW FIELD NUMBER \{20}\{0}\{20}\{0}\{20}\{1}";J;" \{20}\{0}" 3120 INPUT "type new field ";x$ 3130 IF LEN x$>32 THEN GO TO 3120 3140 LET f$(z,j)=x$ 3145 PRINT X$ 3150 INPUT "any other changes to this file";z$ 3160 IF z$="y" OR z$="Y" THEN GO TO 3100 3170 CLS 3180 PRINT "\{20}\{1}NEW FILE NUMBER ";Z-1;" \{20}\{0}":PRINT 3190 FOR X=1 TO 5 3195 PRINT F$(Z,X) 3200 NEXT X 3210 GO TO 9800 3500 FOR X=2 TO FL 3505 IF f$(x,1,1)="*" THEN GO TO 3520 3510 PRINT X-1;"..";F$(X,1) 3520 NEXT X 3530 PRINT "ENTER FILE # TO BE CHANGED" 3540 INPUT Z$:IF Z$="Q" OR z$="q" THEN GO TO 1000 3545 IF Z$="" THEN GO TO 3540 3550 GO TO 3060 3560 LET Z= VAL Z$+1:IF Z>NF THEN GO TO 3530 4000 REM SEARCH 4010 LET A$="********* FILE SEARCH *********":GO SUB 1900 4015 IF P$="1" THEN GO SUB 1800 4020 PRINT "WHEN FOUND DO YOU WANT ":PRINT 4040 PRINT "1. OUTPUT FIELD 1 OF FOUND FILES" 4045 PRINT :PRINT "2. OUTPUT ALL FIELDS IN FILE" 4050 INPUT "CHOOSE BY NUMBER ";Z$ 4060 IF Z$="" THEN GO TO 4050 4070 IF Z$(1)="q" OR Z$(1)="Q" THEN GO TO 1000 4080 IF z$(1) <>"1" AND z$(1) <>"2" THEN GO TO 4050 4090 LET z= VAL z$ 4100 INPUT "enter field number to be searched ";q$ 4110 IF q$="" THEN GO TO 4100 4120 IF q$(1)="q" OR q$(1)="Q" THEN GO TO 1000 4130 LET A$=Q$(1):IF A$ <>"1" AND A$ <>"2" AND A$ <>"3" AND A$ <>"4" AND A$ <>"5" THEN GO TO 4100 4140 LET FI= VAL A$ 4150 LET A$="******* SEARCH FIELD "+ STR$ FI+" *********":GO SUB 1900 4160 PRINT "YOU MAY ENTER ANY NUMBER OF CHARACTERS. I WILL SEARCH FIELD ";FI;" TO FIND ANY THAT BEGIN WITH THE CHARACTERS YOU ENTER" 4170 INPUT "ENTER YOUR DATA TO BE SEARCHED FOR ";S$ 4175 IF S$="QUIT" THEN GO TO 1000 4180 IF S$="" THEN GO TO 4170 4190 IF LEN S$>32 THEN GO TO 4180 4200 GO SUB 1900 4210 IF P$="1" THEN LPRINT "SEARCH CONDUCTED - FIELD ";FI;" FOR":LPRINT S$:LPRINT :GO TO 4230 4230 PRINT "SEARCH CONDUCTED - FIELD ";FI;" FOR":PRINT S$:PRINT 4240 LET FO=0 4250 LET FL= VAL F$(1,1) 4260 FOR X=2 TO FL 4265 IF F$(X,1,1)="*" THEN GO TO 4350 4280 IF F$(X,FI, TO LEN S$)=S$ THEN GO SUB 4500 4350 NEXT X 4360 IF P$="" THEN PRINT :PRINT FO;" FILES FOUND" 4370 IF P$="1" THEN LPRINT :LPRINT FO;" FILES FOUND" 4380 GO TO 9800 4500 LET FO=FO+1 4505 IF P$="1" THEN GO TO 4600 4510 IF Z=1 THEN PRINT F$(X,1) 4520 IF Z <>2 THEN GO TO 4590 4530 FOR J=1 TO 5 4540 IF F$(X,J)=" " THEN GO TO 4580 4550 PRINT F$(X,J) 4580 NEXT J 4585 PRINT 4590 RETURN 4610 IF Z=1 THEN LPRINT F$(X,1) 4620 IF Z <>2 THEN GO TO 4690 4630 FOR J=1 TO 5 4640 IF F$(X,J)=" " THEN GO TO 4680 4650 LPRINT F$(X,J) 4680 NEXT J 4685 LPRINT 4690 RETURN 5000 LET A$="******** LISTING FILES *********":GO SUB 1900 5001 LET FL= VAL F$(1,1) 5002 IF fl<2 THEN PRINT "THERE ARE NO FILES ":GO TO 9800 5010 PRINT "1. LIST ALL NAMES ONLY" 5020 PRINT :PRINT "2. LIST ALL FIELDS" 5030 INPUT "CHOOSE BY NUMBER ";Z$:IF z$="q" OR Z$="Q" THEN GO TO 1000 5040 IF Z$="1" THEN GO TO 5100 5050 IF Z$="2" THEN GO TO 5500 5060 GO TO 5030 5100 LET A$="******* LISTING ALL NAMES ******":GO SUB 1900:IF P$="1" THEN GO SUB 1800 5109 FOR X=2 TO FL 5110 IF P$="1" THEN GO TO 5300 5120 IF f$(x,1,1)="*" THEN GO TO 5310 5150 PRINT F$(X,1) 5160 GO TO 5310 5300 IF f$(x,1,1)="*" THEN GO TO 5310 5305 LPRINT F$(X,1) 5310 NEXT X 5320 GO TO 9800 5500 LET A$="***** LISTING OF ALL FILES *****":GO SUB 1900:IF P$="1" THEN GO SUB 1800 5510 FOR x=2 TO fl 5520 FOR y=1 TO 5 5521 IF f$(X,1,1)="*" THEN GO TO 5540 5525 IF f$(x,y)=" " THEN GO TO 5540 5526 IF p$="1" THEN GO SUB 5600:GO TO 5540 5530 PRINT f$(x,y) 5540 NEXT y 5545 IF p$="1" THEN LPRINT :GO TO 5550 5546 PRINT 5550 NEXT x 5560 GO TO 9800 5600 LPRINT f$(x,y):RETURN 6000 REM SAVE FILES 6010 LET A$="***** SAVING FILES TO TAPE *****" 6020 GO SUB 1900 6030 INPUT "YOUR FILE NAME ? ";N$ 6035 IF N$="QUIT" THEN GO TO 1000 6040 IF LEN N$ >=11 THEN GO TO 6030 6050 PRINT "SAVE FILES UNDER THE NAME ....":PRINT N$ 6060 INPUT "VERIFY (Y OR N)? ";Z$:IF Z$="N" OR Z$="n" THEN GO TO 6000 6065 IF Z$="QUIT" THEN GO TO 1000 6070 PRINT :PRINT "SAVING ...";N$ 6090 RANDOMIZE USR 100:SAVE N$+".A$"DATA F$() 6100 GO TO 1000 7000 REM LOAD FILES 7010 LET A$="**** LOADING FILES FROM TAPE ***":GO SUB 1900 7020 INPUT "NAME OF FILE TO BE LOADED ? ";N$ 7021 IF N$="QUIT" THEN GO TO 1000 7022 PRINT "LOAD ......";N$:INPUT "VERIFY (Y OR N)? ";Z$:IF Z$="N" OR Z$="n" THEN GO TO 7000 7023 IF z$="quit" THEN GO TO 1000 7025 PRINT :PRINT FLASH 1;"LOADING WILL DESTROY ANY DATA CURRENTLY IN THE COMPUTER "; FLASH 0 7026 PRINT :PRINT "PRESS: 'C' TO CONTINUE 'Q' TO QUIT" 7027 IF INKEY$="C" OR INKEY$="c" THEN GO TO 7040 7028 IF INKEY$="" THEN GO TO 7027 7030 GO TO 1000 7040 PRINT :PRINT "PRESS PLAY ON RECORDER " 7045 RANDOMIZE USR 100:LOAD N$+".A$"DATA F$() 7050 GO TO 1000 8000 REM DELETE 8010 LET a$="********** DELETE FILE *********":GO SUB 1900 8020 PRINT "FILE NUMBER TO BE DELETED.." 8030 INPUT "FILE NUMBER ? - TYPE 'U' IF FILENUMBER IS UNKNOWN ";N$ 8035 IF n$="" THEN GO TO 8030 8040 IF N$(1)="Q" THEN GO TO 1000 8050 IF n$="u" OR N$="U" THEN GO SUB 8200:GO TO 8020 8060 LET N= VAL N$ 8070 FOR X=1 TO 5 8080 PRINT F$(N+1,X):NEXT X 8090 INPUT "VERIFY (Y OR N) ?";Z$:IF Z$ <>"Y" AND Z$ <>"y" THEN CLS :GO TO 8010 8095 IF Z$="" THEN GO TO 8090 8100 LET F$(N+1,1)="*" 8110 PRINT "\{20}\{1}\{20}\{1}\{20}\{1} FILE DELETED \{20}\{0}" 8120 GO TO 9800 8200 CLS 8210 PRINT "\{20}\{1} OPEN FILES : \{20}\{0}":PRINT 8220 LET FL= VAL F$(1,1) 8230 FOR X=2 TO FL 8235 IF f$(x,1,1)="*" THEN GO TO 8290 8240 PRINT X-1;"...";F$(X,1) 8290 NEXT X 8300 RETURN 9000 REM fill deleted file 9010 FOR x=2 TO fl 9020 IF f$(x,1,1) <>"*" THEN GO TO 9060 9030 LET flag=x 9040 FOR y=2 TO 5:LET f$(x,y)=" ":NEXT y:RETURN 9060 NEXT x 9065 LET flag=0 9070 RETURN 9800 PRINT :INPUT "PRESS \{20}\{1}ENTER\{20}\{0} FOR INDEX";Z$ 9810 GO TO 1000 9992 REM CLEAR :RANDOMIZE USR 100:SAVE "NAME.B1" LINE 1 9998 REM RANDOMIZE USR 100:LOAD "L.B1" ```