This program implements a full point-of-sale cash register system, managing an inventory stored in a 1,200-entry string array where each record is 25 characters wide (6-digit code, 12-character name, 7-character price with optional taxable flag). It uses a binary search subroutine at line 1 for fast item lookup and a Shell sort subroutine at lines 490–580 to keep inventory in alphabetical order after additions or deletions. Prices are formatted to two decimal places using the custom functions defined at lines 15 and 16, including zero-padding for trailing zeros. The program drives a printer via LPRINT for receipts and stock listings, saves/loads inventory data to tape, and uses two custom UDG characters (A and B) for menu highlighting.
Program Analysis
Program Structure
The program is organized into a main menu dispatcher and a set of subroutines, each handling a distinct function. Initialization occurs at line 9000 (cold start) and line 1000 (warm start / after tape load). The main menu loop runs at lines 40–65, dispatching via a computed GO SUB at line 60.
| Lines | Function |
|---|---|
| 1–12 | Binary search subroutine |
| 15–16 | DEF FN: numeric formatting helpers |
| 20–65 | Initialization, date entry, main menu loop |
| 75–390 | Cash register / transaction processing |
| 490–580 | Shell sort subroutine |
| 585–720 | Add new item |
| 725–810 | Delete item |
| 815–850 | Print stock listing |
| 860–870 | Save to tape |
| 875–935 | Exit / daily totals report |
| 1000–1010 | UDG setup and program entry point |
| 2000 | UDG DATA for characters A and B |
| 9000 | Cold start: initialize array, go to 1000 |
| 9999 | SAVE with auto-run |
Data Storage
All inventory is held in a single string array Z$ dimensioned at line 9000 as DIM Z$(1200,25), giving up to 1,200 records of exactly 25 characters each. The record layout is fixed-width:
- Characters 1–6: item code (zero-padded)
- Characters 7–18: item name (space-padded to 12 characters)
- Characters 19–25: price field (7 characters, space-padded); a trailing
Tin position 25 flags a taxable item
The variable M is used as the next-free-slot pointer; the valid record count is M-1. The array is kept sorted by code after every add or delete operation.
Binary Search (Lines 1–12)
The subroutine at line 1 accepts a search key in Q$ and searches Z$(1) through Z$(M-1) for a matching code in columns 1–6. It returns the found index in S, or 0 if not found. The algorithm uses standard midpoint halving with Y (low), Z (high), and C (mid). A boundary pre-check at line 1 short-circuits the search if Q$ falls outside the range of stored codes, avoiding unnecessary iterations on an empty or out-of-range query.
Line 9 handles the case where the binary search narrows to a single candidate without an exact match: S is set to the current low bound and then validated at line 10, which clears S to 0 if the code does not match exactly.
Shell Sort (Lines 490–580)
The sort subroutine implements a classic Shell sort (diminishing-increment sort). The gap sequence starts at INT(N/2) and is halved at each pass (line 500). Comparisons and swaps operate on entire 25-character strings in Z$(), so the code field naturally controls sort order. Deletion is handled by overwriting the target record’s code with ZZZZZZ (line 795) before sorting, which causes it to bubble to the end; M is then decremented at line 805 to effectively drop it.
Computed GO SUB Dispatch (Line 60)
Line 60 uses an arithmetic expression to compute the target line number:
GO SUB 75*(X=1)+585*(X=2)+725*(X=3)+815*(X=4)+860*(X=5)+875*(X=6)
In Sinclair BASIC, boolean expressions evaluate to 1 (true) or 0 (false), so exactly one term is non-zero for any valid menu choice. This is a compact single-line dispatcher avoiding a chain of IF/GO SUB statements.
Numeric Formatting Functions (Lines 15–16)
Two DEF FN functions handle currency formatting:
FN D(X)at line 15 rounds to two decimal places usingINT(100*X+0.5)/100.FN Q$(X,Q$)at line 16 takes a numberXand its string representationQ$, appending.00if the number is an integer, or a trailing0if the string ends in a decimal point with only one digit. This ensures display values always show exactly two decimal places.
Taxable Item Handling
Items are flagged as taxable by a T in the last character (position 25) of the record, or position 7 of a manually entered price string. When reading the numeric value of a price (line 250), the code strips the trailing T using VAL Z$(S,19 TO 25-(Z$(S,25)="T")). Tax at rate TR (initialized to 6.5% at line 20) is applied only to taxable items, accumulated in TX per transaction and TTX as a daily running total.
UDG Characters
Lines 1000–1010 define two UDG characters, A and B, from DATA at line 2000, used in the menu highlight display at line 59 (CHR$ 144 and CHR$ 145). These two 8-byte patterns represent decorative cursor/marker glyphs flanking the selected menu option.
Input Validation and Padding
Throughout the program, input strings for codes, names, and prices are normalized to fixed widths by either left-padding with spaces/zeros or right-padding with spaces:
- Item codes: left-padded with zeros to 6 characters (e.g., line 135, 620, 755)
- Item names: right-padded with spaces to 12 characters (line 650)
- Prices: left-padded with spaces to 7 characters (line 680)
Not-Found Item Entry (Lines 155–235)
If a scanned code is not in inventory during a transaction (line 150), the cashier is prompted to enter the item name and price directly. The entered price string is parsed with the same taxable-flag logic as stored records. This allows ad-hoc items to be sold without being in the database, printed with an NF (not found) prefix on the receipt.
Notable Anomalies
- Line 110 is referenced from line 265 (
GO TO 110) but does not exist in the listing. In practice this would cause a “Line does not exist” error; the apparent intent is to loop back to line 120 (the next item input prompt), suggesting line 110 is a missing or deleted line that was once equivalent toGO TO 120. - The
SAVEat line 865 saves starting atLINE 1000, so on reload the program enters via the UDG setup routine rather than cold-starting at 9000, preserving the existing array contents if any are in memory. - Line 935 issues
STOP : STOP— the secondSTOPis unreachable but harmless.
Content
Source Code
1 LET N=M-1: LET Y=1: LET Z=N+1: LET S=0: IF (Q$<Z$(1, TO 6))+(Q$>Z$(N, TO 6)) THEN GO TO 12
2 IF Z<Y THEN GO TO 9
3 LET C=INT ((Z+Y)/2): LET T$=Z$(C, TO 6)
4 IF T$=Q$ THEN LET S=C: GO TO 10
5 IF T$<Q$ THEN LET Y=C+1: GO TO 2
6 LET Z=C-1: GO TO 2
9 LET S=Z
10 IF Q$<>Z$(S, TO 6) THEN LET S=0
12 RETURN
15 DEF FN D(X)=INT (100*X+0.5)/100
16 DEF FN Q$(X,Q$)=Q$+(".00" AND X=INT X)+("0" AND ("0"+Q$)(LEN Q$)=".")
20 LET TR=0.065: LET B$=" ** YOUR BUSINESS NAME HERE **"
26 PAPER 6: BORDER 3: POKE 23658,8: CLS : POKE 23609,10
30 PRINT PAPER 5;" POINT OF SALE CASH REGISTER ";AT 1,0;" \* 1985 BY: I. AUERSBACHER ";AT 6,3;"ENTER TODAY'S DATE";AT 7,3;" (MM/DD/YYYY):"
32 INPUT D$
35 LET G=0: LET TTX=0
40 PAPER 3: BORDER 5: CLS : PRINT PAPER 1; INK 7;" POINT OF SALE CASH REGISTER ":
45 PRINT PAPER 7;AT 4,11;" MENU ";AT 7,6;"1- CASH REGISTER";AT 8,6;"2- ADD NEW ITEMS";AT 9,6;"3- DELETE ITEMS ";AT 10,6;"4- LPRINT STOCK ";AT 11,6;"5- SAVE TO TAPE ";AT 12,6;"6- EXIT PROGRAM ";AT 21,0;"OPTION NO?"
50 LET Q$=INKEY$: IF Q$="" THEN GO TO 50
55 IF CODE Q$<49 OR CODE Q$>54 THEN BEEP 0.3,-15: BEEP 0.3,-20: GO TO 50
56 LET X=INT VAL Q$: IF M=1 AND X=1 THEN BEEP .4,-20: GO TO 50
58 BEEP 0.06,25
59 PRINT INK 0;AT 6+X,3;CHR$ 144; INK 6;CHR$ 145: PAUSE 100: PAPER 7: BEEP .1,20
60 GO SUB 75*(X=1)+585*(X=2)+725*(X=3)+815*(X=4)+860*(X=5)+875*(X=6)
65 GO TO 40
75 CLS : PRINT B$: LPRINT : LPRINT : LPRINT B$
80 PRINT " DATE: ";D$: LPRINT " DATE: ";D$
85 PRINT : LPRINT
90 PRINT : LPRINT
100 LET TT=0: LET TX=0
120 INPUT FLASH 1;"ENTER CODE: ";Q$
125 IF Q$="" THEN GO TO 285
130 IF LEN Q$>6 THEN GO TO 120
135 IF LEN Q$<6 THEN LET Q$="00000"( TO 6-LEN Q$)+Q$
150 GO SUB 1: IF S<>0 THEN BEEP .03,25: GO TO 245
155 BEEP .4,-15: BEEP .5,-20: PRINT INK 2;" ";Q$;" NOT FOUND "
160 PRINT INK 2;" ITEM NAME: ";
165 INPUT A$: IF A$="" THEN PRINT FLASH 1;"CANCEL": GO TO 120
170 IF LEN A$>12 THEN LET A$=A$( TO 12)
175 PRINT INK 1;A$
180 PRINT INK 2;" ITEM COST: ";
185 INPUT Q$: IF Q$="" THEN BEEP 0.3,-20: GO TO 185
190 PRINT INK 1;Q$
205 LET X=LEN Q$: LET T=VAL Q$( TO X-(Q$(X)="T"))
210 LET G=G+T: LET TT=TT+T
220 IF X<7 THEN LET Q$=" "( TO 7-X)+Q$
225 PRINT " NF";TAB 8;A$;TAB 20+(Q$(7)="T");Q$: LPRINT " NF";TAB 8;A$;TAB 20+(Q$(7)="T");Q$
230 IF Q$(7)="T" THEN GO TO 270
235 GO TO 120
245 PRINT TAB 1;Z$(S, TO 6);" ";Z$(S,7 TO 18);TAB 20+(Z$(S,25)="T");Z$(S,19 TO )
246 LPRINT TAB 1;Z$(S, TO 6);" ";Z$(S,7 TO 18);TAB 20+(Z$(S,25)="T");Z$(S,19 TO )
250 LET T=VAL Z$(S ,19 TO 25-(Z$(S,25)="T"))
265 LET TT=TT+T: LET G=G+T: IF Z$(S,25)<>"T" THEN GO TO 110
270 LET T=FN D(T*TR)
275 LET TX=TX+T: LET TTX=TTX+T
280 GO TO 120
285 CLS : LET C=FN D(TT): LET Q$=FN Q$(C,STR$ C): BEEP .1,25
290 PRINT AT 4,7;"SUB TOT:";TAB 24-LEN Q$;Q$:
295 LET TX=FN D(TX): LET Q$=FN Q$(TX,STR$ TX)
300 PRINT TAB 7;"TAX DUE:";TAB 24-LEN Q$;Q$: LPRINT
305 LPRINT : LPRINT TAB 7;"TAX DUE:";TAB 24-LEN Q$;Q$
310 LET TT=FN D(TT+TX): LET Q$=FN Q$(TT,STR$ TT): PRINT
315 PRINT TAB 7; FLASH 1;"TOTAL:"; FLASH 0;TAB 24-LEN Q$;Q$
320 LPRINT TAB 7;"TOTAL:";TAB 24-LEN Q$;Q$
325 PRINT : LPRINT
330 PRINT TAB 7;"CASH TEND:";
340 INPUT Z
345 LET C=Z-TT: IF C<-0.001 THEN BEEP 0.7,-20: GO TO 340
350 LET Q$=FN Q$(Z,STR$ Z): PRINT TAB 24-LEN Q$;Q$: LPRINT TAB 7;"CASH TEND:";TAB 24-LEN Q$;Q$
355 LET C=FN D(C): LET Q$=FN Q$(C,STR$ C): PRINT TAB 7;"CHNG DUE :";TAB 24-LEN Q$;Q$
356 LPRINT TAB 7;"CHNG DUE :";TAB 24-LEN Q$;Q$
370 LPRINT : LPRINT : LPRINT " THANK YOU * HAVE A NICE DAY!"
375 FOR Z=1 TO 5: LPRINT
385 NEXT Z: PAUSE 10000
390 RETURN
490 LET N=M-1: LET S=N
500 LET S=INT (S/2)
505 IF S=0 THEN GO TO 580
510 LET W=N-S
515 LET Y=1
520 LET Z=Y
525 LET C=Z+S
535 IF Z$(Z)<=Z$(C) THEN GO TO 565
540 LET Q$=Z$(Z)
545 LET Z$(Z)=Z$(C)
550 LET Z$(C)=Q$
555 LET Z=Z-S
560 IF Z>=1 THEN GO TO 525
565 LET Y=Y+1
570 IF Y<=W THEN GO TO 520
575 GO TO 500
580 RETURN
585 CLS : LET A$=""
590 IF M>1200 THEN PRINT FLASH 1;" FILE FULL ": BEEP 1.5,-22: PAUSE 240: PRINT : GO TO 715
595 PRINT AT 2,8;"ADD DATA-->"
600 PRINT AT 4,1;"CODE NO: ";
605 INPUT Q$
610 IF Q$="" THEN GO TO 715
615 IF LEN Q$>6 THEN GO TO 605
620 IF LEN Q$<6 THEN LET Q$="00000"( TO 6-LEN Q$)+Q$
630 PRINT Q$: LET A$=A$+Q$
635 PRINT AT 5,1;"ITEM NAME: ";
640 INPUT Q$: IF Q$="" THEN BEEP .4,-15: BEEP .5,-20: GO TO 640
645 IF LEN Q$>12 THEN GO TO 640
650 IF LEN Q$<12 THEN LET Q$=Q$+" "( TO 12-LEN Q$)
660 PRINT Q$: LET A$=A$+Q$
665 PRINT AT 6,1;"ITEM COST: ";
670 INPUT Q$: IF Q$="" THEN BEEP 1,-20: GO TO 670
675 IF LEN Q$>7 THEN GO TO 670
680 IF LEN Q$<7 THEN LET Q$=" "( TO 7-LEN Q$)+Q$
685 PRINT Q$
690 LET A$=A$+Q$: LET Z$(M)=A$
700 LET M=M+1: PAUSE 50
710 GO TO 585
715 PRINT : PRINT : PRINT " "; FLASH 1;" SORTING ": GO SUB 490
720 RETURN
725 CLS : IF M=1 THEN RETURN
730 PRINT AT 3,0;"DELETE-->"
735 PRINT
740 PRINT "ENTER CODE NO. ";
745 INPUT Q$: IF Q$="" THEN : BEEP 0.07,22: GO TO 810
750 IF LEN Q$>6 THEN GO TO 745
755 IF LEN Q$<6 THEN LET Q$="00000"( TO 6-LEN Q$)+Q$
760 PRINT Q$: GO SUB 1
775 IF S<>0 THEN GO TO 795
780 PRINT Q$;" NOT FOUND"
785 PAUSE 220: GO TO 810
795 LET Z$(S, TO 6)="ZZZZZZ"
800 PRINT : PRINT TAB 1; FLASH 1;" SORTING ": GO SUB 490
805 LET M=M-1
810 RETURN
815 CLS
820 PRINT " CODE";TAB 10;"ITEM";TAB 23;"PRICE": LPRINT
822 LPRINT : LPRINT " CODE";TAB 10;"ITEM";TAB 23;"PRICE"
825 FOR Z=1 TO M-1
830 LET X$=Z$(Z)
835 PRINT " ";X$( TO 6);" ";X$(7 TO 18);TAB 21+(X$(25)="T");X$(19 TO )
836 LPRINT " ";X$( TO 6);" ";X$(7 TO 18);TAB 21+(X$(25)="T");X$(19 TO )
840 NEXT Z
845 PRINT : LPRINT : LPRINT
850 PAUSE 20000: RETURN
860 CLS : PRINT AT 5,2;"NAME OF THIS FILE?": INPUT Q$: PRINT
862 IF LEN Q$>10 OR Q$="" THEN BEEP 1.5,-20: GO TO 860
863 PRINT AT 7,2; PAPER 6;Q$
865 SAVE Q$ LINE 1000
867 PRINT FLASH 1;AT 9,2;" STOP RECORDER ": PAUSE 400
870 RETURN
875 CLS
880 PRINT : LPRINT : LPRINT
885 LET G=FN D(G): LET X=FN D(TTX): LET Q$=FN Q$(G,STR$ G):
890 LET A$=FN Q$(X,STR$ X)
895 PRINT : PRINT " DATE: ";D$
900 LPRINT " DATE: ";D$
905 PRINT : PRINT " TOTAL SALES: $";TAB 23-LEN Q$;Q$
906 LPRINT : LPRINT " TOTAL SALES: $";TAB 23-LEN Q$;Q$
910 PRINT " TOTAL TAXES: $";TAB 23-LEN A$;A$
912 LPRINT " TOTAL TAXES: $";TAB 23-LEN A$;A$
915 PRINT : LET G=FN D(G+X): LET Q$=FN Q$(G,STR$ G)
920 PRINT " GRAND TOTAL: $";TAB 23-LEN Q$;Q$
925 LPRINT : LPRINT " GRAND TOTAL: $";TAB 23-LEN Q$;Q$
930 PRINT : LPRINT : LPRINT
935 PRINT FLASH 1;AT 12,4;"PROGRAM TERMINATED": STOP : STOP
1000 BEEP 0.1,22: BEEP 0.1,20
1010 RESTORE : FOR Z=0 TO 7: READ Y,C: POKE USR "A"+Z,Y: POKE USR "B"+Z,C: NEXT Z: GO TO 20
2000 DATA 0,24,0,48,127,96,127,255,127,255,115,248,115,248,127,240
9000 LET M=1: DIM Z$(1200,25): GO TO 1000
9999 SAVE "cashreg" LINE 9000
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

