Canonicalize CIDR: Difference between revisions

Added FreeBASIC and QBasic and. Grouping BASIC dialects
(add RPL)
(Added FreeBASIC and QBasic and. Grouping BASIC dialects)
Line 218:
<syntaxhighlight lang="apl"> canonicalize '87.70.141.1/22'
87.70.140.0/22</syntaxhighlight>
 
=={{header|BASIC}}==
==={{header|Commodore BASIC}}===
<syntaxhighlight lang="gwbasic">100 REM THE BINARY OPS ONLY WORK ON SIGNED 16-BIT NUMBERS
110 REM SO WE STORE THE IP ADDRESS AS AN ARRAY OF FOUR OCTETS
120 DIM IP(3)
130 REM READ DEMO DATA
140 READ CI$
150 IF CI$="" THEN END
160 REM FIND /
170 SL=0
180 FOR I=LEN(CI$) TO 1 STEP -1
190 : IF MID$(CI$,I,1)="/" THEN SL=I:I=1
200 NEXT I
210 IF SL=0 THEN PRINT "INVALID CIDR STRING: '"CI$"'":GOTO 140
220 NW=VAL(MID$(CI$,SL+1))
230 IF NW < 1 OR NW > 32 THEN PRINT "INVALID NETWORK WIDTH:"NW:GOTO 140
240 REM PARSE OCTETS INTO IP ARRAY
250 BY=0:N=0
260 FOR I=1 TO SL-1
270 : C$=MID$(CI$,I,1):IF C$<>"." THEN 300
280 : IP(N)=BY:N=N+1:BY=0:IF IP(N-1)<256 THEN 310
290 : PRINT "INVALID OCTET VALUE:"IP(N-1):GOTO 140
300 : C=VAL(C$):IF C OR (C$="0") THEN BY=BY*10+C
310 NEXT I
320 IP(N)=BY:N=N+1:IF IP(N-1)>255 THEN 290
330 REM NUMBER OF COMPLETE OCTETS IN NETWORK PART
340 NB=INT(NW/8)
350 REM NUMBER OF NETWORK BITS IN PARTIAL OCTET
360 XB=NW AND 7
370 REM ZERO OUT HOST BITS IN PARTIAL OCTET
380 IP(NB) = IP(NB) AND (255 - 2^(8-XB) + 1)
390 REM AND SET ANY ALL-HOST OCTETS TO 0
400 IF NB<3 THEN FOR I=NB+1 TO 3:IP(I)=0 :NEXT I
410 REM PRINT OUT THE RESULT
420 PRINT MID$(STR$(IP(0)),2);
430 FOR I=1 TO 3: PRINT "."MID$(STR$(IP( I)),2);:NEXT I
440 PRINT MID$(CI$,SL)
450 REM AND GO BACK FOR NEXT INPUT
460 GOTO 140
500 DATA 87.70.141.1/22, 36.18.154.103/12, 62.62.197.11/29
510 DATA 67.137.119.181/4, 161.214.74.21/24, 184.232.176.184/18
520 REM SOME INVALID INPUTS
530 DATA 127.0.0.1, 123.45.67.89/0, 98.76.54.32/100, 123.456.789.0/12
540 DATA</syntaxhighlight>
 
{{Out}}<pre>READY.
RUN
87.70.140.0/22
36.16.0.0/12
62.62.197.8/29
64.0.0.0/4
161.214.74.0/24
184.232.128.0/18
INVALID CIDR STRING: '127.0.0.1'
INVALID NETWORK WIDTH: 0
INVALID NETWORK WIDTH: 100
INVALID OCTET VALUE: 456
 
READY.</pre>
 
==={{header|FreeBASIC}}===
{{trans|Commodore BASIC}}
<syntaxhighlight lang="vb">#lang "qb"
 
REM THE Binary OPS ONLY WORK On SIGNED 16-Bit NUMBERS
REM SO WE STORE THE IP ADDRESS As AN ARRAY OF FOUR OCTETS
Cls
Dim IP(3)
Do
REM Read DEMO Data
140 Read CI$
If CI$ = "" Then Exit Do 'Sleep: End
REM FIND /
SL = 0
For I = Len(CI$) To 1 Step -1
If Mid$(CI$,I,1) = "/" Then SL = I : I = 1
Next I
If SL = 0 Then Print "INVALID CIDR STRING: '"; CI$; "'": Goto 140
NW = Val(Mid$(CI$,SL+1))
If NW < 1 Or NW > 32 Then Print "INVALID NETWORK WIDTH:"; NW: Goto 140
REM PARSE OCTETS INTO IP ARRAY
BY = 0 : N = 0
For I = 1 To SL-1
C$ = Mid$(CI$,I,1)
If Not (C$ <> ".") Then
IP(N) = BY : N = N + 1
BY = 0
If IP(N-1) < 256 Then 310
Print "INVALID OCTET VALUE:"; IP(N-1): Goto 140
Else C = Val(C$):If C Or (C$="0") Then BY = BY*10+C
End If
310 '
Next I
IP(N) = BY : N = N + 1
If IP(N-1) > 255 Then Print "INVALID OCTET VALUE:"; IP(N-1): Goto 140
REM NUMBER OF COMPLETE OCTETS IN NETWORK PART
NB = Int(NW/8)
REM NUMBER OF NETWORK BITS IN PARTIAL OCTET
XB = NW And 7
REM ZERO Out HOST BITS IN PARTIAL OCTET
IP(NB) = IP(NB) And (255 - 2^(8-XB) + 1)
REM And SET Any ALL-HOST OCTETS To 0
If NB < 3 Then For I = NB +1 To 3 : IP(I) = 0 : Next I
REM Print Out THE RESULT
Print Mid$(Str$(IP(0)),2);
For I = 1 To 3
Print "."; Mid$(Str$(IP( I)),2);
Next I
Print Mid$(CI$,SL)
Loop
Data "87.70.141.1/22", "36.18.154.103/12", "62.62.197.11/29"
Data "67.137.119.181/4", "161.214.74.21/24", "184.232.176.184/18"
REM SOME INVALID INPUTS
Data "127.0.0.1", "123.45.67.89/0", "98.76.54.32/100", "123.456.789.0/12"
 
Sleep</syntaxhighlight>
{{out}}
<pre>Similar to Commodore BASIC entry.</pre>
 
==={{header|QBasic}}===
{{trans|Commodore BASIC}}
{{works with|QBasic|1.1}}
{{works with|QuickBasic|4.5}}
<syntaxhighlight lang="qbasic">CLS
DIM IP(3)
DO
REM Read DEMO Data
140 READ CI$
IF CI$ = "" THEN EXIT DO 'Sleep: End
REM FIND /
SL = 0
FOR I = LEN(CI$) TO 1 STEP -1
IF MID$(CI$, I, 1) = "/" THEN SL = I: I = 1
NEXT I
IF SL = 0 THEN PRINT "INVALID CIDR STRING: '"; CI$; "'": GOTO 140
NW = VAL(MID$(CI$, SL + 1))
IF NW < 1 OR NW > 32 THEN PRINT "INVALID NETWORK WIDTH:"; NW: GOTO 140
REM PARSE OCTETS INTO IP ARRAY
BY = 0: N = 0
FOR I = 1 TO SL - 1
C$ = MID$(CI$, I, 1): IF C$ <> "." THEN 300
IP(N) = BY: N = N + 1: BY = 0: IF IP(N - 1) < 256 THEN 310
290 PRINT "INVALID OCTET VALUE:"; IP(N - 1): GOTO 140
300 C = VAL(C$): IF C OR (C$ = "0") THEN BY = BY * 10 + C
310 '
NEXT I
IP(N) = BY: N = N + 1: IF IP(N - 1) > 255 THEN 290
REM NUMBER OF COMPLETE OCTETS IN NETWORK PART
NB = INT(NW / 8)
REM NUMBER OF NETWORK BITS IN PARTIAL OCTET
XB = NW AND 7
REM ZERO Out HOST BITS IN PARTIAL OCTET
IP(NB) = IP(NB) AND (255 - 2 ^ (8 - XB) + 1)
REM And SET Any ALL-HOST OCTETS To 0
IF NB < 3 THEN FOR I = NB + 1 TO 3: IP(I) = 0: NEXT I
REM Print Out THE RESULT
PRINT MID$(STR$(IP(0)), 2);
FOR I = 1 TO 3
PRINT "."; MID$(STR$(IP(I)), 2);
NEXT I
PRINT MID$(CI$, SL)
LOOP
DATA 87.70.141.1/22, 36.18.154.103/12, 62.62.197.11/29
DATA 67.137.119.181/4, 161.214.74.21/24, 184.232.176.184/18
REM SOME INVALID INPUTS
DATA 127.0.0.1, 123.45.67.89/0, 98.76.54.32/100, 123.456.789.0/12
DATA</syntaxhighlight>
{{out}}
<pre>Similar to Commodore BASIC entry.</pre>
 
==={{header|uBasic/4tH}}===
<syntaxhighlight lang="uBasic/4tH">If Try (_CanonicalizeCIDR (Dup("36.18.154.103/12"))) Then Print "Illegal IP"
If Try (_CanonicalizeCIDR (Dup("62.62.197.11/29"))) Then Print "Illegal IP"
If Try (_CanonicalizeCIDR (Dup("67.137.119.181/4"))) Then Print "Illegal IP"
If Try (_CanonicalizeCIDR (Dup("161.214.74.0/24"))) Then Print "Illegal IP"
If Try (_CanonicalizeCIDR (Dup("184.232.176.184/18"))) Then Print "Illegal IP"
End
 
_CanonicalizeCIDR ' do the whole shebang
Param (1) ' IP string
Local (3)
 
b@ = FUNC(_GetIP (a@)) ' get IP address
c@ = FUNC(_GetMask(a@)) ' get the mask
d@ = FUNC(_Canonicalize (b@, c@)) ' canonicalize IP address
' now print the report
Print Show(a@); Tab(20); " -> "; FUNC(_IP(d@, 24)); ".";
Print FUNC(_IP(d@, 16)); "."; FUNC(_IP(d@, 8)); "."; AND(d@, 255); "/"; c@
Return
_IP Param (2) : Return (AND(255, SHL(a@, -b@)))
_Canonicalize Param (2) : Return (AND(a@, FUNC(_MakeMask (b@))))
_GetMask Param (1) : Return (Val(Chop(a@, o)))
_MakeMask Param (1) : Return (NOT(SHL(1, 32 - a@) - 1))
 
_GetIP ' get the IP address
Param (1) ' IP string
Local (1) ' IP number
 
o = 0
b@ = SHL(FUNC(_Parse (a@, Ord("."))), 24)
b@ = OR(b@, SHL(FUNC(_Parse (a@, Ord("."))), 16))
b@ = OR(b@, SHL(FUNC(_Parse (a@, Ord("."))), 8))
b@ = OR(b@, FUNC(_Parse (a@, Ord("/"))))
Return (b@)
 
_Parse ' parse a token
Param (2) ' string, delimiter
Local (1) ' token
 
c@ = Dup ("") ' start with an empty token
 
For o = o to Len (a@) - 1 Until Peek (a@, o) = b@
c@ = Join (c@, Char (Peek (a@, o)))
Next
 
o = o + 1
Return (Val(c@))</syntaxhighlight>
{{Out}}
<pre>36.18.154.103/12 -> 36.16.0.0/12
62.62.197.11/29 -> 62.62.197.8/29
67.137.119.181/4 -> 64.0.0.0/4
161.214.74.0/24 -> 161.214.74.0/24
184.232.176.184/18 -> 184.232.128.0/18
 
0 OK, 0:388</pre>
 
=={{header|C}}==
This solution uses only the standard library. On POSIX platforms one can use the functions
Line 448 ⟶ 676:
 
{{out}}
<pre>87.70.141.1/22 -> 87.70.140.0/22
<pre>
87.70.141.1/22 -> 87.70.140.0/22
36.18.154.103/12 -> 36.16.0.0/12
62.62.197.11/29 -> 62.62.197.8/29
67.137.119.181/4 -> 64.0.0.0/4
161.214.74.21/24 -> 161.214.74.0/24
184.232.176.184/18 -> 184.232.128.0/18</pre>
</pre>
=={{header|Commodore BASIC}}==
<syntaxhighlight lang="gwbasic">100 REM THE BINARY OPS ONLY WORK ON SIGNED 16-BIT NUMBERS
110 REM SO WE STORE THE IP ADDRESS AS AN ARRAY OF FOUR OCTETS
120 DIM IP(3)
130 REM READ DEMO DATA
140 READ CI$
150 IF CI$="" THEN END
160 REM FIND /
170 SL=0
180 FOR I=LEN(CI$) TO 1 STEP -1
190 : IF MID$(CI$,I,1)="/" THEN SL=I:I=1
200 NEXT I
210 IF SL=0 THEN PRINT "INVALID CIDR STRING: '"CI$"'":GOTO 140
220 NW=VAL(MID$(CI$,SL+1))
230 IF NW < 1 OR NW > 32 THEN PRINT "INVALID NETWORK WIDTH:"NW:GOTO 140
240 REM PARSE OCTETS INTO IP ARRAY
250 BY=0:N=0
260 FOR I=1 TO SL-1
270 : C$=MID$(CI$,I,1):IF C$<>"." THEN 300
280 : IP(N)=BY:N=N+1:BY=0:IF IP(N-1)<256 THEN 310
290 : PRINT "INVALID OCTET VALUE:"IP(N-1):GOTO 140
300 : C=VAL(C$):IF C OR (C$="0") THEN BY=BY*10+C
310 NEXT I
320 IP(N)=BY:N=N+1:IF IP(N-1)>255 THEN 290
330 REM NUMBER OF COMPLETE OCTETS IN NETWORK PART
340 NB=INT(NW/8)
350 REM NUMBER OF NETWORK BITS IN PARTIAL OCTET
360 XB=NW AND 7
370 REM ZERO OUT HOST BITS IN PARTIAL OCTET
380 IP(NB) = IP(NB) AND (255 - 2^(8-XB) + 1)
390 REM AND SET ANY ALL-HOST OCTETS TO 0
400 IF NB<3 THEN FOR I=NB+1 TO 3:IP(I)=0 :NEXT I
410 REM PRINT OUT THE RESULT
420 PRINT MID$(STR$(IP(0)),2);
430 FOR I=1 TO 3: PRINT "."MID$(STR$(IP( I)),2);:NEXT I
440 PRINT MID$(CI$,SL)
450 REM AND GO BACK FOR NEXT INPUT
460 GOTO 140
500 DATA 87.70.141.1/22, 36.18.154.103/12, 62.62.197.11/29
510 DATA 67.137.119.181/4, 161.214.74.21/24, 184.232.176.184/18
520 REM SOME INVALID INPUTS
530 DATA 127.0.0.1, 123.45.67.89/0, 98.76.54.32/100, 123.456.789.0/12
540 DATA</syntaxhighlight>
 
{{Out}}<pre>READY.
RUN
87.70.140.0/22
36.16.0.0/12
62.62.197.8/29
64.0.0.0/4
161.214.74.0/24
184.232.128.0/18
INVALID CIDR STRING: '127.0.0.1'
INVALID NETWORK WIDTH: 0
INVALID NETWORK WIDTH: 100
INVALID OCTET VALUE: 456
 
READY.</pre>
=={{header|Common Lisp}}==
<syntaxhighlight lang="lisp">(defun ip->bit-vector (ip)
Line 1,929 ⟶ 2,098:
inaddr-str
(str-inaddr-net @1.addr @1.prefix)))</syntaxhighlight>
 
=={{header|uBasic/4tH}}==
<syntaxhighlight lang="uBasic/4tH">If Try (_CanonicalizeCIDR (Dup("36.18.154.103/12"))) Then Print "Illegal IP"
If Try (_CanonicalizeCIDR (Dup("62.62.197.11/29"))) Then Print "Illegal IP"
If Try (_CanonicalizeCIDR (Dup("67.137.119.181/4"))) Then Print "Illegal IP"
If Try (_CanonicalizeCIDR (Dup("161.214.74.0/24"))) Then Print "Illegal IP"
If Try (_CanonicalizeCIDR (Dup("184.232.176.184/18"))) Then Print "Illegal IP"
End
 
_CanonicalizeCIDR ' do the whole shebang
Param (1) ' IP string
Local (3)
 
b@ = FUNC(_GetIP (a@)) ' get IP address
c@ = FUNC(_GetMask(a@)) ' get the mask
d@ = FUNC(_Canonicalize (b@, c@)) ' canonicalize IP address
' now print the report
Print Show(a@); Tab(20); " -> "; FUNC(_IP(d@, 24)); ".";
Print FUNC(_IP(d@, 16)); "."; FUNC(_IP(d@, 8)); "."; AND(d@, 255); "/"; c@
Return
_IP Param (2) : Return (AND(255, SHL(a@, -b@)))
_Canonicalize Param (2) : Return (AND(a@, FUNC(_MakeMask (b@))))
_GetMask Param (1) : Return (Val(Chop(a@, o)))
_MakeMask Param (1) : Return (NOT(SHL(1, 32 - a@) - 1))
 
_GetIP ' get the IP address
Param (1) ' IP string
Local (1) ' IP number
 
o = 0
b@ = SHL(FUNC(_Parse (a@, Ord("."))), 24)
b@ = OR(b@, SHL(FUNC(_Parse (a@, Ord("."))), 16))
b@ = OR(b@, SHL(FUNC(_Parse (a@, Ord("."))), 8))
b@ = OR(b@, FUNC(_Parse (a@, Ord("/"))))
Return (b@)
 
_Parse ' parse a token
Param (2) ' string, delimiter
Local (1) ' token
 
c@ = Dup ("") ' start with an empty token
 
For o = o to Len (a@) - 1 Until Peek (a@, o) = b@
c@ = Join (c@, Char (Peek (a@, o)))
Next
 
o = o + 1
Return (Val(c@))</syntaxhighlight>
{{Out}}
<pre>36.18.154.103/12 -> 36.16.0.0/12
62.62.197.11/29 -> 62.62.197.8/29
67.137.119.181/4 -> 64.0.0.0/4
161.214.74.0/24 -> 161.214.74.0/24
184.232.176.184/18 -> 184.232.128.0/18
 
0 OK, 0:388</pre>
 
=={{header|UNIX Shell}}==
2,123

edits