-- Line sorting program to run in Laurel -- -- [Juniper]User>LineSort>LineSorter.mesa -- Mike Schroeder, March 1, 1982 4:38 PM -- DIRECTORY BTreeDefs, crD: FROM "CoreDefs", csD: FROM "CoreStreamDefs", InlineDefs, IODefs, ovD: FROM "OverviewDefs", StringDefs, VMDefs; LineSorter: PROGRAM IMPORTS BTreeDefs, csD, InlineDefs, IODefs, StringDefs, VMDefs = BEGIN OPEN IODefs, StringDefs; MyLowerCase: PROCEDURE[c: CHARACTER] RETURNS[CHARACTER] = INLINE BEGIN RETURN[IF c IN ['A..'Z] THEN c - 'A + 'a ELSE c]; END; --MyLowerCase-- IsFirstGE: BTreeDefs.TestKeys --[a, b: DESC] RETURNS[BOOLEAN] -- = BEGIN aC: POINTER TO PACKED ARRAY OF CHARACTER = LOOPHOLE[BASE[a]]; bC: POINTER TO PACKED ARRAY OF CHARACTER = LOOPHOLE[BASE[b]]; FOR i:CARDINAL IN [0..2*MIN[LENGTH[a],LENGTH[b]]) DO IF MyLowerCase[aC[i]] < MyLowerCase[bC[i]] THEN RETURN[FALSE]; IF MyLowerCase[aC[i]] > MyLowerCase[bC[i]] THEN RETURN[TRUE]; ENDLOOP; RETURN[LENGTH[a] >= LENGTH[b]]; END; -- of IsFirstGE -- AreTheyE: BTreeDefs.TestKeys --[a, b: DESC] RETURNS[BOOLEAN] -- = BEGIN aC: POINTER TO PACKED ARRAY OF CHARACTER = LOOPHOLE[BASE[a]]; bC: POINTER TO PACKED ARRAY OF CHARACTER = LOOPHOLE[BASE[b]]; IF LENGTH[a] = LENGTH[b] THEN FOR i:CARDINAL IN [0..2*LENGTH[a]) DO IF MyLowerCase[aC[i]] # MyLowerCase[bC[i]] THEN EXIT; REPEAT FINISHED => RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; -- of AreTheyE -- Run: PROCEDURE = BEGIN tree: BTreeDefs.BTreeHandle; buffer: STRING = [62]; inputStr, outputStr: csD.StreamHandle _ NIL; NextLine: PROCEDURE [s: STRING] RETURNS [ f: LONG CARDINAL, n: CARDINAL]; FWNextLine: PROCEDURE [s: STRING] RETURNS [ f: LONG CARDINAL, n: CARDINAL] = BEGIN c: CHARACTER; s.length _ 0; f _ csD.GetPosition[inputStr]; BEGIN ENABLE csD.Error => IF reason = ovD.endOfStream THEN CONTINUE; c _ csD.Read[inputStr]; UNTIL c # SP AND c # TAB DO c _ csD.Read[inputStr]; ENDLOOP; UNTIL c = SP OR c = TAB OR c = CR DO AppendChar[s, c ! StringBoundsFault => CONTINUE]; c _ csD.Read[inputStr]; ENDLOOP; IF s.length/2 # 0 THEN AppendChar[s, SP]; UNTIL c = CR DO c _ csD.Read[inputStr]; ENDLOOP; END; --enable-- n _ InlineDefs.LowHalf[ csD.GetPosition[inputStr] - f ]; END; --FWNextLine-- MarkerNextLine: PROCEDURE [s: STRING] RETURNS [ f: LONG CARDINAL, n: CARDINAL] = BEGIN c: CHARACTER; s.length _ 0; f _ csD.GetPosition[inputStr]; BEGIN ENABLE csD.Error => IF reason = ovD.endOfStream THEN CONTINUE; c _ csD.Read[inputStr]; UNTIL c = ControlA OR c = CR DO c _ csD.Read[inputStr]; ENDLOOP; IF c # CR THEN BEGIN UNTIL c # SP AND c # TAB DO c _ csD.Read[inputStr]; ENDLOOP; UNTIL c = ControlB OR c = CR DO AppendChar[s, c ! StringBoundsFault => CONTINUE]; c _ csD.Read[inputStr]; ENDLOOP; IF s.length/2 # 0 THEN AppendChar[s, SP]; UNTIL c = CR DO c _ csD.Read[inputStr]; ENDLOOP; END ELSE IF csD.GetPosition[inputStr] - f > 1 THEN{ csD.SetPosition[inputStr, f]; [] _ FWNextLine[s]}; END; --enable-- n _ InlineDefs.LowHalf[ csD.GetPosition[inputStr] - f ]; END; --MarkerNextLine-- PutEntry: PROCEDURE [key: STRING, start: LONG CARDINAL, count: CARDINAL] = BEGIN keyWords: CARDINAL = (key.length+1)/2; k: DESCRIPTOR FOR ARRAY OF WORD = DESCRIPTOR [@(key.text), (keyWords+SIZE[LONG CARDINAL]+SIZE[CARDINAL])]; v: DESCRIPTOR FOR ARRAY OF WORD = DESCRIPTOR[NIL, 0]; InlineDefs.COPY[from:@start, to:BASE[k]+keyWords, nwords:SIZE[LONG CARDINAL]]; InlineDefs.COPY[from:@count, to:BASE[k]+keyWords+SIZE[LONG CARDINAL], nwords:SIZE[CARDINAL]]; BTreeDefs.Insert[tree, k, v]; END; --PutEntry-- PrintingWork: BTreeDefs.Call --PROCEDURE[k, v: DESCRIPTOR] RETURNS[more, dirty: BOOLEAN]-- = BEGIN first: LONG CARDINAL; number: CARDINAL; more _ TRUE; dirty _ FALSE; IF LENGTH[k] = 0 THEN RETURN; InlineDefs.COPY[from:BASE[k]+LENGTH[k] - SIZE[LONG CARDINAL] - SIZE[CARDINAL], to:@first, nwords:SIZE[LONG CARDINAL]]; InlineDefs.COPY[from:BASE[k]+LENGTH[k] - SIZE[CARDINAL], to:@number, nwords:SIZE[CARDINAL]]; csD.SetPosition[inputStr, first]; csD.StreamCopy[inputStr, outputStr, LONG[number]]; END; --PrintingWork-- BEGIN --for EXITS -- VMDefs.InitializeVM [min:4, max:40]; tree _ BTreeDefs.CreateAndInitializeBTree[ fileH:LOOPHOLE[VMDefs.OpenFile[name: "DLMap.btree$", options: oldOrNew]], initializeFile:TRUE, useDefaultOrderingRoutines:FALSE, isFirstGreaterOrEqual:IsFirstGE, areTheyEqual:AreTheyE]; DO WriteChar[CR]; WriteString["Sort by f(irst word) or m(arkers)? "L]; SELECT LowerCase[ReadChar[]] FROM 'f => NextLine _ FWNextLine; 'm => NextLine _ MarkerNextLine; ENDCASE => LOOP; EXIT; ENDLOOP; DO WriteChar[CR]; WriteString["Type input file name: "L]; buffer.length _ 0; AppendString[buffer, "temp$$"L]; ReadID[buffer ! Rubout => LOOP]; IF buffer.length = 0 THEN GOTO cleanup; inputStr _ csD.OpenFromName[buffer, crD.DMSUser[NIL, NIL, NIL], byte, read, 4 ! csD.Error => {WriteString["Can't open input file."L]; LOOP}]; EXIT; ENDLOOP; DO WriteChar[CR]; WriteString["Type output file name: "L]; buffer.length _ 0; AppendString[buffer, "temp$"L]; ReadID[buffer ! Rubout => LOOP]; IF buffer.length = 0 THEN GOTO cleanup; outputStr _ csD.OpenFromName[buffer, crD.DMSUser[NIL, NIL, NIL], byte, overwrite, 1 ! csD.Error => {WriteString["Can't open output file."L]; LOOP}]; EXIT; ENDLOOP; WriteChar[CR]; WriteLine["Reading input file."L]; DO start: LONG CARDINAL; length: CARDINAL; [start, length] _ NextLine[buffer ! csD.Error => {WriteChar[CR]; WriteLine["File error."L]; GOTO cleanup}]; IF length=0 THEN EXIT; IF buffer.length # 0 THEN PutEntry[buffer, start, length]; ENDLOOP; WriteLine["Writing output file."L]; BTreeDefs.EnumerateFrom[tree, DESCRIPTOR[NIL, 0], PrintingWork ! csD.Error => {WriteChar[CR]; WriteLine["File error."L]; GOTO cleanup}]; GOTO cleanup; EXITS cleanup => BEGIN IF inputStr # NIL THEN csD.Close[inputStr ! csD.Error => CONTINUE]; IF outputStr # NIL THEN csD.Close[outputStr ! csD.Error => CONTINUE]; VMDefs.AbandonFile[LOOPHOLE[BTreeDefs.ReleaseBTree[tree]]]; VMDefs.FinalizeVM[]; END; END; WriteLine["Done"L]; END; Run[]; END.z20461(1792)\f7